Repository navigation
Pin requirements with uv.lock for use in CI and on Read the Docs - #2937
Conversation
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2937 +/- ##
==========================================
- Coverage 95.41% 94.61% -0.80%
==========================================
Files 107 107
Lines 9662 9662
Branches 1462 1462
==========================================
- Hits 9219 9142 -77
- Misses 257 327 +70
- Partials 186 193 +7 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
...instead of the pinned requirements files in `ci_requirements/` that we've been using up until now.
Since uv.lock is about 330 KB, it's probably worth excluding from source distributions and wheels to keep sizes smaller. It'll still be included in Zenodo uploads.
|
@sapols, might you be interested in reviewing this PR to check out some fun infrastructure improvements? The purpose of this PR is to pin the dependencies used in PlasmaPy's CI and doc builds with |
| - These files are updated periodically via pull requests created by a | ||
| GitHub workflow to `update pinned requirements`_. |
There was a problem hiding this comment.
Note: This link currently takes you to the GitHub Action page (https://github.com/PlasmaPy/PlasmaPy/actions/workflows/update-pinned-reqs.yml) instead of the actual workflow script (https://github.com/PlasmaPy/PlasmaPy/blob/main/.github/workflows/update-pinned-reqs.yml).
[Opinion] To me it makes more sense to link to the script and not the Action. In any case this will not affect this PR.
| "numpydoc >= 1.7.0", | ||
| "pillow >= 10.4.0", | ||
| "pygments >= 2.18.0", | ||
| "pygments == 2.18.0", |
There was a problem hiding this comment.
You made a comment in the the .github/content/update-requirements-pr-bocy.md that a PR should be opened to remove an upper bound on a dependency if one is add. Should this also be true if we freeze == a dependency?
There was a problem hiding this comment.
Or maybe we only do this for install requirements (i.e. not tests, docs, etc.).
There was a problem hiding this comment.
Should this also be true if we freeze
==a dependency?
Yes! I'll need to update that.
- address this ⬆️
| maxpython = max(supported_python_versions) | ||
| minpython = min(supported_python_versions) |
There was a problem hiding this comment.
Note: The supported_python_versions can easily get out of date with pyproject.toml. Are there breadcrumbs to ensure this gets updated when pyproject.toml gets updated? Or, is there a way to scrape pyproject.toml for this info?
There was a problem hiding this comment.
I've been thinking the same thing! I did see an example noxfile.py somewhere that scraped pyproject.toml to get the supported versions of Python, but haven't had it be a high priority since I've been pretty thorough when dropping & adding versions of Python. I raised #2954 so we don't forget.
|
|
||
| version : str | ||
| The supported version of Python. | ||
| uv_requirement = "uv >= 0.6.1" |
There was a problem hiding this comment.
uv is not listed as a package dependency, should it be? If uv is included as a dependency, then this line can get out of sync easily.
There was a problem hiding this comment.
I have been wondering the same thing! I've seen it recommended that uv be installed completely independently of Python, which makes sense since uv can be used to install and manage multiple versions of Python at once.
uv needs to get installed first because it's what is used to install the dependencies in the tests. I put the uv requirement in here explicitly as a safeguard so that running nox -s docs will work even if uv hasn't been installed separately.
I'm going to need to take a bit more time to think about it! 😅
| doc_build_dir = "$READTHEDOCS_OUTPUT" if running_on_rtd else "docs/build/html" | ||
|
|
||
| if running_on_rtd: | ||
| rtd_output_path = pathlib.Path(os.environ.get("READTHEDOCS_OUTPUT")) / "html" | ||
| rtd_output_path.mkdir(parents=True, exist_ok=True) | ||
| doc_build_dir = str(rtd_output_path) | ||
| else: | ||
| doc_build_dir = "docs/build/html" |
There was a problem hiding this comment.
Whenever we build the docs the build directory is docs/_build (with an underscore), not docs/build. That's how the make files are constructed.
This build directory is a bit arbitrary though. However, this would make the build directory different if you built with make versus nox.
There was a problem hiding this comment.
Also, this block can be streamlined more...
| doc_build_dir = "$READTHEDOCS_OUTPUT" if running_on_rtd else "docs/build/html" | |
| if running_on_rtd: | |
| rtd_output_path = pathlib.Path(os.environ.get("READTHEDOCS_OUTPUT")) / "html" | |
| rtd_output_path.mkdir(parents=True, exist_ok=True) | |
| doc_build_dir = str(rtd_output_path) | |
| else: | |
| doc_build_dir = "docs/build/html" | |
| doc_build_dir = "docs/build/html" | |
| if running_on_rtd: | |
| rtd_output_path = pathlib.Path(os.environ.get("READTHEDOCS_OUTPUT")) / "html" | |
| rtd_output_path.mkdir(parents=True, exist_ok=True) | |
| doc_build_dir = str(rtd_output_path) |
rocco8773
left a comment
There was a problem hiding this comment.
I left a few minor comments that highlight some potential (unrelated 🤷♂️) issues, but nothing I think really holds up this PR.
With my limited knowledge of how uv and nox works, this looks good to me. There might be some subtleties I'm missing, but if it works it works!
|
@rocco8773 — Thank you for the very helpful review! |
|
Some exciting news for the pythoniverse is that PEP 751 was approved yesterday, which defines a standard for I'm inclined to stick with
It may be helpful to export |
Background
For the last several months, we've been using
uv pip compileto create separate pinned requirements files inci_requirements/for different versions of Python and for different operating systems. Having to deal with 18 separate files got unwieldy, and the Nox session to generate these files began to get tricky to maintain.uv.lockholds information about different dependency groups for different operating systems and for different versions of Python. Pinning requirements inuv.lockwould consolidate all of this information in a single file. 💾Description of changes
This PR switches multiple Nox sessions defined in
noxfile.pyfor testing and documentation builds to use requirements that are frozen inuv.lock. We can then useuv syncto install exact requirements.1Context
Updating pinned requirements is still done via
nox -s requirements, but can also be done withuv lock --upgrade. Keeping this as a Nox session ensures that we have a consistent/canonical way to updateuv.lock(i.e., by making sure we are using the same version ofuvwith the same options) both locally and in CI. With a Nox session, we could add in additional steps too (e.g., logging or exporting a documentation build requirements file).There are some Nox sessions that will not use
uv.lock, including the tests that run against the lowest versions of direct dependencies. Consequently, breaking changes in new versions of indirect dependencies could cause spontaneous CI failures. If this happens more than ∼twice per year, we might be able to create a separateuv.lockor requirements file for the lowest direct dependencies.This PR does not substantively change the GitHub workflow to update pinned requirements that is run weekly to quarantine new versions of dependencies and make sure that CI for other PRs does not get spontaneous failures due to breaking changes in upstream dependencies.
Closes #2852. Closes #2940.
Tasks
uv.lockinsteaduv.lockusinguv syncfor the Nox sessions for:_get_requirements_filepathand other unneeded functionalityvalidate_requirementsci_requirements/filesuv. We could probably adapt this section of the RTD docs to useuv syncinstead ofuv pip installso that the requirements fromuv.lockare used.Footnotes
Whilst
uv.lockis described as a "universal" lockfile, it is frankly planetary at best. 🪐 ↩