Skip to content

build: migrate to uv + pyproject.toml (PEP 621/735) + python-semantic-release - #253

Open
farhan wants to merge 6 commits into
openedx:mainfrom
farhan:farhan/modernize-python-repo-2
Open

farhan wants to merge 6 commits into
openedx:mainfrom
farhan:farhan/modernize-python-repo-2

Conversation

@farhan

@farhan farhan commented Sep 21, 2026 •

Copy link
Copy Markdown

Important

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

Modernize platform-plugin-aspects
Part of openedx/public-engineering#506

Summary

  • Published to PyPI: https://pypi.org/project/platform-plugin-aspects/
  • 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/black as on master.
  • Coverage config moved into pyproject.toml
  • Update CI to use astral-sh/setup-uv; SHA-pin all actions
  • Add python-semantic-release + release.yml (OIDC trusted publishing)
  • Add commitlint.yml to enforce conventional commit format on all future PRs to this repo (already existed on master — kept as-is)
  • Drop Python < 3.12 support was already done on master; requires-python = ">=3.12" set

Removed/Updated

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

Removed Makefile targets:

Target Reason
upgrade Replaced by uv run --with edx-lint edx_lint write_uv_constraints pyproject.toml && uv lock --upgrade
piptools pip-compile era bootstrap target; uv replaces pip-tools entirely

Updated Makefile targets:

Target Change
requirements Was pip-sync -q requirements/dev.txt; now uv sync --group dev
docs Was tox -e docs; now tox -e docs (bare tox — venv activated by caller)
quality Was tox -e quality; now tox -e quality (bare tox — venv activated by caller)
pii_check Was tox -e pii_check; now tox -e pii_check (bare tox — venv activated by caller)
test Was pytest; now pytest (unchanged)
test-all Was tox && tox -e docs; now tox && tox -e docs (bare tox — venv activated by caller)
extract_translations Updated paths from platform_plugin_aspects/ to src/platform_plugin_aspects/
compile_translations Updated paths from platform_plugin_aspects/ to src/platform_plugin_aspects/
format Updated paths from platform_plugin_aspects to src/platform_plugin_aspects
Translation targets Updated directory paths to src/platform_plugin_aspects/ after src/ layout move

Versioning

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

Important Notes

  • The pypi-publish.yml workflow was deleted because it used token-based authentication (PYPI_UPLOAD_TOKEN) and python setup.py sdist bdist_wheel, both of which are obsolete. It is replaced by release.yml which uses OIDC trusted publishing.
  • The CI toxenv matrix now uses py (instead of django52) since only one Django version is tested and it is declared as a runtime dependency in [project].dependencies. The old django52 tox env resolved Django via requirements/test.txt; the new py env installs Django through the test dependency group and uv.lock.
  • commitlint.yml already existed on master and was kept unchanged. Conventional commit format was already enforced on this repo.
  • pip and wheel from pip.in are not declared as explicit dependencies — they are build bootstrap tools that uv replaces entirely. The pip<26.2 constraint is retained in [tool.uv].constraint-dependencies.
  • Baseline tag v2.0.0 has been pushed so python-semantic-release can correctly identify the latest release.

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, pytest, python -m build). Repo-owner is encouraged to run the repo's feature tests before merging.


🤖 Generated with Claude Code

…ic-release

Replaces setup.py/setup.cfg and pip-compile with a PEP 621 pyproject.toml,
PEP 735 dependency groups, uv/uv.lock, src/ layout, and python-semantic-release
with OIDC-based PyPI publishing. Part of openedx/public-engineering#506.

PSR is configured to use conventional commits for version bumping and
changelog generation, with tag_format "v{version}" matching existing release
tags. Releases publish to PyPI via OIDC trusted publishing (no stored secrets),
using a two-step pattern — PSR tags and builds, then gh release create attaches
dists — to satisfy the openedx org's immutable-releases constraint.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@farhan
farhan force-pushed the farhan/modernize-python-repo-2 branch from a22bce9 to c4c4cbd Compare September 22, 2026 15:04
farhan and others added 2 commits September 25, 2026 18:01
Old setup.py used find_packages(exclude=["*tests"]) but nested test
subdirectories (sinks/tests/, extensions/tests/, etc.) slipped through
as package data under include-package-data=true. Add exclude-package-data
to drop all tests/* paths from the built wheel.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Per Feanil's guidance, Makefiles should not force/assume the uv
environment. Developers activate the venv themselves; CI uses
`uv run tox` in the workflow step. Strip `uv run` from all
Makefile targets except `upgrade`.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@farhan
farhan marked this pull request as ready for review September 28, 2026 08:07
Comment thread .readthedocs.yaml
@@ -18,10 +18,7 @@ build:

python:
install:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
install:
# `uv sync` against the committed uv.lock, so the docs build against the
# same pinned versions as CI -- and inherits the minimum release age
# recorded in the lock. This used to be `requirements: requirements/doc.txt`,
# which stopped existing when the repo moved to uv.lock.
- method: uv
command: sync
groups:
- doc

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

good catch, fixed

Comment thread tox.ini
@@ -1,5 +1,6 @@
[tox]
envlist = py312-django{52}
envlist = quality, docs, pii_check, py

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Could you share a reason for removing python and django version. py312-django{52}and use py

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

as only one Django version and one python version is tested, django is already declared as a dependency in the test group in pyproject.toml and pinned via uv.lock.

Comment thread pyproject.toml Outdated
branch = true
relative_files = true
data_file = ".coverage"
source = ["platform_plugin_aspects"]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggested change
source = ["platform_plugin_aspects"]
source_pkgs = ["platform_plugin_aspects"]

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

fixed

farhan and others added 3 commits September 28, 2026 16:50
source = [...] resolves by path, which breaks with a src/ layout since
the package directory doesn't exist at the repo root. source_pkgs
resolves by import name regardless of where the package lives on disk.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The pip method with extra_requirements won't find anything to install
since dependencies moved from pip extras to PEP 735 dependency groups.
uv sync --group doc installs from the committed uv.lock correctly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
source_pkgs resolves by import name and silently drops packages
that pytest never imports. source = ["src"] tracks every .py file
under src/ by path regardless of imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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