Skip to content

feat: modernize repo to use uv, pyproject.toml, and semantic-release#281

Open
farhan wants to merge 8 commits into
openedx:masterfrom
farhan:farhan/modernize-python-repo
Open

feat: modernize repo to use uv, pyproject.toml, and semantic-release#281
farhan wants to merge 8 commits into
openedx:masterfrom
farhan:farhan/modernize-python-repo

Conversation

@farhan

@farhan farhan commented Jul 16, 2026

Copy link
Copy Markdown

Important

PR implemented with the assistance of Claude Code, human-reviewed and improved before pushing to code review.

Split out of #280; ruff retained there for adoption in a future epic (per public-engineering#506).

Summary

Modernize forum to uv + pyproject.toml (PEP 621/735) + src/ layout + python-semantic-release.

Part of openedx/public-engineering#506.

  • 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
  • Move the package into a src/ layout
  • Retain pylint/isort/pycodestyle/pydocstyle as on master (ruff deferred to its own epic per #506); coverage config and mypy config moved into pyproject.toml
  • Update tox.ini to use tox-uv with uv-venv-lock-runner
  • Update CI to use astral-sh/setup-uv; SHA-pin all actions; add workflow_call trigger
  • Add python-semantic-release + release.yml (OIDC trusted publishing)

Removed

Deleted files: setup.py, setup.cfg, requirements/, .coveragerc, mypy.ini, CHANGELOG.rst

Removed Makefile targets:

Target Reason
clean_tox Tox environments managed by tox-uv; manual tox cache cleaning no longer needed
compile-requirements pip-compile workflow replaced by uv + uv.lock
piptools pip-tools no longer used
test-all Superseded by tox / CI matrix
test-quality Replaced by lint target (uv run tox -e quality)
test-lint Consolidated into lint target (uv run tox -e quality)
test-codestyle Consolidated into lint target (uv run tox -e quality)
test-isort Consolidated into lint target (uv run tox -e quality)
test-mypy Replaced by mypy target (uv run tox -e mypy)
test-format Ran black --check; format checking is no longer a separate CI quality gate; the format target now auto-fixes

Versioning

[Dynamic] setuptools-scm with dynamic = ["version"] — master had a PyPI publish workflow (pypi-publish.yml); python-semantic-release controls the version string at release time via git tags. Repo is on 0.x, so allow_zero_version = true and major_on_zero = false are set to prevent a feat: commit from bumping 0.x.y → 1.0.0.

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

Code reviewer notes:

  • Pylint/isort/pycodestyle/pydocstyle are retained exactly as on master — ruff is out of scope this cycle and lives in the companion PR feat: modernize repo to use uv, pyproject.toml, and semantic-release #280 for a future epic.
  • OIDC trusted publisher must be configured on PyPI before merging — first publish fails silently otherwise. This is an out-of-band prerequisite handled by the Axim team (Feanil): PyPI project → PublishingAdd a new publisher, pointing at openedx/forum, workflow release.yml, no environment.
  • commitlint.yml was already present on master; this PR does not change it.
  • Pay close attention to the pyproject.toml dependency groups — verify that all runtime and optional dependencies from the old requirements/*.in files are faithfully carried over, and that no transitive constraint from requirements/constraints.txt was silently dropped.
  • test-format (black --check) was removed as a quality gate; formatting is now only enforced via make format (auto-fix) rather than CI check — reviewers should verify this is acceptable for this repo.

🤖 Generated with Claude Code

Split out of farhan/modernize-repo; ruff retained there for adoption in a
future epic (per public-engineering#506).

- 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 (ruff deferred)
- Update tox.ini to use tox-uv with uv-venv-lock-runner
- Update CI to use astral-sh/setup-uv; SHA-pin all actions; add workflow_call trigger
- Add python-semantic-release + release.yml (OIDC trusted publishing)
- Add commitlint.yml to enforce conventional commit format on all future PRs

Part of openedx/public-engineering#506
farhan and others added 4 commits July 16, 2026 13:38
…warning

- Run isort on all source files to fix import ordering (isort v8 is
  stricter than the pre-migration version; files not yet sorted)
- Remove black --check from tox quality env (black was not in
  requirements/quality.in on master so was never reliably enforced)
- Remove black from quality dependency group accordingly
- Add ref.python to suppress_warnings in docs/conf.py to silence the
  ambiguous cross-reference warning for the `type` attribute (present
  in both Content and ContentSerializer); Sphinx 9.x treats this as
  an error with -W

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace PYPI_UPLOAD_TOKEN with id-token: write + pypa/gh-action-pypi-publish
(no password input). OIDC is the org-wide standard per public-engineering#506,
unconditionally applied regardless of what master used.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Repo is on 0.4.3 (0.x). Without allow_zero_version=true and
major_on_zero=false, the first feat: commit after merge would bump
0.x.y → 1.0.0 unexpectedly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Moves the importable package from forum/ to src/forum/ per the
modernization standard (public-engineering#520). Updates all
tooling references: setuptools find, coverage source_pkgs, tox
quality/mypy envs, Makefile targets, and docs/conf.py apidoc paths.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
black was in master's ci.in but was not carried over to any
dependency group in pyproject.toml, leaving the `format` target
broken (uv run black fails with no such file or directory).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@farhan
farhan marked this pull request as draft July 16, 2026 13:17
@farhan
farhan marked this pull request as ready for review July 16, 2026 16:27
irfanuddinahmad pushed a commit to openedx/enterprise-integrated-channels that referenced this pull request Jul 17, 2026
Moves channel_integrations/ to src/channel_integrations/, in line with
the reference implementation for this modernization effort
(openedx/sample-plugin) and openedx/forum#281.

- pyproject.toml: add where = ["src"] to packages.find
- tox.ini: prefix src/ onto pylint/pycodestyle targets in the quality env
- Makefile: prefix src/ onto all 5 localization targets (extract,
  compile, detect_changed, pull, dummy); atlas pull's local destination
  path updated, remote Transifex identifier left unchanged
- test_settings.py: LOCALE_PATHS root() call updated
- docs/conf.py: sphinx-apidoc call updated to point at src/channel_integrations
- MANIFEST.in: recursive-include path updated

Verified: uv sync (no lock drift), full django42 test run (893 passed),
quality and pii_check envs pass, uv build --wheel + twine check pass.

The docs tox env fails both before and after this change (a pre-existing
sphinx/autodoc ValueError in object_description, unrelated to src-layout
and unrelated to this repo's file layout) -- confirmed by reproducing the
identical failure on the pre-migration commit via git stash.
irfanuddinahmad pushed a commit to openedx/taxonomy-connector that referenced this pull request Jul 17, 2026
Moves taxonomy/ to src/taxonomy/, in line with the reference
implementation for this modernization effort (openedx/sample-plugin)
and openedx/forum#281.

- pyproject.toml: add where = ["src"] to packages.find
- tox.ini: prefix src/ onto pylint/pycodestyle/pydocstyle/isort targets
  in the quality env
- Makefile: prefix src/taxonomy onto the 3 localization targets that
  cd into the package (compile_translations, detect_changed_source_translations,
  dummy_translations); compile_translations' relative ../manage.py climb
  updated to ../../manage.py to account for the extra nesting level
- test_settings.py: LOCALE_PATHS root() call updated
- docs/conf.py: sphinx-apidoc call updated to point at src/taxonomy
- MANIFEST.in: recursive-include path updated

Verified: uv sync (no lock drift), full django42 test run (315 passed),
quality (pylint/pycodestyle/pydocstyle/isort) and pii-annotations envs
pass, docs env passes end to end -- sphinx-apidoc generates real API
docs from the new path, uv build --wheel + twine check pass.
irfanuddinahmad pushed a commit to openedx/openedx-ledger that referenced this pull request Jul 17, 2026
Moves openedx_ledger/ to src/openedx_ledger/, in line with the reference
implementation for this modernization effort (openedx/sample-plugin)
and openedx/forum#281.

- pyproject.toml: add where = ["src"] to packages.find
- tox.ini: prefix src/ onto the quality env's pylint/pycodestyle/isort
  targets
- Makefile: prefix src/openedx_ledger onto the standalone isort/style/lint
  targets and the 5 localization targets that cd into the package;
  extract_translations/compile_translations' relative ../manage.py climbs
  updated to ../../manage.py to account for the extra nesting level
- test_settings.py: LOCALE_PATHS root() call updated
- docs/conf.py: sphinx-apidoc call updated to point at src/openedx_ledger
- MANIFEST.in: recursive-include path updated
- Dockerfile needs no change: it COPYs the whole repo rather than naming
  the package directory directly

Verified: uv build --wheel + twine check pass (direct proof the
where=["src"] packaging change works). Could not run the full
pytest/quality/docs tox matrix locally -- this machine has no
libmysqlclient/pkg-config to build the mysqlclient C extension (a
[project.dependencies] entry, so it's required for every uv sync
regardless of group), same environment limitation hit previously on
enterprise-access. Relying on CI for full-matrix confirmation.
irfanuddinahmad pushed a commit to openedx/edx-enterprise-data that referenced this pull request Jul 17, 2026
Moves all three top-level packages (enterprise_data, enterprise_data_roles,
enterprise_reporting) to src/, in line with the reference implementation
for this modernization effort (openedx/sample-plugin) and openedx/forum#281.

- pyproject.toml: add where = ["src"] to packages.find
- tox.ini: prefix src/ onto the quality env's isort/pylint/pycodestyle/
  pydocstyle targets, and onto the data env's pytest --ignore path and
  the reporting env's test-collection path (--cov's own module-name arg
  is left alone -- it resolves via the installed module, not a filesystem
  path). DJANGO_SETTINGS_MODULE=enterprise_data.settings.test is an
  import path, unaffected by the physical move.
- Makefile: prefix src/ onto the isort target's package names
- MANIFEST.in: all three recursive-include paths updated
- enterprise_data/settings/test.py: this repo's in-package here()/root()
  path helper climbs from src/enterprise_data/settings/ back to the repo
  root -- fixed the climb from '../..' (2 levels, correct pre-move) to
  '../../..' (3 levels, correct post-move) so root() still means what its
  docstring says. root() has no current call sites (dead code), but fixed
  the definition itself for correctness -- verified by direct invocation
  that it now resolves to the true repo root.

Verified: uv sync (no lock drift), uv build --wheel + twine check pass
(direct proof the where=["src"] packaging change works across all three
packages). Could not run the full tox matrix locally -- this machine's
clang/zlib toolchain can't build pyminizip (a native extension in the
"reporting" extra that both the "test" and "quality" dependency groups
pull in), unrelated to src-layout. Relying on CI for full-matrix
confirmation.
irfanuddinahmad pushed a commit to openedx/edx-enterprise that referenced this pull request Jul 17, 2026
Moves all four top-level packages (enterprise, consent, integrated_channels,
enterprise_learner_portal) to src/, in line with the reference implementation
for this modernization effort (openedx/sample-plugin) and openedx/forum#281.
Most complex repo in this batch: 4 packages, an in-package path helper with
real call sites, and JS tooling (webpack, jasmine) alongside the Python side.

- pyproject.toml: add where = ["src"] to packages.find
- tox.ini: prefix src/ onto the pycodestyle exclude list and onto every
  package name in the isort/isort-check/quality env commands
- Makefile: prefix src/ onto clean.static, dummy_translations,
  pull_translations (local destination paths only -- the Transifex/Atlas
  remote path identifiers are left unchanged), jshint, pylint, pycodestyle,
  isort, and isort-check targets
- docs/conf.py: sphinx-apidoc call updated to point at src/enterprise
- webpack.config.js: build context path updated to src/enterprise/static/enterprise
- spec/javascripts/support/jasmine.yml: src_files glob updated to
  src/enterprise/static/enterprise/js/*.js
- MANIFEST.in: all four recursive-include paths and the enterprise/locale
  symlink exclusion updated
- enterprise/settings/test.py: this repo's in-package here()/root() path
  helper climbs from src/enterprise/settings/ back to the repo root --
  fixed the climb from '../..' (2 levels) to '../../..' (3 levels), and
  updated its 3 real call sites (LOCALE_PATHS, REPO_ROOT, STATIC_ROOT) to
  prepend 'src' so they still resolve inside the package. The symlink
  enterprise/locale -> conf/locale is relative and moved as a unit with
  git mv, so it still resolves correctly post-move -- verified.

Verified: uv sync (no lock drift), full py312-django52 test run (2849
passed), quality (pylint/pycodestyle/isort), isort-check, and pii_check
envs pass, docs env passes end to end -- sphinx-apidoc generates real API
docs from the new path, uv build --wheel + twine check pass. A pylint
useless-suppression info note in integrated_channels/cornerstone/models.py
is pre-existing (confirmed identical on the pre-migration commit via git
stash), unrelated to this change.
Comment thread pyproject.toml Outdated
Comment thread tox.ini Outdated
CI pins the interpreter via setup-uv's python-version; the explicit
basepython = python3.12 is unnecessary.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

@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.

Reviewed the modernization changes (uv/pyproject.toml + src-layout + semantic-release migration). OIDC publishing and action pinning look correct; no issues found.

Per review feedback, remove the >=61.0 minimum to stay consistent
with how other modernized openedx repos declare their build-system.

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.

3 participants