Packaging pdm-datareader
This project uses Poetry with the poetry-core build backend (see
pyproject.toml), not setuptools/hatchling/uv. Commands below assume Poetry is
installed and you are at the repo root.
pyproject.toml Essentials
Metadata lives under [tool.poetry]:
[tool.poetry]
name = "pdm-datareader"
version = "2.5.5"
description = "A small python package to execute queries to PDM ..."
authors = ["PDM TEAM <AWL@equinor.com>"]
license = "MIT"
readme = "README.md"
packages = [{ include = "pdm_datareader" }]
repository = "https://github.com/equinor/pdm-datareader"
[tool.poetry.dependencies]
python = "^3.11"
msal-bearer = ">=1.3.0,<2.0.0"
pyodbc = "^5.1.0"
pandas = ">=2.2.2,<4.0.0"
sqlalchemy = "^2.0.36"
urllib3 = "^2.3.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
packages = [{ include = "pdm_datareader" }]tells poetry-core which package directory to ship — keep it in sync with the actual package folder.- Runtime deps go under
[tool.poetry.dependencies]; dev-only tools (pytest,black) go under[tool.poetry.group.dev.dependencies]and are not shipped to users.
Version Bump (do this every release)
Bump version under [tool.poetry] following SemVer
(MAJOR.MINOR.MICRO — see the versioning section in
.github/copilot-instructions.md). Either edit the field directly or use:
poetry version patch # bug fix: 2.5.5 -> 2.5.6
poetry version minor # new feature: 2.5.5 -> 2.6.0
poetry version major # breaking: 2.5.5 -> 3.0.0
Building
poetry build # creates sdist + wheel in dist/
Validate Metadata
poetry run pip install --quiet twine # if twine not already available
poetry run twine check dist/* # validate long_description/metadata
Verify the Built Artifact (a green build is not a correct wheel)
poetry build succeeding only means the backend ran — not that the wheel
contains your code. Always inspect wheel contents before publishing:
python -m zipfile -l dist/*.whl
Confirm the whole package ships — pdm_datareader/__init__.py and
pdm_datareader/tools.py — not just a top-level file. twine check validates
metadata, not contents, so it won't catch a missing module.
Then prove it from a clean install, outside the repo root (so import doesn't
pick up the source tree):
python -m venv /tmp/verify
/tmp/verify/bin/python -m pip install dist/*.whl
cd /tmp && /tmp/verify/bin/python -c "from pdm_datareader import tools; tools.query"
On Windows PowerShell:
python -m venv $env:TEMP\verify
& "$env:TEMP\verify\Scripts\python.exe" -m pip install (Get-ChildItem dist\*.whl)
Push-Location $env:TEMP
& "$env:TEMP\verify\Scripts\python.exe" -c "from pdm_datareader import tools; tools.query"
Pop-Location
Assert on a real symbol (tools.query), never just that the top-level name
imports — a shadowing empty package can make a bare import succeed and prove
nothing.
Publishing to PyPI
Test on TestPyPI first, then publish to production:
# TestPyPI (one-time config)
poetry config repositories.testpypi https://test.pypi.org/legacy/
poetry publish -r testpypi --build
# Production PyPI (uses a configured token)
poetry publish --build
Configure the token once with:
poetry config pypi-token.pypi <your-token>
Never hardcode or commit tokens. Prefer trusted publishing from CI over a locally stored token where available.
Dependency Best Practices
# DO: caret / bounded ranges (poetry style)
msal-bearer = ">=1.3.0,<2.0.0"
pyodbc = "^5.1.0"
# DON'T: exact pins that lock users to one release
pyodbc = "5.1.0"
Keep python = "^3.11" aligned with the supported versions in the project docs
(3.11–3.13).
Checklist
Before Release:
- [ ] Version bumped under [tool.poetry] (SemVer)
- [ ] README.md updated for any new feature
- [ ] pytest passes and black formatting applied
- [ ] poetry build succeeds
- [ ] poetry run twine check dist/* passes
- [ ] python -m zipfile -l dist/*.whl shows pdm_datareader/__init__.py + tools.py
- [ ] Installed the wheel into a clean venv and imported tools.query from
a directory outside the repo
- [ ] Tested on TestPyPI first
After Release:
- [ ] pip install pdm-datareader works
- [ ] from pdm_datareader import query works
- [ ] GitHub release / tag created