Source: setuptools Version: 70.3.0-2 Severity: wishlist Tags: patch User: reproducible-bui...@lists.alioth.debian.org Usertags: randomess toolchain X-Debbugs-Cc: reproducible-b...@lists.alioth.debian.org
Hi, Whilst working on the Reproducible Builds effort [0], we noticed that setuptools can generate nondeterministic PKG-INFO files. For example, here is python-pylatex: ├── ./usr/lib/python3/dist-packages/PyLaTeX-1.4.2.egg-info/PKG-INFO │┄ Ordering differences only │ @@ -42,27 +42,27 @@ │ Requires-Dist: coverage; extra == "testing" │ Requires-Dist: pytest-cov; extra == "testing" │ Requires-Dist: black; extra == "testing" │ Requires-Dist: isort; extra == "testing" │ Provides-Extra: packaging │ Requires-Dist: twine; extra == "packaging" │ Provides-Extra: all │ +Requires-Dist: isort; extra == "all" │ +Requires-Dist: quantities; extra == "all" │ +Requires-Dist: alabaster<0.7.12; extra == "all" │ +Requires-Dist: numpy; extra == "all" │ Requires-Dist: pytest>=4.6; extra == "all" │ +Requires-Dist: black; extra == "all" │ +Requires-Dist: matplotlib; extra == "all" │ +Requires-Dist: MarkupSafe==2.0.1; extra == "all" │ +Requires-Dist: coverage; extra == "all" │ Requires-Dist: twine; extra == "all" │ +Requires-Dist: jinja2<3.0; extra == "all" │ Requires-Dist: sphinx; extra == "all" │ -Requires-Dist: numpy; extra == "all" │ -Requires-Dist: quantities; extra == "all" │ -Requires-Dist: coverage; extra == "all" │ -Requires-Dist: black; extra == "all" │ -Requires-Dist: alabaster<0.7.12; extra == "all" │ -Requires-Dist: isort; extra == "all" │ Requires-Dist: pytest-cov; extra == "all" │ -Requires-Dist: jinja2<3.0; extra == "all" │ -Requires-Dist: MarkupSafe==2.0.1; extra == "all" │ -Requires-Dist: matplotlib; extra == "all" The patch (also attached) is fairly simple: --- a/setuptools/_core_metadata.py +++ b/setuptools/_core_metadata.py @@ -226,7 +226,7 @@ def _write_requirements(self, file): if extra: _write_provides_extra(file, processed_extras, extra, unsafe_extra) - for req in _reqs.parse_strings(reqs): + for req in sorted(_reqs.parse_strings(reqs)): r = _include_extra(req, extra, condition.strip()) file.write(f"Requires-Dist: {r}\n") … although there may be more places where it is a problem. [0] https://reproducible-builds.org/ Regards, -- ,''`. : :' : Chris Lamb `. `'` la...@debian.org / chris-lamb.co.uk `-
diff --git a/setuptools/_core_metadata.py b/setuptools/_core_metadata.py index 45aae7d..f50e2a0 100644 --- a/setuptools/_core_metadata.py +++ b/setuptools/_core_metadata.py @@ -226,7 +226,7 @@ def _write_requirements(self, file): if extra: _write_provides_extra(file, processed_extras, extra, unsafe_extra) - for req in _reqs.parse_strings(reqs): + for req in sorted(_reqs.parse_strings(reqs)): r = _include_extra(req, extra, condition.strip()) file.write(f"Requires-Dist: {r}\n")