Context
The openedx org is standardizing on modern Python tooling across all maintained Python
packages. This issue tracks the work of applying that standard to repos that still use
legacy tooling.
Why:
- pip-tools is being retired in favour of
uv, which is faster and produces a single
reproducible uv.lock lockfile (no more per-environment .txt files)
pyproject.toml (PEP 621/735) consolidates package metadata and dependency
declarations in one file, eliminating setup.py, setup.cfg, and requirements/*.txt
python-semantic-release automates version bumps and PyPI publishing from conventional
commit messages, removing manual release steps
Reference implementation: openedx/sample-plugin- The files to
model after are backend/pyproject.toml, backend/tox.ini, backend/Makefile, and
.github/workflows/backend-ci.yml.
Supporting infrastructure:
Which repos qualify?
A repo should be modernized if it meets all of the following:
- Is a Python package published (or intended to be published) to PyPI
- Uses
pip-compile / requirements/*.txt for dependency management
- Uses
setup.py or setup.cfg for package metadata (or a pyproject.toml that
still uses dynamic = [..., "dependencies"] pointing to a requirements file)
Work per repo
1. Consolidate package metadata into pyproject.toml
Move all package metadata into a single pyproject.toml using PEP 621. This means
replacing setup.py/setup.cfg, declaring a static dependencies list under
[project], and using setuptools-scm for version management from git tags.
Reference: backend/pyproject.toml ([project], [build-system], and [tool.setuptools_scm] sections)
Note: The sample-plugin houses the python library in a subdirectory and so has
to set the root setting in tool.setuptools_scm to ... This should not be
necessary for any other repo and should be omitted.
2. Switch dependency management from pip-compile to uv
Replace all requirements/*.in + requirements/*.txt files with PEP 735
[dependency-groups] in pyproject.toml and a single uv.lock lockfile. The
standard groups are test-base, test, quality, doc, ci, and dev — with
additional version-matrix groups as needed. Update tox.ini to use tox-uv's
uv-venv-lock-runner, update the Makefile to use uv lock/uv sync, and update
CI to install uv and run uv run tox.
Reference: backend/pyproject.toml ([dependency-groups] and [tool.uv] sections), backend/tox.ini, backend/Makefile, .github/workflows/backend-ci.yml
3. Add semantic-release
Configure python-semantic-release so that pushing a conventional commit to main
automatically cuts a version, tags it, and publishes to PyPI. Add commitlint to enforce
conventional commit format on PRs.
Reference: backend/pyproject.toml ([tool.semantic_release] section), .github/workflows/release.yml
Note: The sample plugin overrides minor_tags because it wants to publish new
minor versions on docs changes. That is not needed in our other libraries. They
should use the default value unless you know for sure you need to use something
different.
Notes
[tool.uv].constraint-dependencies is machine-managed. Never edit it directly.
Repo-specific version overrides belong in [tool.edx_lint].uv_constraints.
uv sync does not put tools on PATH. Use uv run tox in CI, not bare tox.
- A new framework version may require bumping
requires-python. If the new version
drops an older Python, bump accordingly and remove that Python from the tox envlist.
- OEP-67 ADR documenting this migration is in progress (link TBD once merged).
Context
The openedx org is standardizing on modern Python tooling across all maintained Python
packages. This issue tracks the work of applying that standard to repos that still use
legacy tooling.
Why:
uv, which is faster and produces a singlereproducible
uv.locklockfile (no more per-environment.txtfiles)pyproject.toml(PEP 621/735) consolidates package metadata and dependencydeclarations in one file, eliminating
setup.py,setup.cfg, andrequirements/*.txtpython-semantic-releaseautomates version bumps and PyPI publishing from conventionalcommit messages, removing manual release steps
Reference implementation: openedx/sample-plugin- The files to
model after are
backend/pyproject.toml,backend/tox.ini,backend/Makefile, and.github/workflows/backend-ci.yml.Supporting infrastructure:
edx_lint write_uv_constraints(feat: add write_uv_constraints command to manage uv constraint-dependencies edx-lint#537) — syncs global versionconstraints from edx-lint into each repo's
[tool.uv].constraint-dependenciesWhich repos qualify?
A repo should be modernized if it meets all of the following:
pip-compile/requirements/*.txtfor dependency managementsetup.pyorsetup.cfgfor package metadata (or apyproject.tomlthatstill uses
dynamic = [..., "dependencies"]pointing to a requirements file)Work per repo
1. Consolidate package metadata into
pyproject.tomlMove all package metadata into a single
pyproject.tomlusing PEP 621. This meansreplacing
setup.py/setup.cfg, declaring a staticdependencieslist under[project], and usingsetuptools-scmfor version management from git tags.Reference: backend/pyproject.toml (
[project],[build-system], and[tool.setuptools_scm]sections)setup.cfg/setup.pyinto[project]dependenciesas a static list (not dynamic from a requirements file)setuptools-scmfor version discoverysetup.pyandsetup.cfgNote: The sample-plugin houses the python library in a subdirectory and so has
to set the
rootsetting intool.setuptools_scmto... This should not benecessary for any other repo and should be omitted.
2. Switch dependency management from pip-compile to uv
Replace all
requirements/*.in+requirements/*.txtfiles with PEP 735[dependency-groups]inpyproject.tomland a singleuv.locklockfile. Thestandard groups are
test-base,test,quality,doc,ci, anddev— withadditional version-matrix groups as needed. Update
tox.inito usetox-uv'suv-venv-lock-runner, update theMakefileto useuv lock/uv sync, and updateCI to install uv and run
uv run tox.Reference: backend/pyproject.toml (
[dependency-groups]and[tool.uv]sections), backend/tox.ini, backend/Makefile, .github/workflows/backend-ci.yml[dependency-groups]topyproject.tomlcovering test, quality, doc, ci, and dev[tool.edx_lint].uv_constraintsfor any repo-specific version overrides,then run
edx_lint write_uv_constraintsto populate[tool.uv].constraint-dependenciesuv.lockand commit itrequirements/directorytox.inito usetox-uv>=1anduv-venv-lock-runnerwithdependency_groupsMakefiletargets (upgrade,compile-requirements,requirements)astral-sh/setup-uv, install deps viauv sync --group ci,and run tests via
uv run tox3. Add semantic-release
Configure
python-semantic-releaseso that pushing a conventional commit tomainautomatically cuts a version, tags it, and publishes to PyPI. Add commitlint to enforce
conventional commit format on PRs.
Reference: backend/pyproject.toml (
[tool.semantic_release]section), .github/workflows/release.ymlNote: The sample plugin overrides
minor_tagsbecause it wants to publish newminor versions on docs changes. That is not needed in our other libraries. They
should use the default value unless you know for sure you need to use something
different.
[tool.semantic_release]config topyproject.tomlwith abuild_commandthat sets
SETUPTOOLS_SCM_PRETEND_VERSIONat build timerelease.ymlworkflow that runs CI then publishes to PyPI via OIDCcommitlint.ymlworkflow to enforce conventional commits on PRsNotes
[tool.uv].constraint-dependenciesis machine-managed. Never edit it directly.Repo-specific version overrides belong in
[tool.edx_lint].uv_constraints.uv syncdoes not put tools on PATH. Useuv run toxin CI, not baretox.requires-python. If the new versiondrops an older Python, bump accordingly and remove that Python from the tox envlist.