Skip to content

build: modernize edx-django-utils repo to uv + pyproject.toml - #557

Open
farhan wants to merge 1 commit into
openedx:masterfrom
farhan:farhan/modernize-python-repo
Open

farhan wants to merge 1 commit into
openedx:masterfrom
farhan:farhan/modernize-python-repo

Conversation

@farhan

@farhan farhan commented Oct 28, 2026 •

Copy link
Copy Markdown

Important

PR implemented with the assistance of Claude Code. Refined and validated before being submitted for code review.

Modernize edx-django-utils
Part of openedx/public-engineering#506

Summary

  • Publishes to PyPI as edx-django-utils.
  • Move the package into a src/ layout.
  • Replace setup.py/setup.cfg with pyproject.toml (PEP 621 static metadata).
  • Switch from pip-compile to uv with PEP 735 dependency groups; commit uv.lock.
  • Retain pylint/isort/pycodestyle/pydocstyle as on master.
  • Coverage config moved from .coveragerc into pyproject.toml.
  • Update CI to use astral-sh/setup-uv; SHA-pin all actions; set ci.yml token to permissions: contents: read.
  • Add python-semantic-release + release.yml (OIDC trusted publishing), replacing the tag-triggered pypi-publish.yml.

Removed/Updated

Deleted files: setup.py, setup.cfg, requirements/, .coveragerc, .github/workflows/pypi-publish.yml

Updated Makefile targets:

Target Change
requirements uv sync --locked --group dev instead of pip-sync
upgrade edx_lint write_uv_constraints + uv lock --upgrade instead of pip-compile
quality Runs pylint/pycodestyle/pydocstyle/isort directly with DJANGO_SETTINGS_MODULE=test_settings exported (tox now calls make quality); setup.py dropped from the file lists
isort Runs isort directly (tox now calls make isort)
docs Runs doc8/Sphinx/build/twine directly (tox now calls make docs); python setup.py bdist_wheel → python -m build --wheel; the dev group now includes doc so this works from make requirements
test python -Wd -m pytest $(PYTEST_ARGS) so tox keeps master's -Wd and {posargs} behavior

Versioning

setuptools-scm with dynamic = ["version"] — master had a PyPI publish workflow; python-semantic-release controls the version string at release time via git tags.

[tool.semantic_release] sets tag_format = "v{version}" (matching the existing v8.1.0-style tags), major_on_zero = false and allow_zero_version = true explicitly, so releases don't depend on PSR defaults.

Important Notes

  • [tool.edx_lint].uv_constraints adds setuptools<82: the existing doc8<1.0.0 pin imports pkg_resources, which setuptools 82 removed.
  • uv.lock is seeded from master's requirements/*.txt pins, so dependency versions match master; upgrades are left to the first make upgrade. The django42 group is at master's Django 4.2.25; the test group (and quality/doc, which include it) uses Django 5.2, which master never pinned.
  • The README CI badge now tracks release.yml, since ci.yml no longer runs on pushes to master.
  • ci.yml no longer has a push: trigger; release.yml calls it via workflow_call on pushes to master. The tests job name and matrix are unchanged.
  • tox and the Makefile now run the other way round: tox envs call Makefile targets (make test, make quality, make docs, make isort), whereas on master tox ran the commands itself. This goes beyond the migration and is intentional. Running make docs locally now also builds the dist and runs twine check, which master only did inside tox -e docs.

Testing Notes

This PR has not been manually tested against the repo's own features. Testing relied on CI checks and local agent tooling (make requirements, make quality, make test, make docs, python -m build). Repo-owner is encouraged to run the repo's feature tests before merging.


🤖 Generated with Claude Code

@farhan
farhan marked this pull request as ready for review October 30, 2026 06:26
@irfanuddinahmad

Copy link
Copy Markdown
Contributor

uv.lock was resolved fresh, so this upgrades most of master's pins (Django 4.2.25→5.2.18 in base/quality, newrelic 11→14, pylint 3→4). Per feanil on enterprise-access#1015, please seed the lock from master's requirements/*.txt and leave upgrades to the first make upgrade. docs/getting_started.rst and docs/testing.rst still describe a virtualenv setup.

Since ci.yml no longer runs on pushes to master (CI now runs inside release.yml), the README "Python CI" badge will stay stuck on its last pre-migration result; XBlock's still shows June's. Pointing it at actions/workflows/release.yml/badge.svg?branch=master, or dropping it, fixes that.

@farhan

farhan commented Nov 2, 2026 •

Copy link
Copy Markdown
Author

Fixed in 0f65291. Django stays on 5.2 in quality/runtime-only: quality includes test (5.2), and nothing pins runtime Django, so uv picks the latest.

@irfanuddinahmad irfanuddinahmad left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add tag_format = "v{version}", major_on_zero = false and allow_zero_version = true to [tool.semantic_release], use fallback_version = "0.0.0", and add a top-level permissions: contents: read to ci.yml, since run_ci now calls it from release.yml.

This flips the Makefile/tox direction (tox now calls make). Fine by me since it's the direction feanil prefers, but it's beyond the migration itself, so flag it in the description.

Move to the org-standard packaging and release tooling (public-engineering#506):
static PEP 621 metadata, a locked uv environment seeded from master's pins,
PEP 735 dependency groups, a src/ layout, and python-semantic-release with
OIDC publishing so releases are driven by conventional commits instead of
manual tags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@farhan
farhan force-pushed the farhan/modernize-python-repo branch from d71edd6 to 9333632 Compare November 3, 2026 06:19
@farhan
farhan requested a review from feanil November 3, 2026 15:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants