Repository navigation
Modernize Python repos: pyproject.toml + uv + semantic-release #506
Description
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
reproducibleuv.locklockfile (no more per-environment.txtfiles) pyproject.toml(PEP 621/735) consolidates package metadata and dependency
declarations in one file, eliminatingsetup.py,setup.cfg, andrequirements/*.txtpython-semantic-releaseautomates 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:
edx_lint write_uv_constraints(feat: add write_uv_constraints command to manage uv constraint-dependencies edx-lint#537) — syncs global version
constraints from edx-lint into each repo's[tool.uv].constraint-dependencies
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/*.txtfor dependency management - Uses
setup.pyorsetup.cfgfor package metadata (or apyproject.tomlthat
still usesdynamic = [..., "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)
- Migrate metadata from
setup.cfg/setup.pyinto[project] - Declare
dependenciesas a static list (not dynamic from a requirements file) - Configure
setuptools-scmfor version discovery - Delete
setup.pyandsetup.cfg
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
- Add
[dependency-groups]topyproject.tomlcovering test, quality, doc, ci, and dev - Add
[tool.edx_lint].uv_constraintsfor any repo-specific version overrides,
then runedx_lint write_uv_constraintsto populate[tool.uv].constraint-dependencies - Generate
uv.lockand commit it - Delete the
requirements/directory - Update
tox.inito usetox-uv>=1anduv-venv-lock-runnerwithdependency_groups - Update
Makefiletargets (upgrade,compile-requirements,requirements) - Update CI to install uv via
astral-sh/setup-uv, install deps viauv sync --group ci,
and run tests viauv run tox
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.
- Add
[tool.semantic_release]config topyproject.tomlwith abuild_command
that setsSETUPTOOLS_SCM_PRETEND_VERSIONat build time - Add a
release.ymlworkflow that runs CI then publishes to PyPI via OIDC - Add a
commitlint.ymlworkflow to enforce conventional commits on PRs - Confirm PyPI trusted publisher (OIDC) is configured for the repo
Notes
[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.- 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).
Metadata
Metadata
Assignees
Labels
Type
Projects
- StatusShow more project fields🔖 Ready
Activity
xitij2000 commentedon Apr 27, 2026
@feanil Sorry if this was already discussed and I'm jumping in too late, but I'd like to recommend hatch instead of uv as the build backend. It supports build environments which will allow replacing tox as well. It's a pypa project so it follows PEP standards closely and can still use uv for installing packages.
Sorry if this has already been discussed and eliminated.
feanil commentedon Apr 29, 2026
@xitij2000 My understanding is that the build backend is still setuptools and we're just using uv for dependency management. Hatch seems promising as a setuptools replacement but I haven't evaluated it too deeply yet because I didn't want to add complexity to the switch from setup.py to pyproject.toml by also changing the build backend at the same time. Let me know if I misunderstood something about the ecosystem here.
farhan commentedon Apr 29, 2026
bradenmacdonald commentedon Apr 30, 2026
I just want to point out that
sample-plugin/backendis not using asrc/directory layout, and I would highly recommend that we try to adopt that where feasible, for these reasons and this reason (editable installs of repos likeopaque-keyswill not be usable by important tools like mypy because they're not using asrc/directory, but repos likeopenedx-corethat do use a src directory work fine).feanil commentedon Apr 30, 2026
@bradenmacdonald thanks, that seems like another general improvement we should make across all of our libraries as we modernize.
feanil commentedon May 1, 2026
PR for that refactor in the sample-plugin repo: openedx/sample-plugin#32 if anyone has a sec to review.
salman2013 commentedon May 6, 2026
Uses setup.py/setup.cfg — pip-compile / requirements/*.txt — PUBLISHED on PyPI
Uses setup.py/setup.cfg + requirements/*.txt — NOT on PyPI
Uses setup.py/setup.cfg — NO requirements/*.txt — NOT on PyPI
136 remaining items
feat: consolidate package metadata into pyproject.toml
feat: switch dependency management from pip-compile to uv
feat: add semantic-release and commitlint workflows
feat: modernize Python tooling (pyproject.toml + uv + semantic-releas…
feat: modernize to uv + pyproject.toml + python-semantic-release
refactor: move package to src/ layout
feat: modernize to uv + pyproject.toml + python-semantic-release
feat: modernize to uv + pyproject.toml + semantic-release (#381)
feat: modernize to uv + pyproject.toml + semantic-release (#190)
build: modernize edx-submissions repo to uv + pyproject.toml
build: modernize edx-submissions repo to uv + pyproject.toml
build: modernize edx-submissions repo to uv + pyproject.toml
feat: modernize Python tooling (pyproject.toml + uv + semantic-releas…
fix: address review-modernize-python-tooling findings
build: modernize edx-submissions repo to uv + pyproject.toml