diff --git a/.github/workflows/doc-build.yml b/.github/workflows/doc-build.yml index 86418ff1f1f..2d7b797d54a 100644 --- a/.github/workflows/doc-build.yml +++ b/.github/workflows/doc-build.yml @@ -204,10 +204,9 @@ jobs: -e 's;#L[0-9]*";";' \ && git commit -a -m 'wipe-out') # Since HEAD is at commit 'wipe-out', HEAD~1 is commit 'new' (new doc), HEAD~2 is commit 'old' (old doc) - (cd doc && git diff $(git rev-parse HEAD~2) -- "*.html") > diff.txt - # Restore the new doc dropping changes by "wipe out" - (cd doc && git checkout -q -f HEAD~1) - .ci/create-changes-html.sh diff.txt doc + .ci/create-changes-html.sh $(cd doc && git rev-parse HEAD~2) doc + # Restore the new doc with changes made in create-changes-html.sh but dropping changes by "wipe out" + (cd doc && git stash -q && git checkout -q -f HEAD~1 && git stash pop -q || echo '(error ignored)') # Sometimes rm -rf .git errors out because of some diehard hidden files # So we simply move it out of the doc directory (cd doc && mv .git ../git && mv .gitattributes ../gitattributes) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 6af5214c27f..116d12bd3f9 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -349,7 +349,7 @@ esac ensure_pkg_src() { ############################################### case "$PKG_SRC_TYPE" in normal|wheel) - PKG_SRC=$(sage-package download $SAGE_DOWNLOAD_FILE_OPTIONS $PKG_BASE) || exit_with_error_msg "Error downloading tarball of $PKG_BASE" + PKG_SRC=$(sage-package download $SAGE_DOWNLOAD_FILE_OPTIONS -- $PKG_BASE) || exit_with_error_msg "Error downloading tarball of $PKG_BASE" # Do a final check that PKG_SRC is a file with an absolute path cd / if [ ! -f "$PKG_SRC" ]; then @@ -804,6 +804,13 @@ if [ $ERASE_ONLY = 1 ]; then exit 0 fi +if [ -z "$SAGE_INSTALL_FETCH_ONLY" ]; then + TAGS=$("$SAGE_INST_LOCAL"/bin/python3 -c "from packaging.tags import sys_tags; print(' '.join(f'{tag.interpreter}-{tag.abi}-{tag.platform}' for tag in sys_tags()))" 2>/dev/null) + if [ -n "$TAGS" ]; then + SAGE_DOWNLOAD_FILE_OPTIONS+=" --tags $TAGS" + fi +fi + if [ $INSTALL = 1 ]; then warning_for_experimental_packages ensure_pkg_src diff --git a/build/pkgs/clarabel/checksums.ini b/build/pkgs/clarabel/checksums.ini new file mode 100644 index 00000000000..18b86de9dc3 --- /dev/null +++ b/build/pkgs/clarabel/checksums.ini @@ -0,0 +1,35 @@ +[clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl] +tarball=clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl +sha256=702cc4666c0ccf893c936f9f1f55cbb3233ae2d5fa05f67b370ac3e7ec50f222 +upstream_url=https://files.pythonhosted.org/packages/8b/b9/e41f5316a2d4261c340d9fa6aa1694dd57d12cc45f1e5dfc5773d2b53d39/clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl + +[clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.whl] +tarball=clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.whl +sha256=8ea616757b460153ead375b3dd3ce763d46fc3717248077bbfa7b2c844b1775f +upstream_url=https://files.pythonhosted.org/packages/65/75/b4f2b5f4a0af6975c463efe9ef580debff98ade6795e6e885babf7527586/clarabel-0.9.0-cp37-abi3-macosx_10_12_x86_64.whl + +[clarabel-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=clarabel-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=2b5ae16d7dd87aabf72260cf9590ba0d037c52d48555bcf3a86b1f0d9cf88dd4 +upstream_url=https://files.pythonhosted.org/packages/a5/2e/096e0bc32ffa7eadb69f6e768fbbc58acf0b0e4003db4bd70c79b1856c47/clarabel-0.9.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[clarabel-0.9.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl] +tarball=clarabel-0.9.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl +sha256=85cb560a5c4cdfb079e3437e21f0b62b69ba766ae082aeb96ced0b5763214077 +upstream_url=https://files.pythonhosted.org/packages/d9/1a/4319fa902c9c3e350d134d78d79baa61c6e2e5e51050861ecc147c73f6a7/clarabel-0.9.0-cp37-abi3-manylinux_2_17_i686.manylinux2014_i686.whl + +[clarabel-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=clarabel-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=0eaeb3fbb5a90b598700d5435c7f102592a1a79ee25df5a097e0af575838786b +upstream_url=https://files.pythonhosted.org/packages/8c/12/e92ba69884f84e0f16a9fb5093522924502995348f0269cc42ed062f2edc/clarabel-0.9.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[clarabel-0.9.0-cp37-abi3-win32.whl] +tarball=clarabel-0.9.0-cp37-abi3-win32.whl +sha256=759c2fa0ccc61ae1a02691c43753638a0ae793bf1de81c6f6763c346789a7e25 +upstream_url=https://files.pythonhosted.org/packages/2e/1f/ce55955a7ad5946cacd1f0aa76233ee354d4c357669ce81f1e5dc69be971/clarabel-0.9.0-cp37-abi3-win32.whl + +[clarabel-0.9.0-cp37-abi3-win_amd64.whl] +tarball=clarabel-0.9.0-cp37-abi3-win_amd64.whl +sha256=d24e4ed1b686eb2fe2a1b6e77935af6ad62a2c044131e70801ec1d3ef3d33280 +upstream_url=https://files.pythonhosted.org/packages/36/be/110fe7ca190e024e3185d6351645346b785da6933ce3fb382d4811215f8c/clarabel-0.9.0-cp37-abi3-win_amd64.whl + diff --git a/build/pkgs/clarabel/dependencies b/build/pkgs/clarabel/dependencies index 47296a7bace..8d5698b62b8 100644 --- a/build/pkgs/clarabel/dependencies +++ b/build/pkgs/clarabel/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) +numpy scipy | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/clarabel/package-version.txt b/build/pkgs/clarabel/package-version.txt new file mode 100644 index 00000000000..ac39a106c48 --- /dev/null +++ b/build/pkgs/clarabel/package-version.txt @@ -0,0 +1 @@ +0.9.0 diff --git a/build/pkgs/clarabel/requirements.txt b/build/pkgs/clarabel/version_requirements.txt similarity index 100% rename from build/pkgs/clarabel/requirements.txt rename to build/pkgs/clarabel/version_requirements.txt diff --git a/build/pkgs/jsonschema/SPKG.rst b/build/pkgs/jsonschema/SPKG.rst index bf655277b78..e5376e5a230 100644 --- a/build/pkgs/jsonschema/SPKG.rst +++ b/build/pkgs/jsonschema/SPKG.rst @@ -1,19 +1,18 @@ -jsonschema: Python implementation of JSON Schema -================================================ +jsonschema: Implementation of JSON Schema validation for Python +=============================================================== Description ----------- -jsonschema is an implementation of JSON Schema for Python +Implementation of JSON Schema validation for Python License ------- -MIT License - +MIT Upstream Contact ---------------- -Home page: http://github.com/Julian/jsonschema +https://pypi.org/project/jsonschema/ diff --git a/build/pkgs/jsonschema/checksums.ini b/build/pkgs/jsonschema/checksums.ini index e709e36e5d3..c41106adfcf 100644 --- a/build/pkgs/jsonschema/checksums.ini +++ b/build/pkgs/jsonschema/checksums.ini @@ -1,4 +1,5 @@ -tarball=jsonschema-VERSION-py3-none-any.whl -sha1=189537b18c91e60be991a3dba704577d19f8e48d -sha256=a870ad254da1a8ca84b6a2905cac29d265f805acc57af304784962a2aa6508f6 -upstream_url=https://pypi.io/packages/py3/j/jsonschema/jsonschema-VERSION-py3-none-any.whl +[jsonschema-4.22.0-py3-none-any.whl] +tarball=jsonschema-4.22.0-py3-none-any.whl +sha256=ff4cfd6b1367a40e7bc6411caec72effadd3db0bbe5017de188f2d6108335802 +upstream_url=https://files.pythonhosted.org/packages/c8/2f/324fab4be6fe37fb7b521546e8a557e6cf08c1c1b3d0b4839a00f589d9ef/jsonschema-4.22.0-py3-none-any.whl + diff --git a/build/pkgs/jsonschema/dependencies b/build/pkgs/jsonschema/dependencies index 8c7c4532c8d..14bf29a08ad 100644 --- a/build/pkgs/jsonschema/dependencies +++ b/build/pkgs/jsonschema/dependencies @@ -1,4 +1,4 @@ -jsonschema_specifications pyrsistent attrs fqdn isoduration jsonpointer uri_template webcolors | $(PYTHON_TOOLCHAIN) $(PYTHON) +attrs jsonschema_specifications referencing rpds_py | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonschema/package-version.txt b/build/pkgs/jsonschema/package-version.txt index ab268c2099f..d7638f377ef 100644 --- a/build/pkgs/jsonschema/package-version.txt +++ b/build/pkgs/jsonschema/package-version.txt @@ -1 +1 @@ -4.17.3 +4.22.0 diff --git a/build/pkgs/jsonschema/version_requirements.txt b/build/pkgs/jsonschema/version_requirements.txt index 904caddfed0..d89304b1a89 100644 --- a/build/pkgs/jsonschema/version_requirements.txt +++ b/build/pkgs/jsonschema/version_requirements.txt @@ -1 +1 @@ -jsonschema >=3.2.0 +jsonschema diff --git a/build/pkgs/jsonschema_specifications/checksums.ini b/build/pkgs/jsonschema_specifications/checksums.ini index df5d6944abd..fd52498cb57 100644 --- a/build/pkgs/jsonschema_specifications/checksums.ini +++ b/build/pkgs/jsonschema_specifications/checksums.ini @@ -1,4 +1,4 @@ tarball=jsonschema_specifications-VERSION-py3-none-any.whl -sha1=4132bed31478bc96960099e58ae4c083c514c551 -sha256=764a2b9325c225208121948b15f2b2d16fddbe223fdfc096b45c70c1f7f7b8c1 +sha1=2000de39fb573689f2119aa8ad9d1108cd1db217 +sha256=87e4fdf3a94858b8a2ba2778d9ba57d8a9cafca7c7489c46ba0d30a8bc6a9c3c upstream_url=https://pypi.io/packages/py3/j/jsonschema_specifications/jsonschema_specifications-VERSION-py3-none-any.whl diff --git a/build/pkgs/jsonschema_specifications/package-version.txt b/build/pkgs/jsonschema_specifications/package-version.txt index 5fe615f731b..7729d27eac0 100644 --- a/build/pkgs/jsonschema_specifications/package-version.txt +++ b/build/pkgs/jsonschema_specifications/package-version.txt @@ -1 +1 @@ -2023.3.3 +2023.12.1 diff --git a/build/pkgs/pyrsistent/SPKG.rst b/build/pkgs/pyrsistent/SPKG.rst deleted file mode 100644 index d943e31aaf8..00000000000 --- a/build/pkgs/pyrsistent/SPKG.rst +++ /dev/null @@ -1,32 +0,0 @@ -pyrsistent: Persistent data structures in Python -================================================ - -Description ------------ - -Pyrsistent is a number of persistent collections (by some referred to as -functional data structures). Persistent in the sense that they are immutable. - -License -------- - -MIT License - - -Upstream Contact ----------------- - -Home page: http://github.com/tobgu/pyrsistent/ - -Dependencies ------------- - -- Python -- Setuptools -- hypothesis -- memory-profiler -- pyperform -- pytest -- Sphinx -- sphinx-rtd-theme -- tox diff --git a/build/pkgs/pyrsistent/checksums.ini b/build/pkgs/pyrsistent/checksums.ini deleted file mode 100644 index b7a30f5a171..00000000000 --- a/build/pkgs/pyrsistent/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=pyrsistent-VERSION.tar.gz -sha1=79980873658f7634ae25758b9710088b62e0612a -sha256=1a2994773706bbb4995c31a97bc94f1418314923bd1048c6d964837040376440 -upstream_url=https://pypi.io/packages/source/p/pyrsistent/pyrsistent-VERSION.tar.gz diff --git a/build/pkgs/pyrsistent/distros/conda.txt b/build/pkgs/pyrsistent/distros/conda.txt deleted file mode 100644 index c44a762ba0b..00000000000 --- a/build/pkgs/pyrsistent/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -pyrsistent diff --git a/build/pkgs/pyrsistent/distros/gentoo.txt b/build/pkgs/pyrsistent/distros/gentoo.txt deleted file mode 100644 index 83439cebfe4..00000000000 --- a/build/pkgs/pyrsistent/distros/gentoo.txt +++ /dev/null @@ -1 +0,0 @@ -dev-python/pyrsistent diff --git a/build/pkgs/pyrsistent/distros/macports.txt b/build/pkgs/pyrsistent/distros/macports.txt deleted file mode 100644 index a0c9da3d19b..00000000000 --- a/build/pkgs/pyrsistent/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -py-pyrsistent diff --git a/build/pkgs/pyrsistent/distros/repology.txt b/build/pkgs/pyrsistent/distros/repology.txt deleted file mode 100644 index 4b8b8a25979..00000000000 --- a/build/pkgs/pyrsistent/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -pyrsistent -python:pyrsistent diff --git a/build/pkgs/pyrsistent/distros/void.txt b/build/pkgs/pyrsistent/distros/void.txt deleted file mode 100644 index 77485df49f0..00000000000 --- a/build/pkgs/pyrsistent/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -python3-pyrsistent diff --git a/build/pkgs/pyrsistent/package-version.txt b/build/pkgs/pyrsistent/package-version.txt deleted file mode 100644 index b72b05ede10..00000000000 --- a/build/pkgs/pyrsistent/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.19.3 diff --git a/build/pkgs/pyrsistent/spkg-configure.m4 b/build/pkgs/pyrsistent/spkg-configure.m4 deleted file mode 100644 index f7ca75dbac5..00000000000 --- a/build/pkgs/pyrsistent/spkg-configure.m4 +++ /dev/null @@ -1 +0,0 @@ -SAGE_SPKG_CONFIGURE([pyrsistent], [SAGE_PYTHON_PACKAGE_CHECK([pyrsistent])]) diff --git a/build/pkgs/pyrsistent/spkg-install.in b/build/pkgs/pyrsistent/spkg-install.in deleted file mode 100644 index c896e17115c..00000000000 --- a/build/pkgs/pyrsistent/spkg-install.in +++ /dev/null @@ -1,14 +0,0 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo "Error installing pyrsistent ... exiting" - exit 1 -fi diff --git a/build/pkgs/pyrsistent/version_requirements.txt b/build/pkgs/pyrsistent/version_requirements.txt deleted file mode 100644 index e2e8c5f1c74..00000000000 --- a/build/pkgs/pyrsistent/version_requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pyrsistent >=0.16.0 diff --git a/build/pkgs/referencing/checksums.ini b/build/pkgs/referencing/checksums.ini index 293629ca16d..de509c55fc2 100644 --- a/build/pkgs/referencing/checksums.ini +++ b/build/pkgs/referencing/checksums.ini @@ -1,4 +1,4 @@ tarball=referencing-VERSION-py3-none-any.whl -sha1=9d710ba3a604d24ffded218a3813b5fd1fe2e495 -sha256=160f24a7d2411dc82b1efd96dfb083ee9e5cc9bc8e492d323e0dd853989d37b3 +sha1=99eff1ea1adcc39e04dbed8487bc01974766646e +sha256=eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de upstream_url=https://pypi.io/packages/py3/r/referencing/referencing-VERSION-py3-none-any.whl diff --git a/build/pkgs/referencing/dependencies b/build/pkgs/referencing/dependencies index 39c6d3527b3..4e1a55d2f84 100644 --- a/build/pkgs/referencing/dependencies +++ b/build/pkgs/referencing/dependencies @@ -1,4 +1,4 @@ -attrs pyrsistent | $(PYTHON_TOOLCHAIN) $(PYTHON) +attrs rpds_py | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/referencing/package-version.txt b/build/pkgs/referencing/package-version.txt index ca222b7cf39..731b95d7fc8 100644 --- a/build/pkgs/referencing/package-version.txt +++ b/build/pkgs/referencing/package-version.txt @@ -1 +1 @@ -0.23.0 +0.35.1 diff --git a/build/pkgs/rpds_py/SPKG.rst b/build/pkgs/rpds_py/SPKG.rst new file mode 100644 index 00000000000..a24834a771a --- /dev/null +++ b/build/pkgs/rpds_py/SPKG.rst @@ -0,0 +1,21 @@ +rpds_py: Python bindings to Rust's persistent data structures (rpds) +==================================================================== + +Description +----------- + +Python bindings to Rust's persistent data structures (rpds) + +In SageMath, this package is used as a dependency package of the +Jupyter notebook / JupyterLab. + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/rpds-py/ + diff --git a/build/pkgs/rpds_py/checksums.ini b/build/pkgs/rpds_py/checksums.ini new file mode 100644 index 00000000000..e2e459d4c0f --- /dev/null +++ b/build/pkgs/rpds_py/checksums.ini @@ -0,0 +1,325 @@ +[rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl +sha256=d31dea506d718693b6b2cffc0648a8929bdc51c70a311b2770f09611caa10d53 +upstream_url=https://files.pythonhosted.org/packages/a1/eb/5b7591bb8d9f710df243a3b6304a2b70db5a426a2bd478c2912f8b81b806/rpds_py-0.18.1-cp310-cp310-macosx_10_12_x86_64.whl + +[rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl +sha256=732672fbc449bab754e0b15356c077cc31566df874964d4801ab14f71951ea80 +upstream_url=https://files.pythonhosted.org/packages/b9/9a/f1cce2481968d0ff1301d6da02bb977d7c7dc2ad9d218281ead38cc7f1ae/rpds_py-0.18.1-cp310-cp310-macosx_11_0_arm64.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=4a98a1f0552b5f227a3d6422dbd61bc6f30db170939bd87ed14f3c339aa6c7c9 +upstream_url=https://files.pythonhosted.org/packages/f3/16/7ddc46210ec4b52614c5d5ed72ca0afd12b6c6af1d7cb3859b2e7faa8ffe/rpds_py-0.18.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl +sha256=7f1944ce16401aad1e3f7d312247b3d5de7981f634dc9dfe90da72b87d37887d +upstream_url=https://files.pythonhosted.org/packages/fd/6a/e67b83791863db607a297b822fe95813c6cbff979608496f47d81ad45fea/rpds_py-0.18.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl +sha256=38e14fb4e370885c4ecd734f093a2225ee52dc384b86fa55fe3f74638b2cfb09 +upstream_url=https://files.pythonhosted.org/packages/d7/a9/b25013071a61f008a8266a208e701cf8ec2c2946feb6005b3ec454f63a66/rpds_py-0.18.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl +sha256=08d74b184f9ab6289b87b19fe6a6d1a97fbfea84b8a3e745e87a5de3029bf944 +upstream_url=https://files.pythonhosted.org/packages/57/65/b9769f891d0f2f915151f6d172f82ce182cedf950bcc65af4e853d794421/rpds_py-0.18.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=d70129cef4a8d979caa37e7fe957202e7eee8ea02c5e16455bc9808a59c6b2f0 +upstream_url=https://files.pythonhosted.org/packages/e5/20/10c12b1acb102c4981a7e1dc86b60e36c1d5c940a7bda48643542f80dbff/rpds_py-0.18.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl] +tarball=rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl +sha256=ce0bb20e3a11bd04461324a6a798af34d503f8d6f1aa3d2aa8901ceaf039176d +upstream_url=https://files.pythonhosted.org/packages/73/5b/bf77d1fe5025eeec85d62e389edacf073b93553b4837f8221093acc3ed7e/rpds_py-0.18.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl + +[rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl +sha256=81c5196a790032e0fc2464c0b4ab95f8610f96f1f2fa3d4deacce6a79852da60 +upstream_url=https://files.pythonhosted.org/packages/c2/b9/dcb20646cda07b4e9db3b346c19a4685623c9a9aa8ad8a566776def0da33/rpds_py-0.18.1-cp310-cp310-musllinux_1_2_aarch64.whl + +[rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl] +tarball=rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl +sha256=f3027be483868c99b4985fda802a57a67fdf30c5d9a50338d9db646d590198da +upstream_url=https://files.pythonhosted.org/packages/55/5c/f59ed857a85d6713d936d70e3235a7c9bc51bc83ab7c1b4e9b4f9371abbc/rpds_py-0.18.1-cp310-cp310-musllinux_1_2_i686.whl + +[rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl] +tarball=rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl +sha256=d44607f98caa2961bab4fa3c4309724b185b464cdc3ba6f3d7340bac3ec97cc1 +upstream_url=https://files.pythonhosted.org/packages/4f/3c/2807bb396f1d940813d1ec39efb8984ec01e84e2064db9a06bf314f3658d/rpds_py-0.18.1-cp310-cp310-musllinux_1_2_x86_64.whl + +[rpds_py-0.18.1-cp310-none-win32.whl] +tarball=rpds_py-0.18.1-cp310-none-win32.whl +sha256=c273e795e7a0f1fddd46e1e3cb8be15634c29ae8ff31c196debb620e1edb9333 +upstream_url=https://files.pythonhosted.org/packages/d2/13/495eea6921b280ac04602fc3cc4b385ab985a2eb3e450281d02ce98872bc/rpds_py-0.18.1-cp310-none-win32.whl + +[rpds_py-0.18.1-cp310-none-win_amd64.whl] +tarball=rpds_py-0.18.1-cp310-none-win_amd64.whl +sha256=8352f48d511de5f973e4f2f9412736d7dea76c69faa6d36bcf885b50c758ab9a +upstream_url=https://files.pythonhosted.org/packages/1b/bf/c8f8b5d1da7f0673998c63d2246987773c3422e1c2482bbf511b7fffe184/rpds_py-0.18.1-cp310-none-win_amd64.whl + +[rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl +sha256=6b5ff7e1d63a8281654b5e2896d7f08799378e594f09cf3674e832ecaf396ce8 +upstream_url=https://files.pythonhosted.org/packages/0c/f3/454ef9c66219ea511991e024f3a379fca618acd4cbe12e369b2d02f9d0b6/rpds_py-0.18.1-cp311-cp311-macosx_10_12_x86_64.whl + +[rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl +sha256=8927638a4d4137a289e41d0fd631551e89fa346d6dbcfc31ad627557d03ceb6d +upstream_url=https://files.pythonhosted.org/packages/58/e3/b5eb611e2d51688726533bb97b420d36a55d4560c53d016e977ff6d48116/rpds_py-0.18.1-cp311-cp311-macosx_11_0_arm64.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=154bf5c93d79558b44e5b50cc354aa0459e518e83677791e6adb0b039b7aa6a7 +upstream_url=https://files.pythonhosted.org/packages/92/48/32bed868dd4e7d16e26457cc0b8634d6b16cb0e082a93f044ef5f7c77361/rpds_py-0.18.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl +sha256=07f2139741e5deb2c5154a7b9629bc5aa48c766b643c1a6750d16f865a82c5fc +upstream_url=https://files.pythonhosted.org/packages/77/66/905aa687ea072d8980f7b14eb9e3c3023f5f3892eb8b88be024094956014/rpds_py-0.18.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl +sha256=8c7672e9fba7425f79019db9945b16e308ed8bc89348c23d955c8c0540da0a07 +upstream_url=https://files.pythonhosted.org/packages/4e/6c/c658183fc2d2a6ed97b0816ab4fef59d609e596bf6f5f0898ae955c14885/rpds_py-0.18.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl +sha256=489bdfe1abd0406eba6b3bb4fdc87c7fa40f1031de073d0cfb744634cc8fa261 +upstream_url=https://files.pythonhosted.org/packages/91/33/b680feac0159b5b66ebb9e6d635d78e94486b0b7ed58bea273be2cc80817/rpds_py-0.18.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=3c20f05e8e3d4fc76875fc9cb8cf24b90a63f5a1b4c5b9273f0e8225e169b100 +upstream_url=https://files.pythonhosted.org/packages/1b/a0/a3702128743ae5bf14175a7333a4741db167f62d42f70e0edc15d9cd45c5/rpds_py-0.18.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl] +tarball=rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl +sha256=967342e045564cef76dfcf1edb700b1e20838d83b1aa02ab313e6a497cf923b8 +upstream_url=https://files.pythonhosted.org/packages/c1/3b/a4ed8b067a8f55df92dc1bc4d20858f02ddfdba3057f96759f4dd1bff7af/rpds_py-0.18.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl + +[rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl +sha256=2cc7c1a47f3a63282ab0f422d90ddac4aa3034e39fc66a559ab93041e6505da7 +upstream_url=https://files.pythonhosted.org/packages/f4/ba/adb81247a2fe211ff74cd4c2790454bbf37eb7430ee898e4aa7ce5cb6507/rpds_py-0.18.1-cp311-cp311-musllinux_1_2_aarch64.whl + +[rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl] +tarball=rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl +sha256=f7afbfee1157e0f9376c00bb232e80a60e59ed716e3211a80cb8506550671e6e +upstream_url=https://files.pythonhosted.org/packages/52/fc/1eb8dcf82ec8d1252c060644fa44478660e94637ddd91dc8d452b467f359/rpds_py-0.18.1-cp311-cp311-musllinux_1_2_i686.whl + +[rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl] +tarball=rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl +sha256=9e6934d70dc50f9f8ea47081ceafdec09245fd9f6032669c3b45705dea096b88 +upstream_url=https://files.pythonhosted.org/packages/a9/3f/0b8e2ac89076fede032aae3fc9cf9390c6fd99a470b238fb62bbc64f4cbf/rpds_py-0.18.1-cp311-cp311-musllinux_1_2_x86_64.whl + +[rpds_py-0.18.1-cp311-none-win32.whl] +tarball=rpds_py-0.18.1-cp311-none-win32.whl +sha256=c69882964516dc143083d3795cb508e806b09fc3800fd0d4cddc1df6c36e76bb +upstream_url=https://files.pythonhosted.org/packages/74/e0/f9dc97509b3048ddc3ab7b0cd48bd25f78dff45bec463c62b0171c57398c/rpds_py-0.18.1-cp311-none-win32.whl + +[rpds_py-0.18.1-cp311-none-win_amd64.whl] +tarball=rpds_py-0.18.1-cp311-none-win_amd64.whl +sha256=70a838f7754483bcdc830444952fd89645569e7452e3226de4a613a4c1793fb2 +upstream_url=https://files.pythonhosted.org/packages/ff/26/0778cc18815f20e37eb492bfed622d01722db38b2f3f86790753b01b2a73/rpds_py-0.18.1-cp311-none-win_amd64.whl + +[rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl +sha256=3dd3cd86e1db5aadd334e011eba4e29d37a104b403e8ca24dcd6703c68ca55b3 +upstream_url=https://files.pythonhosted.org/packages/03/04/a39fc930b1ab45943b7f3a8d990a3c731b37541d9eb58c5664374c2ce007/rpds_py-0.18.1-cp312-cp312-macosx_10_12_x86_64.whl + +[rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl +sha256=05f3d615099bd9b13ecf2fc9cf2d839ad3f20239c678f461c753e93755d629ee +upstream_url=https://files.pythonhosted.org/packages/97/2a/e96015e3e6c0b1d5c06a009ab058f30776a4a6e1b14773ad7beefac82b99/rpds_py-0.18.1-cp312-cp312-macosx_11_0_arm64.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=35b2b771b13eee8729a5049c976197ff58a27a3829c018a04341bcf1ae409b2b +upstream_url=https://files.pythonhosted.org/packages/19/38/eb7ae2b3ca5001b74536a67555e65202bedd1302f3d5d5000f7b0dc67ba6/rpds_py-0.18.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl +sha256=ee17cd26b97d537af8f33635ef38be873073d516fd425e80559f4585a7b90c43 +upstream_url=https://files.pythonhosted.org/packages/20/6a/571d8b2afa73bf750f86eeaad7e132c7cce1b0a22cc0ab2c53545bbac6e1/rpds_py-0.18.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl +sha256=b646bf655b135ccf4522ed43d6902af37d3f5dbcf0da66c769a2b3938b9d8184 +upstream_url=https://files.pythonhosted.org/packages/3c/b1/af0a13cdcd9183ec6f4ea9f2ae8cb48a697db0961a3f80e11a937af91f28/rpds_py-0.18.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl +sha256=19ba472b9606c36716062c023afa2484d1e4220548751bda14f725a7de17b4f6 +upstream_url=https://files.pythonhosted.org/packages/03/30/067d42b83d2b4e0c918a3e130236423cb3c7da0920cc162c5fce8f944205/rpds_py-0.18.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=6e30ac5e329098903262dc5bdd7e2086e0256aa762cc8b744f9e7bf2a427d3f8 +upstream_url=https://files.pythonhosted.org/packages/28/1c/2e208636275eab9636981fee10cb5cdaf3d5a202c3c16bf31fdd52ee08d0/rpds_py-0.18.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl] +tarball=rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl +sha256=d58ad6317d188c43750cb76e9deacf6051d0f884d87dc6518e0280438648a9ac +upstream_url=https://files.pythonhosted.org/packages/45/04/8fd5e166e8bb6d386491f41da51ae07118deb5461114f9eb160a7c10cedc/rpds_py-0.18.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl + +[rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl +sha256=e1735502458621921cee039c47318cb90b51d532c2766593be6207eec53e5c4c +upstream_url=https://files.pythonhosted.org/packages/6b/b8/5da92178ecd95f6193cb4144f5c2a21bd6d743200c0739c9290c6240bfc1/rpds_py-0.18.1-cp312-cp312-musllinux_1_2_aarch64.whl + +[rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl] +tarball=rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl +sha256=f5bab211605d91db0e2995a17b5c6ee5edec1270e46223e513eaa20da20076ac +upstream_url=https://files.pythonhosted.org/packages/d1/28/e63095852b338b4c476f34fca47d87befb19f219a326fd3f3e3749e1a49b/rpds_py-0.18.1-cp312-cp312-musllinux_1_2_i686.whl + +[rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl] +tarball=rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl +sha256=2fc24a329a717f9e2448f8cd1f960f9dac4e45b6224d60734edeb67499bab03a +upstream_url=https://files.pythonhosted.org/packages/63/5e/20602b2cfdf0cafa8b1668cf64ccdb32d43dcb996d3ba456fcc02e791a88/rpds_py-0.18.1-cp312-cp312-musllinux_1_2_x86_64.whl + +[rpds_py-0.18.1-cp312-none-win32.whl] +tarball=rpds_py-0.18.1-cp312-none-win32.whl +sha256=1805d5901779662d599d0e2e4159d8a82c0b05faa86ef9222bf974572286b2b6 +upstream_url=https://files.pythonhosted.org/packages/fd/c6/947a657bc116c985517e7a7efe01a043f263ee2dd2c9875cedc8ebf26373/rpds_py-0.18.1-cp312-none-win32.whl + +[rpds_py-0.18.1-cp312-none-win_amd64.whl] +tarball=rpds_py-0.18.1-cp312-none-win_amd64.whl +sha256=720edcb916df872d80f80a1cc5ea9058300b97721efda8651efcd938a9c70a72 +upstream_url=https://files.pythonhosted.org/packages/01/7d/8552e329973a198e5e150cc6be068f5cbae797a89e64c02bbd47bd397dee/rpds_py-0.18.1-cp312-none-win_amd64.whl + +[rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl +sha256=c827576e2fa017a081346dce87d532a5310241648eb3700af9a571a6e9fc7e74 +upstream_url=https://files.pythonhosted.org/packages/db/89/c0e8e04be0d4ebb390d9b0941288a0268b5d1a98a6eec22723e009c9334f/rpds_py-0.18.1-cp38-cp38-macosx_10_12_x86_64.whl + +[rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl +sha256=aa3679e751408d75a0b4d8d26d6647b6d9326f5e35c00a7ccd82b78ef64f65f8 +upstream_url=https://files.pythonhosted.org/packages/65/42/e8ea20e5ecbd3ed2228500db56024fc09f130a75bf9d530c88aca4f57aa6/rpds_py-0.18.1-cp38-cp38-macosx_11_0_arm64.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=0abeee75434e2ee2d142d650d1e54ac1f8b01e6e6abdde8ffd6eeac6e9c38e20 +upstream_url=https://files.pythonhosted.org/packages/59/21/26b0b40d3945e2a83d3626dff45ca65d4d719f914bbcbc23e43162b5cd8d/rpds_py-0.18.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl +sha256=ed402d6153c5d519a0faf1bb69898e97fb31613b49da27a84a13935ea9164dfc +upstream_url=https://files.pythonhosted.org/packages/11/12/866549e2af13cc70f23ec297d9bbdb9cf97745392bfdf61cbd946a7d7ca6/rpds_py-0.18.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl +sha256=338dee44b0cef8b70fd2ef54b4e09bb1b97fc6c3a58fea5db6cc083fd9fc2724 +upstream_url=https://files.pythonhosted.org/packages/e8/81/d47f29b80a9cd9ea81bd03561c7e0515f2bbe823767864f91745a3906cb0/rpds_py-0.18.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl +sha256=7750569d9526199c5b97e5a9f8d96a13300950d910cf04a861d96f4273d5b104 +upstream_url=https://files.pythonhosted.org/packages/ba/47/7995225572d53b14bafb9d406f52145b6a082009cf10143646d3f22913f2/rpds_py-0.18.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=607345bd5912aacc0c5a63d45a1f73fef29e697884f7e861094e443187c02be5 +upstream_url=https://files.pythonhosted.org/packages/6b/2d/7ce6b2fe57d288b0c3e735e79612e79cddb52b6042b68e9c329e25c42ff5/rpds_py-0.18.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl] +tarball=rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl +sha256=207c82978115baa1fd8d706d720b4a4d2b0913df1c78c85ba73fe6c5804505f0 +upstream_url=https://files.pythonhosted.org/packages/a5/2d/2447c5a8872097a7b6bb7d28305fc85d27d797bf9715d5ea44f36eacabc7/rpds_py-0.18.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl + +[rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl +sha256=6d1e42d2735d437e7e80bab4d78eb2e459af48c0a46e686ea35f690b93db792d +upstream_url=https://files.pythonhosted.org/packages/e5/5a/2e0ac1c38021da0055f08a0f49be29f64df6dcffcdd63b2d38c402e94489/rpds_py-0.18.1-cp38-cp38-musllinux_1_2_aarch64.whl + +[rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl] +tarball=rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl +sha256=5463c47c08630007dc0fe99fb480ea4f34a89712410592380425a9b4e1611d8e +upstream_url=https://files.pythonhosted.org/packages/6f/3e/efa774354adc00b3d3dbae80daf3fbd0155d68c246d0b41f626d53f329d1/rpds_py-0.18.1-cp38-cp38-musllinux_1_2_i686.whl + +[rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl] +tarball=rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl +sha256=06d218939e1bf2ca50e6b0ec700ffe755e5216a8230ab3e87c059ebb4ea06afc +upstream_url=https://files.pythonhosted.org/packages/19/4e/e72c314d3a5933aa37cdd045ec21e1b0ad9cf3b38166b61732481d3a4a00/rpds_py-0.18.1-cp38-cp38-musllinux_1_2_x86_64.whl + +[rpds_py-0.18.1-cp38-none-win32.whl] +tarball=rpds_py-0.18.1-cp38-none-win32.whl +sha256=312fe69b4fe1ffbe76520a7676b1e5ac06ddf7826d764cc10265c3b53f96dbe9 +upstream_url=https://files.pythonhosted.org/packages/85/d1/af79ddf8087c350c4534a0fabc340befd4b066e0db4548669e57ab1a2b2b/rpds_py-0.18.1-cp38-none-win32.whl + +[rpds_py-0.18.1-cp38-none-win_amd64.whl] +tarball=rpds_py-0.18.1-cp38-none-win_amd64.whl +sha256=9437ca26784120a279f3137ee080b0e717012c42921eb07861b412340f85bae2 +upstream_url=https://files.pythonhosted.org/packages/d1/db/babfc21d701ab9a7192b634803881e450bb73b9e8894b7f10d1015fedec1/rpds_py-0.18.1-cp38-none-win_amd64.whl + +[rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl +sha256=19e515b78c3fc1039dd7da0a33c28c3154458f947f4dc198d3c72db2b6b5dc93 +upstream_url=https://files.pythonhosted.org/packages/d7/a0/15114fa1e4427b966e686f10fbad8c23a464d226d34a6712dcaa366707d7/rpds_py-0.18.1-cp39-cp39-macosx_10_12_x86_64.whl + +[rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl +sha256=a7b28c5b066bca9a4eb4e2f2663012debe680f097979d880657f00e1c30875a0 +upstream_url=https://files.pythonhosted.org/packages/7e/f6/89c0302279feb2c7dcce7064326cb588299470f0c172979ef26888b6aa53/rpds_py-0.18.1-cp39-cp39-macosx_11_0_arm64.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl +sha256=673fdbbf668dd958eff750e500495ef3f611e2ecc209464f661bc82e9838991e +upstream_url=https://files.pythonhosted.org/packages/89/4b/633f22dcfc96b33e0bba801d3022359d0cec6f02f0001790cea84df636ad/rpds_py-0.18.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl +sha256=d960de62227635d2e61068f42a6cb6aae91a7fe00fca0e3aeed17667c8a34611 +upstream_url=https://files.pythonhosted.org/packages/6a/cb/86f59a827bdd446759cffeb10242814da0652b28e57362c41dfabab71ca0/rpds_py-0.18.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl +sha256=352a88dc7892f1da66b6027af06a2e7e5d53fe05924cc2cfc56495b586a10b72 +upstream_url=https://files.pythonhosted.org/packages/8c/14/fa947a9cf31b7d08b26feea4fcc3d57de96924fd1a6c87b46b430fbb11b7/rpds_py-0.18.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl +sha256=4e0ee01ad8260184db21468a6e1c37afa0529acc12c3a697ee498d3c2c4dcaf3 +upstream_url=https://files.pythonhosted.org/packages/c8/3b/cc231994f64baaff05ac2a6f847f9760d362263765b904c98782e377a317/rpds_py-0.18.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl +sha256=e4c39ad2f512b4041343ea3c7894339e4ca7839ac38ca83d68a832fc8b3748ab +upstream_url=https://files.pythonhosted.org/packages/97/b1/12238bd8cdf3cef71e85188af133399bfde1bddf319007361cc869d6f6a7/rpds_py-0.18.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl + +[rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl] +tarball=rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl +sha256=aaa71ee43a703c321906813bb252f69524f02aa05bf4eec85f0c41d5d62d0f4c +upstream_url=https://files.pythonhosted.org/packages/d9/d6/cb9edd4910b6f253b4f64b0d8871ddcdc9ff02241307f33cccdb61f903cd/rpds_py-0.18.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl + +[rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl +sha256=6cd8098517c64a85e790657e7b1e509b9fe07487fd358e19431cb120f7d96338 +upstream_url=https://files.pythonhosted.org/packages/24/57/599c6a77ceec52607fc2db134c583cad9b89268573ffd1fbcb15b9576f5f/rpds_py-0.18.1-cp39-cp39-musllinux_1_2_aarch64.whl + +[rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl] +tarball=rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl +sha256=4adec039b8e2928983f885c53b7cc4cda8965b62b6596501a0308d2703f8af1b +upstream_url=https://files.pythonhosted.org/packages/74/42/d05e5e023aa3b410408881960664e7e3a526d2e6e9c8620a3fa926574451/rpds_py-0.18.1-cp39-cp39-musllinux_1_2_i686.whl + +[rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl] +tarball=rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl +sha256=32b7daaa3e9389db3695964ce8e566e3413b0c43e3394c05e4b243a4cd7bef26 +upstream_url=https://files.pythonhosted.org/packages/96/57/bb354853ee6d867c900d4149b277ad027df7ad530084caa7e3b29c2ee6d3/rpds_py-0.18.1-cp39-cp39-musllinux_1_2_x86_64.whl + +[rpds_py-0.18.1-cp39-none-win32.whl] +tarball=rpds_py-0.18.1-cp39-none-win32.whl +sha256=2625f03b105328729f9450c8badda34d5243231eef6535f80064d57035738360 +upstream_url=https://files.pythonhosted.org/packages/81/28/1f37f2c547aadc74100569d271644a7becd1ab75b067897800049cad4364/rpds_py-0.18.1-cp39-none-win32.whl + +[rpds_py-0.18.1-cp39-none-win_amd64.whl] +tarball=rpds_py-0.18.1-cp39-none-win_amd64.whl +sha256=bf18932d0003c8c4d51a39f244231986ab23ee057d235a12b2684ea26a353590 +upstream_url=https://files.pythonhosted.org/packages/e6/49/13a9adc8f2e7dae30ab76f3d6a750807a297fc4c897178a19e33f9eac10e/rpds_py-0.18.1-cp39-none-win_amd64.whl + diff --git a/build/pkgs/pyrsistent/dependencies b/build/pkgs/rpds_py/dependencies similarity index 66% rename from build/pkgs/pyrsistent/dependencies rename to build/pkgs/rpds_py/dependencies index 47296a7bace..644ad35f773 100644 --- a/build/pkgs/pyrsistent/dependencies +++ b/build/pkgs/rpds_py/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | pip $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/rpds_py/package-version.txt b/build/pkgs/rpds_py/package-version.txt new file mode 100644 index 00000000000..249afd517d9 --- /dev/null +++ b/build/pkgs/rpds_py/package-version.txt @@ -0,0 +1 @@ +0.18.1 diff --git a/build/pkgs/rpds_py/spkg-configure.m4 b/build/pkgs/rpds_py/spkg-configure.m4 new file mode 100644 index 00000000000..4eab56fa755 --- /dev/null +++ b/build/pkgs/rpds_py/spkg-configure.m4 @@ -0,0 +1 @@ +SAGE_SPKG_CONFIGURE([rpds_py], [SAGE_PYTHON_PACKAGE_CHECK([rpds_py])]) diff --git a/build/pkgs/pyrsistent/type b/build/pkgs/rpds_py/type similarity index 100% rename from build/pkgs/pyrsistent/type rename to build/pkgs/rpds_py/type diff --git a/build/pkgs/rpds_py/version_requirements.txt b/build/pkgs/rpds_py/version_requirements.txt new file mode 100644 index 00000000000..340ec175016 --- /dev/null +++ b/build/pkgs/rpds_py/version_requirements.txt @@ -0,0 +1 @@ +rpds-py diff --git a/build/sage_bootstrap/app.py b/build/sage_bootstrap/app.py index 2b8b44959b1..9a6fecedc5e 100644 --- a/build/sage_bootstrap/app.py +++ b/build/sage_bootstrap/app.py @@ -203,14 +203,16 @@ def name(self, tarball_filename): def tarball(self, package_name): """ - Find the tarball filename given a package name + Find the tarball filenames given a package name $ sage --package tarball pari pari-2.8-1564-gdeac36e.tar.gz """ log.debug('Looking up tarball name for %s', package_name) package = Package(package_name) - print(package.tarball.filename) + tarballs = package.tarballs() + for key in tarballs: + print(tarballs[key].filename) def apropos(self, incorrect_name): """ @@ -252,7 +254,7 @@ def update(self, package_name, new_version, url=None, commit=False): """ log.debug('Updating %s to %s', package_name, new_version) update = PackageUpdater(package_name, new_version) - if url is not None or update.package.tarball_upstream_url: + if url is not None or update.package.tarball_upstream_url_pattern: log.debug('Downloading %s', url) update.download_upstream(url) update.fix_checksum() @@ -302,7 +304,7 @@ def update_latest_cls(self, package_name_or_class, commit=False): except PyPiError as e: log.warn('updating %s failed: %s', package_name, e) - def download(self, package_name, allow_upstream=False): + def download(self, package_name, allow_upstream=False, tags=()): """ Download a package @@ -312,8 +314,19 @@ def download(self, package_name, allow_upstream=False): """ log.debug('Downloading %s', package_name) package = Package(package_name) - package.tarball.download(allow_upstream=allow_upstream) - print(package.tarball.upstream_fqn) + tarballs = package.tarballs() + sorted_tarballs = [] + for tag in tags: + for key in tarballs: + if key is not None and tag in key: + sorted_tarballs.append(tarballs[key]) + del tarballs[key] + break + if not sorted_tarballs: + sorted_tarballs = tarballs.values() + for tarball in sorted_tarballs: + tarball.download(allow_upstream=allow_upstream) + print(tarball.upstream_fqn) def download_cls(self, *package_classes, **kwds): """ @@ -321,12 +334,13 @@ def download_cls(self, *package_classes, **kwds): """ allow_upstream = kwds.pop('allow_upstream', False) on_error = kwds.pop('on_error', 'stop') + tags = kwds.pop('tags', []) has_files = list(kwds.pop('has_files', [])) pc = PackageClass(*package_classes, has_files=has_files + ['checksums.ini'], **kwds) def download_with_args(package): try: - self.download(package, allow_upstream=allow_upstream) + self.download(package, allow_upstream=allow_upstream, tags=tags) except FileNotMirroredError: if on_error == 'stop': raise @@ -344,16 +358,18 @@ def upload(self, package_name): Uploading /home/vbraun/Code/sage.git/upstream/pari-2.8-2044-g89b0f1e.tar.gz """ package = Package(package_name) - if not os.path.exists(package.tarball.upstream_fqn): - log.debug('Skipping %s because there is no local tarball', package_name) - return - if not package.tarball.is_distributable(): - log.info('Skipping %s because the tarball is marked as not distributable', - package_name) - return - log.info('Uploading %s', package.tarball.upstream_fqn) - fs = FileServer() - fs.upload(package) + tarballs = package.tarballs() + for key in tarballs: + tarball = tarballs[key] + if not os.path.exists(tarball.upstream_fqn): + log.debug('Skipping %s because it does not exist locally', tarball) + continue + if not tarball.is_distributable(): + log.info('Skipping %s because it is marked as not distributable', tarball) + continue + log.info('Uploading %s', tarball.upstream_fqn) + fs = FileServer() + fs.upload(tarball) def upload_cls(self, package_name_or_class): pc = PackageClass(package_name_or_class) @@ -381,7 +397,7 @@ def fix_checksum(self, package_name): log.debug('Correcting the checksum of %s', package_name) update = ChecksumUpdater(package_name) pkg = update.package - if not pkg.tarball_filename: + if not pkg.tarball_pattern: log.info('Ignoring {0} because it is not a normal package'.format(package_name)) return if not os.path.exists(pkg.tarball.upstream_fqn): @@ -417,13 +433,13 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre if pypi: if source is None: try: - if PyPiVersion(package_name, source='wheel').tarball.endswith('-none-any.whl'): + if PyPiVersion(package_name, source='wheel', version=version).tarball.endswith('-none-any.whl'): source = 'wheel' else: source = 'normal' except PyPiError: source = 'normal' - pypi_version = PyPiVersion(package_name, source=source) + pypi_version = PyPiVersion(package_name, source=source, version=version) if source == 'normal': if not tarball: # Guess the general format of the tarball name. @@ -434,14 +450,10 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre # because it follows a simple pattern. upstream_url = 'https://pypi.io/packages/source/{0:1.1}/{0}/{1}'.format(package_name, tarball) elif source == 'wheel': - if not tarball: - tarball = pypi_version.tarball.replace(pypi_version.version, 'VERSION') - if not tarball.endswith('-none-any.whl'): - raise ValueError('Only platform-independent wheels can be used for wheel packages, got {0}'.format(tarball)) if not version: version = pypi_version.version if dependencies is None: - log.info('Requires-Python: {0}'.format(pypi_version.requires_python)) + log.info('Requires-Python: {0}'.format(pypi_version.requires_python or 'none')) requires_dist = pypi_version.requires_dist if requires_dist: dependencies = [] @@ -459,7 +471,6 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre self.create(dep, pkg_type=pkg_type) dep = Package(dep).name dependencies.append(dep) - upstream_url = 'https://pypi.io/packages/{2}/{0:1.1}/{0}/{1}'.format(package_name, tarball, pypi_version.python_version) if not description: description = pypi_version.summary if not license: @@ -470,11 +481,9 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre tarball = upstream_url.rpartition('/')[2] if tarball and source is None: source = 'normal' - if tarball and not pkg_type: - # If we set a tarball, also make sure to create a "type" file, - # so that subsequent operations (downloading of tarballs) work. + if not pkg_type: pkg_type = 'optional' - log.debug('Creating %s: %s, %s, %s', package_name, version, tarball, pkg_type) + log.info('Creating build/pkgs/%s', package_name) creator = PackageCreator(package_name) if version: creator.set_version(version) @@ -485,6 +494,8 @@ def create(self, package_name, version=None, tarball=None, pkg_type=None, upstre if pypi or source == 'pip': creator.set_python_data_and_scripts(pypi_package_name=pypi_version.name, source=source, dependencies=dependencies) + if source == 'wheel': + creator.set_pypi_urls(pypi_version) if tarball: creator.set_tarball(tarball, upstream_url) if upstream_url and version: @@ -570,6 +581,6 @@ def metrics_cls(self, *package_classes): if not key.startswith('distros_'): metrics['line_count_file_' + key] += sum(package.line_count_file(filename) for filename in filenames) - metrics['has_tarball_upstream_url'] += int(bool(package.tarball_upstream_url)) + metrics['has_tarball_upstream_url'] += int(bool(package.tarball_upstream_url_pattern)) for key, value in sorted(metrics.items()): print('{0}={1}'.format(key, value)) diff --git a/build/sage_bootstrap/cmdline.py b/build/sage_bootstrap/cmdline.py index cbd4a544bb6..4a801fbab34 100644 --- a/build/sage_bootstrap/cmdline.py +++ b/build/sage_bootstrap/cmdline.py @@ -414,6 +414,9 @@ def make_parser(): parser_download.add_argument( '--no-check-certificate', action='store_true', help='do not check SSL certificates for https connections') + parser_download.add_argument( + '--tags', nargs='*', default=[], + help='ordered list of platform compatibility tags to try (for platform-dependent wheels only)') parser_upload = subparsers.add_parser( 'upload', epilog=epilog_upload, @@ -539,7 +542,8 @@ def run(): has_files=args.has_files, no_files=args.no_files, exclude=args.exclude, allow_upstream=args.allow_upstream, - on_error=args.on_error) + on_error=args.on_error, + tags=args.tags) elif args.subcommand == 'create': app.create(args.package_name, args.version, args.tarball, args.type, args.url, args.description, args.license, args.upstream_contact, diff --git a/build/sage_bootstrap/creator.py b/build/sage_bootstrap/creator.py index e16002f12f9..2e889efc9d3 100644 --- a/build/sage_bootstrap/creator.py +++ b/build/sage_bootstrap/creator.py @@ -59,6 +59,19 @@ def set_tarball(self, tarball, upstream_url): f.write('upstream_url={0}'.format(upstream_url)) f.write('\n') + def set_pypi_urls(self, pypi_version): + """ + Write the ``checksums.ini`` file + """ + with open(os.path.join(self.path, 'checksums.ini'), 'w+') as f: + for url in pypi_version.urls: + if 'cp' in url['python_version'] or 'py3' in url['python_version']: + f.write('[{0}]\n'.format(url['filename'])) + f.write('tarball={0}\n'.format(url['filename'])) + f.write('sha256={0}\n'.format(url['digests']['sha256'])) + f.write('upstream_url={0}\n'.format(url['url'])) + f.write('\n') + def set_description(self, description, license, upstream_contact): """ Write the ``SPKG.rst`` file diff --git a/build/sage_bootstrap/fileserver.py b/build/sage_bootstrap/fileserver.py index e884242c0e1..d3efd8a06ac 100644 --- a/build/sage_bootstrap/fileserver.py +++ b/build/sage_bootstrap/fileserver.py @@ -31,20 +31,20 @@ def upstream_directory(self, package): '/', 'data', 'files', 'spkg', 'upstream', package.name, ) - def upload(self, package): + def upload(self, tarball): """ - Upload the current tarball of package + Upload the current tarball of a package """ - if not package.tarball.is_distributable(): - raise ValueError('Tarball of {} is marked as not distributable'.format(package)) + if not tarball.is_distributable(): + raise ValueError('Tarball {} is marked as not distributable'.format(tarball)) subprocess.check_call([ 'ssh', 'sagemath@fileserver.sagemath.org', - 'mkdir -p {0} && touch {0}/index.html'.format(self.upstream_directory(package)) + 'mkdir -p {0} && touch {0}/index.html'.format(self.upstream_directory(tarball.package)) ]) subprocess.check_call([ 'rsync', '-av', '--checksum', '-e', 'ssh -l sagemath', - package.tarball.upstream_fqn, - 'fileserver.sagemath.org:{0}'.format(self.upstream_directory(package)) + tarball.upstream_fqn, + 'fileserver.sagemath.org:{0}'.format(self.upstream_directory(tarball.package)) ]) def publish(self): diff --git a/build/sage_bootstrap/package.py b/build/sage_bootstrap/package.py index c063af0c816..67ec65ebec4 100644 --- a/build/sage_bootstrap/package.py +++ b/build/sage_bootstrap/package.py @@ -80,7 +80,7 @@ def __init__(self, package_name): raise ValueError('package names use underscores, not dashes, got {0}'.format(package_name)) self.__name = package_name - self.__tarball = None + self.__tarballs = None self._init_checksum() self._init_version() self._init_type() @@ -107,28 +107,6 @@ def name(self): """ return self.__name - @property - def sha1(self): - """ - Return the SHA1 checksum - - OUTPUT: - - String. - """ - return self.__sha1 - - @property - def sha256(self): - """ - Return the SHA256 checksum - - OUTPUT: - - String. - """ - return self.__sha256 - @property def tarball(self): """ @@ -141,10 +119,26 @@ def tarball(self): Instance of :class:`sage_bootstrap.tarball.Tarball` """ - if self.__tarball is None: + return self.tarballs()[None] + + def tarballs(self): + """ + Return a dictionary of the tarballs + """ + if self.__tarballs is None: from sage_bootstrap.tarball import Tarball - self.__tarball = Tarball(self.tarball_filename, package=self) - return self.__tarball + self.__tarballs = dict() + for key in self.__checksums: + c = self.__checksums[key] + tarball_filename = self._substitute_variables(c['tarball']) + if 'upstream_url' in c: + upstream_url = self._substitute_variables(c['upstream_url']) + else: + upstream_url = None + self.__tarballs[key] = Tarball(tarball_filename, package=self, + upstream_url=upstream_url, + sha1=c.get('sha1'), sha256=c.get('sha256')) + return self.__tarballs def _substitute_variables_once(self, pattern): """ @@ -195,7 +189,10 @@ def tarball_pattern(self): String. The full-qualified tarball filename, but with ``VERSION`` instead of the actual tarball filename. """ - return self.__tarball_pattern + try: + return self.__checksums[None]['tarball'] + except KeyError: + return None @property def tarball_filename(self): @@ -225,7 +222,10 @@ def tarball_upstream_url_pattern(self): String. The tarball upstream URL, but with the placeholder ``VERSION``. """ - return self.__tarball_upstream_url_pattern + try: + return self.__checksums[None]['upstream_url'] + except KeyError: + return None @property def tarball_upstream_url(self): @@ -261,6 +261,16 @@ def tarball_package(self): else: return type(self)(n) + def is_package_of_tarball(self, tarball_filename): + """ + Whether ``tarball_filename`` is a tarball of ``self``. + """ + tarballs = self.tarballs() + for key in tarballs: + if tarballs[key].filename == tarball_filename: + return True + return False + @property def version(self): """ @@ -349,10 +359,13 @@ def source(self): """ if self.__requirements is not None: return 'pip' - if self.tarball_filename: - if self.tarball_filename.endswith('.whl'): + + tarballs = self.tarballs() + for key in tarballs: + if tarballs[key].filename.endswith('.whl'): return 'wheel' return 'normal' + if self.has_file('spkg-install') or self.has_file('spkg-install.in'): return 'script' return 'none' @@ -512,22 +525,28 @@ def _init_checksum(self): Load the checksums from the appropriate ``checksums.ini`` file """ checksums_ini = os.path.join(self.path, 'checksums.ini') + section = re.compile(r'\[(?P
[-a-zA-Z0-9_.]*)\]') assignment = re.compile('(?P[a-zA-Z0-9_]*)=(?P.*)') result = dict() + key = None try: with open(checksums_ini, 'rt') as f: for line in f.readlines(): + match = section.match(line) + if match is not None: + key = match.group('section') + result[key] = dict() + continue match = assignment.match(line) if match is None: continue var, value = match.groups() - result[var] = value + if key not in result: + result[key] = dict() + result[key][var] = value except IOError: pass - self.__sha1 = result.get('sha1', None) - self.__sha256 = result.get('sha256', None) - self.__tarball_pattern = result.get('tarball', None) - self.__tarball_upstream_url_pattern = result.get('upstream_url', None) + self.__checksums = result # Name of the directory containing the checksums.ini file self.__tarball_package_name = os.path.realpath(checksums_ini).split(os.sep)[-2] diff --git a/build/sage_bootstrap/pypi.py b/build/sage_bootstrap/pypi.py index 215feb69343..69ebf119628 100644 --- a/build/sage_bootstrap/pypi.py +++ b/build/sage_bootstrap/pypi.py @@ -35,8 +35,12 @@ class PyPiError(Exception): class PyPiVersion(object): - def __init__(self, package_name, source='normal'): + def __init__(self, package_name, source='normal', version=None): self.name = package_name + if version is None: + self.suffix = '' + else: + self.suffix = '/' + version self.json = self._get_json() # Replace provided name with the canonical name self.name = self.json['info']['name'] @@ -55,7 +59,7 @@ def _get_json(self): @property def json_url(self): - return 'https://pypi.python.org/pypi/{0}/json'.format(self.name) + return 'https://pypi.python.org/pypi/{0}{1}/json'.format(self.name, self.suffix) @property def version(self): @@ -70,6 +74,7 @@ def url(self): Return the source url """ for download in self.json['urls']: + log.info('{0}'.format(download)) if self.python_version in download['python_version']: self.python_version = download['python_version'] return download['url'] @@ -81,11 +86,30 @@ def tarball(self): Return the source tarball name """ for download in self.json['urls']: + log.info('{0}'.format(download)) if self.python_version in download['python_version']: self.python_version = download['python_version'] return download['filename'] raise PyPiError('No %s url for %s found', self.python_version, self.name) + @property + def urls(self): + """ + Return the list of URLs. + + Each URL is a dictionary:: + + {'digests': {'sha256': 'ad277f74b1c164f7248afa968700e410651eb858d7c160d109fb451dc45a2f09', ...}, + 'filename': 'rpds_py-0.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl', + 'packagetype': 'bdist_wheel', + 'python_version': 'cp310', + 'requires_python': '>=3.8', + 'url': 'https://files.pythonhosted.org/packages/79/c6/432ec657f5f44a878e8653c73abfc51708afd0899c3d89f2967e11f81f14/rpds_py-0.10.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl', + 'yanked': False, + ...} + """ + return self.json['urls'] + @property def package_url(self): """ @@ -125,7 +149,10 @@ def update(self, package=None): if package is None: package = Package(self.name) if package.version == self.version: - log.info('%s is already at the latest version', self.name) + if self.suffix: + log.info('%s is already at this version', self.name) + else: + log.info('%s is already at the latest version', self.name) return log.info('Updating %s: %s -> %s', package.name, package.version, self.version) update = PackageUpdater(package.name, self.version) diff --git a/build/sage_bootstrap/tarball.py b/build/sage_bootstrap/tarball.py index 54af50dd8f8..798b3371820 100644 --- a/build/sage_bootstrap/tarball.py +++ b/build/sage_bootstrap/tarball.py @@ -40,7 +40,8 @@ class FileNotMirroredError(Exception): class Tarball(object): - def __init__(self, tarball_name, package=None): + def __init__(self, tarball_name, package=None, + upstream_url=None, sha1=None, sha256=None): """ A (third-party downloadable) tarball @@ -57,7 +58,7 @@ def __init__(self, tarball_name, package=None): if package is None: self.__package = None for pkg in Package.all(): - if pkg.tarball_filename == tarball_name: + if pkg.is_package_of_tarball(tarball_name): self.__package = pkg.tarball_package if self.package is None: error = 'tarball {0} is not referenced by any Sage package'.format(tarball_name) @@ -65,10 +66,9 @@ def __init__(self, tarball_name, package=None): raise ValueError(error) else: self.__package = package - if package.tarball_filename != tarball_name: - error = 'tarball {0} is not referenced by the {1} package'.format(tarball_name, package.name) - log.error(error) - raise ValueError(error) + self.__upstream_url = upstream_url + self.__sha1 = sha1 + self.__sha256 = sha256 def __repr__(self): return 'Tarball {0}'.format(self.filename) @@ -96,6 +96,28 @@ def package(self): """ return self.__package + @property + def sha1(self): + """ + Return the SHA1 checksum + + OUTPUT: + + String. + """ + return self.__sha1 + + @property + def sha256(self): + """ + Return the SHA256 checksum + + OUTPUT: + + String. + """ + return self.__sha256 + @property def upstream_fqn(self): """ @@ -103,6 +125,17 @@ def upstream_fqn(self): """ return os.path.join(SAGE_DISTFILES, self.filename) + @property + def upstream_url(self): + """ + The upstream URL or ``None`` if none is recorded + + OUTPUT: + + String. The URL. + """ + return self.__upstream_url + def __eq__(self, other): return self.filename == other.filename @@ -127,17 +160,22 @@ def checksum_verifies(self, force_sha256=False): """ Test whether the checksum of the downloaded file is correct. """ - if self.package.sha256: + if self.sha256: sha256 = self._compute_sha256() - if sha256 != self.package.sha256: + if sha256 != self.sha256: return False + if self.sha1 is None: + return True elif force_sha256: log.warning('sha256 not available for {0}'.format(self.package.name)) return False else: log.warning('sha256 not available for {0}, using sha1'.format(self.package.name)) + if self.sha1 is None: + log.warning('sha1 not available for {0}'.format(self.package.name)) + return True sha1 = self._compute_sha1() - return sha1 == self.package.sha1 + return sha1 == self.sha1 def is_distributable(self): return 'do-not-distribute' not in self.filename @@ -178,7 +216,7 @@ def download(self, allow_upstream=False): except IOError: log.debug('File not on mirror') if not successful_download: - url = self.package.tarball_upstream_url + url = self.upstream_url if allow_upstream and url: log.info('Attempting to download from {}'.format(url)) try: diff --git a/configure.ac b/configure.ac index 58adf54f78f..47d881b6f23 100644 --- a/configure.ac +++ b/configure.ac @@ -450,7 +450,7 @@ AC_ARG_ENABLE([cvxopt], AC_ARG_ENABLE([notebook], AS_HELP_STRING([--disable-notebook], [disable build of the Jupyter notebook and related packages]), [ - for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi argon2_cffi_bindings webencodings tinycss2 ipympl soupsieve fastjsonschema anyio arrow async_lru fqdn isoduration json5 jsonpointer jsonschema_specifications jupyter_events jupyter_lsp jupyter_server jupyter_server_terminals jupyterlab jupyterlab_server jupyterlab_pygments jupyterlab_mathjax2 jupyter_sphinx notebook_shim overrides python_json_logger pyyaml referencing rfc3339_validator rfc3986_validator sniffio types_python_dateutil uri_template webcolors websocket_client; do + for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi argon2_cffi_bindings webencodings tinycss2 ipympl soupsieve fastjsonschema anyio arrow async_lru fqdn isoduration json5 jsonpointer jsonschema_specifications jupyter_events jupyter_lsp jupyter_server jupyter_server_terminals jupyterlab jupyterlab_server jupyterlab_pygments jupyterlab_mathjax2 jupyter_sphinx notebook_shim overrides python_json_logger pyyaml referencing rfc3339_validator rfc3986_validator rpds_py sniffio types_python_dateutil uri_template webcolors websocket_client; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index d59e5dc07e9..b605869752d 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -86,11 +86,8 @@ the following source types: #. A ``wheel`` package: - - comes from the wheel file named in the required file ``checksums.ini`` - and hosted on the Sage mirrors; - - - per policy, only platform-independent wheels are allowed, i.e., - ``*-none-any.whl`` files; + - comes from the wheel file(s) named in the required file ``checksums.ini`` + and hosted on the Sage mirrors and GitHub Release Assets; - its version number is defined by the required file ``package-version.txt``; @@ -102,7 +99,19 @@ the following source types: - Sage records the version number of the package installed using a file in ``$SAGE_LOCAL/var/lib/sage/installed/`` and will rerun the installation - if ``package-version.txt`` changes. + if ``package-version.txt`` changes; + + - platform-independent ``wheel`` packages are preferred to ``normal`` packages + because the installation is faster and there are no build requirements; + + - platform-dependent ``wheel`` packages should only be used when installation + from source (as a ``normal`` package) would have unusual build requirements + (example: the package :ref:`rpds_py ` would need Rust); + + - if a platform-dependent ``wheel`` package is a standard package, there + must be a ``configure`` option that disables it + (example: use of the package :ref:`rpds_py ` can be disabled + by using ``./configure --disable-notebook``). #. A ``pip`` package: @@ -589,8 +598,9 @@ would simply contain: Python-based packages --------------------- -Python-based packages should declare ``$(PYTHON)`` as a dependency, -and most Python-based packages will also have ``$(PYTHON_TOOLCHAIN)`` as +Python-based packages should declare ``$(PYTHON)`` as an order-only dependency. + +Most ``normal`` Python-based packages will also have ``$(PYTHON_TOOLCHAIN)`` as an order-only dependency, which will ensure that fundamental packages such as ``pip`` and ``setuptools`` are available at the time of building the package. @@ -1087,6 +1097,13 @@ package requires patching), you can use:: --source normal \ --type optional +To create a platform-dependent ``wheel`` package instead of a ``normal`` package, +use:: + + [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \ + --source wheel \ + --type optional + To create a ``pip`` package rather than a ``normal`` or ``wheel`` package, you can use:: [alice@localhost sage]$ ./sage --package create pkg:pypi/scikit-spatial \