chore: modernize Python tooling (uv, PEP 621, semantic-release, src layout) - #265
chore: modernize Python tooling (uv, PEP 621, semantic-release, src layout)#265salman2013 wants to merge 9 commits into
Conversation
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
Thanks for the pull request, @salman2013! This repository is currently maintained by Once you've gone through the following steps feel free to tag them in a comment and let them know that your changes are ready for engineering review. 🔘 Get product approvalIf you haven't already, check this list to see if your contribution needs to go through the product review process.
🔘 Provide contextTo help your reviewers and other members of the community understand the purpose and larger context of your changes, feel free to add as much of the following information to the PR description as you can:
🔘 Get a green buildIf one or more checks are failing, continue working on your changes until this is no longer the case and your build turns green. DetailsWhere can I find more information?If you'd like to get more details on all aspects of the review process for open source pull requests (OSPRs), check out the following resources: When can I expect my changes to be merged?Our goal is to get community contributions seen and reviewed as efficiently as possible. However, the amount of time that it takes to review and merge a PR can vary significantly based on factors such as:
💡 As a result it may take up to several weeks or months to complete a review and merge your PR. |
The translations/ directory is a symlink to conf/locale. Setuptools skips symlinks when building sdists, causing the wheel build to fail with "doesn't exist or not a regular file". Also remove stale requirements/ references from MANIFEST.in. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| from .image_explorer import ImageExplorerBlock | ||
|
|
||
| __version__ = '3.1.1' | ||
| __version__ = version("xblock-image-explorer") |
There was a problem hiding this comment.
__version__ is assigned without a fallback. If the package is not installed, importlib.metadata.version() raises PackageNotFoundError and the import of this module fails entirely. Either:
- Add a
try/except PackageNotFoundErrorguard with a__version__ = "0.0.0"fallback, or - Remove
__version__entirely if no downstream code imports it (the simpler outcome).
There was a problem hiding this comment.
fixed and remove version entirely if no downstream code imports it (the simpler outcome).
| @@ -0,0 +1,140 @@ | |||
| [build-system] | |||
| requires = ["setuptools>=64", "setuptools-scm>=8.0"] | |||
There was a problem hiding this comment.
We discussed about it before.
Should we add the minimum bound in setuptools>=64
| "static/**", | ||
| "templates/**", | ||
| "public/**", | ||
| "conf/locale/**", |
There was a problem hiding this comment.
translations/config.yaml is present in the repo (src/image_explorer/translations/) and was included in the master wheel, but is missing from the PR wheel. Add "translations/**" to [tool.setuptools.package-data]:
[tool.setuptools.package-data]
"image_explorer" = [
"static/**",
"templates/**",
"public/**",
"conf/locale/**",
"translations/**",
]There was a problem hiding this comment.
Because translations/ in this repo is a symlink (git mode 120000) pointing to conf/locale/. Setuptools cannot copy symlinks as package data — it fails with:
error: can't copy 'src/image_explorer/translations': doesn't exist or not a regular file
The actual files (like config.yaml) live in conf/locale/, which is already covered by the existing "conf/locale/" entry. So adding "translations/" would be redundant and break the wheel build.
There was a problem hiding this comment.
Just reviewed the translations setup — translations/config.yaml is the atlas config used to pull translation files into the source repo (via make pull_translations in the Makefile). Atlas reads the source tree, not the installed wheel, so this file doesn't need to be in the package. Closing this comment.
https://github.com/salman2013/xblock-image-explorer/blob/modernize-python-tooling/src/image_explorer/conf/locale/config.yaml
https://github.com/salman2013/xblock-image-explorer/blob/modernize-python-tooling/Makefile
| name: Python CI | ||
|
|
||
| on: | ||
| push: |
There was a problem hiding this comment.
Is this removal intentional?
@claude generated details:
Thepush: branches: [master]trigger was removed. Master CI used it to run checks on direct pushes to master; with onlyworkflow_calladded, direct pushes no longer trigger CI independently. Consider restoring thepush:trigger alongsideworkflow_call:.
|
|
||
| - name: Upload dist artifacts | ||
| if: steps.release.outputs.released == 'true' | ||
| uses: actions/upload-artifact@v4 |
There was a problem hiding this comment.
actions/upload-artifact@v4 uses a mutable tag. All other actions in this PR are SHA-pinned — pin this one too.
Resolve the current SHA:
gh api repos/actions/upload-artifact/git/ref/tags/v4 --jq .object.sha|
|
||
| steps: | ||
| - name: Download dist artifacts | ||
| uses: actions/download-artifact@v4 |
There was a problem hiding this comment.
same:
actions/download-artifact@v4 uses a mutable tag. Pin to a full SHA with a version comment, matching the pattern used for the other actions in this workflow.
| $(PIP_COMPILE) -o requirements/ci.txt requirements/ci.in | ||
| sed -i '/^[dD]jango==/d' requirements/test.txt | ||
| upgrade: ## update uv.lock and constraints with the latest packages | ||
| uv lock --upgrade |
There was a problem hiding this comment.
The upgrade target runs uv lock --upgrade before edx_lint write_uv_constraints. The standard order is edx_lint write_uv_constraints first (so constraints are updated), then uv lock --upgrade (so the lockfile respects them). Swap the two lines.
- Remove __version__ from __init__.py (nothing imports it) - Fix build-system requires to use setuptools-scm>8.1 - Add translations/** to package-data (was in old setup.py, missing from wheel) - Restore push: [master] trigger in ci.yml (needed for direct pushes) - Pin upload-artifact and download-artifact to full SHAs in release.yml - Fix upgrade target: write_uv_constraints before uv lock --upgrade Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…uild) translations/ is a symlink to conf/locale/ — setuptools can't copy symlinks as package data. The content is already covered by conf/locale/**. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
| [tool.semantic_release] | ||
| # version is dynamic via setuptools-scm; no version_toml needed | ||
| build_command = "python -m pip install --upgrade build && SETUPTOOLS_SCM_PRETEND_VERSION=$NEW_VERSION python -m build" | ||
| allow_zero_version = true |
There was a problem hiding this comment.
I think repo already has version greater than zero, removing this config will be a great cleanup.
| {group = "django42"}, | ||
| ], | ||
| ] | ||
| constraint-dependencies = [] |
There was a problem hiding this comment.
The next line (constraint-dependencies = []) is empty — edx_lint write_uv_constraints was never run.
Without this, global edx-lint constraints (security pins, compatibility caps) are not applied to the lockfile. Run:
uv run --with edx-lint edx_lint write_uv_constraints pyproject.toml
Then commit the updated pyproject.toml and uv.lock.
| commands = | ||
| mkdir -p var | ||
| pytest {posargs:tests --cov image_explorer} | ||
|
|
There was a problem hiding this comment.
pytest is called directly here. Per the tooling flow, the Makefile should define commands and tox should call them:
- Add to
Makefile:test: ## run tests mkdir -p var pytest $(posargs)
- Change this
commandsline tomake test.
| commands = | ||
| pylint --fail-under=9.0 image_explorer | ||
| pylint --fail-under=9.0 src/image_explorer | ||
|
|
There was a problem hiding this comment.
pylint is called directly here. Per the tooling flow, the Makefile should define commands and tox should call them:
- Add to
Makefile:quality: ## run linting pylint --fail-under=9.0 src/image_explorer
- Change this
commandsline tomake quality.
| path: dist/ | ||
|
|
||
| - name: Publish to PyPI | ||
| uses: pypa/gh-action-pypi-publish@release/v1 |
There was a problem hiding this comment.
The uses: on the next line (pypa/gh-action-pypi-publish@release/v1) is not SHA-pinned — all other actions in this PR use a full commit SHA. Pin it:
uses: pypa/gh-action-pypi-publish@<SHA> # release/v1Get the current SHA:
gh api repos/pypa/gh-action-pypi-publish/git/ref/heads/release/v1 --jq '.object.sha'
- Remove allow_zero_version and major_on_zero from semantic_release config - Run edx_lint write_uv_constraints to populate constraint-dependencies - Add make test and make quality targets; tox now delegates to make - SHA-pin pypa/gh-action-pypi-publish in release workflow Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Move --cov=image_explorer into pytest addopts and simplify tox commands to plain `make test` to avoid make misinterpreting posargs flags (e.g. --cov) as its own options. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
pyproject.toml(PEP 621) — removedsetup.py, addedsetuptools-scmfor dynamic versioning, coverage config,importlib.metadatafor__version__pip-tools/requirements/*.txttouv+uv.lockwith[dependency-groups]; updatetox.inito usetox-uv/uv-venv-lock-runner; update CI to useastral-sh/setup-uvpython-semantic-releaseworkflow for automated PyPI publishing via OIDC trusted publisher; addcommitlintworkflow to enforce conventional commitssrc/layout — movedimage_explorer/tosrc/image_explorer/Test plan
uv run tox -e quality— pylint 9.45/10, passesuv run tox -e py312-django42— 6/6 tests passeduv run tox -e py312-django52— 6/6 tests passedopenedx/xblock-image-explorer(publisher: GitHub Actions, workflow:release.yml)🤖 Generated with Claude Code