diff --git a/.gitignore b/.gitignore index 58459341..5083f1a2 100644 --- a/.gitignore +++ b/.gitignore @@ -361,4 +361,5 @@ MigrationBackup/ .Rhistory ML-For-Beginners.Rproj .venv -.obsidian \ No newline at end of file +.obsidian +.venv/Lib/site-packages/ \ No newline at end of file diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/INSTALLER b/.venv/Lib/site-packages/pip-23.0.1.dist-info/INSTALLER deleted file mode 100644 index a1b589e3..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/INSTALLER +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/LICENSE.txt b/.venv/Lib/site-packages/pip-23.0.1.dist-info/LICENSE.txt deleted file mode 100644 index 8e7b65ea..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/LICENSE.txt +++ /dev/null @@ -1,20 +0,0 @@ -Copyright (c) 2008-present The pip developers (see AUTHORS.txt file) - -Permission is hereby granted, free of charge, to any person obtaining -a copy of this software and associated documentation files (the -"Software"), to deal in the Software without restriction, including -without limitation the rights to use, copy, modify, merge, publish, -distribute, sublicense, and/or sell copies of the Software, and to -permit persons to whom the Software is furnished to do so, subject to -the following conditions: - -The above copyright notice and this permission notice shall be -included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/METADATA b/.venv/Lib/site-packages/pip-23.0.1.dist-info/METADATA deleted file mode 100644 index 984f9ad3..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/METADATA +++ /dev/null @@ -1,88 +0,0 @@ -Metadata-Version: 2.1 -Name: pip -Version: 23.0.1 -Summary: The PyPA recommended tool for installing Python packages. -Home-page: https://pip.pypa.io/ -Author: The pip developers -Author-email: distutils-sig@python.org -License: MIT -Project-URL: Documentation, https://pip.pypa.io -Project-URL: Source, https://github.com/pypa/pip -Project-URL: Changelog, https://pip.pypa.io/en/stable/news/ -Classifier: Development Status :: 5 - Production/Stable -Classifier: Intended Audience :: Developers -Classifier: License :: OSI Approved :: MIT License -Classifier: Topic :: Software Development :: Build Tools -Classifier: Programming Language :: Python -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3 :: Only -Classifier: Programming Language :: Python :: 3.7 -Classifier: Programming Language :: Python :: 3.8 -Classifier: Programming Language :: Python :: 3.9 -Classifier: Programming Language :: Python :: 3.10 -Classifier: Programming Language :: Python :: 3.11 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Requires-Python: >=3.7 -License-File: LICENSE.txt - -pip - The Python Package Installer -================================== - -.. image:: https://img.shields.io/pypi/v/pip.svg - :target: https://pypi.org/project/pip/ - -.. image:: https://readthedocs.org/projects/pip/badge/?version=latest - :target: https://pip.pypa.io/en/latest - -pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes. - -Please take a look at our documentation for how to install and use pip: - -* `Installation`_ -* `Usage`_ - -We release updates regularly, with a new version every 3 months. Find more details in our documentation: - -* `Release notes`_ -* `Release process`_ - -In pip 20.3, we've `made a big improvement to the heart of pip`_; `learn more`_. We want your input, so `sign up for our user experience research studies`_ to help us do it right. - -**Note**: pip 21.0, in January 2021, removed Python 2 support, per pip's `Python 2 support policy`_. Please migrate to Python 3. - -If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms: - -* `Issue tracking`_ -* `Discourse channel`_ -* `User IRC`_ - -If you want to get involved head over to GitHub to get the source code, look at our development documentation and feel free to jump on the developer mailing lists and chat rooms: - -* `GitHub page`_ -* `Development documentation`_ -* `Development IRC`_ - -Code of Conduct ---------------- - -Everyone interacting in the pip project's codebases, issue trackers, chat -rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_. - -.. _package installer: https://packaging.python.org/guides/tool-recommendations/ -.. _Python Package Index: https://pypi.org -.. _Installation: https://pip.pypa.io/en/stable/installation/ -.. _Usage: https://pip.pypa.io/en/stable/ -.. _Release notes: https://pip.pypa.io/en/stable/news.html -.. _Release process: https://pip.pypa.io/en/latest/development/release-process/ -.. _GitHub page: https://github.com/pypa/pip -.. _Development documentation: https://pip.pypa.io/en/latest/development -.. _made a big improvement to the heart of pip: https://pyfound.blogspot.com/2020/11/pip-20-3-new-resolver.html -.. _learn more: https://pip.pypa.io/en/latest/user_guide/#changes-to-the-pip-dependency-resolver-in-20-3-2020 -.. _sign up for our user experience research studies: https://pyfound.blogspot.com/2020/03/new-pip-resolver-to-roll-out-this-year.html -.. _Python 2 support policy: https://pip.pypa.io/en/latest/development/release-process/#python-2-support -.. _Issue tracking: https://github.com/pypa/pip/issues -.. _Discourse channel: https://discuss.python.org/c/packaging -.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa -.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev -.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/RECORD b/.venv/Lib/site-packages/pip-23.0.1.dist-info/RECORD deleted file mode 100644 index 44a251f0..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/RECORD +++ /dev/null @@ -1,1002 +0,0 @@ -../../Scripts/pip.exe,sha256=OdqXzGDA8wu7yB7HuDPy-bF3wWjHklhmPrM_KnNZSZA,108435 -../../Scripts/pip3.10.exe,sha256=OdqXzGDA8wu7yB7HuDPy-bF3wWjHklhmPrM_KnNZSZA,108435 -../../Scripts/pip3.exe,sha256=OdqXzGDA8wu7yB7HuDPy-bF3wWjHklhmPrM_KnNZSZA,108435 -pip-23.0.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip-23.0.1.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093 -pip-23.0.1.dist-info/METADATA,sha256=POh89utz-H1e0K-xDY9CL9gs-x0MjH-AWxbhJG3aaVE,4072 -pip-23.0.1.dist-info/RECORD,, -pip-23.0.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip-23.0.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92 -pip-23.0.1.dist-info/entry_points.txt,sha256=w694mjHYSfmSoUVVSaHoQ9UkOBBdtKKIJbyDRLdKju8,124 -pip-23.0.1.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4 -pip/__init__.py,sha256=5yroedzc2dKKbcynDrHX8vBoLxqU27KmFvvHmdqQN9w,357 -pip/__main__.py,sha256=mXwWDftNLMKfwVqKFWGE_uuBZvGSIiUELhLkeysIuZc,1198 -pip/__pip-runner__.py,sha256=EnrfKmKMzWAdqg_JicLCOP9Y95Ux7zHh4ObvqLtQcjo,1444 -pip/__pycache__/__init__.cpython-310.pyc,, -pip/__pycache__/__main__.cpython-310.pyc,, -pip/__pycache__/__pip-runner__.cpython-310.pyc,, -pip/_internal/__init__.py,sha256=nnFCuxrPMgALrIDxSoy-H6Zj4W4UY60D-uL1aJyq0pc,573 -pip/_internal/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/__pycache__/build_env.cpython-310.pyc,, -pip/_internal/__pycache__/cache.cpython-310.pyc,, -pip/_internal/__pycache__/configuration.cpython-310.pyc,, -pip/_internal/__pycache__/exceptions.cpython-310.pyc,, -pip/_internal/__pycache__/main.cpython-310.pyc,, -pip/_internal/__pycache__/pyproject.cpython-310.pyc,, -pip/_internal/__pycache__/self_outdated_check.cpython-310.pyc,, -pip/_internal/__pycache__/wheel_builder.cpython-310.pyc,, -pip/_internal/build_env.py,sha256=1ESpqw0iupS_K7phZK5zshVE5Czy9BtGLFU4W6Enva8,10243 -pip/_internal/cache.py,sha256=C3n78VnBga9rjPXZqht_4A4d-T25poC7K0qBM7FHDhU,10734 -pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132 -pip/_internal/cli/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/cli/__pycache__/autocompletion.cpython-310.pyc,, -pip/_internal/cli/__pycache__/base_command.cpython-310.pyc,, -pip/_internal/cli/__pycache__/cmdoptions.cpython-310.pyc,, -pip/_internal/cli/__pycache__/command_context.cpython-310.pyc,, -pip/_internal/cli/__pycache__/main.cpython-310.pyc,, -pip/_internal/cli/__pycache__/main_parser.cpython-310.pyc,, -pip/_internal/cli/__pycache__/parser.cpython-310.pyc,, -pip/_internal/cli/__pycache__/progress_bars.cpython-310.pyc,, -pip/_internal/cli/__pycache__/req_command.cpython-310.pyc,, -pip/_internal/cli/__pycache__/spinners.cpython-310.pyc,, -pip/_internal/cli/__pycache__/status_codes.cpython-310.pyc,, -pip/_internal/cli/autocompletion.py,sha256=wY2JPZY2Eji1vhR7bVo-yCBPJ9LCy6P80iOAhZD1Vi8,6676 -pip/_internal/cli/base_command.py,sha256=t1D5x40Hfn9HnPnMt-iSxvqL14nht2olBCacW74pc-k,7842 -pip/_internal/cli/cmdoptions.py,sha256=0OHXkgnppCtC4QyF28ZL8FBosVUXG5pWj2uzO1CgWhM,29497 -pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774 -pip/_internal/cli/main.py,sha256=ioJ8IVlb2K1qLOxR-tXkee9lURhYV89CDM71MKag7YY,2472 -pip/_internal/cli/main_parser.py,sha256=laDpsuBDl6kyfywp9eMMA9s84jfH2TJJn-vmL0GG90w,4338 -pip/_internal/cli/parser.py,sha256=tWP-K1uSxnJyXu3WE0kkH3niAYRBeuUaxeydhzOdhL4,10817 -pip/_internal/cli/progress_bars.py,sha256=So4mPoSjXkXiSHiTzzquH3VVyVD_njXlHJSExYPXAow,1968 -pip/_internal/cli/req_command.py,sha256=ypTutLv4j_efxC2f6C6aCQufxre-zaJdi5m_tWlLeBk,18172 -pip/_internal/cli/spinners.py,sha256=hIJ83GerdFgFCdobIA23Jggetegl_uC4Sp586nzFbPE,5118 -pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116 -pip/_internal/commands/__init__.py,sha256=5oRO9O3dM2vGuh0bFw4HOVletryrz5HHMmmPWwJrH9U,3882 -pip/_internal/commands/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/commands/__pycache__/cache.cpython-310.pyc,, -pip/_internal/commands/__pycache__/check.cpython-310.pyc,, -pip/_internal/commands/__pycache__/completion.cpython-310.pyc,, -pip/_internal/commands/__pycache__/configuration.cpython-310.pyc,, -pip/_internal/commands/__pycache__/debug.cpython-310.pyc,, -pip/_internal/commands/__pycache__/download.cpython-310.pyc,, -pip/_internal/commands/__pycache__/freeze.cpython-310.pyc,, -pip/_internal/commands/__pycache__/hash.cpython-310.pyc,, -pip/_internal/commands/__pycache__/help.cpython-310.pyc,, -pip/_internal/commands/__pycache__/index.cpython-310.pyc,, -pip/_internal/commands/__pycache__/inspect.cpython-310.pyc,, -pip/_internal/commands/__pycache__/install.cpython-310.pyc,, -pip/_internal/commands/__pycache__/list.cpython-310.pyc,, -pip/_internal/commands/__pycache__/search.cpython-310.pyc,, -pip/_internal/commands/__pycache__/show.cpython-310.pyc,, -pip/_internal/commands/__pycache__/uninstall.cpython-310.pyc,, -pip/_internal/commands/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/commands/cache.py,sha256=muaT0mbL-ZUpn6AaushVAipzTiMwE4nV2BLbJBwt_KQ,7582 -pip/_internal/commands/check.py,sha256=0gjXR7j36xJT5cs2heYU_dfOfpnFfzX8OoPNNoKhqdM,1685 -pip/_internal/commands/completion.py,sha256=H0TJvGrdsoleuIyQKzJbicLFppYx2OZA0BLNpQDeFjI,4129 -pip/_internal/commands/configuration.py,sha256=NB5uf8HIX8-li95YLoZO09nALIWlLCHDF5aifSKcBn8,9815 -pip/_internal/commands/debug.py,sha256=AesEID-4gPFDWTwPiPaGZuD4twdT-imaGuMR5ZfSn8s,6591 -pip/_internal/commands/download.py,sha256=LwKEyYMG2L67nQRyGo8hQdNEeMU2bmGWqJfcB8JDXas,5289 -pip/_internal/commands/freeze.py,sha256=gCjoD6foBZPBAAYx5t8zZLkJhsF_ZRtnb3dPuD7beO8,2951 -pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703 -pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132 -pip/_internal/commands/index.py,sha256=cGQVSA5dAs7caQ9sz4kllYvaI4ZpGiq1WhCgaImXNSA,4793 -pip/_internal/commands/inspect.py,sha256=2wSPt9yfr3r6g-s2S5L6PvRtaHNVyb4TuodMStJ39cw,3188 -pip/_internal/commands/install.py,sha256=3vT9tnHOV-p6dPMaKDqzivqmcq_kPAI-jVkxOEwN5C4,32389 -pip/_internal/commands/list.py,sha256=Fk1TSxB33NlRS4qlLQ0xwnytnF9-zkQJbKQYv2xc4Q4,12343 -pip/_internal/commands/search.py,sha256=sbBZiARRc050QquOKcCvOr2K3XLsoYebLKZGRi__iUI,5697 -pip/_internal/commands/show.py,sha256=t5jia4zcYJRJZy4U_Von7zMl03hJmmcofj6oDNTnj7Y,6419 -pip/_internal/commands/uninstall.py,sha256=OIqO9tqadY8kM4HwhFf1Q62fUIp7v8KDrTRo8yWMz7Y,3886 -pip/_internal/commands/wheel.py,sha256=mbFJd4dmUfrVFJkQbK8n2zHyRcD3AI91f7EUo9l3KYg,7396 -pip/_internal/configuration.py,sha256=uBKTus43pDIO6IzT2mLWQeROmHhtnoabhniKNjPYvD0,13529 -pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858 -pip/_internal/distributions/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/base.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/installed.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/sdist.cpython-310.pyc,, -pip/_internal/distributions/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/distributions/base.py,sha256=jrF1Vi7eGyqFqMHrieh1PIOrGU7KeCxhYPZnbvtmvGY,1221 -pip/_internal/distributions/installed.py,sha256=NI2OgsgH9iBq9l5vB-56vOg5YsybOy-AU4VE5CSCO2I,729 -pip/_internal/distributions/sdist.py,sha256=SQBdkatXSigKGG_SaD0U0p1Jwdfrg26UCNcHgkXZfdA,6494 -pip/_internal/distributions/wheel.py,sha256=m-J4XO-gvFerlYsFzzSXYDvrx8tLZlJFTCgDxctn8ig,1164 -pip/_internal/exceptions.py,sha256=cU4dz7x-1uFGrf2A1_Np9tKcy599bRJKRJkikgARxW4,24244 -pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30 -pip/_internal/index/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/index/__pycache__/collector.cpython-310.pyc,, -pip/_internal/index/__pycache__/package_finder.cpython-310.pyc,, -pip/_internal/index/__pycache__/sources.cpython-310.pyc,, -pip/_internal/index/collector.py,sha256=3OmYZ3tCoRPGOrELSgQWG-03M-bQHa2-VCA3R_nJAaU,16504 -pip/_internal/index/package_finder.py,sha256=rrUw4vj7QE_eMt022jw--wQiKznMaUgVBkJ1UCrVUxo,37873 -pip/_internal/index/sources.py,sha256=SVyPitv08-Qalh2_Bk5diAJ9GAA_d-a93koouQodAG0,6557 -pip/_internal/locations/__init__.py,sha256=Dh8LJWG8LRlDK4JIj9sfRF96TREzE--N_AIlx7Tqoe4,15365 -pip/_internal/locations/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/locations/__pycache__/_distutils.cpython-310.pyc,, -pip/_internal/locations/__pycache__/_sysconfig.cpython-310.pyc,, -pip/_internal/locations/__pycache__/base.cpython-310.pyc,, -pip/_internal/locations/_distutils.py,sha256=cmi6h63xYNXhQe7KEWEMaANjHFy5yQOPt_1_RCWyXMY,6100 -pip/_internal/locations/_sysconfig.py,sha256=jyNVtUfMIf0mtyY-Xp1m9yQ8iwECozSVVFmjkN9a2yw,7680 -pip/_internal/locations/base.py,sha256=RQiPi1d4FVM2Bxk04dQhXZ2PqkeljEL2fZZ9SYqIQ78,2556 -pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340 -pip/_internal/metadata/__init__.py,sha256=84j1dPJaIoz5Q2ZTPi0uB1iaDAHiUNfKtYSGQCfFKpo,4280 -pip/_internal/metadata/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/_json.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/base.cpython-310.pyc,, -pip/_internal/metadata/__pycache__/pkg_resources.cpython-310.pyc,, -pip/_internal/metadata/_json.py,sha256=BTkWfFDrWFwuSodImjtbAh8wCL3isecbnjTb5E6UUDI,2595 -pip/_internal/metadata/base.py,sha256=vIwIo1BtoqegehWMAXhNrpLGYBq245rcaCNkBMPnTU8,25277 -pip/_internal/metadata/importlib/__init__.py,sha256=9ZVO8BoE7NEZPmoHp5Ap_NJo0HgNIezXXg-TFTtt3Z4,107 -pip/_internal/metadata/importlib/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_compat.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_dists.cpython-310.pyc,, -pip/_internal/metadata/importlib/__pycache__/_envs.cpython-310.pyc,, -pip/_internal/metadata/importlib/_compat.py,sha256=GAe_prIfCE4iUylrnr_2dJRlkkBVRUbOidEoID7LPoE,1882 -pip/_internal/metadata/importlib/_dists.py,sha256=BUV8y6D0PePZrEN3vfJL-m1FDqZ6YPRgAiBeBinHhNg,8181 -pip/_internal/metadata/importlib/_envs.py,sha256=7BxanCh3T7arusys__O2ZHJdnmDhQXFmfU7x1-jB5xI,7457 -pip/_internal/metadata/pkg_resources.py,sha256=WjwiNdRsvxqxL4MA5Tb5a_q3Q3sUhdpbZF8wGLtPMI0,9773 -pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63 -pip/_internal/models/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/models/__pycache__/candidate.cpython-310.pyc,, -pip/_internal/models/__pycache__/direct_url.cpython-310.pyc,, -pip/_internal/models/__pycache__/format_control.cpython-310.pyc,, -pip/_internal/models/__pycache__/index.cpython-310.pyc,, -pip/_internal/models/__pycache__/installation_report.cpython-310.pyc,, -pip/_internal/models/__pycache__/link.cpython-310.pyc,, -pip/_internal/models/__pycache__/scheme.cpython-310.pyc,, -pip/_internal/models/__pycache__/search_scope.cpython-310.pyc,, -pip/_internal/models/__pycache__/selection_prefs.cpython-310.pyc,, -pip/_internal/models/__pycache__/target_python.cpython-310.pyc,, -pip/_internal/models/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/models/candidate.py,sha256=6pcABsaR7CfIHlbJbr2_kMkVJFL_yrYjTx6SVWUnCPQ,990 -pip/_internal/models/direct_url.py,sha256=f3WiKUwWPdBkT1xm7DlolS32ZAMYh3jbkkVH-BUON5A,6626 -pip/_internal/models/format_control.py,sha256=DJpMYjxeYKKQdwNcML2_F0vtAh-qnKTYe-CpTxQe-4g,2520 -pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030 -pip/_internal/models/installation_report.py,sha256=Hymmzv9-e3WhtewYm2NIOeMyAB6lXp736mpYqb9scZ0,2617 -pip/_internal/models/link.py,sha256=nfybVSpXgVHeU0MkC8hMkN2IgMup8Pdaudg74_sQEC8,18602 -pip/_internal/models/scheme.py,sha256=3EFQp_ICu_shH1-TBqhl0QAusKCPDFOlgHFeN4XowWs,738 -pip/_internal/models/search_scope.py,sha256=iGPQQ6a4Lau8oGQ_FWj8aRLik8A21o03SMO5KnSt-Cg,4644 -pip/_internal/models/selection_prefs.py,sha256=KZdi66gsR-_RUXUr9uejssk3rmTHrQVJWeNA2sV-VSY,1907 -pip/_internal/models/target_python.py,sha256=qKpZox7J8NAaPmDs5C_aniwfPDxzvpkrCKqfwndG87k,3858 -pip/_internal/models/wheel.py,sha256=YqazoIZyma_Q1ejFa1C7NHKQRRWlvWkdK96VRKmDBeI,3600 -pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50 -pip/_internal/network/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/network/__pycache__/auth.cpython-310.pyc,, -pip/_internal/network/__pycache__/cache.cpython-310.pyc,, -pip/_internal/network/__pycache__/download.cpython-310.pyc,, -pip/_internal/network/__pycache__/lazy_wheel.cpython-310.pyc,, -pip/_internal/network/__pycache__/session.cpython-310.pyc,, -pip/_internal/network/__pycache__/utils.cpython-310.pyc,, -pip/_internal/network/__pycache__/xmlrpc.cpython-310.pyc,, -pip/_internal/network/auth.py,sha256=MQVP0k4hUXk8ReYEfsGQ5t7_TS7cNHQuaHJuBlJLHxU,16507 -pip/_internal/network/cache.py,sha256=hgXftU-eau4MWxHSLquTMzepYq5BPC2zhCkhN3glBy8,2145 -pip/_internal/network/download.py,sha256=HvDDq9bVqaN3jcS3DyVJHP7uTqFzbShdkf7NFSoHfkw,6096 -pip/_internal/network/lazy_wheel.py,sha256=PbPyuleNhtEq6b2S7rufoGXZWMD15FAGL4XeiAQ8FxA,7638 -pip/_internal/network/session.py,sha256=BpDOJ7_Xw5VkgPYWsePzcaqOfcyRZcB2AW7W0HGBST0,18443 -pip/_internal/network/utils.py,sha256=6A5SrUJEEUHxbGtbscwU2NpCyz-3ztiDlGWHpRRhsJ8,4073 -pip/_internal/network/xmlrpc.py,sha256=AzQgG4GgS152_cqmGr_Oz2MIXsCal-xfsis7fA7nmU0,1791 -pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/operations/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/__pycache__/check.cpython-310.pyc,, -pip/_internal/operations/__pycache__/freeze.cpython-310.pyc,, -pip/_internal/operations/__pycache__/prepare.cpython-310.pyc,, -pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/operations/build/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/build_tracker.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata_editable.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel_editable.cpython-310.pyc,, -pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-310.pyc,, -pip/_internal/operations/build/build_tracker.py,sha256=vf81EwomN3xe9G8qRJED0VGqNikmRQRQoobNsxi5Xrs,4133 -pip/_internal/operations/build/metadata.py,sha256=9S0CUD8U3QqZeXp-Zyt8HxwU90lE4QrnYDgrqZDzBnc,1422 -pip/_internal/operations/build/metadata_editable.py,sha256=VLL7LvntKE8qxdhUdEJhcotFzUsOSI8NNS043xULKew,1474 -pip/_internal/operations/build/metadata_legacy.py,sha256=o-eU21As175hDC7dluM1fJJ_FqokTIShyWpjKaIpHZw,2198 -pip/_internal/operations/build/wheel.py,sha256=sT12FBLAxDC6wyrDorh8kvcZ1jG5qInCRWzzP-UkJiQ,1075 -pip/_internal/operations/build/wheel_editable.py,sha256=yOtoH6zpAkoKYEUtr8FhzrYnkNHQaQBjWQ2HYae1MQg,1417 -pip/_internal/operations/build/wheel_legacy.py,sha256=C9j6rukgQI1n_JeQLoZGuDdfUwzCXShyIdPTp6edbMQ,3064 -pip/_internal/operations/check.py,sha256=WsN7z0_QSgJjw0JsWWcqOHj4wWTaFv0J7mxgUByDCOg,5122 -pip/_internal/operations/freeze.py,sha256=mwTZ2uML8aQgo3k8MR79a7SZmmmvdAJqdyaknKbavmg,9784 -pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51 -pip/_internal/operations/install/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/editable_legacy.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/legacy.cpython-310.pyc,, -pip/_internal/operations/install/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/operations/install/editable_legacy.py,sha256=ee4kfJHNuzTdKItbfAsNOSEwq_vD7DRPGkBdK48yBhU,1354 -pip/_internal/operations/install/legacy.py,sha256=cHdcHebyzf8w7OaOLwcsTNSMSSV8WBoAPFLay_9CjE8,4105 -pip/_internal/operations/install/wheel.py,sha256=CxzEg2wTPX4SxNTPIx0ozTqF1X7LhpCyP3iM2FjcKUE,27407 -pip/_internal/operations/prepare.py,sha256=BeYXrLFpRoV5XBnRXQHxRA2plyC36kK9Pms5D9wjCo4,25091 -pip/_internal/pyproject.py,sha256=QqSZR5AGwtf3HTa8NdbDq2yj9T2r9S2h9gnU4aX2Kvg,6987 -pip/_internal/req/__init__.py,sha256=rUQ9d_Sh3E5kNYqX9pkN0D06YL-LrtcbJQ-LiIonq08,2807 -pip/_internal/req/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/req/__pycache__/constructors.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_file.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_install.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_set.cpython-310.pyc,, -pip/_internal/req/__pycache__/req_uninstall.cpython-310.pyc,, -pip/_internal/req/constructors.py,sha256=ypjtq1mOQ3d2mFkFPMf_6Mr8SLKeHQk3tUKHA1ddG0U,16611 -pip/_internal/req/req_file.py,sha256=N6lPO3c0to_G73YyGAnk7VUYmed5jV4Qxgmt1xtlXVg,17646 -pip/_internal/req/req_install.py,sha256=X4WNQlTtvkeATwWdSiJcNLihwbYI_EnGDgE99p-Aa00,35763 -pip/_internal/req/req_set.py,sha256=j3esG0s6SzoVReX9rWn4rpYNtyET_fwxbwJPRimvRxo,2858 -pip/_internal/req/req_uninstall.py,sha256=ZFQfgSNz6H1BMsgl87nQNr2iaQCcbFcmXpW8rKVQcic,24045 -pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/__pycache__/base.cpython-310.pyc,, -pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583 -pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/legacy/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/legacy/__pycache__/resolver.cpython-310.pyc,, -pip/_internal/resolution/legacy/resolver.py,sha256=9em8D5TcSsEN4xZM1WreaRShOnyM4LlvhMSHpUPsocE,24129 -pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/base.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-310.pyc,, -pip/_internal/resolution/resolvelib/base.py,sha256=u1O4fkvCO4mhmu5i32xrDv9AX5NgUci_eYVyBDQhTIM,5220 -pip/_internal/resolution/resolvelib/candidates.py,sha256=6kQZeMzwibnL4lO6bW0hUQQjNEvXfADdFphRRkRvOtc,18963 -pip/_internal/resolution/resolvelib/factory.py,sha256=OnjkLIgyk5Tol7uOOqapA1D4qiRHWmPU18DF1yN5N8o,27878 -pip/_internal/resolution/resolvelib/found_candidates.py,sha256=hvL3Hoa9VaYo-qEOZkBi2Iqw251UDxPz-uMHVaWmLpE,5705 -pip/_internal/resolution/resolvelib/provider.py,sha256=Vd4jW_NnyifB-HMkPYtZIO70M3_RM0MbL5YV6XyBM-w,9914 -pip/_internal/resolution/resolvelib/reporter.py,sha256=3ZVVYrs5PqvLFJkGLcuXoMK5mTInFzl31xjUpDBpZZk,2526 -pip/_internal/resolution/resolvelib/requirements.py,sha256=B1ndvKPSuyyyTEXt9sKhbwminViSWnBrJa7qO2ln4Z0,5455 -pip/_internal/resolution/resolvelib/resolver.py,sha256=nYZ9bTFXj5c1ILKnkSgU7tUCTYyo5V5J-J0sKoA7Wzg,11533 -pip/_internal/self_outdated_check.py,sha256=pnqBuKKZQ8OxKP0MaUUiDHl3AtyoMJHHG4rMQ7YcYXY,8167 -pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_internal/utils/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/utils/__pycache__/_log.cpython-310.pyc,, -pip/_internal/utils/__pycache__/appdirs.cpython-310.pyc,, -pip/_internal/utils/__pycache__/compat.cpython-310.pyc,, -pip/_internal/utils/__pycache__/compatibility_tags.cpython-310.pyc,, -pip/_internal/utils/__pycache__/datetime.cpython-310.pyc,, -pip/_internal/utils/__pycache__/deprecation.cpython-310.pyc,, -pip/_internal/utils/__pycache__/direct_url_helpers.cpython-310.pyc,, -pip/_internal/utils/__pycache__/distutils_args.cpython-310.pyc,, -pip/_internal/utils/__pycache__/egg_link.cpython-310.pyc,, -pip/_internal/utils/__pycache__/encoding.cpython-310.pyc,, -pip/_internal/utils/__pycache__/entrypoints.cpython-310.pyc,, -pip/_internal/utils/__pycache__/filesystem.cpython-310.pyc,, -pip/_internal/utils/__pycache__/filetypes.cpython-310.pyc,, -pip/_internal/utils/__pycache__/glibc.cpython-310.pyc,, -pip/_internal/utils/__pycache__/hashes.cpython-310.pyc,, -pip/_internal/utils/__pycache__/inject_securetransport.cpython-310.pyc,, -pip/_internal/utils/__pycache__/logging.cpython-310.pyc,, -pip/_internal/utils/__pycache__/misc.cpython-310.pyc,, -pip/_internal/utils/__pycache__/models.cpython-310.pyc,, -pip/_internal/utils/__pycache__/packaging.cpython-310.pyc,, -pip/_internal/utils/__pycache__/setuptools_build.cpython-310.pyc,, -pip/_internal/utils/__pycache__/subprocess.cpython-310.pyc,, -pip/_internal/utils/__pycache__/temp_dir.cpython-310.pyc,, -pip/_internal/utils/__pycache__/unpacking.cpython-310.pyc,, -pip/_internal/utils/__pycache__/urls.cpython-310.pyc,, -pip/_internal/utils/__pycache__/virtualenv.cpython-310.pyc,, -pip/_internal/utils/__pycache__/wheel.cpython-310.pyc,, -pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015 -pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665 -pip/_internal/utils/compat.py,sha256=ACyBfLgj3_XG-iA5omEDrXqDM0cQKzi8h8HRBInzG6Q,1884 -pip/_internal/utils/compatibility_tags.py,sha256=ydin8QG8BHqYRsPY4OL6cmb44CbqXl1T0xxS97VhHkk,5377 -pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242 -pip/_internal/utils/deprecation.py,sha256=OLc7GzDwPob9y8jscDYCKUNBV-9CWwqFplBOJPLOpBM,5764 -pip/_internal/utils/direct_url_helpers.py,sha256=6F1tc2rcKaCZmgfVwsE6ObIe_Pux23mUVYA-2D9wCFc,3206 -pip/_internal/utils/distutils_args.py,sha256=bYUt4wfFJRaeGO4VHia6FNaA8HlYXMcKuEq1zYijY5g,1115 -pip/_internal/utils/egg_link.py,sha256=ZryCchR_yQSCsdsMkCpxQjjLbQxObA5GDtLG0RR5mGc,2118 -pip/_internal/utils/encoding.py,sha256=qqsXDtiwMIjXMEiIVSaOjwH5YmirCaK-dIzb6-XJsL0,1169 -pip/_internal/utils/entrypoints.py,sha256=YlhLTRl2oHBAuqhc-zmL7USS67TPWVHImjeAQHreZTQ,3064 -pip/_internal/utils/filesystem.py,sha256=RhMIXUaNVMGjc3rhsDahWQ4MavvEQDdqXqgq-F6fpw8,5122 -pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716 -pip/_internal/utils/glibc.py,sha256=tDfwVYnJCOC0BNVpItpy8CGLP9BjkxFHdl0mTS0J7fc,3110 -pip/_internal/utils/hashes.py,sha256=1WhkVNIHNfuYLafBHThIjVKGplxFJXSlQtuG2mXNlJI,4831 -pip/_internal/utils/inject_securetransport.py,sha256=o-QRVMGiENrTJxw3fAhA7uxpdEdw6M41TjHYtSVRrcg,795 -pip/_internal/utils/logging.py,sha256=U2q0i1n8hPS2gQh8qcocAg5dovGAa_bR24akmXMzrk4,11632 -pip/_internal/utils/misc.py,sha256=XLtMDOmy8mWiNLuPIhxPdO1bWIleLdN6JnWDZsXfTgE,22253 -pip/_internal/utils/models.py,sha256=5GoYU586SrxURMvDn_jBMJInitviJg4O5-iOU-6I0WY,1193 -pip/_internal/utils/packaging.py,sha256=5Wm6_x7lKrlqVjPI5MBN_RurcRHwVYoQ7Ksrs84de7s,2108 -pip/_internal/utils/setuptools_build.py,sha256=4i3CuS34yNrkePnZ73rR47pyDzpZBo-SX9V5PNDSSHY,5662 -pip/_internal/utils/subprocess.py,sha256=0EMhgfPGFk8FZn6Qq7Hp9PN6YHuQNWiVby4DXcTCON4,9200 -pip/_internal/utils/temp_dir.py,sha256=aCX489gRa4Nu0dMKRFyGhV6maJr60uEynu5uCbKR4Qg,7702 -pip/_internal/utils/unpacking.py,sha256=SBb2iV1crb89MDRTEKY86R4A_UOWApTQn9VQVcMDOlE,8821 -pip/_internal/utils/urls.py,sha256=AhaesUGl-9it6uvG6fsFPOr9ynFpGaTMk4t5XTX7Z_Q,1759 -pip/_internal/utils/virtualenv.py,sha256=S6f7csYorRpiD6cvn3jISZYc3I8PJC43H5iMFpRAEDU,3456 -pip/_internal/utils/wheel.py,sha256=lXOgZyTlOm5HmK8tw5iw0A3_5A6wRzsXHOaQkIvvloU,4549 -pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596 -pip/_internal/vcs/__pycache__/__init__.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/bazaar.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/git.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/mercurial.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/subversion.cpython-310.pyc,, -pip/_internal/vcs/__pycache__/versioncontrol.cpython-310.pyc,, -pip/_internal/vcs/bazaar.py,sha256=j0oin0fpGRHcCFCxEcpPCQoFEvA-DMLULKdGP8Nv76o,3519 -pip/_internal/vcs/git.py,sha256=mjhwudCx9WlLNkxZ6_kOKmueF0rLoU2i1xeASKF6yiQ,18116 -pip/_internal/vcs/mercurial.py,sha256=Bzbd518Jsx-EJI0IhIobiQqiRsUv5TWYnrmRIFWE0Gw,5238 -pip/_internal/vcs/subversion.py,sha256=vhZs8L-TNggXqM1bbhl-FpbxE3TrIB6Tgnx8fh3S2HE,11729 -pip/_internal/vcs/versioncontrol.py,sha256=KUOc-hN51em9jrqxKwUR3JnkgSE-xSOqMiiJcSaL6B8,22811 -pip/_internal/wheel_builder.py,sha256=8cObBCu4mIsMJqZM7xXI9DO3vldiAnRNa1Gt6izPPTs,13079 -pip/_vendor/__init__.py,sha256=fNxOSVD0auElsD8fN9tuq5psfgMQ-RFBtD4X5gjlRkg,4966 -pip/_vendor/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/__pycache__/six.cpython-310.pyc,, -pip/_vendor/__pycache__/typing_extensions.cpython-310.pyc,, -pip/_vendor/cachecontrol/__init__.py,sha256=hrxlv3q7upsfyMw8k3gQ9vagBax1pYHSGGqYlZ0Zk0M,465 -pip/_vendor/cachecontrol/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/adapter.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/controller.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/serialize.cpython-310.pyc,, -pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-310.pyc,, -pip/_vendor/cachecontrol/_cmd.py,sha256=lxUXqfNTVx84zf6tcWbkLZHA6WVBRtJRpfeA9ZqhaAY,1379 -pip/_vendor/cachecontrol/adapter.py,sha256=ew9OYEQHEOjvGl06ZsuX8W3DAvHWsQKHwWAxISyGug8,5033 -pip/_vendor/cachecontrol/cache.py,sha256=Tty45fOjH40fColTGkqKQvQQmbYsMpk-nCyfLcv2vG4,1535 -pip/_vendor/cachecontrol/caches/__init__.py,sha256=h-1cUmOz6mhLsjTjOrJ8iPejpGdLCyG4lzTftfGZvLg,242 -pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-310.pyc,, -pip/_vendor/cachecontrol/caches/file_cache.py,sha256=GpexcE29LoY4MaZwPUTcUBZaDdcsjqyLxZFznk8Hbr4,5271 -pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=mp-QWonP40I3xJGK3XVO-Gs9a3UjzlqqEmp9iLJH9F4,1033 -pip/_vendor/cachecontrol/compat.py,sha256=LNx7vqBndYdHU8YuJt53ab_8rzMGTXVrvMb7CZJkxG0,778 -pip/_vendor/cachecontrol/controller.py,sha256=bAYrt7x_VH4toNpI066LQxbHpYGpY1MxxmZAhspplvw,16416 -pip/_vendor/cachecontrol/filewrapper.py,sha256=X4BAQOO26GNOR7nH_fhTzAfeuct2rBQcx_15MyFBpcs,3946 -pip/_vendor/cachecontrol/heuristics.py,sha256=8kAyuZLSCyEIgQr6vbUwfhpqg9ows4mM0IV6DWazevI,4154 -pip/_vendor/cachecontrol/serialize.py,sha256=_U1NU_C-SDgFzkbAxAsPDgMTHeTWZZaHCQnZN_jh0U8,7105 -pip/_vendor/cachecontrol/wrapper.py,sha256=X3-KMZ20Ho3VtqyVaXclpeQpFzokR5NE8tZSfvKVaB8,774 -pip/_vendor/certifi/__init__.py,sha256=bK_nm9bLJzNvWZc2oZdiTwg2KWD4HSPBWGaM0zUDvMw,94 -pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255 -pip/_vendor/certifi/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/certifi/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/certifi/__pycache__/core.cpython-310.pyc,, -pip/_vendor/certifi/cacert.pem,sha256=LBHDzgj_xA05AxnHK8ENT5COnGNElNZe0svFUHMf1SQ,275233 -pip/_vendor/certifi/core.py,sha256=ZwiOsv-sD_ouU1ft8wy_xZ3LQ7UbcVzyqj2XNyrsZis,4279 -pip/_vendor/chardet/__init__.py,sha256=57R-HSxj0PWmILMN0GFmUNqEMfrEVSamXyjD-W6_fbs,4797 -pip/_vendor/chardet/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/big5freq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/big5prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/chardistribution.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/charsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/cp949prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/enums.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/escprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/escsm.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/eucjpprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euckrfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euckrprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euctwfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/euctwprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/gb2312freq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/gb2312prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/hebrewprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/jisfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/johabfreq.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/johabprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/jpcntx.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langthaimodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/latin1prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/macromanprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/mbcssm.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/resultdict.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/sjisprober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/universaldetector.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/utf1632prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/utf8prober.cpython-310.pyc,, -pip/_vendor/chardet/__pycache__/version.cpython-310.pyc,, -pip/_vendor/chardet/big5freq.py,sha256=ltcfP-3PjlNHCoo5e4a7C4z-2DhBTXRfY6jbMbB7P30,31274 -pip/_vendor/chardet/big5prober.py,sha256=lPMfwCX6v2AaPgvFh_cSWZcgLDbWiFCHLZ_p9RQ9uxE,1763 -pip/_vendor/chardet/chardistribution.py,sha256=13B8XUG4oXDuLdXvfbIWwLFeR-ZU21AqTS1zcdON8bU,10032 -pip/_vendor/chardet/charsetgroupprober.py,sha256=UKK3SaIZB2PCdKSIS0gnvMtLR9JJX62M-fZJu3OlWyg,3915 -pip/_vendor/chardet/charsetprober.py,sha256=L3t8_wIOov8em-vZWOcbkdsrwe43N6_gqNh5pH7WPd4,5420 -pip/_vendor/chardet/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/chardet/cli/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-310.pyc,, -pip/_vendor/chardet/cli/chardetect.py,sha256=zibMVg5RpKb-ME9_7EYG4ZM2Sf07NHcQzZ12U-rYJho,3242 -pip/_vendor/chardet/codingstatemachine.py,sha256=K7k69sw3jY5DmTXoSJQVsUtFIQKYPQVOSJJhBuGv_yE,3732 -pip/_vendor/chardet/codingstatemachinedict.py,sha256=0GY3Hi2qIZvDrOOJ3AtqppM1RsYxr_66ER4EHjuMiMc,542 -pip/_vendor/chardet/cp949prober.py,sha256=0jKRV7fECuWI16rNnks0ZECKA1iZYCIEaP8A1ZvjUSI,1860 -pip/_vendor/chardet/enums.py,sha256=TzECiZoCKNMqgwU76cPCeKWFBqaWvAdLMev5_bCkhY8,1683 -pip/_vendor/chardet/escprober.py,sha256=Kho48X65xE0scFylIdeJjM2bcbvRvv0h0WUbMWrJD3A,4006 -pip/_vendor/chardet/escsm.py,sha256=AqyXpA2FQFD7k-buBty_7itGEYkhmVa8X09NLRul3QM,12176 -pip/_vendor/chardet/eucjpprober.py,sha256=5KYaM9fsxkRYzw1b5k0fL-j_-ezIw-ij9r97a9MHxLY,3934 -pip/_vendor/chardet/euckrfreq.py,sha256=3mHuRvXfsq_QcQysDQFb8qSudvTiol71C6Ic2w57tKM,13566 -pip/_vendor/chardet/euckrprober.py,sha256=hiFT6wM174GIwRvqDsIcuOc-dDsq2uPKMKbyV8-1Xnc,1753 -pip/_vendor/chardet/euctwfreq.py,sha256=2alILE1Lh5eqiFJZjzRkMQXolNJRHY5oBQd-vmZYFFM,36913 -pip/_vendor/chardet/euctwprober.py,sha256=NxbpNdBtU0VFI0bKfGfDkpP7S2_8_6FlO87dVH0ogws,1753 -pip/_vendor/chardet/gb2312freq.py,sha256=49OrdXzD-HXqwavkqjo8Z7gvs58hONNzDhAyMENNkvY,20735 -pip/_vendor/chardet/gb2312prober.py,sha256=KPEBueaSLSvBpFeINMu0D6TgHcR90e5PaQawifzF4o0,1759 -pip/_vendor/chardet/hebrewprober.py,sha256=96T_Lj_OmW-fK7JrSHojYjyG3fsGgbzkoTNleZ3kfYE,14537 -pip/_vendor/chardet/jisfreq.py,sha256=mm8tfrwqhpOd3wzZKS4NJqkYBQVcDfTM2JiQ5aW932E,25796 -pip/_vendor/chardet/johabfreq.py,sha256=dBpOYG34GRX6SL8k_LbS9rxZPMjLjoMlgZ03Pz5Hmqc,42498 -pip/_vendor/chardet/johabprober.py,sha256=O1Qw9nVzRnun7vZp4UZM7wvJSv9W941mEU9uDMnY3DU,1752 -pip/_vendor/chardet/jpcntx.py,sha256=uhHrYWkLxE_rF5OkHKInm0HUsrjgKHHVQvtt3UcvotA,27055 -pip/_vendor/chardet/langbulgarianmodel.py,sha256=vmbvYFP8SZkSxoBvLkFqKiH1sjma5ihk3PTpdy71Rr4,104562 -pip/_vendor/chardet/langgreekmodel.py,sha256=JfB7bupjjJH2w3X_mYnQr9cJA_7EuITC2cRW13fUjeI,98484 -pip/_vendor/chardet/langhebrewmodel.py,sha256=3HXHaLQPNAGcXnJjkIJfozNZLTvTJmf4W5Awi6zRRKc,98196 -pip/_vendor/chardet/langhungarianmodel.py,sha256=WxbeQIxkv8YtApiNqxQcvj-tMycsoI4Xy-fwkDHpP_Y,101363 -pip/_vendor/chardet/langrussianmodel.py,sha256=s395bTZ87ESTrZCOdgXbEjZ9P1iGPwCl_8xSsac_DLY,128035 -pip/_vendor/chardet/langthaimodel.py,sha256=7bJlQitRpTnVGABmbSznHnJwOHDy3InkTvtFUx13WQI,102774 -pip/_vendor/chardet/langturkishmodel.py,sha256=XY0eGdTIy4eQ9Xg1LVPZacb-UBhHBR-cq0IpPVHowKc,95372 -pip/_vendor/chardet/latin1prober.py,sha256=p15EEmFbmQUwbKLC7lOJVGHEZwcG45ubEZYTGu01J5g,5380 -pip/_vendor/chardet/macromanprober.py,sha256=9anfzmY6TBfUPDyBDOdY07kqmTHpZ1tK0jL-p1JWcOY,6077 -pip/_vendor/chardet/mbcharsetprober.py,sha256=Wr04WNI4F3X_VxEverNG-H25g7u-MDDKlNt-JGj-_uU,3715 -pip/_vendor/chardet/mbcsgroupprober.py,sha256=iRpaNBjV0DNwYPu_z6TiHgRpwYahiM7ztI_4kZ4Uz9A,2131 -pip/_vendor/chardet/mbcssm.py,sha256=hUtPvDYgWDaA2dWdgLsshbwRfm3Q5YRlRogdmeRUNQw,30391 -pip/_vendor/chardet/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/chardet/metadata/__pycache__/languages.cpython-310.pyc,, -pip/_vendor/chardet/metadata/languages.py,sha256=FhvBIdZFxRQ-dTwkb_0madRKgVBCaUMQz9I5xqjE5iQ,13560 -pip/_vendor/chardet/resultdict.py,sha256=ez4FRvN5KaSosJeJ2WzUyKdDdg35HDy_SSLPXKCdt5M,402 -pip/_vendor/chardet/sbcharsetprober.py,sha256=-nd3F90i7GpXLjehLVHqVBE0KlWzGvQUPETLBNn4o6U,6400 -pip/_vendor/chardet/sbcsgroupprober.py,sha256=gcgI0fOfgw_3YTClpbra_MNxwyEyJ3eUXraoLHYb59E,4137 -pip/_vendor/chardet/sjisprober.py,sha256=aqQufMzRw46ZpFlzmYaYeT2-nzmKb-hmcrApppJ862k,4007 -pip/_vendor/chardet/universaldetector.py,sha256=xYBrg4x0dd9WnT8qclfADVD9ondrUNkqPmvte1pa520,14848 -pip/_vendor/chardet/utf1632prober.py,sha256=pw1epGdMj1hDGiCu1AHqqzOEfjX8MVdiW7O1BlT8-eQ,8505 -pip/_vendor/chardet/utf8prober.py,sha256=8m08Ub5490H4jQ6LYXvFysGtgKoKsHUd2zH_i8_TnVw,2812 -pip/_vendor/chardet/version.py,sha256=lGtJcxGM44Qz4Cbk4rbbmrKxnNr1-97U25TameLehZw,244 -pip/_vendor/colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266 -pip/_vendor/colorama/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/ansi.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/ansitowin32.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/initialise.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/win32.cpython-310.pyc,, -pip/_vendor/colorama/__pycache__/winterm.cpython-310.pyc,, -pip/_vendor/colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522 -pip/_vendor/colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128 -pip/_vendor/colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325 -pip/_vendor/colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75 -pip/_vendor/colorama/tests/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/utils.cpython-310.pyc,, -pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-310.pyc,, -pip/_vendor/colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839 -pip/_vendor/colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678 -pip/_vendor/colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741 -pip/_vendor/colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866 -pip/_vendor/colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079 -pip/_vendor/colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709 -pip/_vendor/colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181 -pip/_vendor/colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134 -pip/_vendor/distlib/__init__.py,sha256=acgfseOC55dNrVAzaBKpUiH3Z6V7Q1CaxsiQ3K7pC-E,581 -pip/_vendor/distlib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/database.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/index.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/locators.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/manifest.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/markers.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/metadata.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/resources.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/scripts.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/util.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/version.cpython-310.pyc,, -pip/_vendor/distlib/__pycache__/wheel.cpython-310.pyc,, -pip/_vendor/distlib/compat.py,sha256=tfoMrj6tujk7G4UC2owL6ArgDuCKabgBxuJRGZSmpko,41259 -pip/_vendor/distlib/database.py,sha256=o_mw0fAr93NDAHHHfqG54Y1Hi9Rkfrp2BX15XWZYK50,51697 -pip/_vendor/distlib/index.py,sha256=HFiDG7LMoaBs829WuotrfIwcErOOExUOR_AeBtw_TCU,20834 -pip/_vendor/distlib/locators.py,sha256=wNzG-zERzS_XGls-nBPVVyLRHa2skUlkn0-5n0trMWA,51991 -pip/_vendor/distlib/manifest.py,sha256=nQEhYmgoreaBZzyFzwYsXxJARu3fo4EkunU163U16iE,14811 -pip/_vendor/distlib/markers.py,sha256=TpHHHLgkzyT7YHbwj-2i6weRaq-Ivy2-MUnrDkjau-U,5058 -pip/_vendor/distlib/metadata.py,sha256=g_DIiu8nBXRzA-mWPRpatHGbmFZqaFoss7z9TG7QSUU,39801 -pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820 -pip/_vendor/distlib/scripts.py,sha256=BmkTKmiTk4m2cj-iueliatwz3ut_9SsABBW51vnQnZU,18102 -pip/_vendor/distlib/t32.exe,sha256=a0GV5kCoWsMutvliiCKmIgV98eRZ33wXoS-XrqvJQVs,97792 -pip/_vendor/distlib/t64-arm.exe,sha256=68TAa32V504xVBnufojh0PcenpR3U4wAqTqf-MZqbPw,182784 -pip/_vendor/distlib/t64.exe,sha256=gaYY8hy4fbkHYTTnA4i26ct8IQZzkBG2pRdy0iyuBrc,108032 -pip/_vendor/distlib/util.py,sha256=31dPXn3Rfat0xZLeVoFpuniyhe6vsbl9_QN-qd9Lhlk,66262 -pip/_vendor/distlib/version.py,sha256=WG__LyAa2GwmA6qSoEJtvJE8REA1LZpbSizy8WvhJLk,23513 -pip/_vendor/distlib/w32.exe,sha256=R4csx3-OGM9kL4aPIzQKRo5TfmRSHZo6QWyLhDhNBks,91648 -pip/_vendor/distlib/w64-arm.exe,sha256=xdyYhKj0WDcVUOCb05blQYvzdYIKMbmJn2SZvzkcey4,168448 -pip/_vendor/distlib/w64.exe,sha256=ejGf-rojoBfXseGLpya6bFTFPWRG21X5KvU8J5iU-K0,101888 -pip/_vendor/distlib/wheel.py,sha256=Rgqs658VsJ3R2845qwnZD8XQryV2CzWw2mghwLvxxsI,43898 -pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981 -pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64 -pip/_vendor/distro/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/distro/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/distro/__pycache__/distro.cpython-310.pyc,, -pip/_vendor/distro/distro.py,sha256=UZO1LjIhtFCMdlbiz39gj3raV-Amf3SBwzGzfApiMHw,49330 -pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849 -pip/_vendor/idna/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/codec.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/core.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/idnadata.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/intranges.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/package_data.cpython-310.pyc,, -pip/_vendor/idna/__pycache__/uts46data.cpython-310.pyc,, -pip/_vendor/idna/codec.py,sha256=6ly5odKfqrytKT9_7UrlGklHnf1DSK2r9C6cSM4sa28,3374 -pip/_vendor/idna/compat.py,sha256=0_sOEUMT4CVw9doD3vyRhX80X19PwqFoUBs7gWsFME4,321 -pip/_vendor/idna/core.py,sha256=1JxchwKzkxBSn7R_oCE12oBu3eVux0VzdxolmIad24M,12950 -pip/_vendor/idna/idnadata.py,sha256=xUjqKqiJV8Ho_XzBpAtv5JFoVPSupK-SUXvtjygUHqw,44375 -pip/_vendor/idna/intranges.py,sha256=YBr4fRYuWH7kTKS2tXlFjM24ZF1Pdvcir-aywniInqg,1881 -pip/_vendor/idna/package_data.py,sha256=C_jHJzmX8PI4xq0jpzmcTMxpb5lDsq4o5VyxQzlVrZE,21 -pip/_vendor/idna/uts46data.py,sha256=zvjZU24s58_uAS850Mcd0NnD0X7_gCMAMjzWNIeUJdc,206539 -pip/_vendor/msgpack/__init__.py,sha256=NryGaKLDk_Egd58ZxXpnuI7OWO27AXz7S6CBFRM3sAY,1132 -pip/_vendor/msgpack/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/ext.cpython-310.pyc,, -pip/_vendor/msgpack/__pycache__/fallback.cpython-310.pyc,, -pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081 -pip/_vendor/msgpack/ext.py,sha256=TuldJPkYu8Wo_Xh0tFGL2l06-gY88NSR8tOje9fo2Wg,6080 -pip/_vendor/msgpack/fallback.py,sha256=OORDn86-fHBPlu-rPlMdM10KzkH6S_Rx9CHN1b7o4cg,34557 -pip/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661 -pip/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497 -pip/_vendor/packaging/__pycache__/__about__.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_manylinux.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_musllinux.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/_structures.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/markers.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/requirements.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/specifiers.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/tags.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/utils.cpython-310.pyc,, -pip/_vendor/packaging/__pycache__/version.cpython-310.pyc,, -pip/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488 -pip/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378 -pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431 -pip/_vendor/packaging/markers.py,sha256=AJBOcY8Oq0kYc570KuuPTkvuqjAlhufaE2c9sCUbm64,8487 -pip/_vendor/packaging/requirements.py,sha256=NtDlPBtojpn1IUC85iMjPNsUmufjpSlwnNA-Xb4m5NA,4676 -pip/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110 -pip/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699 -pip/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200 -pip/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665 -pip/_vendor/pkg_resources/__init__.py,sha256=NnpQ3g6BCHzpMgOR_OLBmYtniY4oOzdKpwqghfq_6ug,108287 -pip/_vendor/pkg_resources/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pkg_resources/__pycache__/py31compat.cpython-310.pyc,, -pip/_vendor/pkg_resources/py31compat.py,sha256=CRk8fkiPRDLsbi5pZcKsHI__Pbmh_94L8mr9Qy9Ab2U,562 -pip/_vendor/platformdirs/__init__.py,sha256=9iY4Z8iJDZB0djln6zHHwrPVWpB54TCygcnh--MujU0,12936 -pip/_vendor/platformdirs/__main__.py,sha256=ZmsnTxEOxtTvwa-Y_Vfab_JN3X4XCVeN8X0yyy9-qnc,1176 -pip/_vendor/platformdirs/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/android.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/api.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/macos.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/unix.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/version.cpython-310.pyc,, -pip/_vendor/platformdirs/__pycache__/windows.cpython-310.pyc,, -pip/_vendor/platformdirs/android.py,sha256=GKizhyS7ESRiU67u8UnBJLm46goau9937EchXWbPBlk,4068 -pip/_vendor/platformdirs/api.py,sha256=MXKHXOL3eh_-trSok-JUTjAR_zjmmKF3rjREVABjP8s,4910 -pip/_vendor/platformdirs/macos.py,sha256=-3UXQewbT0yMhMdkzRXfXGAntmLIH7Qt4a9Hlf8I5_Y,2655 -pip/_vendor/platformdirs/unix.py,sha256=P-WQjSSieE38DXjMDa1t4XHnKJQ5idEaKT0PyXwm8KQ,6911 -pip/_vendor/platformdirs/version.py,sha256=qaN-fw_htIgKUVXoAuAEVgKxQu3tZ9qE2eiKkWIS7LA,160 -pip/_vendor/platformdirs/windows.py,sha256=LOrXLgI0CjQldDo2zhOZYGYZ6g4e_cJOCB_pF9aMRWQ,6596 -pip/_vendor/pygments/__init__.py,sha256=5oLcMLXD0cTG8YcHBPITtK1fS0JBASILEvEnWkTezgE,2999 -pip/_vendor/pygments/__main__.py,sha256=p0_rz3JZmNZMNZBOqDojaEx1cr9wmA9FQZX_TYl74lQ,353 -pip/_vendor/pygments/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/cmdline.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/console.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/filter.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/formatter.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/lexer.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/modeline.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/plugin.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/regexopt.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/scanner.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/sphinxext.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/style.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/token.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/unistring.cpython-310.pyc,, -pip/_vendor/pygments/__pycache__/util.cpython-310.pyc,, -pip/_vendor/pygments/cmdline.py,sha256=rc0fah4eknRqFgn1wKNEwkq0yWnSqYOGaA4PaIeOxVY,23685 -pip/_vendor/pygments/console.py,sha256=hQfqCFuOlGk7DW2lPQYepsw-wkOH1iNt9ylNA1eRymM,1697 -pip/_vendor/pygments/filter.py,sha256=NglMmMPTRRv-zuRSE_QbWid7JXd2J4AvwjCW2yWALXU,1938 -pip/_vendor/pygments/filters/__init__.py,sha256=b5YuXB9rampSy2-cMtKxGQoMDfrG4_DcvVwZrzTlB6w,40386 -pip/_vendor/pygments/filters/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/formatter.py,sha256=6-TS2Y8pUMeWIUolWwr1O8ruC-U6HydWDwOdbAiJgJQ,2917 -pip/_vendor/pygments/formatters/__init__.py,sha256=YTqGeHS17fNXCLMZpf7oCxBCKLB9YLsZ8IAsjGhawyg,4810 -pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/groff.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/html.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/img.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/irc.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/latex.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/other.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/svg.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-310.pyc,, -pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-310.pyc,, -pip/_vendor/pygments/formatters/_mapping.py,sha256=fCZgvsM6UEuZUG7J6lr47eVss5owKd_JyaNbDfxeqmQ,4104 -pip/_vendor/pygments/formatters/bbcode.py,sha256=JrL4ITjN-KzPcuQpPMBf1pm33eW2sDUNr8WzSoAJsJA,3314 -pip/_vendor/pygments/formatters/groff.py,sha256=xrOFoLbafSA9uHsSLRogy79_Zc4GWJ8tMK2hCdTJRsw,5086 -pip/_vendor/pygments/formatters/html.py,sha256=QNt9prPgxmbKx2M-nfDwoR1bIg06-sNouQuWnE434Wc,35441 -pip/_vendor/pygments/formatters/img.py,sha256=h75Y7IRZLZxDEIwyoOsdRLTwm7kLVPbODKkgEiJ0iKI,21938 -pip/_vendor/pygments/formatters/irc.py,sha256=iwk5tDJOxbCV64SCmOFyvk__x6RD60ay0nUn7ko9n7U,5871 -pip/_vendor/pygments/formatters/latex.py,sha256=thPbytJCIs2AUXsO3NZwqKtXJ-upOlcXP4CXsx94G4w,19351 -pip/_vendor/pygments/formatters/other.py,sha256=PczqK1Rms43lz6iucOLPeBMxIncPKOGBt-195w1ynII,5073 -pip/_vendor/pygments/formatters/pangomarkup.py,sha256=ZZzMsKJKXrsDniFeMTkIpe7aQ4VZYRHu0idWmSiUJ2U,2212 -pip/_vendor/pygments/formatters/rtf.py,sha256=abrKlWjipBkQvhIICxtjYTUNv6WME0iJJObFvqVuudE,5014 -pip/_vendor/pygments/formatters/svg.py,sha256=6MM9YyO8NhU42RTQfTWBiagWMnsf9iG5gwhqSriHORE,7335 -pip/_vendor/pygments/formatters/terminal.py,sha256=NpEGvwkC6LgMLQTjVzGrJXji3XcET1sb5JCunSCzoRo,4674 -pip/_vendor/pygments/formatters/terminal256.py,sha256=4v4OVizvsxtwWBpIy_Po30zeOzE5oJg_mOc1-rCjMDk,11753 -pip/_vendor/pygments/lexer.py,sha256=ZPB_TGn_qzrXodRFwEdPzzJk6LZBo9BlfSy3lacc6zg,32005 -pip/_vendor/pygments/lexers/__init__.py,sha256=8d80-XfL5UKDCC1wRD1a_ZBZDkZ2HOe7Zul8SsnNYFE,11174 -pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-310.pyc,, -pip/_vendor/pygments/lexers/__pycache__/python.cpython-310.pyc,, -pip/_vendor/pygments/lexers/_mapping.py,sha256=zEiCV5FPiBioMJQJjw9kk7IJ5Y9GwknS4VJPYlcNchs,70232 -pip/_vendor/pygments/lexers/python.py,sha256=gZROs9iNSOA18YyVghP1cUCD0OwYZ04a6PCwgSOCeSA,53376 -pip/_vendor/pygments/modeline.py,sha256=gIbMSYrjSWPk0oATz7W9vMBYkUyTK2OcdVyKjioDRvA,986 -pip/_vendor/pygments/plugin.py,sha256=5rPxEoB_89qQMpOs0nI4KyLOzAHNlbQiwEMOKxqNmv8,2591 -pip/_vendor/pygments/regexopt.py,sha256=c6xcXGpGgvCET_3VWawJJqAnOp0QttFpQEdOPNY2Py0,3072 -pip/_vendor/pygments/scanner.py,sha256=F2T2G6cpkj-yZtzGQr-sOBw5w5-96UrJWveZN6va2aM,3092 -pip/_vendor/pygments/sphinxext.py,sha256=F8L0211sPnXaiWutN0lkSUajWBwlgDMIEFFAbMWOvZY,4630 -pip/_vendor/pygments/style.py,sha256=RRnussX1YiK9Z7HipIvKorImxu3-HnkdpPCO4u925T0,6257 -pip/_vendor/pygments/styles/__init__.py,sha256=iZDZ7PBKb55SpGlE1--cx9cbmWx5lVTH4bXO87t2Vok,3419 -pip/_vendor/pygments/styles/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pygments/token.py,sha256=vA2yNHGJBHfq4jNQSah7C9DmIOp34MmYHPA8P-cYAHI,6184 -pip/_vendor/pygments/unistring.py,sha256=gP3gK-6C4oAFjjo9HvoahsqzuV4Qz0jl0E0OxfDerHI,63187 -pip/_vendor/pygments/util.py,sha256=KgwpWWC3By5AiNwxGTI7oI9aXupH2TyZWukafBJe0Mg,9110 -pip/_vendor/pyparsing/__init__.py,sha256=ZPdI7pPo4IYXcABw-51AcqOzsxVvDtqnQbyn_qYWZvo,9171 -pip/_vendor/pyparsing/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/actions.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/common.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/core.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/helpers.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/results.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/testing.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/unicode.cpython-310.pyc,, -pip/_vendor/pyparsing/__pycache__/util.cpython-310.pyc,, -pip/_vendor/pyparsing/actions.py,sha256=wU9i32e0y1ymxKE3OUwSHO-SFIrt1h_wv6Ws0GQjpNU,6426 -pip/_vendor/pyparsing/common.py,sha256=lFL97ooIeR75CmW5hjURZqwDCTgruqltcTCZ-ulLO2Q,12936 -pip/_vendor/pyparsing/core.py,sha256=AzTm1KFT1FIhiw2zvXZJmrpQoAwB0wOmeDCiR6SYytw,213344 -pip/_vendor/pyparsing/diagram/__init__.py,sha256=KW0PV_TvWKnL7jysz0pQbZ24nzWWu2ZfNaeyUIIywIg,23685 -pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyparsing/exceptions.py,sha256=3LbSafD32NYb1Tzt85GHNkhEAU1eZkTtNSk24cPMemo,9023 -pip/_vendor/pyparsing/helpers.py,sha256=QpUOjW0-psvueMwWb9bQpU2noqKCv98_wnw1VSzSdVo,39129 -pip/_vendor/pyparsing/results.py,sha256=HgNvWVXBdQP-Q6PtJfoCEeOJk2nwEvG-2KVKC5sGA30,25341 -pip/_vendor/pyparsing/testing.py,sha256=7tu4Abp4uSeJV0N_yEPRmmNUhpd18ZQP3CrX41DM814,13402 -pip/_vendor/pyparsing/unicode.py,sha256=fwuhMj30SQ165Cv7HJpu-rSxGbRm93kN9L4Ei7VGc1Y,10787 -pip/_vendor/pyparsing/util.py,sha256=kq772O5YSeXOSdP-M31EWpbH_ayj7BMHImBYo9xPD5M,6805 -pip/_vendor/pyproject_hooks/__init__.py,sha256=kCehmy0UaBa9oVMD7ZIZrnswfnP3LXZ5lvnNJAL5JBM,491 -pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-310.pyc,, -pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-310.pyc,, -pip/_vendor/pyproject_hooks/_compat.py,sha256=by6evrYnqkisiM-MQcvOKs5bgDMzlOSgZqRHNqf04zE,138 -pip/_vendor/pyproject_hooks/_impl.py,sha256=61GJxzQip0IInhuO69ZI5GbNQ82XEDUB_1Gg5_KtUoc,11920 -pip/_vendor/pyproject_hooks/_in_process/__init__.py,sha256=9gQATptbFkelkIy0OfWFEACzqxXJMQDWCH9rBOAZVwQ,546 -pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-310.pyc,, -pip/_vendor/pyproject_hooks/_in_process/_in_process.py,sha256=m2b34c917IW5o-Q_6TYIHlsK9lSUlNiyrITTUH_zwew,10927 -pip/_vendor/requests/__init__.py,sha256=64HgJ8cke-XyNrj1ErwNq0F9SqyAThUTh5lV6m7-YkI,5178 -pip/_vendor/requests/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/__version__.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/_internal_utils.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/adapters.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/api.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/auth.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/certs.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/compat.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/cookies.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/help.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/hooks.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/models.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/packages.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/sessions.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/status_codes.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/structures.cpython-310.pyc,, -pip/_vendor/requests/__pycache__/utils.cpython-310.pyc,, -pip/_vendor/requests/__version__.py,sha256=h48zn-oFukaXrYHocdadp_hIszWyd_PGrS8Eiii6aoc,435 -pip/_vendor/requests/_internal_utils.py,sha256=aSPlF4uDhtfKxEayZJJ7KkAxtormeTfpwKSBSwtmAUw,1397 -pip/_vendor/requests/adapters.py,sha256=GFEz5koZaMZD86v0SHXKVB5SE9MgslEjkCQzldkNwVM,21443 -pip/_vendor/requests/api.py,sha256=dyvkDd5itC9z2g0wHl_YfD1yf6YwpGWLO7__8e21nks,6377 -pip/_vendor/requests/auth.py,sha256=h-HLlVx9j8rKV5hfSAycP2ApOSglTz77R0tz7qCbbEE,10187 -pip/_vendor/requests/certs.py,sha256=PVPooB0jP5hkZEULSCwC074532UFbR2Ptgu0I5zwmCs,575 -pip/_vendor/requests/compat.py,sha256=IhK9quyX0RRuWTNcg6d2JGSAOUbM6mym2p_2XjLTwf4,1286 -pip/_vendor/requests/cookies.py,sha256=kD3kNEcCj-mxbtf5fJsSaT86eGoEYpD3X0CSgpzl7BM,18560 -pip/_vendor/requests/exceptions.py,sha256=FA-_kVwBZ2jhXauRctN_ewHVK25b-fj0Azyz1THQ0Kk,3823 -pip/_vendor/requests/help.py,sha256=FnAAklv8MGm_qb2UilDQgS6l0cUttiCFKUjx0zn2XNA,3879 -pip/_vendor/requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733 -pip/_vendor/requests/models.py,sha256=dDZ-iThotky-Noq9yy97cUEJhr3wnY6mv-xR_ePg_lk,35288 -pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695 -pip/_vendor/requests/sessions.py,sha256=KUqJcRRLovNefUs7ScOXSUVCcfSayTFWtbiJ7gOSlTI,30180 -pip/_vendor/requests/status_codes.py,sha256=FvHmT5uH-_uimtRz5hH9VCbt7VV-Nei2J9upbej6j8g,4235 -pip/_vendor/requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912 -pip/_vendor/requests/utils.py,sha256=0gzSOcx9Ya4liAbHnHuwt4jM78lzCZZoDFgkmsInNUg,33240 -pip/_vendor/resolvelib/__init__.py,sha256=UL-B2BDI0_TRIqkfGwLHKLxY-LjBlomz7941wDqzB1I,537 -pip/_vendor/resolvelib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/providers.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/reporters.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/resolvers.cpython-310.pyc,, -pip/_vendor/resolvelib/__pycache__/structs.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-310.pyc,, -pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156 -pip/_vendor/resolvelib/providers.py,sha256=roVmFBItQJ0TkhNua65h8LdNny7rmeqVEXZu90QiP4o,5872 -pip/_vendor/resolvelib/reporters.py,sha256=fW91NKf-lK8XN7i6Yd_rczL5QeOT3sc6AKhpaTEnP3E,1583 -pip/_vendor/resolvelib/resolvers.py,sha256=2wYzVGBGerbmcIpH8cFmgSKgLSETz8jmwBMGjCBMHG4,17592 -pip/_vendor/resolvelib/structs.py,sha256=IVIYof6sA_N4ZEiE1C1UhzTX495brCNnyCdgq6CYq28,4794 -pip/_vendor/rich/__init__.py,sha256=dRxjIL-SbFVY0q3IjSMrfgBTHrm1LZDgLOygVBwiYZc,6090 -pip/_vendor/rich/__main__.py,sha256=TT8sb9PTnsnKhhrGuHkLN0jdN0dtKhtPkEr9CidDbPM,8478 -pip/_vendor/rich/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/__main__.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_cell_widths.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_emoji_codes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_emoji_replace.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_export_format.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_extension.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_inspect.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_log_render.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_loop.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_null_file.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_palettes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_pick.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_ratio.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_spinners.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_stack.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_timer.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_win32_console.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_windows.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_windows_renderer.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/_wrap.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/abc.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/align.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/ansi.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/bar.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/box.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/cells.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/color.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/color_triplet.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/columns.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/console.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/constrain.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/containers.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/control.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/default_styles.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/diagnose.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/emoji.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/errors.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/file_proxy.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/filesize.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/highlighter.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/json.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/jupyter.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/layout.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/live.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/live_render.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/logging.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/markup.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/measure.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/padding.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/pager.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/palette.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/panel.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/pretty.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/progress.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/progress_bar.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/prompt.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/protocol.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/region.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/repr.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/rule.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/scope.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/screen.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/segment.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/spinner.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/status.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/style.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/styled.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/syntax.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/table.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/terminal_theme.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/text.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/theme.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/themes.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/traceback.cpython-310.pyc,, -pip/_vendor/rich/__pycache__/tree.cpython-310.pyc,, -pip/_vendor/rich/_cell_widths.py,sha256=2n4EiJi3X9sqIq0O16kUZ_zy6UYMd3xFfChlKfnW1Hc,10096 -pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235 -pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064 -pip/_vendor/rich/_export_format.py,sha256=nHArqOljIlYn6NruhWsAsh-fHo7oJC3y9BDJyAa-QYQ,2114 -pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265 -pip/_vendor/rich/_inspect.py,sha256=oZJGw31e64dwXSCmrDnvZbwVb1ZKhWfU8wI3VWohjJk,9695 -pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225 -pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236 -pip/_vendor/rich/_null_file.py,sha256=cTaTCU_xuDXGGa9iqK-kZ0uddZCSvM-RgM2aGMuMiHs,1643 -pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063 -pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423 -pip/_vendor/rich/_ratio.py,sha256=2lLSliL025Y-YMfdfGbutkQDevhcyDqc-DtUYW9mU70,5472 -pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919 -pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351 -pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417 -pip/_vendor/rich/_win32_console.py,sha256=P0vxI2fcndym1UU1S37XAzQzQnkyY7YqAKmxm24_gug,22820 -pip/_vendor/rich/_windows.py,sha256=dvNl9TmfPzNVxiKk5WDFihErZ5796g2UC9-KGGyfXmk,1926 -pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783 -pip/_vendor/rich/_wrap.py,sha256=xfV_9t0Sg6rzimmrDru8fCVmUlalYAcHLDfrJZnbbwQ,1840 -pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890 -pip/_vendor/rich/align.py,sha256=FV6_GS-8uhIyViMng3hkIWSFaTgMohK1Oqyjl8I8mGE,10368 -pip/_vendor/rich/ansi.py,sha256=THex7-qjc82-ZRtmDPAYlVEObYOEE_ARB1692Fk-JHs,6819 -pip/_vendor/rich/bar.py,sha256=a7UD303BccRCrEhGjfMElpv5RFYIinaAhAuqYqhUvmw,3264 -pip/_vendor/rich/box.py,sha256=FJ6nI3jD7h2XNFU138bJUt2HYmWOlRbltoCEuIAZhew,9842 -pip/_vendor/rich/cells.py,sha256=zMjFI15wCpgjLR14lHdfFMVC6qMDi5OsKIB0PYZBBMk,4503 -pip/_vendor/rich/color.py,sha256=GTITgffj47On3YK1v_I5T2CPZJGSnyWipPID_YkYXqw,18015 -pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054 -pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131 -pip/_vendor/rich/console.py,sha256=w3tJfrILZpS359wrNqaldGmyk3PEhEmV8Pg2g2GjXWI,97992 -pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288 -pip/_vendor/rich/containers.py,sha256=aKgm5UDHn5Nmui6IJaKdsZhbHClh_X7D-_Wg8Ehrr7s,5497 -pip/_vendor/rich/control.py,sha256=DSkHTUQLorfSERAKE_oTAEUFefZnZp4bQb4q8rHbKws,6630 -pip/_vendor/rich/default_styles.py,sha256=WqVh-RPNEsx0Wxf3fhS_fCn-wVqgJ6Qfo-Zg7CoCsLE,7954 -pip/_vendor/rich/diagnose.py,sha256=an6uouwhKPAlvQhYpNNpGq9EJysfMIOvvCbO3oSoR24,972 -pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501 -pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642 -pip/_vendor/rich/file_proxy.py,sha256=4gCbGRXg0rW35Plaf0UVvj3dfENHuzc_n8I_dBqxI7o,1616 -pip/_vendor/rich/filesize.py,sha256=9fTLAPCAwHmBXdRv7KZU194jSgNrRb6Wx7RIoBgqeKY,2508 -pip/_vendor/rich/highlighter.py,sha256=3WW6PACGlq0e3YDjfqiMBQ0dYZwu7pcoFYUgJy01nb0,9585 -pip/_vendor/rich/json.py,sha256=TmeFm96Utaov-Ff5miavBPNo51HRooM8S78HEwrYEjA,5053 -pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252 -pip/_vendor/rich/layout.py,sha256=RFYL6HdCFsHf9WRpcvi3w-fpj-8O5dMZ8W96VdKNdbI,14007 -pip/_vendor/rich/live.py,sha256=emVaLUua-FKSYqZXmtJJjBIstO99CqMOuA6vMAKVkO0,14172 -pip/_vendor/rich/live_render.py,sha256=zElm3PrfSIvjOce28zETHMIUf9pFYSUA5o0AflgUP64,3667 -pip/_vendor/rich/logging.py,sha256=uB-cB-3Q4bmXDLLpbOWkmFviw-Fde39zyMV6tKJ2WHQ,11903 -pip/_vendor/rich/markup.py,sha256=xzF4uAafiEeEYDJYt_vUnJOGoTU8RrH-PH7WcWYXjCg,8198 -pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305 -pip/_vendor/rich/padding.py,sha256=kTFGsdGe0os7tXLnHKpwTI90CXEvrceeZGCshmJy5zw,4970 -pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828 -pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396 -pip/_vendor/rich/panel.py,sha256=wGMe40J8KCGgQoM0LyjRErmGIkv2bsYA71RCXThD0xE,10574 -pip/_vendor/rich/pretty.py,sha256=dAbLqSF3jJnyfBLJ7QjQ3B2J-WGyBnAdGXeuBVIyMyA,37414 -pip/_vendor/rich/progress.py,sha256=eg-OURdfZW3n3bib1-zP3SZl6cIm2VZup1pr_96CyLk,59836 -pip/_vendor/rich/progress_bar.py,sha256=cEoBfkc3lLwqba4XKsUpy4vSQKDh2QQ5J2J94-ACFoo,8165 -pip/_vendor/rich/prompt.py,sha256=x0mW-pIPodJM4ry6grgmmLrl8VZp99kqcmdnBe70YYA,11303 -pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391 -pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166 -pip/_vendor/rich/repr.py,sha256=eJObQe6_c5pUjRM85sZ2rrW47_iF9HT3Z8DrgVjvOl8,4436 -pip/_vendor/rich/rule.py,sha256=V6AWI0wCb6DB0rvN967FRMlQrdlG7HoZdfEAHyeG8CM,4773 -pip/_vendor/rich/scope.py,sha256=TMUU8qo17thyqQCPqjDLYpg_UU1k5qVd-WwiJvnJVas,2843 -pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591 -pip/_vendor/rich/segment.py,sha256=6XdX0MfL18tUCaUWDWncIqx0wpq3GiaqzhYP779JvRA,24224 -pip/_vendor/rich/spinner.py,sha256=7b8MCleS4fa46HX0AzF98zfu6ZM6fAL0UgYzPOoakF4,4374 -pip/_vendor/rich/status.py,sha256=gJsIXIZeSo3urOyxRUjs6VrhX5CZrA0NxIQ-dxhCnwo,4425 -pip/_vendor/rich/style.py,sha256=odBbAlrgdEbAj7pmtPbQtWJNS8upyNhhy--Ks6KwAKk,26332 -pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258 -pip/_vendor/rich/syntax.py,sha256=W1xtdBA1-EVP-weYofKXusUlV5zghCOv1nWMHHfNmiY,34995 -pip/_vendor/rich/table.py,sha256=-WzesL-VJKsaiDU3uyczpJMHy6VCaSewBYJwx8RudI8,39684 -pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370 -pip/_vendor/rich/text.py,sha256=andXaxWW_wBveMiZZpd5viQwucWo7SPopcM3ZCQeO0c,45686 -pip/_vendor/rich/theme.py,sha256=GKNtQhDBZKAzDaY0vQVQQFzbc0uWfFe6CJXA-syT7zQ,3627 -pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102 -pip/_vendor/rich/traceback.py,sha256=6LkGguCEAxKv8v8xmKfMeYPPJ1UXUEHDv4726To6FiQ,26070 -pip/_vendor/rich/tree.py,sha256=BMbUYNjS9uodNPfvtY_odmU09GA5QzcMbQ5cJZhllQI,9169 -pip/_vendor/six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549 -pip/_vendor/tenacity/__init__.py,sha256=rjcWJVq5PcNJNC42rt-TAGGskM-RUEkZbDKu1ra7IPo,18364 -pip/_vendor/tenacity/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/_asyncio.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/_utils.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/after.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/before.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/before_sleep.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/nap.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/retry.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/stop.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-310.pyc,, -pip/_vendor/tenacity/__pycache__/wait.cpython-310.pyc,, -pip/_vendor/tenacity/_asyncio.py,sha256=HEb0BVJEeBJE9P-m9XBxh1KcaF96BwoeqkJCL5sbVcQ,3314 -pip/_vendor/tenacity/_utils.py,sha256=-y68scDcyoqvTJuJJ0GTfjdSCljEYlbCYvgk7nM4NdM,1944 -pip/_vendor/tenacity/after.py,sha256=dlmyxxFy2uqpLXDr838DiEd7jgv2AGthsWHGYcGYsaI,1496 -pip/_vendor/tenacity/before.py,sha256=7XtvRmO0dRWUp8SVn24OvIiGFj8-4OP5muQRUiWgLh0,1376 -pip/_vendor/tenacity/before_sleep.py,sha256=ThyDvqKU5yle_IvYQz_b6Tp6UjUS0PhVp6zgqYl9U6Y,1908 -pip/_vendor/tenacity/nap.py,sha256=fRWvnz1aIzbIq9Ap3gAkAZgDH6oo5zxMrU6ZOVByq0I,1383 -pip/_vendor/tenacity/retry.py,sha256=Cy504Ss3UrRV7lnYgvymF66WD1wJ2dbM869kDcjuDes,7550 -pip/_vendor/tenacity/stop.py,sha256=sKHmHaoSaW6sKu3dTxUVKr1-stVkY7lw4Y9yjZU30zQ,2790 -pip/_vendor/tenacity/tornadoweb.py,sha256=E8lWO2nwe6dJgoB-N2HhQprYLDLB_UdSgFnv-EN6wKE,2145 -pip/_vendor/tenacity/wait.py,sha256=tdLTESRm5E237VHG0SxCDXRa0DHKPKVq285kslHVURc,8011 -pip/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396 -pip/_vendor/tomli/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_parser.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_re.cpython-310.pyc,, -pip/_vendor/tomli/__pycache__/_types.cpython-310.pyc,, -pip/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633 -pip/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943 -pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254 -pip/_vendor/typing_extensions.py,sha256=VKZ_nHsuzDbKOVUY2CTdavwBgfZ2EXRyluZHRzUYAbg,80114 -pip/_vendor/urllib3/__init__.py,sha256=iXLcYiJySn0GNbWOOZDDApgBL1JgP44EZ8i1760S8Mc,3333 -pip/_vendor/urllib3/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/_collections.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/_version.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/connection.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/connectionpool.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/exceptions.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/fields.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/filepost.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/poolmanager.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/request.cpython-310.pyc,, -pip/_vendor/urllib3/__pycache__/response.cpython-310.pyc,, -pip/_vendor/urllib3/_collections.py,sha256=Rp1mVyBgc_UlAcp6M3at1skJBXR5J43NawRTvW2g_XY,10811 -pip/_vendor/urllib3/_version.py,sha256=JWE--BUVy7--9FsXILONIpQ43irftKGjT9j2H_fdF2M,64 -pip/_vendor/urllib3/connection.py,sha256=8976wL6sGeVMW0JnXvx5mD00yXu87uQjxtB9_VL8dx8,20070 -pip/_vendor/urllib3/connectionpool.py,sha256=vS4UaHLoR9_5aGLXSQ776y_jTxgqqjx0YsjkYksWGOo,39095 -pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957 -pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-310.pyc,, -pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632 -pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922 -pip/_vendor/urllib3/contrib/appengine.py,sha256=VR68eAVE137lxTgjBDwCna5UiBZTOKa01Aj_-5BaCz4,11036 -pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=NlfkW7WMdW8ziqudopjHoW299og1BTWi0IeIibquFwk,4528 -pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=hDJh4MhyY_p-oKlFcYcQaVQRDv6GMmBGuW9yjxyeejM,17081 -pip/_vendor/urllib3/contrib/securetransport.py,sha256=yhZdmVjY6PI6EeFbp7qYOp6-vp1Rkv2NMuOGaEj7pmc,34448 -pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097 -pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217 -pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579 -pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440 -pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/packages/__pycache__/six.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0 -pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-310.pyc,, -pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417 -pip/_vendor/urllib3/packages/six.py,sha256=b9LM0wBXv7E7SrbCjAm4wwN-hrH-iNxv18LgWNMMKPo,34665 -pip/_vendor/urllib3/poolmanager.py,sha256=0KOOJECoeLYVjUHvv-0h4Oq3FFQQ2yb-Fnjkbj8gJO0,19786 -pip/_vendor/urllib3/request.py,sha256=ZFSIqX0C6WizixecChZ3_okyu7BEv0lZu1VT0s6h4SM,5985 -pip/_vendor/urllib3/response.py,sha256=fmDJAFkG71uFTn-sVSTh2Iw0WmcXQYqkbRjihvwBjU8,30641 -pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155 -pip/_vendor/urllib3/util/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/connection.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/proxy.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/queue.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/request.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/response.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/retry.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/timeout.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/url.cpython-310.pyc,, -pip/_vendor/urllib3/util/__pycache__/wait.cpython-310.pyc,, -pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901 -pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605 -pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498 -pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997 -pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510 -pip/_vendor/urllib3/util/retry.py,sha256=4laWh0HpwGijLiBmdBIYtbhYekQnNzzhx2W9uys0RHA,22003 -pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177 -pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758 -pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895 -pip/_vendor/urllib3/util/timeout.py,sha256=QSbBUNOB9yh6AnDn61SrLQ0hg5oz0I9-uXEG91AJuIg,10003 -pip/_vendor/urllib3/util/url.py,sha256=HLCLEKt8D-QMioTNbneZSzGTGyUkns4w_lSJP1UzE2E,14298 -pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403 -pip/_vendor/vendor.txt,sha256=3i3Zr7_kRDD9UEva0I8YOMroCZ8xuZ9OWd_Q4jmazqE,476 -pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579 -pip/_vendor/webencodings/__pycache__/__init__.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/labels.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/mklabels.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/tests.cpython-310.pyc,, -pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-310.pyc,, -pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979 -pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305 -pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563 -pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307 -pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286 diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/REQUESTED b/.venv/Lib/site-packages/pip-23.0.1.dist-info/REQUESTED deleted file mode 100644 index e69de29b..00000000 diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/WHEEL b/.venv/Lib/site-packages/pip-23.0.1.dist-info/WHEEL deleted file mode 100644 index 57e3d840..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/WHEEL +++ /dev/null @@ -1,5 +0,0 @@ -Wheel-Version: 1.0 -Generator: bdist_wheel (0.38.4) -Root-Is-Purelib: true -Tag: py3-none-any - diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/entry_points.txt b/.venv/Lib/site-packages/pip-23.0.1.dist-info/entry_points.txt deleted file mode 100644 index ab909c9b..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/entry_points.txt +++ /dev/null @@ -1,4 +0,0 @@ -[console_scripts] -pip = pip._internal.cli.main:main -pip3 = pip._internal.cli.main:main -pip3.9 = pip._internal.cli.main:main diff --git a/.venv/Lib/site-packages/pip-23.0.1.dist-info/top_level.txt b/.venv/Lib/site-packages/pip-23.0.1.dist-info/top_level.txt deleted file mode 100644 index a1b589e3..00000000 --- a/.venv/Lib/site-packages/pip-23.0.1.dist-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -pip diff --git a/.venv/Lib/site-packages/pip/__init__.py b/.venv/Lib/site-packages/pip/__init__.py index 42f6c455..62498a77 100644 --- a/.venv/Lib/site-packages/pip/__init__.py +++ b/.venv/Lib/site-packages/pip/__init__.py @@ -1,6 +1,6 @@ from typing import List, Optional -__version__ = "23.0.1" +__version__ = "23.3" def main(args: Optional[List[str]] = None) -> int: diff --git a/.venv/Lib/site-packages/pip/__main__.py b/.venv/Lib/site-packages/pip/__main__.py index fe34a7b7..59913261 100644 --- a/.venv/Lib/site-packages/pip/__main__.py +++ b/.venv/Lib/site-packages/pip/__main__.py @@ -1,6 +1,5 @@ import os import sys -import warnings # Remove '' and current working directory from the first entry # of sys.path, if present to avoid using current directory @@ -20,12 +19,6 @@ if __package__ == "": sys.path.insert(0, path) if __name__ == "__main__": - # Work around the error reported in #9540, pending a proper fix. - # Note: It is essential the warning filter is set *before* importing - # pip, as the deprecation happens at import time, not runtime. - warnings.filterwarnings( - "ignore", category=DeprecationWarning, module=".*packaging\\.version" - ) from pip._internal.cli.main import main as _main sys.exit(_main()) diff --git a/.venv/Lib/site-packages/pip/_internal/__init__.py b/.venv/Lib/site-packages/pip/_internal/__init__.py index 6afb5c62..96c6b88c 100644 --- a/.venv/Lib/site-packages/pip/_internal/__init__.py +++ b/.venv/Lib/site-packages/pip/_internal/__init__.py @@ -1,6 +1,5 @@ from typing import List, Optional -import pip._internal.utils.inject_securetransport # noqa from pip._internal.utils import _log # init_logging() must be called before any call to logging.getLogger() diff --git a/.venv/Lib/site-packages/pip/_internal/cache.py b/.venv/Lib/site-packages/pip/_internal/cache.py index c53b7f02..f45ac23e 100644 --- a/.venv/Lib/site-packages/pip/_internal/cache.py +++ b/.venv/Lib/site-packages/pip/_internal/cache.py @@ -6,14 +6,13 @@ import json import logging import os from pathlib import Path -from typing import Any, Dict, List, Optional, Set +from typing import Any, Dict, List, Optional from pip._vendor.packaging.tags import Tag, interpreter_name, interpreter_version from pip._vendor.packaging.utils import canonicalize_name from pip._internal.exceptions import InvalidWheelFilename from pip._internal.models.direct_url import DirectUrl -from pip._internal.models.format_control import FormatControl from pip._internal.models.link import Link from pip._internal.models.wheel import Wheel from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds @@ -33,25 +32,13 @@ def _hash_dict(d: Dict[str, str]) -> str: class Cache: """An abstract class - provides cache directories for data from links - :param cache_dir: The root of the cache. - :param format_control: An object of FormatControl class to limit - binaries being read from the cache. - :param allowed_formats: which formats of files the cache should store. - ('binary' and 'source' are the only allowed values) """ - def __init__( - self, cache_dir: str, format_control: FormatControl, allowed_formats: Set[str] - ) -> None: + def __init__(self, cache_dir: str) -> None: super().__init__() assert not cache_dir or os.path.isabs(cache_dir) self.cache_dir = cache_dir or None - self.format_control = format_control - self.allowed_formats = allowed_formats - - _valid_formats = {"source", "binary"} - assert self.allowed_formats.union(_valid_formats) == _valid_formats def _get_cache_path_parts(self, link: Link) -> List[str]: """Get parts of part that must be os.path.joined with cache_dir""" @@ -91,16 +78,10 @@ class Cache: if can_not_cache: return [] - formats = self.format_control.get_allowed_formats(canonical_package_name) - if not self.allowed_formats.intersection(formats): - return [] - - candidates = [] path = self.get_path_for_link(link) if os.path.isdir(path): - for candidate in os.listdir(path): - candidates.append((candidate, path)) - return candidates + return [(candidate, path) for candidate in os.listdir(path)] + return [] def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached items in for link.""" @@ -121,8 +102,8 @@ class Cache: class SimpleWheelCache(Cache): """A cache of wheels for future installs.""" - def __init__(self, cache_dir: str, format_control: FormatControl) -> None: - super().__init__(cache_dir, format_control, {"binary"}) + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) def get_path_for_link(self, link: Link) -> str: """Return a directory to store cached wheels for link @@ -191,13 +172,13 @@ class SimpleWheelCache(Cache): class EphemWheelCache(SimpleWheelCache): """A SimpleWheelCache that creates it's own temporary cache directory""" - def __init__(self, format_control: FormatControl) -> None: + def __init__(self) -> None: self._temp_dir = TempDirectory( kind=tempdir_kinds.EPHEM_WHEEL_CACHE, globally_managed=True, ) - super().__init__(self._temp_dir.path, format_control) + super().__init__(self._temp_dir.path) class CacheEntry: @@ -211,7 +192,17 @@ class CacheEntry: self.origin: Optional[DirectUrl] = None origin_direct_url_path = Path(self.link.file_path).parent / ORIGIN_JSON_NAME if origin_direct_url_path.exists(): - self.origin = DirectUrl.from_json(origin_direct_url_path.read_text()) + try: + self.origin = DirectUrl.from_json( + origin_direct_url_path.read_text(encoding="utf-8") + ) + except Exception as e: + logger.warning( + "Ignoring invalid cache entry origin file %s for %s (%s)", + origin_direct_url_path, + link.filename, + e, + ) class WheelCache(Cache): @@ -221,14 +212,10 @@ class WheelCache(Cache): when a certain link is not found in the simple wheel cache first. """ - def __init__( - self, cache_dir: str, format_control: Optional[FormatControl] = None - ) -> None: - if format_control is None: - format_control = FormatControl() - super().__init__(cache_dir, format_control, {"binary"}) - self._wheel_cache = SimpleWheelCache(cache_dir, format_control) - self._ephem_cache = EphemWheelCache(format_control) + def __init__(self, cache_dir: str) -> None: + super().__init__(cache_dir) + self._wheel_cache = SimpleWheelCache(cache_dir) + self._ephem_cache = EphemWheelCache() def get_path_for_link(self, link: Link) -> str: return self._wheel_cache.get_path_for_link(link) @@ -278,16 +265,26 @@ class WheelCache(Cache): @staticmethod def record_download_origin(cache_dir: str, download_info: DirectUrl) -> None: origin_path = Path(cache_dir) / ORIGIN_JSON_NAME - if origin_path.is_file(): - origin = DirectUrl.from_json(origin_path.read_text()) - # TODO: use DirectUrl.equivalent when https://github.com/pypa/pip/pull/10564 - # is merged. - if origin.url != download_info.url: + if origin_path.exists(): + try: + origin = DirectUrl.from_json(origin_path.read_text(encoding="utf-8")) + except Exception as e: logger.warning( - "Origin URL %s in cache entry %s does not match download URL %s. " - "This is likely a pip bug or a cache corruption issue.", - origin.url, - cache_dir, - download_info.url, + "Could not read origin file %s in cache entry (%s). " + "Will attempt to overwrite it.", + origin_path, + e, ) + else: + # TODO: use DirectUrl.equivalent when + # https://github.com/pypa/pip/pull/10564 is merged. + if origin.url != download_info.url: + logger.warning( + "Origin URL %s in cache entry %s does not match download URL " + "%s. This is likely a pip bug or a cache corruption issue. " + "Will overwrite it with the new value.", + origin.url, + cache_dir, + download_info.url, + ) origin_path.write_text(download_info.to_json(), encoding="utf-8") diff --git a/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py b/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py index 226fe84d..e5950b90 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/autocompletion.py @@ -71,8 +71,9 @@ def autocomplete() -> None: for opt in subcommand.parser.option_list_all: if opt.help != optparse.SUPPRESS_HELP: - for opt_str in opt._long_opts + opt._short_opts: - options.append((opt_str, opt.nargs)) + options += [ + (opt_str, opt.nargs) for opt_str in opt._long_opts + opt._short_opts + ] # filter out previously specified options from available options prev_opts = [x.split("=")[0] for x in cwords[1 : cword - 1]] diff --git a/.venv/Lib/site-packages/pip/_internal/cli/base_command.py b/.venv/Lib/site-packages/pip/_internal/cli/base_command.py index 5bd7e67e..db9d5cc6 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/base_command.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/base_command.py @@ -122,6 +122,26 @@ class Command(CommandContextMixIn): user_log_file=options.log, ) + always_enabled_features = set(options.features_enabled) & set( + cmdoptions.ALWAYS_ENABLED_FEATURES + ) + if always_enabled_features: + logger.warning( + "The following features are always enabled: %s. ", + ", ".join(sorted(always_enabled_features)), + ) + + # Make sure that the --python argument isn't specified after the + # subcommand. We can tell, because if --python was specified, + # we should only reach this point if we're running in the created + # subprocess, which has the _PIP_RUNNING_IN_SUBPROCESS environment + # variable set. + if options.python and "_PIP_RUNNING_IN_SUBPROCESS" not in os.environ: + logger.critical( + "The --python option must be placed before the pip subcommand name" + ) + sys.exit(ERROR) + # TODO: Try to get these passing down from the command? # without resorting to os.environ to hold these. # This also affects isolated builds and it should. @@ -161,7 +181,7 @@ class Command(CommandContextMixIn): assert isinstance(status, int) return status except DiagnosticPipError as exc: - logger.error("[present-rich] %s", exc) + logger.error("%s", exc, extra={"rich": True}) logger.debug("Exception information:", exc_info=True) return ERROR diff --git a/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py b/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py index 1f804097..8fb16dc4 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/cmdoptions.py @@ -92,10 +92,10 @@ def check_dist_restriction(options: Values, check_target: bool = False) -> None: ) if check_target: - if dist_restriction_set and not options.target_dir: + if not options.dry_run and dist_restriction_set and not options.target_dir: raise CommandError( "Can not use any platform or abi specific options unless " - "installing via '--target'" + "installing via '--target' or using '--dry-run'" ) @@ -252,6 +252,19 @@ no_input: Callable[..., Option] = partial( help="Disable prompting for input.", ) +keyring_provider: Callable[..., Option] = partial( + Option, + "--keyring-provider", + dest="keyring_provider", + choices=["auto", "disabled", "import", "subprocess"], + default="auto", + help=( + "Enable the credential lookup via the keyring library if user input is allowed." + " Specify which mechanism to use [disabled, import, subprocess]." + " (default: disabled)" + ), +) + proxy: Callable[..., Option] = partial( Option, "--proxy", @@ -657,7 +670,10 @@ def prefer_binary() -> Option: dest="prefer_binary", action="store_true", default=False, - help="Prefer older binary packages over newer source packages.", + help=( + "Prefer binary packages over source packages, even if the " + "source packages are newer." + ), ) @@ -770,10 +786,14 @@ def _handle_no_use_pep517( """ raise_option_error(parser, option=option, msg=msg) - # If user doesn't wish to use pep517, we check if setuptools is installed + # If user doesn't wish to use pep517, we check if setuptools and wheel are installed # and raise error if it is not. - if not importlib.util.find_spec("setuptools"): - msg = "It is not possible to use --no-use-pep517 without setuptools installed." + packages = ("setuptools", "wheel") + if not all(importlib.util.find_spec(package) for package in packages): + msg = ( + f"It is not possible to use --no-use-pep517 " + f"without {' and '.join(packages)} installed." + ) raise_option_error(parser, option=option, msg=msg) # Otherwise, --no-use-pep517 was passed via the command-line. @@ -806,16 +826,23 @@ def _handle_config_settings( ) -> None: key, sep, val = value.partition("=") if sep != "=": - parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") # noqa + parser.error(f"Arguments to {opt_str} must be of the form KEY=VAL") dest = getattr(parser.values, option.dest) if dest is None: dest = {} setattr(parser.values, option.dest, dest) - dest[key] = val + if key in dest: + if isinstance(dest[key], list): + dest[key].append(val) + else: + dest[key] = [dest[key], val] + else: + dest[key] = val config_settings: Callable[..., Option] = partial( Option, + "-C", "--config-settings", dest="config_settings", type=str, @@ -827,17 +854,6 @@ config_settings: Callable[..., Option] = partial( "to pass multiple keys to the backend.", ) -install_options: Callable[..., Option] = partial( - Option, - "--install-option", - dest="install_options", - action="append", - metavar="options", - help="This option is deprecated. Using this option with location-changing " - "options may cause unexpected behavior. " - "Use pip-level options like --user, --prefix, --root, and --target.", -) - build_options: Callable[..., Option] = partial( Option, "--build-option", @@ -905,13 +921,13 @@ def _handle_merge_hash( algo, digest = value.split(":", 1) except ValueError: parser.error( - "Arguments to {} must be a hash name " # noqa + "Arguments to {} must be a hash name " "followed by a value, like --hash=sha256:" "abcde...".format(opt_str) ) if algo not in STRONG_HASHES: parser.error( - "Allowed hash algorithms for {} are {}.".format( # noqa + "Allowed hash algorithms for {} are {}.".format( opt_str, ", ".join(STRONG_HASHES) ) ) @@ -981,6 +997,11 @@ no_python_version_warning: Callable[..., Option] = partial( ) +# Features that are now always on. A warning is printed if they are used. +ALWAYS_ENABLED_FEATURES = [ + "no-binary-enable-wheel-cache", # always on since 23.1 +] + use_new_feature: Callable[..., Option] = partial( Option, "--use-feature", @@ -991,8 +1012,8 @@ use_new_feature: Callable[..., Option] = partial( choices=[ "fast-deps", "truststore", - "no-binary-enable-wheel-cache", - ], + ] + + ALWAYS_ENABLED_FEATURES, help="Enable new functionality, that may be backward incompatible.", ) @@ -1027,6 +1048,7 @@ general_group: Dict[str, Any] = { quiet, log, no_input, + keyring_provider, proxy, retries, timeout, diff --git a/.venv/Lib/site-packages/pip/_internal/cli/main.py b/.venv/Lib/site-packages/pip/_internal/cli/main.py index 0e312215..7e061f5b 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/main.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/main.py @@ -4,6 +4,7 @@ import locale import logging import os import sys +import warnings from typing import List, Optional from pip._internal.cli.autocompletion import autocomplete @@ -46,6 +47,14 @@ def main(args: Optional[List[str]] = None) -> int: if args is None: args = sys.argv[1:] + # Suppress the pkg_resources deprecation warning + # Note - we use a module of .*pkg_resources to cover + # the normal case (pip._vendor.pkg_resources) and the + # devendored case (a bare pkg_resources) + warnings.filterwarnings( + action="ignore", category=DeprecationWarning, module=".*pkg_resources" + ) + # Configure our deprecation warnings to be sent through loggers deprecation.install_warning_logger() diff --git a/.venv/Lib/site-packages/pip/_internal/cli/parser.py b/.venv/Lib/site-packages/pip/_internal/cli/parser.py index c762cf27..64cf9719 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/parser.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/parser.py @@ -229,7 +229,7 @@ class ConfigOptionParser(CustomOptionParser): val = strtobool(val) except ValueError: self.error( - "{} is not a valid value for {} option, " # noqa + "{} is not a valid value for {} option, " "please specify a boolean value like yes/no, " "true/false or 1/0 instead.".format(val, key) ) @@ -240,7 +240,7 @@ class ConfigOptionParser(CustomOptionParser): val = int(val) if not isinstance(val, int) or val < 0: self.error( - "{} is not a valid value for {} option, " # noqa + "{} is not a valid value for {} option, " "please instead specify either a non-negative integer " "or a boolean value like yes/no or false/true " "which is equivalent to 1/0.".format(val, key) diff --git a/.venv/Lib/site-packages/pip/_internal/cli/req_command.py b/.venv/Lib/site-packages/pip/_internal/cli/req_command.py index 1044809f..6f2f79c6 100644 --- a/.venv/Lib/site-packages/pip/_internal/cli/req_command.py +++ b/.venv/Lib/site-packages/pip/_internal/cli/req_command.py @@ -58,12 +58,9 @@ def _create_truststore_ssl_context() -> Optional["SSLContext"]: return None try: - import truststore - except ImportError: - raise CommandError( - "To use the truststore feature, 'truststore' must be installed into " - "pip's current environment." - ) + from pip._vendor import truststore + except ImportError as e: + raise CommandError(f"The truststore feature is unavailable: {e}") return truststore.SSLContext(ssl.PROTOCOL_TLS_CLIENT) @@ -123,7 +120,7 @@ class SessionCommandMixin(CommandContextMixIn): ssl_context = None session = PipSession( - cache=os.path.join(cache_dir, "http") if cache_dir else None, + cache=os.path.join(cache_dir, "http-v2") if cache_dir else None, retries=retries if retries is not None else options.retries, trusted_hosts=options.trusted_hosts, index_urls=self._get_index_urls(options), @@ -151,6 +148,7 @@ class SessionCommandMixin(CommandContextMixIn): # Determine if we can prompt the user for authentication or not session.auth.prompting = not options.no_input + session.auth.keyring_provider = options.keyring_provider return session @@ -267,7 +265,7 @@ class RequirementCommand(IndexGroupCommand): if "legacy-resolver" in options.deprecated_features_enabled: return "legacy" - return "2020-resolver" + return "resolvelib" @classmethod def make_requirement_preparer( @@ -286,9 +284,10 @@ class RequirementCommand(IndexGroupCommand): """ temp_build_dir_path = temp_build_dir.path assert temp_build_dir_path is not None + legacy_resolver = False resolver_variant = cls.determine_resolver_variant(options) - if resolver_variant == "2020-resolver": + if resolver_variant == "resolvelib": lazy_wheel = "fast-deps" in options.features_enabled if lazy_wheel: logger.warning( @@ -299,6 +298,7 @@ class RequirementCommand(IndexGroupCommand): "production." ) else: + legacy_resolver = True lazy_wheel = False if "fast-deps" in options.features_enabled: logger.warning( @@ -319,6 +319,7 @@ class RequirementCommand(IndexGroupCommand): use_user_site=use_user_site, lazy_wheel=lazy_wheel, verbosity=verbosity, + legacy_resolver=legacy_resolver, ) @classmethod @@ -343,13 +344,12 @@ class RequirementCommand(IndexGroupCommand): install_req_from_req_string, isolated=options.isolated_mode, use_pep517=use_pep517, - config_settings=getattr(options, "config_settings", None), ) resolver_variant = cls.determine_resolver_variant(options) # The long import name and duplicated invocation is needed to convince # Mypy into correctly typechecking. Otherwise it would complain the # "Resolver" class being redefined. - if resolver_variant == "2020-resolver": + if resolver_variant == "resolvelib": import pip._internal.resolution.resolvelib.resolver return pip._internal.resolution.resolvelib.resolver.Resolver( @@ -410,7 +410,7 @@ class RequirementCommand(IndexGroupCommand): for req in args: req_to_add = install_req_from_line( req, - None, + comes_from=None, isolated=options.isolated_mode, use_pep517=options.use_pep517, user_supplied=True, @@ -438,6 +438,9 @@ class RequirementCommand(IndexGroupCommand): isolated=options.isolated_mode, use_pep517=options.use_pep517, user_supplied=True, + config_settings=parsed_req.options.get("config_settings") + if parsed_req.options + else None, ) requirements.append(req_to_add) diff --git a/.venv/Lib/site-packages/pip/_internal/commands/cache.py b/.venv/Lib/site-packages/pip/_internal/commands/cache.py index c5f03302..1f3b5fe1 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/cache.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/cache.py @@ -3,10 +3,10 @@ import textwrap from optparse import Values from typing import Any, List -import pip._internal.utils.filesystem as filesystem from pip._internal.cli.base_command import Command from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.exceptions import CommandError, PipError +from pip._internal.utils import filesystem from pip._internal.utils.logging import getLogger logger = getLogger(__name__) @@ -37,7 +37,6 @@ class CacheCommand(Command): """ def add_options(self) -> None: - self.cmd_opts.add_option( "--format", action="store", @@ -94,24 +93,30 @@ class CacheCommand(Command): num_http_files = len(self._find_http_files(options)) num_packages = len(self._find_wheels(options, "*")) - http_cache_location = self._cache_dir(options, "http") + http_cache_location = self._cache_dir(options, "http-v2") + old_http_cache_location = self._cache_dir(options, "http") wheels_cache_location = self._cache_dir(options, "wheels") - http_cache_size = filesystem.format_directory_size(http_cache_location) + http_cache_size = filesystem.format_size( + filesystem.directory_size(http_cache_location) + + filesystem.directory_size(old_http_cache_location) + ) wheels_cache_size = filesystem.format_directory_size(wheels_cache_location) message = ( textwrap.dedent( """ - Package index page cache location: {http_cache_location} + Package index page cache location (pip v23.3+): {http_cache_location} + Package index page cache location (older pips): {old_http_cache_location} Package index page cache size: {http_cache_size} Number of HTTP files: {num_http_files} Locally built wheels location: {wheels_cache_location} Locally built wheels size: {wheels_cache_size} Number of locally built wheels: {package_count} - """ + """ # noqa: E501 ) .format( http_cache_location=http_cache_location, + old_http_cache_location=old_http_cache_location, http_cache_size=http_cache_size, num_http_files=num_http_files, wheels_cache_location=wheels_cache_location, @@ -152,14 +157,8 @@ class CacheCommand(Command): logger.info("\n".join(sorted(results))) def format_for_abspath(self, files: List[str]) -> None: - if not files: - return - - results = [] - for filename in files: - results.append(filename) - - logger.info("\n".join(sorted(results))) + if files: + logger.info("\n".join(sorted(files))) def remove_cache_items(self, options: Values, args: List[Any]) -> None: if len(args) > 1: @@ -196,8 +195,11 @@ class CacheCommand(Command): return os.path.join(options.cache_dir, subdir) def _find_http_files(self, options: Values) -> List[str]: - http_dir = self._cache_dir(options, "http") - return filesystem.find_files(http_dir, "*") + old_http_dir = self._cache_dir(options, "http") + new_http_dir = self._cache_dir(options, "http-v2") + return filesystem.find_files(old_http_dir, "*") + filesystem.find_files( + new_http_dir, "*" + ) def _find_wheels(self, options: Values, pattern: str) -> List[str]: wheel_dir = self._cache_dir(options, "wheels") diff --git a/.venv/Lib/site-packages/pip/_internal/commands/check.py b/.venv/Lib/site-packages/pip/_internal/commands/check.py index 3864220b..5efd0a34 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/check.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/check.py @@ -7,6 +7,7 @@ from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.operations.check import ( check_package_set, create_package_set_from_installed, + warn_legacy_versions_and_specifiers, ) from pip._internal.utils.misc import write_output @@ -20,8 +21,8 @@ class CheckCommand(Command): %prog [options]""" def run(self, options: Values, args: List[str]) -> int: - package_set, parsing_probs = create_package_set_from_installed() + warn_legacy_versions_and_specifiers(package_set) missing, conflicting = check_package_set(package_set) for project_name in missing: diff --git a/.venv/Lib/site-packages/pip/_internal/commands/completion.py b/.venv/Lib/site-packages/pip/_internal/commands/completion.py index deaa3089..9e89e279 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/completion.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/completion.py @@ -22,15 +22,19 @@ COMPLETION_SCRIPTS = { complete -o default -F _pip_completion {prog} """, "zsh": """ - function _pip_completion {{ - local words cword - read -Ac words - read -cn cword - reply=( $( COMP_WORDS="$words[*]" \\ - COMP_CWORD=$(( cword-1 )) \\ - PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null )) + #compdef -P pip[0-9.]# + __pip() {{ + compadd $( COMP_WORDS="$words[*]" \\ + COMP_CWORD=$((CURRENT-1)) \\ + PIP_AUTO_COMPLETE=1 $words[1] 2>/dev/null ) }} - compctl -K _pip_completion {prog} + if [[ $zsh_eval_context[-1] == loadautofunc ]]; then + # autoload from fpath, call function directly + __pip "$@" + else + # eval/source/. command, register function for later + compdef __pip -P 'pip[0-9.]#' + fi """, "fish": """ function __fish_complete_pip diff --git a/.venv/Lib/site-packages/pip/_internal/commands/debug.py b/.venv/Lib/site-packages/pip/_internal/commands/debug.py index 2a3e7d29..5dc91bf4 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/debug.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/debug.py @@ -46,22 +46,29 @@ def create_vendor_txt_map() -> Dict[str, str]: return dict(line.split("==", 1) for line in lines) -def get_module_from_module_name(module_name: str) -> ModuleType: +def get_module_from_module_name(module_name: str) -> Optional[ModuleType]: # Module name can be uppercase in vendor.txt for some reason... module_name = module_name.lower().replace("-", "_") # PATCH: setuptools is actually only pkg_resources. if module_name == "setuptools": module_name = "pkg_resources" - __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) - return getattr(pip._vendor, module_name) + try: + __import__(f"pip._vendor.{module_name}", globals(), locals(), level=0) + return getattr(pip._vendor, module_name) + except ImportError: + # We allow 'truststore' to fail to import due + # to being unavailable on Python 3.9 and earlier. + if module_name == "truststore" and sys.version_info < (3, 10): + return None + raise def get_vendor_version_from_module(module_name: str) -> Optional[str]: module = get_module_from_module_name(module_name) version = getattr(module, "__version__", None) - if not version: + if module and not version: # Try to find version in debundled module info. assert module.__file__ is not None env = get_environment([os.path.dirname(module.__file__)]) @@ -105,7 +112,7 @@ def show_tags(options: Values) -> None: tag_limit = 10 target_python = make_target_python(options) - tags = target_python.get_tags() + tags = target_python.get_sorted_tags() # Display the target options that were explicitly provided. formatted_target = target_python.format_given() @@ -134,10 +141,7 @@ def show_tags(options: Values) -> None: def ca_bundle_info(config: Configuration) -> str: - levels = set() - for key, _ in config.items(): - levels.add(key.split(".")[0]) - + levels = {key.split(".", 1)[0] for key, _ in config.items()} if not levels: return "Not specified" diff --git a/.venv/Lib/site-packages/pip/_internal/commands/download.py b/.venv/Lib/site-packages/pip/_internal/commands/download.py index 4132e089..54247a78 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/download.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/download.py @@ -8,10 +8,7 @@ from pip._internal.cli.cmdoptions import make_target_python from pip._internal.cli.req_command import RequirementCommand, with_cleanup from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.build.build_tracker import get_build_tracker -from pip._internal.req.req_install import ( - LegacySetupPyOptionsCheckMode, - check_legacy_setup_py_options, -) +from pip._internal.req.req_install import check_legacy_setup_py_options from pip._internal.utils.misc import ensure_dir, normalize_path, write_output from pip._internal.utils.temp_dir import TempDirectory @@ -79,7 +76,6 @@ class DownloadCommand(RequirementCommand): @with_cleanup def run(self, options: Values, args: List[str]) -> int: - options.ignore_installed = True # editable doesn't really make sense for `pip download`, but the bowels # of the RequirementSet code require that property. @@ -109,9 +105,7 @@ class DownloadCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) - check_legacy_setup_py_options( - options, reqs, LegacySetupPyOptionsCheckMode.DOWNLOAD - ) + check_legacy_setup_py_options(options, reqs) preparer = self.make_requirement_preparer( temp_build_dir=directory, @@ -143,6 +137,10 @@ class DownloadCommand(RequirementCommand): assert req.name is not None preparer.save_linked_requirement(req) downloaded.append(req.name) + + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + requirement_set.warn_legacy_versions_and_specifiers() + if downloaded: write_output("Successfully downloaded %s", " ".join(downloaded)) diff --git a/.venv/Lib/site-packages/pip/_internal/commands/freeze.py b/.venv/Lib/site-packages/pip/_internal/commands/freeze.py index 5fa6d39b..fd9d88a8 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/freeze.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/freeze.py @@ -1,6 +1,6 @@ import sys from optparse import Values -from typing import List +from typing import AbstractSet, List from pip._internal.cli import cmdoptions from pip._internal.cli.base_command import Command @@ -8,7 +8,18 @@ from pip._internal.cli.status_codes import SUCCESS from pip._internal.operations.freeze import freeze from pip._internal.utils.compat import stdlib_pkgs -DEV_PKGS = {"pip", "setuptools", "distribute", "wheel"} + +def _should_suppress_build_backends() -> bool: + return sys.version_info < (3, 12) + + +def _dev_pkgs() -> AbstractSet[str]: + pkgs = {"pip"} + + if _should_suppress_build_backends(): + pkgs |= {"setuptools", "distribute", "wheel"} + + return pkgs class FreezeCommand(Command): @@ -61,7 +72,7 @@ class FreezeCommand(Command): action="store_true", help=( "Do not skip these packages in the output:" - " {}".format(", ".join(DEV_PKGS)) + " {}".format(", ".join(_dev_pkgs())) ), ) self.cmd_opts.add_option( @@ -77,7 +88,7 @@ class FreezeCommand(Command): def run(self, options: Values, args: List[str]) -> int: skip = set(stdlib_pkgs) if not options.freeze_all: - skip.update(DEV_PKGS) + skip.update(_dev_pkgs()) if options.excludes: skip.update(options.excludes) diff --git a/.venv/Lib/site-packages/pip/_internal/commands/install.py b/.venv/Lib/site-packages/pip/_internal/commands/install.py index b20aeddf..365764fc 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/install.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/install.py @@ -5,9 +5,8 @@ import os import shutil import site from optparse import SUPPRESS_HELP, Values -from typing import Iterable, List, Optional +from typing import List, Optional -from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.rich import print_json from pip._internal.cache import WheelCache @@ -22,22 +21,15 @@ from pip._internal.cli.status_codes import ERROR, SUCCESS from pip._internal.exceptions import CommandError, InstallationError from pip._internal.locations import get_scheme from pip._internal.metadata import get_environment -from pip._internal.models.format_control import FormatControl from pip._internal.models.installation_report import InstallationReport from pip._internal.operations.build.build_tracker import get_build_tracker from pip._internal.operations.check import ConflictDetails, check_install_conflicts from pip._internal.req import install_given_reqs from pip._internal.req.req_install import ( InstallRequirement, - LegacySetupPyOptionsCheckMode, check_legacy_setup_py_options, ) from pip._internal.utils.compat import WINDOWS -from pip._internal.utils.deprecation import ( - LegacyInstallReasonFailedBdistWheel, - deprecated, -) -from pip._internal.utils.distutils_args import parse_distutils_args from pip._internal.utils.filesystem import test_writable_dir from pip._internal.utils.logging import getLogger from pip._internal.utils.misc import ( @@ -52,26 +44,11 @@ from pip._internal.utils.virtualenv import ( running_under_virtualenv, virtualenv_no_global, ) -from pip._internal.wheel_builder import ( - BdistWheelAllowedPredicate, - build, - should_build_for_install_command, -) +from pip._internal.wheel_builder import build, should_build_for_install_command logger = getLogger(__name__) -def get_check_bdist_wheel_allowed( - format_control: FormatControl, -) -> BdistWheelAllowedPredicate: - def check_binary_allowed(req: InstallRequirement) -> bool: - canonical_name = canonicalize_name(req.name or "") - allowed_formats = format_control.get_allowed_formats(canonical_name) - return "binary" in allowed_formats - - return check_binary_allowed - - class InstallCommand(RequirementCommand): """ Install packages from: @@ -156,7 +133,12 @@ class InstallCommand(RequirementCommand): default=None, help=( "Installation prefix where lib, bin and other top-level " - "folders are placed" + "folders are placed. Note that the resulting installation may " + "contain scripts and other resources which reference the " + "Python interpreter of pip, and not that of ``--prefix``. " + "See also the ``--python`` option if the intention is to " + "install packages into another (possibly pip-free) " + "environment." ), ) @@ -218,7 +200,6 @@ class InstallCommand(RequirementCommand): self.cmd_opts.add_option(cmdoptions.override_externally_managed()) self.cmd_opts.add_option(cmdoptions.config_settings()) - self.cmd_opts.add_option(cmdoptions.install_options()) self.cmd_opts.add_option(cmdoptions.global_options()) self.cmd_opts.add_option( @@ -309,8 +290,6 @@ class InstallCommand(RequirementCommand): cmdoptions.check_dist_restriction(options, check_target=True) - install_options = options.install_options or [] - logger.verbose("Using %s", get_pip_version()) options.use_user_site = decide_user_install( options.use_user_site, @@ -361,28 +340,9 @@ class InstallCommand(RequirementCommand): try: reqs = self.get_requirements(args, options, finder, session) - check_legacy_setup_py_options( - options, reqs, LegacySetupPyOptionsCheckMode.INSTALL - ) + check_legacy_setup_py_options(options, reqs) - if "no-binary-enable-wheel-cache" in options.features_enabled: - # TODO: remove format_control from WheelCache when the deprecation cycle - # is over - wheel_cache = WheelCache(options.cache_dir) - else: - if options.format_control.no_binary: - deprecated( - reason=( - "--no-binary currently disables reading from " - "the cache of locally built wheels. In the future " - "--no-binary will not influence the wheel cache." - ), - replacement="to use the --no-cache-dir option", - feature_flag="no-binary-enable-wheel-cache", - issue=11453, - gone_in="23.1", - ) - wheel_cache = WheelCache(options.cache_dir, options.format_control) + wheel_cache = WheelCache(options.cache_dir) # Only when installing is it permitted to use PEP 660. # In other circumstances (pip wheel, pip download) we generate @@ -390,8 +350,6 @@ class InstallCommand(RequirementCommand): for req in reqs: req.permit_editable_wheels = True - reject_location_related_install_options(reqs, options.install_options) - preparer = self.make_requirement_preparer( temp_build_dir=directory, options=options, @@ -429,6 +387,9 @@ class InstallCommand(RequirementCommand): json.dump(report.to_dict(), f, indent=2, ensure_ascii=False) if options.dry_run: + # In non dry-run mode, the legacy versions and specifiers check + # will be done as part of conflict detection. + requirement_set.warn_legacy_versions_and_specifiers() would_install_items = sorted( (r.metadata["name"], r.metadata["version"]) for r in requirement_set.requirements_to_install @@ -450,14 +411,10 @@ class InstallCommand(RequirementCommand): modifying_pip = pip_req.satisfied_by is None protect_pip_from_modification_on_windows(modifying_pip=modifying_pip) - check_bdist_wheel_allowed = get_check_bdist_wheel_allowed( - finder.format_control - ) - reqs_to_build = [ r for r in requirement_set.requirements.values() - if should_build_for_install_command(r, check_bdist_wheel_allowed) + if should_build_for_install_command(r) ] _, build_failures = build( @@ -468,26 +425,14 @@ class InstallCommand(RequirementCommand): global_options=global_options, ) - # If we're using PEP 517, we cannot do a legacy setup.py install - # so we fail here. - pep517_build_failure_names: List[str] = [ - r.name for r in build_failures if r.use_pep517 # type: ignore - ] - if pep517_build_failure_names: + if build_failures: raise InstallationError( "Could not build wheels for {}, which is required to " "install pyproject.toml-based projects".format( - ", ".join(pep517_build_failure_names) + ", ".join(r.name for r in build_failures) # type: ignore ) ) - # For now, we just warn about failures building legacy - # requirements, as we'll fall through to a setup.py install for - # those. - for r in build_failures: - if not r.use_pep517: - r.legacy_install_reason = LegacyInstallReasonFailedBdistWheel - to_install = resolver.get_installation_order(requirement_set) # Check for conflicts in the package set we're installing. @@ -506,7 +451,6 @@ class InstallCommand(RequirementCommand): installed = install_given_reqs( to_install, - install_options, global_options, root=options.root_path, home=target_temp_dir_path, @@ -557,7 +501,7 @@ class InstallCommand(RequirementCommand): show_traceback, options.use_user_site, ) - logger.error(message, exc_info=show_traceback) # noqa + logger.error(message, exc_info=show_traceback) return ERROR @@ -651,7 +595,7 @@ class InstallCommand(RequirementCommand): "source of the following dependency conflicts." ) else: - assert resolver_variant == "2020-resolver" + assert resolver_variant == "resolvelib" parts.append( "pip's dependency resolver does not currently take into account " "all the packages that are installed. This behaviour is the " @@ -684,7 +628,7 @@ class InstallCommand(RequirementCommand): requirement=req, dep_name=dep_name, dep_version=dep_version, - you=("you" if resolver_variant == "2020-resolver" else "you'll"), + you=("you" if resolver_variant == "resolvelib" else "you'll"), ) parts.append(message) @@ -777,45 +721,6 @@ def decide_user_install( return True -def reject_location_related_install_options( - requirements: List[InstallRequirement], options: Optional[List[str]] -) -> None: - """If any location-changing --install-option arguments were passed for - requirements or on the command-line, then show a deprecation warning. - """ - - def format_options(option_names: Iterable[str]) -> List[str]: - return ["--{}".format(name.replace("_", "-")) for name in option_names] - - offenders = [] - - for requirement in requirements: - install_options = requirement.install_options - location_options = parse_distutils_args(install_options) - if location_options: - offenders.append( - "{!r} from {}".format( - format_options(location_options.keys()), requirement - ) - ) - - if options: - location_options = parse_distutils_args(options) - if location_options: - offenders.append( - "{!r} from command line".format(format_options(location_options.keys())) - ) - - if not offenders: - return - - raise CommandError( - "Location-changing options found in --install-option: {}." - " This is unsupported, use pip-level options like --user," - " --prefix, --root, and --target instead.".format("; ".join(offenders)) - ) - - def create_os_error_message( error: OSError, show_traceback: bool, using_user_site: bool ) -> str: diff --git a/.venv/Lib/site-packages/pip/_internal/commands/list.py b/.venv/Lib/site-packages/pip/_internal/commands/list.py index 8e1426db..e551dda9 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/list.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/list.py @@ -103,7 +103,10 @@ class ListCommand(IndexGroupCommand): dest="list_format", default="columns", choices=("columns", "freeze", "json"), - help="Select the output format among: columns (default), freeze, or json", + help=( + "Select the output format among: columns (default), freeze, or json. " + "The 'freeze' format cannot be used with the --outdated option." + ), ) self.cmd_opts.add_option( @@ -157,7 +160,7 @@ class ListCommand(IndexGroupCommand): if options.outdated and options.list_format == "freeze": raise CommandError( - "List format 'freeze' can not be used with the --outdated option." + "List format 'freeze' cannot be used with the --outdated option." ) cmdoptions.check_list_path_option(options) @@ -294,7 +297,7 @@ class ListCommand(IndexGroupCommand): # Create and add a separator. if len(data) > 0: - pkg_strings.insert(1, " ".join(map(lambda x: "-" * x, sizes))) + pkg_strings.insert(1, " ".join("-" * x for x in sizes)) for val in pkg_strings: write_output(val) diff --git a/.venv/Lib/site-packages/pip/_internal/commands/wheel.py b/.venv/Lib/site-packages/pip/_internal/commands/wheel.py index 1afbd562..ed578aa2 100644 --- a/.venv/Lib/site-packages/pip/_internal/commands/wheel.py +++ b/.venv/Lib/site-packages/pip/_internal/commands/wheel.py @@ -12,10 +12,8 @@ from pip._internal.exceptions import CommandError from pip._internal.operations.build.build_tracker import get_build_tracker from pip._internal.req.req_install import ( InstallRequirement, - LegacySetupPyOptionsCheckMode, check_legacy_setup_py_options, ) -from pip._internal.utils.deprecation import deprecated from pip._internal.utils.misc import ensure_dir, normalize_path from pip._internal.utils.temp_dir import TempDirectory from pip._internal.wheel_builder import build, should_build_for_wheel_command @@ -44,7 +42,6 @@ class WheelCommand(RequirementCommand): %prog [options] ...""" def add_options(self) -> None: - self.cmd_opts.add_option( "-w", "--wheel-dir", @@ -108,7 +105,6 @@ class WheelCommand(RequirementCommand): session = self.get_default_session(options) finder = self._build_package_finder(options, session) - wheel_cache = WheelCache(options.cache_dir, options.format_control) options.wheel_dir = normalize_path(options.wheel_dir) ensure_dir(options.wheel_dir) @@ -122,28 +118,9 @@ class WheelCommand(RequirementCommand): ) reqs = self.get_requirements(args, options, finder, session) - check_legacy_setup_py_options( - options, reqs, LegacySetupPyOptionsCheckMode.WHEEL - ) + check_legacy_setup_py_options(options, reqs) - if "no-binary-enable-wheel-cache" in options.features_enabled: - # TODO: remove format_control from WheelCache when the deprecation cycle - # is over - wheel_cache = WheelCache(options.cache_dir) - else: - if options.format_control.no_binary: - deprecated( - reason=( - "--no-binary currently disables reading from " - "the cache of locally built wheels. In the future " - "--no-binary will not influence the wheel cache." - ), - replacement="to use the --no-cache-dir option", - feature_flag="no-binary-enable-wheel-cache", - issue=11453, - gone_in="23.1", - ) - wheel_cache = WheelCache(options.cache_dir, options.format_control) + wheel_cache = WheelCache(options.cache_dir) preparer = self.make_requirement_preparer( temp_build_dir=directory, @@ -176,6 +153,9 @@ class WheelCommand(RequirementCommand): elif should_build_for_wheel_command(req): reqs_to_build.append(req) + preparer.prepare_linked_requirements_more(requirement_set.requirements.values()) + requirement_set.warn_legacy_versions_and_specifiers() + # build wheels build_successes, build_failures = build( reqs_to_build, diff --git a/.venv/Lib/site-packages/pip/_internal/configuration.py b/.venv/Lib/site-packages/pip/_internal/configuration.py index 8fd46c9b..96f82495 100644 --- a/.venv/Lib/site-packages/pip/_internal/configuration.py +++ b/.venv/Lib/site-packages/pip/_internal/configuration.py @@ -210,8 +210,15 @@ class Configuration: # Ensure directory exists. ensure_dir(os.path.dirname(fname)) - with open(fname, "w") as f: - parser.write(f) + # Ensure directory's permission(need to be writeable) + try: + with open(fname, "w") as f: + parser.write(f) + except OSError as error: + raise ConfigurationError( + f"An error occurred while writing to the configuration file " + f"{fname}: {error}" + ) # # Private routines diff --git a/.venv/Lib/site-packages/pip/_internal/distributions/base.py b/.venv/Lib/site-packages/pip/_internal/distributions/base.py index 75ce2dc9..6fb0d7b7 100644 --- a/.venv/Lib/site-packages/pip/_internal/distributions/base.py +++ b/.venv/Lib/site-packages/pip/_internal/distributions/base.py @@ -1,4 +1,5 @@ import abc +from typing import Optional from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata.base import BaseDistribution @@ -19,12 +20,23 @@ class AbstractDistribution(metaclass=abc.ABCMeta): - we must be able to create a Distribution object exposing the above metadata. + + - if we need to do work in the build tracker, we must be able to generate a unique + string to identify the requirement in the build tracker. """ def __init__(self, req: InstallRequirement) -> None: super().__init__() self.req = req + @abc.abstractproperty + def build_tracker_id(self) -> Optional[str]: + """A string that uniquely identifies this requirement to the build tracker. + + If None, then this dist has no work to do in the build tracker, and + ``.prepare_distribution_metadata()`` will not be called.""" + raise NotImplementedError() + @abc.abstractmethod def get_metadata_distribution(self) -> BaseDistribution: raise NotImplementedError() diff --git a/.venv/Lib/site-packages/pip/_internal/distributions/installed.py b/.venv/Lib/site-packages/pip/_internal/distributions/installed.py index edb38aa1..ab8d53be 100644 --- a/.venv/Lib/site-packages/pip/_internal/distributions/installed.py +++ b/.venv/Lib/site-packages/pip/_internal/distributions/installed.py @@ -1,3 +1,5 @@ +from typing import Optional + from pip._internal.distributions.base import AbstractDistribution from pip._internal.index.package_finder import PackageFinder from pip._internal.metadata import BaseDistribution @@ -10,6 +12,10 @@ class InstalledDistribution(AbstractDistribution): been computed. """ + @property + def build_tracker_id(self) -> Optional[str]: + return None + def get_metadata_distribution(self) -> BaseDistribution: assert self.req.satisfied_by is not None, "not actually installed" return self.req.satisfied_by diff --git a/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py b/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py index 4c256479..15ff42b7 100644 --- a/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py +++ b/.venv/Lib/site-packages/pip/_internal/distributions/sdist.py @@ -1,5 +1,5 @@ import logging -from typing import Iterable, Set, Tuple +from typing import Iterable, Optional, Set, Tuple from pip._internal.build_env import BuildEnvironment from pip._internal.distributions.base import AbstractDistribution @@ -18,6 +18,12 @@ class SourceDistribution(AbstractDistribution): generated, either using PEP 517 or using the legacy `setup.py egg_info`. """ + @property + def build_tracker_id(self) -> Optional[str]: + """Identify this requirement uniquely by its link.""" + assert self.req.link + return self.req.link.url_without_fragment + def get_metadata_distribution(self) -> BaseDistribution: return self.req.get_dist() diff --git a/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py b/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py index 03aac775..eb16e25c 100644 --- a/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py +++ b/.venv/Lib/site-packages/pip/_internal/distributions/wheel.py @@ -1,3 +1,5 @@ +from typing import Optional + from pip._vendor.packaging.utils import canonicalize_name from pip._internal.distributions.base import AbstractDistribution @@ -15,6 +17,10 @@ class WheelDistribution(AbstractDistribution): This does not need any preparation as wheels can be directly unpacked. """ + @property + def build_tracker_id(self) -> Optional[str]: + return None + def get_metadata_distribution(self) -> BaseDistribution: """Loads the metadata from the wheel file into memory and returns a Distribution that uses it, not relying on the wheel file or diff --git a/.venv/Lib/site-packages/pip/_internal/exceptions.py b/.venv/Lib/site-packages/pip/_internal/exceptions.py index d4527295..d95fe44b 100644 --- a/.venv/Lib/site-packages/pip/_internal/exceptions.py +++ b/.venv/Lib/site-packages/pip/_internal/exceptions.py @@ -361,20 +361,6 @@ class MetadataInconsistent(InstallationError): ) -class LegacyInstallFailure(DiagnosticPipError): - """Error occurred while executing `setup.py install`""" - - reference = "legacy-install-failure" - - def __init__(self, package_details: str) -> None: - super().__init__( - message="Encountered error while trying to install package.", - context=package_details, - hint_stmt="See above for output from the failure.", - note_stmt="This is an issue with the package mentioned above, not pip.", - ) - - class InstallationSubprocessError(DiagnosticPipError, InstallationError): """A subprocess call failed.""" @@ -558,7 +544,7 @@ class HashMissing(HashError): # so the output can be directly copied into the requirements file. package = ( self.req.original_link - if self.req.original_link + if self.req.is_direct # In case someone feeds something downright stupid # to InstallRequirement's constructor. else getattr(self.req, "req", None) diff --git a/.venv/Lib/site-packages/pip/_internal/index/package_finder.py b/.venv/Lib/site-packages/pip/_internal/index/package_finder.py index b6f8d57e..2121ca32 100644 --- a/.venv/Lib/site-packages/pip/_internal/index/package_finder.py +++ b/.venv/Lib/site-packages/pip/_internal/index/package_finder.py @@ -198,7 +198,7 @@ class LinkEvaluator: reason = f"wrong project name (not {self.project_name})" return (LinkType.different_project, reason) - supported_tags = self._target_python.get_tags() + supported_tags = self._target_python.get_unsorted_tags() if not wheel.supported(supported_tags): # Include the wheel's tags in the reason string to # simplify troubleshooting compatibility issues. @@ -414,7 +414,7 @@ class CandidateEvaluator: if specifier is None: specifier = specifiers.SpecifierSet() - supported_tags = target_python.get_tags() + supported_tags = target_python.get_sorted_tags() return cls( project_name=project_name, diff --git a/.venv/Lib/site-packages/pip/_internal/index/sources.py b/.venv/Lib/site-packages/pip/_internal/index/sources.py index eec3f12f..cd9cb8d4 100644 --- a/.venv/Lib/site-packages/pip/_internal/index/sources.py +++ b/.venv/Lib/site-packages/pip/_internal/index/sources.py @@ -171,7 +171,6 @@ def build_source( expand_dir: bool, cache_link_parsing: bool, ) -> Tuple[Optional[str], Optional[LinkSource]]: - path: Optional[str] = None url: Optional[str] = None if os.path.exists(location): # Is a local path. diff --git a/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py b/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py index 92bd9317..48689f5f 100644 --- a/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py +++ b/.venv/Lib/site-packages/pip/_internal/locations/_distutils.py @@ -89,7 +89,7 @@ def distutils_scheme( # finalize_options(); we only want to override here if the user # has explicitly requested it hence going back to the config if "install_lib" in d.get_option_dict("install"): - scheme.update(dict(purelib=i.install_lib, platlib=i.install_lib)) + scheme.update({"purelib": i.install_lib, "platlib": i.install_lib}) if running_under_virtualenv(): if home: diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py b/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py index 9f73ca71..aa232b6c 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/__init__.py @@ -9,7 +9,7 @@ from pip._internal.utils.misc import strtobool from .base import BaseDistribution, BaseEnvironment, FilesystemWheel, MemoryWheel, Wheel if TYPE_CHECKING: - from typing import Protocol + from typing import Literal, Protocol else: Protocol = object @@ -50,6 +50,7 @@ def _should_use_importlib_metadata() -> bool: class Backend(Protocol): + NAME: 'Literal["importlib", "pkg_resources"]' Distribution: Type[BaseDistribution] Environment: Type[BaseEnvironment] diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/base.py b/.venv/Lib/site-packages/pip/_internal/metadata/base.py index cafb79fb..92491244 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/base.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/base.py @@ -24,7 +24,7 @@ from typing import ( from pip._vendor.packaging.requirements import Requirement from pip._vendor.packaging.specifiers import InvalidSpecifier, SpecifierSet -from pip._vendor.packaging.utils import NormalizedName +from pip._vendor.packaging.utils import NormalizedName, canonicalize_name from pip._vendor.packaging.version import LegacyVersion, Version from pip._internal.exceptions import NoneMetadataError @@ -37,7 +37,6 @@ from pip._internal.models.direct_url import ( from pip._internal.utils.compat import stdlib_pkgs # TODO: Move definition here. from pip._internal.utils.egg_link import egg_link_path_from_sys_path from pip._internal.utils.misc import is_local, normalize_path -from pip._internal.utils.packaging import safe_extra from pip._internal.utils.urls import url_to_path from ._json import msg_to_json @@ -460,6 +459,19 @@ class BaseDistribution(Protocol): For modern .dist-info distributions, this is the collection of "Provides-Extra:" entries in distribution metadata. + + The return value of this function is not particularly useful other than + display purposes due to backward compatibility issues and the extra + names being poorly normalized prior to PEP 685. If you want to perform + logic operations on extras, use :func:`is_extra_provided` instead. + """ + raise NotImplementedError() + + def is_extra_provided(self, extra: str) -> bool: + """Check whether an extra is provided by this distribution. + + This is needed mostly for compatibility issues with pkg_resources not + following the extra normalization rules defined in PEP 685. """ raise NotImplementedError() @@ -537,10 +549,11 @@ class BaseDistribution(Protocol): """Get extras from the egg-info directory.""" known_extras = {""} for entry in self._iter_requires_txt_entries(): - if entry.extra in known_extras: + extra = canonicalize_name(entry.extra) + if extra in known_extras: continue - known_extras.add(entry.extra) - yield entry.extra + known_extras.add(extra) + yield extra def _iter_egg_info_dependencies(self) -> Iterable[str]: """Get distribution dependencies from the egg-info directory. @@ -556,10 +569,11 @@ class BaseDistribution(Protocol): all currently available PEP 517 backends, although not standardized. """ for entry in self._iter_requires_txt_entries(): - if entry.extra and entry.marker: - marker = f'({entry.marker}) and extra == "{safe_extra(entry.extra)}"' - elif entry.extra: - marker = f'extra == "{safe_extra(entry.extra)}"' + extra = canonicalize_name(entry.extra) + if extra and entry.marker: + marker = f'({entry.marker}) and extra == "{extra}"' + elif extra: + marker = f'extra == "{extra}"' elif entry.marker: marker = entry.marker else: diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py index 5e7af9fe..a779138d 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/__init__.py @@ -1,4 +1,6 @@ from ._dists import Distribution from ._envs import Environment -__all__ = ["Distribution", "Environment"] +__all__ = ["NAME", "Distribution", "Environment"] + +NAME = "importlib" diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py index 65c043c8..26370fac 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_dists.py @@ -27,7 +27,6 @@ from pip._internal.metadata.base import ( Wheel, ) from pip._internal.utils.misc import normalize_path -from pip._internal.utils.packaging import safe_extra from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.wheel import parse_wheel, read_wheel_metadata_file @@ -208,12 +207,16 @@ class Distribution(BaseDistribution): return cast(email.message.Message, self._dist.metadata) def iter_provided_extras(self) -> Iterable[str]: - return ( - safe_extra(extra) for extra in self.metadata.get_all("Provides-Extra", []) + return self.metadata.get_all("Provides-Extra", []) + + def is_extra_provided(self, extra: str) -> bool: + return any( + canonicalize_name(provided_extra) == canonicalize_name(extra) + for provided_extra in self.metadata.get_all("Provides-Extra", []) ) def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: - contexts: Sequence[Dict[str, str]] = [{"extra": safe_extra(e)} for e in extras] + contexts: Sequence[Dict[str, str]] = [{"extra": e} for e in extras] for req_string in self.metadata.get_all("Requires-Dist", []): req = Requirement(req_string) if not req.marker: diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py index cbec59e2..048dc55d 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/importlib/_envs.py @@ -151,7 +151,8 @@ def _emit_egg_deprecation(location: Optional[str]) -> None: deprecated( reason=f"Loading egg at {location} is deprecated.", replacement="to use pip for package installation.", - gone_in=None, + gone_in="24.3", + issue=12330, ) @@ -174,7 +175,7 @@ class Environment(BaseEnvironment): for location in self._paths: yield from finder.find(location) for dist in finder.find_eggs(location): - # _emit_egg_deprecation(dist.location) # TODO: Enable this. + _emit_egg_deprecation(dist.location) yield dist # This must go last because that's how pkg_resources tie-breaks. yield from finder.find_linked(location) diff --git a/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py b/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py index f330ef12..bb11e5bd 100644 --- a/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py +++ b/.venv/Lib/site-packages/pip/_internal/metadata/pkg_resources.py @@ -24,8 +24,12 @@ from .base import ( Wheel, ) +__all__ = ["NAME", "Distribution", "Environment"] + logger = logging.getLogger(__name__) +NAME = "pkg_resources" + class EntryPoint(NamedTuple): name: str @@ -212,12 +216,16 @@ class Distribution(BaseDistribution): def iter_dependencies(self, extras: Collection[str] = ()) -> Iterable[Requirement]: if extras: # pkg_resources raises on invalid extras, so we sanitize. - extras = frozenset(extras).intersection(self._dist.extras) + extras = frozenset(pkg_resources.safe_extra(e) for e in extras) + extras = extras.intersection(self._dist.extras) return self._dist.requires(extras) def iter_provided_extras(self) -> Iterable[str]: return self._dist.extras + def is_extra_provided(self, extra: str) -> bool: + return pkg_resources.safe_extra(extra) in self._dist.extras + class Environment(BaseEnvironment): def __init__(self, ws: pkg_resources.WorkingSet) -> None: diff --git a/.venv/Lib/site-packages/pip/_internal/models/direct_url.py b/.venv/Lib/site-packages/pip/_internal/models/direct_url.py index c3de70a7..e219d738 100644 --- a/.venv/Lib/site-packages/pip/_internal/models/direct_url.py +++ b/.venv/Lib/site-packages/pip/_internal/models/direct_url.py @@ -105,22 +105,31 @@ class ArchiveInfo: hash: Optional[str] = None, hashes: Optional[Dict[str, str]] = None, ) -> None: - if hash is not None: + # set hashes before hash, since the hash setter will further populate hashes + self.hashes = hashes + self.hash = hash + + @property + def hash(self) -> Optional[str]: + return self._hash + + @hash.setter + def hash(self, value: Optional[str]) -> None: + if value is not None: # Auto-populate the hashes key to upgrade to the new format automatically. - # We don't back-populate the legacy hash key. + # We don't back-populate the legacy hash key from hashes. try: - hash_name, hash_value = hash.split("=", 1) + hash_name, hash_value = value.split("=", 1) except ValueError: raise DirectUrlValidationError( - f"invalid archive_info.hash format: {hash!r}" + f"invalid archive_info.hash format: {value!r}" ) - if hashes is None: - hashes = {hash_name: hash_value} - elif hash_name not in hash: - hashes = hashes.copy() - hashes[hash_name] = hash_value - self.hash = hash - self.hashes = hashes + if self.hashes is None: + self.hashes = {hash_name: hash_value} + elif hash_name not in self.hashes: + self.hashes = self.hashes.copy() + self.hashes[hash_name] = hash_value + self._hash = value @classmethod def _from_dict(cls, d: Optional[Dict[str, Any]]) -> Optional["ArchiveInfo"]: diff --git a/.venv/Lib/site-packages/pip/_internal/models/installation_report.py b/.venv/Lib/site-packages/pip/_internal/models/installation_report.py index b54afb10..b9c6330d 100644 --- a/.venv/Lib/site-packages/pip/_internal/models/installation_report.py +++ b/.venv/Lib/site-packages/pip/_internal/models/installation_report.py @@ -14,7 +14,7 @@ class InstallationReport: def _install_req_to_dict(cls, ireq: InstallRequirement) -> Dict[str, Any]: assert ireq.download_info, f"No download_info for {ireq}" res = { - # PEP 610 json for the download URL. download_info.archive_info.hash may + # PEP 610 json for the download URL. download_info.archive_info.hashes may # be absent when the requirement was installed from the wheel cache # and the cache entry was populated by an older pip version that did not # record origin.json. @@ -22,7 +22,10 @@ class InstallationReport: # is_direct is true if the requirement was a direct URL reference (which # includes editable requirements), and false if the requirement was # downloaded from a PEP 503 index or --find-links. - "is_direct": bool(ireq.original_link), + "is_direct": ireq.is_direct, + # is_yanked is true if the requirement was yanked from the index, but + # was still selected by pip to conform to PEP 592. + "is_yanked": ireq.link.is_yanked if ireq.link else False, # requested is true if the requirement was specified by the user (aka # top level requirement), and false if it was installed as a dependency of a # requirement. https://peps.python.org/pep-0376/#requested @@ -33,7 +36,7 @@ class InstallationReport: } if ireq.user_supplied and ireq.extras: # For top level requirements, the list of requested extras, if any. - res["requested_extras"] = list(sorted(ireq.extras)) + res["requested_extras"] = sorted(ireq.extras) return res def to_dict(self) -> Dict[str, Any]: diff --git a/.venv/Lib/site-packages/pip/_internal/models/link.py b/.venv/Lib/site-packages/pip/_internal/models/link.py index a1e4d5a0..4453519a 100644 --- a/.venv/Lib/site-packages/pip/_internal/models/link.py +++ b/.venv/Lib/site-packages/pip/_internal/models/link.py @@ -55,25 +55,25 @@ class LinkHash: name: str value: str - _hash_re = re.compile( + _hash_url_fragment_re = re.compile( # NB: we do not validate that the second group (.*) is a valid hex # digest. Instead, we simply keep that string in this class, and then check it # against Hashes when hash-checking is needed. This is easier to debug than # proactively discarding an invalid hex digest, as we handle incorrect hashes # and malformed hashes in the same place. - r"({choices})=(.*)".format( + r"[#&]({choices})=([^&]*)".format( choices="|".join(re.escape(hash_name) for hash_name in _SUPPORTED_HASHES) ), ) def __post_init__(self) -> None: - assert self._hash_re.match(f"{self.name}={self.value}") + assert self.name in _SUPPORTED_HASHES @classmethod @functools.lru_cache(maxsize=None) - def split_hash_name_and_value(cls, url: str) -> Optional["LinkHash"]: + def find_hash_url_fragment(cls, url: str) -> Optional["LinkHash"]: """Search a string for a checksum algorithm name and encoded output value.""" - match = cls._hash_re.search(url) + match = cls._hash_url_fragment_re.search(url) if match is None: return None name, value = match.groups() @@ -95,6 +95,28 @@ class LinkHash: return hashes.is_hash_allowed(self.name, hex_digest=self.value) +@dataclass(frozen=True) +class MetadataFile: + """Information about a core metadata file associated with a distribution.""" + + hashes: Optional[Dict[str, str]] + + def __post_init__(self) -> None: + if self.hashes is not None: + assert all(name in _SUPPORTED_HASHES for name in self.hashes) + + +def supported_hashes(hashes: Optional[Dict[str, str]]) -> Optional[Dict[str, str]]: + # Remove any unsupported hash types from the mapping. If this leaves no + # supported hashes, return None + if hashes is None: + return None + hashes = {n: v for n, v in hashes.items() if n in _SUPPORTED_HASHES} + if not hashes: + return None + return hashes + + def _clean_url_path_part(part: str) -> str: """ Clean a "part" of a URL path (i.e. after splitting on "@" characters). @@ -167,7 +189,7 @@ class Link(KeyBasedCompareMixin): "comes_from", "requires_python", "yanked_reason", - "dist_info_metadata", + "metadata_file_data", "cache_link_parsing", "egg_fragment", ] @@ -178,7 +200,7 @@ class Link(KeyBasedCompareMixin): comes_from: Optional[Union[str, "IndexContent"]] = None, requires_python: Optional[str] = None, yanked_reason: Optional[str] = None, - dist_info_metadata: Optional[str] = None, + metadata_file_data: Optional[MetadataFile] = None, cache_link_parsing: bool = True, hashes: Optional[Mapping[str, str]] = None, ) -> None: @@ -196,11 +218,10 @@ class Link(KeyBasedCompareMixin): a simple repository HTML link. If the file has been yanked but no reason was provided, this should be the empty string. See PEP 592 for more information and the specification. - :param dist_info_metadata: the metadata attached to the file, or None if no such - metadata is provided. This is the value of the "data-dist-info-metadata" - attribute, if present, in a simple repository HTML link. This may be parsed - into its own `Link` by `self.metadata_link()`. See PEP 658 for more - information and the specification. + :param metadata_file_data: the metadata attached to the file, or None if + no such metadata is provided. This argument, if not None, indicates + that a separate metadata file exists, and also optionally supplies + hashes for that file. :param cache_link_parsing: A flag that is used elsewhere to determine whether resources retrieved from this link should be cached. PyPI URLs should generally have this set to False, for example. @@ -208,6 +229,10 @@ class Link(KeyBasedCompareMixin): determine the validity of a download. """ + # The comes_from, requires_python, and metadata_file_data arguments are + # only used by classmethods of this class, and are not used in client + # code directly. + # url can be a UNC windows share if url.startswith("\\\\"): url = path_to_url(url) @@ -217,7 +242,7 @@ class Link(KeyBasedCompareMixin): # trying to set a new value. self._url = url - link_hash = LinkHash.split_hash_name_and_value(url) + link_hash = LinkHash.find_hash_url_fragment(url) hashes_from_link = {} if link_hash is None else link_hash.as_dict() if hashes is None: self._hashes = hashes_from_link @@ -227,7 +252,7 @@ class Link(KeyBasedCompareMixin): self.comes_from = comes_from self.requires_python = requires_python if requires_python else None self.yanked_reason = yanked_reason - self.dist_info_metadata = dist_info_metadata + self.metadata_file_data = metadata_file_data super().__init__(key=url, defining_class=Link) @@ -250,9 +275,25 @@ class Link(KeyBasedCompareMixin): url = _ensure_quoted_url(urllib.parse.urljoin(page_url, file_url)) pyrequire = file_data.get("requires-python") yanked_reason = file_data.get("yanked") - dist_info_metadata = file_data.get("dist-info-metadata") hashes = file_data.get("hashes", {}) + # PEP 714: Indexes must use the name core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = file_data.get("core-metadata") + if metadata_info is None: + metadata_info = file_data.get("dist-info-metadata") + + # The metadata info value may be a boolean, or a dict of hashes. + if isinstance(metadata_info, dict): + # The file exists, and hashes have been supplied + metadata_file_data = MetadataFile(supported_hashes(metadata_info)) + elif metadata_info: + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + else: + # False or not present: the file does not exist + metadata_file_data = None + # The Link.yanked_reason expects an empty string instead of a boolean. if yanked_reason and not isinstance(yanked_reason, str): yanked_reason = "" @@ -266,7 +307,7 @@ class Link(KeyBasedCompareMixin): requires_python=pyrequire, yanked_reason=yanked_reason, hashes=hashes, - dist_info_metadata=dist_info_metadata, + metadata_file_data=metadata_file_data, ) @classmethod @@ -286,14 +327,39 @@ class Link(KeyBasedCompareMixin): url = _ensure_quoted_url(urllib.parse.urljoin(base_url, href)) pyrequire = anchor_attribs.get("data-requires-python") yanked_reason = anchor_attribs.get("data-yanked") - dist_info_metadata = anchor_attribs.get("data-dist-info-metadata") + + # PEP 714: Indexes must use the name data-core-metadata, but + # clients should support the old name as a fallback for compatibility. + metadata_info = anchor_attribs.get("data-core-metadata") + if metadata_info is None: + metadata_info = anchor_attribs.get("data-dist-info-metadata") + # The metadata info value may be the string "true", or a string of + # the form "hashname=hashval" + if metadata_info == "true": + # The file exists, but there are no hashes + metadata_file_data = MetadataFile(None) + elif metadata_info is None: + # The file does not exist + metadata_file_data = None + else: + # The file exists, and hashes have been supplied + hashname, sep, hashval = metadata_info.partition("=") + if sep == "=": + metadata_file_data = MetadataFile(supported_hashes({hashname: hashval})) + else: + # Error - data is wrong. Treat as no hashes supplied. + logger.debug( + "Index returned invalid data-dist-info-metadata value: %s", + metadata_info, + ) + metadata_file_data = MetadataFile(None) return cls( url, comes_from=page_url, requires_python=pyrequire, yanked_reason=yanked_reason, - dist_info_metadata=dist_info_metadata, + metadata_file_data=metadata_file_data, ) def __str__(self) -> str: @@ -395,22 +461,13 @@ class Link(KeyBasedCompareMixin): return match.group(1) def metadata_link(self) -> Optional["Link"]: - """Implementation of PEP 658 parsing.""" - # Note that Link.from_element() parsing the "data-dist-info-metadata" attribute - # from an HTML anchor tag is typically how the Link.dist_info_metadata attribute - # gets set. - if self.dist_info_metadata is None: + """Return a link to the associated core metadata file (if any).""" + if self.metadata_file_data is None: return None metadata_url = f"{self.url_without_fragment}.metadata" - # If data-dist-info-metadata="true" is set, then the metadata file exists, - # but there is no information about its checksum or anything else. - if self.dist_info_metadata != "true": - link_hash = LinkHash.split_hash_name_and_value(self.dist_info_metadata) - else: - link_hash = None - if link_hash is None: + if self.metadata_file_data.hashes is None: return Link(metadata_url) - return Link(metadata_url, hashes=link_hash.as_dict()) + return Link(metadata_url, hashes=self.metadata_file_data.hashes) def as_hashes(self) -> Hashes: return Hashes({k: [v] for k, v in self._hashes.items()}) diff --git a/.venv/Lib/site-packages/pip/_internal/models/search_scope.py b/.venv/Lib/site-packages/pip/_internal/models/search_scope.py index a64af738..fe61e811 100644 --- a/.venv/Lib/site-packages/pip/_internal/models/search_scope.py +++ b/.venv/Lib/site-packages/pip/_internal/models/search_scope.py @@ -79,7 +79,6 @@ class SearchScope: redacted_index_urls = [] if self.index_urls and self.index_urls != [PyPI.simple_url]: for url in self.index_urls: - redacted_index_url = redact_auth_from_url(url) # Parse the URL diff --git a/.venv/Lib/site-packages/pip/_internal/models/target_python.py b/.venv/Lib/site-packages/pip/_internal/models/target_python.py index 744bd7ef..67ea5da7 100644 --- a/.venv/Lib/site-packages/pip/_internal/models/target_python.py +++ b/.venv/Lib/site-packages/pip/_internal/models/target_python.py @@ -1,5 +1,5 @@ import sys -from typing import List, Optional, Tuple +from typing import List, Optional, Set, Tuple from pip._vendor.packaging.tags import Tag @@ -22,6 +22,7 @@ class TargetPython: "py_version", "py_version_info", "_valid_tags", + "_valid_tags_set", ] def __init__( @@ -61,8 +62,9 @@ class TargetPython: self.py_version = py_version self.py_version_info = py_version_info - # This is used to cache the return value of get_tags(). + # This is used to cache the return value of get_(un)sorted_tags. self._valid_tags: Optional[List[Tag]] = None + self._valid_tags_set: Optional[Set[Tag]] = None def format_given(self) -> str: """ @@ -84,7 +86,7 @@ class TargetPython: f"{key}={value!r}" for key, value in key_values if value is not None ) - def get_tags(self) -> List[Tag]: + def get_sorted_tags(self) -> List[Tag]: """ Return the supported PEP 425 tags to check wheel candidates against. @@ -108,3 +110,13 @@ class TargetPython: self._valid_tags = tags return self._valid_tags + + def get_unsorted_tags(self) -> Set[Tag]: + """Exactly the same as get_sorted_tags, but returns a set. + + This is important for performance. + """ + if self._valid_tags_set is None: + self._valid_tags_set = set(self.get_sorted_tags()) + + return self._valid_tags_set diff --git a/.venv/Lib/site-packages/pip/_internal/network/auth.py b/.venv/Lib/site-packages/pip/_internal/network/auth.py index c1621326..94a82fa6 100644 --- a/.venv/Lib/site-packages/pip/_internal/network/auth.py +++ b/.venv/Lib/site-packages/pip/_internal/network/auth.py @@ -3,12 +3,17 @@ Contains interface (MultiDomainBasicAuth) and associated glue code for providing credentials in the context of network requests. """ - +import logging import os import shutil import subprocess +import sysconfig +import typing import urllib.parse from abc import ABC, abstractmethod +from functools import lru_cache +from os.path import commonprefix +from pathlib import Path from typing import Any, Dict, List, NamedTuple, Optional, Tuple from pip._vendor.requests.auth import AuthBase, HTTPBasicAuth @@ -39,6 +44,8 @@ class Credentials(NamedTuple): class KeyRingBaseProvider(ABC): """Keyring base provider interface""" + has_keyring: bool + @abstractmethod def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: ... @@ -51,6 +58,8 @@ class KeyRingBaseProvider(ABC): class KeyRingNullProvider(KeyRingBaseProvider): """Keyring null provider""" + has_keyring = False + def get_auth_info(self, url: str, username: Optional[str]) -> Optional[AuthInfo]: return None @@ -61,6 +70,8 @@ class KeyRingNullProvider(KeyRingBaseProvider): class KeyRingPythonProvider(KeyRingBaseProvider): """Keyring interface which uses locally imported `keyring`""" + has_keyring = True + def __init__(self) -> None: import keyring @@ -97,6 +108,8 @@ class KeyRingCliProvider(KeyRingBaseProvider): PATH. """ + has_keyring = True + def __init__(self, cmd: str) -> None: self.keyring = cmd @@ -123,7 +136,7 @@ class KeyRingCliProvider(KeyRingBaseProvider): res = subprocess.run( cmd, stdin=subprocess.DEVNULL, - capture_output=True, + stdout=subprocess.PIPE, env=env, ) if res.returncode: @@ -134,66 +147,89 @@ class KeyRingCliProvider(KeyRingBaseProvider): """Mirror the implementation of keyring.set_password using cli""" if self.keyring is None: return None - - cmd = [self.keyring, "set", service_name, username] - input_ = (password + os.linesep).encode("utf-8") env = os.environ.copy() env["PYTHONIOENCODING"] = "utf-8" - res = subprocess.run(cmd, input=input_, env=env) - res.check_returncode() + subprocess.run( + [self.keyring, "set", service_name, username], + input=f"{password}{os.linesep}".encode("utf-8"), + env=env, + check=True, + ) return None -def get_keyring_provider() -> KeyRingBaseProvider: +@lru_cache(maxsize=None) +def get_keyring_provider(provider: str) -> KeyRingBaseProvider: + logger.verbose("Keyring provider requested: %s", provider) + # keyring has previously failed and been disabled - if not KEYRING_DISABLED: - # Default to trying to use Python provider + if KEYRING_DISABLED: + provider = "disabled" + if provider in ["import", "auto"]: try: - return KeyRingPythonProvider() + impl = KeyRingPythonProvider() + logger.verbose("Keyring provider set: import") + return impl except ImportError: pass except Exception as exc: # In the event of an unexpected exception # we should warn the user - logger.warning( - "Installed copy of keyring fails with exception %s, " - "trying to find a keyring executable as a fallback", - str(exc), - ) - - # Fallback to Cli Provider if `keyring` isn't installed + msg = "Installed copy of keyring fails with exception %s" + if provider == "auto": + msg = msg + ", trying to find a keyring executable as a fallback" + logger.warning(msg, exc, exc_info=logger.isEnabledFor(logging.DEBUG)) + if provider in ["subprocess", "auto"]: cli = shutil.which("keyring") + if cli and cli.startswith(sysconfig.get_path("scripts")): + # all code within this function is stolen from shutil.which implementation + @typing.no_type_check + def PATH_as_shutil_which_determines_it() -> str: + path = os.environ.get("PATH", None) + if path is None: + try: + path = os.confstr("CS_PATH") + except (AttributeError, ValueError): + # os.confstr() or CS_PATH is not available + path = os.defpath + # bpo-35755: Don't use os.defpath if the PATH environment variable is + # set to an empty string + + return path + + scripts = Path(sysconfig.get_path("scripts")) + + paths = [] + for path in PATH_as_shutil_which_determines_it().split(os.pathsep): + p = Path(path) + try: + if not p.samefile(scripts): + paths.append(path) + except FileNotFoundError: + pass + + path = os.pathsep.join(paths) + + cli = shutil.which("keyring", path=path) + if cli: + logger.verbose("Keyring provider set: subprocess with executable %s", cli) return KeyRingCliProvider(cli) + logger.verbose("Keyring provider set: disabled") return KeyRingNullProvider() -def get_keyring_auth(url: Optional[str], username: Optional[str]) -> Optional[AuthInfo]: - """Return the tuple auth for a given url from keyring.""" - # Do nothing if no url was provided - if not url: - return None - - keyring = get_keyring_provider() - try: - return keyring.get_auth_info(url, username) - except Exception as exc: - logger.warning( - "Keyring is skipped due to an exception: %s", - str(exc), - ) - global KEYRING_DISABLED - KEYRING_DISABLED = True - return None - - class MultiDomainBasicAuth(AuthBase): def __init__( - self, prompting: bool = True, index_urls: Optional[List[str]] = None + self, + prompting: bool = True, + index_urls: Optional[List[str]] = None, + keyring_provider: str = "auto", ) -> None: self.prompting = prompting self.index_urls = index_urls + self.keyring_provider = keyring_provider # type: ignore[assignment] self.passwords: Dict[str, AuthInfo] = {} # When the user is prompted to enter credentials and keyring is # available, we will offer to save them. If the user accepts, @@ -202,6 +238,47 @@ class MultiDomainBasicAuth(AuthBase): # ``save_credentials`` to save these. self._credentials_to_save: Optional[Credentials] = None + @property + def keyring_provider(self) -> KeyRingBaseProvider: + return get_keyring_provider(self._keyring_provider) + + @keyring_provider.setter + def keyring_provider(self, provider: str) -> None: + # The free function get_keyring_provider has been decorated with + # functools.cache. If an exception occurs in get_keyring_auth that + # cache will be cleared and keyring disabled, take that into account + # if you want to remove this indirection. + self._keyring_provider = provider + + @property + def use_keyring(self) -> bool: + # We won't use keyring when --no-input is passed unless + # a specific provider is requested because it might require + # user interaction + return self.prompting or self._keyring_provider not in ["auto", "disabled"] + + def _get_keyring_auth( + self, + url: Optional[str], + username: Optional[str], + ) -> Optional[AuthInfo]: + """Return the tuple auth for a given url from keyring.""" + # Do nothing if no url was provided + if not url: + return None + + try: + return self.keyring_provider.get_auth_info(url, username) + except Exception as exc: + logger.warning( + "Keyring is skipped due to an exception: %s", + str(exc), + ) + global KEYRING_DISABLED + KEYRING_DISABLED = True + get_keyring_provider.cache_clear() + return None + def _get_index_url(self, url: str) -> Optional[str]: """Return the original index URL matching the requested URL. @@ -218,15 +295,42 @@ class MultiDomainBasicAuth(AuthBase): if not url or not self.index_urls: return None - for u in self.index_urls: - prefix = remove_auth_from_url(u).rstrip("/") + "/" - if url.startswith(prefix): - return u - return None + url = remove_auth_from_url(url).rstrip("/") + "/" + parsed_url = urllib.parse.urlsplit(url) + + candidates = [] + + for index in self.index_urls: + index = index.rstrip("/") + "/" + parsed_index = urllib.parse.urlsplit(remove_auth_from_url(index)) + if parsed_url == parsed_index: + return index + + if parsed_url.netloc != parsed_index.netloc: + continue + + candidate = urllib.parse.urlsplit(index) + candidates.append(candidate) + + if not candidates: + return None + + candidates.sort( + reverse=True, + key=lambda candidate: commonprefix( + [ + parsed_url.path, + candidate.path, + ] + ).rfind("/"), + ) + + return urllib.parse.urlunsplit(candidates[0]) def _get_new_credentials( self, original_url: str, + *, allow_netrc: bool = True, allow_keyring: bool = False, ) -> AuthInfo: @@ -270,8 +374,8 @@ class MultiDomainBasicAuth(AuthBase): # The index url is more specific than the netloc, so try it first # fmt: off kr_auth = ( - get_keyring_auth(index_url, username) or - get_keyring_auth(netloc, username) + self._get_keyring_auth(index_url, username) or + self._get_keyring_auth(netloc, username) ) # fmt: on if kr_auth: @@ -348,18 +452,23 @@ class MultiDomainBasicAuth(AuthBase): def _prompt_for_password( self, netloc: str ) -> Tuple[Optional[str], Optional[str], bool]: - username = ask_input(f"User for {netloc}: ") + username = ask_input(f"User for {netloc}: ") if self.prompting else None if not username: return None, None, False - auth = get_keyring_auth(netloc, username) - if auth and auth[0] is not None and auth[1] is not None: - return auth[0], auth[1], False + if self.use_keyring: + auth = self._get_keyring_auth(netloc, username) + if auth and auth[0] is not None and auth[1] is not None: + return auth[0], auth[1], False password = ask_password("Password: ") return username, password, True # Factored out to allow for easy patching in tests def _should_save_password_to_keyring(self) -> bool: - if get_keyring_provider() is None: + if ( + not self.prompting + or not self.use_keyring + or not self.keyring_provider.has_keyring + ): return False return ask("Save credentials to keyring [y/N]: ", ["y", "n"]) == "y" @@ -369,19 +478,22 @@ class MultiDomainBasicAuth(AuthBase): if resp.status_code != 401: return resp + username, password = None, None + + # Query the keyring for credentials: + if self.use_keyring: + username, password = self._get_new_credentials( + resp.url, + allow_netrc=False, + allow_keyring=True, + ) + # We are not able to prompt the user so simply return the response - if not self.prompting: + if not self.prompting and not username and not password: return resp parsed = urllib.parse.urlparse(resp.url) - # Query the keyring for credentials: - username, password = self._get_new_credentials( - resp.url, - allow_netrc=False, - allow_keyring=True, - ) - # Prompt the user for a new username and password save = False if not username and not password: @@ -402,7 +514,9 @@ class MultiDomainBasicAuth(AuthBase): # Consume content and release the original connection to allow our new # request to reuse the same one. - resp.content + # The result of the assignment isn't used, it's just needed to consume + # the content. + _ = resp.content resp.raw.release_conn() # Add our new username and password to the request @@ -431,9 +545,8 @@ class MultiDomainBasicAuth(AuthBase): def save_credentials(self, resp: Response, **kwargs: Any) -> None: """Response callback to save credentials on success.""" - keyring = get_keyring_provider() - assert not isinstance( - keyring, KeyRingNullProvider + assert ( + self.keyring_provider.has_keyring ), "should never reach here without keyring" creds = self._credentials_to_save @@ -441,6 +554,8 @@ class MultiDomainBasicAuth(AuthBase): if creds and resp.status_code < 400: try: logger.info("Saving credentials to keyring") - keyring.save_auth_info(creds.url, creds.username, creds.password) + self.keyring_provider.save_auth_info( + creds.url, creds.username, creds.password + ) except Exception: logger.exception("Failed to save credentials") diff --git a/.venv/Lib/site-packages/pip/_internal/network/cache.py b/.venv/Lib/site-packages/pip/_internal/network/cache.py index a81a2398..a4d13620 100644 --- a/.venv/Lib/site-packages/pip/_internal/network/cache.py +++ b/.venv/Lib/site-packages/pip/_internal/network/cache.py @@ -3,10 +3,11 @@ import os from contextlib import contextmanager -from typing import Generator, Optional +from datetime import datetime +from typing import BinaryIO, Generator, Optional, Union -from pip._vendor.cachecontrol.cache import BaseCache -from pip._vendor.cachecontrol.caches import FileCache +from pip._vendor.cachecontrol.cache import SeparateBodyBaseCache +from pip._vendor.cachecontrol.caches import SeparateBodyFileCache from pip._vendor.requests.models import Response from pip._internal.utils.filesystem import adjacent_tmp_file, replace @@ -28,7 +29,7 @@ def suppressed_cache_errors() -> Generator[None, None, None]: pass -class SafeFileCache(BaseCache): +class SafeFileCache(SeparateBodyBaseCache): """ A file based cache which is safe to use even when the target directory may not be accessible or writable. @@ -43,7 +44,7 @@ class SafeFileCache(BaseCache): # From cachecontrol.caches.file_cache.FileCache._fn, brought into our # class for backwards-compatibility and to avoid using a non-public # method. - hashed = FileCache.encode(name) + hashed = SeparateBodyFileCache.encode(name) parts = list(hashed[:5]) + [hashed] return os.path.join(self.directory, *parts) @@ -53,17 +54,33 @@ class SafeFileCache(BaseCache): with open(path, "rb") as f: return f.read() - def set(self, key: str, value: bytes, expires: Optional[int] = None) -> None: - path = self._get_cache_path(key) + def _write(self, path: str, data: bytes) -> None: with suppressed_cache_errors(): ensure_dir(os.path.dirname(path)) with adjacent_tmp_file(path) as f: - f.write(value) + f.write(data) replace(f.name, path) + def set( + self, key: str, value: bytes, expires: Union[int, datetime, None] = None + ) -> None: + path = self._get_cache_path(key) + self._write(path, value) + def delete(self, key: str) -> None: path = self._get_cache_path(key) with suppressed_cache_errors(): os.remove(path) + with suppressed_cache_errors(): + os.remove(path + ".body") + + def get_body(self, key: str) -> Optional[BinaryIO]: + path = self._get_cache_path(key) + ".body" + with suppressed_cache_errors(): + return open(path, "rb") + + def set_body(self, key: str, body: bytes) -> None: + path = self._get_cache_path(key) + ".body" + self._write(path, body) diff --git a/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py b/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py index 854a6fa1..82ec50d5 100644 --- a/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py +++ b/.venv/Lib/site-packages/pip/_internal/network/lazy_wheel.py @@ -6,7 +6,7 @@ from bisect import bisect_left, bisect_right from contextlib import contextmanager from tempfile import NamedTemporaryFile from typing import Any, Dict, Generator, List, Optional, Tuple -from zipfile import BadZipfile, ZipFile +from zipfile import BadZipFile, ZipFile from pip._vendor.packaging.utils import canonicalize_name from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response @@ -160,7 +160,7 @@ class LazyZipOverHTTP: # For read-only ZIP files, ZipFile only needs # methods read, seek, seekable and tell. ZipFile(self) # type: ignore - except BadZipfile: + except BadZipFile: pass else: break diff --git a/.venv/Lib/site-packages/pip/_internal/network/session.py b/.venv/Lib/site-packages/pip/_internal/network/session.py index e512ac78..887dc14e 100644 --- a/.venv/Lib/site-packages/pip/_internal/network/session.py +++ b/.venv/Lib/site-packages/pip/_internal/network/session.py @@ -316,7 +316,6 @@ class InsecureCacheControlAdapter(CacheControlAdapter): class PipSession(requests.Session): - timeout: Optional[int] = None def __init__( @@ -420,15 +419,17 @@ class PipSession(requests.Session): msg += f" (from {source})" logger.info(msg) - host_port = parse_netloc(host) - if host_port not in self.pip_trusted_origins: - self.pip_trusted_origins.append(host_port) + parsed_host, parsed_port = parse_netloc(host) + if parsed_host is None: + raise ValueError(f"Trusted host URL must include a host part: {host!r}") + if (parsed_host, parsed_port) not in self.pip_trusted_origins: + self.pip_trusted_origins.append((parsed_host, parsed_port)) self.mount( build_url_from_netloc(host, scheme="http") + "/", self._trusted_host_adapter ) self.mount(build_url_from_netloc(host) + "/", self._trusted_host_adapter) - if not host_port[1]: + if not parsed_port: self.mount( build_url_from_netloc(host, scheme="http") + ":", self._trusted_host_adapter, diff --git a/.venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py b/.venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py index 6621549b..37919322 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/build/build_tracker.py @@ -51,10 +51,22 @@ def get_build_tracker() -> Generator["BuildTracker", None, None]: yield tracker +class TrackerId(str): + """Uniquely identifying string provided to the build tracker.""" + + class BuildTracker: + """Ensure that an sdist cannot request itself as a setup requirement. + + When an sdist is prepared, it identifies its setup requirements in the + context of ``BuildTracker.track()``. If a requirement shows up recursively, this + raises an exception. + + This stops fork bombs embedded in malicious packages.""" + def __init__(self, root: str) -> None: self._root = root - self._entries: Set[InstallRequirement] = set() + self._entries: Dict[TrackerId, InstallRequirement] = {} logger.debug("Created build tracker: %s", self._root) def __enter__(self) -> "BuildTracker": @@ -69,16 +81,15 @@ class BuildTracker: ) -> None: self.cleanup() - def _entry_path(self, link: Link) -> str: - hashed = hashlib.sha224(link.url_without_fragment.encode()).hexdigest() + def _entry_path(self, key: TrackerId) -> str: + hashed = hashlib.sha224(key.encode()).hexdigest() return os.path.join(self._root, hashed) - def add(self, req: InstallRequirement) -> None: + def add(self, req: InstallRequirement, key: TrackerId) -> None: """Add an InstallRequirement to build tracking.""" - assert req.link # Get the file to write information about this requirement. - entry_path = self._entry_path(req.link) + entry_path = self._entry_path(key) # Try reading from the file. If it exists and can be read from, a build # is already in progress, so a LookupError is raised. @@ -92,33 +103,37 @@ class BuildTracker: raise LookupError(message) # If we're here, req should really not be building already. - assert req not in self._entries + assert key not in self._entries # Start tracking this requirement. with open(entry_path, "w", encoding="utf-8") as fp: fp.write(str(req)) - self._entries.add(req) + self._entries[key] = req logger.debug("Added %s to build tracker %r", req, self._root) - def remove(self, req: InstallRequirement) -> None: + def remove(self, req: InstallRequirement, key: TrackerId) -> None: """Remove an InstallRequirement from build tracking.""" - assert req.link - # Delete the created file and the corresponding entries. - os.unlink(self._entry_path(req.link)) - self._entries.remove(req) + # Delete the created file and the corresponding entry. + os.unlink(self._entry_path(key)) + del self._entries[key] logger.debug("Removed %s from build tracker %r", req, self._root) def cleanup(self) -> None: - for req in set(self._entries): - self.remove(req) + for key, req in list(self._entries.items()): + self.remove(req, key) logger.debug("Removed build tracker: %r", self._root) @contextlib.contextmanager - def track(self, req: InstallRequirement) -> Generator[None, None, None]: - self.add(req) + def track(self, req: InstallRequirement, key: str) -> Generator[None, None, None]: + """Ensure that `key` cannot install itself as a setup requirement. + + :raises LookupError: If `key` was already provided in a parent invocation of + the context introduced by this method.""" + tracker_id = TrackerId(key) + self.add(req, tracker_id) yield - self.remove(req) + self.remove(req, tracker_id) diff --git a/.venv/Lib/site-packages/pip/_internal/operations/check.py b/.venv/Lib/site-packages/pip/_internal/operations/check.py index e3bce69b..1b7fd7ab 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/check.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/check.py @@ -5,12 +5,15 @@ import logging from typing import Callable, Dict, List, NamedTuple, Optional, Set, Tuple from pip._vendor.packaging.requirements import Requirement +from pip._vendor.packaging.specifiers import LegacySpecifier from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.version import LegacyVersion from pip._internal.distributions import make_distribution_for_install_requirement from pip._internal.metadata import get_default_environment from pip._internal.metadata.base import DistributionVersion from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.deprecation import deprecated logger = logging.getLogger(__name__) @@ -57,6 +60,8 @@ def check_package_set( package name and returns a boolean. """ + warn_legacy_versions_and_specifiers(package_set) + missing = {} conflicting = {} @@ -147,3 +152,36 @@ def _create_whitelist( break return packages_affected + + +def warn_legacy_versions_and_specifiers(package_set: PackageSet) -> None: + for project_name, package_details in package_set.items(): + if isinstance(package_details.version, LegacyVersion): + deprecated( + reason=( + f"{project_name} {package_details.version} " + f"has a non-standard version number." + ), + replacement=( + f"to upgrade to a newer version of {project_name} " + f"or contact the author to suggest that they " + f"release a version with a conforming version number" + ), + issue=12063, + gone_in="24.0", + ) + for dep in package_details.dependencies: + if any(isinstance(spec, LegacySpecifier) for spec in dep.specifier): + deprecated( + reason=( + f"{project_name} {package_details.version} " + f"has a non-standard dependency specifier {dep}." + ), + replacement=( + f"to upgrade to a newer version of {project_name} " + f"or contact the author to suggest that they " + f"release a version with a conforming dependency specifiers" + ), + issue=12063, + gone_in="24.0", + ) diff --git a/.venv/Lib/site-packages/pip/_internal/operations/freeze.py b/.venv/Lib/site-packages/pip/_internal/operations/freeze.py index 930d4c60..35445684 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/freeze.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/freeze.py @@ -145,9 +145,10 @@ def freeze( def _format_as_name_version(dist: BaseDistribution) -> str: - if isinstance(dist.version, Version): - return f"{dist.raw_name}=={dist.version}" - return f"{dist.raw_name}==={dist.version}" + dist_version = dist.version + if isinstance(dist_version, Version): + return f"{dist.raw_name}=={dist_version}" + return f"{dist.raw_name}==={dist_version}" def _get_editable_info(dist: BaseDistribution) -> _EditableInfo: diff --git a/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py b/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py index bb548cdc..bebe24e6 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/install/editable_legacy.py @@ -1,7 +1,7 @@ """Legacy editable installation process, i.e. `setup.py develop`. """ import logging -from typing import List, Optional, Sequence +from typing import Optional, Sequence from pip._internal.build_env import BuildEnvironment from pip._internal.utils.logging import indent_log @@ -12,7 +12,7 @@ logger = logging.getLogger(__name__) def install_editable( - install_options: List[str], + *, global_options: Sequence[str], prefix: Optional[str], home: Optional[str], @@ -31,7 +31,6 @@ def install_editable( args = make_setuptools_develop_args( setup_py_path, global_options=global_options, - install_options=install_options, no_user_config=isolated, prefix=prefix, home=home, diff --git a/.venv/Lib/site-packages/pip/_internal/operations/install/legacy.py b/.venv/Lib/site-packages/pip/_internal/operations/install/legacy.py deleted file mode 100644 index 290967dd..00000000 --- a/.venv/Lib/site-packages/pip/_internal/operations/install/legacy.py +++ /dev/null @@ -1,120 +0,0 @@ -"""Legacy installation process, i.e. `setup.py install`. -""" - -import logging -import os -from typing import List, Optional, Sequence - -from pip._internal.build_env import BuildEnvironment -from pip._internal.exceptions import InstallationError, LegacyInstallFailure -from pip._internal.locations.base import change_root -from pip._internal.models.scheme import Scheme -from pip._internal.utils.misc import ensure_dir -from pip._internal.utils.setuptools_build import make_setuptools_install_args -from pip._internal.utils.subprocess import runner_with_spinner_message -from pip._internal.utils.temp_dir import TempDirectory - -logger = logging.getLogger(__name__) - - -def write_installed_files_from_setuptools_record( - record_lines: List[str], - root: Optional[str], - req_description: str, -) -> None: - def prepend_root(path: str) -> str: - if root is None or not os.path.isabs(path): - return path - else: - return change_root(root, path) - - for line in record_lines: - directory = os.path.dirname(line) - if directory.endswith(".egg-info"): - egg_info_dir = prepend_root(directory) - break - else: - message = ( - "{} did not indicate that it installed an " - ".egg-info directory. Only setup.py projects " - "generating .egg-info directories are supported." - ).format(req_description) - raise InstallationError(message) - - new_lines = [] - for line in record_lines: - filename = line.strip() - if os.path.isdir(filename): - filename += os.path.sep - new_lines.append(os.path.relpath(prepend_root(filename), egg_info_dir)) - new_lines.sort() - ensure_dir(egg_info_dir) - inst_files_path = os.path.join(egg_info_dir, "installed-files.txt") - with open(inst_files_path, "w") as f: - f.write("\n".join(new_lines) + "\n") - - -def install( - install_options: List[str], - global_options: Sequence[str], - root: Optional[str], - home: Optional[str], - prefix: Optional[str], - use_user_site: bool, - pycompile: bool, - scheme: Scheme, - setup_py_path: str, - isolated: bool, - req_name: str, - build_env: BuildEnvironment, - unpacked_source_directory: str, - req_description: str, -) -> bool: - - header_dir = scheme.headers - - with TempDirectory(kind="record") as temp_dir: - try: - record_filename = os.path.join(temp_dir.path, "install-record.txt") - install_args = make_setuptools_install_args( - setup_py_path, - global_options=global_options, - install_options=install_options, - record_filename=record_filename, - root=root, - prefix=prefix, - header_dir=header_dir, - home=home, - use_user_site=use_user_site, - no_user_config=isolated, - pycompile=pycompile, - ) - - runner = runner_with_spinner_message( - f"Running setup.py install for {req_name}" - ) - with build_env: - runner( - cmd=install_args, - cwd=unpacked_source_directory, - ) - - if not os.path.exists(record_filename): - logger.debug("Record file %s not found", record_filename) - # Signal to the caller that we didn't install the new package - return False - - except Exception as e: - # Signal to the caller that we didn't install the new package - raise LegacyInstallFailure(package_details=req_name) from e - - # At this point, we have successfully installed the requirement. - - # We intentionally do not use any encoding to read the file because - # setuptools writes the file using distutils.file_util.write_file, - # which does not specify an encoding. - with open(record_filename) as f: - record_lines = f.read().splitlines() - - write_installed_files_from_setuptools_record(record_lines, root, req_description) - return True diff --git a/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py b/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py index c7994139..58a77305 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/install/wheel.py @@ -143,16 +143,18 @@ def message_about_scripts_not_on_PATH(scripts: Sequence[str]) -> Optional[str]: # We don't want to warn for directories that are on PATH. not_warn_dirs = [ - os.path.normcase(i).rstrip(os.sep) + os.path.normcase(os.path.normpath(i)).rstrip(os.sep) for i in os.environ.get("PATH", "").split(os.pathsep) ] # If an executable sits with sys.executable, we don't warn for it. # This covers the case of venv invocations without activating the venv. - not_warn_dirs.append(os.path.normcase(os.path.dirname(sys.executable))) + not_warn_dirs.append( + os.path.normcase(os.path.normpath(os.path.dirname(sys.executable))) + ) warn_for: Dict[str, Set[str]] = { parent_dir: scripts for parent_dir, scripts in grouped_by_dir.items() - if os.path.normcase(parent_dir) not in not_warn_dirs + if os.path.normcase(os.path.normpath(parent_dir)) not in not_warn_dirs } if not warn_for: return None @@ -265,9 +267,9 @@ def get_csv_rows_for_installed( path = _fs_to_record_path(f, lib_dir) digest, length = rehash(f) installed_rows.append((path, digest, length)) - for installed_record_path in installed.values(): - installed_rows.append((installed_record_path, "", "")) - return installed_rows + return installed_rows + [ + (installed_record_path, "", "") for installed_record_path in installed.values() + ] def get_console_script_specs(console: Dict[str, str]) -> List[str]: diff --git a/.venv/Lib/site-packages/pip/_internal/operations/prepare.py b/.venv/Lib/site-packages/pip/_internal/operations/prepare.py index 4bf414cb..488e7635 100644 --- a/.venv/Lib/site-packages/pip/_internal/operations/prepare.py +++ b/.venv/Lib/site-packages/pip/_internal/operations/prepare.py @@ -4,10 +4,10 @@ # The following comment should be removed at some point in the future. # mypy: strict-optional=False -import logging import mimetypes import os import shutil +from pathlib import Path from typing import Dict, Iterable, List, Optional from pip._vendor.packaging.utils import canonicalize_name @@ -21,7 +21,6 @@ from pip._internal.exceptions import ( InstallationError, MetadataInconsistent, NetworkConnectionError, - PreviousBuildDirError, VcsHashUnsupported, ) from pip._internal.index.package_finder import PackageFinder @@ -37,6 +36,7 @@ from pip._internal.network.lazy_wheel import ( from pip._internal.network.session import PipSession from pip._internal.operations.build.build_tracker import BuildTracker from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils._log import getLogger from pip._internal.utils.direct_url_helpers import ( direct_url_for_editable, direct_url_from_link, @@ -47,13 +47,13 @@ from pip._internal.utils.misc import ( display_path, hash_file, hide_url, - is_installable_dir, + redact_auth_from_requirement, ) from pip._internal.utils.temp_dir import TempDirectory from pip._internal.utils.unpacking import unpack_file from pip._internal.vcs import vcs -logger = logging.getLogger(__name__) +logger = getLogger(__name__) def _get_prepared_distribution( @@ -65,10 +65,12 @@ def _get_prepared_distribution( ) -> BaseDistribution: """Prepare a distribution for installation.""" abstract_dist = make_distribution_for_install_requirement(req) - with build_tracker.track(req): - abstract_dist.prepare_distribution_metadata( - finder, build_isolation, check_build_deps - ) + tracker_id = abstract_dist.build_tracker_id + if tracker_id is not None: + with build_tracker.track(req, tracker_id): + abstract_dist.prepare_distribution_metadata( + finder, build_isolation, check_build_deps + ) return abstract_dist.get_metadata_distribution() @@ -179,7 +181,10 @@ def unpack_url( def _check_download_dir( - link: Link, download_dir: str, hashes: Optional[Hashes] + link: Link, + download_dir: str, + hashes: Optional[Hashes], + warn_on_hash_mismatch: bool = True, ) -> Optional[str]: """Check download_dir for previously downloaded file with correct hash If a correct file is found return its path else None @@ -195,10 +200,11 @@ def _check_download_dir( try: hashes.check_against_path(download_path) except HashMismatch: - logger.warning( - "Previously-downloaded file %s has bad hash. Re-downloading.", - download_path, - ) + if warn_on_hash_mismatch: + logger.warning( + "Previously-downloaded file %s has bad hash. Re-downloading.", + download_path, + ) os.unlink(download_path) return None return download_path @@ -222,6 +228,7 @@ class RequirementPreparer: use_user_site: bool, lazy_wheel: bool, verbosity: int, + legacy_resolver: bool, ) -> None: super().__init__() @@ -255,6 +262,9 @@ class RequirementPreparer: # How verbose should underlying tooling be? self.verbosity = verbosity + # Are we using the legacy resolver? + self.legacy_resolver = legacy_resolver + # Memoized downloaded files, as mapping of url: path. self._downloaded: Dict[str, str] = {} @@ -263,18 +273,28 @@ class RequirementPreparer: def _log_preparing_link(self, req: InstallRequirement) -> None: """Provide context for the requirement being prepared.""" - if req.link.is_file and not req.original_link_is_in_wheel_cache: + if req.link.is_file and not req.is_wheel_from_cache: message = "Processing %s" information = str(display_path(req.link.file_path)) else: message = "Collecting %s" - information = str(req.req or req) + information = redact_auth_from_requirement(req.req) if req.req else str(req) + + # If we used req.req, inject requirement source if available (this + # would already be included if we used req directly) + if req.req and req.comes_from: + if isinstance(req.comes_from, str): + comes_from: Optional[str] = req.comes_from + else: + comes_from = req.comes_from.from_path() + if comes_from: + information += f" (from {comes_from})" if (message, information) != self._previous_requirement_header: self._previous_requirement_header = (message, information) logger.info(message, information) - if req.original_link_is_in_wheel_cache: + if req.is_wheel_from_cache: with indent_log(): logger.info("Using cached %s", req.link.filename) @@ -299,21 +319,7 @@ class RequirementPreparer: autodelete=True, parallel_builds=parallel_builds, ) - - # If a checkout exists, it's unwise to keep going. version - # inconsistencies are logged later, but do not fail the - # installation. - # FIXME: this won't upgrade when there's an existing - # package unpacked in `req.source_dir` - # TODO: this check is now probably dead code - if is_installable_dir(req.source_dir): - raise PreviousBuildDirError( - "pip can't proceed with requirements '{}' due to a" - "pre-existing build directory ({}). This is likely " - "due to a previous installation that failed . pip is " - "being responsible and not assuming it can delete this. " - "Please delete it and try again.".format(req, req.source_dir) - ) + req.ensure_pristine_source_checkout() def _get_linked_req_hashes(self, req: InstallRequirement) -> Hashes: # By the time this is called, the requirement's link should have @@ -338,7 +344,7 @@ class RequirementPreparer: # a surprising hash mismatch in the future. # file:/// URLs aren't pinnable, so don't complain about them # not being pinned. - if req.original_link is None and not req.is_pinned: + if not req.is_direct and not req.is_pinned: raise HashUnpinned() # If known-good hashes are missing for this requirement, @@ -351,6 +357,11 @@ class RequirementPreparer: self, req: InstallRequirement, ) -> Optional[BaseDistribution]: + if self.legacy_resolver: + logger.debug( + "Metadata-only fetching is not used in the legacy resolver", + ) + return None if self.require_hashes: logger.debug( "Metadata-only fetching is not used as hash checking is required", @@ -371,7 +382,7 @@ class RequirementPreparer: if metadata_link is None: return None assert req.req is not None - logger.info( + logger.verbose( "Obtaining dependency information for %s from %s", req.req, metadata_link, @@ -396,7 +407,7 @@ class RequirementPreparer: # NB: raw_name will fall back to the name from the install requirement if # the Name: field is not present, but it's noted in the raw_name docstring # that that should NEVER happen anyway. - if metadata_dist.raw_name != req.req.name: + if canonicalize_name(metadata_dist.raw_name) != canonicalize_name(req.req.name): raise MetadataInconsistent( req, "Name", req.req.name, metadata_dist.raw_name ) @@ -456,7 +467,19 @@ class RequirementPreparer: for link, (filepath, _) in batch_download: logger.debug("Downloading link %s to %s", link, filepath) req = links_to_fully_download[link] + # Record the downloaded file path so wheel reqs can extract a Distribution + # in .get_dist(). req.local_file_path = filepath + # Record that the file is downloaded so we don't do it again in + # _prepare_linked_requirement(). + self._downloaded[req.link.url] = filepath + + # If this is an sdist, we need to unpack it after downloading, but the + # .source_dir won't be set up until we are in _prepare_linked_requirement(). + # Add the downloaded archive to the install requirement to unpack after + # preparing the source dir. + if not req.is_wheel: + req.needs_unpacked_archive(Path(filepath)) # This step is necessary to ensure all lazy wheels are processed # successfully by the 'download', 'wheel', and 'install' commands. @@ -475,7 +498,18 @@ class RequirementPreparer: file_path = None if self.download_dir is not None and req.link.is_wheel: hashes = self._get_linked_req_hashes(req) - file_path = _check_download_dir(req.link, self.download_dir, hashes) + file_path = _check_download_dir( + req.link, + self.download_dir, + hashes, + # When a locally built wheel has been found in cache, we don't warn + # about re-downloading when the already downloaded wheel hash does + # not match. This is because the hash must be checked against the + # original link, not the cached link. It that case the already + # downloaded file will be removed and re-fetched from cache (which + # implies a hash check against the cache entry's origin.json). + warn_on_hash_mismatch=not req.is_wheel_from_cache, + ) if file_path is not None: # The file is already available, so mark it as downloaded @@ -526,9 +560,35 @@ class RequirementPreparer: assert req.link link = req.link - self._ensure_link_req_src_dir(req, parallel_builds) hashes = self._get_linked_req_hashes(req) + if hashes and req.is_wheel_from_cache: + assert req.download_info is not None + assert link.is_wheel + assert link.is_file + # We need to verify hashes, and we have found the requirement in the cache + # of locally built wheels. + if ( + isinstance(req.download_info.info, ArchiveInfo) + and req.download_info.info.hashes + and hashes.has_one_of(req.download_info.info.hashes) + ): + # At this point we know the requirement was built from a hashable source + # artifact, and we verified that the cache entry's hash of the original + # artifact matches one of the hashes we expect. We don't verify hashes + # against the cached wheel, because the wheel is not the original. + hashes = None + else: + logger.warning( + "The hashes of the source archive found in cache entry " + "don't match, ignoring cached built wheel " + "and re-downloading source." + ) + req.link = req.cached_wheel_source_link + link = req.link + + self._ensure_link_req_src_dir(req, parallel_builds) + if link.is_existing_dir(): local_file = None elif link.url not in self._downloaded: @@ -561,12 +621,15 @@ class RequirementPreparer: # Make sure we have a hash in download_info. If we got it as part of the # URL, it will have been verified and we can rely on it. Otherwise we # compute it from the downloaded file. + # FIXME: https://github.com/pypa/pip/issues/11943 if ( isinstance(req.download_info.info, ArchiveInfo) - and not req.download_info.info.hash + and not req.download_info.info.hashes and local_file ): hash = hash_file(local_file.path)[0].hexdigest() + # We populate info.hash for backward compatibility. + # This will automatically populate info.hashes. req.download_info.info.hash = f"sha256={hash}" # For use in later processing, diff --git a/.venv/Lib/site-packages/pip/_internal/pyproject.py b/.venv/Lib/site-packages/pip/_internal/pyproject.py index 1de9f0fd..eb8e12b2 100644 --- a/.venv/Lib/site-packages/pip/_internal/pyproject.py +++ b/.venv/Lib/site-packages/pip/_internal/pyproject.py @@ -91,14 +91,19 @@ def load_pyproject_toml( # If we haven't worked out whether to use PEP 517 yet, # and the user hasn't explicitly stated a preference, # we do so if the project has a pyproject.toml file - # or if we cannot import setuptools. + # or if we cannot import setuptools or wheels. - # We fallback to PEP 517 when without setuptools, + # We fallback to PEP 517 when without setuptools or without the wheel package, # so setuptools can be installed as a default build backend. # For more info see: # https://discuss.python.org/t/pip-without-setuptools-could-the-experience-be-improved/11810/9 + # https://github.com/pypa/pip/issues/8559 elif use_pep517 is None: - use_pep517 = has_pyproject or not importlib.util.find_spec("setuptools") + use_pep517 = ( + has_pyproject + or not importlib.util.find_spec("setuptools") + or not importlib.util.find_spec("wheel") + ) # At this point, we know whether we're going to use PEP 517. assert use_pep517 is not None diff --git a/.venv/Lib/site-packages/pip/_internal/req/__init__.py b/.venv/Lib/site-packages/pip/_internal/req/__init__.py index 8d563596..16de903a 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/__init__.py +++ b/.venv/Lib/site-packages/pip/_internal/req/__init__.py @@ -36,7 +36,6 @@ def _validate_requirements( def install_given_reqs( requirements: List[InstallRequirement], - install_options: List[str], global_options: Sequence[str], root: Optional[str], home: Optional[str], @@ -71,7 +70,6 @@ def install_given_reqs( try: requirement.install( - install_options, global_options, root=root, home=home, diff --git a/.venv/Lib/site-packages/pip/_internal/req/constructors.py b/.venv/Lib/site-packages/pip/_internal/req/constructors.py index dea7c3b0..b52c9a45 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/constructors.py +++ b/.venv/Lib/site-packages/pip/_internal/req/constructors.py @@ -8,10 +8,11 @@ These are meant to be used elsewhere within pip to create instances of InstallRequirement. """ +import copy import logging import os import re -from typing import Any, Dict, Optional, Set, Tuple, Union +from typing import Collection, Dict, List, Optional, Set, Tuple, Union from pip._vendor.packaging.markers import Marker from pip._vendor.packaging.requirements import InvalidRequirement, Requirement @@ -57,6 +58,31 @@ def convert_extras(extras: Optional[str]) -> Set[str]: return get_requirement("placeholder" + extras.lower()).extras +def _set_requirement_extras(req: Requirement, new_extras: Set[str]) -> Requirement: + """ + Returns a new requirement based on the given one, with the supplied extras. If the + given requirement already has extras those are replaced (or dropped if no new extras + are given). + """ + match: Optional[re.Match[str]] = re.fullmatch( + # see https://peps.python.org/pep-0508/#complete-grammar + r"([\w\t .-]+)(\[[^\]]*\])?(.*)", + str(req), + flags=re.ASCII, + ) + # ireq.req is a valid requirement so the regex should always match + assert ( + match is not None + ), f"regex match on requirement {req} failed, this should never happen" + pre: Optional[str] = match.group(1) + post: Optional[str] = match.group(3) + assert ( + pre is not None and post is not None + ), f"regex group selection for requirement {req} failed, this should never happen" + extras: str = "[%s]" % ",".join(sorted(new_extras)) if new_extras else "" + return Requirement(f"{pre}{extras}{post}") + + def parse_editable(editable_req: str) -> Tuple[Optional[str], str, Set[str]]: """Parses an editable requirement into: - a requirement name @@ -201,15 +227,16 @@ def parse_req_from_editable(editable_req: str) -> RequirementParts: def install_req_from_editable( editable_req: str, comes_from: Optional[Union[InstallRequirement, str]] = None, + *, use_pep517: Optional[bool] = None, isolated: bool = False, - options: Optional[Dict[str, Any]] = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, user_supplied: bool = False, permit_editable_wheels: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: - parts = parse_req_from_editable(editable_req) return InstallRequirement( @@ -222,9 +249,8 @@ def install_req_from_editable( constraint=constraint, use_pep517=use_pep517, isolated=isolated, - install_options=options.get("install_options", []) if options else [], - global_options=options.get("global_options", []) if options else [], - hash_options=options.get("hashes", {}) if options else {}, + global_options=global_options, + hash_options=hash_options, config_settings=config_settings, extras=parts.extras, ) @@ -376,13 +402,15 @@ def parse_req_from_line(name: str, line_source: Optional[str]) -> RequirementPar def install_req_from_line( name: str, comes_from: Optional[Union[str, InstallRequirement]] = None, + *, use_pep517: Optional[bool] = None, isolated: bool = False, - options: Optional[Dict[str, Any]] = None, + global_options: Optional[List[str]] = None, + hash_options: Optional[Dict[str, List[str]]] = None, constraint: bool = False, line_source: Optional[str] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: """Creates an InstallRequirement from a name, which might be a requirement, directory containing 'setup.py', filename, or URL. @@ -399,9 +427,8 @@ def install_req_from_line( markers=parts.markers, use_pep517=use_pep517, isolated=isolated, - install_options=options.get("install_options", []) if options else [], - global_options=options.get("global_options", []) if options else [], - hash_options=options.get("hashes", {}) if options else {}, + global_options=global_options, + hash_options=hash_options, config_settings=config_settings, constraint=constraint, extras=parts.extras, @@ -415,7 +442,6 @@ def install_req_from_req_string( isolated: bool = False, use_pep517: Optional[bool] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, ) -> InstallRequirement: try: req = get_requirement(req_string) @@ -445,7 +471,6 @@ def install_req_from_req_string( isolated=isolated, use_pep517=use_pep517, user_supplied=user_supplied, - config_settings=config_settings, ) @@ -454,7 +479,7 @@ def install_req_from_parsed_requirement( isolated: bool = False, use_pep517: Optional[bool] = None, user_supplied: bool = False, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> InstallRequirement: if parsed_req.is_editable: req = install_req_from_editable( @@ -473,7 +498,14 @@ def install_req_from_parsed_requirement( comes_from=parsed_req.comes_from, use_pep517=use_pep517, isolated=isolated, - options=parsed_req.options, + global_options=( + parsed_req.options.get("global_options", []) + if parsed_req.options + else [] + ), + hash_options=( + parsed_req.options.get("hashes", {}) if parsed_req.options else {} + ), constraint=parsed_req.constraint, line_source=parsed_req.line_source, user_supplied=user_supplied, @@ -493,9 +525,52 @@ def install_req_from_link_and_ireq( markers=ireq.markers, use_pep517=ireq.use_pep517, isolated=ireq.isolated, - install_options=ireq.install_options, global_options=ireq.global_options, hash_options=ireq.hash_options, config_settings=ireq.config_settings, user_supplied=ireq.user_supplied, ) + + +def install_req_drop_extras(ireq: InstallRequirement) -> InstallRequirement: + """ + Creates a new InstallationRequirement using the given template but without + any extras. Sets the original requirement as the new one's parent + (comes_from). + """ + return InstallRequirement( + req=( + _set_requirement_extras(ireq.req, set()) if ireq.req is not None else None + ), + comes_from=ireq, + editable=ireq.editable, + link=ireq.link, + markers=ireq.markers, + use_pep517=ireq.use_pep517, + isolated=ireq.isolated, + global_options=ireq.global_options, + hash_options=ireq.hash_options, + constraint=ireq.constraint, + extras=[], + config_settings=ireq.config_settings, + user_supplied=ireq.user_supplied, + permit_editable_wheels=ireq.permit_editable_wheels, + ) + + +def install_req_extend_extras( + ireq: InstallRequirement, + extras: Collection[str], +) -> InstallRequirement: + """ + Returns a copy of an installation requirement with some additional extras. + Makes a shallow copy of the ireq object. + """ + result = copy.copy(ireq) + result.extras = {*ireq.extras, *extras} + result.req = ( + _set_requirement_extras(ireq.req, result.extras) + if ireq.req is not None + else None + ) + return result diff --git a/.venv/Lib/site-packages/pip/_internal/req/req_file.py b/.venv/Lib/site-packages/pip/_internal/req/req_file.py index 11ec699a..f717c1cc 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/req_file.py +++ b/.venv/Lib/site-packages/pip/_internal/req/req_file.py @@ -2,6 +2,7 @@ Requirements file parsing """ +import logging import optparse import os import re @@ -69,14 +70,16 @@ SUPPORTED_OPTIONS: List[Callable[..., optparse.Option]] = [ # options to be passed to requirements SUPPORTED_OPTIONS_REQ: List[Callable[..., optparse.Option]] = [ - cmdoptions.install_options, cmdoptions.global_options, cmdoptions.hash, + cmdoptions.config_settings, ] # the 'dest' string values SUPPORTED_OPTIONS_REQ_DEST = [str(o().dest) for o in SUPPORTED_OPTIONS_REQ] +logger = logging.getLogger(__name__) + class ParsedRequirement: def __init__( @@ -166,7 +169,6 @@ def handle_requirement_line( line: ParsedLine, options: Optional[optparse.Values] = None, ) -> ParsedRequirement: - # preserve for the nested code path line_comes_from = "{} {} (line {})".format( "-c" if line.constraint else "-r", @@ -211,6 +213,12 @@ def handle_option_line( options: Optional[optparse.Values] = None, session: Optional[PipSession] = None, ) -> None: + if opts.hashes: + logger.warning( + "%s line %s has --hash but no requirement, and will be ignored.", + filename, + lineno, + ) if options: # percolate options upward diff --git a/.venv/Lib/site-packages/pip/_internal/req/req_install.py b/.venv/Lib/site-packages/pip/_internal/req/req_install.py index bb38ec09..e556be2b 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/req_install.py +++ b/.venv/Lib/site-packages/pip/_internal/req/req_install.py @@ -1,6 +1,3 @@ -# The following comment should be removed at some point in the future. -# mypy: strict-optional=False - import functools import logging import os @@ -8,8 +5,8 @@ import shutil import sys import uuid import zipfile -from enum import Enum from optparse import Values +from pathlib import Path from typing import Any, Collection, Dict, Iterable, List, Optional, Sequence, Union from pip._vendor.packaging.markers import Marker @@ -21,7 +18,7 @@ from pip._vendor.packaging.version import parse as parse_version from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._internal.build_env import BuildEnvironment, NoOpBuildEnvironment -from pip._internal.exceptions import InstallationError, LegacyInstallFailure +from pip._internal.exceptions import InstallationError, PreviousBuildDirError from pip._internal.locations import get_scheme from pip._internal.metadata import ( BaseDistribution, @@ -40,15 +37,10 @@ from pip._internal.operations.build.metadata_legacy import ( from pip._internal.operations.install.editable_legacy import ( install_editable as install_editable_legacy, ) -from pip._internal.operations.install.legacy import install as install_legacy from pip._internal.operations.install.wheel import install_wheel from pip._internal.pyproject import load_pyproject_toml, make_pyproject_path from pip._internal.req.req_uninstall import UninstallPathSet -from pip._internal.utils.deprecation import LegacyInstallReason, deprecated -from pip._internal.utils.direct_url_helpers import ( - direct_url_for_editable, - direct_url_from_link, -) +from pip._internal.utils.deprecation import deprecated from pip._internal.utils.hashes import Hashes from pip._internal.utils.misc import ( ConfiguredBuildBackendHookCaller, @@ -56,11 +48,14 @@ from pip._internal.utils.misc import ( backup_dir, display_path, hide_url, + is_installable_dir, + redact_auth_from_requirement, redact_auth_from_url, ) from pip._internal.utils.packaging import safe_extra from pip._internal.utils.subprocess import runner_with_spinner_message from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds +from pip._internal.utils.unpacking import unpack_file from pip._internal.utils.virtualenv import running_under_virtualenv from pip._internal.vcs import vcs @@ -83,10 +78,10 @@ class InstallRequirement: markers: Optional[Marker] = None, use_pep517: Optional[bool] = None, isolated: bool = False, - install_options: Optional[List[str]] = None, + *, global_options: Optional[List[str]] = None, hash_options: Optional[Dict[str, List[str]]] = None, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, constraint: bool = False, extras: Collection[str] = (), user_supplied: bool = False, @@ -98,7 +93,6 @@ class InstallRequirement: self.constraint = constraint self.editable = editable self.permit_editable_wheels = permit_editable_wheels - self.legacy_install_reason: Optional[LegacyInstallReason] = None # source_dir is the local directory where the linked requirement is # located, or unpacked. In case unpacking is needed, creating and @@ -111,11 +105,17 @@ class InstallRequirement: if link.is_file: self.source_dir = os.path.normpath(os.path.abspath(link.file_path)) + # original_link is the direct URL that was provided by the user for the + # requirement, either directly or via a constraints file. if link is None and req and req.url: # PEP 508 URL requirement link = Link(req.url) self.link = self.original_link = link - self.original_link_is_in_wheel_cache = False + + # When this InstallRequirement is a wheel obtained from the cache of locally + # built wheels, this is the source link corresponding to the cache entry, which + # was used to download and build the cached wheel. + self.cached_wheel_source_link: Optional[Link] = None # Information about the location of the artifact that was downloaded . This # property is guaranteed to be set in resolver results. @@ -129,7 +129,7 @@ class InstallRequirement: if extras: self.extras = extras elif req: - self.extras = {safe_extra(extra) for extra in req.extras} + self.extras = req.extras else: self.extras = set() if markers is None and req: @@ -146,7 +146,6 @@ class InstallRequirement: # Set to True after successful installation self.install_succeeded: Optional[bool] = None # Supplied options - self.install_options = install_options if install_options else [] self.global_options = global_options if global_options else [] self.hash_options = hash_options if hash_options else {} self.config_settings = config_settings @@ -185,9 +184,12 @@ class InstallRequirement: # This requirement needs more preparation before it can be built self.needs_more_preparation = False + # This requirement needs to be unpacked before it can be installed. + self._archive_source: Optional[Path] = None + def __str__(self) -> str: if self.req: - s = str(self.req) + s = redact_auth_from_requirement(self.req) if self.link: s += " from {}".format(redact_auth_from_url(self.link.url)) elif self.link: @@ -246,15 +248,22 @@ class InstallRequirement: @property def specifier(self) -> SpecifierSet: + assert self.req is not None return self.req.specifier + @property + def is_direct(self) -> bool: + """Whether this requirement was specified as a direct URL.""" + return self.original_link is not None + @property def is_pinned(self) -> bool: """Return whether I am pinned to an exact version. For example, some-package==1.2 is pinned; some-package>1.2 is not. """ - specifiers = self.specifier + assert self.req is not None + specifiers = self.req.specifier return len(specifiers) == 1 and next(iter(specifiers)).operator in {"==", "==="} def match_markers(self, extras_requested: Optional[Iterable[str]] = None) -> bool: @@ -264,7 +273,12 @@ class InstallRequirement: extras_requested = ("",) if self.markers is not None: return any( - self.markers.evaluate({"extra": extra}) for extra in extras_requested + self.markers.evaluate({"extra": extra}) + # TODO: Remove these two variants when packaging is upgraded to + # support the marker comparison logic specified in PEP 685. + or self.markers.evaluate({"extra": safe_extra(extra)}) + or self.markers.evaluate({"extra": canonicalize_name(extra)}) + for extra in extras_requested ) else: return True @@ -295,8 +309,14 @@ class InstallRequirement: """ good_hashes = self.hash_options.copy() - link = self.link if trust_internet else self.original_link + if trust_internet: + link = self.link + elif self.is_direct and self.user_supplied: + link = self.original_link + else: + link = None if link and link.hash: + assert link.hash_name is not None good_hashes.setdefault(link.hash_name, []).append(link.hash) return Hashes(good_hashes) @@ -306,6 +326,7 @@ class InstallRequirement: return None s = str(self.req) if self.comes_from: + comes_from: Optional[str] if isinstance(self.comes_from, str): comes_from = self.comes_from else: @@ -337,7 +358,7 @@ class InstallRequirement: # When parallel builds are enabled, add a UUID to the build directory # name so multiple builds do not interfere with each other. - dir_name: str = canonicalize_name(self.name) + dir_name: str = canonicalize_name(self.req.name) if parallel_builds: dir_name = f"{dir_name}_{uuid.uuid4().hex}" @@ -380,6 +401,7 @@ class InstallRequirement: ) def warn_on_mismatching_name(self) -> None: + assert self.req is not None metadata_name = canonicalize_name(self.metadata["Name"]) if canonicalize_name(self.req.name) == metadata_name: # Everything is fine. @@ -440,9 +462,16 @@ class InstallRequirement: return False return self.link.is_wheel + @property + def is_wheel_from_cache(self) -> bool: + # When True, it means that this InstallRequirement is a local wheel file in the + # cache of locally built wheels. + return self.cached_wheel_source_link is not None + # Things valid for sdists @property def unpacked_source_directory(self) -> str: + assert self.source_dir, f"No source dir for {self}" return os.path.join( self.source_dir, self.link and self.link.subdirectory_fragment or "" ) @@ -479,6 +508,15 @@ class InstallRequirement: ) if pyproject_toml_data is None: + if self.config_settings: + deprecated( + reason=f"Config settings are ignored for project {self}.", + replacement=( + "to use --use-pep517 or add a " + "pyproject.toml file to the project" + ), + gone_in="24.0", + ) self.use_pep517 = False return @@ -520,7 +558,7 @@ class InstallRequirement: Under PEP 517 and PEP 660, call the backend hook to prepare the metadata. Under legacy processing, call setup.py egg-info. """ - assert self.source_dir + assert self.source_dir, f"No source dir for {self}" details = self.name or f"from {self.link}" if self.use_pep517: @@ -569,8 +607,10 @@ class InstallRequirement: if self.metadata_directory: return get_directory_distribution(self.metadata_directory) elif self.local_file_path and self.is_wheel: + assert self.req is not None return get_wheel_distribution( - FilesystemWheel(self.local_file_path), canonicalize_name(self.name) + FilesystemWheel(self.local_file_path), + canonicalize_name(self.req.name), ) raise AssertionError( f"InstallRequirement {self} has no metadata directory and no wheel: " @@ -578,9 +618,9 @@ class InstallRequirement: ) def assert_source_matches_version(self) -> None: - assert self.source_dir + assert self.source_dir, f"No source dir for {self}" version = self.metadata["version"] - if self.req.specifier and version not in self.req.specifier: + if self.req and self.req.specifier and version not in self.req.specifier: logger.warning( "Requested %s, but installing version %s", self, @@ -617,6 +657,27 @@ class InstallRequirement: parallel_builds=parallel_builds, ) + def needs_unpacked_archive(self, archive_source: Path) -> None: + assert self._archive_source is None + self._archive_source = archive_source + + def ensure_pristine_source_checkout(self) -> None: + """Ensure the source directory has not yet been built in.""" + assert self.source_dir is not None + if self._archive_source is not None: + unpack_file(str(self._archive_source), self.source_dir) + elif is_installable_dir(self.source_dir): + # If a checkout exists, it's unwise to keep going. + # version inconsistencies are logged later, but do not fail + # the installation. + raise PreviousBuildDirError( + f"pip can't proceed with requirements '{self}' due to a " + f"pre-existing build directory ({self.source_dir}). This is likely " + "due to a previous installation that failed . pip is " + "being responsible and not assuming it can delete this. " + "Please delete it and try again." + ) + # For editable installations def update_editable(self) -> None: if not self.link: @@ -673,9 +734,10 @@ class InstallRequirement: name = name.replace(os.path.sep, "/") return name + assert self.req is not None path = os.path.join(parentdir, path) name = _clean_zip_name(path, rootdir) - return self.name + "/" + name + return self.req.name + "/" + name def archive(self, build_dir: Optional[str]) -> None: """Saves archive to provided build_dir. @@ -746,7 +808,6 @@ class InstallRequirement: def install( self, - install_options: List[str], global_options: Optional[Sequence[str]] = None, root: Optional[str] = None, home: Optional[str] = None, @@ -755,8 +816,9 @@ class InstallRequirement: use_user_site: bool = False, pycompile: bool = True, ) -> None: + assert self.req is not None scheme = get_scheme( - self.name, + self.req.name, user=use_user_site, home=home, root=root, @@ -764,15 +826,13 @@ class InstallRequirement: prefix=prefix, ) - global_options = global_options if global_options is not None else [] if self.editable and not self.is_wheel: install_editable_legacy( - install_options, - global_options, + global_options=global_options if global_options is not None else [], prefix=prefix, home=home, use_user_site=use_user_site, - name=self.name, + name=self.req.name, setup_py_path=self.setup_py_path, isolated=self.isolated, build_env=self.build_env, @@ -781,82 +841,23 @@ class InstallRequirement: self.install_succeeded = True return - if self.is_wheel: - assert self.local_file_path - direct_url = None - # TODO this can be refactored to direct_url = self.download_info - if self.editable: - direct_url = direct_url_for_editable(self.unpacked_source_directory) - elif self.original_link: - direct_url = direct_url_from_link( - self.original_link, - self.source_dir, - self.original_link_is_in_wheel_cache, - ) - install_wheel( - self.name, - self.local_file_path, - scheme=scheme, - req_description=str(self.req), - pycompile=pycompile, - warn_script_location=warn_script_location, - direct_url=direct_url, - requested=self.user_supplied, - ) - self.install_succeeded = True - return - - # TODO: Why don't we do this for editable installs? - - # Extend the list of global and install options passed on to - # the setup.py call with the ones from the requirements file. - # Options specified in requirements file override those - # specified on the command line, since the last option given - # to setup.py is the one that is used. - global_options = list(global_options) + self.global_options - install_options = list(install_options) + self.install_options - - try: - if ( - self.legacy_install_reason is not None - and self.legacy_install_reason.emit_before_install - ): - self.legacy_install_reason.emit_deprecation(self.name) - success = install_legacy( - install_options=install_options, - global_options=global_options, - root=root, - home=home, - prefix=prefix, - use_user_site=use_user_site, - pycompile=pycompile, - scheme=scheme, - setup_py_path=self.setup_py_path, - isolated=self.isolated, - req_name=self.name, - build_env=self.build_env, - unpacked_source_directory=self.unpacked_source_directory, - req_description=str(self.req), - ) - except LegacyInstallFailure as exc: - self.install_succeeded = False - raise exc - except Exception: - self.install_succeeded = True - raise - - self.install_succeeded = success - - if ( - success - and self.legacy_install_reason is not None - and self.legacy_install_reason.emit_after_success - ): - self.legacy_install_reason.emit_deprecation(self.name) + assert self.is_wheel + assert self.local_file_path + + install_wheel( + self.req.name, + self.local_file_path, + scheme=scheme, + req_description=str(self.req), + pycompile=pycompile, + warn_script_location=warn_script_location, + direct_url=self.download_info if self.is_direct else None, + requested=self.user_supplied, + ) + self.install_succeeded = True def check_invalid_constraint_type(req: InstallRequirement) -> str: - # Check for unsupported forms problem = "" if not req.name: @@ -893,54 +894,21 @@ def _has_option(options: Values, reqs: List[InstallRequirement], option: str) -> return False -def _install_option_ignored( - install_options: List[str], reqs: List[InstallRequirement] -) -> bool: - for req in reqs: - if (install_options or req.install_options) and not req.use_pep517: - return False - return True - - -class LegacySetupPyOptionsCheckMode(Enum): - INSTALL = 1 - WHEEL = 2 - DOWNLOAD = 3 - - def check_legacy_setup_py_options( options: Values, reqs: List[InstallRequirement], - mode: LegacySetupPyOptionsCheckMode, ) -> None: - has_install_options = _has_option(options, reqs, "install_options") has_build_options = _has_option(options, reqs, "build_options") has_global_options = _has_option(options, reqs, "global_options") - legacy_setup_py_options_present = ( - has_install_options or has_build_options or has_global_options - ) - if not legacy_setup_py_options_present: - return - - options.format_control.disallow_binaries() - logger.warning( - "Implying --no-binary=:all: due to the presence of " - "--build-option / --global-option / --install-option. " - "Consider using --config-settings for more flexibility.", - ) - if mode == LegacySetupPyOptionsCheckMode.INSTALL and has_install_options: - if _install_option_ignored(options.install_options, reqs): - logger.warning( - "Ignoring --install-option when building using PEP 517", - ) - else: - deprecated( - reason=( - "--install-option is deprecated because " - "it forces pip to use the 'setup.py install' " - "command which is itself deprecated." - ), - issue=11358, - replacement="to use --config-settings", - gone_in="23.1", - ) + if has_build_options or has_global_options: + deprecated( + reason="--build-option and --global-option are deprecated.", + issue=11859, + replacement="to use --config-settings", + gone_in="24.0", + ) + logger.warning( + "Implying --no-binary=:all: due to the presence of " + "--build-option / --global-option. " + ) + options.format_control.disallow_binaries() diff --git a/.venv/Lib/site-packages/pip/_internal/req/req_set.py b/.venv/Lib/site-packages/pip/_internal/req/req_set.py index ec7a6e07..1bf73d59 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/req_set.py +++ b/.venv/Lib/site-packages/pip/_internal/req/req_set.py @@ -2,9 +2,12 @@ import logging from collections import OrderedDict from typing import Dict, List +from pip._vendor.packaging.specifiers import LegacySpecifier from pip._vendor.packaging.utils import canonicalize_name +from pip._vendor.packaging.version import LegacyVersion from pip._internal.req.req_install import InstallRequirement +from pip._internal.utils.deprecation import deprecated logger = logging.getLogger(__name__) @@ -80,3 +83,37 @@ class RequirementSet: for install_req in self.all_requirements if not install_req.constraint and not install_req.satisfied_by ] + + def warn_legacy_versions_and_specifiers(self) -> None: + for req in self.requirements_to_install: + version = req.get_dist().version + if isinstance(version, LegacyVersion): + deprecated( + reason=( + f"pip has selected the non standard version {version} " + f"of {req}. In the future this version will be " + f"ignored as it isn't standard compliant." + ), + replacement=( + "set or update constraints to select another version " + "or contact the package author to fix the version number" + ), + issue=12063, + gone_in="24.0", + ) + for dep in req.get_dist().iter_dependencies(): + if any(isinstance(spec, LegacySpecifier) for spec in dep.specifier): + deprecated( + reason=( + f"pip has selected {req} {version} which has non " + f"standard dependency specifier {dep}. " + f"In the future this version of {req} will be " + f"ignored as it isn't standard compliant." + ), + replacement=( + "set or update constraints to select another version " + "or contact the package author to fix the version number" + ), + issue=12063, + gone_in="24.0", + ) diff --git a/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py b/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py index 15b67385..861aa4f2 100644 --- a/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py +++ b/.venv/Lib/site-packages/pip/_internal/req/req_uninstall.py @@ -11,8 +11,9 @@ from pip._internal.metadata import BaseDistribution from pip._internal.utils.compat import WINDOWS from pip._internal.utils.egg_link import egg_link_path_from_location from pip._internal.utils.logging import getLogger, indent_log -from pip._internal.utils.misc import ask, is_local, normalize_path, renames, rmtree +from pip._internal.utils.misc import ask, normalize_path, renames, rmtree from pip._internal.utils.temp_dir import AdjacentTempDirectory, TempDirectory +from pip._internal.utils.virtualenv import running_under_virtualenv logger = getLogger(__name__) @@ -273,7 +274,7 @@ class StashedUninstallPathSet: def commit(self) -> None: """Commits the uninstall by removing stashed files.""" - for _, save_dir in self._save_dirs.items(): + for save_dir in self._save_dirs.values(): save_dir.cleanup() self._moves = [] self._save_dirs = {} @@ -312,6 +313,10 @@ class UninstallPathSet: self._pth: Dict[str, UninstallPthEntries] = {} self._dist = dist self._moved_paths = StashedUninstallPathSet() + # Create local cache of normalize_path results. Creating an UninstallPathSet + # can result in hundreds/thousands of redundant calls to normalize_path with + # the same args, which hurts performance. + self._normalize_path_cached = functools.lru_cache()(normalize_path) def _permitted(self, path: str) -> bool: """ @@ -319,14 +324,17 @@ class UninstallPathSet: remove/modify, False otherwise. """ - return is_local(path) + # aka is_local, but caching normalized sys.prefix + if not running_under_virtualenv(): + return True + return path.startswith(self._normalize_path_cached(sys.prefix)) def add(self, path: str) -> None: head, tail = os.path.split(path) # we normalize the head to resolve parent directory symlinks, but not # the tail, since we only want to uninstall symlinks, not their targets - path = os.path.join(normalize_path(head), os.path.normcase(tail)) + path = os.path.join(self._normalize_path_cached(head), os.path.normcase(tail)) if not os.path.exists(path): return @@ -341,7 +349,7 @@ class UninstallPathSet: self.add(cache_from_source(path)) def add_pth(self, pth_file: str, entry: str) -> None: - pth_file = normalize_path(pth_file) + pth_file = self._normalize_path_cached(pth_file) if self._permitted(pth_file): if pth_file not in self._pth: self._pth[pth_file] = UninstallPthEntries(pth_file) @@ -531,12 +539,14 @@ class UninstallPathSet: # above, so this only covers the setuptools-style editable. with open(develop_egg_link) as fh: link_pointer = os.path.normcase(fh.readline().strip()) - normalized_link_pointer = normalize_path(link_pointer) + normalized_link_pointer = paths_to_remove._normalize_path_cached( + link_pointer + ) assert os.path.samefile( normalized_link_pointer, normalized_dist_location ), ( - f"Egg-link {link_pointer} does not match installed location of " - f"{dist.raw_name} (at {dist_location})" + f"Egg-link {develop_egg_link} (to {link_pointer}) does not match " + f"installed location of {dist.raw_name} (at {dist_location})" ) paths_to_remove.add(develop_egg_link) easy_install_pth = os.path.join( diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py b/.venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py index fb49d416..b17b7e45 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/legacy/resolver.py @@ -431,12 +431,12 @@ class Resolver(BaseResolver): if cache_entry is not None: logger.debug("Using cached wheel link: %s", cache_entry.link) if req.link is req.original_link and cache_entry.persistent: - req.original_link_is_in_wheel_cache = True + req.cached_wheel_source_link = req.link if cache_entry.origin is not None: req.download_info = cache_entry.origin else: # Legacy cache entry that does not have origin.json. - # download_info may miss the archive_info.hash field. + # download_info may miss the archive_info.hashes field. req.download_info = direct_url_from_link( req.link, link_is_in_wheel_cache=cache_entry.persistent ) diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py index b206692a..9c0ef5ca 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/base.py @@ -1,7 +1,7 @@ from typing import FrozenSet, Iterable, Optional, Tuple, Union from pip._vendor.packaging.specifiers import SpecifierSet -from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._vendor.packaging.utils import NormalizedName from pip._vendor.packaging.version import LegacyVersion, Version from pip._internal.models.link import Link, links_equivalent @@ -12,11 +12,11 @@ CandidateLookup = Tuple[Optional["Candidate"], Optional[InstallRequirement]] CandidateVersion = Union[LegacyVersion, Version] -def format_name(project: str, extras: FrozenSet[str]) -> str: +def format_name(project: NormalizedName, extras: FrozenSet[NormalizedName]) -> str: if not extras: return project - canonical_extras = sorted(canonicalize_name(e) for e in extras) - return "{}[{}]".format(project, ",".join(canonical_extras)) + extras_expr = ",".join(sorted(extras)) + return f"{project}[{extras_expr}]" class Constraint: diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py index f5bc343b..97541655 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/candidates.py @@ -65,15 +65,13 @@ def make_install_req_from_link( use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) ireq.original_link = template.original_link ireq.link = link + ireq.extras = template.extras return ireq @@ -81,7 +79,7 @@ def make_install_req_from_editable( link: Link, template: InstallRequirement ) -> InstallRequirement: assert template.editable, "template not editable" - return install_req_from_editable( + ireq = install_req_from_editable( link.url, user_supplied=template.user_supplied, comes_from=template.comes_from, @@ -89,13 +87,12 @@ def make_install_req_from_editable( isolated=template.isolated, constraint=template.constraint, permit_editable_wheels=template.permit_editable_wheels, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) + ireq.extras = template.extras + return ireq def _make_install_req_from_dist( @@ -114,11 +111,8 @@ def _make_install_req_from_dist( use_pep517=template.use_pep517, isolated=template.isolated, constraint=template.constraint, - options=dict( - install_options=template.install_options, - global_options=template.global_options, - hashes=template.hash_options, - ), + global_options=template.global_options, + hash_options=template.hash_options, config_settings=template.config_settings, ) ireq.satisfied_by = dist @@ -246,7 +240,7 @@ class _InstallRequirementBackedCandidate(Candidate): def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: requires = self.dist.iter_dependencies() if with_requires else () for r in requires: - yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) yield self._factory.make_requires_python_requirement(self.dist.requires_python) def get_install_requirement(self) -> Optional[InstallRequirement]: @@ -265,7 +259,7 @@ class LinkCandidate(_InstallRequirementBackedCandidate): version: Optional[CandidateVersion] = None, ) -> None: source_link = link - cache_entry = factory.get_wheel_cache_entry(link, name) + cache_entry = factory.get_wheel_cache_entry(source_link, name) if cache_entry is not None: logger.debug("Using cached wheel link: %s", cache_entry.link) link = cache_entry.link @@ -283,13 +277,15 @@ class LinkCandidate(_InstallRequirementBackedCandidate): ) if cache_entry is not None: + assert ireq.link.is_wheel + assert ireq.link.is_file if cache_entry.persistent and template.link is template.original_link: - ireq.original_link_is_in_wheel_cache = True + ireq.cached_wheel_source_link = source_link if cache_entry.origin is not None: ireq.download_info = cache_entry.origin else: # Legacy cache entry that does not have origin.json. - # download_info may miss the archive_info.hash field. + # download_info may miss the archive_info.hashes field. ireq.download_info = direct_url_from_link( source_link, link_is_in_wheel_cache=cache_entry.persistent ) @@ -345,6 +341,7 @@ class AlreadyInstalledCandidate(Candidate): self.dist = dist self._ireq = _make_install_req_from_dist(dist, template) self._factory = factory + self._version = None # This is just logging some messages, so we can do it eagerly. # The returned dist would be exactly the same as self.dist because we @@ -380,7 +377,9 @@ class AlreadyInstalledCandidate(Candidate): @property def version(self) -> CandidateVersion: - return self.dist.version + if self._version is None: + self._version = self.dist.version + return self._version @property def is_editable(self) -> bool: @@ -393,7 +392,7 @@ class AlreadyInstalledCandidate(Candidate): if not with_requires: return for r in self.dist.iter_dependencies(): - yield self._factory.make_requirement_from_spec(str(r), self._ireq) + yield from self._factory.make_requirements_from_spec(str(r), self._ireq) def get_install_requirement(self) -> Optional[InstallRequirement]: return None @@ -428,9 +427,28 @@ class ExtrasCandidate(Candidate): self, base: BaseCandidate, extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, ) -> None: + """ + :param comes_from: the InstallRequirement that led to this candidate if it + differs from the base's InstallRequirement. This will often be the + case in the sense that this candidate's requirement has the extras + while the base's does not. Unlike the InstallRequirement backed + candidates, this requirement is used solely for reporting purposes, + it does not do any leg work. + """ self.base = base - self.extras = extras + self.extras = frozenset(canonicalize_name(e) for e in extras) + # If any extras are requested in their non-normalized forms, keep track + # of their raw values. This is needed when we look up dependencies + # since PEP 685 has not been implemented for marker-matching, and using + # the non-normalized extra for lookup ensures the user can select a + # non-normalized extra in a package with its non-normalized form. + # TODO: Remove this attribute when packaging is upgraded to support the + # marker comparison logic specified in PEP 685. + self._unnormalized_extras = extras.difference(self.extras) + self._comes_from = comes_from if comes_from is not None else self.base._ireq def __str__(self) -> str: name, rest = str(self.base).split(" ", 1) @@ -481,6 +499,50 @@ class ExtrasCandidate(Candidate): def source_link(self) -> Optional[Link]: return self.base.source_link + def _warn_invalid_extras( + self, + requested: FrozenSet[str], + valid: FrozenSet[str], + ) -> None: + """Emit warnings for invalid extras being requested. + + This emits a warning for each requested extra that is not in the + candidate's ``Provides-Extra`` list. + """ + invalid_extras_to_warn = frozenset( + extra + for extra in requested + if extra not in valid + # If an extra is requested in an unnormalized form, skip warning + # about the normalized form being missing. + and extra in self.extras + ) + if not invalid_extras_to_warn: + return + for extra in sorted(invalid_extras_to_warn): + logger.warning( + "%s %s does not provide the extra '%s'", + self.base.name, + self.version, + extra, + ) + + def _calculate_valid_requested_extras(self) -> FrozenSet[str]: + """Get a list of valid extras requested by this candidate. + + The user (or upstream dependant) may have specified extras that the + candidate doesn't support. Any unsupported extras are dropped, and each + cause a warning to be logged here. + """ + requested_extras = self.extras.union(self._unnormalized_extras) + valid_extras = frozenset( + extra + for extra in requested_extras + if self.base.dist.is_extra_provided(extra) + ) + self._warn_invalid_extras(requested_extras, valid_extras) + return valid_extras + def iter_dependencies(self, with_requires: bool) -> Iterable[Optional[Requirement]]: factory = self.base._factory @@ -490,24 +552,13 @@ class ExtrasCandidate(Candidate): if not with_requires: return - # The user may have specified extras that the candidate doesn't - # support. We ignore any unsupported extras here. - valid_extras = self.extras.intersection(self.base.dist.iter_provided_extras()) - invalid_extras = self.extras.difference(self.base.dist.iter_provided_extras()) - for extra in sorted(invalid_extras): - logger.warning( - "%s %s does not provide the extra '%s'", - self.base.name, - self.version, - extra, - ) - + valid_extras = self._calculate_valid_requested_extras() for r in self.base.dist.iter_dependencies(valid_extras): - requirement = factory.make_requirement_from_spec( - str(r), self.base._ireq, valid_extras + yield from factory.make_requirements_from_spec( + str(r), + self._comes_from, + valid_extras, ) - if requirement: - yield requirement def get_install_requirement(self) -> Optional[InstallRequirement]: # We don't return anything here, because we always diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py index a4c24b52..38c19944 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/factory.py @@ -62,6 +62,7 @@ from .requirements import ( ExplicitRequirement, RequiresPythonRequirement, SpecifierRequirement, + SpecifierWithoutExtrasRequirement, UnsatisfiableRequirement, ) @@ -112,7 +113,7 @@ class Factory: self._editable_candidate_cache: Cache[EditableCandidate] = {} self._installed_candidate_cache: Dict[str, AlreadyInstalledCandidate] = {} self._extras_candidate_cache: Dict[ - Tuple[int, FrozenSet[str]], ExtrasCandidate + Tuple[int, FrozenSet[NormalizedName]], ExtrasCandidate ] = {} if not ignore_installed: @@ -132,19 +133,23 @@ class Factory: if not link.is_wheel: return wheel = Wheel(link.filename) - if wheel.supported(self._finder.target_python.get_tags()): + if wheel.supported(self._finder.target_python.get_unsorted_tags()): return msg = f"{link.filename} is not a supported wheel on this platform." raise UnsupportedWheel(msg) def _make_extras_candidate( - self, base: BaseCandidate, extras: FrozenSet[str] + self, + base: BaseCandidate, + extras: FrozenSet[str], + *, + comes_from: Optional[InstallRequirement] = None, ) -> ExtrasCandidate: - cache_key = (id(base), extras) + cache_key = (id(base), frozenset(canonicalize_name(e) for e in extras)) try: candidate = self._extras_candidate_cache[cache_key] except KeyError: - candidate = ExtrasCandidate(base, extras) + candidate = ExtrasCandidate(base, extras, comes_from=comes_from) self._extras_candidate_cache[cache_key] = candidate return candidate @@ -161,7 +166,7 @@ class Factory: self._installed_candidate_cache[dist.canonical_name] = base if not extras: return base - return self._make_extras_candidate(base, extras) + return self._make_extras_candidate(base, extras, comes_from=template) def _make_candidate_from_link( self, @@ -223,7 +228,7 @@ class Factory: if not extras: return base - return self._make_extras_candidate(base, extras) + return self._make_extras_candidate(base, extras, comes_from=template) def _iter_found_candidates( self, @@ -385,16 +390,21 @@ class Factory: if ireq is not None: ireqs.append(ireq) - # If the current identifier contains extras, add explicit candidates - # from entries from extra-less identifier. + # If the current identifier contains extras, add requires and explicit + # candidates from entries from extra-less identifier. with contextlib.suppress(InvalidRequirement): parsed_requirement = get_requirement(identifier) - explicit_candidates.update( - self._iter_explicit_candidates_from_base( - requirements.get(parsed_requirement.name, ()), - frozenset(parsed_requirement.extras), - ), - ) + if parsed_requirement.name != identifier: + explicit_candidates.update( + self._iter_explicit_candidates_from_base( + requirements.get(parsed_requirement.name, ()), + frozenset(parsed_requirement.extras), + ), + ) + for req in requirements.get(parsed_requirement.name, []): + _, ireq = req.get_candidate_lookup() + if ireq is not None: + ireqs.append(ireq) # Add explicit candidates from constraints. We only do this if there are # known ireqs, which represent requirements not already explicit. If @@ -437,37 +447,49 @@ class Factory: and all(req.is_satisfied_by(c) for req in requirements[identifier]) ) - def _make_requirement_from_install_req( + def _make_requirements_from_install_req( self, ireq: InstallRequirement, requested_extras: Iterable[str] - ) -> Optional[Requirement]: + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given InstallRequirement. In + most cases this will be a single object but the following special cases exist: + - the InstallRequirement has markers that do not apply -> result is empty + - the InstallRequirement has both a constraint and extras -> result is split + in two requirement objects: one with the constraint and one with the + extra. This allows centralized constraint handling for the base, + resulting in fewer candidate rejections. + """ if not ireq.match_markers(requested_extras): logger.info( "Ignoring %s: markers '%s' don't match your environment", ireq.name, ireq.markers, ) - return None - if not ireq.link: - return SpecifierRequirement(ireq) - self._fail_if_link_is_unsupported_wheel(ireq.link) - cand = self._make_candidate_from_link( - ireq.link, - extras=frozenset(ireq.extras), - template=ireq, - name=canonicalize_name(ireq.name) if ireq.name else None, - version=None, - ) - if cand is None: - # There's no way we can satisfy a URL requirement if the underlying - # candidate fails to build. An unnamed URL must be user-supplied, so - # we fail eagerly. If the URL is named, an unsatisfiable requirement - # can make the resolver do the right thing, either backtrack (and - # maybe find some other requirement that's buildable) or raise a - # ResolutionImpossible eventually. - if not ireq.name: - raise self._build_failures[ireq.link] - return UnsatisfiableRequirement(canonicalize_name(ireq.name)) - return self.make_requirement_from_candidate(cand) + elif not ireq.link: + if ireq.extras and ireq.req is not None and ireq.req.specifier: + yield SpecifierWithoutExtrasRequirement(ireq) + yield SpecifierRequirement(ireq) + else: + self._fail_if_link_is_unsupported_wheel(ireq.link) + cand = self._make_candidate_from_link( + ireq.link, + extras=frozenset(ireq.extras), + template=ireq, + name=canonicalize_name(ireq.name) if ireq.name else None, + version=None, + ) + if cand is None: + # There's no way we can satisfy a URL requirement if the underlying + # candidate fails to build. An unnamed URL must be user-supplied, so + # we fail eagerly. If the URL is named, an unsatisfiable requirement + # can make the resolver do the right thing, either backtrack (and + # maybe find some other requirement that's buildable) or raise a + # ResolutionImpossible eventually. + if not ireq.name: + raise self._build_failures[ireq.link] + yield UnsatisfiableRequirement(canonicalize_name(ireq.name)) + else: + yield self.make_requirement_from_candidate(cand) def collect_root_requirements( self, root_ireqs: List[InstallRequirement] @@ -488,15 +510,27 @@ class Factory: else: collected.constraints[name] = Constraint.from_ireq(ireq) else: - req = self._make_requirement_from_install_req( - ireq, - requested_extras=(), + reqs = list( + self._make_requirements_from_install_req( + ireq, + requested_extras=(), + ) ) - if req is None: + if not reqs: continue - if ireq.user_supplied and req.name not in collected.user_requested: - collected.user_requested[req.name] = i - collected.requirements.append(req) + template = reqs[0] + if ireq.user_supplied and template.name not in collected.user_requested: + collected.user_requested[template.name] = i + collected.requirements.extend(reqs) + # Put requirements with extras at the end of the root requires. This does not + # affect resolvelib's picking preference but it does affect its initial criteria + # population: by putting extras at the end we enable the candidate finder to + # present resolvelib with a smaller set of candidates to resolvelib, already + # taking into account any non-transient constraints on the associated base. This + # means resolvelib will have fewer candidates to visit and reject. + # Python's list sort is stable, meaning relative order is kept for objects with + # the same key. + collected.requirements.sort(key=lambda r: r.name != r.project_name) return collected def make_requirement_from_candidate( @@ -504,14 +538,23 @@ class Factory: ) -> ExplicitRequirement: return ExplicitRequirement(candidate) - def make_requirement_from_spec( + def make_requirements_from_spec( self, specifier: str, comes_from: Optional[InstallRequirement], requested_extras: Iterable[str] = (), - ) -> Optional[Requirement]: + ) -> Iterator[Requirement]: + """ + Returns requirement objects associated with the given specifier. In most cases + this will be a single object but the following special cases exist: + - the specifier has markers that do not apply -> result is empty + - the specifier has both a constraint and extras -> result is split + in two requirement objects: one with the constraint and one with the + extra. This allows centralized constraint handling for the base, + resulting in fewer candidate rejections. + """ ireq = self._make_install_req_from_spec(specifier, comes_from) - return self._make_requirement_from_install_req(ireq, requested_extras) + return self._make_requirements_from_install_req(ireq, requested_extras) def make_requires_python_requirement( self, @@ -535,7 +578,7 @@ class Factory: hash mismatches. Furthermore, cached wheels at present have nondeterministic contents due to file modification times. """ - if self._wheel_cache is None or self.preparer.require_hashes: + if self._wheel_cache is None: return None return self._wheel_cache.get_cache_entry( link=link, @@ -603,8 +646,26 @@ class Factory: cands = self._finder.find_all_candidates(req.project_name) skipped_by_requires_python = self._finder.requires_python_skipped_reasons() - versions = [str(v) for v in sorted({c.version for c in cands})] + versions_set: Set[CandidateVersion] = set() + yanked_versions_set: Set[CandidateVersion] = set() + for c in cands: + is_yanked = c.link.is_yanked if c.link else False + if is_yanked: + yanked_versions_set.add(c.version) + else: + versions_set.add(c.version) + + versions = [str(v) for v in sorted(versions_set)] + yanked_versions = [str(v) for v in sorted(yanked_versions_set)] + + if yanked_versions: + # Saying "version X is yanked" isn't entirely accurate. + # https://github.com/pypa/pip/issues/11745#issuecomment-1402805842 + logger.critical( + "Ignored the following yanked versions: %s", + ", ".join(yanked_versions) or "none", + ) if skipped_by_requires_python: logger.critical( "Ignored the following versions that require a different python " @@ -632,7 +693,6 @@ class Factory: e: "ResolutionImpossible[Requirement, Candidate]", constraints: Dict[str, Constraint], ) -> InstallationError: - assert e.causes, "Installation error reported with no cause" # If one of the things we can't solve is "we need Python X.Y", diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py index 6300dfc5..315fb9c8 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/provider.py @@ -104,7 +104,7 @@ class PipProvider(_ProviderBase): def identify(self, requirement_or_candidate: Union[Requirement, Candidate]) -> str: return requirement_or_candidate.name - def get_preference( # type: ignore + def get_preference( self, identifier: str, resolutions: Mapping[str, Candidate], @@ -124,14 +124,29 @@ class PipProvider(_ProviderBase): * If equal, prefer if any requirement is "pinned", i.e. contains operator ``===`` or ``==``. * If equal, calculate an approximate "depth" and resolve requirements - closer to the user-specified requirements first. + closer to the user-specified requirements first. If the depth cannot + by determined (eg: due to no matching parents), it is considered + infinite. * Order user-specified requirements by the order they are specified. * If equal, prefers "non-free" requirements, i.e. contains at least one operator, such as ``>=`` or ``<``. * If equal, order alphabetically for consistency (helps debuggability). """ - lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) - candidate, ireqs = zip(*lookups) + try: + next(iter(information[identifier])) + except StopIteration: + # There is no information for this identifier, so there's no known + # candidates. + has_information = False + else: + has_information = True + + if has_information: + lookups = (r.get_candidate_lookup() for r, _ in information[identifier]) + candidate, ireqs = zip(*lookups) + else: + candidate, ireqs = None, () + operators = [ specifier.operator for specifier_set in (ireq.specifier for ireq in ireqs if ireq) @@ -146,11 +161,14 @@ class PipProvider(_ProviderBase): requested_order: Union[int, float] = self._user_requested[identifier] except KeyError: requested_order = math.inf - parent_depths = ( - self._known_depths[parent.name] if parent is not None else 0.0 - for _, parent in information[identifier] - ) - inferred_depth = min(d for d in parent_depths) + 1.0 + if has_information: + parent_depths = ( + self._known_depths[parent.name] if parent is not None else 0.0 + for _, parent in information[identifier] + ) + inferred_depth = min(d for d in parent_depths) + 1.0 + else: + inferred_depth = math.inf else: inferred_depth = 1.0 self._known_depths[identifier] = inferred_depth @@ -161,16 +179,6 @@ class PipProvider(_ProviderBase): # free, so we always do it first to avoid needless work if it fails. requires_python = identifier == REQUIRES_PYTHON_IDENTIFIER - # HACK: Setuptools have a very long and solid backward compatibility - # track record, and extremely few projects would request a narrow, - # non-recent version range of it since that would break a lot things. - # (Most projects specify it only to request for an installer feature, - # which does not work, but that's another topic.) Intentionally - # delaying Setuptools helps reduce branches the resolver has to check. - # This serves as a temporary fix for issues like "apache-airflow[all]" - # while we work on "proper" branch pruning techniques. - delay_this = identifier == "setuptools" - # Prefer the causes of backtracking on the assumption that the problem # resolving the dependency tree is related to the failures that caused # the backtracking @@ -178,7 +186,6 @@ class PipProvider(_ProviderBase): return ( not requires_python, - delay_this, not direct, not pinned, not backtrack_cause, diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py index 6ced5329..12adeff7 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/reporter.py @@ -11,16 +11,16 @@ logger = getLogger(__name__) class PipReporter(BaseReporter): def __init__(self) -> None: - self.backtracks_by_package: DefaultDict[str, int] = defaultdict(int) + self.reject_count_by_package: DefaultDict[str, int] = defaultdict(int) - self._messages_at_backtrack = { + self._messages_at_reject_count = { 1: ( "pip is looking at multiple versions of {package_name} to " "determine which version is compatible with other " "requirements. This could take a while." ), 8: ( - "pip is looking at multiple versions of {package_name} to " + "pip is still looking at multiple versions of {package_name} to " "determine which version is compatible with other " "requirements. This could take a while." ), @@ -32,16 +32,28 @@ class PipReporter(BaseReporter): ), } - def backtracking(self, candidate: Candidate) -> None: - self.backtracks_by_package[candidate.name] += 1 + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + self.reject_count_by_package[candidate.name] += 1 - count = self.backtracks_by_package[candidate.name] - if count not in self._messages_at_backtrack: + count = self.reject_count_by_package[candidate.name] + if count not in self._messages_at_reject_count: return - message = self._messages_at_backtrack[count] + message = self._messages_at_reject_count[count] logger.info("INFO: %s", message.format(package_name=candidate.name)) + msg = "Will try a different candidate, due to conflict:" + for req_info in criterion.information: + req, parent = req_info.requirement, req_info.parent + # Inspired by Factory.get_installation_error + msg += "\n " + if parent: + msg += f"{parent.name} {parent.version} depends on " + else: + msg += "The user requested " + msg += req.format_for_error() + logger.debug(msg) + class PipDebuggingReporter(BaseReporter): """A reporter that does an info log for every event it sees.""" @@ -61,8 +73,8 @@ class PipDebuggingReporter(BaseReporter): def adding_requirement(self, requirement: Requirement, parent: Candidate) -> None: logger.info("Reporter.adding_requirement(%r, %r)", requirement, parent) - def backtracking(self, candidate: Candidate) -> None: - logger.info("Reporter.backtracking(%r)", candidate) + def rejecting_candidate(self, criterion: Any, candidate: Candidate) -> None: + logger.info("Reporter.rejecting_candidate(%r, %r)", criterion, candidate) def pinning(self, candidate: Candidate) -> None: logger.info("Reporter.pinning(%r)", candidate) diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py index f561f1f1..7d1e7bfd 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/requirements.py @@ -1,6 +1,7 @@ from pip._vendor.packaging.specifiers import SpecifierSet from pip._vendor.packaging.utils import NormalizedName, canonicalize_name +from pip._internal.req.constructors import install_req_drop_extras from pip._internal.req.req_install import InstallRequirement from .base import Candidate, CandidateLookup, Requirement, format_name @@ -43,7 +44,7 @@ class SpecifierRequirement(Requirement): def __init__(self, ireq: InstallRequirement) -> None: assert ireq.link is None, "This is a link, not a specifier" self._ireq = ireq - self._extras = frozenset(ireq.extras) + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) def __str__(self) -> str: return str(self._ireq.req) @@ -64,7 +65,6 @@ class SpecifierRequirement(Requirement): return format_name(self.project_name, self._extras) def format_for_error(self) -> str: - # Convert comma-separated specifiers into "A, B, ..., F and G" # This makes the specifier a bit more "human readable", without # risking a change in meaning. (Hopefully! Not all edge cases have @@ -93,6 +93,18 @@ class SpecifierRequirement(Requirement): return spec.contains(candidate.version, prereleases=True) +class SpecifierWithoutExtrasRequirement(SpecifierRequirement): + """ + Requirement backed by an install requirement on a base package. + Trims extras from its install requirement if there are any. + """ + + def __init__(self, ireq: InstallRequirement) -> None: + assert ireq.link is None, "This is a link, not a specifier" + self._ireq = install_req_drop_extras(ireq) + self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras) + + class RequiresPythonRequirement(Requirement): """A requirement representing Requires-Python metadata.""" diff --git a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py index a605d6c2..c12beef0 100644 --- a/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py +++ b/.venv/Lib/site-packages/pip/_internal/resolution/resolvelib/resolver.py @@ -1,3 +1,4 @@ +import contextlib import functools import logging import os @@ -11,6 +12,7 @@ from pip._vendor.resolvelib.structs import DirectedGraph from pip._internal.cache import WheelCache from pip._internal.index.package_finder import PackageFinder from pip._internal.operations.prepare import RequirementPreparer +from pip._internal.req.constructors import install_req_extend_extras from pip._internal.req.req_install import InstallRequirement from pip._internal.req.req_set import RequirementSet from pip._internal.resolution.base import BaseResolver, InstallRequirementProvider @@ -19,6 +21,7 @@ from pip._internal.resolution.resolvelib.reporter import ( PipDebuggingReporter, PipReporter, ) +from pip._internal.utils.packaging import get_requirement from .base import Candidate, Requirement from .factory import Factory @@ -88,9 +91,9 @@ class Resolver(BaseResolver): ) try: - try_to_avoid_resolution_too_deep = 2000000 + limit_how_complex_resolution_can_be = 200000 result = self._result = resolver.resolve( - collected.requirements, max_rounds=try_to_avoid_resolution_too_deep + collected.requirements, max_rounds=limit_how_complex_resolution_can_be ) except ResolutionImpossible as e: @@ -101,9 +104,24 @@ class Resolver(BaseResolver): raise error from e req_set = RequirementSet(check_supported_wheels=check_supported_wheels) - for candidate in result.mapping.values(): + # process candidates with extras last to ensure their base equivalent is + # already in the req_set if appropriate. + # Python's sort is stable so using a binary key function keeps relative order + # within both subsets. + for candidate in sorted( + result.mapping.values(), key=lambda c: c.name != c.project_name + ): ireq = candidate.get_install_requirement() if ireq is None: + if candidate.name != candidate.project_name: + # extend existing req's extras + with contextlib.suppress(KeyError): + req = req_set.get_requirement(candidate.project_name) + req_set.add_named_requirement( + install_req_extend_extras( + req, get_requirement(candidate.name).extras + ) + ) continue # Check if there is already an installation under the same name, @@ -159,6 +177,9 @@ class Resolver(BaseResolver): reqs = req_set.all_requirements self.factory.preparer.prepare_linked_requirements_more(reqs) + for req in reqs: + req.prepared = True + req.needs_more_preparation = False return req_set def get_installation_order( diff --git a/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py b/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py index 41cc42c5..cb18edbe 100644 --- a/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py +++ b/.venv/Lib/site-packages/pip/_internal/self_outdated_check.py @@ -28,8 +28,7 @@ from pip._internal.utils.entrypoints import ( from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace from pip._internal.utils.misc import ensure_dir -_DATE_FMT = "%Y-%m-%dT%H:%M:%SZ" - +_WEEK = datetime.timedelta(days=7) logger = logging.getLogger(__name__) @@ -73,12 +72,10 @@ class SelfCheckState: if "pypi_version" not in self._state: return None - seven_days_in_seconds = 7 * 24 * 60 * 60 - # Determine if we need to refresh the state - last_check = datetime.datetime.strptime(self._state["last_check"], _DATE_FMT) - seconds_since_last_check = (current_time - last_check).total_seconds() - if seconds_since_last_check > seven_days_in_seconds: + last_check = datetime.datetime.fromisoformat(self._state["last_check"]) + time_since_last_check = current_time - last_check + if time_since_last_check > _WEEK: return None return self._state["pypi_version"] @@ -100,7 +97,7 @@ class SelfCheckState: # Include the key so it's easy to tell which pip wrote the # file. "key": self.key, - "last_check": current_time.strftime(_DATE_FMT), + "last_check": current_time.isoformat(), "pypi_version": pypi_version, } @@ -229,14 +226,14 @@ def pip_self_version_check(session: PipSession, options: optparse.Values) -> Non try: upgrade_prompt = _self_version_check_logic( state=SelfCheckState(cache_dir=options.cache_dir), - current_time=datetime.datetime.utcnow(), + current_time=datetime.datetime.now(datetime.timezone.utc), local_version=installed_dist.version, get_remote_version=functools.partial( _get_current_remote_pip_version, session, options ), ) if upgrade_prompt is not None: - logger.warning("[present-rich] %s", upgrade_prompt) + logger.warning("%s", upgrade_prompt, extra={"rich": True}) except Exception: logger.warning("There was an error checking the latest version of pip.") logger.debug("See below for error", exc_info=True) diff --git a/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py b/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py index 18e9be9f..72bd6f25 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/deprecation.py @@ -118,71 +118,3 @@ def deprecated( raise PipDeprecationWarning(message) warnings.warn(message, category=PipDeprecationWarning, stacklevel=2) - - -class LegacyInstallReason: - def __init__( - self, - reason: str, - replacement: Optional[str] = None, - gone_in: Optional[str] = None, - feature_flag: Optional[str] = None, - issue: Optional[int] = None, - emit_after_success: bool = False, - emit_before_install: bool = False, - ): - self._reason = reason - self._replacement = replacement - self._gone_in = gone_in - self._feature_flag = feature_flag - self._issue = issue - self.emit_after_success = emit_after_success - self.emit_before_install = emit_before_install - - def emit_deprecation(self, name: str) -> None: - deprecated( - reason=self._reason.format(name=name), - replacement=self._replacement, - gone_in=self._gone_in, - feature_flag=self._feature_flag, - issue=self._issue, - ) - - -LegacyInstallReasonFailedBdistWheel = LegacyInstallReason( - reason=( - "{name} was installed using the legacy 'setup.py install' " - "method, because a wheel could not be built for it." - ), - replacement="to fix the wheel build issue reported above", - gone_in="23.1", - issue=8368, - emit_after_success=True, -) - - -LegacyInstallReasonMissingWheelPackage = LegacyInstallReason( - reason=( - "{name} is being installed using the legacy " - "'setup.py install' method, because it does not have a " - "'pyproject.toml' and the 'wheel' package " - "is not installed." - ), - replacement="to enable the '--use-pep517' option", - gone_in="23.1", - issue=8559, - emit_before_install=True, -) - -LegacyInstallReasonNoBinaryForcesSetuptoolsInstall = LegacyInstallReason( - reason=( - "{name} is being installed using the legacy " - "'setup.py install' method, because the '--no-binary' option was enabled " - "for it and this currently disables local wheel building for projects that " - "don't have a 'pyproject.toml' file." - ), - replacement="to enable the '--use-pep517' option", - gone_in="23.1", - issue=11451, - emit_before_install=True, -) diff --git a/.venv/Lib/site-packages/pip/_internal/utils/distutils_args.py b/.venv/Lib/site-packages/pip/_internal/utils/distutils_args.py deleted file mode 100644 index 2fd18620..00000000 --- a/.venv/Lib/site-packages/pip/_internal/utils/distutils_args.py +++ /dev/null @@ -1,43 +0,0 @@ -from getopt import GetoptError, getopt -from typing import Dict, List - -_options = [ - "exec-prefix=", - "home=", - "install-base=", - "install-data=", - "install-headers=", - "install-lib=", - "install-platlib=", - "install-purelib=", - "install-scripts=", - "prefix=", - "root=", - "user", -] - - -def parse_distutils_args(args: List[str]) -> Dict[str, str]: - """Parse provided arguments, returning an object that has the matched arguments. - - Any unknown arguments are ignored. - """ - result = {} - for arg in args: - try: - parsed_opt, _ = getopt(args=[arg], shortopts="", longopts=_options) - except GetoptError: - # We don't care about any other options, which here may be - # considered unrecognized since our option list is not - # exhaustive. - continue - - if not parsed_opt: - continue - - option = parsed_opt[0] - name_from_parsed = option[0][2:].replace("-", "_") - value_from_parsed = option[1] or "true" - result[name_from_parsed] = value_from_parsed - - return result diff --git a/.venv/Lib/site-packages/pip/_internal/utils/glibc.py b/.venv/Lib/site-packages/pip/_internal/utils/glibc.py index 7bd3c206..81342afa 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/glibc.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/glibc.py @@ -1,6 +1,3 @@ -# The following comment should be removed at some point in the future. -# mypy: strict-optional=False - import os import sys from typing import Optional, Tuple @@ -20,8 +17,11 @@ def glibc_version_string_confstr() -> Optional[str]: if sys.platform == "win32": return None try: + gnu_libc_version = os.confstr("CS_GNU_LIBC_VERSION") + if gnu_libc_version is None: + return None # os.confstr("CS_GNU_LIBC_VERSION") returns a string like "glibc 2.17": - _, version = os.confstr("CS_GNU_LIBC_VERSION").split() + _, version = gnu_libc_version.split() except (AttributeError, OSError, ValueError): # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)... return None diff --git a/.venv/Lib/site-packages/pip/_internal/utils/hashes.py b/.venv/Lib/site-packages/pip/_internal/utils/hashes.py index 76727306..843cffc6 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/hashes.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/hashes.py @@ -105,6 +105,13 @@ class Hashes: with open(path, "rb") as file: return self.check_against_file(file) + def has_one_of(self, hashes: Dict[str, str]) -> bool: + """Return whether any of the given hashes are allowed.""" + for hash_name, hex_digest in hashes.items(): + if self.is_hash_allowed(hash_name, hex_digest): + return True + return False + def __bool__(self) -> bool: """Return whether I know any known-good hashes.""" return bool(self._allowed) diff --git a/.venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py b/.venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py deleted file mode 100644 index 276aa79b..00000000 --- a/.venv/Lib/site-packages/pip/_internal/utils/inject_securetransport.py +++ /dev/null @@ -1,35 +0,0 @@ -"""A helper module that injects SecureTransport, on import. - -The import should be done as early as possible, to ensure all requests and -sessions (or whatever) are created after injecting SecureTransport. - -Note that we only do the injection on macOS, when the linked OpenSSL is too -old to handle TLSv1.2. -""" - -import sys - - -def inject_securetransport() -> None: - # Only relevant on macOS - if sys.platform != "darwin": - return - - try: - import ssl - except ImportError: - return - - # Checks for OpenSSL 1.0.1 - if ssl.OPENSSL_VERSION_NUMBER >= 0x1000100F: - return - - try: - from pip._vendor.urllib3.contrib import securetransport - except (ImportError, OSError): - return - - securetransport.inject_into_urllib3() - - -inject_securetransport() diff --git a/.venv/Lib/site-packages/pip/_internal/utils/logging.py b/.venv/Lib/site-packages/pip/_internal/utils/logging.py index c10e1f4c..95982dfb 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/logging.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/logging.py @@ -155,8 +155,8 @@ class RichPipStreamHandler(RichHandler): # If we are given a diagnostic error to present, present it with indentation. assert isinstance(record.args, tuple) - if record.msg == "[present-rich] %s" and len(record.args) == 1: - rich_renderable = record.args[0] + if getattr(record, "rich", False): + (rich_renderable,) = record.args assert isinstance( rich_renderable, (ConsoleRenderable, RichCast, str) ), f"{rich_renderable} is not rich-console-renderable" diff --git a/.venv/Lib/site-packages/pip/_internal/utils/misc.py b/.venv/Lib/site-packages/pip/_internal/utils/misc.py index baa1ba7e..78060e86 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/misc.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/misc.py @@ -1,6 +1,3 @@ -# The following comment should be removed at some point in the future. -# mypy: strict-optional=False - import contextlib import errno import getpass @@ -14,9 +11,11 @@ import stat import sys import sysconfig import urllib.parse +from functools import partial from io import StringIO from itertools import filterfalse, tee, zip_longest -from types import TracebackType +from pathlib import Path +from types import FunctionType, TracebackType from typing import ( Any, BinaryIO, @@ -32,9 +31,11 @@ from typing import ( Tuple, Type, TypeVar, + Union, cast, ) +from pip._vendor.packaging.requirements import Requirement from pip._vendor.pyproject_hooks import BuildBackendHookCaller from pip._vendor.tenacity import retry, stop_after_delay, wait_fixed @@ -68,6 +69,8 @@ T = TypeVar("T") ExcInfo = Tuple[Type[BaseException], BaseException, TracebackType] VersionInfo = Tuple[int, int, int] NetlocTuple = Tuple[str, Tuple[Optional[str], Optional[str]]] +OnExc = Callable[[FunctionType, Path, BaseException], Any] +OnErr = Callable[[FunctionType, Path, ExcInfo], Any] def get_pip_version() -> str: @@ -125,28 +128,75 @@ def get_prog() -> str: # Retry every half second for up to 3 seconds # Tenacity raises RetryError by default, explicitly raise the original exception @retry(reraise=True, stop=stop_after_delay(3), wait=wait_fixed(0.5)) -def rmtree(dir: str, ignore_errors: bool = False) -> None: - shutil.rmtree(dir, ignore_errors=ignore_errors, onerror=rmtree_errorhandler) +def rmtree( + dir: str, + ignore_errors: bool = False, + onexc: Optional[OnExc] = None, +) -> None: + if ignore_errors: + onexc = _onerror_ignore + if onexc is None: + onexc = _onerror_reraise + handler: OnErr = partial( + # `[func, path, Union[ExcInfo, BaseException]] -> Any` is equivalent to + # `Union[([func, path, ExcInfo] -> Any), ([func, path, BaseException] -> Any)]`. + cast(Union[OnExc, OnErr], rmtree_errorhandler), + onexc=onexc, + ) + if sys.version_info >= (3, 12): + # See https://docs.python.org/3.12/whatsnew/3.12.html#shutil. + shutil.rmtree(dir, onexc=handler) + else: + shutil.rmtree(dir, onerror=handler) + + +def _onerror_ignore(*_args: Any) -> None: + pass + + +def _onerror_reraise(*_args: Any) -> None: + raise -def rmtree_errorhandler(func: Callable[..., Any], path: str, exc_info: ExcInfo) -> None: - """On Windows, the files in .svn are read-only, so when rmtree() tries to - remove them, an exception is thrown. We catch that here, remove the - read-only attribute, and hopefully continue without problems.""" +def rmtree_errorhandler( + func: FunctionType, + path: Path, + exc_info: Union[ExcInfo, BaseException], + *, + onexc: OnExc = _onerror_reraise, +) -> None: + """ + `rmtree` error handler to 'force' a file remove (i.e. like `rm -f`). + + * If a file is readonly then it's write flag is set and operation is + retried. + + * `onerror` is the original callback from `rmtree(... onerror=onerror)` + that is chained at the end if the "rm -f" still fails. + """ try: - has_attr_readonly = not (os.stat(path).st_mode & stat.S_IWRITE) + st_mode = os.stat(path).st_mode except OSError: # it's equivalent to os.path.exists return - if has_attr_readonly: + if not st_mode & stat.S_IWRITE: # convert to read/write - os.chmod(path, stat.S_IWRITE) - # use the original function to repeat the operation - func(path) - return - else: - raise + try: + os.chmod(path, st_mode | stat.S_IWRITE) + except OSError: + pass + else: + # use the original function to repeat the operation + try: + func(path) + return + except OSError: + pass + + if not isinstance(exc_info, BaseException): + _, exc_info, _ = exc_info + onexc(func, path, exc_info) def display_path(path: str) -> str: @@ -338,17 +388,18 @@ def write_output(msg: Any, *args: Any) -> None: class StreamWrapper(StringIO): - orig_stream: TextIO = None + orig_stream: TextIO @classmethod def from_stream(cls, orig_stream: TextIO) -> "StreamWrapper": - cls.orig_stream = orig_stream - return cls() + ret = cls() + ret.orig_stream = orig_stream + return ret # compileall.compile_dir() needs stdout.encoding to print to stdout - # https://github.com/python/mypy/issues/4125 + # type ignore is because TextIOBase.encoding is writeable @property - def encoding(self): # type: ignore + def encoding(self) -> str: # type: ignore return self.orig_stream.encoding @@ -416,7 +467,7 @@ def build_url_from_netloc(netloc: str, scheme: str = "https") -> str: return f"{scheme}://{netloc}" -def parse_netloc(netloc: str) -> Tuple[str, Optional[int]]: +def parse_netloc(netloc: str) -> Tuple[Optional[str], Optional[int]]: """ Return the host-port pair from a netloc. """ @@ -504,7 +555,9 @@ def _redact_netloc(netloc: str) -> Tuple[str]: return (redact_netloc(netloc),) -def split_auth_netloc_from_url(url: str) -> Tuple[str, str, Tuple[str, str]]: +def split_auth_netloc_from_url( + url: str, +) -> Tuple[str, str, Tuple[Optional[str], Optional[str]]]: """ Parse a url into separate netloc, auth, and url with no auth. @@ -526,6 +579,13 @@ def redact_auth_from_url(url: str) -> str: return _transform_url(url, _redact_netloc)[0] +def redact_auth_from_requirement(req: Requirement) -> str: + """Replace the password in a given requirement url with ****.""" + if not req.url: + return str(req) + return str(req).replace(req.url, redact_auth_from_url(req.url)) + + class HiddenText: def __init__(self, secret: str, redacted: str) -> None: self.secret = secret @@ -614,18 +674,6 @@ def hash_file(path: str, blocksize: int = 1 << 20) -> Tuple[Any, int]: return h, length -def is_wheel_installed() -> bool: - """ - Return whether the wheel package is installed. - """ - try: - import wheel # noqa: F401 - except ImportError: - return False - - return True - - def pairwise(iterable: Iterable[Any]) -> Iterator[Tuple[Any, Any]]: """ Return paired elements. @@ -669,7 +717,7 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): def build_wheel( self, wheel_directory: str, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, metadata_directory: Optional[str] = None, ) -> str: cs = self.config_holder.config_settings @@ -678,7 +726,9 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): ) def build_sdist( - self, sdist_directory: str, config_settings: Optional[Dict[str, str]] = None + self, + sdist_directory: str, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, ) -> str: cs = self.config_holder.config_settings return super().build_sdist(sdist_directory, config_settings=cs) @@ -686,7 +736,7 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): def build_editable( self, wheel_directory: str, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, metadata_directory: Optional[str] = None, ) -> str: cs = self.config_holder.config_settings @@ -695,19 +745,19 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): ) def get_requires_for_build_wheel( - self, config_settings: Optional[Dict[str, str]] = None + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_wheel(config_settings=cs) def get_requires_for_build_sdist( - self, config_settings: Optional[Dict[str, str]] = None + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_sdist(config_settings=cs) def get_requires_for_build_editable( - self, config_settings: Optional[Dict[str, str]] = None + self, config_settings: Optional[Dict[str, Union[str, List[str]]]] = None ) -> List[str]: cs = self.config_holder.config_settings return super().get_requires_for_build_editable(config_settings=cs) @@ -715,7 +765,7 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): def prepare_metadata_for_build_wheel( self, metadata_directory: str, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, _allow_fallback: bool = True, ) -> str: cs = self.config_holder.config_settings @@ -728,7 +778,7 @@ class ConfiguredBuildBackendHookCaller(BuildBackendHookCaller): def prepare_metadata_for_build_editable( self, metadata_directory: str, - config_settings: Optional[Dict[str, str]] = None, + config_settings: Optional[Dict[str, Union[str, List[str]]]] = None, _allow_fallback: bool = True, ) -> str: cs = self.config_holder.config_settings diff --git a/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py b/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py index 01ef4a4c..96d1b246 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/setuptools_build.py @@ -103,8 +103,8 @@ def make_setuptools_clean_args( def make_setuptools_develop_args( setup_py_path: str, + *, global_options: Sequence[str], - install_options: Sequence[str], no_user_config: bool, prefix: Optional[str], home: Optional[str], @@ -120,8 +120,6 @@ def make_setuptools_develop_args( args += ["develop", "--no-deps"] - args += install_options - if prefix: args += ["--prefix", prefix] if home is not None: @@ -146,50 +144,3 @@ def make_setuptools_egg_info_args( args += ["--egg-base", egg_info_dir] return args - - -def make_setuptools_install_args( - setup_py_path: str, - global_options: Sequence[str], - install_options: Sequence[str], - record_filename: str, - root: Optional[str], - prefix: Optional[str], - header_dir: Optional[str], - home: Optional[str], - use_user_site: bool, - no_user_config: bool, - pycompile: bool, -) -> List[str]: - assert not (use_user_site and prefix) - assert not (use_user_site and root) - - args = make_setuptools_shim_args( - setup_py_path, - global_options=global_options, - no_user_config=no_user_config, - unbuffered_output=True, - ) - args += ["install", "--record", record_filename] - args += ["--single-version-externally-managed"] - - if root is not None: - args += ["--root", root] - if prefix is not None: - args += ["--prefix", prefix] - if home is not None: - args += ["--home", home] - if use_user_site: - args += ["--user", "--prefix="] - - if pycompile: - args += ["--compile"] - else: - args += ["--no-compile"] - - if header_dir: - args += ["--install-headers", header_dir] - - args += install_options - - return args diff --git a/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py b/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py index 1e8ff50e..79580b05 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/subprocess.py @@ -209,7 +209,7 @@ def call_subprocess( output_lines=all_output if not showing_subprocess else None, ) if log_failed_cmd: - subprocess_logger.error("[present-rich] %s", error) + subprocess_logger.error("%s", error, extra={"rich": True}) subprocess_logger.verbose( "[bold magenta]full command[/]: [blue]%s[/]", escape(format_command_args(cmd)), diff --git a/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py b/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py index 8ee8a1cb..4eec5f37 100644 --- a/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py +++ b/.venv/Lib/site-packages/pip/_internal/utils/temp_dir.py @@ -3,8 +3,19 @@ import itertools import logging import os.path import tempfile +import traceback from contextlib import ExitStack, contextmanager -from typing import Any, Dict, Generator, Optional, TypeVar, Union +from pathlib import Path +from typing import ( + Any, + Callable, + Dict, + Generator, + List, + Optional, + TypeVar, + Union, +) from pip._internal.utils.misc import enum, rmtree @@ -106,6 +117,7 @@ class TempDirectory: delete: Union[bool, None, _Default] = _default, kind: str = "temp", globally_managed: bool = False, + ignore_cleanup_errors: bool = True, ): super().__init__() @@ -128,6 +140,7 @@ class TempDirectory: self._deleted = False self.delete = delete self.kind = kind + self.ignore_cleanup_errors = ignore_cleanup_errors if globally_managed: assert _tempdir_manager is not None @@ -170,7 +183,44 @@ class TempDirectory: self._deleted = True if not os.path.exists(self._path): return - rmtree(self._path) + + errors: List[BaseException] = [] + + def onerror( + func: Callable[..., Any], + path: Path, + exc_val: BaseException, + ) -> None: + """Log a warning for a `rmtree` error and continue""" + formatted_exc = "\n".join( + traceback.format_exception_only(type(exc_val), exc_val) + ) + formatted_exc = formatted_exc.rstrip() # remove trailing new line + if func in (os.unlink, os.remove, os.rmdir): + logger.debug( + "Failed to remove a temporary file '%s' due to %s.\n", + path, + formatted_exc, + ) + else: + logger.debug("%s failed with %s.", func.__qualname__, formatted_exc) + errors.append(exc_val) + + if self.ignore_cleanup_errors: + try: + # first try with tenacity; retrying to handle ephemeral errors + rmtree(self._path, ignore_errors=False) + except OSError: + # last pass ignore/log all errors + rmtree(self._path, onexc=onerror) + if errors: + logger.warning( + "Failed to remove contents in a temporary directory '%s'.\n" + "You can safely remove it manually.", + self._path, + ) + else: + rmtree(self._path) class AdjacentTempDirectory(TempDirectory): diff --git a/.venv/Lib/site-packages/pip/_internal/vcs/git.py b/.venv/Lib/site-packages/pip/_internal/vcs/git.py index 8d1d4993..8c242cf8 100644 --- a/.venv/Lib/site-packages/pip/_internal/vcs/git.py +++ b/.venv/Lib/site-packages/pip/_internal/vcs/git.py @@ -101,7 +101,7 @@ class Git(VersionControl): if not match: logger.warning("Can't parse git version: %s", version) return () - return tuple(int(c) for c in match.groups()) + return (int(match.group(1)), int(match.group(2))) @classmethod def get_current_branch(cls, location: str) -> Optional[str]: diff --git a/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py b/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py index 2a005e0a..e440c122 100644 --- a/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py +++ b/.venv/Lib/site-packages/pip/_internal/vcs/mercurial.py @@ -31,7 +31,7 @@ class Mercurial(VersionControl): @staticmethod def get_base_rev_args(rev: str) -> List[str]: - return [rev] + return [f"-r={rev}"] def fetch_new( self, dest: str, url: HiddenText, rev_options: RevOptions, verbosity: int diff --git a/.venv/Lib/site-packages/pip/_internal/wheel_builder.py b/.venv/Lib/site-packages/pip/_internal/wheel_builder.py index 15b30af5..60d75dd1 100644 --- a/.venv/Lib/site-packages/pip/_internal/wheel_builder.py +++ b/.venv/Lib/site-packages/pip/_internal/wheel_builder.py @@ -5,7 +5,7 @@ import logging import os.path import re import shutil -from typing import Callable, Iterable, List, Optional, Tuple +from typing import Iterable, List, Optional, Tuple from pip._vendor.packaging.utils import canonicalize_name, canonicalize_version from pip._vendor.packaging.version import InvalidVersion, Version @@ -19,12 +19,8 @@ from pip._internal.operations.build.wheel import build_wheel_pep517 from pip._internal.operations.build.wheel_editable import build_wheel_editable from pip._internal.operations.build.wheel_legacy import build_wheel_legacy from pip._internal.req.req_install import InstallRequirement -from pip._internal.utils.deprecation import ( - LegacyInstallReasonMissingWheelPackage, - LegacyInstallReasonNoBinaryForcesSetuptoolsInstall, -) from pip._internal.utils.logging import indent_log -from pip._internal.utils.misc import ensure_dir, hash_file, is_wheel_installed +from pip._internal.utils.misc import ensure_dir, hash_file from pip._internal.utils.setuptools_build import make_setuptools_clean_args from pip._internal.utils.subprocess import call_subprocess from pip._internal.utils.temp_dir import TempDirectory @@ -35,7 +31,6 @@ logger = logging.getLogger(__name__) _egg_info_re = re.compile(r"([a-z0-9_.]+)-([a-z0-9_.!+-]+)", re.IGNORECASE) -BdistWheelAllowedPredicate = Callable[[InstallRequirement], bool] BuildResult = Tuple[List[InstallRequirement], List[InstallRequirement]] @@ -50,7 +45,6 @@ def _contains_egg_info(s: str) -> bool: def _should_build( req: InstallRequirement, need_wheel: bool, - check_bdist_wheel: Optional[BdistWheelAllowedPredicate] = None, ) -> bool: """Return whether an InstallRequirement should be built into a wheel.""" if req.constraint: @@ -78,24 +72,6 @@ def _should_build( # we only build PEP 660 editable requirements return req.supports_pyproject_editable() - if req.use_pep517: - return True - - assert check_bdist_wheel is not None - if not check_bdist_wheel(req): - # /!\ When we change this to unconditionally return True, we must also remove - # support for `--install-option`. Indeed, `--install-option` implies - # `--no-binary` so we can return False here and run `setup.py install`. - # `--global-option` and `--build-option` can remain until we drop support for - # building with `setup.py bdist_wheel`. - req.legacy_install_reason = LegacyInstallReasonNoBinaryForcesSetuptoolsInstall - return False - - if not is_wheel_installed(): - # we don't build legacy requirements if wheel is not installed - req.legacy_install_reason = LegacyInstallReasonMissingWheelPackage - return False - return True @@ -107,11 +83,8 @@ def should_build_for_wheel_command( def should_build_for_install_command( req: InstallRequirement, - check_bdist_wheel_allowed: BdistWheelAllowedPredicate, ) -> bool: - return _should_build( - req, need_wheel=False, check_bdist_wheel=check_bdist_wheel_allowed - ) + return _should_build(req, need_wheel=False) def _should_cache( diff --git a/.venv/Lib/site-packages/pip/_vendor/__init__.py b/.venv/Lib/site-packages/pip/_vendor/__init__.py index b22f7abb..c1884baf 100644 --- a/.venv/Lib/site-packages/pip/_vendor/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/__init__.py @@ -117,4 +117,5 @@ if DEBUNDLED: vendored("rich.traceback") vendored("tenacity") vendored("tomli") + vendored("truststore") vendored("urllib3") diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py index f631ae6d..4d20bc9b 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/__init__.py @@ -8,11 +8,21 @@ Make it easy to import from cachecontrol without long namespaces. """ __author__ = "Eric Larson" __email__ = "eric@ionrock.org" -__version__ = "0.12.11" +__version__ = "0.13.1" -from .wrapper import CacheControl -from .adapter import CacheControlAdapter -from .controller import CacheController +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.controller import CacheController +from pip._vendor.cachecontrol.wrapper import CacheControl + +__all__ = [ + "__author__", + "__email__", + "__version__", + "CacheControlAdapter", + "CacheController", + "CacheControl", +] import logging + logging.getLogger(__name__).addHandler(logging.NullHandler()) diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py index 4266b5ee..2c84208a 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/_cmd.py @@ -1,8 +1,11 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations import logging +from argparse import ArgumentParser +from typing import TYPE_CHECKING from pip._vendor import requests @@ -10,16 +13,19 @@ from pip._vendor.cachecontrol.adapter import CacheControlAdapter from pip._vendor.cachecontrol.cache import DictCache from pip._vendor.cachecontrol.controller import logger -from argparse import ArgumentParser +if TYPE_CHECKING: + from argparse import Namespace + from pip._vendor.cachecontrol.controller import CacheController -def setup_logging(): + +def setup_logging() -> None: logger.setLevel(logging.DEBUG) handler = logging.StreamHandler() logger.addHandler(handler) -def get_session(): +def get_session() -> requests.Session: adapter = CacheControlAdapter( DictCache(), cache_etags=True, serializer=None, heuristic=None ) @@ -27,17 +33,17 @@ def get_session(): sess.mount("http://", adapter) sess.mount("https://", adapter) - sess.cache_controller = adapter.controller + sess.cache_controller = adapter.controller # type: ignore[attr-defined] return sess -def get_args(): +def get_args() -> Namespace: parser = ArgumentParser() parser.add_argument("url", help="The URL to try and cache") return parser.parse_args() -def main(args=None): +def main() -> None: args = get_args() sess = get_session() @@ -48,10 +54,13 @@ def main(args=None): setup_logging() # try setting the cache - sess.cache_controller.cache_response(resp.request, resp.raw) + cache_controller: CacheController = ( + sess.cache_controller # type: ignore[attr-defined] + ) + cache_controller.cache_response(resp.request, resp.raw) # Now try to get it - if sess.cache_controller.cached_request(resp.request): + if cache_controller.cached_request(resp.request): print("Cached!") else: print("Not cached :(") diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py index 94c75e1a..3e83e308 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/adapter.py @@ -1,16 +1,26 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations -import types import functools +import types import zlib +from typing import TYPE_CHECKING, Any, Collection, Mapping from pip._vendor.requests.adapters import HTTPAdapter -from .controller import CacheController, PERMANENT_REDIRECT_STATUSES -from .cache import DictCache -from .filewrapper import CallbackFileWrapper +from pip._vendor.cachecontrol.cache import DictCache +from pip._vendor.cachecontrol.controller import PERMANENT_REDIRECT_STATUSES, CacheController +from pip._vendor.cachecontrol.filewrapper import CallbackFileWrapper + +if TYPE_CHECKING: + from pip._vendor.requests import PreparedRequest, Response + from pip._vendor.urllib3 import HTTPResponse + + from pip._vendor.cachecontrol.cache import BaseCache + from pip._vendor.cachecontrol.heuristics import BaseHeuristic + from pip._vendor.cachecontrol.serialize import Serializer class CacheControlAdapter(HTTPAdapter): @@ -18,16 +28,16 @@ class CacheControlAdapter(HTTPAdapter): def __init__( self, - cache=None, - cache_etags=True, - controller_class=None, - serializer=None, - heuristic=None, - cacheable_methods=None, - *args, - **kw - ): - super(CacheControlAdapter, self).__init__(*args, **kw) + cache: BaseCache | None = None, + cache_etags: bool = True, + controller_class: type[CacheController] | None = None, + serializer: Serializer | None = None, + heuristic: BaseHeuristic | None = None, + cacheable_methods: Collection[str] | None = None, + *args: Any, + **kw: Any, + ) -> None: + super().__init__(*args, **kw) self.cache = DictCache() if cache is None else cache self.heuristic = heuristic self.cacheable_methods = cacheable_methods or ("GET",) @@ -37,7 +47,16 @@ class CacheControlAdapter(HTTPAdapter): self.cache, cache_etags=cache_etags, serializer=serializer ) - def send(self, request, cacheable_methods=None, **kw): + def send( + self, + request: PreparedRequest, + stream: bool = False, + timeout: None | float | tuple[float, float] | tuple[float, None] = None, + verify: bool | str = True, + cert: (None | bytes | str | tuple[bytes | str, bytes | str]) = None, + proxies: Mapping[str, str] | None = None, + cacheable_methods: Collection[str] | None = None, + ) -> Response: """ Send a request. Use the request information to see if it exists in the cache and cache the response if we need to and can. @@ -54,13 +73,17 @@ class CacheControlAdapter(HTTPAdapter): # check for etags and add headers if appropriate request.headers.update(self.controller.conditional_headers(request)) - resp = super(CacheControlAdapter, self).send(request, **kw) + resp = super().send(request, stream, timeout, verify, cert, proxies) return resp def build_response( - self, request, response, from_cache=False, cacheable_methods=None - ): + self, + request: PreparedRequest, + response: HTTPResponse, + from_cache: bool = False, + cacheable_methods: Collection[str] | None = None, + ) -> Response: """ Build a response by making a request or using the cache. @@ -102,36 +125,37 @@ class CacheControlAdapter(HTTPAdapter): else: # Wrap the response file with a wrapper that will cache the # response when the stream has been consumed. - response._fp = CallbackFileWrapper( - response._fp, + response._fp = CallbackFileWrapper( # type: ignore[attr-defined] + response._fp, # type: ignore[attr-defined] functools.partial( self.controller.cache_response, request, response ), ) if response.chunked: - super_update_chunk_length = response._update_chunk_length + super_update_chunk_length = response._update_chunk_length # type: ignore[attr-defined] - def _update_chunk_length(self): + def _update_chunk_length(self: HTTPResponse) -> None: super_update_chunk_length() if self.chunk_left == 0: - self._fp._close() + self._fp._close() # type: ignore[attr-defined] - response._update_chunk_length = types.MethodType( + response._update_chunk_length = types.MethodType( # type: ignore[attr-defined] _update_chunk_length, response ) - resp = super(CacheControlAdapter, self).build_response(request, response) + resp: Response = super().build_response(request, response) # type: ignore[no-untyped-call] # See if we should invalidate the cache. if request.method in self.invalidating_methods and resp.ok: + assert request.url is not None cache_url = self.controller.cache_url(request.url) self.cache.delete(cache_url) # Give the request a from_cache attr to let people use it - resp.from_cache = from_cache + resp.from_cache = from_cache # type: ignore[attr-defined] return resp - def close(self): + def close(self) -> None: self.cache.close() - super(CacheControlAdapter, self).close() + super().close() # type: ignore[no-untyped-call] diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py index 2a965f59..3293b005 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/cache.py @@ -6,38 +6,46 @@ The cache object API for implementing caches. The default is a thread safe in-memory dictionary. """ +from __future__ import annotations + from threading import Lock +from typing import IO, TYPE_CHECKING, MutableMapping +if TYPE_CHECKING: + from datetime import datetime -class BaseCache(object): - def get(self, key): +class BaseCache: + def get(self, key: str) -> bytes | None: raise NotImplementedError() - def set(self, key, value, expires=None): + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: raise NotImplementedError() - def delete(self, key): + def delete(self, key: str) -> None: raise NotImplementedError() - def close(self): + def close(self) -> None: pass class DictCache(BaseCache): - - def __init__(self, init_dict=None): + def __init__(self, init_dict: MutableMapping[str, bytes] | None = None) -> None: self.lock = Lock() self.data = init_dict or {} - def get(self, key): + def get(self, key: str) -> bytes | None: return self.data.get(key, None) - def set(self, key, value, expires=None): + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: with self.lock: self.data.update({key: value}) - def delete(self, key): + def delete(self, key: str) -> None: with self.lock: if key in self.data: self.data.pop(key) @@ -55,10 +63,11 @@ class SeparateBodyBaseCache(BaseCache): Similarly, the body should be loaded separately via ``get_body()``. """ - def set_body(self, key, body): + + def set_body(self, key: str, body: bytes) -> None: raise NotImplementedError() - def get_body(self, key): + def get_body(self, key: str) -> IO[bytes] | None: """ Return the body as file-like object. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py index 37827291..24ff469f 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/__init__.py @@ -2,8 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -from .file_cache import FileCache, SeparateBodyFileCache -from .redis_cache import RedisCache - +from pip._vendor.cachecontrol.caches.file_cache import FileCache, SeparateBodyFileCache +from pip._vendor.cachecontrol.caches.redis_cache import RedisCache __all__ = ["FileCache", "SeparateBodyFileCache", "RedisCache"] diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py index f1ddb2eb..1fd28013 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/file_cache.py @@ -1,22 +1,23 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations import hashlib import os from textwrap import dedent +from typing import IO, TYPE_CHECKING -from ..cache import BaseCache, SeparateBodyBaseCache -from ..controller import CacheController +from pip._vendor.cachecontrol.cache import BaseCache, SeparateBodyBaseCache +from pip._vendor.cachecontrol.controller import CacheController -try: - FileNotFoundError -except NameError: - # py2.X - FileNotFoundError = (IOError, OSError) +if TYPE_CHECKING: + from datetime import datetime + from filelock import BaseFileLock -def _secure_open_write(filename, fmode): + +def _secure_open_write(filename: str, fmode: int) -> IO[bytes]: # We only want to write to this file, so open it in write only mode flags = os.O_WRONLY @@ -39,7 +40,7 @@ def _secure_open_write(filename, fmode): # there try: os.remove(filename) - except (IOError, OSError): + except OSError: # The file must not exist already, so we can just skip ahead to opening pass @@ -62,37 +63,27 @@ class _FileCacheMixin: def __init__( self, - directory, - forever=False, - filemode=0o0600, - dirmode=0o0700, - use_dir_lock=None, - lock_class=None, - ): - - if use_dir_lock is not None and lock_class is not None: - raise ValueError("Cannot use use_dir_lock and lock_class together") - + directory: str, + forever: bool = False, + filemode: int = 0o0600, + dirmode: int = 0o0700, + lock_class: type[BaseFileLock] | None = None, + ) -> None: try: - from lockfile import LockFile - from lockfile.mkdirlockfile import MkdirLockFile + if lock_class is None: + from filelock import FileLock + + lock_class = FileLock except ImportError: notice = dedent( """ NOTE: In order to use the FileCache you must have - lockfile installed. You can install it via pip: - pip install lockfile + filelock installed. You can install it via pip: + pip install filelock """ ) raise ImportError(notice) - else: - if use_dir_lock: - lock_class = MkdirLockFile - - elif lock_class is None: - lock_class = LockFile - self.directory = directory self.forever = forever self.filemode = filemode @@ -100,17 +91,17 @@ class _FileCacheMixin: self.lock_class = lock_class @staticmethod - def encode(x): + def encode(x: str) -> str: return hashlib.sha224(x.encode()).hexdigest() - def _fn(self, name): + def _fn(self, name: str) -> str: # NOTE: This method should not change as some may depend on it. # See: https://github.com/ionrock/cachecontrol/issues/63 hashed = self.encode(name) parts = list(hashed[:5]) + [hashed] return os.path.join(self.directory, *parts) - def get(self, key): + def get(self, key: str) -> bytes | None: name = self._fn(key) try: with open(name, "rb") as fh: @@ -119,26 +110,28 @@ class _FileCacheMixin: except FileNotFoundError: return None - def set(self, key, value, expires=None): + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: name = self._fn(key) self._write(name, value) - def _write(self, path, data: bytes): + def _write(self, path: str, data: bytes) -> None: """ Safely write the data to the given path. """ # Make sure the directory exists try: os.makedirs(os.path.dirname(path), self.dirmode) - except (IOError, OSError): + except OSError: pass - with self.lock_class(path) as lock: + with self.lock_class(path + ".lock"): # Write our actual file - with _secure_open_write(lock.path, self.filemode) as fh: + with _secure_open_write(path, self.filemode) as fh: fh.write(data) - def _delete(self, key, suffix): + def _delete(self, key: str, suffix: str) -> None: name = self._fn(key) + suffix if not self.forever: try: @@ -153,7 +146,7 @@ class FileCache(_FileCacheMixin, BaseCache): downloads. """ - def delete(self, key): + def delete(self, key: str) -> None: self._delete(key, "") @@ -163,23 +156,23 @@ class SeparateBodyFileCache(_FileCacheMixin, SeparateBodyBaseCache): peak memory usage. """ - def get_body(self, key): + def get_body(self, key: str) -> IO[bytes] | None: name = self._fn(key) + ".body" try: return open(name, "rb") except FileNotFoundError: return None - def set_body(self, key, body): + def set_body(self, key: str, body: bytes) -> None: name = self._fn(key) + ".body" self._write(name, body) - def delete(self, key): + def delete(self, key: str) -> None: self._delete(key, "") self._delete(key, ".body") -def url_to_file_path(url, filecache): +def url_to_file_path(url: str, filecache: FileCache) -> str: """Return the file cache path based on the URL. This does not ensure the file exists! diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py index 2cba4b07..f4f68c47 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/caches/redis_cache.py @@ -1,39 +1,48 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations -from __future__ import division -from datetime import datetime +from datetime import datetime, timezone +from typing import TYPE_CHECKING + from pip._vendor.cachecontrol.cache import BaseCache +if TYPE_CHECKING: + from redis import Redis -class RedisCache(BaseCache): - def __init__(self, conn): +class RedisCache(BaseCache): + def __init__(self, conn: Redis[bytes]) -> None: self.conn = conn - def get(self, key): + def get(self, key: str) -> bytes | None: return self.conn.get(key) - def set(self, key, value, expires=None): + def set( + self, key: str, value: bytes, expires: int | datetime | None = None + ) -> None: if not expires: self.conn.set(key, value) elif isinstance(expires, datetime): - expires = expires - datetime.utcnow() - self.conn.setex(key, int(expires.total_seconds()), value) + now_utc = datetime.now(timezone.utc) + if expires.tzinfo is None: + now_utc = now_utc.replace(tzinfo=None) + delta = expires - now_utc + self.conn.setex(key, int(delta.total_seconds()), value) else: self.conn.setex(key, expires, value) - def delete(self, key): + def delete(self, key: str) -> None: self.conn.delete(key) - def clear(self): + def clear(self) -> None: """Helper for clearing all the keys in a database. Use with caution!""" for key in self.conn.keys(): self.conn.delete(key) - def close(self): + def close(self) -> None: """Redis uses connection pooling, no need to close the connection.""" pass diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py deleted file mode 100644 index ccec9379..00000000 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/compat.py +++ /dev/null @@ -1,32 +0,0 @@ -# SPDX-FileCopyrightText: 2015 Eric Larson -# -# SPDX-License-Identifier: Apache-2.0 - -try: - from urllib.parse import urljoin -except ImportError: - from urlparse import urljoin - - -try: - import cPickle as pickle -except ImportError: - import pickle - -# Handle the case where the requests module has been patched to not have -# urllib3 bundled as part of its source. -try: - from pip._vendor.requests.packages.urllib3.response import HTTPResponse -except ImportError: - from pip._vendor.urllib3.response import HTTPResponse - -try: - from pip._vendor.requests.packages.urllib3.util import is_fp_closed -except ImportError: - from pip._vendor.urllib3.util import is_fp_closed - -# Replicate some six behaviour -try: - text_type = unicode -except NameError: - text_type = str diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py index 7f23529f..586b9f97 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/controller.py @@ -5,17 +5,27 @@ """ The httplib2 algorithms ported for use with requests. """ +from __future__ import annotations + +import calendar import logging import re -import calendar import time from email.utils import parsedate_tz +from typing import TYPE_CHECKING, Collection, Mapping from pip._vendor.requests.structures import CaseInsensitiveDict -from .cache import DictCache, SeparateBodyBaseCache -from .serialize import Serializer +from pip._vendor.cachecontrol.cache import DictCache, SeparateBodyBaseCache +from pip._vendor.cachecontrol.serialize import Serializer + +if TYPE_CHECKING: + from typing import Literal + + from pip._vendor.requests import PreparedRequest + from pip._vendor.urllib3 import HTTPResponse + from pip._vendor.cachecontrol.cache import BaseCache logger = logging.getLogger(__name__) @@ -24,20 +34,26 @@ URI = re.compile(r"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?") PERMANENT_REDIRECT_STATUSES = (301, 308) -def parse_uri(uri): +def parse_uri(uri: str) -> tuple[str, str, str, str, str]: """Parses a URI using the regex given in Appendix B of RFC 3986. (scheme, authority, path, query, fragment) = parse_uri(uri) """ - groups = URI.match(uri).groups() + match = URI.match(uri) + assert match is not None + groups = match.groups() return (groups[1], groups[3], groups[4], groups[6], groups[8]) -class CacheController(object): +class CacheController: """An interface to see if request should cached or not.""" def __init__( - self, cache=None, cache_etags=True, serializer=None, status_codes=None + self, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Serializer | None = None, + status_codes: Collection[int] | None = None, ): self.cache = DictCache() if cache is None else cache self.cache_etags = cache_etags @@ -45,7 +61,7 @@ class CacheController(object): self.cacheable_status_codes = status_codes or (200, 203, 300, 301, 308) @classmethod - def _urlnorm(cls, uri): + def _urlnorm(cls, uri: str) -> str: """Normalize the URL to create a safe key for the cache""" (scheme, authority, path, query, fragment) = parse_uri(uri) if not scheme or not authority: @@ -65,10 +81,10 @@ class CacheController(object): return defrag_uri @classmethod - def cache_url(cls, uri): + def cache_url(cls, uri: str) -> str: return cls._urlnorm(uri) - def parse_cache_control(self, headers): + def parse_cache_control(self, headers: Mapping[str, str]) -> dict[str, int | None]: known_directives = { # https://tools.ietf.org/html/rfc7234#section-5.2 "max-age": (int, True), @@ -87,7 +103,7 @@ class CacheController(object): cc_headers = headers.get("cache-control", headers.get("Cache-Control", "")) - retval = {} + retval: dict[str, int | None] = {} for cc_directive in cc_headers.split(","): if not cc_directive.strip(): @@ -122,11 +138,33 @@ class CacheController(object): return retval - def cached_request(self, request): + def _load_from_cache(self, request: PreparedRequest) -> HTTPResponse | None: + """ + Load a cached response, or return None if it's not available. + """ + cache_url = request.url + assert cache_url is not None + cache_data = self.cache.get(cache_url) + if cache_data is None: + logger.debug("No cache entry available") + return None + + if isinstance(self.cache, SeparateBodyBaseCache): + body_file = self.cache.get_body(cache_url) + else: + body_file = None + + result = self.serializer.loads(request, cache_data, body_file) + if result is None: + logger.warning("Cache entry deserialization failed, entry ignored") + return result + + def cached_request(self, request: PreparedRequest) -> HTTPResponse | Literal[False]: """ Return a cached response if it exists in the cache, otherwise return False. """ + assert request.url is not None cache_url = self.cache_url(request.url) logger.debug('Looking up "%s" in the cache', cache_url) cc = self.parse_cache_control(request.headers) @@ -140,21 +178,9 @@ class CacheController(object): logger.debug('Request header has "max_age" as 0, cache bypassed') return False - # Request allows serving from the cache, let's see if we find something - cache_data = self.cache.get(cache_url) - if cache_data is None: - logger.debug("No cache entry available") - return False - - if isinstance(self.cache, SeparateBodyBaseCache): - body_file = self.cache.get_body(cache_url) - else: - body_file = None - - # Check whether it can be deserialized - resp = self.serializer.loads(request, cache_data, body_file) + # Check whether we can load the response from the cache: + resp = self._load_from_cache(request) if not resp: - logger.warning("Cache entry deserialization failed, entry ignored") return False # If we have a cached permanent redirect, return it immediately. We @@ -174,7 +200,7 @@ class CacheController(object): logger.debug(msg) return resp - headers = CaseInsensitiveDict(resp.headers) + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) if not headers or "date" not in headers: if "etag" not in headers: # Without date or etag, the cached response can never be used @@ -185,7 +211,9 @@ class CacheController(object): return False now = time.time() - date = calendar.timegm(parsedate_tz(headers["date"])) + time_tuple = parsedate_tz(headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) current_age = max(0, now - date) logger.debug("Current age based on date: %i", current_age) @@ -199,28 +227,30 @@ class CacheController(object): freshness_lifetime = 0 # Check the max-age pragma in the cache control header - if "max-age" in resp_cc: - freshness_lifetime = resp_cc["max-age"] + max_age = resp_cc.get("max-age") + if max_age is not None: + freshness_lifetime = max_age logger.debug("Freshness lifetime from max-age: %i", freshness_lifetime) # If there isn't a max-age, check for an expires header elif "expires" in headers: expires = parsedate_tz(headers["expires"]) if expires is not None: - expire_time = calendar.timegm(expires) - date + expire_time = calendar.timegm(expires[:6]) - date freshness_lifetime = max(0, expire_time) logger.debug("Freshness lifetime from expires: %i", freshness_lifetime) # Determine if we are setting freshness limit in the # request. Note, this overrides what was in the response. - if "max-age" in cc: - freshness_lifetime = cc["max-age"] + max_age = cc.get("max-age") + if max_age is not None: + freshness_lifetime = max_age logger.debug( "Freshness lifetime from request max-age: %i", freshness_lifetime ) - if "min-fresh" in cc: - min_fresh = cc["min-fresh"] + min_fresh = cc.get("min-fresh") + if min_fresh is not None: # adjust our current age by our min fresh current_age += min_fresh logger.debug("Adjusted current age from min-fresh: %i", current_age) @@ -239,13 +269,12 @@ class CacheController(object): # return the original handler return False - def conditional_headers(self, request): - cache_url = self.cache_url(request.url) - resp = self.serializer.loads(request, self.cache.get(cache_url)) + def conditional_headers(self, request: PreparedRequest) -> dict[str, str]: + resp = self._load_from_cache(request) new_headers = {} if resp: - headers = CaseInsensitiveDict(resp.headers) + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict(resp.headers) if "etag" in headers: new_headers["If-None-Match"] = headers["ETag"] @@ -255,7 +284,14 @@ class CacheController(object): return new_headers - def _cache_set(self, cache_url, request, response, body=None, expires_time=None): + def _cache_set( + self, + cache_url: str, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + expires_time: int | None = None, + ) -> None: """ Store the data in the cache. """ @@ -267,7 +303,10 @@ class CacheController(object): self.serializer.dumps(request, response, b""), expires=expires_time, ) - self.cache.set_body(cache_url, body) + # body is None can happen when, for example, we're only updating + # headers, as is the case in update_cached_response(). + if body is not None: + self.cache.set_body(cache_url, body) else: self.cache.set( cache_url, @@ -275,7 +314,13 @@ class CacheController(object): expires=expires_time, ) - def cache_response(self, request, response, body=None, status_codes=None): + def cache_response( + self, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + status_codes: Collection[int] | None = None, + ) -> None: """ Algorithm for caching requests. @@ -290,10 +335,14 @@ class CacheController(object): ) return - response_headers = CaseInsensitiveDict(response.headers) + response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + response.headers + ) if "date" in response_headers: - date = calendar.timegm(parsedate_tz(response_headers["date"])) + time_tuple = parsedate_tz(response_headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) else: date = 0 @@ -312,6 +361,7 @@ class CacheController(object): cc_req = self.parse_cache_control(request.headers) cc = self.parse_cache_control(response_headers) + assert request.url is not None cache_url = self.cache_url(request.url) logger.debug('Updating cache with response from "%s"', cache_url) @@ -344,11 +394,11 @@ class CacheController(object): if response_headers.get("expires"): expires = parsedate_tz(response_headers["expires"]) if expires is not None: - expires_time = calendar.timegm(expires) - date + expires_time = calendar.timegm(expires[:6]) - date expires_time = max(expires_time, 14 * 86400) - logger.debug("etag object cached for {0} seconds".format(expires_time)) + logger.debug(f"etag object cached for {expires_time} seconds") logger.debug("Caching due to etag") self._cache_set(cache_url, request, response, body, expires_time) @@ -362,11 +412,14 @@ class CacheController(object): # is no date header then we can't do anything about expiring # the cache. elif "date" in response_headers: - date = calendar.timegm(parsedate_tz(response_headers["date"])) + time_tuple = parsedate_tz(response_headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) # cache when there is a max-age > 0 - if "max-age" in cc and cc["max-age"] > 0: + max_age = cc.get("max-age") + if max_age is not None and max_age > 0: logger.debug("Caching b/c date exists and max-age > 0") - expires_time = cc["max-age"] + expires_time = max_age self._cache_set( cache_url, request, @@ -381,12 +434,12 @@ class CacheController(object): if response_headers["expires"]: expires = parsedate_tz(response_headers["expires"]) if expires is not None: - expires_time = calendar.timegm(expires) - date + expires_time = calendar.timegm(expires[:6]) - date else: expires_time = None logger.debug( - "Caching b/c of expires header. expires in {0} seconds".format( + "Caching b/c of expires header. expires in {} seconds".format( expires_time ) ) @@ -398,16 +451,18 @@ class CacheController(object): expires_time, ) - def update_cached_response(self, request, response): + def update_cached_response( + self, request: PreparedRequest, response: HTTPResponse + ) -> HTTPResponse: """On a 304 we will get a new set of headers that we want to update our cached value with, assuming we have one. This should only ever be called when we've sent an ETag and gotten a 304 as the response. """ + assert request.url is not None cache_url = self.cache_url(request.url) - - cached_response = self.serializer.loads(request, self.cache.get(cache_url)) + cached_response = self._load_from_cache(request) if not cached_response: # we didn't have a cached response @@ -423,11 +478,11 @@ class CacheController(object): excluded_headers = ["content-length"] cached_response.headers.update( - dict( - (k, v) - for k, v in response.headers.items() + { + k: v + for k, v in response.headers.items() # type: ignore[no-untyped-call] if k.lower() not in excluded_headers - ) + } ) # we want a 200 b/c we have content via the cache diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py index f5ed5f6f..25143902 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/filewrapper.py @@ -1,12 +1,17 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations -from tempfile import NamedTemporaryFile import mmap +from tempfile import NamedTemporaryFile +from typing import TYPE_CHECKING, Any, Callable + +if TYPE_CHECKING: + from http.client import HTTPResponse -class CallbackFileWrapper(object): +class CallbackFileWrapper: """ Small wrapper around a fp object which will tee everything read into a buffer, and when that file is closed it will execute a callback with the @@ -25,12 +30,14 @@ class CallbackFileWrapper(object): performance impact. """ - def __init__(self, fp, callback): + def __init__( + self, fp: HTTPResponse, callback: Callable[[bytes], None] | None + ) -> None: self.__buf = NamedTemporaryFile("rb+", delete=True) self.__fp = fp self.__callback = callback - def __getattr__(self, name): + def __getattr__(self, name: str) -> Any: # The vaguaries of garbage collection means that self.__fp is # not always set. By using __getattribute__ and the private # name[0] allows looking up the attribute value and raising an @@ -42,7 +49,7 @@ class CallbackFileWrapper(object): fp = self.__getattribute__("_CallbackFileWrapper__fp") return getattr(fp, name) - def __is_fp_closed(self): + def __is_fp_closed(self) -> bool: try: return self.__fp.fp is None @@ -50,7 +57,8 @@ class CallbackFileWrapper(object): pass try: - return self.__fp.closed + closed: bool = self.__fp.closed + return closed except AttributeError: pass @@ -59,7 +67,7 @@ class CallbackFileWrapper(object): # TODO: Add some logging here... return False - def _close(self): + def _close(self) -> None: if self.__callback: if self.__buf.tell() == 0: # Empty file: @@ -86,8 +94,8 @@ class CallbackFileWrapper(object): # Important when caching big files. self.__buf.close() - def read(self, amt=None): - data = self.__fp.read(amt) + def read(self, amt: int | None = None) -> bytes: + data: bytes = self.__fp.read(amt) if data: # We may be dealing with b'', a sign that things are over: # it's passed e.g. after we've already closed self.__buf. @@ -97,8 +105,8 @@ class CallbackFileWrapper(object): return data - def _safe_read(self, amt): - data = self.__fp._safe_read(amt) + def _safe_read(self, amt: int) -> bytes: + data: bytes = self.__fp._safe_read(amt) # type: ignore[attr-defined] if amt == 2 and data == b"\r\n": # urllib executes this read to toss the CRLF at the end # of the chunk. diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py index ebe4a96f..b9d72ca4 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/heuristics.py @@ -1,29 +1,31 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations import calendar import time - +from datetime import datetime, timedelta, timezone from email.utils import formatdate, parsedate, parsedate_tz +from typing import TYPE_CHECKING, Any, Mapping -from datetime import datetime, timedelta +if TYPE_CHECKING: + from pip._vendor.urllib3 import HTTPResponse TIME_FMT = "%a, %d %b %Y %H:%M:%S GMT" -def expire_after(delta, date=None): - date = date or datetime.utcnow() +def expire_after(delta: timedelta, date: datetime | None = None) -> datetime: + date = date or datetime.now(timezone.utc) return date + delta -def datetime_to_header(dt): +def datetime_to_header(dt: datetime) -> str: return formatdate(calendar.timegm(dt.timetuple())) -class BaseHeuristic(object): - - def warning(self, response): +class BaseHeuristic: + def warning(self, response: HTTPResponse) -> str | None: """ Return a valid 1xx warning header value describing the cache adjustments. @@ -34,7 +36,7 @@ class BaseHeuristic(object): """ return '110 - "Response is Stale"' - def update_headers(self, response): + def update_headers(self, response: HTTPResponse) -> dict[str, str]: """Update the response headers with any new headers. NOTE: This SHOULD always include some Warning header to @@ -43,7 +45,7 @@ class BaseHeuristic(object): """ return {} - def apply(self, response): + def apply(self, response: HTTPResponse) -> HTTPResponse: updated_headers = self.update_headers(response) if updated_headers: @@ -61,12 +63,12 @@ class OneDayCache(BaseHeuristic): future. """ - def update_headers(self, response): + def update_headers(self, response: HTTPResponse) -> dict[str, str]: headers = {} if "expires" not in response.headers: date = parsedate(response.headers["date"]) - expires = expire_after(timedelta(days=1), date=datetime(*date[:6])) + expires = expire_after(timedelta(days=1), date=datetime(*date[:6], tzinfo=timezone.utc)) # type: ignore[misc] headers["expires"] = datetime_to_header(expires) headers["cache-control"] = "public" return headers @@ -77,14 +79,14 @@ class ExpiresAfter(BaseHeuristic): Cache **all** requests for a defined time period. """ - def __init__(self, **kw): + def __init__(self, **kw: Any) -> None: self.delta = timedelta(**kw) - def update_headers(self, response): + def update_headers(self, response: HTTPResponse) -> dict[str, str]: expires = expire_after(self.delta) return {"expires": datetime_to_header(expires), "cache-control": "public"} - def warning(self, response): + def warning(self, response: HTTPResponse) -> str | None: tmpl = "110 - Automatically cached for %s. Response might be stale" return tmpl % self.delta @@ -101,12 +103,23 @@ class LastModified(BaseHeuristic): http://lxr.mozilla.org/mozilla-release/source/netwerk/protocol/http/nsHttpResponseHead.cpp#397 Unlike mozilla we limit this to 24-hr. """ + cacheable_by_default_statuses = { - 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, 501 + 200, + 203, + 204, + 206, + 300, + 301, + 404, + 405, + 410, + 414, + 501, } - def update_headers(self, resp): - headers = resp.headers + def update_headers(self, resp: HTTPResponse) -> dict[str, str]: + headers: Mapping[str, str] = resp.headers if "expires" in headers: return {} @@ -120,9 +133,11 @@ class LastModified(BaseHeuristic): if "date" not in headers or "last-modified" not in headers: return {} - date = calendar.timegm(parsedate_tz(headers["date"])) + time_tuple = parsedate_tz(headers["date"]) + assert time_tuple is not None + date = calendar.timegm(time_tuple[:6]) last_modified = parsedate(headers["last-modified"]) - if date is None or last_modified is None: + if last_modified is None: return {} now = time.time() @@ -135,5 +150,5 @@ class LastModified(BaseHeuristic): expires = date + freshness_lifetime return {"expires": time.strftime(TIME_FMT, time.gmtime(expires))} - def warning(self, resp): + def warning(self, resp: HTTPResponse) -> str | None: return None diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py index 7fe1a3e3..f9e967c3 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/serialize.py @@ -1,78 +1,76 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations -import base64 import io -import json -import zlib +from typing import IO, TYPE_CHECKING, Any, Mapping, cast from pip._vendor import msgpack from pip._vendor.requests.structures import CaseInsensitiveDict +from pip._vendor.urllib3 import HTTPResponse -from .compat import HTTPResponse, pickle, text_type +if TYPE_CHECKING: + from pip._vendor.requests import PreparedRequest -def _b64_decode_bytes(b): - return base64.b64decode(b.encode("ascii")) +class Serializer: + serde_version = "4" - -def _b64_decode_str(s): - return _b64_decode_bytes(s).decode("utf8") - - -_default_body_read = object() - - -class Serializer(object): - def dumps(self, request, response, body=None): - response_headers = CaseInsensitiveDict(response.headers) + def dumps( + self, + request: PreparedRequest, + response: HTTPResponse, + body: bytes | None = None, + ) -> bytes: + response_headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + response.headers + ) if body is None: # When a body isn't passed in, we'll read the response. We # also update the response with a new file handler to be # sure it acts as though it was never read. body = response.read(decode_content=False) - response._fp = io.BytesIO(body) - - # NOTE: This is all a bit weird, but it's really important that on - # Python 2.x these objects are unicode and not str, even when - # they contain only ascii. The problem here is that msgpack - # understands the difference between unicode and bytes and we - # have it set to differentiate between them, however Python 2 - # doesn't know the difference. Forcing these to unicode will be - # enough to have msgpack know the difference. + response._fp = io.BytesIO(body) # type: ignore[attr-defined] + response.length_remaining = len(body) + data = { - u"response": { - u"body": body, # Empty bytestring if body is stored separately - u"headers": dict( - (text_type(k), text_type(v)) for k, v in response.headers.items() - ), - u"status": response.status, - u"version": response.version, - u"reason": text_type(response.reason), - u"strict": response.strict, - u"decode_content": response.decode_content, + "response": { + "body": body, # Empty bytestring if body is stored separately + "headers": {str(k): str(v) for k, v in response.headers.items()}, # type: ignore[no-untyped-call] + "status": response.status, + "version": response.version, + "reason": str(response.reason), + "decode_content": response.decode_content, } } # Construct our vary headers - data[u"vary"] = {} - if u"vary" in response_headers: - varied_headers = response_headers[u"vary"].split(",") + data["vary"] = {} + if "vary" in response_headers: + varied_headers = response_headers["vary"].split(",") for header in varied_headers: - header = text_type(header).strip() + header = str(header).strip() header_value = request.headers.get(header, None) if header_value is not None: - header_value = text_type(header_value) - data[u"vary"][header] = header_value + header_value = str(header_value) + data["vary"][header] = header_value + + return b",".join([f"cc={self.serde_version}".encode(), self.serialize(data)]) - return b",".join([b"cc=4", msgpack.dumps(data, use_bin_type=True)]) + def serialize(self, data: dict[str, Any]) -> bytes: + return cast(bytes, msgpack.dumps(data, use_bin_type=True)) - def loads(self, request, data, body_file=None): + def loads( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: # Short circuit if we've been given an empty set of data if not data: - return + return None # Determine what version of the serializer the data was serialized # with @@ -88,18 +86,23 @@ class Serializer(object): ver = b"cc=0" # Get the version number out of the cc=N - ver = ver.split(b"=", 1)[-1].decode("ascii") + verstr = ver.split(b"=", 1)[-1].decode("ascii") # Dispatch to the actual load method for the given version try: - return getattr(self, "_loads_v{}".format(ver))(request, data, body_file) + return getattr(self, f"_loads_v{verstr}")(request, data, body_file) # type: ignore[no-any-return] except AttributeError: # This is a version we don't have a loads function for, so we'll # just treat it as a miss and return None - return - - def prepare_response(self, request, cached, body_file=None): + return None + + def prepare_response( + self, + request: PreparedRequest, + cached: Mapping[str, Any], + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: """Verify our vary headers match and construct a real urllib3 HTTPResponse object. """ @@ -108,23 +111,26 @@ class Serializer(object): # This case is also handled in the controller code when creating # a cache entry, but is left here for backwards compatibility. if "*" in cached.get("vary", {}): - return + return None # Ensure that the Vary headers for the cached response match our # request for header, value in cached.get("vary", {}).items(): if request.headers.get(header, None) != value: - return + return None body_raw = cached["response"].pop("body") - headers = CaseInsensitiveDict(data=cached["response"]["headers"]) + headers: CaseInsensitiveDict[str] = CaseInsensitiveDict( + data=cached["response"]["headers"] + ) if headers.get("transfer-encoding", "") == "chunked": headers.pop("transfer-encoding") cached["response"]["headers"] = headers try: + body: IO[bytes] if body_file is None: body = io.BytesIO(body_raw) else: @@ -138,53 +144,63 @@ class Serializer(object): # TypeError: 'str' does not support the buffer interface body = io.BytesIO(body_raw.encode("utf8")) + # Discard any `strict` parameter serialized by older version of cachecontrol. + cached["response"].pop("strict", None) + return HTTPResponse(body=body, preload_content=False, **cached["response"]) - def _loads_v0(self, request, data, body_file=None): + def _loads_v0( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> None: # The original legacy cache data. This doesn't contain enough # information to construct everything we need, so we'll treat this as # a miss. - return - - def _loads_v1(self, request, data, body_file=None): - try: - cached = pickle.loads(data) - except ValueError: - return - - return self.prepare_response(request, cached, body_file) - - def _loads_v2(self, request, data, body_file=None): - assert body_file is None - try: - cached = json.loads(zlib.decompress(data).decode("utf8")) - except (ValueError, zlib.error): - return - - # We need to decode the items that we've base64 encoded - cached["response"]["body"] = _b64_decode_bytes(cached["response"]["body"]) - cached["response"]["headers"] = dict( - (_b64_decode_str(k), _b64_decode_str(v)) - for k, v in cached["response"]["headers"].items() - ) - cached["response"]["reason"] = _b64_decode_str(cached["response"]["reason"]) - cached["vary"] = dict( - (_b64_decode_str(k), _b64_decode_str(v) if v is not None else v) - for k, v in cached["vary"].items() - ) - - return self.prepare_response(request, cached, body_file) - - def _loads_v3(self, request, data, body_file): + return None + + def _loads_v1( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: + # The "v1" pickled cache format. This is no longer supported + # for security reasons, so we treat it as a miss. + return None + + def _loads_v2( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: + # The "v2" compressed base64 cache format. + # This has been removed due to age and poor size/performance + # characteristics, so we treat it as a miss. + return None + + def _loads_v3( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> None: # Due to Python 2 encoding issues, it's impossible to know for sure # exactly how to load v3 entries, thus we'll treat these as a miss so # that they get rewritten out as v4 entries. - return - - def _loads_v4(self, request, data, body_file=None): + return None + + def _loads_v4( + self, + request: PreparedRequest, + data: bytes, + body_file: IO[bytes] | None = None, + ) -> HTTPResponse | None: try: cached = msgpack.loads(data, raw=False) except ValueError: - return + return None return self.prepare_response(request, cached, body_file) diff --git a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py index b6ee7f20..f618bc36 100644 --- a/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py +++ b/.venv/Lib/site-packages/pip/_vendor/cachecontrol/wrapper.py @@ -1,22 +1,32 @@ # SPDX-FileCopyrightText: 2015 Eric Larson # # SPDX-License-Identifier: Apache-2.0 +from __future__ import annotations -from .adapter import CacheControlAdapter -from .cache import DictCache +from typing import TYPE_CHECKING, Collection +from pip._vendor.cachecontrol.adapter import CacheControlAdapter +from pip._vendor.cachecontrol.cache import DictCache -def CacheControl( - sess, - cache=None, - cache_etags=True, - serializer=None, - heuristic=None, - controller_class=None, - adapter_class=None, - cacheable_methods=None, -): +if TYPE_CHECKING: + from pip._vendor import requests + + from pip._vendor.cachecontrol.cache import BaseCache + from pip._vendor.cachecontrol.controller import CacheController + from pip._vendor.cachecontrol.heuristics import BaseHeuristic + from pip._vendor.cachecontrol.serialize import Serializer + +def CacheControl( + sess: requests.Session, + cache: BaseCache | None = None, + cache_etags: bool = True, + serializer: Serializer | None = None, + heuristic: BaseHeuristic | None = None, + controller_class: type[CacheController] | None = None, + adapter_class: type[CacheControlAdapter] | None = None, + cacheable_methods: Collection[str] | None = None, +) -> requests.Session: cache = DictCache() if cache is None else cache adapter_class = adapter_class or CacheControlAdapter adapter = adapter_class( diff --git a/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py b/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py index a3546f12..8ce89cef 100644 --- a/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/certifi/__init__.py @@ -1,4 +1,4 @@ from .core import contents, where __all__ = ["contents", "where"] -__version__ = "2022.12.07" +__version__ = "2023.07.22" diff --git a/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem b/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem index df9e4e3c..02123695 100644 --- a/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem +++ b/.venv/Lib/site-packages/pip/_vendor/certifi/cacert.pem @@ -791,34 +791,6 @@ uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2 XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E= -----END CERTIFICATE----- -# Issuer: CN=Hongkong Post Root CA 1 O=Hongkong Post -# Subject: CN=Hongkong Post Root CA 1 O=Hongkong Post -# Label: "Hongkong Post Root CA 1" -# Serial: 1000 -# MD5 Fingerprint: a8:0d:6f:39:78:b9:43:6d:77:42:6d:98:5a:cc:23:ca -# SHA1 Fingerprint: d6:da:a8:20:8d:09:d2:15:4d:24:b5:2f:cb:34:6e:b2:58:b2:8a:58 -# SHA256 Fingerprint: f9:e6:7d:33:6c:51:00:2a:c0:54:c6:32:02:2d:66:dd:a2:e7:e3:ff:f1:0a:d0:61:ed:31:d8:bb:b4:10:cf:b2 ------BEGIN CERTIFICATE----- -MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx -FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg -Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG -A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr -b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC -AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ -jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn -PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh -ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9 -nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h -q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED -MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC -mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3 -7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB -oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs -EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO -fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi -AmvZWg== ------END CERTIFICATE----- - # Issuer: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. # Subject: CN=SecureSign RootCA11 O=Japan Certification Services, Inc. # Label: "SecureSign RootCA11" @@ -1676,50 +1648,6 @@ HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY= -----END CERTIFICATE----- -# Issuer: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Subject: CN=E-Tugra Certification Authority O=E-Tu\u011fra EBG Bili\u015fim Teknolojileri ve Hizmetleri A.\u015e. OU=E-Tugra Sertifikasyon Merkezi -# Label: "E-Tugra Certification Authority" -# Serial: 7667447206703254355 -# MD5 Fingerprint: b8:a1:03:63:b0:bd:21:71:70:8a:6f:13:3a:bb:79:49 -# SHA1 Fingerprint: 51:c6:e7:08:49:06:6e:f3:92:d4:5c:a0:0d:6d:a3:62:8f:c3:52:39 -# SHA256 Fingerprint: b0:bf:d5:2b:b0:d7:d9:bd:92:bf:5d:4d:c1:3d:a2:55:c0:2c:54:2f:37:83:65:ea:89:39:11:f5:5e:55:f2:3c ------BEGIN CERTIFICATE----- -MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV -BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC -aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV -BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1 -Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz -MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+ -BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp -em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN -ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5 -MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY -B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH -D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF -Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo -q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D -k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH -fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut -dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM -ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8 -zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn -rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX -U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6 -Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5 -XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF -Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR -HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY -GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c -77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3 -+GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK -vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6 -FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl -yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P -AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD -y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d -NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA== ------END CERTIFICATE----- - # Issuer: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Subject: CN=T-TeleSec GlobalRoot Class 2 O=T-Systems Enterprise Services GmbH OU=T-Systems Trust Center # Label: "T-TeleSec GlobalRoot Class 2" @@ -4397,73 +4325,6 @@ ut6Dacpps6kFtZaSF4fC0urQe87YQVt8rgIwRt7qy12a7DLCZRawTDBcMPPaTnOG BtjOiQRINzf43TNRnXCve1XYAS59BWQOhriR -----END CERTIFICATE----- -# Issuer: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Subject: CN=E-Tugra Global Root CA RSA v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Label: "E-Tugra Global Root CA RSA v3" -# Serial: 75951268308633135324246244059508261641472512052 -# MD5 Fingerprint: 22:be:10:f6:c2:f8:03:88:73:5f:33:29:47:28:47:a4 -# SHA1 Fingerprint: e9:a8:5d:22:14:52:1c:5b:aa:0a:b4:be:24:6a:23:8a:c9:ba:e2:a9 -# SHA256 Fingerprint: ef:66:b0:b1:0a:3c:db:9f:2e:36:48:c7:6b:d2:af:18:ea:d2:bf:e6:f1:17:65:5e:28:c4:06:0d:a1:a3:f4:c2 ------BEGIN CERTIFICATE----- -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 ------END CERTIFICATE----- - -# Issuer: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Subject: CN=E-Tugra Global Root CA ECC v3 O=E-Tugra EBG A.S. OU=E-Tugra Trust Center -# Label: "E-Tugra Global Root CA ECC v3" -# Serial: 218504919822255052842371958738296604628416471745 -# MD5 Fingerprint: 46:bc:81:bb:f1:b5:1e:f7:4b:96:bc:14:e2:e7:27:64 -# SHA1 Fingerprint: 8a:2f:af:57:53:b1:b0:e6:a1:04:ec:5b:6a:69:71:6d:f6:1c:e2:84 -# SHA256 Fingerprint: 87:3f:46:85:fa:7f:56:36:25:25:2e:6d:36:bc:d7:f1:6f:c2:49:51:f2:64:e4:7e:1b:95:4f:49:08:cd:ca:13 ------BEGIN CERTIFICATE----- -MIICpTCCAiqgAwIBAgIUJkYZdzHhT28oNt45UYbm1JeIIsEwCgYIKoZIzj0EAwMw -gYAxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHEwZBbmthcmExGTAXBgNVBAoTEEUtVHVn -cmEgRUJHIEEuUy4xHTAbBgNVBAsTFEUtVHVncmEgVHJ1c3QgQ2VudGVyMSYwJAYD -VQQDEx1FLVR1Z3JhIEdsb2JhbCBSb290IENBIEVDQyB2MzAeFw0yMDAzMTgwOTQ2 -NThaFw00NTAzMTIwOTQ2NThaMIGAMQswCQYDVQQGEwJUUjEPMA0GA1UEBxMGQW5r -YXJhMRkwFwYDVQQKExBFLVR1Z3JhIEVCRyBBLlMuMR0wGwYDVQQLExRFLVR1Z3Jh -IFRydXN0IENlbnRlcjEmMCQGA1UEAxMdRS1UdWdyYSBHbG9iYWwgUm9vdCBDQSBF -Q0MgdjMwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASOmCm/xxAeJ9urA8woLNheSBkQ -KczLWYHMjLiSF4mDKpL2w6QdTGLVn9agRtwcvHbB40fQWxPa56WzZkjnIZpKT4YK -fWzqTTKACrJ6CZtpS5iB4i7sAnCWH/31Rs7K3IKjYzBhMA8GA1UdEwEB/wQFMAMB -Af8wHwYDVR0jBBgwFoAU/4Ixcj75xGZsrTie0bBRiKWQzPUwHQYDVR0OBBYEFP+C -MXI++cRmbK04ntGwUYilkMz1MA4GA1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNp -ADBmAjEA5gVYaWHlLcoNy/EZCL3W/VGSGn5jVASQkZo1kTmZ+gepZpO6yGjUij/6 -7W4WAie3AjEA3VoXK3YdZUKWpqxdinlW2Iob35reX8dQj7FbcQwm32pAAOwzkSFx -vmjkI6TZraE3 ------END CERTIFICATE----- - # Issuer: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. # Subject: CN=Security Communication RootCA3 O=SECOM Trust Systems CO.,LTD. # Label: "Security Communication RootCA3" @@ -4525,3 +4386,250 @@ BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjAVXUI9/Lbu 9zuxNuie9sRGKEkz0FhDKmMpzE2xtHqiuQ04pV1IKv3LsnNdo4gIxwwCMQDAqy0O be0YottT6SXbVQjgUMzfRGEWgqtJsLKB7HOHeLRMsmIbEvoWTSVLY70eN9k= -----END CERTIFICATE----- + +# Issuer: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY +# Subject: CN=BJCA Global Root CA1 O=BEIJING CERTIFICATE AUTHORITY +# Label: "BJCA Global Root CA1" +# Serial: 113562791157148395269083148143378328608 +# MD5 Fingerprint: 42:32:99:76:43:33:36:24:35:07:82:9b:28:f9:d0:90 +# SHA1 Fingerprint: d5:ec:8d:7b:4c:ba:79:f4:e7:e8:cb:9d:6b:ae:77:83:10:03:21:6a +# SHA256 Fingerprint: f3:89:6f:88:fe:7c:0a:88:27:66:a7:fa:6a:d2:74:9f:b5:7a:7f:3e:98:fb:76:9c:1f:a7:b0:9c:2c:44:d5:ae +-----BEGIN CERTIFICATE----- +MIIFdDCCA1ygAwIBAgIQVW9l47TZkGobCdFsPsBsIDANBgkqhkiG9w0BAQsFADBU +MQswCQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRI +T1JJVFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0ExMB4XDTE5MTIxOTAz +MTYxN1oXDTQ0MTIxMjAzMTYxN1owVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJF +SUpJTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2Jh +bCBSb290IENBMTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAPFmCL3Z +xRVhy4QEQaVpN3cdwbB7+sN3SJATcmTRuHyQNZ0YeYjjlwE8R4HyDqKYDZ4/N+AZ +spDyRhySsTphzvq3Rp4Dhtczbu33RYx2N95ulpH3134rhxfVizXuhJFyV9xgw8O5 +58dnJCNPYwpj9mZ9S1WnP3hkSWkSl+BMDdMJoDIwOvqfwPKcxRIqLhy1BDPapDgR +at7GGPZHOiJBhyL8xIkoVNiMpTAK+BcWyqw3/XmnkRd4OJmtWO2y3syJfQOcs4ll +5+M7sSKGjwZteAf9kRJ/sGsciQ35uMt0WwfCyPQ10WRjeulumijWML3mG90Vr4Tq +nMfK9Q7q8l0ph49pczm+LiRvRSGsxdRpJQaDrXpIhRMsDQa4bHlW/KNnMoH1V6XK +V0Jp6VwkYe/iMBhORJhVb3rCk9gZtt58R4oRTklH2yiUAguUSiz5EtBP6DF+bHq/ +pj+bOT0CFqMYs2esWz8sgytnOYFcuX6U1WTdno9uruh8W7TXakdI136z1C2OVnZO +z2nxbkRs1CTqjSShGL+9V/6pmTW12xB3uD1IutbB5/EjPtffhZ0nPNRAvQoMvfXn +jSXWgXSHRtQpdaJCbPdzied9v3pKH9MiyRVVz99vfFXQpIsHETdfg6YmV6YBW37+ +WGgHqel62bno/1Afq8K0wM7o6v0PvY1NuLxxAgMBAAGjQjBAMB0GA1UdDgQWBBTF +7+3M2I0hxkjk49cULqcWk+WYATAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE +AwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAUoKsITQfI/Ki2Pm4rzc2IInRNwPWaZ+4 +YRC6ojGYWUfo0Q0lHhVBDOAqVdVXUsv45Mdpox1NcQJeXyFFYEhcCY5JEMEE3Kli +awLwQ8hOnThJdMkycFRtwUf8jrQ2ntScvd0g1lPJGKm1Vrl2i5VnZu69mP6u775u ++2D2/VnGKhs/I0qUJDAnyIm860Qkmss9vk/Ves6OF8tiwdneHg56/0OGNFK8YT88 +X7vZdrRTvJez/opMEi4r89fO4aL/3Xtw+zuhTaRjAv04l5U/BXCga99igUOLtFkN +SoxUnMW7gZ/NfaXvCyUeOiDbHPwfmGcCCtRzRBPbUYQaVQNW4AB+dAb/OMRyHdOo +P2gxXdMJxy6MW2Pg6Nwe0uxhHvLe5e/2mXZgLR6UcnHGCyoyx5JO1UbXHfmpGQrI ++pXObSOYqgs4rZpWDW+N8TEAiMEXnM0ZNjX+VVOg4DwzX5Ze4jLp3zO7Bkqp2IRz +znfSxqxx4VyjHQy7Ct9f4qNx2No3WqB4K/TUfet27fJhcKVlmtOJNBir+3I+17Q9 +eVzYH6Eze9mCUAyTF6ps3MKCuwJXNq+YJyo5UOGwifUll35HaBC07HPKs5fRJNz2 +YqAo07WjuGS3iGJCz51TzZm+ZGiPTx4SSPfSKcOYKMryMguTjClPPGAyzQWWYezy +r/6zcCwupvI= +-----END CERTIFICATE----- + +# Issuer: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY +# Subject: CN=BJCA Global Root CA2 O=BEIJING CERTIFICATE AUTHORITY +# Label: "BJCA Global Root CA2" +# Serial: 58605626836079930195615843123109055211 +# MD5 Fingerprint: 5e:0a:f6:47:5f:a6:14:e8:11:01:95:3f:4d:01:eb:3c +# SHA1 Fingerprint: f4:27:86:eb:6e:b8:6d:88:31:67:02:fb:ba:66:a4:53:00:aa:7a:a6 +# SHA256 Fingerprint: 57:4d:f6:93:1e:27:80:39:66:7b:72:0a:fd:c1:60:0f:c2:7e:b6:6d:d3:09:29:79:fb:73:85:64:87:21:28:82 +-----BEGIN CERTIFICATE----- +MIICJTCCAaugAwIBAgIQLBcIfWQqwP6FGFkGz7RK6zAKBggqhkjOPQQDAzBUMQsw +CQYDVQQGEwJDTjEmMCQGA1UECgwdQkVJSklORyBDRVJUSUZJQ0FURSBBVVRIT1JJ +VFkxHTAbBgNVBAMMFEJKQ0EgR2xvYmFsIFJvb3QgQ0EyMB4XDTE5MTIxOTAzMTgy +MVoXDTQ0MTIxMjAzMTgyMVowVDELMAkGA1UEBhMCQ04xJjAkBgNVBAoMHUJFSUpJ +TkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZMR0wGwYDVQQDDBRCSkNBIEdsb2JhbCBS +b290IENBMjB2MBAGByqGSM49AgEGBSuBBAAiA2IABJ3LgJGNU2e1uVCxA/jlSR9B +IgmwUVJY1is0j8USRhTFiy8shP8sbqjV8QnjAyEUxEM9fMEsxEtqSs3ph+B99iK+ ++kpRuDCK/eHeGBIK9ke35xe/J4rUQUyWPGCWwf0VHKNCMEAwHQYDVR0OBBYEFNJK +sVF/BvDRgh9Obl+rg/xI1LCRMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD +AgEGMAoGCCqGSM49BAMDA2gAMGUCMBq8W9f+qdJUDkpd0m2xQNz0Q9XSSpkZElaA +94M04TVOSG0ED1cxMDAtsaqdAzjbBgIxAMvMh1PLet8gUXOQwKhbYdDFUDn9hf7B +43j4ptZLvZuHjw/l1lOWqzzIQNph91Oj9w== +-----END CERTIFICATE----- + +# Issuer: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited +# Subject: CN=Sectigo Public Server Authentication Root E46 O=Sectigo Limited +# Label: "Sectigo Public Server Authentication Root E46" +# Serial: 88989738453351742415770396670917916916 +# MD5 Fingerprint: 28:23:f8:b2:98:5c:37:16:3b:3e:46:13:4e:b0:b3:01 +# SHA1 Fingerprint: ec:8a:39:6c:40:f0:2e:bc:42:75:d4:9f:ab:1c:1a:5b:67:be:d2:9a +# SHA256 Fingerprint: c9:0f:26:f0:fb:1b:40:18:b2:22:27:51:9b:5c:a2:b5:3e:2c:a5:b3:be:5c:f1:8e:fe:1b:ef:47:38:0c:53:83 +-----BEGIN CERTIFICATE----- +MIICOjCCAcGgAwIBAgIQQvLM2htpN0RfFf51KBC49DAKBggqhkjOPQQDAzBfMQsw +CQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1T +ZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwHhcN +MjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEYMBYG +A1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1YmxpYyBT +ZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBFNDYwdjAQBgcqhkjOPQIBBgUrgQQA +IgNiAAR2+pmpbiDt+dd34wc7qNs9Xzjoq1WmVk/WSOrsfy2qw7LFeeyZYX8QeccC +WvkEN/U0NSt3zn8gj1KjAIns1aeibVvjS5KToID1AZTc8GgHHs3u/iVStSBDHBv+ +6xnOQ6OjQjBAMB0GA1UdDgQWBBTRItpMWfFLXyY4qp3W7usNw/upYTAOBgNVHQ8B +Af8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNnADBkAjAn7qRa +qCG76UeXlImldCBteU/IvZNeWBj7LRoAasm4PdCkT0RHlAFWovgzJQxC36oCMB3q +4S6ILuH5px0CMk7yn2xVdOOurvulGu7t0vzCAxHrRVxgED1cf5kDW21USAGKcw== +-----END CERTIFICATE----- + +# Issuer: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited +# Subject: CN=Sectigo Public Server Authentication Root R46 O=Sectigo Limited +# Label: "Sectigo Public Server Authentication Root R46" +# Serial: 156256931880233212765902055439220583700 +# MD5 Fingerprint: 32:10:09:52:00:d5:7e:6c:43:df:15:c0:b1:16:93:e5 +# SHA1 Fingerprint: ad:98:f9:f3:e4:7d:75:3b:65:d4:82:b3:a4:52:17:bb:6e:f5:e4:38 +# SHA256 Fingerprint: 7b:b6:47:a6:2a:ee:ac:88:bf:25:7a:a5:22:d0:1f:fe:a3:95:e0:ab:45:c7:3f:93:f6:56:54:ec:38:f2:5a:06 +-----BEGIN CERTIFICATE----- +MIIFijCCA3KgAwIBAgIQdY39i658BwD6qSWn4cetFDANBgkqhkiG9w0BAQwFADBf +MQswCQYDVQQGEwJHQjEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQD +Ey1TZWN0aWdvIFB1YmxpYyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYw +HhcNMjEwMzIyMDAwMDAwWhcNNDYwMzIxMjM1OTU5WjBfMQswCQYDVQQGEwJHQjEY +MBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMTYwNAYDVQQDEy1TZWN0aWdvIFB1Ymxp +YyBTZXJ2ZXIgQXV0aGVudGljYXRpb24gUm9vdCBSNDYwggIiMA0GCSqGSIb3DQEB +AQUAA4ICDwAwggIKAoICAQCTvtU2UnXYASOgHEdCSe5jtrch/cSV1UgrJnwUUxDa +ef0rty2k1Cz66jLdScK5vQ9IPXtamFSvnl0xdE8H/FAh3aTPaE8bEmNtJZlMKpnz +SDBh+oF8HqcIStw+KxwfGExxqjWMrfhu6DtK2eWUAtaJhBOqbchPM8xQljeSM9xf +iOefVNlI8JhD1mb9nxc4Q8UBUQvX4yMPFF1bFOdLvt30yNoDN9HWOaEhUTCDsG3X +ME6WW5HwcCSrv0WBZEMNvSE6Lzzpng3LILVCJ8zab5vuZDCQOc2TZYEhMbUjUDM3 +IuM47fgxMMxF/mL50V0yeUKH32rMVhlATc6qu/m1dkmU8Sf4kaWD5QazYw6A3OAS +VYCmO2a0OYctyPDQ0RTp5A1NDvZdV3LFOxxHVp3i1fuBYYzMTYCQNFu31xR13NgE +SJ/AwSiItOkcyqex8Va3e0lMWeUgFaiEAin6OJRpmkkGj80feRQXEgyDet4fsZfu ++Zd4KKTIRJLpfSYFplhym3kT2BFfrsU4YjRosoYwjviQYZ4ybPUHNs2iTG7sijbt +8uaZFURww3y8nDnAtOFr94MlI1fZEoDlSfB1D++N6xybVCi0ITz8fAr/73trdf+L +HaAZBav6+CuBQug4urv7qv094PPK306Xlynt8xhW6aWWrL3DkJiy4Pmi1KZHQ3xt +zwIDAQABo0IwQDAdBgNVHQ4EFgQUVnNYZJX5khqwEioEYnmhQBWIIUkwDgYDVR0P +AQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAC9c +mTz8Bl6MlC5w6tIyMY208FHVvArzZJ8HXtXBc2hkeqK5Duj5XYUtqDdFqij0lgVQ +YKlJfp/imTYpE0RHap1VIDzYm/EDMrraQKFz6oOht0SmDpkBm+S8f74TlH7Kph52 +gDY9hAaLMyZlbcp+nv4fjFg4exqDsQ+8FxG75gbMY/qB8oFM2gsQa6H61SilzwZA +Fv97fRheORKkU55+MkIQpiGRqRxOF3yEvJ+M0ejf5lG5Nkc/kLnHvALcWxxPDkjB +JYOcCj+esQMzEhonrPcibCTRAUH4WAP+JWgiH5paPHxsnnVI84HxZmduTILA7rpX +DhjvLpr3Etiga+kFpaHpaPi8TD8SHkXoUsCjvxInebnMMTzD9joiFgOgyY9mpFui +TdaBJQbpdqQACj7LzTWb4OE4y2BThihCQRxEV+ioratF4yUQvNs+ZUH7G6aXD+u5 +dHn5HrwdVw1Hr8Mvn4dGp+smWg9WY7ViYG4A++MnESLn/pmPNPW56MORcr3Ywx65 +LvKRRFHQV80MNNVIIb/bE/FmJUNS0nAiNs2fxBx1IK1jcmMGDw4nztJqDby1ORrp +0XZ60Vzk50lJLVU3aPAaOpg+VBeHVOmmJ1CJeyAvP/+/oYtKR5j/K3tJPsMpRmAY +QqszKbrAKbkTidOIijlBO8n9pu0f9GBj39ItVQGL +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com TLS RSA Root CA 2022 O=SSL Corporation +# Label: "SSL.com TLS RSA Root CA 2022" +# Serial: 148535279242832292258835760425842727825 +# MD5 Fingerprint: d8:4e:c6:59:30:d8:fe:a0:d6:7a:5a:2c:2c:69:78:da +# SHA1 Fingerprint: ec:2c:83:40:72:af:26:95:10:ff:0e:f2:03:ee:31:70:f6:78:9d:ca +# SHA256 Fingerprint: 8f:af:7d:2e:2c:b4:70:9b:b8:e0:b3:36:66:bf:75:a5:dd:45:b5:de:48:0f:8e:a8:d4:bf:e6:be:bc:17:f2:ed +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD +DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX +DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP +L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY +t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins +S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 +PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO +L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 +R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w +dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS ++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS +d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG +AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f +gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z +NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM +QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf +R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ +DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW +P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy +lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq +bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w +AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q +r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji +Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU +98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- + +# Issuer: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation +# Subject: CN=SSL.com TLS ECC Root CA 2022 O=SSL Corporation +# Label: "SSL.com TLS ECC Root CA 2022" +# Serial: 26605119622390491762507526719404364228 +# MD5 Fingerprint: 99:d7:5c:f1:51:36:cc:e9:ce:d9:19:2e:77:71:56:c5 +# SHA1 Fingerprint: 9f:5f:d9:1a:54:6d:f5:0c:71:f0:ee:7a:bd:17:49:98:84:73:e2:39 +# SHA256 Fingerprint: c3:2f:fd:9f:46:f9:36:d1:6c:36:73:99:09:59:43:4b:9a:d6:0a:af:bb:9e:7c:f3:36:54:f1:44:cc:1b:a1:43 +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT +U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 +MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh +dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm +acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN +SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW +uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp +15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN +b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos +# Subject: CN=Atos TrustedRoot Root CA ECC TLS 2021 O=Atos +# Label: "Atos TrustedRoot Root CA ECC TLS 2021" +# Serial: 81873346711060652204712539181482831616 +# MD5 Fingerprint: 16:9f:ad:f1:70:ad:79:d6:ed:29:b4:d1:c5:79:70:a8 +# SHA1 Fingerprint: 9e:bc:75:10:42:b3:02:f3:81:f4:f7:30:62:d4:8f:c3:a7:51:b2:dd +# SHA256 Fingerprint: b2:fa:e5:3e:14:cc:d7:ab:92:12:06:47:01:ae:27:9c:1d:89:88:fa:cb:77:5f:a8:a0:08:91:4e:66:39:88:a8 +-----BEGIN CERTIFICATE----- +MIICFTCCAZugAwIBAgIQPZg7pmY9kGP3fiZXOATvADAKBggqhkjOPQQDAzBMMS4w +LAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgRUNDIFRMUyAyMDIxMQ0w +CwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTI2MjNaFw00MTA0 +MTcwOTI2MjJaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBDQSBF +Q0MgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMHYwEAYHKoZI +zj0CAQYFK4EEACIDYgAEloZYKDcKZ9Cg3iQZGeHkBQcfl+3oZIK59sRxUM6KDP/X +tXa7oWyTbIOiaG6l2b4siJVBzV3dscqDY4PMwL502eCdpO5KTlbgmClBk1IQ1SQ4 +AjJn8ZQSb+/Xxd4u/RmAo0IwQDAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR2 +KCXWfeBmmnoJsmo7jjPXNtNPojAOBgNVHQ8BAf8EBAMCAYYwCgYIKoZIzj0EAwMD +aAAwZQIwW5kp85wxtolrbNa9d+F851F+uDrNozZffPc8dz7kUK2o59JZDCaOMDtu +CCrCp1rIAjEAmeMM56PDr9NJLkaCI2ZdyQAUEv049OGYa3cpetskz2VAv9LcjBHo +9H1/IISpQuQo +-----END CERTIFICATE----- + +# Issuer: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos +# Subject: CN=Atos TrustedRoot Root CA RSA TLS 2021 O=Atos +# Label: "Atos TrustedRoot Root CA RSA TLS 2021" +# Serial: 111436099570196163832749341232207667876 +# MD5 Fingerprint: d4:d3:46:b8:9a:c0:9c:76:5d:9e:3a:c3:b9:99:31:d2 +# SHA1 Fingerprint: 18:52:3b:0d:06:37:e4:d6:3a:df:23:e4:98:fb:5b:16:fb:86:74:48 +# SHA256 Fingerprint: 81:a9:08:8e:a5:9f:b3:64:c5:48:a6:f8:55:59:09:9b:6f:04:05:ef:bf:18:e5:32:4e:c9:f4:57:ba:00:11:2f +-----BEGIN CERTIFICATE----- +MIIFZDCCA0ygAwIBAgIQU9XP5hmTC/srBRLYwiqipDANBgkqhkiG9w0BAQwFADBM +MS4wLAYDVQQDDCVBdG9zIFRydXN0ZWRSb290IFJvb3QgQ0EgUlNBIFRMUyAyMDIx +MQ0wCwYDVQQKDARBdG9zMQswCQYDVQQGEwJERTAeFw0yMTA0MjIwOTIxMTBaFw00 +MTA0MTcwOTIxMDlaMEwxLjAsBgNVBAMMJUF0b3MgVHJ1c3RlZFJvb3QgUm9vdCBD +QSBSU0EgVExTIDIwMjExDTALBgNVBAoMBEF0b3MxCzAJBgNVBAYTAkRFMIICIjAN +BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAtoAOxHm9BYx9sKOdTSJNy/BBl01Z +4NH+VoyX8te9j2y3I49f1cTYQcvyAh5x5en2XssIKl4w8i1mx4QbZFc4nXUtVsYv +Ye+W/CBGvevUez8/fEc4BKkbqlLfEzfTFRVOvV98r61jx3ncCHvVoOX3W3WsgFWZ +kmGbzSoXfduP9LVq6hdKZChmFSlsAvFr1bqjM9xaZ6cF4r9lthawEO3NUDPJcFDs +GY6wx/J0W2tExn2WuZgIWWbeKQGb9Cpt0xU6kGpn8bRrZtkh68rZYnxGEFzedUln +nkL5/nWpo63/dgpnQOPF943HhZpZnmKaau1Fh5hnstVKPNe0OwANwI8f4UDErmwh +3El+fsqyjW22v5MvoVw+j8rtgI5Y4dtXz4U2OLJxpAmMkokIiEjxQGMYsluMWuPD +0xeqqxmjLBvk1cbiZnrXghmmOxYsL3GHX0WelXOTwkKBIROW1527k2gV+p2kHYzy +geBYBr3JtuP2iV2J+axEoctr+hbxx1A9JNr3w+SH1VbxT5Aw+kUJWdo0zuATHAR8 +ANSbhqRAvNncTFd+rrcztl524WWLZt+NyteYr842mIycg5kDcPOvdO3GDjbnvezB +c6eUWsuSZIKmAMFwoW4sKeFYV+xafJlrJaSQOoD0IJ2azsct+bJLKZWD6TWNp0lI +pw9MGZHQ9b8Q4HECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU +dEmZ0f+0emhFdcN+tNzMzjkz2ggwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB +DAUAA4ICAQAjQ1MkYlxt/T7Cz1UAbMVWiLkO3TriJQ2VSpfKgInuKs1l+NsW4AmS +4BjHeJi78+xCUvuppILXTdiK/ORO/auQxDh1MoSf/7OwKwIzNsAQkG8dnK/haZPs +o0UvFJ/1TCplQ3IM98P4lYsU84UgYt1UU90s3BiVaU+DR3BAM1h3Egyi61IxHkzJ +qM7F78PRreBrAwA0JrRUITWXAdxfG/F851X6LWh3e9NpzNMOa7pNdkTWwhWaJuyw +xfW70Xp0wmzNxbVe9kzmWy2B27O3Opee7c9GslA9hGCZcbUztVdF5kJHdWoOsAgM +rr3e97sPWD2PAzHoPYJQyi9eDF20l74gNAf0xBLh7tew2VktafcxBPTy+av5EzH4 +AXcOPUIjJsyacmdRIXrMPIWo6iFqO9taPKU0nprALN+AnCng33eU0aKAQv9qTFsR +0PXNor6uzFFcw9VUewyu1rkGd4Di7wcaaMxZUa1+XGdrudviB0JbuAEFWDlN5LuY +o7Ey7Nmj1m+UI/87tyll5gfp77YZ6ufCOB0yiJA8EytuzO+rdwY0d4RPcuSBhPm5 +dDTedk+SKlOxJTnbPP/lPqYO5Wue/9vsL3SD3460s6neFE3/MaNFcyT6lSnMEpcE +oji2jbDwN/zIIX8/syQbPYtuzE2wFg2WHYMfRsCbvUOZ58SWLs5fyQ== +-----END CERTIFICATE----- diff --git a/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py b/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py index 50710218..1300b866 100644 --- a/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/msgpack/__init__.py @@ -6,8 +6,8 @@ import os import sys -version = (1, 0, 4) -__version__ = "1.0.4" +version = (1, 0, 5) +__version__ = "1.0.5" if os.environ.get("MSGPACK_PUREPYTHON") or sys.version_info[0] == 2: diff --git a/.venv/Lib/site-packages/pip/_vendor/msgpack/ext.py b/.venv/Lib/site-packages/pip/_vendor/msgpack/ext.py index 25544c55..23e0d6b4 100644 --- a/.venv/Lib/site-packages/pip/_vendor/msgpack/ext.py +++ b/.venv/Lib/site-packages/pip/_vendor/msgpack/ext.py @@ -56,7 +56,7 @@ class Timestamp(object): Note: Negative times (before the UNIX epoch) are represented as negative seconds + positive ns. """ if not isinstance(seconds, int_types): - raise TypeError("seconds must be an interger") + raise TypeError("seconds must be an integer") if not isinstance(nanoseconds, int_types): raise TypeError("nanoseconds must be an integer") if not (0 <= nanoseconds < 10**9): diff --git a/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py b/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py index f560c7b5..e8cebc1b 100644 --- a/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py +++ b/.venv/Lib/site-packages/pip/_vendor/msgpack/fallback.py @@ -814,7 +814,7 @@ class Packer(object): self._pack_raw_header(n) return self._buffer.write(obj) if check(obj, memoryview): - n = len(obj) * obj.itemsize + n = obj.nbytes if n >= 2**32: raise ValueError("Memoryview is too large") self._pack_bin_header(n) diff --git a/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py index 4cd562cf..ad279407 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pkg_resources/__init__.py @@ -1,4 +1,3 @@ -# coding: utf-8 """ Package resource API -------------------- @@ -13,9 +12,10 @@ The package resource API is designed to work with normal filesystem packages, .egg files, and unpacked .egg files. It can also work in a limited way with .zip files and with custom PEP 302 loaders that support the ``get_data()`` method. -""" -from __future__ import absolute_import +This module is deprecated. Users are directed to :mod:`importlib.resources`, +:mod:`importlib.metadata` and :pypi:`packaging` instead. +""" import sys import os @@ -37,10 +37,10 @@ import email.parser import errno import tempfile import textwrap -import itertools import inspect import ntpath import posixpath +import importlib from pkgutil import get_importer try: @@ -54,13 +54,12 @@ try: except NameError: FileExistsError = OSError -from pip._vendor import six -from pip._vendor.six.moves import urllib, map, filter - # capture these to bypass sandboxing from os import utime + try: from os import mkdir, rename, unlink + WRITE_SUPPORT = True except ImportError: # no write support, probably under GAE @@ -71,31 +70,30 @@ from os.path import isdir, split try: import importlib.machinery as importlib_machinery + # access attribute to force import under delayed import mechanisms. importlib_machinery.__name__ except ImportError: importlib_machinery = None -from . import py31compat +from pip._internal.utils._jaraco_text import ( + yield_lines, + drop_comment, + join_continuation, +) + from pip._vendor import platformdirs from pip._vendor import packaging + __import__('pip._vendor.packaging.version') __import__('pip._vendor.packaging.specifiers') __import__('pip._vendor.packaging.requirements') __import__('pip._vendor.packaging.markers') +__import__('pip._vendor.packaging.utils') - -__metaclass__ = type - - -if (3, 0) < sys.version_info < (3, 5): +if sys.version_info < (3, 5): raise RuntimeError("Python 3.5 or later is required") -if six.PY2: - # Those builtin exceptions are only defined in Python 3 - PermissionError = None - NotADirectoryError = None - # declare some globals that will be defined later to # satisfy the linters. require = None @@ -117,6 +115,17 @@ _namespace_handlers = None _namespace_packages = None +warnings.warn( + "pkg_resources is deprecated as an API. " + "See https://setuptools.pypa.io/en/latest/pkg_resources.html", + DeprecationWarning, + stacklevel=2 +) + + +_PEP440_FALLBACK = re.compile(r"^v?(?P(?:[0-9]+!)?[0-9]+(?:\.[0-9]+)*)", re.I) + + class PEP440Warning(RuntimeWarning): """ Used when there is an issue with a version or specifier not complying with @@ -124,11 +133,7 @@ class PEP440Warning(RuntimeWarning): """ -def parse_version(v): - try: - return packaging.version.Version(v) - except packaging.version.InvalidVersion: - return packaging.version.LegacyVersion(v) +parse_version = packaging.version.Version _state_vars = {} @@ -178,10 +183,10 @@ def get_supported_platform(): """Return this platform's maximum compatible version. distutils.util.get_platform() normally reports the minimum version - of Mac OS X that would be required to *use* extensions produced by + of macOS that would be required to *use* extensions produced by distutils. But what we want when checking compatibility is to know the - version of Mac OS X that we are *running*. To allow usage of packages that - explicitly require a newer version of Mac OS X, we must also know the + version of macOS that we are *running*. To allow usage of packages that + explicitly require a newer version of macOS, we must also know the current version of the OS. If this condition occurs for any other platform with a version in its @@ -191,60 +196,96 @@ def get_supported_platform(): m = macosVersionString.match(plat) if m is not None and sys.platform == "darwin": try: - plat = 'macosx-%s-%s' % ('.'.join(_macosx_vers()[:2]), m.group(3)) + plat = 'macosx-%s-%s' % ('.'.join(_macos_vers()[:2]), m.group(3)) except ValueError: - # not Mac OS X + # not macOS pass return plat __all__ = [ # Basic resource access and distribution/entry point discovery - 'require', 'run_script', 'get_provider', 'get_distribution', - 'load_entry_point', 'get_entry_map', 'get_entry_info', + 'require', + 'run_script', + 'get_provider', + 'get_distribution', + 'load_entry_point', + 'get_entry_map', + 'get_entry_info', 'iter_entry_points', - 'resource_string', 'resource_stream', 'resource_filename', - 'resource_listdir', 'resource_exists', 'resource_isdir', - + 'resource_string', + 'resource_stream', + 'resource_filename', + 'resource_listdir', + 'resource_exists', + 'resource_isdir', # Environmental control - 'declare_namespace', 'working_set', 'add_activation_listener', - 'find_distributions', 'set_extraction_path', 'cleanup_resources', + 'declare_namespace', + 'working_set', + 'add_activation_listener', + 'find_distributions', + 'set_extraction_path', + 'cleanup_resources', 'get_default_cache', - # Primary implementation classes - 'Environment', 'WorkingSet', 'ResourceManager', - 'Distribution', 'Requirement', 'EntryPoint', - + 'Environment', + 'WorkingSet', + 'ResourceManager', + 'Distribution', + 'Requirement', + 'EntryPoint', # Exceptions - 'ResolutionError', 'VersionConflict', 'DistributionNotFound', - 'UnknownExtra', 'ExtractionError', - + 'ResolutionError', + 'VersionConflict', + 'DistributionNotFound', + 'UnknownExtra', + 'ExtractionError', # Warnings 'PEP440Warning', - # Parsing functions and string utilities - 'parse_requirements', 'parse_version', 'safe_name', 'safe_version', - 'get_platform', 'compatible_platforms', 'yield_lines', 'split_sections', - 'safe_extra', 'to_filename', 'invalid_marker', 'evaluate_marker', - + 'parse_requirements', + 'parse_version', + 'safe_name', + 'safe_version', + 'get_platform', + 'compatible_platforms', + 'yield_lines', + 'split_sections', + 'safe_extra', + 'to_filename', + 'invalid_marker', + 'evaluate_marker', # filesystem utilities - 'ensure_directory', 'normalize_path', - + 'ensure_directory', + 'normalize_path', # Distribution "precedence" constants - 'EGG_DIST', 'BINARY_DIST', 'SOURCE_DIST', 'CHECKOUT_DIST', 'DEVELOP_DIST', - + 'EGG_DIST', + 'BINARY_DIST', + 'SOURCE_DIST', + 'CHECKOUT_DIST', + 'DEVELOP_DIST', # "Provider" interfaces, implementations, and registration/lookup APIs - 'IMetadataProvider', 'IResourceProvider', 'FileMetadata', - 'PathMetadata', 'EggMetadata', 'EmptyProvider', 'empty_provider', - 'NullProvider', 'EggProvider', 'DefaultProvider', 'ZipProvider', - 'register_finder', 'register_namespace_handler', 'register_loader_type', - 'fixup_namespace_packages', 'get_importer', - + 'IMetadataProvider', + 'IResourceProvider', + 'FileMetadata', + 'PathMetadata', + 'EggMetadata', + 'EmptyProvider', + 'empty_provider', + 'NullProvider', + 'EggProvider', + 'DefaultProvider', + 'ZipProvider', + 'register_finder', + 'register_namespace_handler', + 'register_loader_type', + 'fixup_namespace_packages', + 'get_importer', # Warnings 'PkgResourcesDeprecationWarning', - # Deprecated/backward compatibility only - 'run_main', 'AvailableDistributions', + 'run_main', + 'AvailableDistributions', ] @@ -303,8 +344,10 @@ class ContextualVersionConflict(VersionConflict): class DistributionNotFound(ResolutionError): """A requested distribution was not found""" - _template = ("The '{self.req}' distribution was not found " - "and is required by {self.requirers_str}") + _template = ( + "The '{self.req}' distribution was not found " + "and is required by {self.requirers_str}" + ) @property def req(self): @@ -364,7 +407,7 @@ def get_provider(moduleOrReq): return _find_adapter(_provider_factories, loader)(module) -def _macosx_vers(_cache=[]): +def _macos_vers(_cache=[]): if not _cache: version = platform.mac_ver()[0] # fallback for MacPorts @@ -380,7 +423,7 @@ def _macosx_vers(_cache=[]): return _cache[0] -def _macosx_arch(machine): +def _macos_arch(machine): return {'PowerPC': 'ppc', 'Power_Macintosh': 'ppc'}.get(machine, machine) @@ -388,18 +431,19 @@ def get_build_platform(): """Return this platform's string for platform-specific distributions XXX Currently this is the same as ``distutils.util.get_platform()``, but it - needs some hacks for Linux and Mac OS X. + needs some hacks for Linux and macOS. """ from sysconfig import get_platform plat = get_platform() if sys.platform == "darwin" and not plat.startswith('macosx-'): try: - version = _macosx_vers() + version = _macos_vers() machine = os.uname()[4].replace(" ", "_") return "macosx-%d.%d-%s" % ( - int(version[0]), int(version[1]), - _macosx_arch(machine), + int(version[0]), + int(version[1]), + _macos_arch(machine), ) except ValueError: # if someone is running a non-Mac darwin system, this will fall @@ -425,7 +469,7 @@ def compatible_platforms(provided, required): # easy case return True - # Mac OS X special cases + # macOS special cases reqMac = macosVersionString.match(required) if reqMac: provMac = macosVersionString.match(provided) @@ -434,20 +478,23 @@ def compatible_platforms(provided, required): if not provMac: # this is backwards compatibility for packages built before # setuptools 0.6. All packages built after this point will - # use the new macosx designation. + # use the new macOS designation. provDarwin = darwinVersionString.match(provided) if provDarwin: dversion = int(provDarwin.group(1)) macosversion = "%s.%s" % (reqMac.group(1), reqMac.group(2)) - if dversion == 7 and macosversion >= "10.3" or \ - dversion == 8 and macosversion >= "10.4": + if ( + dversion == 7 + and macosversion >= "10.3" + or dversion == 8 + and macosversion >= "10.4" + ): return True - # egg isn't macosx or legacy darwin + # egg isn't macOS or legacy darwin return False # are they the same major version and machine type? - if provMac.group(1) != reqMac.group(1) or \ - provMac.group(3) != reqMac.group(3): + if provMac.group(1) != reqMac.group(1) or provMac.group(3) != reqMac.group(3): return False # is the required OS major update >= the provided one? @@ -475,7 +522,7 @@ run_main = run_script def get_distribution(dist): """Return a current distribution object for a Requirement or string""" - if isinstance(dist, six.string_types): + if isinstance(dist, str): dist = Requirement.parse(dist) if isinstance(dist, Requirement): dist = get_provider(dist) @@ -509,8 +556,8 @@ class IMetadataProvider: def get_metadata_lines(name): """Yield named metadata resource as list of non-blank non-comment lines - Leading and trailing whitespace is stripped from each line, and lines - with ``#`` as the first non-blank character are omitted.""" + Leading and trailing whitespace is stripped from each line, and lines + with ``#`` as the first non-blank character are omitted.""" def metadata_isdir(name): """Is the named metadata a directory? (like ``os.path.isdir()``)""" @@ -558,6 +605,7 @@ class WorkingSet: self.entries = [] self.entry_keys = {} self.by_key = {} + self.normalized_to_canonical_keys = {} self.callbacks = [] if entries is None: @@ -638,6 +686,14 @@ class WorkingSet: is returned. """ dist = self.by_key.get(req.key) + + if dist is None: + canonical_key = self.normalized_to_canonical_keys.get(req.key) + + if canonical_key is not None: + req.key = canonical_key + dist = self.by_key.get(canonical_key) + if dist is not None and dist not in req: # XXX add more info raise VersionConflict(dist, req) @@ -706,14 +762,22 @@ class WorkingSet: return self.by_key[dist.key] = dist + normalized_name = packaging.utils.canonicalize_name(dist.key) + self.normalized_to_canonical_keys[normalized_name] = dist.key if dist.key not in keys: keys.append(dist.key) if dist.key not in keys2: keys2.append(dist.key) self._added_new(dist) - def resolve(self, requirements, env=None, installer=None, - replace_conflicting=False, extras=None): + def resolve( + self, + requirements, + env=None, + installer=None, + replace_conflicting=False, + extras=None, + ): """List all distributions needed to (recursively) meet `requirements` `requirements` must be a sequence of ``Requirement`` objects. `env`, @@ -762,33 +826,9 @@ class WorkingSet: if not req_extras.markers_pass(req, extras): continue - dist = best.get(req.key) - if dist is None: - # Find the best distribution and add it to the map - dist = self.by_key.get(req.key) - if dist is None or (dist not in req and replace_conflicting): - ws = self - if env is None: - if dist is None: - env = Environment(self.entries) - else: - # Use an empty environment and workingset to avoid - # any further conflicts with the conflicting - # distribution - env = Environment([]) - ws = WorkingSet([]) - dist = best[req.key] = env.best_match( - req, ws, installer, - replace_conflicting=replace_conflicting - ) - if dist is None: - requirers = required_by.get(req, None) - raise DistributionNotFound(req, requirers) - to_activate.append(dist) - if dist not in req: - # Oops, the "best" so far conflicts with a dependency - dependent_req = required_by[req] - raise VersionConflict(dist, req).with_context(dependent_req) + dist = self._resolve_dist( + req, best, replace_conflicting, env, installer, required_by, to_activate + ) # push the new requirements onto the stack new_requirements = dist.requires(req.extras)[::-1] @@ -804,8 +844,38 @@ class WorkingSet: # return list of distros to activate return to_activate - def find_plugins( - self, plugin_env, full_env=None, installer=None, fallback=True): + def _resolve_dist( + self, req, best, replace_conflicting, env, installer, required_by, to_activate + ): + dist = best.get(req.key) + if dist is None: + # Find the best distribution and add it to the map + dist = self.by_key.get(req.key) + if dist is None or (dist not in req and replace_conflicting): + ws = self + if env is None: + if dist is None: + env = Environment(self.entries) + else: + # Use an empty environment and workingset to avoid + # any further conflicts with the conflicting + # distribution + env = Environment([]) + ws = WorkingSet([]) + dist = best[req.key] = env.best_match( + req, ws, installer, replace_conflicting=replace_conflicting + ) + if dist is None: + requirers = required_by.get(req, None) + raise DistributionNotFound(req, requirers) + to_activate.append(dist) + if dist not in req: + # Oops, the "best" so far conflicts with a dependency + dependent_req = required_by[req] + raise VersionConflict(dist, req).with_context(dependent_req) + return dist + + def find_plugins(self, plugin_env, full_env=None, installer=None, fallback=True): """Find all activatable distributions in `plugin_env` Example usage:: @@ -858,9 +928,7 @@ class WorkingSet: list(map(shadow_set.add, self)) for project_name in plugin_projects: - for dist in plugin_env[project_name]: - req = [dist.as_requirement()] try: @@ -924,15 +992,19 @@ class WorkingSet: def __getstate__(self): return ( - self.entries[:], self.entry_keys.copy(), self.by_key.copy(), - self.callbacks[:] + self.entries[:], + self.entry_keys.copy(), + self.by_key.copy(), + self.normalized_to_canonical_keys.copy(), + self.callbacks[:], ) - def __setstate__(self, e_k_b_c): - entries, keys, by_key, callbacks = e_k_b_c + def __setstate__(self, e_k_b_n_c): + entries, keys, by_key, normalized_to_canonical_keys, callbacks = e_k_b_n_c self.entries = entries[:] self.entry_keys = keys.copy() self.by_key = by_key.copy() + self.normalized_to_canonical_keys = normalized_to_canonical_keys.copy() self.callbacks = callbacks[:] @@ -960,8 +1032,8 @@ class Environment: """Searchable snapshot of distributions on a search path""" def __init__( - self, search_path=None, platform=get_supported_platform(), - python=PY_MAJOR): + self, search_path=None, platform=get_supported_platform(), python=PY_MAJOR + ): """Snapshot distributions available on a search path Any distributions found on `search_path` are added to the environment. @@ -1028,16 +1100,14 @@ class Environment: return self._distmap.get(distribution_key, []) def add(self, dist): - """Add `dist` if we ``can_add()`` it and it has not already been added - """ + """Add `dist` if we ``can_add()`` it and it has not already been added""" if self.can_add(dist) and dist.has_version(): dists = self._distmap.setdefault(dist.key, []) if dist not in dists: dists.append(dist) dists.sort(key=operator.attrgetter('hashcmp'), reverse=True) - def best_match( - self, req, working_set, installer=None, replace_conflicting=False): + def best_match(self, req, working_set, installer=None, replace_conflicting=False): """Find distribution best matching `req` and usable on `working_set` This calls the ``find(req)`` method of the `working_set` to see if a @@ -1124,6 +1194,7 @@ class ExtractionError(RuntimeError): class ResourceManager: """Manage resource extraction and packages""" + extraction_path = None def __init__(self): @@ -1135,9 +1206,7 @@ class ResourceManager: def resource_isdir(self, package_or_requirement, resource_name): """Is the named resource an existing directory?""" - return get_provider(package_or_requirement).resource_isdir( - resource_name - ) + return get_provider(package_or_requirement).resource_isdir(resource_name) def resource_filename(self, package_or_requirement, resource_name): """Return a true filesystem path for specified resource""" @@ -1159,9 +1228,7 @@ class ResourceManager: def resource_listdir(self, package_or_requirement, resource_name): """List the contents of the named resource directory""" - return get_provider(package_or_requirement).resource_listdir( - resource_name - ) + return get_provider(package_or_requirement).resource_listdir(resource_name) def extraction_error(self): """Give an error message for problems extracting file(s)""" @@ -1169,7 +1236,8 @@ class ResourceManager: old_exc = sys.exc_info()[1] cache_path = self.extraction_path or get_default_cache() - tmpl = textwrap.dedent(""" + tmpl = textwrap.dedent( + """ Can't extract file(s) to egg cache The following error occurred while trying to extract file(s) @@ -1184,7 +1252,8 @@ class ResourceManager: Perhaps your account does not have write access to this directory? You can change the cache directory by setting the PYTHON_EGG_CACHE environment variable to point to an accessible directory. - """).lstrip() + """ + ).lstrip() err = ExtractionError(tmpl.format(**locals())) err.manager = self err.cache_path = cache_path @@ -1234,12 +1303,13 @@ class ResourceManager: mode = os.stat(path).st_mode if mode & stat.S_IWOTH or mode & stat.S_IWGRP: msg = ( - "%s is writable by group/others and vulnerable to attack " - "when " - "used with get_resource_filename. Consider a more secure " + "Extraction path is writable by group/others " + "and vulnerable to attack when " + "used with get_resource_filename ({path}). " + "Consider a more secure " "location (set with .set_extraction_path or the " - "PYTHON_EGG_CACHE environment variable)." % path - ) + "PYTHON_EGG_CACHE environment variable)." + ).format(**locals()) warnings.warn(msg, UserWarning) def postprocess(self, tempname, filename): @@ -1282,9 +1352,7 @@ class ResourceManager: ``cleanup_resources()``.) """ if self.cached_files: - raise ValueError( - "Can't change extraction path, files already extracted" - ) + raise ValueError("Can't change extraction path, files already extracted") self.extraction_path = path @@ -1308,9 +1376,8 @@ def get_default_cache(): or a platform-relevant user cache dir for an app named "Python-Eggs". """ - return ( - os.environ.get('PYTHON_EGG_CACHE') - or platformdirs.user_cache_dir(appname='Python-Eggs') + return os.environ.get('PYTHON_EGG_CACHE') or platformdirs.user_cache_dir( + appname='Python-Eggs' ) @@ -1334,6 +1401,38 @@ def safe_version(version): return re.sub('[^A-Za-z0-9.]+', '-', version) +def _forgiving_version(version): + """Fallback when ``safe_version`` is not safe enough + >>> parse_version(_forgiving_version('0.23ubuntu1')) + + >>> parse_version(_forgiving_version('0.23-')) + + >>> parse_version(_forgiving_version('0.-_')) + + >>> parse_version(_forgiving_version('42.+?1')) + + >>> parse_version(_forgiving_version('hello world')) + + """ + version = version.replace(' ', '.') + match = _PEP440_FALLBACK.search(version) + if match: + safe = match["safe"] + rest = version[len(safe):] + else: + safe = "0" + rest = version + local = f"sanitized.{_safe_segment(rest)}".strip(".") + return f"{safe}.dev0+{local}" + + +def _safe_segment(segment): + """Convert an arbitrary string into a safe segment""" + segment = re.sub('[^A-Za-z0-9.]+', '-', segment) + segment = re.sub('-[^A-Za-z0-9]+', '-', segment) + return re.sub(r'\.[^A-Za-z0-9]+', '.', segment).strip(".-") + + def safe_extra(extra): """Convert an arbitrary string to a standard 'extra' name @@ -1377,7 +1476,7 @@ def evaluate_marker(text, extra=None): marker = packaging.markers.Marker(text) return marker.evaluate() except packaging.markers.InvalidMarker as e: - raise SyntaxError(e) + raise SyntaxError(e) from e class NullProvider: @@ -1418,8 +1517,6 @@ class NullProvider: return "" path = self._get_metadata_path(name) value = self._get(path) - if six.PY2: - return value try: return value.decode('utf-8') except UnicodeDecodeError as exc: @@ -1449,21 +1546,27 @@ class NullProvider: script = 'scripts/' + script_name if not self.has_metadata(script): raise ResolutionError( - "Script {script!r} not found in metadata at {self.egg_info!r}" - .format(**locals()), + "Script {script!r} not found in metadata at {self.egg_info!r}".format( + **locals() + ), ) script_text = self.get_metadata(script).replace('\r\n', '\n') script_text = script_text.replace('\r', '\n') script_filename = self._fn(self.egg_info, script) namespace['__file__'] = script_filename if os.path.exists(script_filename): - source = open(script_filename).read() + with open(script_filename) as fid: + source = fid.read() code = compile(source, script_filename, 'exec') exec(code, namespace, namespace) else: from linecache import cache + cache[script_filename] = ( - len(script_text), 0, script_text.split('\n'), script_filename + len(script_text), + 0, + script_text.split('\n'), + script_filename, ) script_code = compile(script_text, script_filename, 'exec') exec(script_code, namespace, namespace) @@ -1493,7 +1596,7 @@ class NullProvider: def _validate_resource_path(path): """ Validate the resource paths according to the docs. - https://setuptools.readthedocs.io/en/latest/pkg_resources.html#basic-resource-access + https://setuptools.pypa.io/en/latest/pkg_resources.html#basic-resource-access >>> warned = getfixture('recwarn') >>> warnings.simplefilter('always') @@ -1543,9 +1646,9 @@ is not allowed. AttributeError: ... """ invalid = ( - os.path.pardir in path.split(posixpath.sep) or - posixpath.isabs(path) or - ntpath.isabs(path) + os.path.pardir in path.split(posixpath.sep) + or posixpath.isabs(path) + or ntpath.isabs(path) ) if not invalid: return @@ -1558,10 +1661,9 @@ is not allowed. # for compatibility, warn; in future # raise ValueError(msg) - warnings.warn( + issue_warning( msg[:-1] + " and will raise exceptions in a future release.", DeprecationWarning, - stacklevel=4, ) def _get(self, path): @@ -1575,26 +1677,35 @@ is not allowed. register_loader_type(object, NullProvider) +def _parents(path): + """ + yield all parents of path including path + """ + last = None + while path != last: + yield path + last = path + path, _ = os.path.split(path) + + class EggProvider(NullProvider): """Provider based on a virtual filesystem""" def __init__(self, module): - NullProvider.__init__(self, module) + super().__init__(module) self._setup_prefix() def _setup_prefix(self): - # we assume here that our metadata may be nested inside a "basket" - # of multiple eggs; that's why we use module_path instead of .archive - path = self.module_path - old = None - while path != old: - if _is_egg_path(path): - self.egg_name = os.path.basename(path) - self.egg_info = os.path.join(path, 'EGG-INFO') - self.egg_root = path - break - old = path - path, base = os.path.split(path) + # Assume that metadata may be nested inside a "basket" + # of multiple eggs and use module_path instead of .archive. + eggs = filter(_is_egg_path, _parents(self.module_path)) + egg = next(eggs, None) + egg and self._set_egg(egg) + + def _set_egg(self, path): + self.egg_name = os.path.basename(path) + self.egg_info = os.path.join(path, 'EGG-INFO') + self.egg_root = path class DefaultProvider(EggProvider): @@ -1618,7 +1729,10 @@ class DefaultProvider(EggProvider): @classmethod def _register(cls): - loader_names = 'SourceFileLoader', 'SourcelessFileLoader', + loader_names = ( + 'SourceFileLoader', + 'SourcelessFileLoader', + ) for name in loader_names: loader_cls = getattr(importlib_machinery, name, type(None)) register_loader_type(loader_cls, cls) @@ -1678,6 +1792,7 @@ class MemoizedZipManifests(ZipManifests): """ Memoized zipfile manifests. """ + manifest_mod = collections.namedtuple('manifest_mod', 'manifest mtime') def load(self, path): @@ -1701,7 +1816,7 @@ class ZipProvider(EggProvider): _zip_manifests = MemoizedZipManifests() def __init__(self, module): - EggProvider.__init__(self, module) + super().__init__(module) self.zip_pre = self.loader.archive + os.sep def _zipinfo_name(self, fspath): @@ -1711,20 +1826,16 @@ class ZipProvider(EggProvider): if fspath == self.loader.archive: return '' if fspath.startswith(self.zip_pre): - return fspath[len(self.zip_pre):] - raise AssertionError( - "%s is not a subpath of %s" % (fspath, self.zip_pre) - ) + return fspath[len(self.zip_pre) :] + raise AssertionError("%s is not a subpath of %s" % (fspath, self.zip_pre)) def _parts(self, zip_path): # Convert a zipfile subpath into an egg-relative path part list. # pseudo-fs path fspath = self.zip_pre + zip_path if fspath.startswith(self.egg_root + os.sep): - return fspath[len(self.egg_root) + 1:].split(os.sep) - raise AssertionError( - "%s is not a subpath of %s" % (fspath, self.egg_root) - ) + return fspath[len(self.egg_root) + 1 :].split(os.sep) + raise AssertionError("%s is not a subpath of %s" % (fspath, self.egg_root)) @property def zipinfo(self): @@ -1752,26 +1863,22 @@ class ZipProvider(EggProvider): timestamp = time.mktime(date_time) return timestamp, size - def _extract_resource(self, manager, zip_path): - + # FIXME: 'ZipProvider._extract_resource' is too complex (12) + def _extract_resource(self, manager, zip_path): # noqa: C901 if zip_path in self._index(): for name in self._index()[zip_path]: - last = self._extract_resource( - manager, os.path.join(zip_path, name) - ) + last = self._extract_resource(manager, os.path.join(zip_path, name)) # return the extracted directory name return os.path.dirname(last) timestamp, size = self._get_date_and_size(self.zipinfo[zip_path]) if not WRITE_SUPPORT: - raise IOError('"os.rename" and "os.unlink" are not supported ' - 'on this platform') - try: - - real_path = manager.get_cache_path( - self.egg_name, self._parts(zip_path) + raise IOError( + '"os.rename" and "os.unlink" are not supported ' 'on this platform' ) + try: + real_path = manager.get_cache_path(self.egg_name, self._parts(zip_path)) if self._is_current(real_path, zip_path): return real_path @@ -1900,8 +2007,7 @@ class FileMetadata(EmptyProvider): return metadata def _warn_on_replacement(self, metadata): - # Python 2.7 compat for: replacement_char = '�' - replacement_char = b'\xef\xbf\xbd'.decode('utf-8') + replacement_char = '�' if replacement_char in metadata: tmpl = "{self.path} could not be properly decoded in UTF-8" msg = tmpl.format(**locals()) @@ -1991,7 +2097,7 @@ def find_eggs_in_zip(importer, path_item, only=False): dists = find_eggs_in_zip(zipimport.zipimporter(subpath), subpath) for dist in dists: yield dist - elif subitem.lower().endswith('.dist-info'): + elif subitem.lower().endswith(('.dist-info', '.egg-info')): subpath = os.path.join(path_item, subitem) submeta = EggMetadata(zipimport.zipimporter(subpath)) submeta.egg_info = subpath @@ -2008,58 +2114,21 @@ def find_nothing(importer, path_item, only=False): register_finder(object, find_nothing) -def _by_version_descending(names): - """ - Given a list of filenames, return them in descending order - by version number. - - >>> names = 'bar', 'foo', 'Python-2.7.10.egg', 'Python-2.7.2.egg' - >>> _by_version_descending(names) - ['Python-2.7.10.egg', 'Python-2.7.2.egg', 'foo', 'bar'] - >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.egg' - >>> _by_version_descending(names) - ['Setuptools-1.2.3.egg', 'Setuptools-1.2.3b1.egg'] - >>> names = 'Setuptools-1.2.3b1.egg', 'Setuptools-1.2.3.post1.egg' - >>> _by_version_descending(names) - ['Setuptools-1.2.3.post1.egg', 'Setuptools-1.2.3b1.egg'] - """ - def _by_version(name): - """ - Parse each component of the filename - """ - name, ext = os.path.splitext(name) - parts = itertools.chain(name.split('-'), [ext]) - return [packaging.version.parse(part) for part in parts] - - return sorted(names, key=_by_version, reverse=True) - - def find_on_path(importer, path_item, only=False): """Yield distributions accessible on a sys.path directory""" path_item = _normalize_cached(path_item) if _is_unpacked_egg(path_item): yield Distribution.from_filename( - path_item, metadata=PathMetadata( - path_item, os.path.join(path_item, 'EGG-INFO') - ) + path_item, + metadata=PathMetadata(path_item, os.path.join(path_item, 'EGG-INFO')), ) return - entries = safe_listdir(path_item) - - # for performance, before sorting by version, - # screen entries for only those that will yield - # distributions - filtered = ( - entry - for entry in entries - if dist_factory(path_item, entry, only) - ) + entries = (os.path.join(path_item, child) for child in safe_listdir(path_item)) # scan for .egg and .egg-info in directory - path_item_entries = _by_version_descending(filtered) - for entry in path_item_entries: + for entry in sorted(entries): fullpath = os.path.join(path_item, entry) factory = dist_factory(path_item, entry, only) for dist in factory(fullpath): @@ -2067,19 +2136,21 @@ def find_on_path(importer, path_item, only=False): def dist_factory(path_item, entry, only): - """ - Return a dist_factory for a path_item and entry - """ + """Return a dist_factory for the given entry.""" lower = entry.lower() - is_meta = any(map(lower.endswith, ('.egg-info', '.dist-info'))) + is_egg_info = lower.endswith('.egg-info') + is_dist_info = lower.endswith('.dist-info') and os.path.isdir( + os.path.join(path_item, entry) + ) + is_meta = is_egg_info or is_dist_info return ( distributions_from_metadata - if is_meta else - find_distributions - if not only and _is_egg_path(entry) else - resolve_egg_link - if not only and lower.endswith('.egg-link') else - NoDists() + if is_meta + else find_distributions + if not only and _is_egg_path(entry) + else resolve_egg_link + if not only and lower.endswith('.egg-link') + else NoDists() ) @@ -2091,10 +2162,9 @@ class NoDists: >>> list(NoDists()('anything')) [] """ + def __bool__(self): return False - if six.PY2: - __nonzero__ = __bool__ def __call__(self, fullpath): return iter(()) @@ -2111,12 +2181,7 @@ def safe_listdir(path): except OSError as e: # Ignore the directory if does not exist, not a directory or # permission denied - ignorable = ( - e.errno in (errno.ENOTDIR, errno.EACCES, errno.ENOENT) - # Python 2 on Windows needs to be handled this way :( - or getattr(e, "winerror", None) == 267 - ) - if not ignorable: + if e.errno not in (errno.ENOTDIR, errno.EACCES, errno.ENOENT): raise return () @@ -2132,7 +2197,10 @@ def distributions_from_metadata(path): metadata = FileMetadata(path) entry = os.path.basename(path) yield Distribution.from_location( - root, entry, metadata, precedence=DEVELOP_DIST, + root, + entry, + metadata, + precedence=DEVELOP_DIST, ) @@ -2154,17 +2222,16 @@ def resolve_egg_link(path): """ referenced_paths = non_empty_lines(path) resolved_paths = ( - os.path.join(os.path.dirname(path), ref) - for ref in referenced_paths + os.path.join(os.path.dirname(path), ref) for ref in referenced_paths ) dist_groups = map(find_distributions, resolved_paths) return next(dist_groups, ()) -register_finder(pkgutil.ImpImporter, find_on_path) +if hasattr(pkgutil, 'ImpImporter'): + register_finder(pkgutil.ImpImporter, find_on_path) -if hasattr(importlib_machinery, 'FileFinder'): - register_finder(importlib_machinery.FileFinder, find_on_path) +register_finder(importlib_machinery.FileFinder, find_on_path) _declare_state('dict', _namespace_handlers={}) _declare_state('dict', _namespace_packages={}) @@ -2195,10 +2262,16 @@ def _handle_ns(packageName, path_item): if importer is None: return None - # capture warnings due to #1111 - with warnings.catch_warnings(): - warnings.simplefilter("ignore") - loader = importer.find_module(packageName) + # use find_spec (PEP 451) and fall-back to find_module (PEP 302) + try: + spec = importer.find_spec(packageName) + except AttributeError: + # capture warnings due to #1111 + with warnings.catch_warnings(): + warnings.simplefilter("ignore") + loader = importer.find_module(packageName) + else: + loader = spec.loader if spec else None if loader is None: return None @@ -2214,7 +2287,7 @@ def _handle_ns(packageName, path_item): if subpath is not None: path = module.__path__ path.append(subpath) - loader.load_module(packageName) + importlib.import_module(packageName) _rebuild_mod_path(path, packageName, module) return subpath @@ -2256,6 +2329,15 @@ def _rebuild_mod_path(orig_path, package_name, module): def declare_namespace(packageName): """Declare that package 'packageName' is a namespace package""" + msg = ( + f"Deprecated call to `pkg_resources.declare_namespace({packageName!r})`.\n" + "Implementing implicit namespace packages (as specified in PEP 420) " + "is preferred to `pkg_resources.declare_namespace`. " + "See https://setuptools.pypa.io/en/latest/references/" + "keywords.html#keyword-namespace-packages" + ) + warnings.warn(msg, DeprecationWarning, stacklevel=2) + _imp.acquire_lock() try: if packageName in _namespace_packages: @@ -2270,8 +2352,8 @@ def declare_namespace(packageName): __import__(parent) try: path = sys.modules[parent].__path__ - except AttributeError: - raise TypeError("Not a package:", parent) + except AttributeError as e: + raise TypeError("Not a package:", parent) from e # Track what packages are namespaces, so when new path items are added, # they can be updated @@ -2312,11 +2394,11 @@ def file_ns_handler(importer, path_item, packageName, module): return subpath -register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) -register_namespace_handler(zipimport.zipimporter, file_ns_handler) +if hasattr(pkgutil, 'ImpImporter'): + register_namespace_handler(pkgutil.ImpImporter, file_ns_handler) -if hasattr(importlib_machinery, 'FileFinder'): - register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) +register_namespace_handler(zipimport.zipimporter, file_ns_handler) +register_namespace_handler(importlib_machinery.FileFinder, file_ns_handler) def null_ns_handler(importer, path_item, packageName, module): @@ -2354,16 +2436,23 @@ def _is_egg_path(path): """ Determine if given path appears to be an egg. """ - return path.lower().endswith('.egg') + return _is_zip_egg(path) or _is_unpacked_egg(path) + + +def _is_zip_egg(path): + return ( + path.lower().endswith('.egg') + and os.path.isfile(path) + and zipfile.is_zipfile(path) + ) def _is_unpacked_egg(path): """ Determine if given path appears to be an unpacked egg. """ - return ( - _is_egg_path(path) and - os.path.isfile(os.path.join(path, 'EGG-INFO', 'PKG-INFO')) + return path.lower().endswith('.egg') and os.path.isfile( + os.path.join(path, 'EGG-INFO', 'PKG-INFO') ) @@ -2375,20 +2464,6 @@ def _set_parent_ns(packageName): setattr(sys.modules[parent], name, sys.modules[packageName]) -def yield_lines(strs): - """Yield non-empty/non-comment lines of a string or sequence""" - if isinstance(strs, six.string_types): - for s in strs.splitlines(): - s = s.strip() - # skip blank lines/comments - if s and not s.startswith('#'): - yield s - else: - for ss in strs: - for s in yield_lines(ss): - yield s - - MODULE = re.compile(r"\w+(\.\w+)*$").match EGG_NAME = re.compile( r""" @@ -2450,7 +2525,7 @@ class EntryPoint: try: return functools.reduce(getattr, self.attrs, module) except AttributeError as exc: - raise ImportError(str(exc)) + raise ImportError(str(exc)) from exc def require(self, env=None, installer=None): if self.extras and not self.dist: @@ -2536,22 +2611,15 @@ class EntryPoint: return maps -def _remove_md5_fragment(location): - if not location: - return '' - parsed = urllib.parse.urlparse(location) - if parsed[-1].startswith('md5='): - return urllib.parse.urlunparse(parsed[:-1] + ('',)) - return location - - def _version_from_file(lines): """ Given an iterable of lines from a Metadata file, return the value of the Version field, if present, or None otherwise. """ + def is_version_line(line): return line.lower().startswith('version:') + version_lines = filter(is_version_line, lines) line = next(iter(version_lines), '') _, _, value = line.partition(':') @@ -2560,12 +2628,19 @@ def _version_from_file(lines): class Distribution: """Wrap an actual or potential sys.path entry w/metadata""" + PKG_INFO = 'PKG-INFO' def __init__( - self, location=None, metadata=None, project_name=None, - version=None, py_version=PY_MAJOR, platform=None, - precedence=EGG_DIST): + self, + location=None, + metadata=None, + project_name=None, + version=None, + py_version=PY_MAJOR, + platform=None, + precedence=EGG_DIST, + ): self.project_name = safe_name(project_name or 'Unknown') if version is not None: self._version = safe_version(version) @@ -2588,8 +2663,13 @@ class Distribution: 'name', 'ver', 'pyver', 'plat' ) return cls( - location, metadata, project_name=project_name, version=version, - py_version=py_version, platform=platform, **kw + location, + metadata, + project_name=project_name, + version=version, + py_version=py_version, + platform=platform, + **kw, )._reload_version() def _reload_version(self): @@ -2598,10 +2678,10 @@ class Distribution: @property def hashcmp(self): return ( - self.parsed_version, + self._forgiving_parsed_version, self.precedence, self.key, - _remove_md5_fragment(self.location), + self.location, self.py_version or '', self.platform or '', ) @@ -2645,48 +2725,55 @@ class Distribution: @property def parsed_version(self): if not hasattr(self, "_parsed_version"): - self._parsed_version = parse_version(self.version) + try: + self._parsed_version = parse_version(self.version) + except packaging.version.InvalidVersion as ex: + info = f"(package: {self.project_name})" + if hasattr(ex, "add_note"): + ex.add_note(info) # PEP 678 + raise + raise packaging.version.InvalidVersion(f"{str(ex)} {info}") from None return self._parsed_version - def _warn_legacy_version(self): - LV = packaging.version.LegacyVersion - is_legacy = isinstance(self._parsed_version, LV) - if not is_legacy: - return + @property + def _forgiving_parsed_version(self): + try: + return self.parsed_version + except packaging.version.InvalidVersion as ex: + self._parsed_version = parse_version(_forgiving_version(self.version)) - # While an empty version is technically a legacy version and - # is not a valid PEP 440 version, it's also unlikely to - # actually come from someone and instead it is more likely that - # it comes from setuptools attempting to parse a filename and - # including it in the list. So for that we'll gate this warning - # on if the version is anything at all or not. - if not self.version: - return + notes = "\n".join(getattr(ex, "__notes__", [])) # PEP 678 + msg = f"""!!\n\n + ************************************************************************* + {str(ex)}\n{notes} + + This is a long overdue deprecation. + For the time being, `pkg_resources` will use `{self._parsed_version}` + as a replacement to avoid breaking existing environments, + but no future compatibility is guaranteed. - tmpl = textwrap.dedent(""" - '{project_name} ({version})' is being parsed as a legacy, - non PEP 440, - version. You may find odd behavior and sort order. - In particular it will be sorted as less than 0.0. It - is recommended to migrate to PEP 440 compatible - versions. - """).strip().replace('\n', ' ') + If you maintain package {self.project_name} you should implement + the relevant changes to adequate the project to PEP 440 immediately. + ************************************************************************* + \n\n!! + """ + warnings.warn(msg, DeprecationWarning) - warnings.warn(tmpl.format(**vars(self)), PEP440Warning) + return self._parsed_version @property def version(self): try: return self._version - except AttributeError: + except AttributeError as e: version = self._get_version() if version is None: path = self._get_metadata_path_for_display(self.PKG_INFO) - msg = ( - "Missing 'Version:' header and/or {} file at path: {}" - ).format(self.PKG_INFO, path) - raise ValueError(msg, self) + msg = ("Missing 'Version:' header and/or {} file at path: {}").format( + self.PKG_INFO, path + ) + raise ValueError(msg, self) from e return version @@ -2714,8 +2801,7 @@ class Distribution: reqs = dm.pop(extra) new_extra, _, marker = extra.partition(':') fails_marker = marker and ( - invalid_marker(marker) - or not evaluate_marker(marker) + invalid_marker(marker) or not evaluate_marker(marker) ) if fails_marker: reqs = [] @@ -2739,10 +2825,10 @@ class Distribution: for ext in extras: try: deps.extend(dm[safe_extra(ext)]) - except KeyError: + except KeyError as e: raise UnknownExtra( "%s has no such extra feature %r" % (self, ext) - ) + ) from e return deps def _get_metadata_path_for_display(self, name): @@ -2787,8 +2873,9 @@ class Distribution: def egg_name(self): """Return what this distribution's standard .egg filename should be""" filename = "%s-%s-py%s" % ( - to_filename(self.project_name), to_filename(self.version), - self.py_version or PY_MAJOR + to_filename(self.project_name), + to_filename(self.version), + self.py_version or PY_MAJOR, ) if self.platform: @@ -2818,21 +2905,13 @@ class Distribution: def __dir__(self): return list( set(super(Distribution, self).__dir__()) - | set( - attr for attr in self._provider.__dir__() - if not attr.startswith('_') - ) + | set(attr for attr in self._provider.__dir__() if not attr.startswith('_')) ) - if not hasattr(object, '__dir__'): - # python 2.7 not supported - del __dir__ - @classmethod def from_filename(cls, filename, metadata=None, **kw): return cls.from_location( - _normalize_cached(filename), os.path.basename(filename), metadata, - **kw + _normalize_cached(filename), os.path.basename(filename), metadata, **kw ) def as_requirement(self): @@ -2867,7 +2946,8 @@ class Distribution: """Return the EntryPoint object for `group`+`name`, or ``None``""" return self.get_entry_map(group).get(name) - def insert_on(self, path, loc=None, replace=False): + # FIXME: 'Distribution.insert_on' is too complex (13) + def insert_on(self, path, loc=None, replace=False): # noqa: C901 """Ensure self.location is on path If replace=False (default): @@ -2943,14 +3023,18 @@ class Distribution: nsp = dict.fromkeys(self._get_metadata('namespace_packages.txt')) loc = normalize_path(self.location) for modname in self._get_metadata('top_level.txt'): - if (modname not in sys.modules or modname in nsp - or modname in _namespace_packages): + if ( + modname not in sys.modules + or modname in nsp + or modname in _namespace_packages + ): continue if modname in ('pkg_resources', 'setuptools', 'site'): continue fn = getattr(sys.modules[modname], '__file__', None) - if fn and (normalize_path(fn).startswith(loc) or - fn.startswith(self.location)): + if fn and ( + normalize_path(fn).startswith(loc) or fn.startswith(self.location) + ): continue issue_warning( "Module %s was already imported from %s, but %s is being added" @@ -2963,6 +3047,9 @@ class Distribution: except ValueError: issue_warning("Unbuilt egg for " + repr(self)) return False + except SystemError: + # TODO: remove this except clause when python/cpython#103632 is fixed. + return False return True def clone(self, **kw): @@ -3002,6 +3089,7 @@ class DistInfoDistribution(Distribution): Wrap an actual or potential sys.path entry w/metadata, .dist-info style. """ + PKG_INFO = 'METADATA' EQEQ = re.compile(r"([\(,])\s*(\d.*?)\s*([,\)])") @@ -3037,12 +3125,12 @@ class DistInfoDistribution(Distribution): if not req.marker or req.marker.evaluate({'extra': extra}): yield req - common = frozenset(reqs_for_extra(None)) + common = types.MappingProxyType(dict.fromkeys(reqs_for_extra(None))) dm[None].extend(common) for extra in self._parsed_pkg_info.get_all('Provides-Extra') or []: s_extra = safe_extra(extra.strip()) - dm[s_extra] = list(frozenset(reqs_for_extra(extra)) - common) + dm[s_extra] = [r for r in reqs_for_extra(extra) if r not in common] return dm @@ -3067,45 +3155,27 @@ def issue_warning(*args, **kw): warnings.warn(stacklevel=level + 1, *args, **kw) -class RequirementParseError(ValueError): - def __str__(self): - return ' '.join(self.args) - - def parse_requirements(strs): - """Yield ``Requirement`` objects for each specification in `strs` + """ + Yield ``Requirement`` objects for each specification in `strs`. `strs` must be a string, or a (possibly-nested) iterable thereof. """ - # create a steppable iterator, so we can handle \-continuations - lines = iter(yield_lines(strs)) + return map(Requirement, join_continuation(map(drop_comment, yield_lines(strs)))) - for line in lines: - # Drop comments -- a hash without a space may be in a URL. - if ' #' in line: - line = line[:line.find(' #')] - # If there is a line continuation, drop it, and append the next line. - if line.endswith('\\'): - line = line[:-2].strip() - try: - line += next(lines) - except StopIteration: - return - yield Requirement(line) + +class RequirementParseError(packaging.requirements.InvalidRequirement): + "Compatibility wrapper for InvalidRequirement" class Requirement(packaging.requirements.Requirement): def __init__(self, requirement_string): """DO NOT CALL THIS UNDOCUMENTED METHOD; use Requirement.parse()!""" - try: - super(Requirement, self).__init__(requirement_string) - except packaging.requirements.InvalidRequirement as e: - raise RequirementParseError(str(e)) + super(Requirement, self).__init__(requirement_string) self.unsafe_name = self.name project_name = safe_name(self.name) self.project_name, self.key = project_name, project_name.lower() - self.specs = [ - (spec.operator, spec.version) for spec in self.specifier] + self.specs = [(spec.operator, spec.version) for spec in self.specifier] self.extras = tuple(map(safe_extra, self.extras)) self.hashCmp = ( self.key, @@ -3117,10 +3187,7 @@ class Requirement(packaging.requirements.Requirement): self.__hash = hash(self.hashCmp) def __eq__(self, other): - return ( - isinstance(other, Requirement) and - self.hashCmp == other.hashCmp - ) + return isinstance(other, Requirement) and self.hashCmp == other.hashCmp def __ne__(self, other): return not self == other @@ -3145,7 +3212,7 @@ class Requirement(packaging.requirements.Requirement): @staticmethod def parse(s): - req, = parse_requirements(s) + (req,) = parse_requirements(s) return req @@ -3170,7 +3237,7 @@ def _find_adapter(registry, ob): def ensure_directory(path): """Ensure that the parent directory of `path` exists""" dirname = os.path.dirname(path) - py31compat.makedirs(dirname, exist_ok=True) + os.makedirs(dirname, exist_ok=True) def _bypass_ensure_directory(path): @@ -3248,6 +3315,15 @@ def _initialize(g=globals()): ) +class PkgResourcesDeprecationWarning(Warning): + """ + Base class for warning about deprecations in ``pkg_resources`` + + This class is not derived from ``DeprecationWarning``, and as such is + visible by default. + """ + + @_call_aside def _initialize_master_working_set(): """ @@ -3274,10 +3350,7 @@ def _initialize_master_working_set(): # ensure that all distributions added to the working set in the future # (e.g. by calling ``require()``) will get activated as well, # with higher priority (replace=True). - tuple( - dist.activate(replace=False) - for dist in working_set - ) + tuple(dist.activate(replace=False) for dist in working_set) add_activation_listener( lambda dist: dist.activate(replace=True), existing=False, @@ -3286,11 +3359,3 @@ def _initialize_master_working_set(): # match order list(map(working_set.add_entry, sys.path)) globals().update(locals()) - -class PkgResourcesDeprecationWarning(Warning): - """ - Base class for warning about deprecations in ``pkg_resources`` - - This class is not derived from ``DeprecationWarning``, and as such is - visible by default. - """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py b/.venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py deleted file mode 100644 index a2d3007c..00000000 --- a/.venv/Lib/site-packages/pip/_vendor/pkg_resources/py31compat.py +++ /dev/null @@ -1,23 +0,0 @@ -import os -import errno -import sys - -from pip._vendor import six - - -def _makedirs_31(path, exist_ok=False): - try: - os.makedirs(path) - except OSError as exc: - if not exist_ok or exc.errno != errno.EEXIST: - raise - - -# rely on compatibility behavior until mode considerations -# and exists_ok considerations are disentangled. -# See https://github.com/pypa/setuptools/pull/1083#issuecomment-315168663 -needs_makedirs = ( - six.PY2 or - (3, 4) <= sys.version_info < (3, 4, 1) -) -makedirs = _makedirs_31 if needs_makedirs else os.makedirs diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py index 82d90716..5ebf5957 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/__init__.py @@ -6,17 +6,20 @@ from __future__ import annotations import os import sys -from pathlib import Path - -if sys.version_info >= (3, 8): # pragma: no cover (py38+) - from typing import Literal -else: # pragma: no cover (py38+) - from pip._vendor.typing_extensions import Literal +from typing import TYPE_CHECKING from .api import PlatformDirsABC from .version import __version__ from .version import __version_tuple__ as __version_info__ +if TYPE_CHECKING: + from pathlib import Path + + if sys.version_info >= (3, 8): # pragma: no cover (py38+) + from typing import Literal + else: # pragma: no cover (py38+) + from pip._vendor.typing_extensions import Literal + def _set_platform_dir_class() -> type[PlatformDirsABC]: if sys.platform == "win32": @@ -27,7 +30,6 @@ def _set_platform_dir_class() -> type[PlatformDirsABC]: from pip._vendor.platformdirs.unix import Unix as Result if os.getenv("ANDROID_DATA") == "/data" and os.getenv("ANDROID_ROOT") == "/system": - if os.getenv("SHELL") or os.getenv("PREFIX"): return Result @@ -49,270 +51,482 @@ def user_data_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: data directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_data_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_data_dir def site_data_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - multipath: bool = False, + multipath: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param multipath: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: data directory shared by users """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_data_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + multipath=multipath, + ensure_exists=ensure_exists, + ).site_data_dir def user_config_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: config directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_config_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_config_dir def site_config_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - multipath: bool = False, + multipath: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param multipath: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: config directory shared by the users """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_config_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + multipath=multipath, + ensure_exists=ensure_exists, + ).site_config_dir def user_cache_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: cache directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_cache_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_cache_dir + + +def site_cache_dir( + appname: str | None = None, + appauthor: str | None | Literal[False] = None, + version: str | None = None, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 +) -> str: + """ + :param appname: See `appname `. + :param appauthor: See `appauthor `. + :param version: See `version `. + :param opinion: See `opinion `. + :param ensure_exists: See `ensure_exists `. + :returns: cache directory tied to the user + """ + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).site_cache_dir def user_state_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: state directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_state_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_state_dir def user_log_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: log directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_log_dir def user_documents_dir() -> str: - """ - :returns: documents directory tied to the user - """ + """:returns: documents directory tied to the user""" return PlatformDirs().user_documents_dir +def user_downloads_dir() -> str: + """:returns: downloads directory tied to the user""" + return PlatformDirs().user_downloads_dir + + +def user_pictures_dir() -> str: + """:returns: pictures directory tied to the user""" + return PlatformDirs().user_pictures_dir + + +def user_videos_dir() -> str: + """:returns: videos directory tied to the user""" + return PlatformDirs().user_videos_dir + + +def user_music_dir() -> str: + """:returns: music directory tied to the user""" + return PlatformDirs().user_music_dir + + def user_runtime_dir( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> str: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `opinion `. + :param ensure_exists: See `ensure_exists `. :returns: runtime directory tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_dir + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_runtime_dir def user_data_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: data path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_data_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_data_path def site_data_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - multipath: bool = False, + multipath: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param multipath: See `multipath `. + :param ensure_exists: See `ensure_exists `. :returns: data path shared by users """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_data_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + multipath=multipath, + ensure_exists=ensure_exists, + ).site_data_path def user_config_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: config path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_config_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_config_path def site_config_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - multipath: bool = False, + multipath: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param multipath: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: config path shared by the users """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, multipath=multipath).site_config_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + multipath=multipath, + ensure_exists=ensure_exists, + ).site_config_path + + +def site_cache_path( + appname: str | None = None, + appauthor: str | None | Literal[False] = None, + version: str | None = None, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 +) -> Path: + """ + :param appname: See `appname `. + :param appauthor: See `appauthor `. + :param version: See `version `. + :param opinion: See `opinion `. + :param ensure_exists: See `ensure_exists `. + :returns: cache directory tied to the user + """ + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).site_cache_path def user_cache_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: cache path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_cache_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_cache_path def user_state_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, + roaming: bool = False, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. - :param roaming: See `roaming `. + :param roaming: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: state path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, roaming=roaming).user_state_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + roaming=roaming, + ensure_exists=ensure_exists, + ).user_state_path def user_log_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `roaming `. + :param ensure_exists: See `ensure_exists `. :returns: log path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_log_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_log_path def user_documents_path() -> Path: - """ - :returns: documents path tied to the user - """ + """:returns: documents path tied to the user""" return PlatformDirs().user_documents_path +def user_downloads_path() -> Path: + """:returns: downloads path tied to the user""" + return PlatformDirs().user_downloads_path + + +def user_pictures_path() -> Path: + """:returns: pictures path tied to the user""" + return PlatformDirs().user_pictures_path + + +def user_videos_path() -> Path: + """:returns: videos path tied to the user""" + return PlatformDirs().user_videos_path + + +def user_music_path() -> Path: + """:returns: music path tied to the user""" + return PlatformDirs().user_music_path + + def user_runtime_path( appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - opinion: bool = True, + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 ) -> Path: """ :param appname: See `appname `. :param appauthor: See `appauthor `. :param version: See `version `. :param opinion: See `opinion `. + :param ensure_exists: See `ensure_exists `. :returns: runtime path tied to the user """ - return PlatformDirs(appname=appname, appauthor=appauthor, version=version, opinion=opinion).user_runtime_path + return PlatformDirs( + appname=appname, + appauthor=appauthor, + version=version, + opinion=opinion, + ensure_exists=ensure_exists, + ).user_runtime_path __all__ = [ @@ -327,16 +541,26 @@ __all__ = [ "user_state_dir", "user_log_dir", "user_documents_dir", + "user_downloads_dir", + "user_pictures_dir", + "user_videos_dir", + "user_music_dir", "user_runtime_dir", "site_data_dir", "site_config_dir", + "site_cache_dir", "user_data_path", "user_config_path", "user_cache_path", "user_state_path", "user_log_path", "user_documents_path", + "user_downloads_path", + "user_pictures_path", + "user_videos_path", + "user_music_path", "user_runtime_path", "site_data_path", "site_config_path", + "site_cache_path", ] diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py index 9c54bfb4..6a0d6dd1 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/__main__.py @@ -1,3 +1,4 @@ +"""Main entry point.""" from __future__ import annotations from pip._vendor.platformdirs import PlatformDirs, __version__ @@ -9,37 +10,43 @@ PROPS = ( "user_state_dir", "user_log_dir", "user_documents_dir", + "user_downloads_dir", + "user_pictures_dir", + "user_videos_dir", + "user_music_dir", "user_runtime_dir", "site_data_dir", "site_config_dir", + "site_cache_dir", ) def main() -> None: + """Run main entry point.""" app_name = "MyApp" app_author = "MyCompany" - print(f"-- platformdirs {__version__} --") + print(f"-- platformdirs {__version__} --") # noqa: T201 - print("-- app dirs (with optional 'version')") + print("-- app dirs (with optional 'version')") # noqa: T201 dirs = PlatformDirs(app_name, app_author, version="1.0") for prop in PROPS: - print(f"{prop}: {getattr(dirs, prop)}") + print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201 - print("\n-- app dirs (without optional 'version')") + print("\n-- app dirs (without optional 'version')") # noqa: T201 dirs = PlatformDirs(app_name, app_author) for prop in PROPS: - print(f"{prop}: {getattr(dirs, prop)}") + print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201 - print("\n-- app dirs (without optional 'appauthor')") + print("\n-- app dirs (without optional 'appauthor')") # noqa: T201 dirs = PlatformDirs(app_name) for prop in PROPS: - print(f"{prop}: {getattr(dirs, prop)}") + print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201 - print("\n-- app dirs (with disabled 'appauthor')") + print("\n-- app dirs (with disabled 'appauthor')") # noqa: T201 dirs = PlatformDirs(app_name, appauthor=False) for prop in PROPS: - print(f"{prop}: {getattr(dirs, prop)}") + print(f"{prop}: {getattr(dirs, prop)}") # noqa: T201 if __name__ == "__main__": diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/android.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/android.py index eda80935..76527dda 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/android.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/android.py @@ -1,3 +1,4 @@ +"""Android.""" from __future__ import annotations import os @@ -12,8 +13,9 @@ from .api import PlatformDirsABC class Android(PlatformDirsABC): """ Follows the guidance `from here `_. Makes use of the - `appname ` and - `version `. + `appname `, + `version `, + `ensure_exists `. """ @property @@ -29,7 +31,8 @@ class Android(PlatformDirsABC): @property def user_config_dir(self) -> str: """ - :return: config directory tied to the user, e.g. ``/data/user///shared_prefs/`` + :return: config directory tied to the user, e.g. \ + ``/data/user///shared_prefs/`` """ return self._append_app_name_and_version(cast(str, _android_folder()), "shared_prefs") @@ -43,6 +46,11 @@ class Android(PlatformDirsABC): """:return: cache directory tied to the user, e.g. e.g. ``/data/user///cache/``""" return self._append_app_name_and_version(cast(str, _android_folder()), "cache") + @property + def site_cache_dir(self) -> str: + """:return: cache directory shared by users, same as `user_cache_dir`""" + return self.user_cache_dir + @property def user_state_dir(self) -> str: """:return: state directory tied to the user, same as `user_data_dir`""" @@ -56,16 +64,34 @@ class Android(PlatformDirsABC): """ path = self.user_cache_dir if self.opinion: - path = os.path.join(path, "log") + path = os.path.join(path, "log") # noqa: PTH118 return path @property def user_documents_dir(self) -> str: - """ - :return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents`` - """ + """:return: documents directory tied to the user e.g. ``/storage/emulated/0/Documents``""" return _android_documents_folder() + @property + def user_downloads_dir(self) -> str: + """:return: downloads directory tied to the user e.g. ``/storage/emulated/0/Downloads``""" + return _android_downloads_folder() + + @property + def user_pictures_dir(self) -> str: + """:return: pictures directory tied to the user e.g. ``/storage/emulated/0/Pictures``""" + return _android_pictures_folder() + + @property + def user_videos_dir(self) -> str: + """:return: videos directory tied to the user e.g. ``/storage/emulated/0/DCIM/Camera``""" + return _android_videos_folder() + + @property + def user_music_dir(self) -> str: + """:return: music directory tied to the user e.g. ``/storage/emulated/0/Music``""" + return _android_music_folder() + @property def user_runtime_dir(self) -> str: """ @@ -74,20 +100,20 @@ class Android(PlatformDirsABC): """ path = self.user_cache_dir if self.opinion: - path = os.path.join(path, "tmp") + path = os.path.join(path, "tmp") # noqa: PTH118 return path @lru_cache(maxsize=1) def _android_folder() -> str | None: - """:return: base folder for the Android OS or None if cannot be found""" + """:return: base folder for the Android OS or None if it cannot be found""" try: # First try to get path to android app via pyjnius from jnius import autoclass - Context = autoclass("android.content.Context") # noqa: N806 - result: str | None = Context.getFilesDir().getParentFile().getAbsolutePath() - except Exception: + context = autoclass("android.content.Context") + result: str | None = context.getFilesDir().getParentFile().getAbsolutePath() + except Exception: # noqa: BLE001 # if fails find an android folder looking path on the sys.path pattern = re.compile(r"/data/(data|user/\d+)/(.+)/files") for path in sys.path: @@ -106,15 +132,79 @@ def _android_documents_folder() -> str: try: from jnius import autoclass - Context = autoclass("android.content.Context") # noqa: N806 - Environment = autoclass("android.os.Environment") # noqa: N806 - documents_dir: str = Context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath() - except Exception: + context = autoclass("android.content.Context") + environment = autoclass("android.os.Environment") + documents_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOCUMENTS).getAbsolutePath() + except Exception: # noqa: BLE001 documents_dir = "/storage/emulated/0/Documents" return documents_dir +@lru_cache(maxsize=1) +def _android_downloads_folder() -> str: + """:return: downloads folder for the Android OS""" + # Get directories with pyjnius + try: + from jnius import autoclass + + context = autoclass("android.content.Context") + environment = autoclass("android.os.Environment") + downloads_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + except Exception: # noqa: BLE001 + downloads_dir = "/storage/emulated/0/Downloads" + + return downloads_dir + + +@lru_cache(maxsize=1) +def _android_pictures_folder() -> str: + """:return: pictures folder for the Android OS""" + # Get directories with pyjnius + try: + from jnius import autoclass + + context = autoclass("android.content.Context") + environment = autoclass("android.os.Environment") + pictures_dir: str = context.getExternalFilesDir(environment.DIRECTORY_PICTURES).getAbsolutePath() + except Exception: # noqa: BLE001 + pictures_dir = "/storage/emulated/0/Pictures" + + return pictures_dir + + +@lru_cache(maxsize=1) +def _android_videos_folder() -> str: + """:return: videos folder for the Android OS""" + # Get directories with pyjnius + try: + from jnius import autoclass + + context = autoclass("android.content.Context") + environment = autoclass("android.os.Environment") + videos_dir: str = context.getExternalFilesDir(environment.DIRECTORY_DCIM).getAbsolutePath() + except Exception: # noqa: BLE001 + videos_dir = "/storage/emulated/0/DCIM/Camera" + + return videos_dir + + +@lru_cache(maxsize=1) +def _android_music_folder() -> str: + """:return: music folder for the Android OS""" + # Get directories with pyjnius + try: + from jnius import autoclass + + context = autoclass("android.content.Context") + environment = autoclass("android.os.Environment") + music_dir: str = context.getExternalFilesDir(environment.DIRECTORY_MUSIC).getAbsolutePath() + except Exception: # noqa: BLE001 + music_dir = "/storage/emulated/0/Music" + + return music_dir + + __all__ = [ "Android", ] diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py index 6f6e2c2c..d64ebb9d 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/api.py @@ -1,28 +1,33 @@ +"""Base API.""" from __future__ import annotations import os -import sys from abc import ABC, abstractmethod from pathlib import Path +from typing import TYPE_CHECKING -if sys.version_info >= (3, 8): # pragma: no branch - from typing import Literal # pragma: no cover +if TYPE_CHECKING: + import sys + + if sys.version_info >= (3, 8): # pragma: no cover (py38+) + from typing import Literal + else: # pragma: no cover (py38+) + from pip._vendor.typing_extensions import Literal class PlatformDirsABC(ABC): - """ - Abstract base class for platform directories. - """ + """Abstract base class for platform directories.""" - def __init__( + def __init__( # noqa: PLR0913 self, appname: str | None = None, appauthor: str | None | Literal[False] = None, version: str | None = None, - roaming: bool = False, - multipath: bool = False, - opinion: bool = True, - ): + roaming: bool = False, # noqa: FBT001, FBT002 + multipath: bool = False, # noqa: FBT001, FBT002 + opinion: bool = True, # noqa: FBT001, FBT002 + ensure_exists: bool = False, # noqa: FBT001, FBT002 + ) -> None: """ Create a new platform directory. @@ -32,6 +37,7 @@ class PlatformDirsABC(ABC): :param roaming: See `roaming`. :param multipath: See `multipath`. :param opinion: See `opinion`. + :param ensure_exists: See `ensure_exists`. """ self.appname = appname #: The name of application. self.appauthor = appauthor @@ -56,6 +62,11 @@ class PlatformDirsABC(ABC): returned. By default, the first item would only be returned. """ self.opinion = opinion #: A flag to indicating to use opinionated values. + self.ensure_exists = ensure_exists + """ + Optionally create the directory (and any missing parents) upon access if it does not exist. + By default, no directories are created. + """ def _append_app_name_and_version(self, *base: str) -> str: params = list(base[1:]) @@ -63,7 +74,13 @@ class PlatformDirsABC(ABC): params.append(self.appname) if self.version: params.append(self.version) - return os.path.join(base[0], *params) + path = os.path.join(base[0], *params) # noqa: PTH118 + self._optionally_create_directory(path) + return path + + def _optionally_create_directory(self, path: str) -> None: + if self.ensure_exists: + Path(path).mkdir(parents=True, exist_ok=True) @property @abstractmethod @@ -90,6 +107,11 @@ class PlatformDirsABC(ABC): def user_cache_dir(self) -> str: """:return: cache directory tied to the user""" + @property + @abstractmethod + def site_cache_dir(self) -> str: + """:return: cache directory shared by users""" + @property @abstractmethod def user_state_dir(self) -> str: @@ -105,6 +127,26 @@ class PlatformDirsABC(ABC): def user_documents_dir(self) -> str: """:return: documents directory tied to the user""" + @property + @abstractmethod + def user_downloads_dir(self) -> str: + """:return: downloads directory tied to the user""" + + @property + @abstractmethod + def user_pictures_dir(self) -> str: + """:return: pictures directory tied to the user""" + + @property + @abstractmethod + def user_videos_dir(self) -> str: + """:return: videos directory tied to the user""" + + @property + @abstractmethod + def user_music_dir(self) -> str: + """:return: music directory tied to the user""" + @property @abstractmethod def user_runtime_dir(self) -> str: @@ -135,6 +177,11 @@ class PlatformDirsABC(ABC): """:return: cache path tied to the user""" return Path(self.user_cache_dir) + @property + def site_cache_path(self) -> Path: + """:return: cache path shared by users""" + return Path(self.site_cache_dir) + @property def user_state_path(self) -> Path: """:return: state path tied to the user""" @@ -150,6 +197,26 @@ class PlatformDirsABC(ABC): """:return: documents path tied to the user""" return Path(self.user_documents_dir) + @property + def user_downloads_path(self) -> Path: + """:return: downloads path tied to the user""" + return Path(self.user_downloads_dir) + + @property + def user_pictures_path(self) -> Path: + """:return: pictures path tied to the user""" + return Path(self.user_pictures_dir) + + @property + def user_videos_path(self) -> Path: + """:return: videos path tied to the user""" + return Path(self.user_videos_dir) + + @property + def user_music_path(self) -> Path: + """:return: music path tied to the user""" + return Path(self.user_music_dir) + @property def user_runtime_path(self) -> Path: """:return: runtime path tied to the user""" diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py index a01337c7..a753e2a3 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/macos.py @@ -1,6 +1,7 @@ +"""macOS.""" from __future__ import annotations -import os +import os.path from .api import PlatformDirsABC @@ -9,14 +10,15 @@ class MacOS(PlatformDirsABC): """ Platform directories for the macOS operating system. Follows the guidance from `Apple documentation `_. - Makes use of the `appname ` and - `version `. + Makes use of the `appname `, + `version `, + `ensure_exists `. """ @property def user_data_dir(self) -> str: """:return: data directory tied to the user, e.g. ``~/Library/Application Support/$appname/$version``""" - return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support/")) + return self._append_app_name_and_version(os.path.expanduser("~/Library/Application Support")) # noqa: PTH111 @property def site_data_dir(self) -> str: @@ -25,18 +27,23 @@ class MacOS(PlatformDirsABC): @property def user_config_dir(self) -> str: - """:return: config directory tied to the user, e.g. ``~/Library/Preferences/$appname/$version``""" - return self._append_app_name_and_version(os.path.expanduser("~/Library/Preferences/")) + """:return: config directory tied to the user, same as `user_data_dir`""" + return self.user_data_dir @property def site_config_dir(self) -> str: - """:return: config directory shared by the users, e.g. ``/Library/Preferences/$appname``""" - return self._append_app_name_and_version("/Library/Preferences") + """:return: config directory shared by the users, same as `site_data_dir`""" + return self.site_data_dir @property def user_cache_dir(self) -> str: """:return: cache directory tied to the user, e.g. ``~/Library/Caches/$appname/$version``""" - return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches")) + return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches")) # noqa: PTH111 + + @property + def site_cache_dir(self) -> str: + """:return: cache directory shared by users, e.g. ``/Library/Caches/$appname/$version``""" + return self._append_app_name_and_version("/Library/Caches") @property def user_state_dir(self) -> str: @@ -46,17 +53,37 @@ class MacOS(PlatformDirsABC): @property def user_log_dir(self) -> str: """:return: log directory tied to the user, e.g. ``~/Library/Logs/$appname/$version``""" - return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs")) + return self._append_app_name_and_version(os.path.expanduser("~/Library/Logs")) # noqa: PTH111 @property def user_documents_dir(self) -> str: """:return: documents directory tied to the user, e.g. ``~/Documents``""" - return os.path.expanduser("~/Documents") + return os.path.expanduser("~/Documents") # noqa: PTH111 + + @property + def user_downloads_dir(self) -> str: + """:return: downloads directory tied to the user, e.g. ``~/Downloads``""" + return os.path.expanduser("~/Downloads") # noqa: PTH111 + + @property + def user_pictures_dir(self) -> str: + """:return: pictures directory tied to the user, e.g. ``~/Pictures``""" + return os.path.expanduser("~/Pictures") # noqa: PTH111 + + @property + def user_videos_dir(self) -> str: + """:return: videos directory tied to the user, e.g. ``~/Movies``""" + return os.path.expanduser("~/Movies") # noqa: PTH111 + + @property + def user_music_dir(self) -> str: + """:return: music directory tied to the user, e.g. ``~/Music``""" + return os.path.expanduser("~/Music") # noqa: PTH111 @property def user_runtime_dir(self) -> str: """:return: runtime directory tied to the user, e.g. ``~/Library/Caches/TemporaryItems/$appname/$version``""" - return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems")) + return self._append_app_name_and_version(os.path.expanduser("~/Library/Caches/TemporaryItems")) # noqa: PTH111 __all__ = [ diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py index 9aca5a03..468b0ab4 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/unix.py @@ -1,3 +1,4 @@ +"""Unix.""" from __future__ import annotations import os @@ -7,12 +8,14 @@ from pathlib import Path from .api import PlatformDirsABC -if sys.platform.startswith("linux"): # pragma: no branch # no op check, only to please the type checker - from os import getuid -else: +if sys.platform == "win32": def getuid() -> int: - raise RuntimeError("should only be used on Linux") + msg = "should only be used on Unix" + raise RuntimeError(msg) + +else: + from os import getuid class Unix(PlatformDirsABC): @@ -24,7 +27,8 @@ class Unix(PlatformDirsABC): `appname `, `version `, `multipath `, - `opinion `. + `opinion `, + `ensure_exists `. """ @property @@ -35,7 +39,7 @@ class Unix(PlatformDirsABC): """ path = os.environ.get("XDG_DATA_HOME", "") if not path.strip(): - path = os.path.expanduser("~/.local/share") + path = os.path.expanduser("~/.local/share") # noqa: PTH111 return self._append_app_name_and_version(path) @property @@ -55,7 +59,7 @@ class Unix(PlatformDirsABC): path_list = path.split(os.pathsep) if not self.multipath: path_list = path_list[0:1] - path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list] + path_list = [self._append_app_name_and_version(os.path.expanduser(p)) for p in path_list] # noqa: PTH111 return os.pathsep.join(path_list) @property @@ -66,7 +70,7 @@ class Unix(PlatformDirsABC): """ path = os.environ.get("XDG_CONFIG_HOME", "") if not path.strip(): - path = os.path.expanduser("~/.config") + path = os.path.expanduser("~/.config") # noqa: PTH111 return self._append_app_name_and_version(path) @property @@ -90,9 +94,14 @@ class Unix(PlatformDirsABC): """ path = os.environ.get("XDG_CACHE_HOME", "") if not path.strip(): - path = os.path.expanduser("~/.cache") + path = os.path.expanduser("~/.cache") # noqa: PTH111 return self._append_app_name_and_version(path) + @property + def site_cache_dir(self) -> str: + """:return: cache directory shared by users, e.g. ``/var/tmp/$appname/$version``""" + return self._append_app_name_and_version("/var/tmp") # noqa: S108 + @property def user_state_dir(self) -> str: """ @@ -101,41 +110,60 @@ class Unix(PlatformDirsABC): """ path = os.environ.get("XDG_STATE_HOME", "") if not path.strip(): - path = os.path.expanduser("~/.local/state") + path = os.path.expanduser("~/.local/state") # noqa: PTH111 return self._append_app_name_and_version(path) @property def user_log_dir(self) -> str: - """ - :return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it - """ + """:return: log directory tied to the user, same as `user_state_dir` if not opinionated else ``log`` in it""" path = self.user_state_dir if self.opinion: - path = os.path.join(path, "log") + path = os.path.join(path, "log") # noqa: PTH118 return path @property def user_documents_dir(self) -> str: - """ - :return: documents directory tied to the user, e.g. ``~/Documents`` - """ - documents_dir = _get_user_dirs_folder("XDG_DOCUMENTS_DIR") - if documents_dir is None: - documents_dir = os.environ.get("XDG_DOCUMENTS_DIR", "").strip() - if not documents_dir: - documents_dir = os.path.expanduser("~/Documents") + """:return: documents directory tied to the user, e.g. ``~/Documents``""" + return _get_user_media_dir("XDG_DOCUMENTS_DIR", "~/Documents") - return documents_dir + @property + def user_downloads_dir(self) -> str: + """:return: downloads directory tied to the user, e.g. ``~/Downloads``""" + return _get_user_media_dir("XDG_DOWNLOAD_DIR", "~/Downloads") + + @property + def user_pictures_dir(self) -> str: + """:return: pictures directory tied to the user, e.g. ``~/Pictures``""" + return _get_user_media_dir("XDG_PICTURES_DIR", "~/Pictures") + + @property + def user_videos_dir(self) -> str: + """:return: videos directory tied to the user, e.g. ``~/Videos``""" + return _get_user_media_dir("XDG_VIDEOS_DIR", "~/Videos") + + @property + def user_music_dir(self) -> str: + """:return: music directory tied to the user, e.g. ``~/Music``""" + return _get_user_media_dir("XDG_MUSIC_DIR", "~/Music") @property def user_runtime_dir(self) -> str: """ :return: runtime directory tied to the user, e.g. ``/run/user/$(id -u)/$appname/$version`` or - ``$XDG_RUNTIME_DIR/$appname/$version`` + ``$XDG_RUNTIME_DIR/$appname/$version``. + + For FreeBSD/OpenBSD/NetBSD, it would return ``/var/run/user/$(id -u)/$appname/$version`` if + exists, otherwise ``/tmp/runtime-$(id -u)/$appname/$version``, if``$XDG_RUNTIME_DIR`` + is not set. """ path = os.environ.get("XDG_RUNTIME_DIR", "") if not path.strip(): - path = f"/run/user/{getuid()}" + if sys.platform.startswith(("freebsd", "openbsd", "netbsd")): + path = f"/var/run/user/{getuid()}" + if not Path(path).exists(): + path = f"/tmp/runtime-{getuid()}" # noqa: S108 + else: + path = f"/run/user/{getuid()}" return self._append_app_name_and_version(path) @property @@ -148,6 +176,11 @@ class Unix(PlatformDirsABC): """:return: config path shared by the users. Only return first item, even if ``multipath`` is set to ``True``""" return self._first_item_as_path_if_multipath(self.site_config_dir) + @property + def site_cache_path(self) -> Path: + """:return: cache path shared by users. Only return first item, even if ``multipath`` is set to ``True``""" + return self._first_item_as_path_if_multipath(self.site_cache_dir) + def _first_item_as_path_if_multipath(self, directory: str) -> Path: if self.multipath: # If multipath is True, the first path is returned. @@ -155,13 +188,23 @@ class Unix(PlatformDirsABC): return Path(directory) +def _get_user_media_dir(env_var: str, fallback_tilde_path: str) -> str: + media_dir = _get_user_dirs_folder(env_var) + if media_dir is None: + media_dir = os.environ.get(env_var, "").strip() + if not media_dir: + media_dir = os.path.expanduser(fallback_tilde_path) # noqa: PTH111 + + return media_dir + + def _get_user_dirs_folder(key: str) -> str | None: - """Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/""" - user_dirs_config_path = os.path.join(Unix().user_config_dir, "user-dirs.dirs") - if os.path.exists(user_dirs_config_path): + """Return directory from user-dirs.dirs config file. See https://freedesktop.org/wiki/Software/xdg-user-dirs/.""" + user_dirs_config_path = Path(Unix().user_config_dir) / "user-dirs.dirs" + if user_dirs_config_path.exists(): parser = ConfigParser() - with open(user_dirs_config_path) as stream: + with user_dirs_config_path.open() as stream: # Add fake section header, so ConfigParser doesn't complain parser.read_string(f"[top]\n{stream.read()}") @@ -170,8 +213,7 @@ def _get_user_dirs_folder(key: str) -> str | None: path = parser["top"][key].strip('"') # Handle relative home paths - path = path.replace("$HOME", os.path.expanduser("~")) - return path + return path.replace("$HOME", os.path.expanduser("~")) # noqa: PTH111 return None diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py index 9f6eb98e..dc8c44cf 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/version.py @@ -1,4 +1,4 @@ # file generated by setuptools_scm # don't change, don't track in version control -__version__ = version = '2.6.2' -__version_tuple__ = version_tuple = (2, 6, 2) +__version__ = version = '3.8.1' +__version_tuple__ = version_tuple = (3, 8, 1) diff --git a/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py b/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py index d5c27b34..b52c9c6e 100644 --- a/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py +++ b/.venv/Lib/site-packages/pip/_vendor/platformdirs/windows.py @@ -1,23 +1,30 @@ +"""Windows.""" from __future__ import annotations import ctypes import os import sys from functools import lru_cache -from typing import Callable +from typing import TYPE_CHECKING from .api import PlatformDirsABC +if TYPE_CHECKING: + from collections.abc import Callable + class Windows(PlatformDirsABC): - """`MSDN on where to store app data files + """ + `MSDN on where to store app data files `_. Makes use of the `appname `, `appauthor `, `version `, `roaming `, - `opinion `.""" + `opinion `, + `ensure_exists `. + """ @property def user_data_dir(self) -> str: @@ -41,7 +48,9 @@ class Windows(PlatformDirsABC): params.append(opinion_value) if self.version: params.append(self.version) - return os.path.join(path, *params) + path = os.path.join(path, *params) # noqa: PTH118 + self._optionally_create_directory(path) + return path @property def site_data_dir(self) -> str: @@ -68,6 +77,12 @@ class Windows(PlatformDirsABC): path = os.path.normpath(get_win_folder("CSIDL_LOCAL_APPDATA")) return self._append_parts(path, opinion_value="Cache") + @property + def site_cache_dir(self) -> str: + """:return: cache directory shared by users, e.g. ``C:\\ProgramData\\$appauthor\\$appname\\Cache\\$version``""" + path = os.path.normpath(get_win_folder("CSIDL_COMMON_APPDATA")) + return self._append_parts(path, opinion_value="Cache") + @property def user_state_dir(self) -> str: """:return: state directory tied to the user, same as `user_data_dir`""" @@ -75,35 +90,53 @@ class Windows(PlatformDirsABC): @property def user_log_dir(self) -> str: - """ - :return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it - """ + """:return: log directory tied to the user, same as `user_data_dir` if not opinionated else ``Logs`` in it""" path = self.user_data_dir if self.opinion: - path = os.path.join(path, "Logs") + path = os.path.join(path, "Logs") # noqa: PTH118 + self._optionally_create_directory(path) return path @property def user_documents_dir(self) -> str: - """ - :return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents`` - """ + """:return: documents directory tied to the user e.g. ``%USERPROFILE%\\Documents``""" return os.path.normpath(get_win_folder("CSIDL_PERSONAL")) + @property + def user_downloads_dir(self) -> str: + """:return: downloads directory tied to the user e.g. ``%USERPROFILE%\\Downloads``""" + return os.path.normpath(get_win_folder("CSIDL_DOWNLOADS")) + + @property + def user_pictures_dir(self) -> str: + """:return: pictures directory tied to the user e.g. ``%USERPROFILE%\\Pictures``""" + return os.path.normpath(get_win_folder("CSIDL_MYPICTURES")) + + @property + def user_videos_dir(self) -> str: + """:return: videos directory tied to the user e.g. ``%USERPROFILE%\\Videos``""" + return os.path.normpath(get_win_folder("CSIDL_MYVIDEO")) + + @property + def user_music_dir(self) -> str: + """:return: music directory tied to the user e.g. ``%USERPROFILE%\\Music``""" + return os.path.normpath(get_win_folder("CSIDL_MYMUSIC")) + @property def user_runtime_dir(self) -> str: """ :return: runtime directory tied to the user, e.g. ``%USERPROFILE%\\AppData\\Local\\Temp\\$appauthor\\$appname`` """ - path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp")) + path = os.path.normpath(os.path.join(get_win_folder("CSIDL_LOCAL_APPDATA"), "Temp")) # noqa: PTH118 return self._append_parts(path) def get_win_folder_from_env_vars(csidl_name: str) -> str: """Get folder from environment variables.""" - if csidl_name == "CSIDL_PERSONAL": # does not have an environment name - return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents") + result = get_win_folder_if_csidl_name_not_env_var(csidl_name) + if result is not None: + return result env_var_name = { "CSIDL_APPDATA": "APPDATA", @@ -111,28 +144,54 @@ def get_win_folder_from_env_vars(csidl_name: str) -> str: "CSIDL_LOCAL_APPDATA": "LOCALAPPDATA", }.get(csidl_name) if env_var_name is None: - raise ValueError(f"Unknown CSIDL name: {csidl_name}") + msg = f"Unknown CSIDL name: {csidl_name}" + raise ValueError(msg) result = os.environ.get(env_var_name) if result is None: - raise ValueError(f"Unset environment variable: {env_var_name}") + msg = f"Unset environment variable: {env_var_name}" + raise ValueError(msg) return result +def get_win_folder_if_csidl_name_not_env_var(csidl_name: str) -> str | None: + """Get folder for a CSIDL name that does not exist as an environment variable.""" + if csidl_name == "CSIDL_PERSONAL": + return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Documents") # noqa: PTH118 + + if csidl_name == "CSIDL_DOWNLOADS": + return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Downloads") # noqa: PTH118 + + if csidl_name == "CSIDL_MYPICTURES": + return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Pictures") # noqa: PTH118 + + if csidl_name == "CSIDL_MYVIDEO": + return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Videos") # noqa: PTH118 + + if csidl_name == "CSIDL_MYMUSIC": + return os.path.join(os.path.normpath(os.environ["USERPROFILE"]), "Music") # noqa: PTH118 + return None + + def get_win_folder_from_registry(csidl_name: str) -> str: - """Get folder from the registry. + """ + Get folder from the registry. - This is a fallback technique at best. I'm not sure if using the - registry for this guarantees us the correct answer for all CSIDL_* - names. + This is a fallback technique at best. I'm not sure if using the registry for these guarantees us the correct answer + for all CSIDL_* names. """ shell_folder_name = { "CSIDL_APPDATA": "AppData", "CSIDL_COMMON_APPDATA": "Common AppData", "CSIDL_LOCAL_APPDATA": "Local AppData", "CSIDL_PERSONAL": "Personal", + "CSIDL_DOWNLOADS": "{374DE290-123F-4565-9164-39C4925E467B}", + "CSIDL_MYPICTURES": "My Pictures", + "CSIDL_MYVIDEO": "My Video", + "CSIDL_MYMUSIC": "My Music", }.get(csidl_name) if shell_folder_name is None: - raise ValueError(f"Unknown CSIDL name: {csidl_name}") + msg = f"Unknown CSIDL name: {csidl_name}" + raise ValueError(msg) if sys.platform != "win32": # only needed for mypy type checker to know that this code runs only on Windows raise NotImplementedError import winreg @@ -144,25 +203,37 @@ def get_win_folder_from_registry(csidl_name: str) -> str: def get_win_folder_via_ctypes(csidl_name: str) -> str: """Get folder with ctypes.""" + # There is no 'CSIDL_DOWNLOADS'. + # Use 'CSIDL_PROFILE' (40) and append the default folder 'Downloads' instead. + # https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid + csidl_const = { "CSIDL_APPDATA": 26, "CSIDL_COMMON_APPDATA": 35, "CSIDL_LOCAL_APPDATA": 28, "CSIDL_PERSONAL": 5, + "CSIDL_MYPICTURES": 39, + "CSIDL_MYVIDEO": 14, + "CSIDL_MYMUSIC": 13, + "CSIDL_DOWNLOADS": 40, }.get(csidl_name) if csidl_const is None: - raise ValueError(f"Unknown CSIDL name: {csidl_name}") + msg = f"Unknown CSIDL name: {csidl_name}" + raise ValueError(msg) buf = ctypes.create_unicode_buffer(1024) windll = getattr(ctypes, "windll") # noqa: B009 # using getattr to avoid false positive with mypy type checker windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf) # Downgrade to short path name if it has highbit chars. - if any(ord(c) > 255 for c in buf): + if any(ord(c) > 255 for c in buf): # noqa: PLR2004 buf2 = ctypes.create_unicode_buffer(1024) if windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024): buf = buf2 + if csidl_name == "CSIDL_DOWNLOADS": + return os.path.join(buf.value, "Downloads") # noqa: PTH118 + return buf.value diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py index 7185e537..39c84aae 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/__init__.py @@ -21,12 +21,12 @@ .. _Pygments master branch: https://github.com/pygments/pygments/archive/master.zip#egg=Pygments-dev - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ from io import StringIO, BytesIO -__version__ = '2.13.0' +__version__ = '2.15.1' __docformat__ = 'restructuredtext' __all__ = ['lex', 'format', 'highlight'] @@ -34,7 +34,9 @@ __all__ = ['lex', 'format', 'highlight'] def lex(code, lexer): """ - Lex ``code`` with ``lexer`` and return an iterable of tokens. + Lex `code` with the `lexer` (must be a `Lexer` instance) + and return an iterable of tokens. Currently, this only calls + `lexer.get_tokens()`. """ try: return lexer.get_tokens(code) @@ -49,11 +51,12 @@ def lex(code, lexer): def format(tokens, formatter, outfile=None): # pylint: disable=redefined-builtin """ - Format a tokenlist ``tokens`` with the formatter ``formatter``. + Format ``tokens`` (an iterable of tokens) with the formatter ``formatter`` + (a `Formatter` instance). - If ``outfile`` is given and a valid file object (an object - with a ``write`` method), the result will be written to it, otherwise - it is returned as a string. + If ``outfile`` is given and a valid file object (an object with a + ``write`` method), the result will be written to it, otherwise it + is returned as a string. """ try: if not outfile: @@ -73,10 +76,7 @@ def format(tokens, formatter, outfile=None): # pylint: disable=redefined-builti def highlight(code, lexer, formatter, outfile=None): """ - Lex ``code`` with ``lexer`` and format it with the formatter ``formatter``. - - If ``outfile`` is given and a valid file object (an object - with a ``write`` method), the result will be written to it, otherwise - it is returned as a string. + This is the most high-level highlighting function. It combines `lex` and + `format` in one function. """ return format(lex(code, lexer), formatter, outfile) diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py index 90cafd93..2f7f8cba 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/__main__.py @@ -4,7 +4,7 @@ Main entry point for ``python -m pygments``. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py b/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py index de73b06b..eec1775b 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/cmdline.py @@ -4,7 +4,7 @@ Command line interface. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -185,7 +185,7 @@ def main_inner(parser, argns): return 0 if argns.V: - print('Pygments version %s, (c) 2006-2022 by Georg Brandl, Matthäus ' + print('Pygments version %s, (c) 2006-2023 by Georg Brandl, Matthäus ' 'Chajdas and contributors.' % __version__) return 0 diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/console.py b/.venv/Lib/site-packages/pip/_vendor/pygments/console.py index 2ada68e0..deb4937f 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/console.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/console.py @@ -4,7 +4,7 @@ Format colored console output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py b/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py index e5c96649..dafa08d1 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/filter.py @@ -4,7 +4,7 @@ Module that implements the default filter. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py index c302a6c0..5aa9ecbb 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/filters/__init__.py @@ -5,7 +5,7 @@ Module containing filter lookup functions and default filters. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatter.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatter.py index a2349ef8..3ca4892f 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatter.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatter.py @@ -4,7 +4,7 @@ Base formatter class. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -26,7 +26,21 @@ class Formatter: """ Converts a token stream to text. - Options accepted: + Formatters should have attributes to help selecting them. These + are similar to the corresponding :class:`~pygments.lexer.Lexer` + attributes. + + .. autoattribute:: name + :no-value: + + .. autoattribute:: aliases + :no-value: + + .. autoattribute:: filenames + :no-value: + + You can pass options as keyword arguments to the constructor. + All formatters accept these basic options: ``style`` The style to use, can be a string or a Style subclass @@ -47,15 +61,19 @@ class Formatter: support (default: None). ``outencoding`` Overrides ``encoding`` if given. + """ - #: Name of the formatter + #: Full name for the formatter, in human-readable form. name = None - #: Shortcuts for the formatter + #: A list of short, unique identifiers that can be used to lookup + #: the formatter from a list, e.g. using :func:`.get_formatter_by_name()`. aliases = [] - #: fn match rules + #: A list of fnmatch patterns that match filenames for which this + #: formatter can produce output. The patterns in this list should be unique + #: among all formatters. filenames = [] #: If True, this formatter outputs Unicode strings when no encoding @@ -63,6 +81,11 @@ class Formatter: unicodeoutput = True def __init__(self, **options): + """ + As with lexers, this constructor takes arbitrary optional arguments, + and if you override it, you should first process your own options, then + call the base class implementation. + """ self.style = _lookup_style(options.get('style', 'default')) self.full = get_bool_opt(options, 'full', False) self.title = options.get('title', '') @@ -75,18 +98,25 @@ class Formatter: def get_style_defs(self, arg=''): """ - Return the style definitions for the current style as a string. + This method must return statements or declarations suitable to define + the current style for subsequent highlighted text (e.g. CSS classes + in the `HTMLFormatter`). - ``arg`` is an additional argument whose meaning depends on the - formatter used. Note that ``arg`` can also be a list or tuple - for some formatters like the html formatter. + The optional argument `arg` can be used to modify the generation and + is formatter dependent (it is standardized because it can be given on + the command line). + + This method is called by the ``-S`` :doc:`command-line option `, + the `arg` is then given by the ``-a`` option. """ return '' def format(self, tokensource, outfile): """ - Format ``tokensource``, an iterable of ``(tokentype, tokenstring)`` - tuples and write it into ``outfile``. + This method must format the tokens from the `tokensource` iterable and + write the formatted version to the file object `outfile`. + + Formatter options can control how exactly the tokens are converted. """ if self.encoding: # wrap the outfile in a StreamWriter diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py index 43c4c89a..39db8426 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/__init__.py @@ -4,14 +4,14 @@ Pygments formatters. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re import sys import types -from fnmatch import fnmatch +import fnmatch from os.path import basename from pip._vendor.pygments.formatters._mapping import FORMATTERS @@ -22,6 +22,16 @@ __all__ = ['get_formatter_by_name', 'get_formatter_for_filename', 'get_all_formatters', 'load_formatter_from_file'] + list(FORMATTERS) _formatter_cache = {} # classes by name +_pattern_cache = {} + + +def _fn_matches(fn, glob): + """Return whether the supplied file name fn matches pattern filename.""" + if glob not in _pattern_cache: + pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) + return pattern.match(fn) + return _pattern_cache[glob].match(fn) + def _load_formatters(module_name): """Load a formatter (and all others in the module too).""" @@ -58,9 +68,12 @@ def find_formatter_class(alias): def get_formatter_by_name(_alias, **options): - """Lookup and instantiate a formatter by alias. + """ + Return an instance of a :class:`.Formatter` subclass that has `alias` in its + aliases list. The formatter is given the `options` at its instantiation. - Raises ClassNotFound if not found. + Will raise :exc:`pygments.util.ClassNotFound` if no formatter with that + alias is found. """ cls = find_formatter_class(_alias) if cls is None: @@ -68,19 +81,18 @@ def get_formatter_by_name(_alias, **options): return cls(**options) -def load_formatter_from_file(filename, formattername="CustomFormatter", - **options): - """Load a formatter from a file. - - This method expects a file located relative to the current working - directory, which contains a class named CustomFormatter. By default, - it expects the Formatter to be named CustomFormatter; you can specify - your own class name as the second argument to this function. +def load_formatter_from_file(filename, formattername="CustomFormatter", **options): + """ + Return a `Formatter` subclass instance loaded from the provided file, relative + to the current directory. - Users should be very careful with the input, because this method - is equivalent to running eval on the input file. + The file is expected to contain a Formatter class named ``formattername`` + (by default, CustomFormatter). Users should be very careful with the input, because + this method is equivalent to running ``eval()`` on the input file. The formatter is + given the `options` at its instantiation. - Raises ClassNotFound if there are any problems importing the Formatter. + :exc:`pygments.util.ClassNotFound` is raised if there are any errors loading + the formatter. .. versionadded:: 2.2 """ @@ -105,20 +117,23 @@ def load_formatter_from_file(filename, formattername="CustomFormatter", def get_formatter_for_filename(fn, **options): - """Lookup and instantiate a formatter by filename pattern. + """ + Return a :class:`.Formatter` subclass instance that has a filename pattern + matching `fn`. The formatter is given the `options` at its instantiation. - Raises ClassNotFound if not found. + Will raise :exc:`pygments.util.ClassNotFound` if no formatter for that filename + is found. """ fn = basename(fn) for modname, name, _, filenames, _ in FORMATTERS.values(): for filename in filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): if name not in _formatter_cache: _load_formatters(modname) return _formatter_cache[name](**options) for cls in find_plugin_formatters(): for filename in cls.filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): return cls(**options) raise ClassNotFound("no formatter found for file name %r" % fn) diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py index 6e34f960..72ca8404 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/_mapping.py @@ -1,12 +1,12 @@ # Automatically generated by scripts/gen_mapfiles.py. -# DO NOT EDIT BY HAND; run `make mapfiles` instead. +# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead. FORMATTERS = { 'BBCodeFormatter': ('pygments.formatters.bbcode', 'BBCode', ('bbcode', 'bb'), (), 'Format tokens with BBcodes. These formatting codes are used by many bulletin boards, so you can highlight your sourcecode with pygments before posting it there.'), 'BmpImageFormatter': ('pygments.formatters.img', 'img_bmp', ('bmp', 'bitmap'), ('*.bmp',), 'Create a bitmap image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), 'GifImageFormatter': ('pygments.formatters.img', 'img_gif', ('gif',), ('*.gif',), 'Create a GIF image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), 'GroffFormatter': ('pygments.formatters.groff', 'groff', ('groff', 'troff', 'roff'), (), 'Format tokens with groff escapes to change their color and font style.'), - 'HtmlFormatter': ('pygments.formatters.html', 'HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ```` tags within a ``
`` tag, wrapped in a ``
`` tag. The ``
``'s CSS class can be set by the `cssclass` option."), + 'HtmlFormatter': ('pygments.formatters.html', 'HTML', ('html',), ('*.html', '*.htm'), "Format tokens as HTML 4 ```` tags. By default, the content is enclosed in a ``
`` tag, itself wrapped in a ``
`` tag (but see the `nowrap` option). The ``
``'s CSS class can be set by the `cssclass` option."), 'IRCFormatter': ('pygments.formatters.irc', 'IRC', ('irc', 'IRC'), (), 'Format tokens with IRC color sequences'), 'ImageFormatter': ('pygments.formatters.img', 'img', ('img', 'IMG', 'png'), ('*.png',), 'Create a PNG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), 'JpgImageFormatter': ('pygments.formatters.img', 'img_jpg', ('jpg', 'jpeg'), ('*.jpg',), 'Create a JPEG image from source code. This uses the Python Imaging Library to generate a pixmap from the source code.'), diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py index 2be2b4e3..c4db8f4e 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/bbcode.py @@ -4,7 +4,7 @@ BBcode formatter. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py index f3dcbce9..30a528e6 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/groff.py @@ -4,7 +4,7 @@ Formatter for groff output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -84,7 +84,7 @@ class GroffFormatter(Formatter): if ndef['color'] is not None: colors.add(ndef['color']) - for color in colors: + for color in sorted(colors): outfile.write('.defcolor ' + color + ' rgb #' + color + '\n') diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py index d5cda4c4..931d7c3f 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/html.py @@ -4,7 +4,7 @@ Formatter for HTML output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -62,7 +62,7 @@ def _get_ttype_class(ttype): CSSFILE_TEMPLATE = '''\ /* generated by Pygments -Copyright 2006-2022 by the Pygments team. +Copyright 2006-2023 by the Pygments team. Licensed under the BSD license, see LICENSE for details. */ %(styledefs)s @@ -73,7 +73,7 @@ DOC_HEADER = '''\ "http://www.w3.org/TR/html4/strict.dtd"> @@ -112,9 +112,9 @@ DOC_FOOTER = '''\ class HtmlFormatter(Formatter): r""" - Format tokens as HTML 4 ```` tags within a ``
`` tag, wrapped
-    in a ``
`` tag. The ``
``'s CSS class can be set by the `cssclass` - option. + Format tokens as HTML 4 ```` tags. By default, the content is enclosed + in a ``
`` tag, itself wrapped in a ``
`` tag (but see the `nowrap` option). + The ``
``'s CSS class can be set by the `cssclass` option. If the `linenos` option is set to ``"table"``, the ``
`` is
     additionally wrapped inside a ```` which has one row and two
@@ -140,8 +140,6 @@ class HtmlFormatter(Formatter):
 
     (whitespace added to improve clarity).
 
-    Wrapping can be disabled using the `nowrap` option.
-
     A list of lines can be specified using the `hl_lines` option to make these
     lines highlighted (as of Pygments 0.11).
 
@@ -187,8 +185,8 @@ class HtmlFormatter(Formatter):
     Additional options accepted:
 
     `nowrap`
-        If set to ``True``, don't wrap the tokens at all, not even inside a ``
``
-        tag. This disables most other options (default: ``False``).
+        If set to ``True``, don't add a ``
`` and a ``
`` tag + around the tokens. This disables most other options (default: ``False``). `full` Tells the formatter to output a "full" document, i.e. a complete @@ -635,7 +633,7 @@ class HtmlFormatter(Formatter): # write CSS file only if noclobber_cssfile isn't given as an option. try: if not os.path.exists(cssfilename) or not self.noclobber_cssfile: - with open(cssfilename, "w") as cf: + with open(cssfilename, "w", encoding="utf-8") as cf: cf.write(CSSFILE_TEMPLATE % {'styledefs': self.get_style_defs('body')}) except OSError as err: @@ -721,7 +719,7 @@ class HtmlFormatter(Formatter): yield 0, dummyoutfile.getvalue() yield 0, '
' yield 0, '
' - + def _wrap_inlinelinenos(self, inner): # need a list of lines since we need the width of a single number :( @@ -878,10 +876,12 @@ class HtmlFormatter(Formatter): # for all but the last line for part in parts[:-1]: if line: - if lspan != cspan: + # Also check for part being non-empty, so we avoid creating + # empty tags + if lspan != cspan and part: line.extend(((lspan and ''), cspan, part, (cspan and ''), lsep)) - else: # both are the same + else: # both are the same, or the current part was empty line.extend((part, (lspan and ''), lsep)) yield 1, ''.join(line) line = [] @@ -944,9 +944,9 @@ class HtmlFormatter(Formatter): output = source if self.wrapcode: output = self._wrap_code(output) - + output = self._wrap_pre(output) - + return output def format_unencoded(self, tokensource, outfile): diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py index 0f36a32b..a338c158 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/img.py @@ -4,7 +4,7 @@ Formatter for Pixmap output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py index 3f6d52de..2144d439 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/irc.py @@ -4,7 +4,7 @@ Formatter for IRC output - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -128,38 +128,12 @@ class IRCFormatter(Formatter): self._lineno = 0 def _write_lineno(self, outfile): - self._lineno += 1 - outfile.write("\n%04d: " % self._lineno) - - def _format_unencoded_with_lineno(self, tokensource, outfile): - self._write_lineno(outfile) - - for ttype, value in tokensource: - if value.endswith("\n"): - self._write_lineno(outfile) - value = value[:-1] - color = self.colorscheme.get(ttype) - while color is None: - ttype = ttype.parent - color = self.colorscheme.get(ttype) - if color: - color = color[self.darkbg] - spl = value.split('\n') - for line in spl[:-1]: - self._write_lineno(outfile) - if line: - outfile.write(ircformat(color, line[:-1])) - if spl[-1]: - outfile.write(ircformat(color, spl[-1])) - else: - outfile.write(value) - - outfile.write("\n") + if self.linenos: + self._lineno += 1 + outfile.write("%04d: " % self._lineno) def format_unencoded(self, tokensource, outfile): - if self.linenos: - self._format_unencoded_with_lineno(tokensource, outfile) - return + self._write_lineno(outfile) for ttype, value in tokensource: color = self.colorscheme.get(ttype) @@ -173,6 +147,7 @@ class IRCFormatter(Formatter): if line: outfile.write(ircformat(color, line)) outfile.write('\n') + self._write_lineno(outfile) if spl[-1]: outfile.write(ircformat(color, spl[-1])) else: diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py index 4a7375a5..ca539b40 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/latex.py @@ -4,7 +4,7 @@ Formatter for LaTeX fancyvrb output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py index 1e39cd42..990ead48 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/other.py @@ -4,7 +4,7 @@ Other formatters: NullFormatter, RawTokenFormatter. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py index bd00866b..6bb325d0 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/pangomarkup.py @@ -4,7 +4,7 @@ Formatter for Pango markup output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py index 4114d168..125189c6 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/rtf.py @@ -4,7 +4,7 @@ A formatter that generates RTF files. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py index 075150a4..a8727ed8 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/svg.py @@ -4,7 +4,7 @@ Formatter for SVG output. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py index e0bda16a..abb87708 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal.py @@ -4,7 +4,7 @@ Formatter for terminal output with ANSI sequences. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py index 201b3c32..0cfe5d16 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/formatters/terminal256.py @@ -10,7 +10,7 @@ Formatter version 1. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/lexer.py b/.venv/Lib/site-packages/pip/_vendor/pygments/lexer.py index ec7f4de3..eb2c1b46 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/lexer.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/lexer.py @@ -4,7 +4,7 @@ Base lexer classes. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -14,15 +14,16 @@ import time from pip._vendor.pygments.filter import apply_filters, Filter from pip._vendor.pygments.filters import get_filter_by_name -from pip._vendor.pygments.token import Error, Text, Other, _TokenType +from pip._vendor.pygments.token import Error, Text, Other, Whitespace, _TokenType from pip._vendor.pygments.util import get_bool_opt, get_int_opt, get_list_opt, \ make_analysator, Future, guess_decode from pip._vendor.pygments.regexopt import regex_opt __all__ = ['Lexer', 'RegexLexer', 'ExtendedRegexLexer', 'DelegatingLexer', 'LexerContext', 'include', 'inherit', 'bygroups', 'using', 'this', - 'default', 'words'] + 'default', 'words', 'line_re'] +line_re = re.compile('.*?\n') _encoding_map = [(b'\xef\xbb\xbf', 'utf-8'), (b'\xff\xfe\0\0', 'utf-32'), @@ -49,7 +50,31 @@ class Lexer(metaclass=LexerMeta): """ Lexer for a specific language. - Basic options recognized: + See also :doc:`lexerdevelopment`, a high-level guide to writing + lexers. + + Lexer classes have attributes used for choosing the most appropriate + lexer based on various criteria. + + .. autoattribute:: name + :no-value: + .. autoattribute:: aliases + :no-value: + .. autoattribute:: filenames + :no-value: + .. autoattribute:: alias_filenames + .. autoattribute:: mimetypes + :no-value: + .. autoattribute:: priority + + Lexers included in Pygments should have an additional attribute: + + .. autoattribute:: url + :no-value: + + You can pass options to the constructor. The basic options recognized + by all lexers and processed by the base `Lexer` class are: + ``stripnl`` Strip leading and trailing newlines from the input (default: True). ``stripall`` @@ -73,28 +98,55 @@ class Lexer(metaclass=LexerMeta): Overrides the ``encoding`` if given. """ - #: Name of the lexer + #: Full name of the lexer, in human-readable form name = None - #: URL of the language specification/definition - url = None - - #: Shortcuts for the lexer + #: A list of short, unique identifiers that can be used to look + #: up the lexer from a list, e.g., using `get_lexer_by_name()`. aliases = [] - #: File name globs + #: A list of `fnmatch` patterns that match filenames which contain + #: content for this lexer. The patterns in this list should be unique among + #: all lexers. filenames = [] - #: Secondary file name globs + #: A list of `fnmatch` patterns that match filenames which may or may not + #: contain content for this lexer. This list is used by the + #: :func:`.guess_lexer_for_filename()` function, to determine which lexers + #: are then included in guessing the correct one. That means that + #: e.g. every lexer for HTML and a template language should include + #: ``\*.html`` in this list. alias_filenames = [] - #: MIME types + #: A list of MIME types for content that can be lexed with this lexer. mimetypes = [] #: Priority, should multiple lexers match and no content is provided priority = 0 + #: URL of the language specification/definition. Used in the Pygments + #: documentation. + url = None + def __init__(self, **options): + """ + This constructor takes arbitrary options as keyword arguments. + Every subclass must first process its own options and then call + the `Lexer` constructor, since it processes the basic + options like `stripnl`. + + An example looks like this: + + .. sourcecode:: python + + def __init__(self, **options): + self.compress = options.get('compress', '') + Lexer.__init__(self, **options) + + As these options must all be specifiable as strings (due to the + command line usage), there are various utility functions + available to help with that, see `Utilities`_. + """ self.options = options self.stripnl = get_bool_opt(options, 'stripnl', True) self.stripall = get_bool_opt(options, 'stripall', False) @@ -123,10 +175,13 @@ class Lexer(metaclass=LexerMeta): def analyse_text(text): """ - Has to return a float between ``0`` and ``1`` that indicates - if a lexer wants to highlight this text. Used by ``guess_lexer``. - If this method returns ``0`` it won't highlight it in any case, if - it returns ``1`` highlighting with this lexer is guaranteed. + A static method which is called for lexer guessing. + + It should analyse the text and return a float in the range + from ``0.0`` to ``1.0``. If it returns ``0.0``, the lexer + will not be selected as the most probable one, if it returns + ``1.0``, it will be selected immediately. This is used by + `guess_lexer`. The `LexerMeta` metaclass automatically wraps this function so that it works like a static method (no ``self`` or ``cls`` @@ -137,12 +192,17 @@ class Lexer(metaclass=LexerMeta): def get_tokens(self, text, unfiltered=False): """ - Return an iterable of (tokentype, value) pairs generated from - `text`. If `unfiltered` is set to `True`, the filtering mechanism - is bypassed even if filters are defined. + This method is the basic interface of a lexer. It is called by + the `highlight()` function. It must process the text and return an + iterable of ``(tokentype, value)`` pairs from `text`. + + Normally, you don't need to override this method. The default + implementation processes the options recognized by all lexers + (`stripnl`, `stripall` and so on), and then yields all tokens + from `get_tokens_unprocessed()`, with the ``index`` dropped. - Also preprocess the text, i.e. expand tabs and strip it if - wanted and applies registered filters. + If `unfiltered` is set to `True`, the filtering mechanism is + bypassed even if filters are defined. """ if not isinstance(text, str): if self.encoding == 'guess': @@ -196,11 +256,12 @@ class Lexer(metaclass=LexerMeta): def get_tokens_unprocessed(self, text): """ - Return an iterable of (index, tokentype, value) pairs where "index" - is the starting position of the token within the input text. + This method should process the text and return an iterable of + ``(index, tokentype, value)`` tuples where ``index`` is the starting + position of the token within the input text. - In subclasses, implement this method as a generator to - maximize effectiveness. + It must be overridden by subclasses. It is recommended to + implement it as a generator to maximize effectiveness. """ raise NotImplementedError @@ -670,7 +731,7 @@ class RegexLexer(Lexer, metaclass=RegexLexerMeta): # at EOL, reset state to "root" statestack = ['root'] statetokens = tokendefs['root'] - yield pos, Text, '\n' + yield pos, Whitespace, '\n' pos += 1 continue yield pos, Error, text[pos] diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py index ed69f24e..d97c3e39 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/__init__.py @@ -4,14 +4,14 @@ Pygments lexers. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re import sys import types -from fnmatch import fnmatch +import fnmatch from os.path import basename from pip._vendor.pygments.lexers._mapping import LEXERS @@ -28,6 +28,16 @@ __all__ = ['get_lexer_by_name', 'get_lexer_for_filename', 'find_lexer_class', 'guess_lexer', 'load_lexer_from_file'] + list(LEXERS) + list(COMPAT) _lexer_cache = {} +_pattern_cache = {} + + +def _fn_matches(fn, glob): + """Return whether the supplied file name fn matches pattern filename.""" + if glob not in _pattern_cache: + pattern = _pattern_cache[glob] = re.compile(fnmatch.translate(glob)) + return pattern.match(fn) + return _pattern_cache[glob].match(fn) + def _load_lexers(module_name): """Load a lexer (and all others in the module too).""" @@ -52,9 +62,9 @@ def get_all_lexers(plugins=True): def find_lexer_class(name): - """Lookup a lexer class by name. - - Return None if not found. + """ + Return the `Lexer` subclass that with the *name* attribute as given by + the *name* argument. """ if name in _lexer_cache: return _lexer_cache[name] @@ -70,10 +80,15 @@ def find_lexer_class(name): def find_lexer_class_by_name(_alias): - """Lookup a lexer class by alias. + """ + Return the `Lexer` subclass that has `alias` in its aliases list, without + instantiating it. Like `get_lexer_by_name`, but does not instantiate the class. + Will raise :exc:`pygments.util.ClassNotFound` if no lexer with that alias is + found. + .. versionadded:: 2.2 """ if not _alias: @@ -92,9 +107,13 @@ def find_lexer_class_by_name(_alias): def get_lexer_by_name(_alias, **options): - """Get a lexer by an alias. + """ + Return an instance of a `Lexer` subclass that has `alias` in its + aliases list. The lexer is given the `options` at its + instantiation. - Raises ClassNotFound if not found. + Will raise :exc:`pygments.util.ClassNotFound` if no lexer with that alias is + found. """ if not _alias: raise ClassNotFound('no lexer for alias %r found' % _alias) @@ -159,13 +178,13 @@ def find_lexer_class_for_filename(_fn, code=None): fn = basename(_fn) for modname, name, _, filenames, _ in LEXERS.values(): for filename in filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): if name not in _lexer_cache: _load_lexers(modname) matches.append((_lexer_cache[name], filename)) for cls in find_plugin_lexers(): for filename in cls.filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): matches.append((cls, filename)) if isinstance(code, bytes): @@ -193,10 +212,15 @@ def find_lexer_class_for_filename(_fn, code=None): def get_lexer_for_filename(_fn, code=None, **options): """Get a lexer for a filename. - If multiple lexers match the filename pattern, use ``analyse_text()`` to - figure out which one is more appropriate. + Return a `Lexer` subclass instance that has a filename pattern + matching `fn`. The lexer is given the `options` at its + instantiation. - Raises ClassNotFound if not found. + Raise :exc:`pygments.util.ClassNotFound` if no lexer for that filename + is found. + + If multiple lexers match the filename pattern, use their ``analyse_text()`` + methods to figure out which one is more appropriate. """ res = find_lexer_class_for_filename(_fn, code) if not res: @@ -205,9 +229,12 @@ def get_lexer_for_filename(_fn, code=None, **options): def get_lexer_for_mimetype(_mime, **options): - """Get a lexer for a mimetype. + """ + Return a `Lexer` subclass instance that has `mime` in its mimetype + list. The lexer is given the `options` at its instantiation. - Raises ClassNotFound if not found. + Will raise :exc:`pygments.util.ClassNotFound` if not lexer for that mimetype + is found. """ for modname, name, _, _, mimetypes in LEXERS.values(): if _mime in mimetypes: @@ -233,30 +260,22 @@ def _iter_lexerclasses(plugins=True): def guess_lexer_for_filename(_fn, _text, **options): """ - Lookup all lexers that handle those filenames primary (``filenames``) - or secondary (``alias_filenames``). Then run a text analysis for those - lexers and choose the best result. - - usage:: - - >>> from pygments.lexers import guess_lexer_for_filename - >>> guess_lexer_for_filename('hello.html', '<%= @foo %>') - - >>> guess_lexer_for_filename('hello.html', '

{{ title|e }}

') - - >>> guess_lexer_for_filename('style.css', 'a { color: }') - + As :func:`guess_lexer()`, but only lexers which have a pattern in `filenames` + or `alias_filenames` that matches `filename` are taken into consideration. + + :exc:`pygments.util.ClassNotFound` is raised if no lexer thinks it can + handle the content. """ fn = basename(_fn) primary = {} matching_lexers = set() for lexer in _iter_lexerclasses(): for filename in lexer.filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): matching_lexers.add(lexer) primary[lexer] = True for filename in lexer.alias_filenames: - if fnmatch(fn, filename): + if _fn_matches(fn, filename): matching_lexers.add(lexer) primary[lexer] = False if not matching_lexers: @@ -283,7 +302,15 @@ def guess_lexer_for_filename(_fn, _text, **options): def guess_lexer(_text, **options): - """Guess a lexer by strong distinctions in the text (eg, shebang).""" + """ + Return a `Lexer` subclass instance that's guessed from the text in + `text`. For that, the :meth:`.analyse_text()` method of every known lexer + class is called with the text as argument, and the lexer which returned the + highest value will be instantiated and returned. + + :exc:`pygments.util.ClassNotFound` is raised if no lexer thinks it can + handle the content. + """ if not isinstance(_text, str): inencoding = options.get('inencoding', options.get('encoding')) diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py index 40dcaa3c..de6a0153 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/_mapping.py @@ -1,5 +1,5 @@ # Automatically generated by scripts/gen_mapfiles.py. -# DO NOT EDIT BY HAND; run `make mapfiles` instead. +# DO NOT EDIT BY HAND; run `tox -e mapfiles` instead. LEXERS = { 'ABAPLexer': ('pip._vendor.pygments.lexers.business', 'ABAP', ('abap',), ('*.abap', '*.ABAP'), ('text/x-abap',)), @@ -30,6 +30,7 @@ LEXERS = { 'AppleScriptLexer': ('pip._vendor.pygments.lexers.scripting', 'AppleScript', ('applescript',), ('*.applescript',), ()), 'ArduinoLexer': ('pip._vendor.pygments.lexers.c_like', 'Arduino', ('arduino',), ('*.ino',), ('text/x-arduino',)), 'ArrowLexer': ('pip._vendor.pygments.lexers.arrow', 'Arrow', ('arrow',), ('*.arw',), ()), + 'ArturoLexer': ('pip._vendor.pygments.lexers.arturo', 'Arturo', ('arturo', 'art'), ('*.art',), ()), 'AscLexer': ('pip._vendor.pygments.lexers.asc', 'ASCII armored', ('asc', 'pem'), ('*.asc', '*.pem', 'id_dsa', 'id_ecdsa', 'id_ecdsa_sk', 'id_ed25519', 'id_ed25519_sk', 'id_rsa'), ('application/pgp-keys', 'application/pgp-encrypted', 'application/pgp-signature')), 'AspectJLexer': ('pip._vendor.pygments.lexers.jvm', 'AspectJ', ('aspectj',), ('*.aj',), ('text/x-aspectj',)), 'AsymptoteLexer': ('pip._vendor.pygments.lexers.graphics', 'Asymptote', ('asymptote', 'asy'), ('*.asy',), ('text/x-asymptote',)), @@ -70,6 +71,7 @@ LEXERS = { 'CadlLexer': ('pip._vendor.pygments.lexers.archetype', 'cADL', ('cadl',), ('*.cadl',), ()), 'CapDLLexer': ('pip._vendor.pygments.lexers.esoteric', 'CapDL', ('capdl',), ('*.cdl',), ()), 'CapnProtoLexer': ('pip._vendor.pygments.lexers.capnproto', "Cap'n Proto", ('capnp',), ('*.capnp',), ()), + 'CarbonLexer': ('pip._vendor.pygments.lexers.carbon', 'Carbon', ('carbon',), ('*.carbon',), ('text/x-carbon',)), 'CbmBasicV2Lexer': ('pip._vendor.pygments.lexers.basic', 'CBM BASIC V2', ('cbmbas',), ('*.bas',), ()), 'CddlLexer': ('pip._vendor.pygments.lexers.cddl', 'CDDL', ('cddl',), ('*.cddl',), ('text/x-cddl',)), 'CeylonLexer': ('pip._vendor.pygments.lexers.jvm', 'Ceylon', ('ceylon',), ('*.ceylon',), ('text/x-ceylon',)), @@ -120,6 +122,7 @@ LEXERS = { 'DarcsPatchLexer': ('pip._vendor.pygments.lexers.diff', 'Darcs Patch', ('dpatch',), ('*.dpatch', '*.darcspatch'), ()), 'DartLexer': ('pip._vendor.pygments.lexers.javascript', 'Dart', ('dart',), ('*.dart',), ('text/x-dart',)), 'Dasm16Lexer': ('pip._vendor.pygments.lexers.asm', 'DASM16', ('dasm16',), ('*.dasm16', '*.dasm'), ('text/x-dasm16',)), + 'DaxLexer': ('pip._vendor.pygments.lexers.dax', 'Dax', ('dax',), ('*.dax',), ()), 'DebianControlLexer': ('pip._vendor.pygments.lexers.installers', 'Debian Control file', ('debcontrol', 'control'), ('control',), ()), 'DelphiLexer': ('pip._vendor.pygments.lexers.pascal', 'Delphi', ('delphi', 'pas', 'pascal', 'objectpascal'), ('*.pas', '*.dpr'), ('text/x-pascal',)), 'DevicetreeLexer': ('pip._vendor.pygments.lexers.devicetree', 'Devicetree', ('devicetree', 'dts'), ('*.dts', '*.dtsi'), ('text/x-c',)), @@ -152,13 +155,14 @@ LEXERS = { 'EvoqueXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Evoque', ('xml+evoque',), ('*.xml',), ('application/xml+evoque',)), 'ExeclineLexer': ('pip._vendor.pygments.lexers.shell', 'execline', ('execline',), ('*.exec',), ()), 'EzhilLexer': ('pip._vendor.pygments.lexers.ezhil', 'Ezhil', ('ezhil',), ('*.n',), ('text/x-ezhil',)), - 'FSharpLexer': ('pip._vendor.pygments.lexers.dotnet', 'F#', ('fsharp', 'f#'), ('*.fs', '*.fsi'), ('text/x-fsharp',)), + 'FSharpLexer': ('pip._vendor.pygments.lexers.dotnet', 'F#', ('fsharp', 'f#'), ('*.fs', '*.fsi', '*.fsx'), ('text/x-fsharp',)), 'FStarLexer': ('pip._vendor.pygments.lexers.ml', 'FStar', ('fstar',), ('*.fst', '*.fsti'), ('text/x-fstar',)), 'FactorLexer': ('pip._vendor.pygments.lexers.factor', 'Factor', ('factor',), ('*.factor',), ('text/x-factor',)), 'FancyLexer': ('pip._vendor.pygments.lexers.ruby', 'Fancy', ('fancy', 'fy'), ('*.fy', '*.fancypack'), ('text/x-fancysrc',)), 'FantomLexer': ('pip._vendor.pygments.lexers.fantom', 'Fantom', ('fan',), ('*.fan',), ('application/x-fantom',)), 'FelixLexer': ('pip._vendor.pygments.lexers.felix', 'Felix', ('felix', 'flx'), ('*.flx', '*.flxh'), ('text/x-felix',)), 'FennelLexer': ('pip._vendor.pygments.lexers.lisp', 'Fennel', ('fennel', 'fnl'), ('*.fnl',), ()), + 'FiftLexer': ('pip._vendor.pygments.lexers.fift', 'Fift', ('fift', 'fif'), ('*.fif',), ()), 'FishShellLexer': ('pip._vendor.pygments.lexers.shell', 'Fish', ('fish', 'fishshell'), ('*.fish', '*.load'), ('application/x-fish',)), 'FlatlineLexer': ('pip._vendor.pygments.lexers.dsls', 'Flatline', ('flatline',), (), ('text/x-flatline',)), 'FloScriptLexer': ('pip._vendor.pygments.lexers.floscript', 'FloScript', ('floscript', 'flo'), ('*.flo',), ()), @@ -167,7 +171,9 @@ LEXERS = { 'FortranLexer': ('pip._vendor.pygments.lexers.fortran', 'Fortran', ('fortran', 'f90'), ('*.f03', '*.f90', '*.F03', '*.F90'), ('text/x-fortran',)), 'FoxProLexer': ('pip._vendor.pygments.lexers.foxpro', 'FoxPro', ('foxpro', 'vfp', 'clipper', 'xbase'), ('*.PRG', '*.prg'), ()), 'FreeFemLexer': ('pip._vendor.pygments.lexers.freefem', 'Freefem', ('freefem',), ('*.edp',), ('text/x-freefem',)), + 'FuncLexer': ('pip._vendor.pygments.lexers.func', 'FunC', ('func', 'fc'), ('*.fc', '*.func'), ()), 'FutharkLexer': ('pip._vendor.pygments.lexers.futhark', 'Futhark', ('futhark',), ('*.fut',), ('text/x-futhark',)), + 'GAPConsoleLexer': ('pip._vendor.pygments.lexers.algebra', 'GAP session', ('gap-console', 'gap-repl'), ('*.tst',), ()), 'GAPLexer': ('pip._vendor.pygments.lexers.algebra', 'GAP', ('gap',), ('*.g', '*.gd', '*.gi', '*.gap'), ()), 'GDScriptLexer': ('pip._vendor.pygments.lexers.gdscript', 'GDScript', ('gdscript', 'gd'), ('*.gd',), ('text/x-gdscript', 'application/x-gdscript')), 'GLShaderLexer': ('pip._vendor.pygments.lexers.graphics', 'GLSL', ('glsl',), ('*.vert', '*.frag', '*.geo'), ('text/x-glslsrc',)), @@ -196,7 +202,7 @@ LEXERS = { 'HaxeLexer': ('pip._vendor.pygments.lexers.haxe', 'Haxe', ('haxe', 'hxsl', 'hx'), ('*.hx', '*.hxsl'), ('text/haxe', 'text/x-haxe', 'text/x-hx')), 'HexdumpLexer': ('pip._vendor.pygments.lexers.hexdump', 'Hexdump', ('hexdump',), (), ()), 'HsailLexer': ('pip._vendor.pygments.lexers.asm', 'HSAIL', ('hsail', 'hsa'), ('*.hsail',), ('text/x-hsail',)), - 'HspecLexer': ('pip._vendor.pygments.lexers.haskell', 'Hspec', ('hspec',), (), ()), + 'HspecLexer': ('pip._vendor.pygments.lexers.haskell', 'Hspec', ('hspec',), ('*Spec.hs',), ()), 'HtmlDjangoLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Django/Jinja', ('html+django', 'html+jinja', 'htmldjango'), ('*.html.j2', '*.htm.j2', '*.xhtml.j2', '*.html.jinja2', '*.htm.jinja2', '*.xhtml.jinja2'), ('text/html+django', 'text/html+jinja')), 'HtmlGenshiLexer': ('pip._vendor.pygments.lexers.templates', 'HTML+Genshi', ('html+genshi', 'html+kid'), (), ('text/html+genshi',)), 'HtmlLexer': ('pip._vendor.pygments.lexers.html', 'HTML', ('html',), ('*.html', '*.htm', '*.xhtml', '*.xslt'), ('text/html', 'application/xhtml+xml')), @@ -236,6 +242,7 @@ LEXERS = { 'JsonBareObjectLexer': ('pip._vendor.pygments.lexers.data', 'JSONBareObject', (), (), ()), 'JsonLdLexer': ('pip._vendor.pygments.lexers.data', 'JSON-LD', ('jsonld', 'json-ld'), ('*.jsonld',), ('application/ld+json',)), 'JsonLexer': ('pip._vendor.pygments.lexers.data', 'JSON', ('json', 'json-object'), ('*.json', 'Pipfile.lock'), ('application/json', 'application/json-object')), + 'JsonnetLexer': ('pip._vendor.pygments.lexers.jsonnet', 'Jsonnet', ('jsonnet',), ('*.jsonnet', '*.libsonnet'), ()), 'JspLexer': ('pip._vendor.pygments.lexers.templates', 'Java Server Page', ('jsp',), ('*.jsp',), ('application/x-jsp',)), 'JuliaConsoleLexer': ('pip._vendor.pygments.lexers.julia', 'Julia console', ('jlcon', 'julia-repl'), (), ()), 'JuliaLexer': ('pip._vendor.pygments.lexers.julia', 'Julia', ('julia', 'jl'), ('*.jl',), ('text/x-julia', 'application/x-julia')), @@ -270,8 +277,10 @@ LEXERS = { 'LogosLexer': ('pip._vendor.pygments.lexers.objective', 'Logos', ('logos',), ('*.x', '*.xi', '*.xm', '*.xmi'), ('text/x-logos',)), 'LogtalkLexer': ('pip._vendor.pygments.lexers.prolog', 'Logtalk', ('logtalk',), ('*.lgt', '*.logtalk'), ('text/x-logtalk',)), 'LuaLexer': ('pip._vendor.pygments.lexers.scripting', 'Lua', ('lua',), ('*.lua', '*.wlua'), ('text/x-lua', 'application/x-lua')), - 'MCFunctionLexer': ('pip._vendor.pygments.lexers.mcfunction', 'MCFunction', ('mcfunction', 'mcf'), ('*.mcfunction',), ('text/mcfunction',)), + 'MCFunctionLexer': ('pip._vendor.pygments.lexers.minecraft', 'MCFunction', ('mcfunction', 'mcf'), ('*.mcfunction',), ('text/mcfunction',)), + 'MCSchemaLexer': ('pip._vendor.pygments.lexers.minecraft', 'MCSchema', ('mcschema',), ('*.mcschema',), ('text/mcschema',)), 'MIMELexer': ('pip._vendor.pygments.lexers.mime', 'MIME', ('mime',), (), ('multipart/mixed', 'multipart/related', 'multipart/alternative')), + 'MIPSLexer': ('pip._vendor.pygments.lexers.mips', 'MIPS', ('mips',), ('*.mips', '*.MIPS'), ()), 'MOOCodeLexer': ('pip._vendor.pygments.lexers.scripting', 'MOOCode', ('moocode', 'moo'), ('*.moo',), ('text/x-moocode',)), 'MSDOSSessionLexer': ('pip._vendor.pygments.lexers.shell', 'MSDOS Session', ('doscon',), (), ()), 'Macaulay2Lexer': ('pip._vendor.pygments.lexers.macaulay2', 'Macaulay2', ('macaulay2',), ('*.m2',), ()), @@ -316,7 +325,7 @@ LEXERS = { 'MyghtyXmlLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Myghty', ('xml+myghty',), (), ('application/xml+myghty',)), 'NCLLexer': ('pip._vendor.pygments.lexers.ncl', 'NCL', ('ncl',), ('*.ncl',), ('text/ncl',)), 'NSISLexer': ('pip._vendor.pygments.lexers.installers', 'NSIS', ('nsis', 'nsi', 'nsh'), ('*.nsi', '*.nsh'), ('text/x-nsis',)), - 'NasmLexer': ('pip._vendor.pygments.lexers.asm', 'NASM', ('nasm',), ('*.asm', '*.ASM'), ('text/x-nasm',)), + 'NasmLexer': ('pip._vendor.pygments.lexers.asm', 'NASM', ('nasm',), ('*.asm', '*.ASM', '*.nasm'), ('text/x-nasm',)), 'NasmObjdumpLexer': ('pip._vendor.pygments.lexers.asm', 'objdump-nasm', ('objdump-nasm',), ('*.objdump-intel',), ('text/x-nasm-objdump',)), 'NemerleLexer': ('pip._vendor.pygments.lexers.dotnet', 'Nemerle', ('nemerle',), ('*.n',), ('text/x-nemerle',)), 'NesCLexer': ('pip._vendor.pygments.lexers.c_like', 'nesC', ('nesc',), ('*.nc',), ('text/x-nescsrc',)), @@ -350,6 +359,7 @@ LEXERS = { 'PegLexer': ('pip._vendor.pygments.lexers.grammar_notation', 'PEG', ('peg',), ('*.peg',), ('text/x-peg',)), 'Perl6Lexer': ('pip._vendor.pygments.lexers.perl', 'Perl6', ('perl6', 'pl6', 'raku'), ('*.pl', '*.pm', '*.nqp', '*.p6', '*.6pl', '*.p6l', '*.pl6', '*.6pm', '*.p6m', '*.pm6', '*.t', '*.raku', '*.rakumod', '*.rakutest', '*.rakudoc'), ('text/x-perl6', 'application/x-perl6')), 'PerlLexer': ('pip._vendor.pygments.lexers.perl', 'Perl', ('perl', 'pl'), ('*.pl', '*.pm', '*.t', '*.perl'), ('text/x-perl', 'application/x-perl')), + 'PhixLexer': ('pip._vendor.pygments.lexers.phix', 'Phix', ('phix',), ('*.exw',), ('text/x-phix',)), 'PhpLexer': ('pip._vendor.pygments.lexers.php', 'PHP', ('php', 'php3', 'php4', 'php5'), ('*.php', '*.php[345]', '*.inc'), ('text/x-php',)), 'PigLexer': ('pip._vendor.pygments.lexers.jvm', 'Pig', ('pig',), ('*.pig',), ('text/x-pig',)), 'PikeLexer': ('pip._vendor.pygments.lexers.c_like', 'Pike', ('pike',), ('*.pike', '*.pmod'), ('text/x-pike',)), @@ -357,8 +367,10 @@ LEXERS = { 'PlPgsqlLexer': ('pip._vendor.pygments.lexers.sql', 'PL/pgSQL', ('plpgsql',), (), ('text/x-plpgsql',)), 'PointlessLexer': ('pip._vendor.pygments.lexers.pointless', 'Pointless', ('pointless',), ('*.ptls',), ()), 'PonyLexer': ('pip._vendor.pygments.lexers.pony', 'Pony', ('pony',), ('*.pony',), ()), + 'PortugolLexer': ('pip._vendor.pygments.lexers.pascal', 'Portugol', ('portugol',), ('*.alg', '*.portugol'), ()), 'PostScriptLexer': ('pip._vendor.pygments.lexers.graphics', 'PostScript', ('postscript', 'postscr'), ('*.ps', '*.eps'), ('application/postscript',)), 'PostgresConsoleLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL console (psql)', ('psql', 'postgresql-console', 'postgres-console'), (), ('text/x-postgresql-psql',)), + 'PostgresExplainLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL EXPLAIN dialect', ('postgres-explain',), ('*.explain',), ('text/x-postgresql-explain',)), 'PostgresLexer': ('pip._vendor.pygments.lexers.sql', 'PostgreSQL SQL dialect', ('postgresql', 'postgres'), (), ('text/x-postgresql',)), 'PovrayLexer': ('pip._vendor.pygments.lexers.graphics', 'POVRay', ('pov',), ('*.pov', '*.inc'), ('text/x-povray',)), 'PowerShellLexer': ('pip._vendor.pygments.lexers.shell', 'PowerShell', ('powershell', 'pwsh', 'posh', 'ps1', 'psm1'), ('*.ps1', '*.psm1'), ('text/x-powershell',)), @@ -376,7 +388,7 @@ LEXERS = { 'Python2Lexer': ('pip._vendor.pygments.lexers.python', 'Python 2.x', ('python2', 'py2'), (), ('text/x-python2', 'application/x-python2')), 'Python2TracebackLexer': ('pip._vendor.pygments.lexers.python', 'Python 2.x Traceback', ('py2tb',), ('*.py2tb',), ('text/x-python2-traceback',)), 'PythonConsoleLexer': ('pip._vendor.pygments.lexers.python', 'Python console session', ('pycon',), (), ('text/x-python-doctest',)), - 'PythonLexer': ('pip._vendor.pygments.lexers.python', 'Python', ('python', 'py', 'sage', 'python3', 'py3'), ('*.py', '*.pyw', '*.jy', '*.sage', '*.sc', 'SConstruct', 'SConscript', '*.bzl', 'BUCK', 'BUILD', 'BUILD.bazel', 'WORKSPACE', '*.tac'), ('text/x-python', 'application/x-python', 'text/x-python3', 'application/x-python3')), + 'PythonLexer': ('pip._vendor.pygments.lexers.python', 'Python', ('python', 'py', 'sage', 'python3', 'py3'), ('*.py', '*.pyw', '*.pyi', '*.jy', '*.sage', '*.sc', 'SConstruct', 'SConscript', '*.bzl', 'BUCK', 'BUILD', 'BUILD.bazel', 'WORKSPACE', '*.tac'), ('text/x-python', 'application/x-python', 'text/x-python3', 'application/x-python3')), 'PythonTracebackLexer': ('pip._vendor.pygments.lexers.python', 'Python Traceback', ('pytb', 'py3tb'), ('*.pytb', '*.py3tb'), ('text/x-python-traceback', 'text/x-python3-traceback')), 'PythonUL4Lexer': ('pip._vendor.pygments.lexers.ul4', 'Python+UL4', ('py+ul4',), ('*.pyul4',), ()), 'QBasicLexer': ('pip._vendor.pygments.lexers.basic', 'QBasic', ('qbasic', 'basic'), ('*.BAS', '*.bas'), ('text/basic',)), @@ -421,7 +433,7 @@ LEXERS = { 'SASLexer': ('pip._vendor.pygments.lexers.sas', 'SAS', ('sas',), ('*.SAS', '*.sas'), ('text/x-sas', 'text/sas', 'application/x-sas')), 'SLexer': ('pip._vendor.pygments.lexers.r', 'S', ('splus', 's', 'r'), ('*.S', '*.R', '.Rhistory', '.Rprofile', '.Renviron'), ('text/S-plus', 'text/S', 'text/x-r-source', 'text/x-r', 'text/x-R', 'text/x-r-history', 'text/x-r-profile')), 'SMLLexer': ('pip._vendor.pygments.lexers.ml', 'Standard ML', ('sml',), ('*.sml', '*.sig', '*.fun'), ('text/x-standardml', 'application/x-standardml')), - 'SNBTLexer': ('pip._vendor.pygments.lexers.mcfunction', 'SNBT', ('snbt',), ('*.snbt',), ('text/snbt',)), + 'SNBTLexer': ('pip._vendor.pygments.lexers.minecraft', 'SNBT', ('snbt',), ('*.snbt',), ('text/snbt',)), 'SarlLexer': ('pip._vendor.pygments.lexers.jvm', 'SARL', ('sarl',), ('*.sarl',), ('text/x-sarl',)), 'SassLexer': ('pip._vendor.pygments.lexers.css', 'Sass', ('sass',), ('*.sass',), ('text/x-sass',)), 'SaviLexer': ('pip._vendor.pygments.lexers.savi', 'Savi', ('savi',), ('*.savi',), ()), @@ -479,12 +491,13 @@ LEXERS = { 'TeraTermLexer': ('pip._vendor.pygments.lexers.teraterm', 'Tera Term macro', ('teratermmacro', 'teraterm', 'ttl'), ('*.ttl',), ('text/x-teratermmacro',)), 'TermcapLexer': ('pip._vendor.pygments.lexers.configs', 'Termcap', ('termcap',), ('termcap', 'termcap.src'), ()), 'TerminfoLexer': ('pip._vendor.pygments.lexers.configs', 'Terminfo', ('terminfo',), ('terminfo', 'terminfo.src'), ()), - 'TerraformLexer': ('pip._vendor.pygments.lexers.configs', 'Terraform', ('terraform', 'tf'), ('*.tf',), ('application/x-tf', 'application/x-terraform')), + 'TerraformLexer': ('pip._vendor.pygments.lexers.configs', 'Terraform', ('terraform', 'tf', 'hcl'), ('*.tf', '*.hcl'), ('application/x-tf', 'application/x-terraform')), 'TexLexer': ('pip._vendor.pygments.lexers.markup', 'TeX', ('tex', 'latex'), ('*.tex', '*.aux', '*.toc'), ('text/x-tex', 'text/x-latex')), 'TextLexer': ('pip._vendor.pygments.lexers.special', 'Text only', ('text',), ('*.txt',), ('text/plain',)), 'ThingsDBLexer': ('pip._vendor.pygments.lexers.thingsdb', 'ThingsDB', ('ti', 'thingsdb'), ('*.ti',), ()), 'ThriftLexer': ('pip._vendor.pygments.lexers.dsls', 'Thrift', ('thrift',), ('*.thrift',), ('application/x-thrift',)), 'TiddlyWiki5Lexer': ('pip._vendor.pygments.lexers.markup', 'tiddler', ('tid',), ('*.tid',), ('text/vnd.tiddlywiki',)), + 'TlbLexer': ('pip._vendor.pygments.lexers.tlb', 'Tl-b', ('tlb',), ('*.tlb',), ()), 'TodotxtLexer': ('pip._vendor.pygments.lexers.textfmts', 'Todotxt', ('todotxt',), ('todo.txt', '*.todotxt'), ('text/x-todo',)), 'TransactSqlLexer': ('pip._vendor.pygments.lexers.sql', 'Transact-SQL', ('tsql', 't-sql'), ('*.sql',), ('text/x-tsql',)), 'TreetopLexer': ('pip._vendor.pygments.lexers.parsers', 'Treetop', ('treetop',), ('*.treetop', '*.tt'), ()), @@ -518,7 +531,11 @@ LEXERS = { 'WDiffLexer': ('pip._vendor.pygments.lexers.diff', 'WDiff', ('wdiff',), ('*.wdiff',), ()), 'WatLexer': ('pip._vendor.pygments.lexers.webassembly', 'WebAssembly', ('wast', 'wat'), ('*.wat', '*.wast'), ()), 'WebIDLLexer': ('pip._vendor.pygments.lexers.webidl', 'Web IDL', ('webidl',), ('*.webidl',), ()), + 'WgslLexer': ('pip._vendor.pygments.lexers.wgsl', 'WebGPU Shading Language', ('wgsl',), ('*.wgsl',), ('text/wgsl',)), 'WhileyLexer': ('pip._vendor.pygments.lexers.whiley', 'Whiley', ('whiley',), ('*.whiley',), ('text/x-whiley',)), + 'WikitextLexer': ('pip._vendor.pygments.lexers.markup', 'Wikitext', ('wikitext', 'mediawiki'), (), ('text/x-wiki',)), + 'WoWTocLexer': ('pip._vendor.pygments.lexers.wowtoc', 'World of Warcraft TOC', ('wowtoc',), ('*.toc',), ()), + 'WrenLexer': ('pip._vendor.pygments.lexers.wren', 'Wren', ('wren',), ('*.wren',), ()), 'X10Lexer': ('pip._vendor.pygments.lexers.x10', 'X10', ('x10', 'xten'), ('*.x10',), ('text/x-x10',)), 'XMLUL4Lexer': ('pip._vendor.pygments.lexers.ul4', 'XML+UL4', ('xml+ul4',), ('*.xmlul4',), ()), 'XQueryLexer': ('pip._vendor.pygments.lexers.webmisc', 'XQuery', ('xquery', 'xqy', 'xq', 'xql', 'xqm'), ('*.xqy', '*.xquery', '*.xq', '*.xql', '*.xqm'), ('text/xquery', 'application/xquery')), @@ -528,6 +545,7 @@ LEXERS = { 'XmlPhpLexer': ('pip._vendor.pygments.lexers.templates', 'XML+PHP', ('xml+php',), (), ('application/xml+php',)), 'XmlSmartyLexer': ('pip._vendor.pygments.lexers.templates', 'XML+Smarty', ('xml+smarty',), (), ('application/xml+smarty',)), 'XorgLexer': ('pip._vendor.pygments.lexers.xorg', 'Xorg', ('xorg.conf',), ('xorg.conf',), ()), + 'XppLexer': ('pip._vendor.pygments.lexers.dotnet', 'X++', ('xpp', 'x++'), ('*.xpp',), ()), 'XsltLexer': ('pip._vendor.pygments.lexers.html', 'XSLT', ('xslt',), ('*.xsl', '*.xslt', '*.xpl'), ('application/xsl+xml', 'application/xslt+xml')), 'XtendLexer': ('pip._vendor.pygments.lexers.jvm', 'Xtend', ('xtend',), ('*.xtend',), ('text/x-xtend',)), 'XtlangLexer': ('pip._vendor.pygments.lexers.lisp', 'xtlang', ('extempore',), ('*.xtm',), ()), diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py index c24e3c86..e9bf2d33 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/lexers/python.py @@ -4,26 +4,24 @@ Lexers for Python and related languages. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re import keyword -from pip._vendor.pygments.lexer import Lexer, RegexLexer, include, bygroups, using, \ - default, words, combined, do_insertions, this +from pip._vendor.pygments.lexer import DelegatingLexer, Lexer, RegexLexer, include, \ + bygroups, using, default, words, combined, do_insertions, this, line_re from pip._vendor.pygments.util import get_bool_opt, shebang_matches from pip._vendor.pygments.token import Text, Comment, Operator, Keyword, Name, String, \ - Number, Punctuation, Generic, Other, Error + Number, Punctuation, Generic, Other, Error, Whitespace from pip._vendor.pygments import unistring as uni __all__ = ['PythonLexer', 'PythonConsoleLexer', 'PythonTracebackLexer', 'Python2Lexer', 'Python2TracebackLexer', 'CythonLexer', 'DgLexer', 'NumPyLexer'] -line_re = re.compile('.*?\n') - class PythonLexer(RegexLexer): """ @@ -42,6 +40,8 @@ class PythonLexer(RegexLexer): filenames = [ '*.py', '*.pyw', + # Type stubs + '*.pyi', # Jython '*.jy', # Sage @@ -100,11 +100,11 @@ class PythonLexer(RegexLexer): tokens = { 'root': [ - (r'\n', Text), + (r'\n', Whitespace), (r'^(\s*)([rRuUbB]{,2})("""(?:.|\n)*?""")', - bygroups(Text, String.Affix, String.Doc)), + bygroups(Whitespace, String.Affix, String.Doc)), (r"^(\s*)([rRuUbB]{,2})('''(?:.|\n)*?''')", - bygroups(Text, String.Affix, String.Doc)), + bygroups(Whitespace, String.Affix, String.Doc)), (r'\A#!.+$', Comment.Hashbang), (r'#.*$', Comment.Single), (r'\\\n', Text), @@ -169,7 +169,7 @@ class PythonLexer(RegexLexer): combined('bytesescape', 'dqs')), ("([bB])(')", bygroups(String.Affix, String.Single), combined('bytesescape', 'sqs')), - + (r'[^\S\n]+', Text), include('numbers'), (r'!=|==|<<|>>|:=|[-~+/*%=<>&^|.]', Operator), @@ -192,13 +192,13 @@ class PythonLexer(RegexLexer): (r'(=\s*)?' # debug (https://bugs.python.org/issue36817) r'(\![sraf])?' # conversion r':', String.Interpol, '#pop'), - (r'\s+', Text), # allow new lines + (r'\s+', Whitespace), # allow new lines include('expr'), ], 'expr-inside-fstring-inner': [ (r'[{([]', Punctuation, 'expr-inside-fstring-inner'), (r'[])}]', Punctuation, '#pop'), - (r'\s+', Text), # allow new lines + (r'\s+', Whitespace), # allow new lines include('expr'), ], 'expr-keywords': [ @@ -229,21 +229,21 @@ class PythonLexer(RegexLexer): ], 'soft-keywords-inner': [ # optional `_` keyword - (r'(\s+)([^\n_]*)(_\b)', bygroups(Text, using(this), Keyword)), + (r'(\s+)([^\n_]*)(_\b)', bygroups(Whitespace, using(this), Keyword)), default('#pop') ], 'builtins': [ (words(( - '__import__', 'abs', 'all', 'any', 'bin', 'bool', 'bytearray', - 'breakpoint', 'bytes', 'chr', 'classmethod', 'compile', 'complex', - 'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'filter', - 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr', - 'hash', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass', - 'iter', 'len', 'list', 'locals', 'map', 'max', 'memoryview', - 'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', - 'property', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', - 'slice', 'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', - 'type', 'vars', 'zip'), prefix=r'(?>> )(.*\n)', bygroups(Generic.Prompt, Other.Code), 'continuations'), + # This happens, e.g., when tracebacks are embedded in documentation; + # trailing whitespaces are often stripped in such contexts. + (r'(>>>)(\n)', bygroups(Generic.Prompt, Whitespace)), + (r'(\^C)?Traceback \(most recent call last\):\n', Other.Traceback, 'traceback'), + # SyntaxError starts with this + (r' File "[^"]+", line \d+', Other.Traceback, 'traceback'), + (r'.*\n', Generic.Output), + ], + 'continuations': [ + (r'(\.\.\. )(.*\n)', bygroups(Generic.Prompt, Other.Code)), + # See above. + (r'(\.\.\.)(\n)', bygroups(Generic.Prompt, Whitespace)), + default('#pop'), + ], + 'traceback': [ + # As soon as we see a traceback, consume everything until the next + # >>> prompt. + (r'(?=>>>( |$))', Text, '#pop'), + (r'(KeyboardInterrupt)(\n)', bygroups(Name.Class, Whitespace)), + (r'.*\n', Other.Traceback), + ], + } -class PythonConsoleLexer(Lexer): +class PythonConsoleLexer(DelegatingLexer): """ For Python console output or doctests, such as: .. sourcecode:: pycon >>> a = 'foo' - >>> print a + >>> print(a) foo >>> 1 / 0 Traceback (most recent call last): @@ -659,70 +694,28 @@ class PythonConsoleLexer(Lexer): .. versionchanged:: 2.5 Now defaults to ``True``. """ + name = 'Python console session' aliases = ['pycon'] mimetypes = ['text/x-python-doctest'] def __init__(self, **options): - self.python3 = get_bool_opt(options, 'python3', True) - Lexer.__init__(self, **options) - - def get_tokens_unprocessed(self, text): - if self.python3: - pylexer = PythonLexer(**self.options) - tblexer = PythonTracebackLexer(**self.options) + python3 = get_bool_opt(options, 'python3', True) + if python3: + pylexer = PythonLexer + tblexer = PythonTracebackLexer else: - pylexer = Python2Lexer(**self.options) - tblexer = Python2TracebackLexer(**self.options) - - curcode = '' - insertions = [] - curtb = '' - tbindex = 0 - tb = 0 - for match in line_re.finditer(text): - line = match.group() - if line.startswith('>>> ') or line.startswith('... '): - tb = 0 - insertions.append((len(curcode), - [(0, Generic.Prompt, line[:4])])) - curcode += line[4:] - elif line.rstrip() == '...' and not tb: - # only a new >>> prompt can end an exception block - # otherwise an ellipsis in place of the traceback frames - # will be mishandled - insertions.append((len(curcode), - [(0, Generic.Prompt, '...')])) - curcode += line[3:] - else: - if curcode: - yield from do_insertions( - insertions, pylexer.get_tokens_unprocessed(curcode)) - curcode = '' - insertions = [] - if (line.startswith('Traceback (most recent call last):') or - re.match(' File "[^"]+", line \\d+\\n$', line)): - tb = 1 - curtb = line - tbindex = match.start() - elif line == 'KeyboardInterrupt\n': - yield match.start(), Name.Class, line - elif tb: - curtb += line - if not (line.startswith(' ') or line.strip() == '...'): - tb = 0 - for i, t, v in tblexer.get_tokens_unprocessed(curtb): - yield tbindex+i, t, v - curtb = '' - else: - yield match.start(), Generic.Output, line - if curcode: - yield from do_insertions(insertions, - pylexer.get_tokens_unprocessed(curcode)) - if curtb: - for i, t, v in tblexer.get_tokens_unprocessed(curtb): - yield tbindex+i, t, v - + pylexer = Python2Lexer + tblexer = Python2TracebackLexer + # We have two auxiliary lexers. Use DelegatingLexer twice with + # different tokens. TODO: DelegatingLexer should support this + # directly, by accepting a tuplet of auxiliary lexers and a tuple of + # distinguishing tokens. Then we wouldn't need this intermediary + # class. + class _ReplaceInnerCode(DelegatingLexer): + def __init__(self, **options): + super().__init__(pylexer, _PythonConsoleLexerBase, Other.Code, **options) + super().__init__(tblexer, _ReplaceInnerCode, Other.Traceback, **options) class PythonTracebackLexer(RegexLexer): """ @@ -742,8 +735,8 @@ class PythonTracebackLexer(RegexLexer): tokens = { 'root': [ - (r'\n', Text), - (r'^Traceback \(most recent call last\):\n', Generic.Traceback, 'intb'), + (r'\n', Whitespace), + (r'^(\^C)?Traceback \(most recent call last\):\n', Generic.Traceback, 'intb'), (r'^During handling of the above exception, another ' r'exception occurred:\n\n', Generic.Traceback), (r'^The above exception was the direct cause of the ' @@ -753,24 +746,25 @@ class PythonTracebackLexer(RegexLexer): ], 'intb': [ (r'^( File )("[^"]+")(, line )(\d+)(, in )(.+)(\n)', - bygroups(Text, Name.Builtin, Text, Number, Text, Name, Text)), + bygroups(Text, Name.Builtin, Text, Number, Text, Name, Whitespace)), (r'^( File )("[^"]+")(, line )(\d+)(\n)', - bygroups(Text, Name.Builtin, Text, Number, Text)), + bygroups(Text, Name.Builtin, Text, Number, Whitespace)), (r'^( )(.+)(\n)', - bygroups(Text, using(PythonLexer), Text), 'markers'), + bygroups(Whitespace, using(PythonLexer), Whitespace), 'markers'), (r'^([ \t]*)(\.\.\.)(\n)', - bygroups(Text, Comment, Text)), # for doctests... + bygroups(Whitespace, Comment, Whitespace)), # for doctests... (r'^([^:]+)(: )(.+)(\n)', - bygroups(Generic.Error, Text, Name, Text), '#pop'), + bygroups(Generic.Error, Text, Name, Whitespace), '#pop'), (r'^([a-zA-Z_][\w.]*)(:?\n)', - bygroups(Generic.Error, Text), '#pop') + bygroups(Generic.Error, Whitespace), '#pop'), + default('#pop'), ], 'markers': [ # Either `PEP 657 ` # error locations in Python 3.11+, or single-caret markers # for syntax errors before that. (r'^( {4,})([~^]+)(\n)', - bygroups(Text, Punctuation.Marker, Text), + bygroups(Whitespace, Punctuation.Marker, Whitespace), '#pop'), default('#pop'), ], @@ -808,17 +802,17 @@ class Python2TracebackLexer(RegexLexer): ], 'intb': [ (r'^( File )("[^"]+")(, line )(\d+)(, in )(.+)(\n)', - bygroups(Text, Name.Builtin, Text, Number, Text, Name, Text)), + bygroups(Text, Name.Builtin, Text, Number, Text, Name, Whitespace)), (r'^( File )("[^"]+")(, line )(\d+)(\n)', - bygroups(Text, Name.Builtin, Text, Number, Text)), + bygroups(Text, Name.Builtin, Text, Number, Whitespace)), (r'^( )(.+)(\n)', - bygroups(Text, using(Python2Lexer), Text), 'marker'), + bygroups(Text, using(Python2Lexer), Whitespace), 'marker'), (r'^([ \t]*)(\.\.\.)(\n)', - bygroups(Text, Comment, Text)), # for doctests... + bygroups(Text, Comment, Whitespace)), # for doctests... (r'^([^:]+)(: )(.+)(\n)', - bygroups(Generic.Error, Text, Name, Text), '#pop'), + bygroups(Generic.Error, Text, Name, Whitespace), '#pop'), (r'^([a-zA-Z_]\w*)(:?\n)', - bygroups(Generic.Error, Text), '#pop') + bygroups(Generic.Error, Whitespace), '#pop') ], 'marker': [ # For syntax errors. @@ -843,13 +837,13 @@ class CythonLexer(RegexLexer): tokens = { 'root': [ - (r'\n', Text), - (r'^(\s*)("""(?:.|\n)*?""")', bygroups(Text, String.Doc)), - (r"^(\s*)('''(?:.|\n)*?''')", bygroups(Text, String.Doc)), + (r'\n', Whitespace), + (r'^(\s*)("""(?:.|\n)*?""")', bygroups(Whitespace, String.Doc)), + (r"^(\s*)('''(?:.|\n)*?''')", bygroups(Whitespace, String.Doc)), (r'[^\S\n]+', Text), (r'#.*$', Comment), (r'[]{}:(),;[]', Punctuation), - (r'\\\n', Text), + (r'\\\n', Whitespace), (r'\\', Text), (r'(in|is|and|or|not)\b', Operator.Word), (r'(<)([a-zA-Z0-9.?]+)(>)', diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/modeline.py b/.venv/Lib/site-packages/pip/_vendor/pygments/modeline.py index 43630835..7b6f6a32 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/modeline.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/modeline.py @@ -4,7 +4,7 @@ A simple modeline parser (based on pymodeline). - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/plugin.py b/.venv/Lib/site-packages/pip/_vendor/pygments/plugin.py index 3590bee8..7b722d58 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/plugin.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/plugin.py @@ -34,7 +34,7 @@ yourfilter = yourfilter:YourFilter - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py b/.venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py index ae007919..45223ecc 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/regexopt.py @@ -5,7 +5,7 @@ An algorithm that generates optimized regexes for matching long lists of literal strings. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/scanner.py b/.venv/Lib/site-packages/pip/_vendor/pygments/scanner.py index d47ed482..32a2f303 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/scanner.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/scanner.py @@ -11,7 +11,7 @@ Have a look at the `DelphiLexer` to get an idea of how to use this scanner. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py b/.venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py index c41bd49d..2c7facde 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/sphinxext.py @@ -5,7 +5,7 @@ Sphinx extension to generate automatic documentation of lexers, formatters and filters. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -74,6 +74,8 @@ class PygmentsDoc(Directive): out = self.document_formatters() elif self.arguments[0] == 'filters': out = self.document_filters() + elif self.arguments[0] == 'lexers_overview': + out = self.document_lexers_overview() else: raise Exception('invalid argument for "pygmentsdoc" directive') node = nodes.compound() @@ -83,6 +85,66 @@ class PygmentsDoc(Directive): self.state.document.settings.record_dependencies.add(fn) return node.children + def document_lexers_overview(self): + """Generate a tabular overview of all lexers. + + The columns are the lexer name, the extensions handled by this lexer + (or "None"), the aliases and a link to the lexer class.""" + from pip._vendor.pygments.lexers._mapping import LEXERS + from pip._vendor.pygments.lexers import find_lexer_class + out = [] + + table = [] + + def format_link(name, url): + if url: + return f'`{name} <{url}>`_' + return name + + for classname, data in sorted(LEXERS.items(), key=lambda x: x[1][1].lower()): + lexer_cls = find_lexer_class(data[1]) + extensions = lexer_cls.filenames + lexer_cls.alias_filenames + + table.append({ + 'name': format_link(data[1], lexer_cls.url), + 'extensions': ', '.join(extensions).replace('*', '\\*').replace('_', '\\') or 'None', + 'aliases': ', '.join(data[2]), + 'class': f'{data[0]}.{classname}' + }) + + column_names = ['name', 'extensions', 'aliases', 'class'] + column_lengths = [max([len(row[column]) for row in table if row[column]]) + for column in column_names] + + def write_row(*columns): + """Format a table row""" + out = [] + for l, c in zip(column_lengths, columns): + if c: + out.append(c.ljust(l)) + else: + out.append(' '*l) + + return ' '.join(out) + + def write_seperator(): + """Write a table separator row""" + sep = ['='*c for c in column_lengths] + return write_row(*sep) + + out.append(write_seperator()) + out.append(write_row('Name', 'Extension(s)', 'Short name(s)', 'Lexer class')) + out.append(write_seperator()) + for row in table: + out.append(write_row( + row['name'], + row['extensions'], + row['aliases'], + f':class:`~{row["class"]}`')) + out.append(write_seperator()) + + return '\n'.join(out) + def document_lexers(self): from pip._vendor.pygments.lexers._mapping import LEXERS out = [] diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/style.py b/.venv/Lib/site-packages/pip/_vendor/pygments/style.py index 84abbc20..edc19627 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/style.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/style.py @@ -4,7 +4,7 @@ Basic style object. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py index 44cc0efb..7401cf5d 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/styles/__init__.py @@ -4,15 +4,15 @@ Contains built-in styles. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ from pip._vendor.pygments.plugin import find_plugin_styles from pip._vendor.pygments.util import ClassNotFound - -#: Maps style names to 'submodule::classname'. +#: A dictionary of built-in styles, mapping style names to +#: ``'submodule::classname'`` strings. STYLE_MAP = { 'default': 'default::DefaultStyle', 'emacs': 'emacs::EmacsStyle', @@ -66,6 +66,13 @@ STYLE_MAP = { def get_style_by_name(name): + """ + Return a style class by its short name. The names of the builtin styles + are listed in :data:`pygments.styles.STYLE_MAP`. + + Will raise :exc:`pygments.util.ClassNotFound` if no style of that name is + found. + """ if name in STYLE_MAP: mod, cls = STYLE_MAP[name].split('::') builtin = "yes" @@ -90,8 +97,7 @@ def get_style_by_name(name): def get_all_styles(): - """Return a generator for all styles by name, - both builtin and plugin.""" + """Return a generator for all styles by name, both builtin and plugin.""" yield from STYLE_MAP for name, _ in find_plugin_styles(): yield name diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/token.py b/.venv/Lib/site-packages/pip/_vendor/pygments/token.py index e3e565ad..7395cb6a 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/token.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/token.py @@ -4,7 +4,7 @@ Basic token types and the standard tokens. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/unistring.py b/.venv/Lib/site-packages/pip/_vendor/pygments/unistring.py index 2e3c8086..39f6baee 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/unistring.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/unistring.py @@ -7,7 +7,7 @@ Inspired by chartypes_create.py from the MoinMoin project. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -112,7 +112,7 @@ if __name__ == '__main__': # pragma: no cover categories = {'xid_start': [], 'xid_continue': []} - with open(__file__) as fp: + with open(__file__, encoding='utf-8') as fp: content = fp.read() header = content[:content.find('Cc =')] @@ -136,7 +136,7 @@ if __name__ == '__main__': # pragma: no cover if ('a' + c).isidentifier(): categories['xid_continue'].append(c) - with open(__file__, 'w') as fp: + with open(__file__, 'w', encoding='utf-8') as fp: fp.write(header) for cat in sorted(categories): diff --git a/.venv/Lib/site-packages/pip/_vendor/pygments/util.py b/.venv/Lib/site-packages/pip/_vendor/pygments/util.py index 8032962d..941fdb9e 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pygments/util.py +++ b/.venv/Lib/site-packages/pip/_vendor/pygments/util.py @@ -4,7 +4,7 @@ Utility functions. - :copyright: Copyright 2006-2022 by the Pygments team, see AUTHORS. + :copyright: Copyright 2006-2023 by the Pygments team, see AUTHORS. :license: BSD, see LICENSE for details. """ @@ -32,10 +32,16 @@ class ClassNotFound(ValueError): class OptionError(Exception): - pass - + """ + This exception will be raised by all option processing functions if + the type or value of the argument is not correct. + """ def get_choice_opt(options, optname, allowed, default=None, normcase=False): + """ + If the key `optname` from the dictionary is not in the sequence + `allowed`, raise an error, otherwise return it. + """ string = options.get(optname, default) if normcase: string = string.lower() @@ -46,6 +52,17 @@ def get_choice_opt(options, optname, allowed, default=None, normcase=False): def get_bool_opt(options, optname, default=None): + """ + Intuitively, this is `options.get(optname, default)`, but restricted to + Boolean value. The Booleans can be represented as string, in order to accept + Boolean value from the command line arguments. If the key `optname` is + present in the dictionary `options` and is not associated with a Boolean, + raise an `OptionError`. If it is absent, `default` is returned instead. + + The valid string values for ``True`` are ``1``, ``yes``, ``true`` and + ``on``, the ones for ``False`` are ``0``, ``no``, ``false`` and ``off`` + (matched case-insensitively). + """ string = options.get(optname, default) if isinstance(string, bool): return string @@ -66,6 +83,7 @@ def get_bool_opt(options, optname, default=None): def get_int_opt(options, optname, default=None): + """As :func:`get_bool_opt`, but interpret the value as an integer.""" string = options.get(optname, default) try: return int(string) @@ -78,8 +96,12 @@ def get_int_opt(options, optname, default=None): 'must give an integer value' % ( string, optname)) - def get_list_opt(options, optname, default=None): + """ + If the key `optname` from the dictionary `options` is a string, + split it at whitespace and return it. If it is already a list + or a tuple, it is returned as a list. + """ val = options.get(optname, default) if isinstance(val, str): return val.split() diff --git a/.venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py index 75372500..88bc10ac 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pyparsing/__init__.py @@ -56,7 +56,7 @@ self-explanatory class names, and the use of :class:`'+'`, :class:`'|'`, :class:`'^'` and :class:`'&'` operators. The :class:`ParseResults` object returned from -:class:`ParserElement.parseString` can be +:class:`ParserElement.parse_string` can be accessed as a nested list, a dictionary, or an object with named attributes. @@ -85,11 +85,11 @@ classes inherit from. Use the docstrings for examples of how to: and :class:`'&'` operators to combine simple expressions into more complex ones - associate names with your parsed results using - :class:`ParserElement.setResultsName` + :class:`ParserElement.set_results_name` - access the parsed data, which is returned as a :class:`ParseResults` object - - find some helpful expression short-cuts like :class:`delimitedList` - and :class:`oneOf` + - find some helpful expression short-cuts like :class:`DelimitedList` + and :class:`one_of` - find more useful common expressions in the :class:`pyparsing_common` namespace class """ @@ -106,30 +106,22 @@ class version_info(NamedTuple): @property def __version__(self): return ( - "{}.{}.{}".format(self.major, self.minor, self.micro) + f"{self.major}.{self.minor}.{self.micro}" + ( - "{}{}{}".format( - "r" if self.releaselevel[0] == "c" else "", - self.releaselevel[0], - self.serial, - ), + f"{'r' if self.releaselevel[0] == 'c' else ''}{self.releaselevel[0]}{self.serial}", "", )[self.releaselevel == "final"] ) def __str__(self): - return "{} {} / {}".format(__name__, self.__version__, __version_time__) + return f"{__name__} {self.__version__} / {__version_time__}" def __repr__(self): - return "{}.{}({})".format( - __name__, - type(self).__name__, - ", ".join("{}={!r}".format(*nv) for nv in zip(self._fields, self)), - ) + return f"{__name__}.{type(self).__name__}({', '.join('{}={!r}'.format(*nv) for nv in zip(self._fields, self))})" -__version_info__ = version_info(3, 0, 9, "final", 0) -__version_time__ = "05 May 2022 07:02 UTC" +__version_info__ = version_info(3, 1, 0, "final", 1) +__version_time__ = "18 Jun 2023 14:05 UTC" __version__ = __version_info__.__version__ __versionTime__ = __version_time__ __author__ = "Paul McGuire " @@ -139,9 +131,9 @@ from .exceptions import * from .actions import * from .core import __diag__, __compat__ from .results import * -from .core import * +from .core import * # type: ignore[misc, assignment] from .core import _builtin_exprs as core_builtin_exprs -from .helpers import * +from .helpers import * # type: ignore[misc, assignment] from .helpers import _builtin_exprs as helper_builtin_exprs from .unicode import unicode_set, UnicodeRangeList, pyparsing_unicode as unicode @@ -153,11 +145,11 @@ from .common import ( # define backward compat synonyms if "pyparsing_unicode" not in globals(): - pyparsing_unicode = unicode + pyparsing_unicode = unicode # type: ignore[misc] if "pyparsing_common" not in globals(): - pyparsing_common = common + pyparsing_common = common # type: ignore[misc] if "pyparsing_test" not in globals(): - pyparsing_test = testing + pyparsing_test = testing # type: ignore[misc] core_builtin_exprs += common_builtin_exprs + helper_builtin_exprs @@ -174,7 +166,9 @@ __all__ = [ "CaselessKeyword", "CaselessLiteral", "CharsNotIn", + "CloseMatch", "Combine", + "DelimitedList", "Dict", "Each", "Empty", @@ -227,9 +221,11 @@ __all__ = [ "alphas8bit", "any_close_tag", "any_open_tag", + "autoname_elements", "c_style_comment", "col", "common_html_entity", + "condition_as_parse_action", "counted_array", "cpp_style_comment", "dbl_quoted_string", @@ -241,6 +237,7 @@ __all__ = [ "html_comment", "identchars", "identbodychars", + "infix_notation", "java_style_comment", "line", "line_end", @@ -255,8 +252,12 @@ __all__ = [ "null_debug_action", "nums", "one_of", + "original_text_for", "printables", "punc8bit", + "pyparsing_common", + "pyparsing_test", + "pyparsing_unicode", "python_style_comment", "quoted_string", "remove_quotes", @@ -267,28 +268,20 @@ __all__ = [ "srange", "string_end", "string_start", + "token_map", "trace_parse_action", + "ungroup", + "unicode_set", "unicode_string", "with_attribute", - "indentedBlock", - "original_text_for", - "ungroup", - "infix_notation", - "locatedExpr", "with_class", - "CloseMatch", - "token_map", - "pyparsing_common", - "pyparsing_unicode", - "unicode_set", - "condition_as_parse_action", - "pyparsing_test", # pre-PEP8 compatibility names "__versionTime__", "anyCloseTag", "anyOpenTag", "cStyleComment", "commonHTMLEntity", + "conditionAsParseAction", "countedArray", "cppStyleComment", "dblQuotedString", @@ -296,9 +289,12 @@ __all__ = [ "delimitedList", "dictOf", "htmlComment", + "indentedBlock", + "infixNotation", "javaStyleComment", "lineEnd", "lineStart", + "locatedExpr", "makeHTMLTags", "makeXMLTags", "matchOnlyAtCol", @@ -308,6 +304,7 @@ __all__ = [ "nullDebugAction", "oneOf", "opAssoc", + "originalTextFor", "pythonStyleComment", "quotedString", "removeQuotes", @@ -317,15 +314,9 @@ __all__ = [ "sglQuotedString", "stringEnd", "stringStart", + "tokenMap", "traceParseAction", "unicodeString", "withAttribute", - "indentedBlock", - "originalTextFor", - "infixNotation", - "locatedExpr", "withClass", - "tokenMap", - "conditionAsParseAction", - "autoname_elements", ] diff --git a/.venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py b/.venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py index f72c66e7..ca6e4c6a 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py +++ b/.venv/Lib/site-packages/pip/_vendor/pyparsing/actions.py @@ -1,7 +1,7 @@ # actions.py from .exceptions import ParseException -from .util import col +from .util import col, replaced_by_pep8 class OnlyOnce: @@ -38,7 +38,7 @@ def match_only_at_col(n): def verify_col(strg, locn, toks): if col(locn, strg) != n: - raise ParseException(strg, locn, "matched token not at column {}".format(n)) + raise ParseException(strg, locn, f"matched token not at column {n}") return verify_col @@ -148,15 +148,13 @@ def with_attribute(*args, **attr_dict): raise ParseException( s, l, - "attribute {!r} has value {!r}, must be {!r}".format( - attrName, tokens[attrName], attrValue - ), + f"attribute {attrName!r} has value {tokens[attrName]!r}, must be {attrValue!r}", ) return pa -with_attribute.ANY_VALUE = object() +with_attribute.ANY_VALUE = object() # type: ignore [attr-defined] def with_class(classname, namespace=""): @@ -195,13 +193,25 @@ def with_class(classname, namespace=""): 1 4 0 1 0 1,3 2,3 1,1 """ - classattr = "{}:class".format(namespace) if namespace else "class" + classattr = f"{namespace}:class" if namespace else "class" return with_attribute(**{classattr: classname}) # pre-PEP8 compatibility symbols -replaceWith = replace_with -removeQuotes = remove_quotes -withAttribute = with_attribute -withClass = with_class -matchOnlyAtCol = match_only_at_col +# fmt: off +@replaced_by_pep8(replace_with) +def replaceWith(): ... + +@replaced_by_pep8(remove_quotes) +def removeQuotes(): ... + +@replaced_by_pep8(with_attribute) +def withAttribute(): ... + +@replaced_by_pep8(with_class) +def withClass(): ... + +@replaced_by_pep8(match_only_at_col) +def matchOnlyAtCol(): ... + +# fmt: on diff --git a/.venv/Lib/site-packages/pip/_vendor/pyparsing/common.py b/.venv/Lib/site-packages/pip/_vendor/pyparsing/common.py index 1859fb79..7a666b27 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pyparsing/common.py +++ b/.venv/Lib/site-packages/pip/_vendor/pyparsing/common.py @@ -1,6 +1,6 @@ # common.py from .core import * -from .helpers import delimited_list, any_open_tag, any_close_tag +from .helpers import DelimitedList, any_open_tag, any_close_tag from datetime import datetime @@ -22,17 +22,17 @@ class pyparsing_common: Parse actions: - - :class:`convertToInteger` - - :class:`convertToFloat` - - :class:`convertToDate` - - :class:`convertToDatetime` - - :class:`stripHTMLTags` - - :class:`upcaseTokens` - - :class:`downcaseTokens` + - :class:`convert_to_integer` + - :class:`convert_to_float` + - :class:`convert_to_date` + - :class:`convert_to_datetime` + - :class:`strip_html_tags` + - :class:`upcase_tokens` + - :class:`downcase_tokens` Example:: - pyparsing_common.number.runTests(''' + pyparsing_common.number.run_tests(''' # any int or real number, returned as the appropriate type 100 -100 @@ -42,7 +42,7 @@ class pyparsing_common: 1e-12 ''') - pyparsing_common.fnumber.runTests(''' + pyparsing_common.fnumber.run_tests(''' # any int or real number, returned as float 100 -100 @@ -52,19 +52,19 @@ class pyparsing_common: 1e-12 ''') - pyparsing_common.hex_integer.runTests(''' + pyparsing_common.hex_integer.run_tests(''' # hex numbers 100 FF ''') - pyparsing_common.fraction.runTests(''' + pyparsing_common.fraction.run_tests(''' # fractions 1/2 -3/4 ''') - pyparsing_common.mixed_integer.runTests(''' + pyparsing_common.mixed_integer.run_tests(''' # mixed fractions 1 1/2 @@ -73,8 +73,8 @@ class pyparsing_common: ''') import uuid - pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) - pyparsing_common.uuid.runTests(''' + pyparsing_common.uuid.set_parse_action(token_map(uuid.UUID)) + pyparsing_common.uuid.run_tests(''' # uuid 12345678-1234-5678-1234-567812345678 ''') @@ -260,8 +260,8 @@ class pyparsing_common: Example:: date_expr = pyparsing_common.iso8601_date.copy() - date_expr.setParseAction(pyparsing_common.convertToDate()) - print(date_expr.parseString("1999-12-31")) + date_expr.set_parse_action(pyparsing_common.convert_to_date()) + print(date_expr.parse_string("1999-12-31")) prints:: @@ -287,8 +287,8 @@ class pyparsing_common: Example:: dt_expr = pyparsing_common.iso8601_datetime.copy() - dt_expr.setParseAction(pyparsing_common.convertToDatetime()) - print(dt_expr.parseString("1999-12-31T23:59:59.999")) + dt_expr.set_parse_action(pyparsing_common.convert_to_datetime()) + print(dt_expr.parse_string("1999-12-31T23:59:59.999")) prints:: @@ -326,9 +326,9 @@ class pyparsing_common: # strip HTML links from normal text text = 'More info at the pyparsing wiki page' - td, td_end = makeHTMLTags("TD") - table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end - print(table_text.parseString(text).body) + td, td_end = make_html_tags("TD") + table_text = td + SkipTo(td_end).set_parse_action(pyparsing_common.strip_html_tags)("body") + td_end + print(table_text.parse_string(text).body) Prints:: @@ -348,7 +348,7 @@ class pyparsing_common: .streamline() .set_name("commaItem") ) - comma_separated_list = delimited_list( + comma_separated_list = DelimitedList( Opt(quoted_string.copy() | _commasepitem, default="") ).set_name("comma separated list") """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" @@ -363,7 +363,7 @@ class pyparsing_common: url = Regex( # https://mathiasbynens.be/demo/url-regex # https://gist.github.com/dperini/729294 - r"^" + + r"(?P" + # protocol identifier (optional) # short syntax // still required r"(?:(?:(?Phttps?|ftp):)?\/\/)" + @@ -405,18 +405,26 @@ class pyparsing_common: r"(\?(?P[^#]*))?" + # fragment (optional) r"(#(?P\S*))?" + - r"$" + r")" ).set_name("url") + """URL (http/https/ftp scheme)""" # fmt: on # pre-PEP8 compatibility names convertToInteger = convert_to_integer + """Deprecated - use :class:`convert_to_integer`""" convertToFloat = convert_to_float + """Deprecated - use :class:`convert_to_float`""" convertToDate = convert_to_date + """Deprecated - use :class:`convert_to_date`""" convertToDatetime = convert_to_datetime + """Deprecated - use :class:`convert_to_datetime`""" stripHTMLTags = strip_html_tags + """Deprecated - use :class:`strip_html_tags`""" upcaseTokens = upcase_tokens + """Deprecated - use :class:`upcase_tokens`""" downcaseTokens = downcase_tokens + """Deprecated - use :class:`downcase_tokens`""" _builtin_exprs = [ diff --git a/.venv/Lib/site-packages/pip/_vendor/pyparsing/core.py b/.venv/Lib/site-packages/pip/_vendor/pyparsing/core.py index 6ff3c766..8d5a856e 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pyparsing/core.py +++ b/.venv/Lib/site-packages/pip/_vendor/pyparsing/core.py @@ -1,19 +1,22 @@ # # core.py # + +from collections import deque import os import typing from typing import ( - NamedTuple, - Union, - Callable, Any, + Callable, Generator, - Tuple, List, - TextIO, - Set, + NamedTuple, Sequence, + Set, + TextIO, + Tuple, + Union, + cast, ) from abc import ABC, abstractmethod from enum import Enum @@ -40,6 +43,7 @@ from .util import ( _flatten, LRUMemo as _LRUMemo, UnboundedMemo as _UnboundedMemo, + replaced_by_pep8, ) from .exceptions import * from .actions import * @@ -134,6 +138,7 @@ class __diag__(__config_flags): class Diagnostics(Enum): """ Diagnostic configuration (all default to disabled) + - ``warn_multiple_tokens_in_named_alternation`` - flag to enable warnings when a results name is defined on a :class:`MatchFirst` or :class:`Or` expression with one or more :class:`And` subexpressions - ``warn_ungrouped_named_tokens_in_collection`` - flag to enable warnings when a results @@ -228,6 +233,8 @@ _single_arg_builtins = { } _generatorType = types.GeneratorType +ParseImplReturnType = Tuple[int, Any] +PostParseReturnType = Union[ParseResults, Sequence[ParseResults]] ParseAction = Union[ Callable[[], Any], Callable[[ParseResults], Any], @@ -256,7 +263,7 @@ hexnums = nums + "ABCDEFabcdef" alphanums = alphas + nums printables = "".join([c for c in string.printable if c not in string.whitespace]) -_trim_arity_call_line: traceback.StackSummary = None +_trim_arity_call_line: traceback.StackSummary = None # type: ignore[assignment] def _trim_arity(func, max_limit=3): @@ -269,11 +276,6 @@ def _trim_arity(func, max_limit=3): limit = 0 found_arity = False - def extract_tb(tb, limit=0): - frames = traceback.extract_tb(tb, limit=limit) - frame_summary = frames[-1] - return [frame_summary[:2]] - # synthesize what would be returned by traceback.extract_stack at the call to # user's parse action 'func', so that we don't incur call penalty at parse time @@ -297,8 +299,10 @@ def _trim_arity(func, max_limit=3): raise else: tb = te.__traceback__ + frames = traceback.extract_tb(tb, limit=2) + frame_summary = frames[-1] trim_arity_type_error = ( - extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth + [frame_summary[:2]][-1][:2] == pa_call_line_synth ) del tb @@ -320,7 +324,7 @@ def _trim_arity(func, max_limit=3): def condition_as_parse_action( - fn: ParseCondition, message: str = None, fatal: bool = False + fn: ParseCondition, message: typing.Optional[str] = None, fatal: bool = False ) -> ParseAction: """ Function to convert a simple predicate function that returns ``True`` or ``False`` @@ -353,15 +357,9 @@ def _default_start_debug_action( cache_hit_str = "*" if cache_hit else "" print( ( - "{}Match {} at loc {}({},{})\n {}\n {}^".format( - cache_hit_str, - expr, - loc, - lineno(loc, instring), - col(loc, instring), - line(loc, instring), - " " * (col(loc, instring) - 1), - ) + f"{cache_hit_str}Match {expr} at loc {loc}({lineno(loc, instring)},{col(loc, instring)})\n" + f" {line(loc, instring)}\n" + f" {' ' * (col(loc, instring) - 1)}^" ) ) @@ -375,7 +373,7 @@ def _default_success_debug_action( cache_hit: bool = False, ): cache_hit_str = "*" if cache_hit else "" - print("{}Matched {} -> {}".format(cache_hit_str, expr, toks.as_list())) + print(f"{cache_hit_str}Matched {expr} -> {toks.as_list()}") def _default_exception_debug_action( @@ -386,11 +384,7 @@ def _default_exception_debug_action( cache_hit: bool = False, ): cache_hit_str = "*" if cache_hit else "" - print( - "{}Match {} failed, {} raised: {}".format( - cache_hit_str, expr, type(exc).__name__, exc - ) - ) + print(f"{cache_hit_str}Match {expr} failed, {type(exc).__name__} raised: {exc}") def null_debug_action(*args): @@ -402,7 +396,7 @@ class ParserElement(ABC): DEFAULT_WHITE_CHARS: str = " \n\t\r" verbose_stacktrace: bool = False - _literalStringClass: typing.Optional[type] = None + _literalStringClass: type = None # type: ignore[assignment] @staticmethod def set_default_whitespace_chars(chars: str) -> None: @@ -447,6 +441,18 @@ class ParserElement(ABC): """ ParserElement._literalStringClass = cls + @classmethod + def using_each(cls, seq, **class_kwargs): + """ + Yields a sequence of class(obj, **class_kwargs) for obj in seq. + + Example:: + + LPAR, RPAR, LBRACE, RBRACE, SEMI = Suppress.using_each("(){};") + + """ + yield from (cls(obj, **class_kwargs) for obj in seq) + class DebugActions(NamedTuple): debug_try: typing.Optional[DebugStartAction] debug_match: typing.Optional[DebugSuccessAction] @@ -455,9 +461,9 @@ class ParserElement(ABC): def __init__(self, savelist: bool = False): self.parseAction: List[ParseAction] = list() self.failAction: typing.Optional[ParseFailAction] = None - self.customName = None - self._defaultName = None - self.resultsName = None + self.customName: str = None # type: ignore[assignment] + self._defaultName: typing.Optional[str] = None + self.resultsName: str = None # type: ignore[assignment] self.saveAsList = savelist self.skipWhitespace = True self.whiteChars = set(ParserElement.DEFAULT_WHITE_CHARS) @@ -490,12 +496,29 @@ class ParserElement(ABC): base.suppress_warning(Diagnostics.warn_on_parse_using_empty_Forward) # statement would normally raise a warning, but is now suppressed - print(base.parseString("x")) + print(base.parse_string("x")) """ self.suppress_warnings_.append(warning_type) return self + def visit_all(self): + """General-purpose method to yield all expressions and sub-expressions + in a grammar. Typically just for internal use. + """ + to_visit = deque([self]) + seen = set() + while to_visit: + cur = to_visit.popleft() + + # guard against looping forever through recursive grammars + if cur in seen: + continue + seen.add(cur) + + to_visit.extend(cur.recurse()) + yield cur + def copy(self) -> "ParserElement": """ Make a copy of this :class:`ParserElement`. Useful for defining @@ -585,11 +608,11 @@ class ParserElement(ABC): pdb.set_trace() return _parseMethod(instring, loc, doActions, callPreParse) - breaker._originalParseMethod = _parseMethod - self._parse = breaker + breaker._originalParseMethod = _parseMethod # type: ignore [attr-defined] + self._parse = breaker # type: ignore [assignment] else: if hasattr(self._parse, "_originalParseMethod"): - self._parse = self._parse._originalParseMethod + self._parse = self._parse._originalParseMethod # type: ignore [attr-defined, assignment] return self def set_parse_action(self, *fns: ParseAction, **kwargs) -> "ParserElement": @@ -601,9 +624,9 @@ class ParserElement(ABC): Each parse action ``fn`` is a callable method with 0-3 arguments, called as ``fn(s, loc, toks)`` , ``fn(loc, toks)`` , ``fn(toks)`` , or just ``fn()`` , where: - - s = the original string being parsed (see note below) - - loc = the location of the matching substring - - toks = a list of the matched tokens, packaged as a :class:`ParseResults` object + - ``s`` = the original string being parsed (see note below) + - ``loc`` = the location of the matching substring + - ``toks`` = a list of the matched tokens, packaged as a :class:`ParseResults` object The parsed tokens are passed to the parse action as ParseResults. They can be modified in place using list-style append, extend, and pop operations to update @@ -621,7 +644,7 @@ class ParserElement(ABC): Optional keyword arguments: - - call_during_try = (default= ``False``) indicate if parse action should be run during + - ``call_during_try`` = (default= ``False``) indicate if parse action should be run during lookaheads and alternate testing. For parse actions that have side effects, it is important to only call the parse action once it is determined that it is being called as part of a successful parse. For parse actions that perform additional @@ -697,10 +720,10 @@ class ParserElement(ABC): Optional keyword arguments: - - message = define a custom message to be used in the raised exception - - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise + - ``message`` = define a custom message to be used in the raised exception + - ``fatal`` = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException - - call_during_try = boolean to indicate if this method should be called during internal tryParse calls, + - ``call_during_try`` = boolean to indicate if this method should be called during internal tryParse calls, default=False Example:: @@ -716,7 +739,9 @@ class ParserElement(ABC): for fn in fns: self.parseAction.append( condition_as_parse_action( - fn, message=kwargs.get("message"), fatal=kwargs.get("fatal", False) + fn, + message=str(kwargs.get("message")), + fatal=bool(kwargs.get("fatal", False)), ) ) @@ -731,30 +756,33 @@ class ParserElement(ABC): Fail acton fn is a callable function that takes the arguments ``fn(s, loc, expr, err)`` where: - - s = string being parsed - - loc = location where expression match was attempted and failed - - expr = the parse expression that failed - - err = the exception thrown + - ``s`` = string being parsed + - ``loc`` = location where expression match was attempted and failed + - ``expr`` = the parse expression that failed + - ``err`` = the exception thrown The function returns no value. It may throw :class:`ParseFatalException` if it is desired to stop parsing immediately.""" self.failAction = fn return self - def _skipIgnorables(self, instring, loc): + def _skipIgnorables(self, instring: str, loc: int) -> int: + if not self.ignoreExprs: + return loc exprsFound = True + ignore_expr_fns = [e._parse for e in self.ignoreExprs] while exprsFound: exprsFound = False - for e in self.ignoreExprs: + for ignore_fn in ignore_expr_fns: try: while 1: - loc, dummy = e._parse(instring, loc) + loc, dummy = ignore_fn(instring, loc) exprsFound = True except ParseException: pass return loc - def preParse(self, instring, loc): + def preParse(self, instring: str, loc: int) -> int: if self.ignoreExprs: loc = self._skipIgnorables(instring, loc) @@ -830,7 +858,7 @@ class ParserElement(ABC): try: for fn in self.parseAction: try: - tokens = fn(instring, tokens_start, ret_tokens) + tokens = fn(instring, tokens_start, ret_tokens) # type: ignore [call-arg, arg-type] except IndexError as parse_action_exc: exc = ParseException("exception raised in parse action") raise exc from parse_action_exc @@ -853,7 +881,7 @@ class ParserElement(ABC): else: for fn in self.parseAction: try: - tokens = fn(instring, tokens_start, ret_tokens) + tokens = fn(instring, tokens_start, ret_tokens) # type: ignore [call-arg, arg-type] except IndexError as parse_action_exc: exc = ParseException("exception raised in parse action") raise exc from parse_action_exc @@ -875,17 +903,24 @@ class ParserElement(ABC): return loc, ret_tokens - def try_parse(self, instring: str, loc: int, raise_fatal: bool = False) -> int: + def try_parse( + self, + instring: str, + loc: int, + *, + raise_fatal: bool = False, + do_actions: bool = False, + ) -> int: try: - return self._parse(instring, loc, doActions=False)[0] + return self._parse(instring, loc, doActions=do_actions)[0] except ParseFatalException: if raise_fatal: raise raise ParseException(instring, loc, self.errmsg, self) - def can_parse_next(self, instring: str, loc: int) -> bool: + def can_parse_next(self, instring: str, loc: int, do_actions: bool = False) -> bool: try: - self.try_parse(instring, loc) + self.try_parse(instring, loc, do_actions=do_actions) except (ParseException, IndexError): return False else: @@ -897,10 +932,23 @@ class ParserElement(ABC): Tuple[int, "Forward", bool], Tuple[int, Union[ParseResults, Exception]] ] = {} + class _CacheType(dict): + """ + class to help type checking + """ + + not_in_cache: bool + + def get(self, *args): + ... + + def set(self, *args): + ... + # argument cache for optimizing repeated calls when backtracking through recursive expressions packrat_cache = ( - {} - ) # this is set later by enabled_packrat(); this is here so that reset_cache() doesn't fail + _CacheType() + ) # set later by enable_packrat(); this is here so that reset_cache() doesn't fail packrat_cache_lock = RLock() packrat_cache_stats = [0, 0] @@ -930,24 +978,25 @@ class ParserElement(ABC): ParserElement.packrat_cache_stats[HIT] += 1 if self.debug and self.debugActions.debug_try: try: - self.debugActions.debug_try(instring, loc, self, cache_hit=True) + self.debugActions.debug_try(instring, loc, self, cache_hit=True) # type: ignore [call-arg] except TypeError: pass if isinstance(value, Exception): if self.debug and self.debugActions.debug_fail: try: self.debugActions.debug_fail( - instring, loc, self, value, cache_hit=True + instring, loc, self, value, cache_hit=True # type: ignore [call-arg] ) except TypeError: pass raise value + value = cast(Tuple[int, ParseResults, int], value) loc_, result, endloc = value[0], value[1].copy(), value[2] if self.debug and self.debugActions.debug_match: try: self.debugActions.debug_match( - instring, loc_, endloc, self, result, cache_hit=True + instring, loc_, endloc, self, result, cache_hit=True # type: ignore [call-arg] ) except TypeError: pass @@ -1009,7 +1058,7 @@ class ParserElement(ABC): Parameters: - - cache_size_limit - (default=``None``) - memoize at most this many + - ``cache_size_limit`` - (default=``None``) - memoize at most this many ``Forward`` elements during matching; if ``None`` (the default), memoize all ``Forward`` elements. @@ -1022,9 +1071,9 @@ class ParserElement(ABC): elif ParserElement._packratEnabled: raise RuntimeError("Packrat and Bounded Recursion are not compatible") if cache_size_limit is None: - ParserElement.recursion_memos = _UnboundedMemo() + ParserElement.recursion_memos = _UnboundedMemo() # type: ignore[assignment] elif cache_size_limit > 0: - ParserElement.recursion_memos = _LRUMemo(capacity=cache_size_limit) + ParserElement.recursion_memos = _LRUMemo(capacity=cache_size_limit) # type: ignore[assignment] else: raise NotImplementedError("Memo size of %s" % cache_size_limit) ParserElement._left_recursion_enabled = True @@ -1040,7 +1089,7 @@ class ParserElement(ABC): Parameters: - - cache_size_limit - (default= ``128``) - if an integer value is provided + - ``cache_size_limit`` - (default= ``128``) - if an integer value is provided will limit the size of the packrat cache; if None is passed, then the cache size will be unbounded; if 0 is passed, the cache will be effectively disabled. @@ -1070,7 +1119,7 @@ class ParserElement(ABC): if cache_size_limit is None: ParserElement.packrat_cache = _UnboundedCache() else: - ParserElement.packrat_cache = _FifoCache(cache_size_limit) + ParserElement.packrat_cache = _FifoCache(cache_size_limit) # type: ignore[assignment] ParserElement._parse = ParserElement._parseCache def parse_string( @@ -1088,7 +1137,7 @@ class ParserElement(ABC): an object with attributes if the given parser includes results names. If the input string is required to match the entire grammar, ``parse_all`` flag must be set to ``True``. This - is also equivalent to ending the grammar with :class:`StringEnd`(). + is also equivalent to ending the grammar with :class:`StringEnd`\\ (). To report proper column numbers, ``parse_string`` operates on a copy of the input string where all tabs are converted to spaces (8 spaces per tab, as per the default in ``string.expandtabs``). If the input string @@ -1198,7 +1247,9 @@ class ParserElement(ABC): try: while loc <= instrlen and matches < maxMatches: try: - preloc = preparseFn(instring, loc) + preloc: int = preparseFn(instring, loc) + nextLoc: int + tokens: ParseResults nextLoc, tokens = parseFn(instring, preloc, callPreParse=False) except ParseException: loc = preloc + 1 @@ -1352,7 +1403,7 @@ class ParserElement(ABC): def __add__(self, other) -> "ParserElement": """ Implementation of ``+`` operator - returns :class:`And`. Adding strings to a :class:`ParserElement` - converts them to :class:`Literal`s by default. + converts them to :class:`Literal`\\ s by default. Example:: @@ -1364,11 +1415,11 @@ class ParserElement(ABC): Hello, World! -> ['Hello', ',', 'World', '!'] - ``...`` may be used as a parse expression as a short form of :class:`SkipTo`. + ``...`` may be used as a parse expression as a short form of :class:`SkipTo`:: Literal('start') + ... + Literal('end') - is equivalent to: + is equivalent to:: Literal('start') + SkipTo('end')("_skipped*") + Literal('end') @@ -1382,11 +1433,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return And([self, other]) def __radd__(self, other) -> "ParserElement": @@ -1399,11 +1446,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return other + self def __sub__(self, other) -> "ParserElement": @@ -1413,11 +1456,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return self + And._ErrorStop() + other def __rsub__(self, other) -> "ParserElement": @@ -1427,11 +1466,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return other - self def __mul__(self, other) -> "ParserElement": @@ -1440,11 +1475,12 @@ class ParserElement(ABC): ``expr + expr + expr``. Expressions may also be multiplied by a 2-integer tuple, similar to ``{min, max}`` multipliers in regular expressions. Tuples may also include ``None`` as in: + - ``expr*(n, None)`` or ``expr*(n, )`` is equivalent - to ``expr*n + ZeroOrMore(expr)`` - (read as "at least n instances of ``expr``") + to ``expr*n + ZeroOrMore(expr)`` + (read as "at least n instances of ``expr``") - ``expr*(None, n)`` is equivalent to ``expr*(0, n)`` - (read as "0 to n instances of ``expr``") + (read as "0 to n instances of ``expr``") - ``expr*(None, None)`` is equivalent to ``ZeroOrMore(expr)`` - ``expr*(1, None)`` is equivalent to ``OneOrMore(expr)`` @@ -1477,17 +1513,9 @@ class ParserElement(ABC): minElements, optElements = other optElements -= minElements else: - raise TypeError( - "cannot multiply ParserElement and ({}) objects".format( - ",".join(type(item).__name__ for item in other) - ) - ) + return NotImplemented else: - raise TypeError( - "cannot multiply ParserElement and {} objects".format( - type(other).__name__ - ) - ) + return NotImplemented if minElements < 0: raise ValueError("cannot multiply ParserElement by negative value") @@ -1531,13 +1559,12 @@ class ParserElement(ABC): return _PendingSkip(self, must_skip=True) if isinstance(other, str_type): + # `expr | ""` is equivalent to `Opt(expr)` + if other == "": + return Opt(self) other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return MatchFirst([self, other]) def __ror__(self, other) -> "ParserElement": @@ -1547,11 +1574,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return other | self def __xor__(self, other) -> "ParserElement": @@ -1561,11 +1584,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return Or([self, other]) def __rxor__(self, other) -> "ParserElement": @@ -1575,11 +1594,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return other ^ self def __and__(self, other) -> "ParserElement": @@ -1589,11 +1604,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return Each([self, other]) def __rand__(self, other) -> "ParserElement": @@ -1603,11 +1614,7 @@ class ParserElement(ABC): if isinstance(other, str_type): other = self._literalStringClass(other) if not isinstance(other, ParserElement): - raise TypeError( - "Cannot combine element of type {} with ParserElement".format( - type(other).__name__ - ) - ) + return NotImplemented return other & self def __invert__(self) -> "ParserElement": @@ -1636,38 +1643,58 @@ class ParserElement(ABC): ``None`` may be used in place of ``...``. - Note that ``expr[..., n]`` and ``expr[m, n]``do not raise an exception - if more than ``n`` ``expr``s exist in the input stream. If this behavior is + Note that ``expr[..., n]`` and ``expr[m, n]`` do not raise an exception + if more than ``n`` ``expr``\\ s exist in the input stream. If this behavior is desired, then write ``expr[..., n] + ~expr``. + + For repetition with a stop_on expression, use slice notation: + + - ``expr[...: end_expr]`` and ``expr[0, ...: end_expr]`` are equivalent to ``ZeroOrMore(expr, stop_on=end_expr)`` + - ``expr[1, ...: end_expr]`` is equivalent to ``OneOrMore(expr, stop_on=end_expr)`` + """ + stop_on_defined = False + stop_on = NoMatch() + if isinstance(key, slice): + key, stop_on = key.start, key.stop + if key is None: + key = ... + stop_on_defined = True + elif isinstance(key, tuple) and isinstance(key[-1], slice): + key, stop_on = (key[0], key[1].start), key[1].stop + stop_on_defined = True + # convert single arg keys to tuples + if isinstance(key, str_type): + key = (key,) try: - if isinstance(key, str_type): - key = (key,) iter(key) except TypeError: key = (key, key) if len(key) > 2: raise TypeError( - "only 1 or 2 index arguments supported ({}{})".format( - key[:5], "... [{}]".format(len(key)) if len(key) > 5 else "" - ) + f"only 1 or 2 index arguments supported ({key[:5]}{f'... [{len(key)}]' if len(key) > 5 else ''})" ) # clip to 2 elements ret = self * tuple(key[:2]) + ret = typing.cast(_MultipleMatch, ret) + + if stop_on_defined: + ret.stopOn(stop_on) + return ret - def __call__(self, name: str = None) -> "ParserElement": + def __call__(self, name: typing.Optional[str] = None) -> "ParserElement": """ Shortcut for :class:`set_results_name`, with ``list_all_matches=False``. If ``name`` is given with a trailing ``'*'`` character, then ``list_all_matches`` will be passed as ``True``. - If ``name` is omitted, same as calling :class:`copy`. + If ``name`` is omitted, same as calling :class:`copy`. Example:: @@ -1775,17 +1802,18 @@ class ParserElement(ABC): should have the signature ``fn(input_string: str, location: int, expression: ParserElement, exception: Exception, cache_hit: bool)`` """ self.debugActions = self.DebugActions( - start_action or _default_start_debug_action, - success_action or _default_success_debug_action, - exception_action or _default_exception_debug_action, + start_action or _default_start_debug_action, # type: ignore[truthy-function] + success_action or _default_success_debug_action, # type: ignore[truthy-function] + exception_action or _default_exception_debug_action, # type: ignore[truthy-function] ) self.debug = True return self - def set_debug(self, flag: bool = True) -> "ParserElement": + def set_debug(self, flag: bool = True, recurse: bool = False) -> "ParserElement": """ Enable display of debugging messages while doing pattern matching. Set ``flag`` to ``True`` to enable, ``False`` to disable. + Set ``recurse`` to ``True`` to set the debug flag on this expression and all sub-expressions. Example:: @@ -1819,6 +1847,11 @@ class ParserElement(ABC): which makes debugging and exception messages easier to understand - for instance, the default name created for the :class:`Word` expression without calling ``set_name`` is ``"W:(A-Za-z)"``. """ + if recurse: + for expr in self.visit_all(): + expr.set_debug(flag, recurse=False) + return self + if flag: self.set_debug_actions( _default_start_debug_action, @@ -1836,7 +1869,7 @@ class ParserElement(ABC): return self._defaultName @abstractmethod - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: """ Child classes must define this method, which defines how the ``default_name`` is set. """ @@ -1844,7 +1877,9 @@ class ParserElement(ABC): def set_name(self, name: str) -> "ParserElement": """ Define name for this expression, makes debugging and exception messages clearer. + Example:: + Word(nums).parse_string("ABC") # -> Exception: Expected W:(0-9) (at char 0), (line:1, col:1) Word(nums).set_name("integer").parse_string("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) """ @@ -1870,7 +1905,7 @@ class ParserElement(ABC): self._defaultName = None return self - def recurse(self) -> Sequence["ParserElement"]: + def recurse(self) -> List["ParserElement"]: return [] def _checkRecursion(self, parseElementList): @@ -1882,6 +1917,11 @@ class ParserElement(ABC): """ Check defined expressions for valid structure, check for infinite recursive definitions. """ + warnings.warn( + "ParserElement.validate() is deprecated, and should not be used to check for left recursion", + DeprecationWarning, + stacklevel=2, + ) self._checkRecursion([]) def parse_file( @@ -1899,8 +1939,10 @@ class ParserElement(ABC): """ parseAll = parseAll or parse_all try: + file_or_filename = typing.cast(TextIO, file_or_filename) file_contents = file_or_filename.read() except AttributeError: + file_or_filename = typing.cast(str, file_or_filename) with open(file_or_filename, "r", encoding=encoding) as f: file_contents = f.read() try: @@ -1932,6 +1974,7 @@ class ParserElement(ABC): inline microtests of sub expressions while building up larger parser. Parameters: + - ``test_string`` - to test against this expression for a match - ``parse_all`` - (default= ``True``) - flag to pass to :class:`parse_string` when running tests @@ -1955,7 +1998,7 @@ class ParserElement(ABC): full_dump: bool = True, print_results: bool = True, failure_tests: bool = False, - post_parse: Callable[[str, ParseResults], str] = None, + post_parse: typing.Optional[Callable[[str, ParseResults], str]] = None, file: typing.Optional[TextIO] = None, with_line_numbers: bool = False, *, @@ -1963,7 +2006,7 @@ class ParserElement(ABC): fullDump: bool = True, printResults: bool = True, failureTests: bool = False, - postParse: Callable[[str, ParseResults], str] = None, + postParse: typing.Optional[Callable[[str, ParseResults], str]] = None, ) -> Tuple[bool, List[Tuple[str, Union[ParseResults, Exception]]]]: """ Execute the parse expression on a series of test strings, showing each @@ -1971,6 +2014,7 @@ class ParserElement(ABC): run a parse expression against a list of sample strings. Parameters: + - ``tests`` - a list of separate test strings, or a multiline string of test strings - ``parse_all`` - (default= ``True``) - flag to pass to :class:`parse_string` when running tests - ``comment`` - (default= ``'#'``) - expression for indicating embedded comments in the test @@ -2067,22 +2111,27 @@ class ParserElement(ABC): failureTests = failureTests or failure_tests postParse = postParse or post_parse if isinstance(tests, str_type): + tests = typing.cast(str, tests) line_strip = type(tests).strip tests = [line_strip(test_line) for test_line in tests.rstrip().splitlines()] - if isinstance(comment, str_type): - comment = Literal(comment) + comment_specified = comment is not None + if comment_specified: + if isinstance(comment, str_type): + comment = typing.cast(str, comment) + comment = Literal(comment) + comment = typing.cast(ParserElement, comment) if file is None: file = sys.stdout print_ = file.write result: Union[ParseResults, Exception] - allResults = [] - comments = [] + allResults: List[Tuple[str, Union[ParseResults, Exception]]] = [] + comments: List[str] = [] success = True NL = Literal(r"\n").add_parse_action(replace_with("\n")).ignore(quoted_string) BOM = "\ufeff" for t in tests: - if comment is not None and comment.matches(t, False) or comments and not t: + if comment_specified and comment.matches(t, False) or comments and not t: comments.append( pyparsing_test.with_line_numbers(t) if with_line_numbers else t ) @@ -2107,7 +2156,7 @@ class ParserElement(ABC): success = success and failureTests result = pe except Exception as exc: - out.append("FAIL-EXCEPTION: {}: {}".format(type(exc).__name__, exc)) + out.append(f"FAIL-EXCEPTION: {type(exc).__name__}: {exc}") if ParserElement.verbose_stacktrace: out.extend(traceback.format_tb(exc.__traceback__)) success = success and failureTests @@ -2127,9 +2176,7 @@ class ParserElement(ABC): except Exception as e: out.append(result.dump(full=fullDump)) out.append( - "{} failed: {}: {}".format( - postParse.__name__, type(e).__name__, e - ) + f"{postParse.__name__} failed: {type(e).__name__}: {e}" ) else: out.append(result.dump(full=fullDump)) @@ -2148,19 +2195,28 @@ class ParserElement(ABC): vertical: int = 3, show_results_names: bool = False, show_groups: bool = False, + embed: bool = False, **kwargs, ) -> None: """ Create a railroad diagram for the parser. Parameters: - - output_html (str or file-like object) - output target for generated + + - ``output_html`` (str or file-like object) - output target for generated diagram HTML - - vertical (int) - threshold for formatting multiple alternatives vertically + - ``vertical`` (int) - threshold for formatting multiple alternatives vertically instead of horizontally (default=3) - - show_results_names - bool flag whether diagram should show annotations for + - ``show_results_names`` - bool flag whether diagram should show annotations for defined results names - - show_groups - bool flag whether groups should be highlighted with an unlabeled surrounding box + - ``show_groups`` - bool flag whether groups should be highlighted with an unlabeled surrounding box + - ``embed`` - bool flag whether generated HTML should omit , , and tags to embed + the resulting HTML in an enclosing HTML source + - ``head`` - str containing additional HTML to insert into the section of the generated code; + can be used to insert custom CSS styling + - ``body`` - str containing additional HTML to insert at the beginning of the section of the + generated code + Additional diagram-formatting keyword arguments can also be included; see railroad.Diagram class. """ @@ -2183,38 +2239,93 @@ class ParserElement(ABC): ) if isinstance(output_html, (str, Path)): with open(output_html, "w", encoding="utf-8") as diag_file: - diag_file.write(railroad_to_html(railroad)) + diag_file.write(railroad_to_html(railroad, embed=embed, **kwargs)) else: # we were passed a file-like object, just write to it - output_html.write(railroad_to_html(railroad)) - - setDefaultWhitespaceChars = set_default_whitespace_chars - inlineLiteralsUsing = inline_literals_using - setResultsName = set_results_name - setBreak = set_break - setParseAction = set_parse_action - addParseAction = add_parse_action - addCondition = add_condition - setFailAction = set_fail_action - tryParse = try_parse + output_html.write(railroad_to_html(railroad, embed=embed, **kwargs)) + + # Compatibility synonyms + # fmt: off + @staticmethod + @replaced_by_pep8(inline_literals_using) + def inlineLiteralsUsing(): ... + + @staticmethod + @replaced_by_pep8(set_default_whitespace_chars) + def setDefaultWhitespaceChars(): ... + + @replaced_by_pep8(set_results_name) + def setResultsName(self): ... + + @replaced_by_pep8(set_break) + def setBreak(self): ... + + @replaced_by_pep8(set_parse_action) + def setParseAction(self): ... + + @replaced_by_pep8(add_parse_action) + def addParseAction(self): ... + + @replaced_by_pep8(add_condition) + def addCondition(self): ... + + @replaced_by_pep8(set_fail_action) + def setFailAction(self): ... + + @replaced_by_pep8(try_parse) + def tryParse(self): ... + + @staticmethod + @replaced_by_pep8(enable_left_recursion) + def enableLeftRecursion(): ... + + @staticmethod + @replaced_by_pep8(enable_packrat) + def enablePackrat(): ... + + @replaced_by_pep8(parse_string) + def parseString(self): ... + + @replaced_by_pep8(scan_string) + def scanString(self): ... + + @replaced_by_pep8(transform_string) + def transformString(self): ... + + @replaced_by_pep8(search_string) + def searchString(self): ... + + @replaced_by_pep8(ignore_whitespace) + def ignoreWhitespace(self): ... + + @replaced_by_pep8(leave_whitespace) + def leaveWhitespace(self): ... + + @replaced_by_pep8(set_whitespace_chars) + def setWhitespaceChars(self): ... + + @replaced_by_pep8(parse_with_tabs) + def parseWithTabs(self): ... + + @replaced_by_pep8(set_debug_actions) + def setDebugActions(self): ... + + @replaced_by_pep8(set_debug) + def setDebug(self): ... + + @replaced_by_pep8(set_name) + def setName(self): ... + + @replaced_by_pep8(parse_file) + def parseFile(self): ... + + @replaced_by_pep8(run_tests) + def runTests(self): ... + canParseNext = can_parse_next resetCache = reset_cache - enableLeftRecursion = enable_left_recursion - enablePackrat = enable_packrat - parseString = parse_string - scanString = scan_string - searchString = search_string - transformString = transform_string - setWhitespaceChars = set_whitespace_chars - parseWithTabs = parse_with_tabs - setDebugActions = set_debug_actions - setDebug = set_debug defaultName = default_name - setName = set_name - parseFile = parse_file - runTests = run_tests - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace + # fmt: on class _PendingSkip(ParserElement): @@ -2225,7 +2336,7 @@ class _PendingSkip(ParserElement): self.anchor = expr self.must_skip = must_skip - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return str(self.anchor + Empty()).replace("Empty", "...") def __add__(self, other) -> "ParserElement": @@ -2266,21 +2377,10 @@ class Token(ParserElement): def __init__(self): super().__init__(savelist=False) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return type(self).__name__ -class Empty(Token): - """ - An empty token, will always match. - """ - - def __init__(self): - super().__init__() - self.mayReturnEmpty = True - self.mayIndexError = False - - class NoMatch(Token): """ A token that will never match. @@ -2312,25 +2412,33 @@ class Literal(Token): use :class:`Keyword` or :class:`CaselessKeyword`. """ + def __new__(cls, match_string: str = "", *, matchString: str = ""): + # Performance tuning: select a subclass with optimized parseImpl + if cls is Literal: + match_string = matchString or match_string + if not match_string: + return super().__new__(Empty) + if len(match_string) == 1: + return super().__new__(_SingleCharLiteral) + + # Default behavior + return super().__new__(cls) + + # Needed to make copy.copy() work correctly if we customize __new__ + def __getnewargs__(self): + return (self.match,) + def __init__(self, match_string: str = "", *, matchString: str = ""): super().__init__() match_string = matchString or match_string self.match = match_string self.matchLen = len(match_string) - try: - self.firstMatchChar = match_string[0] - except IndexError: - raise ValueError("null string passed to Literal; use Empty() instead") + self.firstMatchChar = match_string[:1] self.errmsg = "Expected " + self.name self.mayReturnEmpty = False self.mayIndexError = False - # Performance tuning: modify __class__ to select - # a parseImpl optimized for single-character check - if self.matchLen == 1 and type(self) is Literal: - self.__class__ = _SingleCharLiteral - - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return repr(self.match) def parseImpl(self, instring, loc, doActions=True): @@ -2341,6 +2449,23 @@ class Literal(Token): raise ParseException(instring, loc, self.errmsg, self) +class Empty(Literal): + """ + An empty token, will always match. + """ + + def __init__(self, match_string="", *, matchString=""): + super().__init__("") + self.mayReturnEmpty = True + self.mayIndexError = False + + def _generateDefaultName(self) -> str: + return "Empty" + + def parseImpl(self, instring, loc, doActions=True): + return loc, [] + + class _SingleCharLiteral(Literal): def parseImpl(self, instring, loc, doActions=True): if instring[loc] == self.firstMatchChar: @@ -2354,8 +2479,8 @@ ParserElement._literalStringClass = Literal class Keyword(Token): """ Token to exactly match a specified string as a keyword, that is, - it must be immediately followed by a non-keyword character. Compare - with :class:`Literal`: + it must be immediately preceded and followed by whitespace or + non-keyword characters. Compare with :class:`Literal`: - ``Literal("if")`` will match the leading ``'if'`` in ``'ifAndOnlyIf'``. @@ -2365,7 +2490,7 @@ class Keyword(Token): Accepts two optional constructor arguments in addition to the keyword string: - - ``identChars`` is a string of characters that would be valid + - ``ident_chars`` is a string of characters that would be valid identifier characters, defaulting to all alphanumerics + "_" and "$" - ``caseless`` allows case-insensitive matching, default is ``False``. @@ -2400,7 +2525,7 @@ class Keyword(Token): self.firstMatchChar = match_string[0] except IndexError: raise ValueError("null string passed to Keyword; use Empty() instead") - self.errmsg = "Expected {} {}".format(type(self).__name__, self.name) + self.errmsg = f"Expected {type(self).__name__} {self.name}" self.mayReturnEmpty = False self.mayIndexError = False self.caseless = caseless @@ -2409,7 +2534,7 @@ class Keyword(Token): identChars = identChars.upper() self.identChars = set(identChars) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return repr(self.match) def parseImpl(self, instring, loc, doActions=True): @@ -2559,7 +2684,7 @@ class CloseMatch(Token): def __init__( self, match_string: str, - max_mismatches: int = None, + max_mismatches: typing.Optional[int] = None, *, maxMismatches: int = 1, caseless=False, @@ -2568,15 +2693,13 @@ class CloseMatch(Token): super().__init__() self.match_string = match_string self.maxMismatches = maxMismatches - self.errmsg = "Expected {!r} (with up to {} mismatches)".format( - self.match_string, self.maxMismatches - ) + self.errmsg = f"Expected {self.match_string!r} (with up to {self.maxMismatches} mismatches)" self.caseless = caseless self.mayIndexError = False self.mayReturnEmpty = False - def _generateDefaultName(self): - return "{}:{!r}".format(type(self).__name__, self.match_string) + def _generateDefaultName(self) -> str: + return f"{type(self).__name__}:{self.match_string!r}" def parseImpl(self, instring, loc, doActions=True): start = loc @@ -2612,7 +2735,9 @@ class CloseMatch(Token): class Word(Token): """Token for matching words composed of allowed character sets. + Parameters: + - ``init_chars`` - string of all characters that should be used to match as a word; "ABC" will match "AAA", "ABAB", "CBAC", etc.; if ``body_chars`` is also specified, then this is the string of @@ -2697,26 +2822,24 @@ class Word(Token): super().__init__() if not initChars: raise ValueError( - "invalid {}, initChars cannot be empty string".format( - type(self).__name__ - ) + f"invalid {type(self).__name__}, initChars cannot be empty string" ) - initChars = set(initChars) - self.initChars = initChars + initChars_set = set(initChars) if excludeChars: - excludeChars = set(excludeChars) - initChars -= excludeChars + excludeChars_set = set(excludeChars) + initChars_set -= excludeChars_set if bodyChars: - bodyChars = set(bodyChars) - excludeChars - self.initCharsOrig = "".join(sorted(initChars)) + bodyChars = "".join(set(bodyChars) - excludeChars_set) + self.initChars = initChars_set + self.initCharsOrig = "".join(sorted(initChars_set)) if bodyChars: - self.bodyCharsOrig = "".join(sorted(bodyChars)) self.bodyChars = set(bodyChars) + self.bodyCharsOrig = "".join(sorted(bodyChars)) else: - self.bodyCharsOrig = "".join(sorted(initChars)) - self.bodyChars = set(initChars) + self.bodyChars = initChars_set + self.bodyCharsOrig = self.initCharsOrig self.maxSpecified = max > 0 @@ -2725,6 +2848,11 @@ class Word(Token): "cannot specify a minimum length < 1; use Opt(Word()) if zero-length word is permitted" ) + if self.maxSpecified and min > max: + raise ValueError( + f"invalid args, if min and max both specified min must be <= max (min={min}, max={max})" + ) + self.minLen = min if max > 0: @@ -2733,62 +2861,66 @@ class Word(Token): self.maxLen = _MAX_INT if exact > 0: + min = max = exact self.maxLen = exact self.minLen = exact self.errmsg = "Expected " + self.name self.mayIndexError = False self.asKeyword = asKeyword + if self.asKeyword: + self.errmsg += " as a keyword" # see if we can make a regex for this Word - if " " not in self.initChars | self.bodyChars and (min == 1 and exact == 0): + if " " not in (self.initChars | self.bodyChars): + if len(self.initChars) == 1: + re_leading_fragment = re.escape(self.initCharsOrig) + else: + re_leading_fragment = f"[{_collapse_string_to_ranges(self.initChars)}]" + if self.bodyChars == self.initChars: if max == 0: repeat = "+" elif max == 1: repeat = "" else: - repeat = "{{{},{}}}".format( - self.minLen, "" if self.maxLen == _MAX_INT else self.maxLen - ) - self.reString = "[{}]{}".format( - _collapse_string_to_ranges(self.initChars), - repeat, - ) - elif len(self.initChars) == 1: - if max == 0: - repeat = "*" - else: - repeat = "{{0,{}}}".format(max - 1) - self.reString = "{}[{}]{}".format( - re.escape(self.initCharsOrig), - _collapse_string_to_ranges(self.bodyChars), - repeat, - ) + if self.minLen != self.maxLen: + repeat = f"{{{self.minLen},{'' if self.maxLen == _MAX_INT else self.maxLen}}}" + else: + repeat = f"{{{self.minLen}}}" + self.reString = f"{re_leading_fragment}{repeat}" else: - if max == 0: - repeat = "*" - elif max == 2: + if max == 1: + re_body_fragment = "" repeat = "" else: - repeat = "{{0,{}}}".format(max - 1) - self.reString = "[{}][{}]{}".format( - _collapse_string_to_ranges(self.initChars), - _collapse_string_to_ranges(self.bodyChars), - repeat, + re_body_fragment = f"[{_collapse_string_to_ranges(self.bodyChars)}]" + if max == 0: + repeat = "*" + elif max == 2: + repeat = "?" if min <= 1 else "" + else: + if min != max: + repeat = f"{{{min - 1 if min > 0 else 0},{max - 1}}}" + else: + repeat = f"{{{min - 1 if min > 0 else 0}}}" + + self.reString = ( + f"{re_leading_fragment}" f"{re_body_fragment}" f"{repeat}" ) + if self.asKeyword: - self.reString = r"\b" + self.reString + r"\b" + self.reString = rf"\b{self.reString}\b" try: self.re = re.compile(self.reString) except re.error: - self.re = None + self.re = None # type: ignore[assignment] else: self.re_match = self.re.match - self.__class__ = _WordRegex + self.parseImpl = self.parseImpl_regex # type: ignore[assignment] - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: def charsAsStr(s): max_repr_len = 16 s = _collapse_string_to_ranges(s, re_escape=False) @@ -2798,11 +2930,9 @@ class Word(Token): return s if self.initChars != self.bodyChars: - base = "W:({}, {})".format( - charsAsStr(self.initChars), charsAsStr(self.bodyChars) - ) + base = f"W:({charsAsStr(self.initChars)}, {charsAsStr(self.bodyChars)})" else: - base = "W:({})".format(charsAsStr(self.initChars)) + base = f"W:({charsAsStr(self.initChars)})" # add length specification if self.minLen > 1 or self.maxLen != _MAX_INT: @@ -2810,11 +2940,11 @@ class Word(Token): if self.minLen == 1: return base[2:] else: - return base + "{{{}}}".format(self.minLen) + return base + f"{{{self.minLen}}}" elif self.maxLen == _MAX_INT: - return base + "{{{},...}}".format(self.minLen) + return base + f"{{{self.minLen},...}}" else: - return base + "{{{},{}}}".format(self.minLen, self.maxLen) + return base + f"{{{self.minLen},{self.maxLen}}}" return base def parseImpl(self, instring, loc, doActions=True): @@ -2849,9 +2979,7 @@ class Word(Token): return loc, instring[start:loc] - -class _WordRegex(Word): - def parseImpl(self, instring, loc, doActions=True): + def parseImpl_regex(self, instring, loc, doActions=True): result = self.re_match(instring, loc) if not result: raise ParseException(instring, loc, self.errmsg, self) @@ -2860,7 +2988,7 @@ class _WordRegex(Word): return loc, result.group() -class Char(_WordRegex): +class Char(Word): """A short-cut class for defining :class:`Word` ``(characters, exact=1)``, when defining a match of any single character in a string of characters. @@ -2878,13 +3006,8 @@ class Char(_WordRegex): asKeyword = asKeyword or as_keyword excludeChars = excludeChars or exclude_chars super().__init__( - charset, exact=1, asKeyword=asKeyword, excludeChars=excludeChars + charset, exact=1, as_keyword=asKeyword, exclude_chars=excludeChars ) - self.reString = "[{}]".format(_collapse_string_to_ranges(self.initChars)) - if asKeyword: - self.reString = r"\b{}\b".format(self.reString) - self.re = re.compile(self.reString) - self.re_match = self.re.match class Regex(Token): @@ -2954,9 +3077,9 @@ class Regex(Token): self.asGroupList = asGroupList self.asMatch = asMatch if self.asGroupList: - self.parseImpl = self.parseImplAsGroupList + self.parseImpl = self.parseImplAsGroupList # type: ignore [assignment] if self.asMatch: - self.parseImpl = self.parseImplAsMatch + self.parseImpl = self.parseImplAsMatch # type: ignore [assignment] @cached_property def re(self): @@ -2966,9 +3089,7 @@ class Regex(Token): try: return re.compile(self.pattern, self.flags) except re.error: - raise ValueError( - "invalid pattern ({!r}) passed to Regex".format(self.pattern) - ) + raise ValueError(f"invalid pattern ({self.pattern!r}) passed to Regex") @cached_property def re_match(self): @@ -2978,7 +3099,7 @@ class Regex(Token): def mayReturnEmpty(self): return self.re_match("") is not None - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "Re:({})".format(repr(self.pattern).replace("\\\\", "\\")) def parseImpl(self, instring, loc, doActions=True): @@ -3024,10 +3145,12 @@ class Regex(Token): # prints "

main title

" """ if self.asGroupList: - raise TypeError("cannot use sub() with Regex(asGroupList=True)") + raise TypeError("cannot use sub() with Regex(as_group_list=True)") if self.asMatch and callable(repl): - raise TypeError("cannot use sub() with a callable with Regex(asMatch=True)") + raise TypeError( + "cannot use sub() with a callable with Regex(as_match=True)" + ) if self.asMatch: @@ -3081,7 +3204,7 @@ class QuotedString(Token): [['This is the "quote"']] [['This is the quote with "embedded" quotes']] """ - ws_map = ((r"\t", "\t"), (r"\n", "\n"), (r"\f", "\f"), (r"\r", "\r")) + ws_map = dict(((r"\t", "\t"), (r"\n", "\n"), (r"\f", "\f"), (r"\r", "\r"))) def __init__( self, @@ -3120,57 +3243,54 @@ class QuotedString(Token): else: endQuoteChar = endQuoteChar.strip() if not endQuoteChar: - raise ValueError("endQuoteChar cannot be the empty string") - - self.quoteChar = quote_char - self.quoteCharLen = len(quote_char) - self.firstQuoteChar = quote_char[0] - self.endQuoteChar = endQuoteChar - self.endQuoteCharLen = len(endQuoteChar) - self.escChar = escChar - self.escQuote = escQuote - self.unquoteResults = unquoteResults - self.convertWhitespaceEscapes = convertWhitespaceEscapes + raise ValueError("end_quote_char cannot be the empty string") + + self.quoteChar: str = quote_char + self.quoteCharLen: int = len(quote_char) + self.firstQuoteChar: str = quote_char[0] + self.endQuoteChar: str = endQuoteChar + self.endQuoteCharLen: int = len(endQuoteChar) + self.escChar: str = escChar or "" + self.escQuote: str = escQuote or "" + self.unquoteResults: bool = unquoteResults + self.convertWhitespaceEscapes: bool = convertWhitespaceEscapes + self.multiline = multiline sep = "" inner_pattern = "" if escQuote: - inner_pattern += r"{}(?:{})".format(sep, re.escape(escQuote)) + inner_pattern += rf"{sep}(?:{re.escape(escQuote)})" sep = "|" if escChar: - inner_pattern += r"{}(?:{}.)".format(sep, re.escape(escChar)) + inner_pattern += rf"{sep}(?:{re.escape(escChar)}.)" sep = "|" - self.escCharReplacePattern = re.escape(self.escChar) + "(.)" + self.escCharReplacePattern = re.escape(escChar) + "(.)" if len(self.endQuoteChar) > 1: inner_pattern += ( - "{}(?:".format(sep) + f"{sep}(?:" + "|".join( - "(?:{}(?!{}))".format( - re.escape(self.endQuoteChar[:i]), - re.escape(self.endQuoteChar[i:]), - ) + f"(?:{re.escape(self.endQuoteChar[:i])}(?!{re.escape(self.endQuoteChar[i:])}))" for i in range(len(self.endQuoteChar) - 1, 0, -1) ) + ")" ) sep = "|" + self.flags = re.RegexFlag(0) + if multiline: self.flags = re.MULTILINE | re.DOTALL - inner_pattern += r"{}(?:[^{}{}])".format( - sep, - _escape_regex_range_chars(self.endQuoteChar[0]), - (_escape_regex_range_chars(escChar) if escChar is not None else ""), + inner_pattern += ( + rf"{sep}(?:[^{_escape_regex_range_chars(self.endQuoteChar[0])}" + rf"{(_escape_regex_range_chars(escChar) if escChar is not None else '')}])" ) else: - self.flags = 0 - inner_pattern += r"{}(?:[^{}\n\r{}])".format( - sep, - _escape_regex_range_chars(self.endQuoteChar[0]), - (_escape_regex_range_chars(escChar) if escChar is not None else ""), + inner_pattern += ( + rf"{sep}(?:[^{_escape_regex_range_chars(self.endQuoteChar[0])}\n\r" + rf"{(_escape_regex_range_chars(escChar) if escChar is not None else '')}])" ) self.pattern = "".join( @@ -3183,26 +3303,33 @@ class QuotedString(Token): ] ) + if self.unquoteResults: + if self.convertWhitespaceEscapes: + self.unquote_scan_re = re.compile( + rf"({'|'.join(re.escape(k) for k in self.ws_map)})|({re.escape(self.escChar)}.)|(\n|.)", + flags=self.flags, + ) + else: + self.unquote_scan_re = re.compile( + rf"({re.escape(self.escChar)}.)|(\n|.)", flags=self.flags + ) + try: self.re = re.compile(self.pattern, self.flags) self.reString = self.pattern self.re_match = self.re.match except re.error: - raise ValueError( - "invalid pattern {!r} passed to Regex".format(self.pattern) - ) + raise ValueError(f"invalid pattern {self.pattern!r} passed to Regex") self.errmsg = "Expected " + self.name self.mayIndexError = False self.mayReturnEmpty = True - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: if self.quoteChar == self.endQuoteChar and isinstance(self.quoteChar, str_type): - return "string enclosed in {!r}".format(self.quoteChar) + return f"string enclosed in {self.quoteChar!r}" - return "quoted string, starting with {} ending with {}".format( - self.quoteChar, self.endQuoteChar - ) + return f"quoted string, starting with {self.quoteChar} ending with {self.endQuoteChar}" def parseImpl(self, instring, loc, doActions=True): result = ( @@ -3217,19 +3344,24 @@ class QuotedString(Token): ret = result.group() if self.unquoteResults: - # strip off quotes ret = ret[self.quoteCharLen : -self.endQuoteCharLen] if isinstance(ret, str_type): - # replace escaped whitespace - if "\\" in ret and self.convertWhitespaceEscapes: - for wslit, wschar in self.ws_map: - ret = ret.replace(wslit, wschar) - - # replace escaped characters - if self.escChar: - ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + if self.convertWhitespaceEscapes: + ret = "".join( + self.ws_map[match.group(1)] + if match.group(1) + else match.group(2)[-1] + if match.group(2) + else match.group(3) + for match in self.unquote_scan_re.finditer(ret) + ) + else: + ret = "".join( + match.group(1)[-1] if match.group(1) else match.group(2) + for match in self.unquote_scan_re.finditer(ret) + ) # replace escaped quotes if self.escQuote: @@ -3252,7 +3384,7 @@ class CharsNotIn(Token): # define a comma-separated-value as anything that is not a ',' csv_value = CharsNotIn(',') - print(delimited_list(csv_value).parse_string("dkls,lsdkjf,s12 34,@!#,213")) + print(DelimitedList(csv_value).parse_string("dkls,lsdkjf,s12 34,@!#,213")) prints:: @@ -3294,12 +3426,12 @@ class CharsNotIn(Token): self.mayReturnEmpty = self.minLen == 0 self.mayIndexError = False - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: not_chars_str = _collapse_string_to_ranges(self.notChars) if len(not_chars_str) > 16: - return "!W:({}...)".format(self.notChars[: 16 - 3]) + return f"!W:({self.notChars[: 16 - 3]}...)" else: - return "!W:({})".format(self.notChars) + return f"!W:({self.notChars})" def parseImpl(self, instring, loc, doActions=True): notchars = self.notCharsSet @@ -3376,7 +3508,7 @@ class White(Token): self.maxLen = exact self.minLen = exact - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "".join(White.whiteStrs[c] for c in self.matchWhite) def parseImpl(self, instring, loc, doActions=True): @@ -3411,7 +3543,7 @@ class GoToColumn(PositionToken): super().__init__() self.col = colno - def preParse(self, instring, loc): + def preParse(self, instring: str, loc: int) -> int: if col(loc, instring) != self.col: instrlen = len(instring) if self.ignoreExprs: @@ -3446,7 +3578,7 @@ class LineStart(PositionToken): B AAA and definitely not this one ''' - for t in (LineStart() + 'AAA' + restOfLine).search_string(test): + for t in (LineStart() + 'AAA' + rest_of_line).search_string(test): print(t) prints:: @@ -3464,7 +3596,7 @@ class LineStart(PositionToken): self.skipper = Empty().set_whitespace_chars(self.whiteChars) self.errmsg = "Expected start of line" - def preParse(self, instring, loc): + def preParse(self, instring: str, loc: int) -> int: if loc == 0: return loc else: @@ -3624,7 +3756,7 @@ class ParseExpression(ParserElement): self.exprs = [exprs] self.callPreparse = False - def recurse(self) -> Sequence[ParserElement]: + def recurse(self) -> List[ParserElement]: return self.exprs[:] def append(self, other) -> ParserElement: @@ -3669,8 +3801,8 @@ class ParseExpression(ParserElement): e.ignore(self.ignoreExprs[-1]) return self - def _generateDefaultName(self): - return "{}:({})".format(self.__class__.__name__, str(self.exprs)) + def _generateDefaultName(self) -> str: + return f"{self.__class__.__name__}:({str(self.exprs)})" def streamline(self) -> ParserElement: if self.streamlined: @@ -3714,6 +3846,11 @@ class ParseExpression(ParserElement): return self def validate(self, validateTrace=None) -> None: + warnings.warn( + "ParserElement.validate() is deprecated, and should not be used to check for left recursion", + DeprecationWarning, + stacklevel=2, + ) tmp = (validateTrace if validateTrace is not None else [])[:] + [self] for e in self.exprs: e.validate(tmp) @@ -3721,6 +3858,7 @@ class ParseExpression(ParserElement): def copy(self) -> ParserElement: ret = super().copy() + ret = typing.cast(ParseExpression, ret) ret.exprs = [e.copy() for e in self.exprs] return ret @@ -3750,8 +3888,14 @@ class ParseExpression(ParserElement): return super()._setResultsName(name, listAllMatches) - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace + # Compatibility synonyms + # fmt: off + @replaced_by_pep8(leave_whitespace) + def leaveWhitespace(self): ... + + @replaced_by_pep8(ignore_whitespace) + def ignoreWhitespace(self): ... + # fmt: on class And(ParseExpression): @@ -3777,7 +3921,7 @@ class And(ParseExpression): super().__init__(*args, **kwargs) self.leave_whitespace() - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "-" def __init__( @@ -3789,7 +3933,9 @@ class And(ParseExpression): for i, expr in enumerate(exprs): if expr is Ellipsis: if i < len(exprs) - 1: - skipto_arg: ParserElement = (Empty() + exprs[i + 1]).exprs[-1] + skipto_arg: ParserElement = typing.cast( + ParseExpression, (Empty() + exprs[i + 1]) + ).exprs[-1] tmp.append(SkipTo(skipto_arg)("_skipped*")) else: raise Exception( @@ -3822,8 +3968,9 @@ class And(ParseExpression): and isinstance(e.exprs[-1], _PendingSkip) for e in self.exprs[:-1] ): + deleted_expr_marker = NoMatch() for i, e in enumerate(self.exprs[:-1]): - if e is None: + if e is deleted_expr_marker: continue if ( isinstance(e, ParseExpression) @@ -3831,17 +3978,19 @@ class And(ParseExpression): and isinstance(e.exprs[-1], _PendingSkip) ): e.exprs[-1] = e.exprs[-1] + self.exprs[i + 1] - self.exprs[i + 1] = None - self.exprs = [e for e in self.exprs if e is not None] + self.exprs[i + 1] = deleted_expr_marker + self.exprs = [e for e in self.exprs if e is not deleted_expr_marker] super().streamline() # link any IndentedBlocks to the prior expression + prev: ParserElement + cur: ParserElement for prev, cur in zip(self.exprs, self.exprs[1:]): # traverse cur or any first embedded expr of cur looking for an IndentedBlock # (but watch out for recursive grammar) seen = set() - while cur: + while True: if id(cur) in seen: break seen.add(id(cur)) @@ -3853,7 +4002,10 @@ class And(ParseExpression): ) break subs = cur.recurse() - cur = next(iter(subs), None) + next_first = next(iter(subs), None) + if next_first is None: + break + cur = typing.cast(ParserElement, next_first) self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) return self @@ -3884,13 +4036,14 @@ class And(ParseExpression): ) else: loc, exprtokens = e._parse(instring, loc, doActions) - if exprtokens or exprtokens.haskeys(): - resultlist += exprtokens + resultlist += exprtokens return loc, resultlist def __iadd__(self, other): if isinstance(other, str_type): other = self._literalStringClass(other) + if not isinstance(other, ParserElement): + return NotImplemented return self.append(other) # And([self, other]) def _checkRecursion(self, parseElementList): @@ -3900,7 +4053,7 @@ class And(ParseExpression): if not e.mayReturnEmpty: break - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: inner = " ".join(str(e) for e in self.exprs) # strip off redundant inner {}'s while len(inner) > 1 and inner[0 :: len(inner) - 1] == "{}": @@ -3958,7 +4111,7 @@ class Or(ParseExpression): loc2 = e.try_parse(instring, loc, raise_fatal=True) except ParseFatalException as pfe: pfe.__traceback__ = None - pfe.parserElement = e + pfe.parser_element = e fatals.append(pfe) maxException = None maxExcLoc = -1 @@ -4016,12 +4169,15 @@ class Or(ParseExpression): if len(fatals) > 1: fatals.sort(key=lambda e: -e.loc) if fatals[0].loc == fatals[1].loc: - fatals.sort(key=lambda e: (-e.loc, -len(str(e.parserElement)))) + fatals.sort(key=lambda e: (-e.loc, -len(str(e.parser_element)))) max_fatal = fatals[0] raise max_fatal if maxException is not None: - maxException.msg = self.errmsg + # infer from this check that all alternatives failed at the current position + # so emit this collective error message instead of any single error message + if maxExcLoc == loc: + maxException.msg = self.errmsg raise maxException else: raise ParseException( @@ -4031,9 +4187,11 @@ class Or(ParseExpression): def __ixor__(self, other): if isinstance(other, str_type): other = self._literalStringClass(other) + if not isinstance(other, ParserElement): + return NotImplemented return self.append(other) # Or([self, other]) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "{" + " ^ ".join(str(e) for e in self.exprs) + "}" def _setResultsName(self, name, listAllMatches=False): @@ -4118,7 +4276,7 @@ class MatchFirst(ParseExpression): ) except ParseFatalException as pfe: pfe.__traceback__ = None - pfe.parserElement = e + pfe.parser_element = e raise except ParseException as err: if err.loc > maxExcLoc: @@ -4132,7 +4290,10 @@ class MatchFirst(ParseExpression): maxExcLoc = len(instring) if maxException is not None: - maxException.msg = self.errmsg + # infer from this check that all alternatives failed at the current position + # so emit this collective error message instead of any individual error message + if maxExcLoc == loc: + maxException.msg = self.errmsg raise maxException else: raise ParseException( @@ -4142,9 +4303,11 @@ class MatchFirst(ParseExpression): def __ior__(self, other): if isinstance(other, str_type): other = self._literalStringClass(other) + if not isinstance(other, ParserElement): + return NotImplemented return self.append(other) # MatchFirst([self, other]) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "{" + " | ".join(str(e) for e in self.exprs) + "}" def _setResultsName(self, name, listAllMatches=False): @@ -4242,6 +4405,13 @@ class Each(ParseExpression): self.initExprGroups = True self.saveAsList = True + def __iand__(self, other): + if isinstance(other, str_type): + other = self._literalStringClass(other) + if not isinstance(other, ParserElement): + return NotImplemented + return self.append(other) # Each([self, other]) + def streamline(self) -> ParserElement: super().streamline() if self.exprs: @@ -4296,7 +4466,7 @@ class Each(ParseExpression): tmpLoc = e.try_parse(instring, tmpLoc, raise_fatal=True) except ParseFatalException as pfe: pfe.__traceback__ = None - pfe.parserElement = e + pfe.parser_element = e fatals.append(pfe) failed.append(e) except ParseException: @@ -4315,7 +4485,7 @@ class Each(ParseExpression): if len(fatals) > 1: fatals.sort(key=lambda e: -e.loc) if fatals[0].loc == fatals[1].loc: - fatals.sort(key=lambda e: (-e.loc, -len(str(e.parserElement)))) + fatals.sort(key=lambda e: (-e.loc, -len(str(e.parser_element)))) max_fatal = fatals[0] raise max_fatal @@ -4324,7 +4494,7 @@ class Each(ParseExpression): raise ParseException( instring, loc, - "Missing one or more required elements ({})".format(missing), + f"Missing one or more required elements ({missing})", ) # add any unmatched Opts, in case they have default values defined @@ -4337,7 +4507,7 @@ class Each(ParseExpression): return loc, total_results - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "{" + " & ".join(str(e) for e in self.exprs) + "}" @@ -4349,12 +4519,14 @@ class ParseElementEnhance(ParserElement): def __init__(self, expr: Union[ParserElement, str], savelist: bool = False): super().__init__(savelist) if isinstance(expr, str_type): + expr_str = typing.cast(str, expr) if issubclass(self._literalStringClass, Token): - expr = self._literalStringClass(expr) + expr = self._literalStringClass(expr_str) # type: ignore[call-arg] elif issubclass(type(self), self._literalStringClass): - expr = Literal(expr) + expr = Literal(expr_str) else: - expr = self._literalStringClass(Literal(expr)) + expr = self._literalStringClass(Literal(expr_str)) # type: ignore[assignment, call-arg] + expr = typing.cast(ParserElement, expr) self.expr = expr if expr is not None: self.mayIndexError = expr.mayIndexError @@ -4367,12 +4539,16 @@ class ParseElementEnhance(ParserElement): self.callPreparse = expr.callPreparse self.ignoreExprs.extend(expr.ignoreExprs) - def recurse(self) -> Sequence[ParserElement]: + def recurse(self) -> List[ParserElement]: return [self.expr] if self.expr is not None else [] def parseImpl(self, instring, loc, doActions=True): if self.expr is not None: - return self.expr._parse(instring, loc, doActions, callPreParse=False) + try: + return self.expr._parse(instring, loc, doActions, callPreParse=False) + except ParseBaseException as pbe: + pbe.msg = self.errmsg + raise else: raise ParseException(instring, loc, "No expression defined", self) @@ -4380,8 +4556,8 @@ class ParseElementEnhance(ParserElement): super().leave_whitespace(recursive) if recursive: - self.expr = self.expr.copy() if self.expr is not None: + self.expr = self.expr.copy() self.expr.leave_whitespace(recursive) return self @@ -4389,8 +4565,8 @@ class ParseElementEnhance(ParserElement): super().ignore_whitespace(recursive) if recursive: - self.expr = self.expr.copy() if self.expr is not None: + self.expr = self.expr.copy() self.expr.ignore_whitespace(recursive) return self @@ -4420,6 +4596,11 @@ class ParseElementEnhance(ParserElement): self.expr._checkRecursion(subRecCheckList) def validate(self, validateTrace=None) -> None: + warnings.warn( + "ParserElement.validate() is deprecated, and should not be used to check for left recursion", + DeprecationWarning, + stacklevel=2, + ) if validateTrace is None: validateTrace = [] tmp = validateTrace[:] + [self] @@ -4427,11 +4608,17 @@ class ParseElementEnhance(ParserElement): self.expr.validate(tmp) self._checkRecursion([]) - def _generateDefaultName(self): - return "{}:({})".format(self.__class__.__name__, str(self.expr)) + def _generateDefaultName(self) -> str: + return f"{self.__class__.__name__}:({str(self.expr)})" + + # Compatibility synonyms + # fmt: off + @replaced_by_pep8(leave_whitespace) + def leaveWhitespace(self): ... - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace + @replaced_by_pep8(ignore_whitespace) + def ignoreWhitespace(self): ... + # fmt: on class IndentedBlock(ParseElementEnhance): @@ -4443,13 +4630,13 @@ class IndentedBlock(ParseElementEnhance): class _Indent(Empty): def __init__(self, ref_col: int): super().__init__() - self.errmsg = "expected indent at column {}".format(ref_col) + self.errmsg = f"expected indent at column {ref_col}" self.add_condition(lambda s, l, t: col(l, s) == ref_col) class _IndentGreater(Empty): def __init__(self, ref_col: int): super().__init__() - self.errmsg = "expected indent at column greater than {}".format(ref_col) + self.errmsg = f"expected indent at column greater than {ref_col}" self.add_condition(lambda s, l, t: col(l, s) > ref_col) def __init__( @@ -4469,7 +4656,7 @@ class IndentedBlock(ParseElementEnhance): # see if self.expr matches at the current location - if not it will raise an exception # and no further work is necessary - self.expr.try_parse(instring, anchor_loc, doActions) + self.expr.try_parse(instring, anchor_loc, do_actions=doActions) indent_col = col(anchor_loc, instring) peer_detect_expr = self._Indent(indent_col) @@ -4532,7 +4719,7 @@ class AtLineStart(ParseElementEnhance): B AAA and definitely not this one ''' - for t in (AtLineStart('AAA') + restOfLine).search_string(test): + for t in (AtLineStart('AAA') + rest_of_line).search_string(test): print(t) prints:: @@ -4598,9 +4785,9 @@ class PrecededBy(ParseElementEnhance): Parameters: - - expr - expression that must match prior to the current parse + - ``expr`` - expression that must match prior to the current parse location - - retreat - (default= ``None``) - (int) maximum number of characters + - ``retreat`` - (default= ``None``) - (int) maximum number of characters to lookbehind prior to the current parse location If the lookbehind expression is a string, :class:`Literal`, @@ -4627,6 +4814,7 @@ class PrecededBy(ParseElementEnhance): self.mayIndexError = False self.exact = False if isinstance(expr, str_type): + expr = typing.cast(str, expr) retreat = len(expr) self.exact = True elif isinstance(expr, (Literal, Keyword)): @@ -4746,18 +4934,18 @@ class NotAny(ParseElementEnhance): self.errmsg = "Found unwanted token, " + str(self.expr) def parseImpl(self, instring, loc, doActions=True): - if self.expr.can_parse_next(instring, loc): + if self.expr.can_parse_next(instring, loc, do_actions=doActions): raise ParseException(instring, loc, self.errmsg, self) return loc, [] - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "~{" + str(self.expr) + "}" class _MultipleMatch(ParseElementEnhance): def __init__( self, - expr: ParserElement, + expr: Union[str, ParserElement], stop_on: typing.Optional[Union[ParserElement, str]] = None, *, stopOn: typing.Optional[Union[ParserElement, str]] = None, @@ -4781,7 +4969,7 @@ class _MultipleMatch(ParseElementEnhance): self_skip_ignorables = self._skipIgnorables check_ender = self.not_ender is not None if check_ender: - try_not_ender = self.not_ender.tryParse + try_not_ender = self.not_ender.try_parse # must be at least one (but first see if we are the stopOn sentinel; # if so, fail) @@ -4798,8 +4986,7 @@ class _MultipleMatch(ParseElementEnhance): else: preloc = loc loc, tmptokens = self_expr_parse(instring, preloc, doActions) - if tmptokens or tmptokens.haskeys(): - tokens += tmptokens + tokens += tmptokens except (ParseException, IndexError): pass @@ -4837,10 +5024,11 @@ class OneOrMore(_MultipleMatch): Repetition of one or more of the given expression. Parameters: - - expr - expression that must match one or more times - - stop_on - (default= ``None``) - expression for a terminating sentinel - (only required if the sentinel would ordinarily match the repetition - expression) + + - ``expr`` - expression that must match one or more times + - ``stop_on`` - (default= ``None``) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) Example:: @@ -4859,7 +5047,7 @@ class OneOrMore(_MultipleMatch): (attr_expr * (1,)).parse_string(text).pprint() """ - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "{" + str(self.expr) + "}..." @@ -4868,6 +5056,7 @@ class ZeroOrMore(_MultipleMatch): Optional repetition of zero or more of the given expression. Parameters: + - ``expr`` - expression that must match zero or more times - ``stop_on`` - expression for a terminating sentinel (only required if the sentinel would ordinarily match the repetition @@ -4878,7 +5067,7 @@ class ZeroOrMore(_MultipleMatch): def __init__( self, - expr: ParserElement, + expr: Union[str, ParserElement], stop_on: typing.Optional[Union[ParserElement, str]] = None, *, stopOn: typing.Optional[Union[ParserElement, str]] = None, @@ -4892,10 +5081,75 @@ class ZeroOrMore(_MultipleMatch): except (ParseException, IndexError): return loc, ParseResults([], name=self.resultsName) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: return "[" + str(self.expr) + "]..." +class DelimitedList(ParseElementEnhance): + def __init__( + self, + expr: Union[str, ParserElement], + delim: Union[str, ParserElement] = ",", + combine: bool = False, + min: typing.Optional[int] = None, + max: typing.Optional[int] = None, + *, + allow_trailing_delim: bool = False, + ): + """Helper to define a delimited list of expressions - the delimiter + defaults to ','. By default, the list elements and delimiters can + have intervening whitespace, and comments, but this can be + overridden by passing ``combine=True`` in the constructor. If + ``combine`` is set to ``True``, the matching tokens are + returned as a single token string, with the delimiters included; + otherwise, the matching tokens are returned as a list of tokens, + with the delimiters suppressed. + + If ``allow_trailing_delim`` is set to True, then the list may end with + a delimiter. + + Example:: + + DelimitedList(Word(alphas)).parse_string("aa,bb,cc") # -> ['aa', 'bb', 'cc'] + DelimitedList(Word(hexnums), delim=':', combine=True).parse_string("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + if isinstance(expr, str_type): + expr = ParserElement._literalStringClass(expr) + expr = typing.cast(ParserElement, expr) + + if min is not None: + if min < 1: + raise ValueError("min must be greater than 0") + if max is not None: + if min is not None and max < min: + raise ValueError("max must be greater than, or equal to min") + + self.content = expr + self.raw_delim = str(delim) + self.delim = delim + self.combine = combine + if not combine: + self.delim = Suppress(delim) + self.min = min or 1 + self.max = max + self.allow_trailing_delim = allow_trailing_delim + + delim_list_expr = self.content + (self.delim + self.content) * ( + self.min - 1, + None if self.max is None else self.max - 1, + ) + if self.allow_trailing_delim: + delim_list_expr += Opt(self.delim) + + if self.combine: + delim_list_expr = Combine(delim_list_expr) + + super().__init__(delim_list_expr, savelist=True) + + def _generateDefaultName(self) -> str: + return "{0} [{1} {0}]...".format(self.content.streamline(), self.raw_delim) + + class _NullToken: def __bool__(self): return False @@ -4909,6 +5163,7 @@ class Opt(ParseElementEnhance): Optional matching of the given expression. Parameters: + - ``expr`` - expression that must match zero or more times - ``default`` (optional) - value to be returned if the optional expression is not found. @@ -4969,7 +5224,7 @@ class Opt(ParseElementEnhance): tokens = [] return loc, tokens - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: inner = str(self.expr) # strip off redundant inner {}'s while len(inner) > 1 and inner[0 :: len(inner) - 1] == "{}": @@ -4986,6 +5241,7 @@ class SkipTo(ParseElementEnhance): expression is found. Parameters: + - ``expr`` - target expression marking the end of the data to be skipped - ``include`` - if ``True``, the target expression is also parsed (the skipped text and target expression are returned as a 2-element @@ -5045,14 +5301,15 @@ class SkipTo(ParseElementEnhance): self, other: Union[ParserElement, str], include: bool = False, - ignore: bool = None, + ignore: typing.Optional[Union[ParserElement, str]] = None, fail_on: typing.Optional[Union[ParserElement, str]] = None, *, - failOn: Union[ParserElement, str] = None, + failOn: typing.Optional[Union[ParserElement, str]] = None, ): super().__init__(other) failOn = failOn or fail_on - self.ignoreExpr = ignore + if ignore is not None: + self.ignore(ignore) self.mayReturnEmpty = True self.mayIndexError = False self.includeMatch = include @@ -5070,9 +5327,7 @@ class SkipTo(ParseElementEnhance): self_failOn_canParseNext = ( self.failOn.canParseNext if self.failOn is not None else None ) - self_ignoreExpr_tryParse = ( - self.ignoreExpr.tryParse if self.ignoreExpr is not None else None - ) + self_preParse = self.preParse if self.callPreparse else None tmploc = loc while tmploc <= instrlen: @@ -5081,13 +5336,9 @@ class SkipTo(ParseElementEnhance): if self_failOn_canParseNext(instring, tmploc): break - if self_ignoreExpr_tryParse is not None: - # advance past ignore expressions - while 1: - try: - tmploc = self_ignoreExpr_tryParse(instring, tmploc) - except ParseBaseException: - break + if self_preParse is not None: + # skip grammar-ignored expressions + tmploc = self_preParse(instring, tmploc) try: self_expr_parse(instring, tmploc, doActions=False, callPreParse=False) @@ -5145,15 +5396,20 @@ class Forward(ParseElementEnhance): def __init__(self, other: typing.Optional[Union[ParserElement, str]] = None): self.caller_frame = traceback.extract_stack(limit=2)[0] - super().__init__(other, savelist=False) + super().__init__(other, savelist=False) # type: ignore[arg-type] self.lshift_line = None - def __lshift__(self, other): + def __lshift__(self, other) -> "Forward": if hasattr(self, "caller_frame"): del self.caller_frame if isinstance(other, str_type): other = self._literalStringClass(other) + + if not isinstance(other, ParserElement): + return NotImplemented + self.expr = other + self.streamlined = other.streamlined self.mayIndexError = self.expr.mayIndexError self.mayReturnEmpty = self.expr.mayReturnEmpty self.set_whitespace_chars( @@ -5162,13 +5418,16 @@ class Forward(ParseElementEnhance): self.skipWhitespace = self.expr.skipWhitespace self.saveAsList = self.expr.saveAsList self.ignoreExprs.extend(self.expr.ignoreExprs) - self.lshift_line = traceback.extract_stack(limit=2)[-2] + self.lshift_line = traceback.extract_stack(limit=2)[-2] # type: ignore[assignment] return self - def __ilshift__(self, other): + def __ilshift__(self, other) -> "Forward": + if not isinstance(other, ParserElement): + return NotImplemented + return self << other - def __or__(self, other): + def __or__(self, other) -> "ParserElement": caller_line = traceback.extract_stack(limit=2)[-2] if ( __diag__.warn_on_match_first_with_lshift_operator @@ -5205,12 +5464,12 @@ class Forward(ParseElementEnhance): not in self.suppress_warnings_ ): # walk stack until parse_string, scan_string, search_string, or transform_string is found - parse_fns = [ + parse_fns = ( "parse_string", "scan_string", "search_string", "transform_string", - ] + ) tb = traceback.extract_stack(limit=200) for i, frm in enumerate(reversed(tb), start=1): if frm.name in parse_fns: @@ -5308,6 +5567,11 @@ class Forward(ParseElementEnhance): return self def validate(self, validateTrace=None) -> None: + warnings.warn( + "ParserElement.validate() is deprecated, and should not be used to check for left recursion", + DeprecationWarning, + stacklevel=2, + ) if validateTrace is None: validateTrace = [] @@ -5317,7 +5581,7 @@ class Forward(ParseElementEnhance): self.expr.validate(tmp) self._checkRecursion([]) - def _generateDefaultName(self): + def _generateDefaultName(self) -> str: # Avoid infinite recursion by setting a temporary _defaultName self._defaultName = ": ..." @@ -5356,8 +5620,14 @@ class Forward(ParseElementEnhance): return super()._setResultsName(name, list_all_matches) - ignoreWhitespace = ignore_whitespace - leaveWhitespace = leave_whitespace + # Compatibility synonyms + # fmt: off + @replaced_by_pep8(leave_whitespace) + def leaveWhitespace(self): ... + + @replaced_by_pep8(ignore_whitespace) + def ignoreWhitespace(self): ... + # fmt: on class TokenConverter(ParseElementEnhance): @@ -5439,11 +5709,11 @@ class Group(TokenConverter): ident = Word(alphas) num = Word(nums) term = ident | num - func = ident + Opt(delimited_list(term)) + func = ident + Opt(DelimitedList(term)) print(func.parse_string("fn a, b, 100")) # -> ['fn', 'a', 'b', '100'] - func = ident + Group(Opt(delimited_list(term))) + func = ident + Group(Opt(DelimitedList(term))) print(func.parse_string("fn a, b, 100")) # -> ['fn', ['a', 'b', '100']] """ @@ -5579,7 +5849,7 @@ class Suppress(TokenConverter): ['a', 'b', 'c', 'd'] ['START', 'relevant text ', 'END'] - (See also :class:`delimited_list`.) + (See also :class:`DelimitedList`.) """ def __init__(self, expr: Union[ParserElement, str], savelist: bool = False): @@ -5638,15 +5908,13 @@ def trace_parse_action(f: ParseAction) -> ParseAction: s, l, t = paArgs[-3:] if len(paArgs) > 3: thisFunc = paArgs[0].__class__.__name__ + "." + thisFunc - sys.stderr.write( - ">>entering {}(line: {!r}, {}, {!r})\n".format(thisFunc, line(l, s), l, t) - ) + sys.stderr.write(f">>entering {thisFunc}(line: {line(l, s)!r}, {l}, {t!r})\n") try: ret = f(*paArgs) except Exception as exc: - sys.stderr.write("< str: ) try: return "".join(_expanded(part) for part in _reBracketExpr.parse_string(s).body) - except Exception: + except Exception as e: return "" @@ -5769,7 +6037,11 @@ def autoname_elements() -> None: Utility to simplify mass-naming of parser elements, for generating railroad diagram with named subdiagrams. """ - for name, var in sys._getframe().f_back.f_locals.items(): + calling_frame = sys._getframe().f_back + if calling_frame is None: + return + calling_frame = typing.cast(types.FrameType, calling_frame) + for name, var in calling_frame.f_locals.items(): if isinstance(var, ParserElement) and not var.customName: var.set_name(name) @@ -5783,9 +6055,28 @@ sgl_quoted_string = Combine( ).set_name("string enclosed in single quotes") quoted_string = Combine( - Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"' - | Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "'" -).set_name("quotedString using single or double quotes") + (Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"').set_name( + "double quoted string" + ) + | (Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "'").set_name( + "single quoted string" + ) +).set_name("quoted string using single or double quotes") + +python_quoted_string = Combine( + (Regex(r'"""(?:[^"\\]|""(?!")|"(?!"")|\\.)*', flags=re.MULTILINE) + '"""').set_name( + "multiline double quoted string" + ) + ^ ( + Regex(r"'''(?:[^'\\]|''(?!')|'(?!'')|\\.)*", flags=re.MULTILINE) + "'''" + ).set_name("multiline single quoted string") + ^ (Regex(r'"(?:[^"\n\r\\]|(?:\\")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*') + '"').set_name( + "double quoted string" + ) + ^ (Regex(r"'(?:[^'\n\r\\]|(?:\\')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*") + "'").set_name( + "single quoted string" + ) +).set_name("Python quoted string") unicode_string = Combine("u" + quoted_string.copy()).set_name("unicode string literal") @@ -5800,9 +6091,7 @@ _builtin_exprs: List[ParserElement] = [ ] # backward compatibility names -tokenMap = token_map -conditionAsParseAction = condition_as_parse_action -nullDebugAction = null_debug_action +# fmt: off sglQuotedString = sgl_quoted_string dblQuotedString = dbl_quoted_string quotedString = quoted_string @@ -5811,4 +6100,16 @@ lineStart = line_start lineEnd = line_end stringStart = string_start stringEnd = string_end -traceParseAction = trace_parse_action + +@replaced_by_pep8(null_debug_action) +def nullDebugAction(): ... + +@replaced_by_pep8(trace_parse_action) +def traceParseAction(): ... + +@replaced_by_pep8(condition_as_parse_action) +def conditionAsParseAction(): ... + +@replaced_by_pep8(token_map) +def tokenMap(): ... +# fmt: on diff --git a/.venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py b/.venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py index 1506d66b..83f9018e 100644 --- a/.venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py +++ b/.venv/Lib/site-packages/pip/_vendor/pyparsing/diagram/__init__.py @@ -1,3 +1,4 @@ +# mypy: ignore-errors import railroad from pip._vendor import pyparsing import typing @@ -17,11 +18,13 @@ import inspect jinja2_template_source = """\ +{% if not embed %} +{% endif %} {% if not head %} - \n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Unnamed: 0cuisinealmondangelicaaniseanise_seedappleapple_brandyapricotarmagnac...whiskeywhite_breadwhite_winewhole_grain_wheat_flourwinewoodyamyeastyogurtzucchini
00indian00000000...0000000000
11indian10000000...0000000000
22indian00000000...0000000000
33indian00000000...0000000000
44indian00000000...0000000010
\n", + "

5 rows × 382 columns

\n", + "
" + ], + "text/plain": [ + " Unnamed: 0 cuisine almond angelica anise anise_seed apple \\\n", + "0 0 indian 0 0 0 0 0 \n", + "1 1 indian 1 0 0 0 0 \n", + "2 2 indian 0 0 0 0 0 \n", + "3 3 indian 0 0 0 0 0 \n", + "4 4 indian 0 0 0 0 0 \n", + "\n", + " apple_brandy apricot armagnac ... whiskey white_bread white_wine \\\n", + "0 0 0 0 ... 0 0 0 \n", + "1 0 0 0 ... 0 0 0 \n", + "2 0 0 0 ... 0 0 0 \n", + "3 0 0 0 ... 0 0 0 \n", + "4 0 0 0 ... 0 0 0 \n", + "\n", + " whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n", + "0 0 0 0 0 0 0 0 \n", + "1 0 0 0 0 0 0 0 \n", + "2 0 0 0 0 0 0 0 \n", + "3 0 0 0 0 0 0 0 \n", + "4 0 0 0 0 0 1 0 \n", + "\n", + "[5 rows x 382 columns]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data = pd.read_csv('../data/cleaned_cuisines.csv')\n", + "data.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
almondangelicaaniseanise_seedappleapple_brandyapricotarmagnacartemisiaartichoke...whiskeywhite_breadwhite_winewhole_grain_wheat_flourwinewoodyamyeastyogurtzucchini
00000000000...0000000000
11000000000...0000000000
20000000000...0000000000
30000000000...0000000000
40000000000...0000000010
\n", + "

5 rows × 380 columns

\n", + "
" + ], + "text/plain": [ + " almond angelica anise anise_seed apple apple_brandy apricot \\\n", + "0 0 0 0 0 0 0 0 \n", + "1 1 0 0 0 0 0 0 \n", + "2 0 0 0 0 0 0 0 \n", + "3 0 0 0 0 0 0 0 \n", + "4 0 0 0 0 0 0 0 \n", + "\n", + " armagnac artemisia artichoke ... whiskey white_bread white_wine \\\n", + "0 0 0 0 ... 0 0 0 \n", + "1 0 0 0 ... 0 0 0 \n", + "2 0 0 0 ... 0 0 0 \n", + "3 0 0 0 ... 0 0 0 \n", + "4 0 0 0 ... 0 0 0 \n", + "\n", + " whole_grain_wheat_flour wine wood yam yeast yogurt zucchini \n", + "0 0 0 0 0 0 0 0 \n", + "1 0 0 0 0 0 0 0 \n", + "2 0 0 0 0 0 0 0 \n", + "3 0 0 0 0 0 0 0 \n", + "4 0 0 0 0 0 1 0 \n", + "\n", + "[5 rows x 380 columns]" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "X = data.iloc[:,2:]\n", + "X.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cuisine
0indian
1indian
2indian
3indian
4indian
\n", + "
" + ], + "text/plain": [ + " cuisine\n", + "0 indian\n", + "1 indian\n", + "2 indian\n", + "3 indian\n", + "4 indian" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y = data[['cuisine']]\n", + "y.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "from sklearn.model_selection import train_test_split,cross_val_score\n", + "from sklearn.metrics import accuracy_score,classification_report,confusion_matrix\n", + "from sklearn.svm import SVC\n" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "X_train, X_test, y_train, y_test= train_test_split(X, y, test_size=0.3)" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
SVC(C=10, kernel='linear', probability=True, random_state=0)
In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
" + ], + "text/plain": [ + "SVC(C=10, kernel='linear', probability=True, random_state=0)" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "model = SVC(kernel='linear', C= 10, probability=True, random_state=0)\n", + "model.fit(X_train, y_train.values.ravel())" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "y_pred = model.predict(X_test)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " precision recall f1-score support\n", + "\n", + " chinese 0.66 0.72 0.69 239\n", + " indian 0.90 0.90 0.90 238\n", + " japanese 0.76 0.74 0.75 246\n", + " korean 0.79 0.75 0.77 233\n", + " thai 0.78 0.75 0.77 243\n", + "\n", + " accuracy 0.77 1199\n", + " macro avg 0.78 0.77 0.77 1199\n", + "weighted avg 0.78 0.77 0.77 1199\n", + "\n" + ] + } + ], + "source": [ + "print(classification_report(y_test,y_pred))" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "from skl2onnx import convert_sklearn\n", + "from skl2onnx.common.data_types import FloatTensorType\n", + "\n", + "initial_type = [('float_input', FloatTensorType([None,380]))]\n", + "\n", + "options = {id(model): {'nocl': True, 'zipmap':False}}" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Convert the model to onnx to be used in a JavaScript based system for inference in a web application" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [], + "source": [ + "onx = convert_sklearn(model, initial_types=initial_type, options=options)\n", + "with open(\"./model.onnx\", \"wb\") as f:\n", + " f.write(onx.SerializeToString())" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, "language_info": { "codemirror_mode": { "name": "ipython", @@ -10,19 +646,10 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": 3 + "version": "3.10.11" }, "orig_nbformat": 4 }, "nbformat": 4, - "nbformat_minor": 2, - "cells": [ - { - "source": [ - "# Build a cuisine recommender" - ], - "cell_type": "markdown", - "metadata": {} - } - ] -} \ No newline at end of file + "nbformat_minor": 2 +} diff --git a/4-Classification/4-Applied/style.css b/4-Classification/4-Applied/style.css new file mode 100644 index 00000000..1cefab09 --- /dev/null +++ b/4-Classification/4-Applied/style.css @@ -0,0 +1,4 @@ +body{ + margin: 20px ; +} + diff --git a/6-NLP/3-Translation-Sentiment/notebook.ipynb b/6-NLP/3-Translation-Sentiment/notebook.ipynb new file mode 100644 index 00000000..54d8fa3e --- /dev/null +++ b/6-NLP/3-Translation-Sentiment/notebook.ipynb @@ -0,0 +1,48 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "from textblob import TextBlob\n", + "from textblob.np_extractors import ConllExtractor\n", + "extractor = ConllExtractor()\n", + "\n", + "\n", + "user_input = input(\"> \")\n", + "user_input_blob = TextBlob(user_input, np_extractor=extractor)\n", + "np = user_input_blob.noun_phrases\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/7-TimeSeries/1-Introduction/working/notebook.ipynb b/7-TimeSeries/1-Introduction/working/notebook.ipynb index 550e7e0a..5df56fab 100644 --- a/7-TimeSeries/1-Introduction/working/notebook.ipynb +++ b/7-TimeSeries/1-Introduction/working/notebook.ipynb @@ -1,6 +1,8 @@ { "cells": [ { + "cell_type": "markdown", + "metadata": {}, "source": [ "# Data Setup\n", "\n", @@ -11,9 +13,146 @@ "The data in this example is taken from the GEFCom2014 forecasting competition1. It consists of 3 years of hourly electricity load and temperature values between 2012 and 2014.\n", "\n", "1Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli and Rob J. Hyndman, \"Probabilistic energy forecasting: Global Energy Forecasting Competition 2014 and beyond\", International Journal of Forecasting, vol.32, no.3, pp 896-913, July-September, 2016." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import matplotlib.pyplot as plt\n", + "from common.utils import load_data\n", + "%matplotlib inline" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
load
2012-01-01 00:00:002698.0
2012-01-01 01:00:002558.0
2012-01-01 02:00:002444.0
2012-01-01 03:00:002402.0
2012-01-01 04:00:002403.0
\n", + "
" + ], + "text/plain": [ + " load\n", + "2012-01-01 00:00:00 2698.0\n", + "2012-01-01 01:00:00 2558.0\n", + "2012-01-01 02:00:00 2444.0\n", + "2012-01-01 03:00:00 2402.0\n", + "2012-01-01 04:00:00 2403.0" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } ], - "cell_type": "markdown", - "metadata": {} + "source": [ + "data_dir ='./data/'\n", + "energy = load_data(data_dir)[['load']]\n", + "energy.head()" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABOkAAALECAYAAABdQ2SgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd5wU9f0/8NdxdBHsCorRBI3GEqNGEmM0fi0xJkZ/EYwaNRoNiV0TS7AlNiBB7AVQlKqIKEWk93bccXAcB9xxR7njeu91b3d+fxy3bJneZ/b1fDxMuN2Zz3x2d+bzmc97PiVJEAQBRERERERERERE5JgeTmeAiIiIiIiIiIgo0TFIR0RERERERERE5DAG6YiIiIiIiIiIiBzGIB0REREREREREZHDGKQjIiIiIiIiIiJyGIN0REREREREREREDmOQjoiIiIiIiIiIyGEM0hERERERERERETmsp9MZ8JtQKISSkhIcffTRSEpKcjo7RERERERERETkIEEQ0NjYiCFDhqBHD+n+cgzSmaykpARDhw51OhtEREREREREROQihYWFOO200yTfZ5DOZEcffTSAri9+4MCBDueGiIiIiIiIiIic1NDQgKFDh4ZjRlIYpDNZ9xDXgQMHMkhHREREREREREQAoDgtGheOICIiIiIiIiIichiDdERERERERERERA5jkI6IiIiIiIiIiMhhnJOOiIiIiIiIiIjCgsEgAoGA09nwjF69eiE5OdlwOgzSERERERERERERBEFAWVkZ6urqnM6K5xxzzDE45ZRTFBeHkMMgHRERERERERERhQN0J510Evr3728o4JQoBEFAS0sLKioqAACDBw/WnRaDdERERERERERECS4YDIYDdMcff7zT2fGUfv36AQAqKipw0kkn6R76yoUjiIiIiIiIiIgSXPccdP3793c4J97U/b0ZmcuPQToiIiIiIiIiIgIADnHVyYzvjUE6IiIiIiIiIiIihzFIR0REREREREREnvWrX/0KTzzxhOePwSAdERERERERERGRwxikIyIiIiIiIiIichiDdERERERERERE5Au1tbW45557cOyxx6J///74zW9+g7y8vPD71dXVuOOOO3Dqqaeif//+uOCCC/DFF19EpdHc3Ix77rkHAwYMwODBgzFhwgRb8s4gHRERERERERERxREEAS0dnbb/JwiC7jzfe++9SE9Px8KFC5GSkgJBEHDjjTciEAgAANra2nDJJZfgu+++w65duzBq1CjcfffdSEtLC6fx9NNPY926dViwYAGWL1+OtWvXYvv27Ya/TyU9LT8CERERERERERF5TmsgiB+9tMz24+555dfo31t7yCovLw8LFy7Epk2bcPnllwMAZs2ahaFDh2L+/PkYOXIkTj31VDz11FPhfR599FEsW7YMc+bMwWWXXYampiZMmTIFM2fOxDXXXAMAmDZtGk477TRzPpwMBumIiIiIiIiIiMjzsrOz0bNnTwwfPjz82vHHH48f/vCHyM7OBgAEg0GMGTMGc+bMQXFxMTo6OtDe3o7+/fsDAPbv34+Ojo6oNI477jj88Ic/tDz/DNIREREREREREVGcfr2SseeVXztyXKuMHz8e77zzDt5++21ccMEFOOqoo/DEE0+go6PDsmOqxSAdERERERERERHFSUpK0jXs1CnnnnsuOjs7kZqaGh7uWl1djb179+JHP/oRAGDTpk24+eabcddddwEAQqEQcnNzw+//4Ac/QK9evZCamorTTz8dQNdiFLm5ubjqqqsszT8XjiAiIiIiIiIiIs8766yzcPPNN+Ovf/0rNm7ciMzMTNx111049dRTcfPNN4e3WbFiBTZv3ozs7Gz87W9/Q3l5eTiNAQMG4P7778fTTz+N1atXY9euXbj33nvRo4f1ITQG6YiIiIiIiIiIyBc+++wzXHLJJfjd736Hn//85xAEAYsXL0avXr0AAC+88AIuvvhi/PrXv8avfvUrnHLKKbjlllui0hg/fjx++ctf4qabbsK1116LK664ApdcconleU8SjKxrS3EaGhowaNAg1NfXY+DAgU5nh4iIiIiIiIhIUVtbGw4ePIgzzzwTffv2dTo7niP3/amNFbEnHRERERERERERkcMYpCMiIiIi12vtCDqdBSIiIiJLMUhHRERERK72wZp9OPelpViVXa68MREREZFHMUhHRERERK42ftleAMCzX2c5nBMiIiIi6zBIR0RERESekMw7VyIiIstxfVF9zPjeeKtDRERERJ7QIynJ6SwQERH5Vq9evQAALS0tDufEm7q/t+7vUY+eZmWGiIiIiMhKDNIRERFZJzk5GccccwwqKioAAP3790cS615FgiCgpaUFFRUVOOaYY5CcnKw7LQbpiIiIiMgTenAMCBERkaVOOeUUAAgH6ki9Y445Jvz96cUgHRERERF5AnvSERERWSspKQmDBw/GSSedhEAg4HR2PKNXr16GetB1Y5COiIiIiDyBQToiIiJ7JCcnmxJ0Im0YpCMiIiIiV0rPr8HSXWXhvxmjIyIiIj9jkI6IiIiIXGnExJSov5MZpSMiIiIf4/S7REREROQJHO5KREREfsYgHRERERF5Qo8eDNIRERGRf3G4KxERERG5yuqccmzMq457nTE6IiIi8jMG6YiIiIjIVf4yNV309WRG6YiIiMjHONyViIiIiDwhiXPSERERkY8xSEdEREREnsCOdERERORnDNIRERERkSdwdVciIiLyMwbpiIiIiMgTkhmkIyIiIh9jkI6IiIiIvIExOiIiIvIxBumIiIiIyBMYoyMiIiI/Y5COiIiIiDxBcDoDRERERBZikI6IiIiIvIFROiIiIvIxBumIiIiIiIiIiIgcxiAdEREREXmCwK50RERE5GMM0hERERGRJwiM0REREZGPMUhHRERERJ7AGB0RERH5GYN0REREREREREREDmOQjoiIiIiIiIiIyGEM0hERERGRJwiclI6IiIh8jEE6IiIiInINuUAcQ3RERETkZwzSEREREZFryHWWY0c6IiIi8jMG6YiIiIjINYKMxBEREVGCYpCOiIiIiFwjGOJwVyIiP9lb1oh/L9iFysZ2p7NC5Ho9nc4AEREREVG3EMe7EhH5yq/fXg8AKKhpwdT7LnM4N0Tu5qqedGvXrkVSUpLof1u2bInadvPmzbjiiivQv39/nHLKKXjsscfQ1NQUl2Z7ezueffZZDBkyBP369cPw4cOxYsUK0eOrTZOIiIiIrCHTkY496YiIPGxXcb3TWSByPVf2pHvsscfw05/+NOq1YcOGhf+9Y8cOXHPNNTj33HPx5ptvoqioCG+88Qby8vKwZMmSqP3uvfdezJ07F0888QTOOussTJ06FTfeeCPWrFmDK664QleaRERERGQNueGuRERERH7myiDdL3/5S4wYMULy/eeeew7HHnss1q5di4EDBwIAzjjjDPz1r3/F8uXLcf311wMA0tLSMHv2bIwfPx5PPfUUAOCee+7B+eefj2eeeQabN2/WnCYRERERWSfEIB0RkS9xxgIiZa4a7hqpsbERnZ2dca83NDRgxYoVuOuuu8LBNKAr+DZgwADMmTMn/NrcuXORnJyM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DCdJJiIiIiIikkdXQbqXXnoJ69evR1VVFeLj41FQUIDZs2fj8OHDXuu++eab6OrqQkJCAlJTU7Fw4UJ8+umnXut1d3fjyiuvRFFREWw2G2pra3H33XcL7l/sNomIiIiIiIiIiJSkq4kjrrjiCjz33HOYNWsWamtrceTIEezduxcNDQ148cUXUV3dk9T/gw8+QHt7O+x2O3bt2oVvvvkGV199NV5//XUcOnQI0dHRzm1ecMEF2LNnD1asWIHm5mY88MADmD9/PkwmE+bOnetcT8o2iYiIiIiIiIiIlGRyOBy6GZ30/PPPo6mpyS0g9vbbb6OmpgYzZ87EnXfeCQBYu3Yt9u/fj7feegsFBQUAgMcffxxjxozBjTfeiJUrVwIAPvzwQxQVFWHlypXYu3cvAMDhcGDEiBF499138d5778FisUjaZiDHjh2D3W7H0aNHkZSUpMwXQ0RkEM/98zOcfvOfAQDv7ZmocWmIiIiIiIi0JzZWpKvhrm1tbV491srKylBVVYU333zTuey+++7Daaed5gymAcDo0aNRXl6Oe+65x7nsgQcewA8//IC1a9c6l5lMJqxZswYffPABXnjhBcnbJCIiIiIiIiIiUpqugnRCHA4HPv74Y6SlpQHo6R33ySefoKmpyWvdlpYWvPLKK86/X3nlFcTHx2PgwIFe6/W+LnWbREREREREREREStN9kO7AgQP48MMPMWfOHADARx99BADIzs72Wjc7OxtffPEFvv/+e+e6mZmZMJlMXusBwH//+1/J2/T0/fff49ixY27/ERERERERERERSaHrIN1bb72FdevWobW1FWeccQYA4NtvvwUAxMTEeK1vs9nc1vn2229Fryd2m552794Nu93u/C8/P1/8ByQiIiIiIiIiIoKOg3RHjhzBxIkTYbfbcfDgQecED7GxsQAg2LPtu+++c1snNjZW9Hpit+lp69atOHr0qPO/999/X/yHJCIKM/qZioiIiIiIiMhYrFoXQMjRo0cxfvx4fPXVV3jmmWeQk5PjfK13SGrvEFVXH330EVJTU5094rKzs/Hkk0/C4XC4DXntfW/vdqVs01NMTIzP14iIIo1HdgEiIiIiIiISSXc96b777jtMmjQJhw8fxoMPPojKykq313Nzc5Geno6XX37Z672HDh1CXV2d8++6ujocP37cbWZYAPjzn//sfF3qNomIyDdblO6qFSIiIiIiIkPQ1d3UyZMnMWfOHLzwwgu499570draKrjejBkz8OCDD7oNLX3iiSdw+PBhzJo1y7lsypQpiIqKwg033OBc5nA4sG/fPuTm5qKtrU3yNomIyLe6/BQMKU7FjIY8rYtCRERERERkKCaHQz8ZhM4880xcd911mDRpEmbPnu31+oIFCwAA77//Purr65GcnIxNmzbhm2++wVVXXYW8vDy89NJLbsNPzz33XFx11VVYuXIlmpub8Zvf/AYPPfQQDhw4gPnz5zvXk7JNf44dOwa73Y6jR48iKSkpyG+EiIiIiIiIiIiMTGysSFdBuo6ODjz99NM+X3ct6htvvIHNmzfj2WefRXR0NCZOnIhrrrkGmZmZbu/p7u7GFVdcgRtvvBEfffQRysrKsHXrVpx++ule2xe7TX8YpCMiIiIiIiIiol6GDNKFAwbpiIiIiIiIiIiol9hYka5y0hEREREREREREUUiBumIiIiIiIiIiIg0xiAdERERERERERGRxhikIyIiIiIiIiIi0hiDdERERERERERERBpjkI6IiIiIiIiIiEhjDNIRERERERERERFpjEE6IiIiIiIiIiIijTFIR0REREREREREpDEG6YiIiIiIiIiIiDTGIB0REREREREREZHGGKQjIiIiIiIiIiLSGIN0REREREREREREGmOQjoiIiIiIiIiISGMM0hEREREREREREWmMQToiIiIiIiIiIiKNMUhHRERERERERESkMQbpiIiIiIiIiIiINMYgHRERERERERERkcYYpCMiIiIiIiIiItIYg3REREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERacyqdQHCjcPhAAAcO3ZM45IQEREREREREZHWemNEvTEjXxikU9jnn38OAMjPz9e4JEREREREREREpBeff/457Ha7z9cZpFNYamoqAOA///mP3y9ebc3NzXjppZcibt96KYPW+9e6DJH++fVSBq33r4cyaL3/Y8eOIT8/H++//z6SkpI0K4cW34PW370eyqD1/vVQhkjfvx7KoPX+9VAGrffPuoDHH78DfgdalyHSP78e9n/06FEUFBQ4Y0a+MEinMLO5J82f3W7XtBK2WCya7V/LfeulDFrvX+syRPrn10sZtN6/Hsqg9f57JSUlRdz3oIfvXusyaL1/PZQh0vevhzJovX89lEHr/fdiXaANrcug9f71UAat988y8PPrYf+9emNGPl8PUTkoxNatWxeR+9ZLGbTev9ZliPTPr5cyaL1/PZRB6/3rhRbfgx6+e63LoPX+9VCGSN+/Hsqg9f71UAat968XrAsic/96KIPW+2cZ+Pn1sH+xTI5AWetIkmPHjsFut+Po0aO6iNISEZF2WCcQERHrAiIiElsXsCedwmJiYrB9+3bExMRoXRQiItIY6wQiImJdQEREYusC9qQjIiIiIiIiIiLSGHvSERERERERERERaYxBOiIKKZPJhB07dmhdDCIi0hDrAiIiYl1A5I1BOiKSbP/+/TCZTHj55Ze1LgoREWmEdQEREbEuIFIWg3REREREREREREQaY5BOJD4hICIigPUBERGxLiAiInUwSEdEQevo6EBHR4fX8sWLF6OwsDDk5SEiotBjXUBERKwLiILDIB0REREREREREZHGGKST6bXXXsPixYtRXFwMm82GrKwsLF26FJ9//rnbejt27IDJZMI///lPLF68GMnJybDb7ViyZAmOHz+uUemJiEgprA+IiIh1ARERKcGqdQGM6rHHHsM777yDJUuWICsrC2+88QZuuukmvPHGG3jxxRdhMpnc1p89ezaKioqwe/du/PWvf8XNN9+MjIwMXHHFFRp9AiIiUgLrAyIiYl1ARERKYJBOprVr12LLli1uy4YMGYJ58+bh2WefxfDhw91eq6+vxy233OL8+/PPP8ctt9zCipiIyOBYHxAREesCIiJSAoe7yhQbG+v893fffYfPPvsMQ4YMAQD89a9/9Vp/9erVbn8PHz4cn3/+OY4dO6ZuQYlCwPPpcK+TJ0+GuCREocf6gKgH6wKKZKwLiHqwLiAKDoN0Mn3xxRfYtGkTMjMzERsbi/T0dBQVFQEAjh496rV+QUGB298pKSkAgC+//FL9whKpLCUlBV999ZXX8n//+9+hLwxRiLE+IOrBuoAiGesCoh6sC4iCw+GuMs2ePRvPP/88zjnnHNTV1SEhIQHd3d3o6upCd3e31/oWi0VwOw6HQ+2iEqmupKQEDz/8MD799FOkp6cDAF599VU899xzyM/P17h0ROpifUDUg3UBRTLWBUQ9WBcQBYdBOhm+/PJLPPHEE9i5cycuvvhi5/K3335bw1IRaWfp0qX40Y9+hHHjxmHZsmX45JNPsG/fPlRVVXHYBoU11gdEfVgXUKRiXUDUh3UBUXA43FWG3idfnk+6rr32Wg1KQxR6vcd+77kwcOBA3H777Th69Cg2b96M3/72t7jjjjvQ0NCgZTGJVMf6gCIZ6wKiHqwLKJKxLiBSFnvSyZCUlIT29nZceeWV+OGHH5Cbm4s//OEPePfdd7UuGlFIfP311wB6zoVep59+Ok4//XS39caOHev1Xg7joHDC+oAiGesCoh6sCyiSsS4gUhZ70onk+YTgrrvuwrhx43D99ddj69atiIqKwu9//3sti0gUMi+99BLi4+PRv39/rYtCFHKsD4h6sC6gSMa6gKgH6wIiZZkcDF+L8pOf/ASbNm3CP//5T5SUlGhdHCJN3HfffXjqqadw/fXXY/ny5bjpppu0LhJRyLE+oEjHuoCIdQER6wIidXC4q0h8QkAEnH322fj666+xbNky/PjHP9a6OESaYH1AkY51ARHrAiLWBUTqYJAugN4nBAcOHMDy5cthtfIro8jF3CoUyVgfEPVgXUCRjHUBUQ/WBUTq4HDXAIqKivD1119j2rRpuPbaaxEfH691kYiISAOsD4iIiHUBERGpiUE6IiIiIiIiIiIijXF2VyIiIiIiIiIiIo0xSEdERERERERERKQxBumIiIiIiIiIiIg0xiAdeqZQX79+PaqqqhAfH4+CggLMnj0bhw8f9lr3zTffRFdXFxISEpCamoqFCxfi008/9Vrv8ssvx+TJk5GZmQmTyYQdO3YI7vv+++/HnDlzUFxcjLi4OAwYMABbtmzBV199pfCnJCIiMbSsE379619j3LhxyMnJQUxMDPLy8jBz5kz8/e9/V/pjEhGRH1rWBZ7GjBkDk8mE9evXB/uxiIhI5zhnOIArrrgCzz33HGbNmoXa2locOXIEe/fuRUNDA1588UVUV1cDAD744AO0t7fDbrdj165d+Oabb3D11Vfj9ddfx6FDhxAdHe3c5oUXXoisrCzU19fj0Ucf9bnvlStXIicnBwsWLEBBQQFef/117N27Fw8//DD++te/IjY2VvXPT0REfbSsE15//XWkpKRg06ZNSEtLw5EjR/CLX/wCLS0teOGFFzBo0CDVPz8REWlbF7i6//778cILL6jyGYmISIcc5Hjuuecc33//vduyw4cPO2JiYhynn366c9maNWscsbGxjn//+9/OZY899pgDgOPGG290e/+7777rcDgcjk8//dQBwLF9+3bBfT/55JNey2677TYHAMfPf/5zeR+IiIhk07JOEHLkyBGH1Wp1rFq1SvqHISIiWfRQF3z77beOwsJCxyWXXOIA4Fi3bl1wH4qIiHSPw10BtLW1uT3lAoCysjJUVVXhzTffdC677777cNppp6GgoMC5bPTo0SgvL8c999zj9v7CwkJR++7o6PBaNm3aNABw2zcREYWGlnWCkIyMDMTFxTENAhFRCOmhLrjyyivR3d2Ns88+W/oHICIiQ2KQzgeHw4GPP/4YaWlpAIAPP/wQn3zyCZqamrzWbWlpwSuvvKLYvo8cOQIAzn0TEZG2Ql0nfPXVV/j000/x+uuvY/ny5Th27BhGjRoV1DaJiCg4oawL/vOf/2DPnj244oormP6GiCiCMEjnw4EDB/Dhhx9izpw5AICPPvoIAJCdne21bnZ2Nr744gt8//33iuz7iiuugMViwcyZMxXZHhERBSfUdcKQIUOQkZGB2tpa3HPPPbjwwguxbNky2dsjIqLghbIu2LJlC+rr6zF37lz5BSYiIsPhxBEC3nrrLaxbtw6tra0444wzAADffvstACAmJsZrfZvN5lxH6HUp7rrrLtxyyy0499xzUVZWFtS2iIgoeFrUCbfeeiuOHTuGd955B7feeiu+/fZbnDx5EmYzn60REWkhlHXBk08+ifvuuw9//vOfgyw1EREZDYN0Ho4cOYKJEyfCbrfj4MGDsFgsAODsZi70NOy7775zW0euZ555BsuWLcO4ceNw+eWXB7UtIiIKnlZ1Qmtrq/Pfc+fOxcCBAwEAV199textEhGRPKGsC06cOIGNGzdi4cKFaG5uDrLkRERkNHwk7+Lo0aMYP348vvrqKzzyyCPIyclxvtbbjb23W7urjz76CKmpqUH1onv11VcxefJkVFdX4+DBg7BaGT8lItKSlnWCq5SUFIwcORIHDhxQZHtERCReqOuC22+/Hf/4xz+watUqvPfee87/AODrr7/Ge++9h+PHj8v/QEREpGsM0p3y3XffYdKkSTh8+DAefPBBVFZWur2em5uL9PR0vPzyy17vPXToEOrq6mTv+1//+he6urqQkZGBhx9+GAkJCbK3RUREwdOyThDy7bff4ujRo4puk4iI/NOiLvjPf/6DH374AUOHDkVRUZHzP6AngFdUVIQ//OEPsj4PERHpH7trATh58iTmzJmDF154AQ888IDbMCNXM2bMwG233Yb3338f+fn5AIAnnngChw8fxllnnSVr30eOHMHYsWNhNpvx6KOPIj09XfbnICKi4GlZJ3zyySfIyMhwW/bee+/hiSeeEJw9kIiI1KFVXTB37lzB4N60adMwYcIErFixAoMHD5a8XSIiMgaTw+FwaF0IrZ155pm47rrrMGnSJMyePdvr9QULFgAA3n//fdTX1yM5ORmbNm3CN998g6uuugp5eXl46aWX3Lqz33HHHfj3v/+N48ePY/fu3ejs7MTIkSMBAAsXLkT//v0BAHV1dXj11Vdx7rnnoqamxm2/mZmZGDNmjFofm4iIBGhZJ2RmZmLUqFGoq6tDSkoK3n77bdxyyy04fvw4nnjiCbS1tYXgGyAiIi3rAiEmkwnr1q3D3r17Ff6kRESkJwzSAejo6MDTTz/t83XXr+iNN97A5s2b8eyzzyI6OhoTJ07ENddcg8zMTNHbfPLJJ9HR0QGgp8L1ZcSIEXjqqafEfxAiIgqalnXCjh078NBDD+Ff//oXvv76a2RkZKC9vR3btm3zepBDRETq0bIuEMIgHRFRZGCQjoiIiIiIiIiISGOcOIKIiIiIiIiIiEhjDNIRERERERERERFpjEE6IiIiIiIiIiIijTFIR0REREREREREpDEG6YiIiIiIiIiIiDTGIB0REREREREREZHGGKQjIiIiIiIiIiLSGIN0REREREREREREGmOQjoiIiCgMFBYWYvHixVoXg4iIiIhkYpCOiIiIyECef/557NixA1999ZXWRRHt+PHj2LFjB5566imti0JERESkW1atC0BERERE4j3//PPYuXMnFi9ejOTkZOfyf/zjHzCb9fn89fjx49i5cycAoKOjQ9vCEBEREekUg3REREREYSAmJkbrIhARERFREPT5uJWIiIiIvOzYsQPnnHMOAKCoqAgmkwkmkwnvvfeeV066/fv3w2Qy4dlnn8XGjRuRnp6O5ORkrFq1Cv/73//w1VdfYdGiRUhJSUFKSgrOPfdcOBwOt/11d3fj2muvRVVVFWw2GzIzM7Fq1Sp8+eWXbuu9/PLLGDduHNLS0hAbG4uioiIsXboUAPDee+8hPT0dALBz505nmXfs2AEAeO2117B48WIUFxfDZrMhKysLS5cuxeeff+712U0mEw4fPowFCxbAbrcjPT0dF110ERwOB95//31MmTIFSUlJyMrKwjXXXOP2/qeeegomkwm/+tWvsG3bNmRlZSE+Ph6TJ0/G+++/H/RvQ0RERBQs9qQjIiIiMojp06fj8OHDuPvuu/HjH/8YaWlpAOAMggnZsGEDsrKysHPnTrz44ou46aabkJycjOeffx4FBQXYtWsXHn74YVx11VWorq7GokWLnO9dtWoV9u/fjyVLlmDjxo149913sXfvXrzyyit47rnnEBUVhU8++QRjx45Feno6zj//fCQnJ+O9997D/fff7yzbz372M6xZswbTpk3D9OnTAQC1tbUAgMceewzvvPMOlixZgqysLLzxxhu46aab8MYbb+DFF1+EyWRy+zxz5szBwIEDsWfPHjz00EO47LLLkJqaihtvvBEjR47EFVdcgQMHDuDss89Gc3Mz2tvb3d5/+eWXw2Qy4bzzzsMnn3yCa6+9FqNHj8bf/vY3xMbGBv8jEREREcnlICIiIiLDuOqqqxwAHO+++67b8v79+zvOOOMM59+33nqrA4Bj3Lhxju7ubufy1tZWh8lkcqxevdq57MSJE468vDzHiBEjnMueeeYZBwDHgQMH3PbzyCOPuC3/9a9/7QDgeOmll3yW+dNPP3UAcGzfvt3rtePHj3stu/vuux0AHH/605+cy7Zv3+4A4Fi5cqVXuU0mk2PPnj3O5V9++aUjNjbW7ft48sknHQAcubm5jmPHjjmX33PPPQ4Ajuuuu85n+YmIiIhCgcNdiYiIiMLYsmXL3HqjDR48GA6HA8uWLXMus1gsaGpqwjvvvONcdu+998Jut2PMmDH47LPPnP81NjYiISEBTz75JAA4J6948MEH8cMPP0gun2vvte+++w6fffYZhgwZAgD461//6rX+8uXLvcrt+XmSk5MxYMAAt8/Ta9GiRUhMTHT+PXPmTGRnZ+Phhx+WXHYiIiIiJTFIR0RERBTGCgoK3P622+0AgPz8fK/lrrnm3n77bRw9ehQZGRlIT093+++bb77BJ598AgAYMWIEZsyYgZ07dyItLQ1TpkzBrbfeiu+//15U+b744gts2rQJmZmZiI2NRXp6OoqKigAAR48eFfV5bDabc+ivr8/Tq6yszO1vk8mE0tJSvPfee6LKS0RERKQW5qQjIiIiCmMWi0X0cofLxBHd3d3IyMjAgQMHBN/fmwfPZDLh4MGDePHFF/G73/0Ojz76KJYuXYprrrkGL774IhISEvyWb/bs2Xj++edxzjnnoK6uDgkJCeju7kZXVxe6u7tFldvXZ3R4TIRBREREpGcM0hEREREZiOdECmopKSnB448/jqFDh4qaUGHIkCEYMmQILr/8ctx11104/fTT8ctf/hLLly/3WeYvv/wSTzzxBHbu3ImLL77Yufztt99W7HN48ty2w+HAP//5T+dEFkRERERa4XBXIiIiIgOJj48HAHz11Veq7mf27Nk4efIkLr30Uq/XTpw44dz/l19+6dVjra6uDgCcQ17j4uIAeJe5twec5/uvvfbaIEvv2+23346vv/7a+ffBgwfx0UcfYfz48artk4iIiEgM9qQjIiIiMpDGxkYAwAUXXIC5c+ciKioKkyZNUnw/I0aMwKpVq7B792787W9/w9ixYxEVFYW3334b9957L6677jrMnDkTt912G2644QZMmzYNJSUl+Prrr/Hzn/8cSUlJmDBhAoCeySEqKyvxq1/9CuXl5UhNTUV1dTWqq6vR3t6OK6+8Ej/88ANyc3Pxhz/8Ae+++67in6dXamoqhg0bhiVLluDjjz/Gtddei9LSUqxYsUK1fRIRERGJwSAdERERkYE0Nzfj0ksvxb59+/DII4+gu7tbtaDWvn370NjYiBtvvBHbtm2D1WpFYWEhFixYgKFDhwLoCeYdOnQIv/zlL/Hxxx/DbrejpaUFBw4ccE4AAQA333wzNmzYgLPOOgv/+9//sH37dlRXV+Ouu+7Chg0bcP3118PhcGDs2LH4/e9/j5ycHFU+07Zt2/Daa69h9+7d+PrrrzFq1CjccMMNzt5+RERERFoxOZhRl4iIiIjC3FNPPYXOzk7ce++9mDlzptbFISIiIvLCnHREREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERaYw56YiIiIiIiIiIiDTGnnREREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERaYxBOiIiIiIiIiIiIo0xSEdERERERERERKQxBumIiIiIiIiIiIg0xiAdERERERERERGRxhikIyIiIiIiIiIi0hiDdERERERERERERBr7/9EpyC0/yJTEAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "energy.plot(y='load', subplots=True, figsize=(15,8), fontsize=12)\n", + "plt.xlabel('timestamp', fontsize= 12)\n", + "plt.ylabel('load',fontsize= 12)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABOkAAALYCAYAAAApV6ZAAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3hbhbk/8O/RtmxZ3tuZzk4gJCGBEBK4hBBSyg4Fyp6FllxoaSmj3PsrBXqbQqGTckvZl0IDAZoykgBhZRGyp7OceO8hW9Y+vz+kc2zHceIh6Qx9P8/jp0WWj17bJ7LOq3cIoiiKICIiIiIiIiIiIsUYlA6AiIiIiIiIiIgo0TFJR0REREREREREpDAm6YiIiIiIiIiIiBTGJB0REREREREREZHCmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjoiIiIiIiIiISGEmpQPQm1AohKqqKjgcDgiCoHQ4RERERERERESkIFEU4XK5UFBQAIOh73o5JumirKqqCsXFxUqHQUREREREREREKlJeXo6ioqI+P88kXZQ5HA4A4R98amqqwtEQEREREREREZGS2traUFxcLOeM+sIkXZRJLa6pqalM0hEREREREREREQCcdCwaF0cQEREREREREREpjEk6IiIiIiIiIiIihTFJR0REREREREREpDDOpCMiIiIiIiIiIlkwGITf71c6DM0wm80wGo1DPg6TdEREREREREREBFEUUVNTg5aWFqVD0Zy0tDTk5eWddDnEiTBJR0REREREREREcoIuJycHdrt9SAmnRCGKItxuN+rq6gAA+fn5gz4Wk3RERERERERERAkuGAzKCbrMzEylw9GUpKQkAEBdXR1ycnIG3frKxRFERERERERERAlOmkFnt9sVjkSbpJ/bUGb5MUlHREREREREREQAwBbXQYrGz41JOiIiIiIiIiIiIoUxSUdERERERERERKQwJumIiIiIiIiIiEizzjnnHNx7772afwwm6YiIiIiIiIiIiBTGJB0REREREREREZHCmKQjIiIiIiIiIqJeRFGE2xeI+4coioOOubm5GTfccAPS09Nht9tx4YUXYv/+/fLnGxsbcc0116CwsBB2ux1TpkzBG2+80eMYHR0duOGGG5CSkoL8/Hw89dRTg45nIExxeRQiIiIiIiIiItKUTn8QEx/9OO6Pu/uXF8BuGVzK6qabbsL+/fvx/vvvIzU1FQ888AAWLVqE3bt3w2w2w+PxYPr06XjggQeQmpqKf//737j++usxevRozJw5EwDw05/+FJ9//jnee+895OTk4KGHHsLmzZsxderUKH6XvTFJR0REREREREREmicl577++mvMnj0bAPD666+juLgY7777LhYvXozCwkLcf//98tfcc889+Pjjj/HWW29h5syZaG9vxwsvvIDXXnsN5513HgDg5ZdfRlFRUczjZ5KOiIiIiIiIiIh6STIbsfuXFyjyuIOxZ88emEwmzJo1S74tMzMT48aNw549ewAAwWAQTzzxBN566y1UVlbC5/PB6/XCbrcDAA4ePAifz9fjGBkZGRg3btwQvqP+YZKOiIiIiIiIiIh6EQRh0G2narV06VI8++yzeOaZZzBlyhQkJyfj3nvvhc/nUzo0Lo4gIiIiIiIiIiLtmzBhAgKBADZs2CDf1tjYiH379mHixIkAgK+//hqXXHIJrrvuOpx66qkYNWoUSktL5fuPHj0aZrO5xzGam5t73CdWmKQjIiIiIiIiIiLNGzNmDC655BLcfvvt+Oqrr7Bt2zZcd911KCwsxCWXXCLfZ9WqVVi7di327NmDO++8E7W1tfIxUlJScOutt+KnP/0pPv30U+zcuRM33XQTDIbYp9CYpCMiIiIiIiIiIl148cUXMX36dFx00UU488wzIYoiPvjgA5jNZgDAI488gmnTpuGCCy7AOeecg7y8PFx66aU9jrF06VKcffbZ+O53v4v58+djzpw5mD59esxjF0RRFGP+KAmkra0NTqcTra2tSE1NVTocIiIiIiIiIqKT8ng8OHz4MEaOHAmbzaZ0OJpzop9ff3NFrKQjIiIiIiIiIiJSGJN0RERR5AuEcPOLG3Hby5vQ7g0oHQ4RERERERFpBJN0RERR9Namcny2rx6r99Tilhe/gdvHRB0RERERERGdHJN0RERR4vEH8cdPDwAABAHYWNaEW1/ahE5fUOHIiIiIiIiI+oerCwYnGj83JumIiKLk/zYcRU2bB/lOG/7vtjOQbDFi3aFG3PHqJnj8TNQREREREZF6SdtP3W63wpFok/Rzk36Og6GqJN2aNWsgCMJxP9avX9/jvmvXrsWcOXNgt9uRl5eHJUuWoL29vdcxvV4vHnjgARQUFCApKQmzZs3CqlWrjvv4/T0mEdGx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00y2XutKls6SdNxCrH3S747trmGcRzcwZ47OxNyx2fAHRfxudd+vS4mIYm1vTRsu+eNX+PeOapgMAn55yST87ntTYbeoslluUKwmozymghtew+NjfMEQDALksUakTjl6WxxxLKkdtbW1721aLpcLDQ0NyM7Olm+bOnUq3G439uzZ0+O+GzZskD8PAIWFhcjOzsamTZt6HXfjxo3y/fRGumjOTLby3XOdKoq8wyKVRauVVNHiTDLDajIqHA1Fk5R0ld4U0DrOTtS+7FRW0nXHza4D97MLxgEA3t1aib012loYRkTad6i+Hff+YwsufPZLHKzvQG6qFW/eeSZuOHOELttB5QH8nEsnzxnPTbXBbNREKidh5UbO2zqtL46oq6vrdZvf78crr7yCpKQkTJw4ER6PBy6Xq9f9HnvsMYiiiIULF8q3XXLJJTCbzfjzn/8s3yaKIp577jkUFhZi9uzZ8u1XXHEFVqxYgfLyro1dn3zyCUpLS7F48eJofYuqIs8Ac7BySa+KIpV0lc3qbslh4kO/dFdJx8URmidV0g3mRZMesZJu4CYXOvGdU/IhisBvP96ndDhElCCONrpx/z+3Yf7Tn+PdrVUQRWDhpDysuOdsTB+u7QURJyJVjNW2spKuiq2umqGbxRF33nkn2traMHfuXBQWFqKmpgavv/469u7di6eeegopKSkoKyvDaaedhmuuuQbjx4fngnz88cf44IMPsHDhQlxyySXy8YqKinDvvfdi6dKl8Pv9OP300/Huu+/iyy+/xOuvvw6jsati56GHHsI///lPnHvuufjP//xPtLe3Y+nSpZgyZQpuvvnmuP8s4oEXm/ontbtWtnSqethqPbcM65b0/NLk9iEQDMGk8Xf9mFDWvq6ZdHyxL4oiK+kG6Sfnj8VHO2uwek8dNpU1YcaIDKVDIiKdqmh240+fHcA/N1UgEAqPh5k/IQf3zh+LyYVOhaOLvVzH4NsG9YabXbVDmqfY4Qui3RtAirX/qTdVJem+973v4YUXXsBf/vIXNDY2wuFwYPr06fif//kfXHzxxQCAtLQ0XHTRRVi1ahVefvllBINBlJSU4IknnsD9998Pg6HnBeCvf/1rpKen469//SteeukljBkzBq+99hquvfbaHvcrLi7G559/jh//+Mf4+c9/DovFgu985zt46qmndDmPDgAaIu1nTNLpV74z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f8rKygb42xIRERERDc7sYYGW1y921yjy+qsPcB4d9TZ3ZKCa7tsidbS8HqpjqysRqZNqk3TV1dU477zzYLfb8c4778gLHo7m7rvvhsFgwJdffinfFhMTc8QKOJfLJf+8+//25b4/ZLVakZiY2OMPEREREZESLpySDUEAvtpbiz1VkR3D0tzuxs5KBwDOo6OepJbXb4vqFZuX2F1RrRMAk3REpD6qTNI5HA6cc845aG5uxqeffoqhQ4ce9zExMTFISUlBY2OjfFtWVhaqq6t7fRBI7a3S80ptrtLtP7xvcnLyEavsiIiIiIjUZER6PM6dGPhu++z/DkT0tdcebIAoAiPT45GRaIvoa5O6zSpMhtVkQHWLC/trW4//gDBbVRSo+JyWp55ts0REgAqTdC6XCxdccAGKiorw0UcfYdy4cX16nNPpRH19PdLS0uTbpkyZgvb29l6bYb///nv55wCQnZ2NtLQ0bNy4sdfzrl+/Xr4fEREREZHa3X7aCADAJzursL/GGbHX7T6Pjqg7m9mIE4Kt2N/sU7bltdrhwu6qFggCMG902vEfQEQUQapK0vl8PixcuBBr167FihUrMHv27F73cblccDp7f9l49NFHIYoizj77bPm2iy66CGazGc8//7x8myiKeOGFF5CdnY2TTjpJvv0nP/kJPvroox4z5b766isUFRVhwYIFofoViYiIiIjCakxmIs4anwFRBJ5dGblqutVM0tExnBJsef18d7WicazcVwsAmJyThJR4dksRkbqoapXNvffei//85z+44IIL0NjYiNdff73Hz6+88kpUV1dj6tSp+OlPf4oxY8YAAD777DN88sknOPvss3HRRRfJ98/JycFdd92FpUuXwuPxYObMmXj//fexatUqLF++vMecuwcffBArVqzAqaeeijvvvBOtra1YunQpJk6ciOuuuy4yfwFERERERCFw+2kj8dmuGny4rRJ3nj4Sw9Liw/p6ZY3tKGloh9Eg4IRhyWF9LdKmcydmYskne7ChpAl7q1swJlOZWd4r9waSdKeNSVfk9YmIjkVVSbqtW7cCAD788EN8+OGHvX5+5ZVXIikpCeeffz6++OILvPLKK/D5fBgxYgSWLFmC++67DwZDz+LAxx9/HEOGDMGLL76IZcuWYeTIkXj99ddx+eWX97hfbm4uvvnmG9xzzz341a9+BYvFgvPO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1QCAeKsJt582AteeXACryajwb0FE1H+spAsxVtIREREREREN3pbDTbjsxbXw+I59ymoQgIUz83DPGaOQlmCNUHRERH3HSjoiIiIiIiLSrKl5Q/DwhePx6/d2Aggk45LjLEiNtwb/WJCRaMOPp2ZjbBYLJIhI+5ikIyIiIiIiIlW64oR8nDYmHSaDAclxFm5qJaKoxiQdERERERERqVaWPUbpEIiIIsKgdABERERERERERER6xyQdERERERERERGRwpikIyIiIiIiIiIiUhiTdERERERERERERApjko6IiIiIiIiIiEhhTNIREREREREREREpjEk6IiIiIiIiIiIihTFJR0REREREREREpDAm6YiIiIiIiIiIiBTGJB0REREREREREZHCmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjoiIiIiIiIiISGFM0hERERERERERESmMSToiIiIiIiIiIiKFMUlHRERERERERESkMCbpiIiIiIiIiIiIFMYkHRERERERERERkcKYpCMiIiIiIiIiIlIYk3REREREREREREQKY5KOiIiIiIiIiIhIYUzSERERERERERERKYxJOiIiIiIiIiIiIoUxSUdERERERERERKQwk9IBRBtRFAEALS0tCkdCRERERERERERKk3JEUs7oaJikC7GGhgYAQG5ursKREBERERERERGRWjQ0NMButx/150zShVhycjIA4PDhw8f8iydSwsyZM7FhwwalwyA6Ih6fpFY8NkmteGySWvHYJLXisUlKcTgcyMvLk3NGR8MkXYgZDIExf3a7HYmJiQpHQ9ST0WjkcUmqxeOT1IrHJqkVj01SKx6bpFY8NklpUs7oqD+PUBxEpAK33nqr0iEQHRWPT1IrHpukVjw2Sa14bJJa8dgktRPE402to35paWmB3W6Hw+Fghp6IiIiIiIiISOf6mitiJV2IWa1WPPTQQ7BarUqHQkRERERERERECutrroiVdERERERERERERApjJR0REREREREREZHCmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjiiKdHZ24pe//CWGDh2KmJgYnHDCCfjiiy/kn7e3t+O5557DmWeeiaysLCQkJGDq1Kn429/+Bp/Pp2DkFO2Od2wCwJIlS3DiiSciLS0NNpsNI0eOxF133YW6ujqFoiY96Mux2V1zczPS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3/z+++9x4MABVtGR6jBJ10+DubJJFE6XXnopfD4f/v73v8u3dXZ24uWXX8YJJ5wgX1n/9ttvsWjRIsydOxfLly/n/AUKu74cm21tbWhvb+/12HfffRdNTU2YMWNGJEMmnejLsfmHP/wB7733Xo8/jz76KADg/vvvx3vvvYe4uDilfgWKUn05NltaWnpdOBZFEX/4wx8AAGeddVZEYyZ96MuxmZCQgHPPPRdr1qzB3r175fvt2bMHa9aswRlnnKFE6BTl+nouJHnjjTcAAJdffnlE4yQ6Hs6k66cpU6Zg5cqVaGlp6bE8oq8VIUThcsIJJ2DBggV44IEHUFtbixEjRuCVV15BSUmJPFi6tLQUF154IQRBwKWXXooVK1b0eI5JkyZx2xaFXF+Ozf3792P+/PlYuHAhxowZA4PBgI0bN+L1119HQUEB7rzzToV/C4pGfTk258yZ0+txSUlJAICZM2fixz/+cQQjJr3oy7G5efNm/PSnP8VPf/pTjBgxAh0dHXjvvfewevVqLF68GNOmTVP4t6Bo1JdjEwhscv3qq69w2mmn4Y477gAA/PWvf0VycjKX8FBY9PXYBACfz4e3334bJ554IoYPH65QxERHIVK/rFu3TgQgLl26VL7N5XKJI0aMEE844YQjPua8884T8/PzIxQh6VlHR4d43333iZmZmaLVahVnzpwpfvrpp/LPV65cKQI46p+HHnpIueApqh3v2KyrqxMXL14sjhkzRoyLixMtFos4cuRI8a677hLr6uoUjJyi3fGOzSOR3ktXrFgRoShJj453bBYXF4sLFiwQCwoKRJvNJsbGxorTp08XX3jhBdHv9ysYOUW7vr5vbtq0SZw/f74YFxcnJiQkiBdddJFYVFSkQMSkF309Nj/99FMRgPjXv/5VgSiJjk0QRVFUKkGoVZdddhnee+893H333XKGfv369fjqq68wd+5cAMD27dvxn//8BwDw+uuvo6amBvfeey8AYPLkybjgggsUi5+IiIiIiIiIiNSFSboBcLlc+O1vf4vXX38dTU1NmDRpEh599NEesz+WLVuG66677oiPv+aaa7Bs2bIIRUtERERERERERGrHJB0REREREREREZHCuNaRiIiIiIiIiIhIYUzSERERERERERERKYxJOiIiIiIiIiIiIoUxSUdERERERERERKQwJumIiIiIiIiIiIgUxiQdERERERERERGRwpikizBBEPDwww8rHQYREREREREREakIk3QDsGzZMgiCgI0bNyodChERERERERERRQEm6YiIiIiIiIiIiBTGJB0REREREREREZHCmKQLgXnz5mHevHm9br/22mtRUFAQ8XiIiIiIiIiIiEhbmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjoiIiIiIiIiISGFM0hERERERERERESmMSboQEAThiLf7fL4IR0JERERERERERFrEJF0IDBkyBM3Nzb1uLy0tjXwwRERERERERESkOUzShcDw4cOxd+9e1NXVybdt27YNq1evVjAqIiIiIiIiIiLSCibpQuD666+Hx+PBWWedheeeew4PPfQQzjzzTIwfP17p0IiIiIiIiIiISAOYpBsAURQBAEajEQAwduxYvPrqq3A4HLjnnnvwn//8B6+99hqmTZumZJhERERERERERKQRJqUD0CKn0wkASExMlG+74oorcMUVV/S435lnntnrsVKCj4iIiIiIiIiISMJKugHYsGED4uLikJ+fr3QoREREREREREQUBVhJ1w/vvvsuvv76ayxfvhw33HADTCb+9RERERERERER0eAJIvsv+6ywsBBOpxMXX3wxnn76acTFxSkdEhERERERERERRQEm6YiIiIiIiIiIiBTGmXREREREREREREQKY5KOiIiIiIiIiIhIYUzSBW3YsAG33XYbxo8fj7i4OOTl5eGyyy5DUVFRr/vu2bMHZ599NuLj45GcnIyrrroKdXV1ve73xz/+ERdeeCEyMjIgCAIefvjhPsVyxhlnQBAE3HbbbYP9tYiIiIiIiIiISAO4njToT3/6E1avXo0FCxZg0qRJqK6uxrPPPotp06Zh3bp1mDBhAgCgvLwcc+fOhd1ux5IlS9Da2oo///nP2LFjB9avXw+LxSI/529+8xtkZmZi6tSp+Oyzz/oUx7///W+sXbs2LL8jERERERERERGpE5N0Qffccw/eeOONHkm2hQsXYuLEiXj88cfx+uuvAwCWLFmCtrY2bNq0CXl5eQCAWbNm4YwzzsCyZcuwePFi+fGHDh1CQUEB6uvrkZaWdtwYXC4X7r33Xvzyl7/E7373uxD/hkREREREREREpFZsdw066aSTeiToAGDkyJEYP3489uzZI9/27rvv4vzzz5cTdAAwf/58jBo1Cv/61796PL6goKBfMTzxxBPw+/247777+v8LEBERERERERGRZjFJdwyiKKKmpgapqakAgIqKCtTW1mLGjBm97jtr1ixs2bJlwK91+PBhPP744/jTn/6EmJiYAT8PERERERERERFpD5N0x7B8+XJUVFRg4cKFAICqqioAQFZWVq/7ZmVlobGxEZ2dnQN6rXvvvRdTp07FokWLBh4wERERERERERFpEmfSHcXevXtx6623Yvbs2bjmmmsAAB0dHQAAq9Xa6/42m02+z5F+fiwrV67Eu+++i++//36QURMRERERERERkRaxku4Iqqurcd5558Fut+Odd96B0WgEALkN9UjVci6Xq8d9+srr9eKOO+7AVVddhZkzZw4yciIiIiIiIiIi0iJW0v2Aw+HAOeecg+bmZqxatQpDhw6Vfya1uUptr91VVVUhOTm531V0r776Kvbt24cXX3wRJSUlPX7mdDpRUlKC9PR0xMbG9v+XISIiIiIiIiIiTWAlXTculwsXXHABioqK8NFHH2HcuHE9fp6dnY20tDRs3Lix12PXr1+PKVOm9Ps1Dx8+DI/Hg5NPPhmFhYXyHyCQwCssLMTnn38+oN+HiIiIiIiIiIi0gZV0QT6fDwsXLsTatWvxwQcfYPbs2Ue8309+8hO88sorKCsrQ25uLgDgq6++QlFREe6+++5+v+6iRYuOmNy7+OKLce655+LGG2/ECSec0O/nJSIiIiIiIiIi7RBEURSVDkIN7rrrLjzzzDO44IILcNlll/X6+ZVXXgkAKCsrw9SpU5GUlIQ777wTra2tWLp0KXJycrBhw4Ye7a6vvfYaSktL0d7ejsceewynnnoqTjvtNADAVVddhfz8/KPGIwgCbr31Vjz77LMh/k2JiIiIiIiIiEhtmKQLmjdvHr755puj/rz7X9OuXbtwzz334LvvvoPFYsF5552HJ598EhkZGX1+zpUrV2LevHlHfT0m6YiIiIiIiIiI9INJOiIiIiIiIiIiIoVxcQQREREREREREZHCmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjoiIiIiIiIiISGFM0hERERERERERESmMSToiIiIiIiIiIiKFMUlHRERERERERESkMCbpiIiIiIiIiIiIFMYkHRERERERERERkcKYpCMiIiKKAgUFBbj22muVDoOIiIiIBohJOiIiIiINWbNmDR5++GE0NzcrHUqftbe34+GHH8bXX3+tdChEREREqmVSOgAiIiIi6rs1a9bgkUcewbXXXoukpCT59n379sFgUOf11/b2djzyyCMAgHnz5ikbDBEREZFKMUlHREREFAWsVqvSIRARERHRIKjzcisRERER9fLwww/jF7/4BQCgsLAQgiBAEASUlJT0mkm3bNkyCIKA7777DnfccQfS0tKQlJSEm266CW63G83Nzbj66qsxZMgQDBkyBPfffz9EUezxen6/H08//TTGjx8Pm82GjIwM3HTTTWhqaupxv40bN+Kss85CamoqYmJiUFhYiOuvvx4AUFJSgrS0NADAI488Isf88MMPAwC2b9+Oa6+9FsOGDYPNZkNmZiauv/56NDQ09PrdBUFAUVERrrzyStjtdqSlpeG3v/0tRFFEWVkZLrroIiQmJiIzMxNPPvlkj8d//fXXEAQBb7/9Nh588EFkZmYiLi4OF154IcrKygb934aIiIhosFhJR0RERKQRl1xyCYqKivDmm2/iqaeeQmpqKgDISbAjuf3225GZmYlHHnkE69atw9///nckJSVhzZo1yMvLw5IlS/DJJ59g6dKlmDBhAq6++mr5sTfddBOWLVuG6667DnfccQcOHTqEZ599Flu2bMHq1athNptRW1uLM888E2lpafjVr36FpKQklJSU4N///rcc29/+9jfcfPPNuPjii3HJJZcAACZNmgQA+OKLL1BcXIzrrrsOmZmZ2LVrF/7+979j165dWLduHQRB6PH7LFy4EGPHjsXjjz+Ojz/+GH/4wx+QnJyMF198Eaeddhr+9Kc/Yfny5bjvvvswc+ZMzJ07t8fj//jHP0IQBPzyl79EbW0tnn76acyfPx9bt25FTEzM4P8jEREREQ2USERERESasXTpUhGAeOjQoR635+fni9dcc438/19++WURgHjWWWeJfr9fvn327NmiIAjiz3/+c/k2r9cr5uTkiKeccop826pVq0QA4vLly3u8zqefftrj9vfee08EIG7YsOGoMdfV1YkAxIceeqjXz9rb23vd9uabb4oAxG+//Va+7aGHHhIBiIsXL+4VtyAI4uOPPy7f3tTUJMbExPT4+1i5cqUIQMzOzhZbWlrk2//1r3+JAMRnnnnmqPETERERRQLbXYmIiIii2M9+9rMe1WgnnHACRFHEz372M/k2o9GIGTNmoLi4WL5txYoVsNvtOOOMM1BfXy//mT59OuLj47Fy5UoAkJdXfPTRR/B4PP2Or3v1msvlQn19PU488UQAwObNm3vd/4YbbugV9w9/n6SkJIwePbrH7yO5+uqrkZCQIP//Sy+9FFlZWfjkk0/6HTsRERFRKDFJR0RERBTF8vLyevx/u90OAMjNze11e/dZc/v374fD4UB6ejrS0tJ6/GltbUVtbS0A4JRTTsFPfvITPPLII0hNTcVFF12El19+GZ2dnX2Kr7GxEXfeeScyMjIQExODtLQ0FBYWAgAcDkeffh+bzSa3/h7t95GMHDmyx/8XBAEjRoxASUlJn+IlIiIiChfOpCMiIiKKYkajsc+3i90WR/j9fqSnp2P58uVHfLw0B08QBLzzzjtYt24dPvzwQ3z22We4/vrr8eSTT2LdunWIj48/ZnyXXXYZ1qxZg1/84heYMmUK4uPj4ff7cfbZZ8Pv9/cp7qP9juIPFmEQERERqRmTdEREREQa8sNFCuEyfPhwfPnllzj55JP7tFDhxBNPxIknnog//vGPeOONN3DFFVfgrbfewg033HDUmJuamvDVV1/hkUcewe9+9zv59v3794fs9/ihHz63KIo4cOCAvMiCiIiISClsdyUiIiLSkLi4OABAc3NzWF/nsssug8/nw6OPPtrrZ16vV379pqamXhVrU6ZMAQC55TU2NhZA75ilCrgfPv7pp58eZPRH9+qrr8LpdMr//5133kFVVRXOOeecsL0mERERUV+wko6IiIhIQ6ZPnw4A+PWvf41FixbBbDbjggsuCPnrnHLKKbjpppvw2GOPYevWrTjzzDNhNpuxf/9+rFixAs888wwuvfRSvPLKK3j++edx8cUXY/jw4XA6nXjppZeQmJiIc889F0BgOcS4cePw9ttvY9SoUUhOTsaECRMwYcIEzJ07F0888QQ8Hg+ys7Px+eef49ChQyH/fSTJycmYM2cOrrvuOtTU1ODpp5/GiBEjcOONN4btNYmIiIj6gkk6IiIiIg2ZOXMmHn30Ubzwwgv49NNP4ff7w5bUeuGFFzB9+nS8+OKLePDBB2EymVBQUIArr7wSJ598MoBAMm/9+vV46623UFNTA7vdjlmzZmH58uXyAggA+Mc//oHbb78dd999N9xuNx566CFMmDABb7zxBm6//XY899xzEEURZ555Jv773/9i6NChYfmdHnzwQWzfvh2PPfYYnE4nTj/9dDz//PNytR8RERGRUgSRE3WJiIiIKMp9/fXXOPXUU7FixQpceumlSodDRERE1Atn0hERERERERERESmMSToiIiIiIiIiIiKFMUlHRERERERERESkMM6kIyIiIiIiIiIiUhgr6YiIiIiIiIiIiBTGJB0REREREREREZHCmKQjIiIiIiIiIiJSGJN0RERERERERERECmOSjoiIiIiIiIiISGFM0hERERERERERESmMSToiIiIiIiIiIiKFMUlHRERERERERESksP8PXYJENA9Rr/wAAAAASUVORK5CYII=", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "energy['2014-07-01': '2014-07-07'].plot(y='load', subplots=True, figsize=(15,8), fontsize=12)\n", + "plt.xlabel('timestamp', fontsize= 12)\n", + "plt.ylabel('load', fontsize= 12)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { @@ -21,8 +160,9 @@ "name": "python3" }, "kernelspec": { - "name": "python37364bit8d3b438fb5fc4430a93ac2cb74d693a7", - "display_name": "Python 3.7.0 64-bit ('3.7')" + "display_name": ".venv", + "language": "python", + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -34,17 +174,17 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" - }, - "nteract": { - "version": "nteract-front-end@1.0.0" + "version": "3.10.11" }, "metadata": { "interpreter": { "hash": "70b38d7a306a849643e446cd70466270a13445e5987dfa1344ef2b127438fa4d" } + }, + "nteract": { + "version": "nteract-front-end@1.0.0" } }, "nbformat": 4, "nbformat_minor": 2 -} \ No newline at end of file +} diff --git a/7-TimeSeries/2-ARIMA/working/notebook.ipynb b/7-TimeSeries/2-ARIMA/working/notebook.ipynb index 72840137..02bf3304 100644 --- a/7-TimeSeries/2-ARIMA/working/notebook.ipynb +++ b/7-TimeSeries/2-ARIMA/working/notebook.ipynb @@ -1,23 +1,8 @@ { - "metadata": { - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": 3 - }, - "orig_nbformat": 2 - }, - "nbformat": 4, - "nbformat_minor": 2, "cells": [ { + "cell_type": "markdown", + "metadata": {}, "source": [ "# Time series forecasting with ARIMA\n", "\n", @@ -30,18 +15,443 @@ "The data in this example is taken from the GEFCom2014 forecasting competition1. It consists of 3 years of hourly electricity load and temperature values between 2012 and 2014. The task is to forecast future values of electricity load. In this example, we show how to forecast one time step ahead, using historical load data only.\n", "\n", "1Tao Hong, Pierre Pinson, Shu Fan, Hamidreza Zareipour, Alberto Troccoli and Rob J. Hyndman, \"Probabilistic energy forecasting: Global Energy Forecasting Competition 2014 and beyond\", International Journal of Forecasting, vol.32, no.3, pp 896-913, July-September, 2016." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import warnings\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import pandas as pd\n", + "import datetime as dt\n", + "import math\n", + "\n", + "from pandas.plotting import autocorrelation_plot\n", + "from statsmodels.tsa.statespace.sarimax import SARIMAX\n", + "from sklearn.preprocessing import MinMaxScaler\n", + "from common.utils import load_data, mape\n", + "from IPython.display import Image\n", + "%matplotlib inline\n", + "pd.options.display.float_format = '{:,.2f}'.format\n", + "np.set_printoptions(precision=2)\n", + "warnings.filterwarnings(\"ignore\")" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
load
2012-01-01 00:00:002,698.00
2012-01-01 01:00:002,558.00
2012-01-01 02:00:002,444.00
2012-01-01 03:00:002,402.00
2012-01-01 04:00:002,403.00
2012-01-01 05:00:002,453.00
2012-01-01 06:00:002,560.00
2012-01-01 07:00:002,719.00
2012-01-01 08:00:002,916.00
2012-01-01 09:00:003,105.00
\n", + "
" + ], + "text/plain": [ + " load\n", + "2012-01-01 00:00:00 2,698.00\n", + "2012-01-01 01:00:00 2,558.00\n", + "2012-01-01 02:00:00 2,444.00\n", + "2012-01-01 03:00:00 2,402.00\n", + "2012-01-01 04:00:00 2,403.00\n", + "2012-01-01 05:00:00 2,453.00\n", + "2012-01-01 06:00:00 2,560.00\n", + "2012-01-01 07:00:00 2,719.00\n", + "2012-01-01 08:00:00 2,916.00\n", + "2012-01-01 09:00:00 3,105.00" + ] + }, + "execution_count": 2, + "metadata": {}, + "output_type": "execute_result" + } ], - "cell_type": "markdown", - "metadata": {} + "source": [ + "energy = load_data('./data/')[['load']]\n", + "energy.head(10)" + ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABOkAAALECAYAAABdQ2SgAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd5wU9f0/8NdxdBHsCorRBI3GEqNGEmM0fi0xJkZ/EYwaNRoNiV0TS7AlNiBB7AVQlKqIKEWk93bccXAcB9xxR7njeu91b3d+fxy3bJneZ/b1fDxMuN2Zz3x2d+bzmc97PiVJEAQBRERERERERERE5JgeTmeAiIiIiIiIiIgo0TFIR0RERERERERE5DAG6YiIiIiIiIiIiBzGIB0REREREREREZHDGKQjIiIiIiIiIiJyGIN0REREREREREREDmOQjoiIiIiIiIiIyGEM0hERERERERERETmsp9MZ8JtQKISSkhIcffTRSEpKcjo7RERERERERETkIEEQ0NjYiCFDhqBHD+n+cgzSmaykpARDhw51OhtEREREREREROQihYWFOO200yTfZ5DOZEcffTSAri9+4MCBDueGiIiIiIiIiIic1NDQgKFDh4ZjRlIYpDNZ9xDXgQMHMkhHREREREREREQAoDgtGheOICIiIiIiIiIichiDdERERERERERERA5jkI6IiIiIiIiIiMhhnJOOiIiIiIiIiIjCgsEgAoGA09nwjF69eiE5OdlwOgzSERERERERERERBEFAWVkZ6urqnM6K5xxzzDE45ZRTFBeHkMMgHRERERERERERhQN0J510Evr3728o4JQoBEFAS0sLKioqAACDBw/WnRaDdERERERERERECS4YDIYDdMcff7zT2fGUfv36AQAqKipw0kkn6R76yoUjiIiIiIiIiIgSXPccdP3793c4J97U/b0ZmcuPQToiIiIiIiIiIgIADnHVyYzvjUE6IiIiIiIiIiIihzFIR0REREREREREnvWrX/0KTzzxhOePwSAdERERERERERGRwxikIyIiIiIiIiIichiDdERERERERERE5Au1tbW45557cOyxx6J///74zW9+g7y8vPD71dXVuOOOO3Dqqaeif//+uOCCC/DFF19EpdHc3Ix77rkHAwYMwODBgzFhwgRb8s4gHRERERERERERxREEAS0dnbb/JwiC7jzfe++9SE9Px8KFC5GSkgJBEHDjjTciEAgAANra2nDJJZfgu+++w65duzBq1CjcfffdSEtLC6fx9NNPY926dViwYAGWL1+OtWvXYvv27Ya/TyU9LT8CERERERERERF5TmsgiB+9tMz24+555dfo31t7yCovLw8LFy7Epk2bcPnllwMAZs2ahaFDh2L+/PkYOXIkTj31VDz11FPhfR599FEsW7YMc+bMwWWXXYampiZMmTIFM2fOxDXXXAMAmDZtGk477TRzPpwMBumIiIiIiIiIiMjzsrOz0bNnTwwfPjz82vHHH48f/vCHyM7OBgAEg0GMGTMGc+bMQXFxMTo6OtDe3o7+/fsDAPbv34+Ojo6oNI477jj88Ic/tDz/DNIREREREREREVGcfr2SseeVXztyXKuMHz8e77zzDt5++21ccMEFOOqoo/DEE0+go6PDsmOqxSAdERERERERERHFSUpK0jXs1CnnnnsuOjs7kZqaGh7uWl1djb179+JHP/oRAGDTpk24+eabcddddwEAQqEQcnNzw+//4Ac/QK9evZCamorTTz8dQNdiFLm5ubjqqqsszT8XjiAiIiIiIiIiIs8766yzcPPNN+Ovf/0rNm7ciMzMTNx111049dRTcfPNN4e3WbFiBTZv3ozs7Gz87W9/Q3l5eTiNAQMG4P7778fTTz+N1atXY9euXbj33nvRo4f1ITQG6YiIiIiIiIiIyBc+++wzXHLJJfjd736Hn//85xAEAYsXL0avXr0AAC+88AIuvvhi/PrXv8avfvUrnHLKKbjlllui0hg/fjx++ctf4qabbsK1116LK664ApdcconleU8SjKxrS3EaGhowaNAg1NfXY+DAgU5nh4iIiIiIiIhIUVtbGw4ePIgzzzwTffv2dTo7niP3/amNFbEnHRERERERERERkcMYpCMiIiIi12vtCDqdBSIiIiJLMUhHRERERK72wZp9OPelpViVXa68MREREZFHMUhHRERERK42ftleAMCzX2c5nBMiIiIi6zBIR0RERESekMw7VyIiIstxfVF9zPjeeKtDRERERJ7QIynJ6SwQERH5Vq9evQAALS0tDufEm7q/t+7vUY+eZmWGiIiIiMhKDNIRERFZJzk5GccccwwqKioAAP3790cS615FgiCgpaUFFRUVOOaYY5CcnKw7LQbpiIiIiMgTenAMCBERkaVOOeUUAAgH6ki9Y445Jvz96cUgHRERERF5AnvSERERWSspKQmDBw/GSSedhEAg4HR2PKNXr16GetB1Y5COiIiIiDyBQToiIiJ7JCcnmxJ0Im0YpCMiIiIiV0rPr8HSXWXhvxmjIyIiIj9jkI6IiIiIXGnExJSov5MZpSMiIiIf4/S7REREROQJHO5KREREfsYgHRERERF5Qo8eDNIRERGRf3G4KxERERG5yuqccmzMq457nTE6IiIi8jMG6YiIiIjIVf4yNV309WRG6YiIiMjHONyViIiIiDwhiXPSERERkY8xSEdEREREnsCOdERERORnDNIRERERkSdwdVciIiLyMwbpiIiIiMgTkhmkIyIiIh9jkI6IiIiIvIExOiIiIvIxBumIiIiIyBMYoyMiIiI/Y5COiIiIiDxBcDoDRERERBZikI6IiIiIvIFROiIiIvIxBumIiIiIiIiIiIgcxiAdEREREXmCwK50RERE5GMM0hERERGRJwiM0REREZGPMUhHRERERJ7AGB0RERH5GYN0REREREREREREDmOQjoiIiIiIiIiIyGEM0hERERGRJwiclI6IiIh8jEE6IiIiInINuUAcQ3RERETkZwzSEREREZFryHWWY0c6IiIi8jMG6YiIiIjINYKMxBEREVGCYpCOiIiIiFwjGOJwVyIiP9lb1oh/L9iFysZ2p7NC5Ho9nc4AEREREVG3EMe7EhH5yq/fXg8AKKhpwdT7LnM4N0Tu5qqedGvXrkVSUpLof1u2bInadvPmzbjiiivQv39/nHLKKXjsscfQ1NQUl2Z7ezueffZZDBkyBP369cPw4cOxYsUK0eOrTZOIiIiIrCHTkY496YiIPGxXcb3TWSByPVf2pHvsscfw05/+NOq1YcOGhf+9Y8cOXHPNNTj33HPx5ptvoqioCG+88Qby8vKwZMmSqP3uvfdezJ07F0888QTOOussTJ06FTfeeCPWrFmDK664QleaRERERGQNueGuRERERH7myiDdL3/5S4wYMULy/eeeew7HHnss1q5di4EDBwIAzjjjDPz1r3/F8uXLcf311wMA0tLSMHv2bIwfPx5PPfUUAOCee+7B+eefj2eeeQabN2/WnCYRERERWSfEIB0RkS9xxgIiZa4a7hqpsbERnZ2dca83NDRgxYoVuOuuu8LBNKAr+DZgwADMmTMn/NrcuXORnJyM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DCdJJiIiIiIikkdXQbqXXnoJ69evR1VVFeLj41FQUIDZs2fj8OHDXuu++eab6OrqQkJCAlJTU7Fw4UJ8+umnXut1d3fjyiuvRFFREWw2G2pra3H33XcL7l/sNomIiIiIiIiIiJSkq4kjrrjiCjz33HOYNWsWamtrceTIEezduxcNDQ148cUXUV3dk9T/gw8+QHt7O+x2O3bt2oVvvvkGV199NV5//XUcOnQI0dHRzm1ecMEF2LNnD1asWIHm5mY88MADmD9/PkwmE+bOnetcT8o2iYiIiIiIiIiIlGRyOBy6GZ30/PPPo6mpyS0g9vbbb6OmpgYzZ87EnXfeCQBYu3Yt9u/fj7feegsFBQUAgMcffxxjxozBjTfeiJUrVwIAPvzwQxQVFWHlypXYu3cvAMDhcGDEiBF499138d5778FisUjaZiDHjh2D3W7H0aNHkZSUpMwXQ0RkEM/98zOcfvOfAQDv7ZmocWmIiIiIiIi0JzZWpKvhrm1tbV491srKylBVVYU333zTuey+++7Daaed5gymAcDo0aNRXl6Oe+65x7nsgQcewA8//IC1a9c6l5lMJqxZswYffPABXnjhBcnbJCIiIiIiIiIiUpqugnRCHA4HPv74Y6SlpQHo6R33ySefoKmpyWvdlpYWvPLKK86/X3nlFcTHx2PgwIFe6/W+LnWbREREREREREREStN9kO7AgQP48MMPMWfOHADARx99BADIzs72Wjc7OxtffPEFvv/+e+e6mZmZMJlMXusBwH//+1/J2/T0/fff49ixY27/ERERERERERERSaHrIN1bb72FdevWobW1FWeccQYA4NtvvwUAxMTEeK1vs9nc1vn2229Fryd2m552794Nu93u/C8/P1/8ByQiIiIiIiIiIoKOg3RHjhzBxIkTYbfbcfDgQecED7GxsQAg2LPtu+++c1snNjZW9Hpit+lp69atOHr0qPO/999/X/yHJCIKM/qZioiIiIiIiMhYrFoXQMjRo0cxfvx4fPXVV3jmmWeQk5PjfK13SGrvEFVXH330EVJTU5094rKzs/Hkk0/C4XC4DXntfW/vdqVs01NMTIzP14iIIo1HdgEiIiIiIiISSXc96b777jtMmjQJhw8fxoMPPojKykq313Nzc5Geno6XX37Z672HDh1CXV2d8++6ujocP37cbWZYAPjzn//sfF3qNomIyDdblO6qFSIiIiIiIkPQ1d3UyZMnMWfOHLzwwgu499570draKrjejBkz8OCDD7oNLX3iiSdw+PBhzJo1y7lsypQpiIqKwg033OBc5nA4sG/fPuTm5qKtrU3yNomIyLe6/BQMKU7FjIY8rYtCRERERERkKCaHQz8ZhM4880xcd911mDRpEmbPnu31+oIFCwAA77//Purr65GcnIxNmzbhm2++wVVXXYW8vDy89NJLbsNPzz33XFx11VVYuXIlmpub8Zvf/AYPPfQQDhw4gPnz5zvXk7JNf44dOwa73Y6jR48iKSkpyG+EiIiIiIiIiIiMTGysSFdBuo6ODjz99NM+X3ct6htvvIHNmzfj2WefRXR0NCZOnIhrrrkGmZmZbu/p7u7GFVdcgRtvvBEfffQRysrKsHXrVpx++ule2xe7TX8YpCMiIiIiIiIiol6GDNKFAwbpiIiIiIiIiIiol9hYka5y0hEREREREREREUUiBumIiIiIiIiIiIg0xiAdERERERERERGRxhikIyIiIiIiIiIi0hiDdERERERERERERBpjkI6IiIiIiIiIiEhjDNIRERERERERERFpjEE6IiIiIiIiIiIijTFIR0REREREREREpDEG6YiIiIiIiIiIiDTGIB0REREREREREZHGGKQjIiIiIiIiIiLSGIN0REREREREREREGmOQjoiIiIiIiIiISGMM0hEREREREREREWmMQToiIiIiIiIiIiKNMUhHRERERERERESkMQbpiIiIiIiIiIiINMYgHRERERERERERkcYYpCMiIiIiIiIiItIYg3REREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERacyqdQHCjcPhAAAcO3ZM45IQEREREREREZHWemNEvTEjXxikU9jnn38OAMjPz9e4JEREREREREREpBeff/457Ha7z9cZpFNYamoqAOA///mP3y9ebc3NzXjppZcibt96KYPW+9e6DJH++fVSBq33r4cyaL3/Y8eOIT8/H++//z6SkpI0K4cW34PW370eyqD1/vVQhkjfvx7KoPX+9VAGrffPuoDHH78DfgdalyHSP78e9n/06FEUFBQ4Y0a+MEinMLO5J82f3W7XtBK2WCya7V/LfeulDFrvX+syRPrn10sZtN6/Hsqg9f57JSUlRdz3oIfvXusyaL1/PZQh0vevhzJovX89lEHr/fdiXaANrcug9f71UAat988y8PPrYf+9emNGPl8PUTkoxNatWxeR+9ZLGbTev9ZliPTPr5cyaL1/PZRB6/3rhRbfgx6+e63LoPX+9VCGSN+/Hsqg9f71UAat968XrAsic/96KIPW+2cZ+Pn1sH+xTI5AWetIkmPHjsFut+Po0aO6iNISEZF2WCcQERHrAiIiElsXsCedwmJiYrB9+3bExMRoXRQiItIY6wQiImJdQEREYusC9qQjIiIiIiIiIiLSGHvSERERERERERERaYxBOiIKKZPJhB07dmhdDCIi0hDrAiIiYl1A5I1BOiKSbP/+/TCZTHj55Ze1LgoREWmEdQEREbEuIFIWg3REREREREREREQaY5BOJD4hICIigPUBERGxLiAiInUwSEdEQevo6EBHR4fX8sWLF6OwsDDk5SEiotBjXUBERKwLiILDIB0REREREREREZHGGKST6bXXXsPixYtRXFwMm82GrKwsLF26FJ9//rnbejt27IDJZMI///lPLF68GMnJybDb7ViyZAmOHz+uUemJiEgprA+IiIh1ARERKcGqdQGM6rHHHsM777yDJUuWICsrC2+88QZuuukmvPHGG3jxxRdhMpnc1p89ezaKioqwe/du/PWvf8XNN9+MjIwMXHHFFRp9AiIiUgLrAyIiYl1ARERKYJBOprVr12LLli1uy4YMGYJ58+bh2WefxfDhw91eq6+vxy233OL8+/PPP8ctt9zCipiIyOBYHxAREesCIiJSAoe7yhQbG+v893fffYfPPvsMQ4YMAQD89a9/9Vp/9erVbn8PHz4cn3/+OY4dO6ZuQYlCwPPpcK+TJ0+GuCREocf6gKgH6wKKZKwLiHqwLiAKDoN0Mn3xxRfYtGkTMjMzERsbi/T0dBQVFQEAjh496rV+QUGB298pKSkAgC+//FL9whKpLCUlBV999ZXX8n//+9+hLwxRiLE+IOrBuoAiGesCoh6sC4iCw+GuMs2ePRvPP/88zjnnHNTV1SEhIQHd3d3o6upCd3e31/oWi0VwOw6HQ+2iEqmupKQEDz/8MD799FOkp6cDAF599VU899xzyM/P17h0ROpifUDUg3UBRTLWBUQ9WBcQBYdBOhm+/PJLPPHEE9i5cycuvvhi5/K3335bw1IRaWfp0qX40Y9+hHHjxmHZsmX45JNPsG/fPlRVVXHYBoU11gdEfVgXUKRiXUDUh3UBUXA43FWG3idfnk+6rr32Wg1KQxR6vcd+77kwcOBA3H777Th69Cg2b96M3/72t7jjjjvQ0NCgZTGJVMf6gCIZ6wKiHqwLKJKxLiBSFnvSyZCUlIT29nZceeWV+OGHH5Cbm4s//OEPePfdd7UuGlFIfP311wB6zoVep59+Ok4//XS39caOHev1Xg7joHDC+oAiGesCoh6sCyiSsS4gUhZ70onk+YTgrrvuwrhx43D99ddj69atiIqKwu9//3sti0gUMi+99BLi4+PRv39/rYtCFHKsD4h6sC6gSMa6gKgH6wIiZZkcDF+L8pOf/ASbNm3CP//5T5SUlGhdHCJN3HfffXjqqadw/fXXY/ny5bjpppu0LhJRyLE+oEjHuoCIdQER6wIidXC4q0h8QkAEnH322fj666+xbNky/PjHP9a6OESaYH1AkY51ARHrAiLWBUTqYJAugN4nBAcOHMDy5cthtfIro8jF3CoUyVgfEPVgXUCRjHUBUQ/WBUTq4HDXAIqKivD1119j2rRpuPbaaxEfH691kYiISAOsD4iIiHUBERGpiUE6IiIiIiIiIiIijXF2VyIiIiIiIiIiIo0xSEdERERERERERKQxBumIiIiIiIiIiIg0xiAdeqZQX79+PaqqqhAfH4+CggLMnj0bhw8f9lr3zTffRFdXFxISEpCamoqFCxfi008/9Vrv8ssvx+TJk5GZmQmTyYQdO3YI7vv+++/HnDlzUFxcjLi4OAwYMABbtmzBV199pfCnJCIiMbSsE379619j3LhxyMnJQUxMDPLy8jBz5kz8/e9/V/pjEhGRH1rWBZ7GjBkDk8mE9evXB/uxiIhI5zhnOIArrrgCzz33HGbNmoXa2locOXIEe/fuRUNDA1588UVUV1cDAD744AO0t7fDbrdj165d+Oabb3D11Vfj9ddfx6FDhxAdHe3c5oUXXoisrCzU19fj0Ucf9bnvlStXIicnBwsWLEBBQQFef/117N27Fw8//DD++te/IjY2VvXPT0REfbSsE15//XWkpKRg06ZNSEtLw5EjR/CLX/wCLS0teOGFFzBo0CDVPz8REWlbF7i6//778cILL6jyGYmISIcc5Hjuuecc33//vduyw4cPO2JiYhynn366c9maNWscsbGxjn//+9/OZY899pgDgOPGG290e/+7777rcDgcjk8//dQBwLF9+3bBfT/55JNey2677TYHAMfPf/5zeR+IiIhk07JOEHLkyBGH1Wp1rFq1SvqHISIiWfRQF3z77beOwsJCxyWXXOIA4Fi3bl1wH4qIiHSPw10BtLW1uT3lAoCysjJUVVXhzTffdC677777cNppp6GgoMC5bPTo0SgvL8c999zj9v7CwkJR++7o6PBaNm3aNABw2zcREYWGlnWCkIyMDMTFxTENAhFRCOmhLrjyyivR3d2Ns88+W/oHICIiQ2KQzgeHw4GPP/4YaWlpAIAPP/wQn3zyCZqamrzWbWlpwSuvvKLYvo8cOQIAzn0TEZG2Ql0nfPXVV/j000/x+uuvY/ny5Th27BhGjRoV1DaJiCg4oawL/vOf/2DPnj244oormP6GiCiCMEjnw4EDB/Dhhx9izpw5AICPPvoIAJCdne21bnZ2Nr744gt8//33iuz7iiuugMViwcyZMxXZHhERBSfUdcKQIUOQkZGB2tpa3HPPPbjwwguxbNky2dsjIqLghbIu2LJlC+rr6zF37lz5BSYiIsPhxBEC3nrrLaxbtw6tra0444wzAADffvstACAmJsZrfZvN5lxH6HUp7rrrLtxyyy0499xzUVZWFtS2iIgoeFrUCbfeeiuOHTuGd955B7feeiu+/fZbnDx5EmYzn60REWkhlHXBk08+ifvuuw9//vOfgyw1EREZDYN0Ho4cOYKJEyfCbrfj4MGDsFgsAODsZi70NOy7775zW0euZ555BsuWLcO4ceNw+eWXB7UtIiIKnlZ1Qmtrq/Pfc+fOxcCBAwEAV199textEhGRPKGsC06cOIGNGzdi4cKFaG5uDrLkRERkNHwk7+Lo0aMYP348vvrqKzzyyCPIyclxvtbbjb23W7urjz76CKmpqUH1onv11VcxefJkVFdX4+DBg7BaGT8lItKSlnWCq5SUFIwcORIHDhxQZHtERCReqOuC22+/Hf/4xz+watUqvPfee87/AODrr7/Ge++9h+PHj8v/QEREpGsM0p3y3XffYdKkSTh8+DAefPBBVFZWur2em5uL9PR0vPzyy17vPXToEOrq6mTv+1//+he6urqQkZGBhx9+GAkJCbK3RUREwdOyThDy7bff4ujRo4puk4iI/NOiLvjPf/6DH374AUOHDkVRUZHzP6AngFdUVIQ//OEPsj4PERHpH7trATh58iTmzJmDF154AQ888IDbMCNXM2bMwG233Yb3338f+fn5AIAnnngChw8fxllnnSVr30eOHMHYsWNhNpvx6KOPIj09XfbnICKi4GlZJ3zyySfIyMhwW/bee+/hiSeeEJw9kIiI1KFVXTB37lzB4N60adMwYcIErFixAoMHD5a8XSIiMgaTw+FwaF0IrZ155pm47rrrMGnSJMyePdvr9QULFgAA3n//fdTX1yM5ORmbNm3CN998g6uuugp5eXl46aWX3Lqz33HHHfj3v/+N48ePY/fu3ejs7MTIkSMBAAsXLkT//v0BAHV1dXj11Vdx7rnnoqamxm2/mZmZGDNmjFofm4iIBGhZJ2RmZmLUqFGoq6tDSkoK3n77bdxyyy04fvw4nnjiCbS1tYXgGyAiIi3rAiEmkwnr1q3D3r17Ff6kRESkJwzSAejo6MDTTz/t83XXr+iNN97A5s2b8eyzzyI6OhoTJ07ENddcg8zMTNHbfPLJJ9HR0QGgp8L1ZcSIEXjqqafEfxAiIgqalnXCjh078NBDD+Ff//oXvv76a2RkZKC9vR3btm3zepBDRETq0bIuEMIgHRFRZGCQjoiIiIiIiIiISGOcOIKIiIiIiIiIiEhjDNIRERERERERERFpjEE6IiIiIiIiIiIijTFIR0REREREREREpDEG6YiIiIiIiIiIiDTGIB0REREREREREZHGGKQjIiIiIiIiIiLSGIN0REREREREREREGmOQjoiIiCgMFBYWYvHixVoXg4iIiIhkYpCOiIiIyECef/557NixA1999ZXWRRHt+PHj2LFjB5566imti0JERESkW1atC0BERERE4j3//PPYuXMnFi9ejOTkZOfyf/zjHzCb9fn89fjx49i5cycAoKOjQ9vCEBEREekUg3REREREYSAmJkbrIhARERFREPT5uJWIiIiIvOzYsQPnnHMOAKCoqAgmkwkmkwnvvfeeV066/fv3w2Qy4dlnn8XGjRuRnp6O5ORkrFq1Cv/73//w1VdfYdGiRUhJSUFKSgrOPfdcOBwOt/11d3fj2muvRVVVFWw2GzIzM7Fq1Sp8+eWXbuu9/PLLGDduHNLS0hAbG4uioiIsXboUAPDee+8hPT0dALBz505nmXfs2AEAeO2117B48WIUFxfDZrMhKysLS5cuxeeff+712U0mEw4fPowFCxbAbrcjPT0dF110ERwOB95//31MmTIFSUlJyMrKwjXXXOP2/qeeegomkwm/+tWvsG3bNmRlZSE+Ph6TJ0/G+++/H/RvQ0RERBQs9qQjIiIiMojp06fj8OHDuPvuu/HjH/8YaWlpAOAMggnZsGEDsrKysHPnTrz44ou46aabkJycjOeffx4FBQXYtWsXHn74YVx11VWorq7GokWLnO9dtWoV9u/fjyVLlmDjxo149913sXfvXrzyyit47rnnEBUVhU8++QRjx45Feno6zj//fCQnJ+O9997D/fff7yzbz372M6xZswbTpk3D9OnTAQC1tbUAgMceewzvvPMOlixZgqysLLzxxhu46aab8MYbb+DFF1+EyWRy+zxz5szBwIEDsWfPHjz00EO47LLLkJqaihtvvBEjR47EFVdcgQMHDuDss89Gc3Mz2tvb3d5/+eWXw2Qy4bzzzsMnn3yCa6+9FqNHj8bf/vY3xMbGBv8jEREREcnlICIiIiLDuOqqqxwAHO+++67b8v79+zvOOOMM59+33nqrA4Bj3Lhxju7ubufy1tZWh8lkcqxevdq57MSJE468vDzHiBEjnMueeeYZBwDHgQMH3PbzyCOPuC3/9a9/7QDgeOmll3yW+dNPP3UAcGzfvt3rtePHj3stu/vuux0AHH/605+cy7Zv3+4A4Fi5cqVXuU0mk2PPnj3O5V9++aUjNjbW7ft48sknHQAcubm5jmPHjjmX33PPPQ4Ajuuuu85n+YmIiIhCgcNdiYiIiMLYsmXL3HqjDR48GA6HA8uWLXMus1gsaGpqwjvvvONcdu+998Jut2PMmDH47LPPnP81NjYiISEBTz75JAA4J6948MEH8cMPP0gun2vvte+++w6fffYZhgwZAgD461//6rX+8uXLvcrt+XmSk5MxYMAAt8/Ta9GiRUhMTHT+PXPmTGRnZ+Phhx+WXHYiIiIiJTFIR0RERBTGCgoK3P622+0AgPz8fK/lrrnm3n77bRw9ehQZGRlIT093+++bb77BJ598AgAYMWIEZsyYgZ07dyItLQ1TpkzBrbfeiu+//15U+b744gts2rQJmZmZiI2NRXp6OoqKigAAR48eFfV5bDabc+ivr8/Tq6yszO1vk8mE0tJSvPfee6LKS0RERKQW5qQjIiIiCmMWi0X0cofLxBHd3d3IyMjAgQMHBN/fmwfPZDLh4MGDePHFF/G73/0Ojz76KJYuXYprrrkGL774IhISEvyWb/bs2Xj++edxzjnnoK6uDgkJCeju7kZXVxe6u7tFldvXZ3R4TIRBREREpGcM0hEREREZiOdECmopKSnB448/jqFDh4qaUGHIkCEYMmQILr/8ctx11104/fTT8ctf/hLLly/3WeYvv/wSTzzxBHbu3ImLL77Yufztt99W7HN48ty2w+HAP//5T+dEFkRERERa4XBXIiIiIgOJj48HAHz11Veq7mf27Nk4efIkLr30Uq/XTpw44dz/l19+6dVjra6uDgCcQ17j4uIAeJe5twec5/uvvfbaIEvv2+23346vv/7a+ffBgwfx0UcfYfz48artk4iIiEgM9qQjIiIiMpDGxkYAwAUXXIC5c+ciKioKkyZNUnw/I0aMwKpVq7B792787W9/w9ixYxEVFYW3334b9957L6677jrMnDkTt912G2644QZMmzYNJSUl+Prrr/Hzn/8cSUlJmDBhAoCeySEqKyvxq1/9CuXl5UhNTUV1dTWqq6vR3t6OK6+8Ej/88ANyc3Pxhz/8Ae+++67in6dXamoqhg0bhiVLluDjjz/Gtddei9LSUqxYsUK1fRIRERGJwSAdERERkYE0Nzfj0ksvxb59+/DII4+gu7tbtaDWvn370NjYiBtvvBHbtm2D1WpFYWEhFixYgKFDhwLoCeYdOnQIv/zlL/Hxxx/DbrejpaUFBw4ccE4AAQA333wzNmzYgLPOOgv/+9//sH37dlRXV+Ouu+7Chg0bcP3118PhcGDs2LH4/e9/j5ycHFU+07Zt2/Daa69h9+7d+PrrrzFq1CjccMMNzt5+RERERFoxOZhRl4iIiIjC3FNPPYXOzk7ce++9mDlzptbFISIiIvLCnHREREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERaYw56YiIiIiIiIiIiDTGnnREREREREREREQaY5COiIiIiIiIiIhIYwzSERERERERERERaYxBOiIiIiIiIiIiIo0xSEdERERERERERKQxBumIiIiIiIiIiIg0xiAdERERERERERGRxhikIyIiIiIiIiIi0hiDdERERERERERERBr7/9EpyC0/yJTEAAAAAElFTkSuQmCC", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "energy.plot(y='load', subplots=True, figsize=(15,8), fontsize=12)\n", + "plt.xlabel('timestamp', fontsize=12)\n", + "plt.ylabel('load', fontsize=12)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ - "pip install statsmodels" + "train_start_dt = '2014-11-01 00:00:00'\n", + "test_start_dt = '2014-12-3o0 00:00:00'" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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ECfd3MpgFXsiCIIgrDVe8IIX4I1vfKO39i655BL83M/9nLf2XBgbJ93999+Pq6++Gu973/t0GCoQi2T9fh87duzApk2bsG3btsLXn3XWWQCAQ4cO6cdOP/107N69O/dcFd56xhln6OfRx83nqucVMTExUejAEwRBEARBEAShmiBInXNHF/vYPNVZxd4IgiAIwuoyNk663bt3YzQa4Q1veAPOPfdc/e/WW2/Ffffdh3PPPRfveMc7Sl//4IMPAkAmTPbiiy/Gfffdl8sTd+utt+q/A8CFF16IdruN2267LfO8Xq+HO+64Qz9PEARBEARBEAR/9Icj/fvhxd4q9kQQBEFYS1xyySX46le/ive///0IggBBEGDHjh347ne/i5/8yZ/Ehg0bcOqpp+JXfuVXcODAAf26a665BhdddBGmpqZw0kkn4cUvfjEWFhbwtre9DR/96EfxL//yL7q9G2644bh/rrFx0l144YX4zGc+k3v8LW95C+bm5vD+978f5513HmZnZ3PutSiK8M53vhMA8LKXvUw//spXvhJXXXUVrr76alx22WUA4pDWD3/4w3jmM5+p3XebN2/Gi1/8YnziE5/AW9/6VmzcuBEA8PGPfxzz8/N41atedcw+tyAIgiAIgiCcqAyGkf79yFJ/FXsiCIIgaKII6C+uznt3poGgPj/p+9//ftx333248MILtaGr0+ngGc94Bl73utfhT//0T7G0tITf+73fwy/+4i/iy1/+Mvbu3YtXv/rVePe7341XvOIVmJubw9e+9jVEUYTLLrsM99xzD2ZnZ/HhD38YAEojOY8lYyPSnXzyyYWxv+973/sAQP/thhtuwKtf/Wq8+tWvxhOf+EQsLS3hM5/5DG6++WZceumleNrTnqZf+8xnPhOvetWr8OY3vxn79u3DE5/4RHz0ox/Fjh07csUnLr/8cjz72c/G85//fFx66aXYtWsX3vOe9+ClL30pfuInfuJYfWxBEARBEARBOGEZjFIn3VER6QRBEMaD/iLwrvK0X8eUP9gDdGdqn7Z582Z0u11MT0/jtNNOAwC8853vxA/90A/hXe96l37ehz70IZx11lm47777MD8/j8FggJ//+Z/H4x//eADARRddpJ+r6hqo9laDsRHpbHn84x+P5z73ufjMZz6DRx99FGEY4klPehI+8IEP4NJLL809/2Mf+xje+ta3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WVeeVHc9flDxVyWtF44fZp4vV6FCi0S6cASvuqvpovBSOCIgC++K8eKevbO44ov3FObw0oV0xkykiwqcC02cdConnYK6pULHwhHqXEoLR8SPc510PooYAfmNHpaTbkyru9Lrm5uTTt+/SaVe1+tbfXWpSOfPScdy1Xt00g2H+fmOa998ugXVOaEKZXHaU211MilMPIW7jsnYKjQnLRwR6DmB03AdmSJdchOpctKNlJOOiHTLR7JFKFR766W6665du/Cud70LMzMzub/dcccdeNGLXoTFxUW8973vxete9zpcffXVeNWrXpV77iWXXIL3vve9+OVf/mW8//3vR6vVwstf/nLcdNNNzm0KgiAIKZlwV7aTLp9ImZt0PVNlccArHKHcbys+nHTddPHnupAUmkHPpd0i0h138k46Xrirru6qw135+ZwAPyJ8ZgyrGC9e99Hb8NdffRD/3z/emW/LqO7KGXd8oo5/EBDnW8UQlgou8XPP3Z6d209lRLrse9ii7j0THV856bKiX3/oHqYHpOfAxsnYVcERPkyRjtMvn9DLb5EZ7jogAhY3t+PICJ3liPD53ILun5OOY1y3P3XlqQIZzmKYRwGrsACIawqTTHQE0z3tsViQsLrQjbG2xaZRKdT9BvDCXaNR2pZjuGu7/imrw2WXXYZnPetZGA6HOHDgQOZvf/AHf4CtW7fihhtuwKZNmwAA55xzDn7zN38T1157LV760pcCAL7xjW/gk5/8JK688kpcdtllAIBf/dVfxYUXXog3velNuOWWWxq3KQiCIGTxmZOOTsK67RArg5Hz5ElPgMkk33WRqyaC1EkXRRECZfdrQFqxMb0F9wajjMtLODbQc2nX4fUt0v3t1x7EOSfN4MVPPnW1u6LJJSTnFo5Irr8WZ/cc6Vgx1W1hZTDyUzgiSBfeVYtSJRZ/8buP5v5mhv+Pi+s2DXcNUudbhRhmhnr+7MVn4K3//F399zO3TunftTOvabhrci55c9Il39lkcuyjKG5LCY3N24uPwQad15RT3TX9TFEUizFUBFktBpmcdH4KR7TCAJ0wxDJGzjknzQIsZjhnE1QfgiA99q7QjcQuc4OA5rfTOekcx1czZx/LSZecq52koMVwFLHTjtBiYK4OVwl3XR/Q+wR10jkJwdT9BjDDXVVOunB9FY648cYbcc011+B973tf7m+zs7O47rrr8JrXvEaLaUAsvm3YsAGf+tSn9GPXXHMNWq0WLr30Uv3Y5OQkXvva1+LrX/86du7c2bhNQRAEIcvyMSgc0SLJj10nT9kJcDI5Z+a381HQwswzBYxXXqH1TMZJt45Fum/vOoJ3fv4evO5jt612VzL4ctKlIl38f5uQyyp8hjbScScNvSnv16mbJvTv5qI6dXO12f3ySVo4wk5Uo6F4ALBpsoM//Okn4+xt0/jobzwDW0j4axjWO/OKUKF9SohpM5105jkBcAoXRPrzKMGVE3JpCgzjI96mn4kb7ppxTTHTVahz00+4qz+xVefSIsKaFyddh1ewxnSn8QpHJCGqHvLIqX51wgBtiw2QKsyxdFyK8gjNoGkRWqSQkVMu0ly4a5Pqrm1gakv8e1lOuobhrmPnpBsOh3j961+P173udbjoootyf//Od76DwWCApz/96ZnHu90uLr74Ytx+++36sdtvvx0XXHBBRngDgGc84xkA4hDXs846q1GbJisrK1hZWdH/n52dtf+wgiAI6wCfOelolSZ2uGtyj/YRLqP6kHG/DUd697tRv9SCoROiHQYYjCLtAhGOLfT7X8/hrrNL6aSyPxxp18Fqk3PSOeeky4a7uhYbUJihjaxwVzLu2CwYnnDyBjw2G88j73t0HheduZn0Kyvo98ZknFAfJ7T8jGZOOgD4jeeci994zrm559o48xRLvSHe+A+340efcJK+96jv0DW3ndlnKtL1hiNMobljjTq3prs8ITiKotxrl/pDbEbHqT2f0G4tMgtHqGu87UHcUedAKoS5i3TqtRsm2phbHmCZNVao6wKpM8x54yL+GQt+vHHMPD4+CkeokN6VwchLuGvX05yu7P/C2oDeJ8LQ3Ykdv8gQ6XS4a8W5MSzISUeddEErFvCAte+k+8AHPoCHH34Yf/RHf1T497179wIATj/99NzfTj/9dOzZsyfz3LLnAdDPbdKmyRVXXIHNmzfrf2eddVbpcwVBENYjNDkxt7pr6qSDv/APkhuKXziCX3WWhuop18e4OCHWO3Rxe3Cht4o9ObbQSnqHF8fncw5HpnvBbbyg4Zbxz6R9diVPfs4qOu4obbTSZUb+dsj4rkz31bgsJNXnCYLAqbprFSqa1MYV+cGbHsSX7noMb/vc3aS6a/weKiyVm5NuMuOk4yfin2ZWCC8SmMaleES2cAQz9cUwdYZxiwT4vL4HhqDPqRRL5wLdNs/9lpk7tZhOutw4zf+MnVaor0nX3KHFOfzczgmfQqSwetD7RCsMmm3O9JeBB74c/wRSkS4wnHSscNd2/Df6XEvGSqQ7ePAg/vAP/xBvfetbsX379sLnLC3FO98TExO5v01OTuq/q+eWPY+21aRNkze/+c04evSo/qdCaAVBEE4UfBaOSHdKQ7ZIV1Q4oue6gztMd+LVTh23X+0w1Dv74qQ7PtDFhmvo81qAikKHF5qFWBxLfFUNHBrOLNbuOfKONY7TJhPuauUyS4/BEUOkM8WFcQnJSkVSu1DjIiddGWkhivrv4LaHD+vfVXilyiHXxJFXRJr/iu/Epq9TbmwfbamQS+591xdUe2HnpCNOOm6RgJHhpOMIazpXYYcftuxTdCoMd3UUb83PxHPSpfkolUjfcyzgRcf9tm8n3ZikEhCakXHSBXYbY5ovvgn4+CuA694a/z8iIaqAZbhrQeGI5dn08TB0DncdK5HuLW95C7Zt24bXv/71pc+ZmoqTy9IQU8Xy8rL+u3pu2fNoW03aNJmYmMCmTZsy/wRBEE4kqEjnK9y1FaThH67FHtK2+JXT+iRhsb+qs+lEf1mcdMcF+p1x3BTjDl3oHRojx6Dv6q5K8/EV2jjpIdyVFo5IC1rUC1gAcGQxO4lXr/MRhgvEQtYtDxxgV5MekbQELQsxLN2YsBDpGhQBuffROf27KgQz2VY56bhOOioS+akODqROP64YAxCRbgyddAvMcNcBcZm1PTnpJnThCH64K9cRSft17ApH8IXguB3382ugnXRpiKqrk46KdLooj3NF7+zr1vN8YD1Dv8bYva7OC4tr/D8/Gv/8xtVJY8r9Zoa7WjrpJrckD0bA0qGkrbZzuOvY5KS7//77cfXVV+N973tfJrx0eXkZ/X4fO3bswKZNm3RIqgpRpezduxdnnHGG/v/pp5+O3bt3Fz4PgH5ukzYFQRCasjIYotsKnSqBrgWWPYp0mRBVlT/GQ/hHpx2w2lITuk4r7tdSf4je0LEyJVnEqx1vKRxxfKALoPW8c04XHOMU7prPSces7mo46Zyru5oinZeFN+xEOiI8mN9VLicd85z9tQ99A996+DDe8lNPwuue+wTndiIikgba+Vb+fDV+2lRGbVk66eZXBth7dFn//+GDCwDS0GCboh1VDHKCwND5+Jv3D4CxyUPOl5kJlS6Bd//47u6j2DbTxRlbyk0JNtDvzJeTLusya37Moigt2sEtzgCQcFcP1+SQCGvclBxDcry4OenyVbg5x4u63/yIra0gQKicdExXnqrSK+Gua5Nc4QiXqt6Bst8Ns/9vWt213QW6G4DePLBwIG1jrTvpdu/ejdFohDe84Q0499xz9b9bb70V9913H84991y84x3vwIUXXoh2u43bbstWLOv1erjjjjtw8cUX68cuvvhi3HfffbliDrfeeqv+O4BGbQqCIDTh0EIPF7/9Ovzmx7612l05ZmTcSUyHRmZnWYeoMqudeZgAD7SrgobhMh0arXQyPS5hbOsdei6t50k5dQmMU+49b046slgDUkddxHTSTXvI/TZs6KSjf8s56ZK2fOWk+1YSHvoP3+SlZlFdDshnBMpDjJrkpFNPqQtX2j+XjX55+OAiAGAyGZ+Vk87KUVFAOk6HbCf2wEiez2mLLkpnPDjpHjqwgJ/+85vw7D/+snMbum+ZwhF+NuzCAGm4q4Nrin79SoSPInfxVglMUx7CXdVXSTcl2dXsPeS3M89NlrO4IETVNdyYhvTqEHSmK2/ak0tZWB2yhSMC602eDBNJFOSoJNw1GqUXa64DJNwVSN10C/vjn0Er/dtojYp0F154IT7zmc/k/v2X//JfcPbZZ+Mzn/kMXvva12Lz5s148YtfjE984hOYm0tt7h//+McxPz+PV73qVfqxV77ylRgOh7j66qv1YysrK/jwhz+MZz7zmbrIQ5M2BUEQmvC5O/dgqT/E9fc8ttpdOWbQCR0n1wuQDRXzWTiiwxT8RkRYY4uHmcIR4qQ7npwo4a5UQD48RiKdL4fGiCxuAb5rygwr9VY4wmLBQBeZppNuZPRrXMT8onBXoDzc2C0nXfXzDsxnRTp1bJSgyc1TmG7M8HPSZe5rntIltMK08BBHpLtrz1Hn15rQwjBcJx0VZNLqrs2/SzomTJBq7M4iqeGkY4W7eqxmP8o46ZRI5ycnHWfcUf0KggCdJqGIRW2RzRntymNeR1NJjkgR6dYmuUrvtnMBKu4qkU7npFPhrkQmKwt5pdVdAWBqS/xz8WDSFi0c0UykG5tw15NPPhk/93M/l3v8fe97HwBk/nb55Zfj2c9+Np7//Ofj0ksvxa5du/Ce97wHL33pS/ETP/ET+nnPfOYz8apXvQpvfvObsW/fPjzxiU/ERz/6UezYsQMf/OAHM+9j26YgCEIT6KRwvUInzpxdZSC7mJvghgWRSb6No8WmX6EH8ZC6SlT+JBHpjg8nSrgrdZyMU046UzBxXUTSxS2QOuq41V29LrzDwGrBQP92uMxJN2ZuD1o4gprjhqMIpBhq/NxRpE0IVjnpLL/LA3P5PNJA6pZqsZ10acJ7tvutoIgRt61WEOjzglM4QvUHiJ2onLQc9CNxx1c1hHFzylKBnM7HXM+LgcecdD43Euk5xnXom45FlrOYnK8q7Qj3M7ZIpIXz92i4p11zHwurCz2/6M9aJ51yugFAdyb+mXPSEZksGqJQNqPhrgAwuTn+uahy0oVpO2s13LUJT3va03D99ddjamoKv/3bv42rr74ar33ta3HNNdfknvuxj30Mb3zjG/Hxj38cb3jDG9Dv9/Gv//qveN7znufcpiAIgi0q5xjgHoo17lD3HHdinpmEscM/4p+tgFRZdOweTSLut3CEqsImE8TjAT2XXHPZrAXownGcRLp8Tjqes1UJRL6qu3opHEHGnVQ8LH8+3dgoq+7qIwyXwk2PGhVsgADFCyP6nbdsctJZfpemk06hBAqnsCdCkZPONcUBdXuk9zXeudoKU5GOs8nTId8J16lJxR3uuUrdmrpIgMMxo+ffBFGQXR1YfWOsYFWC1ucFPGz+xT9prlvXtszPxCkcQUN6Vbi762auehl1V3IFPzq2rtc5+npmaM4FdEh1zXc5uyv9vR+nStCFHVTBiJDsOJUVfSgLd8046dzCXcfGSVfGDTfcUPj4c57zHNx88821r5+cnMSVV16JK6+8sva5tm0KgrC+iaIIt+88gnNOmsG2mS6rrW4rHeSX+yPt1FhP0MWG666mIrOY4YZ/0LAzleeI6bTJLrLcJq6qD+0wJDve4qQ7Hpwo4a50kXVkqdnE8FgyNBwarqKAuXtuU7ygirS6Ky+xeaZvRMCqEpwGFuGukyRJPdft5AOadD2k4a4Fn5M+ZuOkU83VjdX75+Nj9dSztuCu3Uf1d2iGuzo76XQeOQ856YoqxfpwEzFzj8V9SjcSF3tDLT65QL8zzjUEZBffnHBjev7FBbxi4cg1l5nalFTijmt1Udq3WIj0FFIdQs+dxiHcdRilY0WHmZMuDXcFOm2e4GeOF0B8znbb67PA23qFphKgP2td9bNpkVKsJKnOdLhrMiYGVKQrC3c1nHRmuGvQSgtHjAblue0KWJNOOkEQhGPJ1x88iJ//y1vwovfcwG6L7lIv9Hg5WsYVOkkdjiJnN4t6PeAn+TENiUuddB5FOmbltBZx0i2Lk+64cKIUjqALvXEKpc7npGOGu6rqrkH28cbt5dwxfvJMNQ13PbKQFVT1QpIIJ+OQly4Ndw0yIl2RXkHvDzY56WwXWapwxAt/YDuu/tUf1o+fvKGbeS8/Oek8hbt6EGPS8wukX3w3FwAsMucoVDDx5aTjVgWl338rJHnRHI+ZWTiiP4ycHVijAkGfO0cJiZPO1alsCo8+ctK1gtRJ51pgLFM4ImReRyq3IBlb13MKjPVKWaX32nFfiWgAsDIbi2e14a5FHSgLd6VOOtJOmSOvgLF30gmCIBxvbro/Lp1t5gdyge4sL64MgQ3sJscOM2ykPxphInTbjVdzw7YHMaxoAuzFSddiioeZwhGSk+54csLkpCML0HEQdRS+qrtG5u65r3BX5c5gbDQ0LhxBvqu5lQH6w5EWX9TrprvZhSTH7QQAAXhuEbrwrgt3zTrp6r0Bqr26oVqFu568YQI//oOn4ov/87m477E5PPn0TZl2XJ1OdMzXVSmdE95Dt6Xua86OqUzVWZ4zCcjevzm57YDs988dd3RxGCJsunyXVIQMg7j4U2/oLtKpz0ivwcEoymzINu1bGPDnKNnCEbycdPlwV37evTAItPuNW+whm6fQdcyPf2ZEusEImHBqTlglcoUjLFJMAACWDpNGBsBgORXpCsNdawpHKEFPh7uqnHStVMADUlHPAnHSCYIgGGyZ7nhri04g5pnVzsYVc1eUUzxCTcLDMNChws45R0j4R2ixWK7ulz8nHS0cMeEhXEmw58QJd00/28oYCcCmyOG+WIt/quuaW901DXfl537LjDvJLNvWSQcAR0l4sunw4/bNFxFxc1FzXJH7jX7nFkY6Hcpb911SkQ4AnnT6JvzsxY/Tr0+dSfXvWUTGSZd8kc4up4L8aq757WgRI67DL34tddLxxgraDe74moZUEwcWw0kXBkmFUU8FGjL57bh5c0O/bn9u0S0l+nJTjgDEdUvcb67C+SgjnHPdrclnbId6rBiHsVVoBs3FCDTYsKMiHRCHvCqXmxLcggBQG1q24a7KSbeSVM0OSbgr0Kh4hIh0giAIBpun0gGVG/5BJ1zctsaRKIpykySOSKdeGjs04t+57hjbsLMqihN/+ygcIU6648GB+RX8xZfv1yFyQLx44DhQxpn+mDvp1ESaHfKnkkUzc9KZ7hhfeaZsQjfNY6CKR0RRlLqJPOTo9InqVxAECIJAi29FYzUtumOTS882f6gS6bZvLM4bm4p0vEV8qxXwz9ekrXbLZ046Eu7KcH7SfvBFOo+FIwqc8C5hpUPDacNx5QHpeUkrxbq6uei8gisqF6UKWXZMJ6DOp+kJfs7cIRFJ2zrUmx/u2mW6SDMbrx7EbmF1KAt3rZ3rF4l0OicdcdCp323DXVVOOv16UjgCaBTuKiKdIAiCgQoVAICD87zKiPSmv8CcAPvmf33mO7jii/ew2hiOolxYkmtCZsCcmPNCz4rCzriuihaZALu6gDKFI5RIJ4Ujjil/9K9346pr78PXHzyYeZyb3HxcGVsnnZHPyVXoHhliH9spm/TDR8XGwjB7CyedOiYqzQJ9CR13xkF0pZU3AbIwqnDS2eSjo23WVnedi+/NyklnYlNZtwrqpGvbVgwsgbo92DnpiBNbt8U4J+g1uNT3tynJFTxoSLXSdl022ah4BYBfYVQ56TIiHT/1BbcaMRX81Hnh7CxOPs9MN3YU8Zx0efcbt3BEm7TFrZJMU6uMw9gqNCNXOMK2YJAp0i0fJTnpqEiXuOqaVndVBK3YkadCaMVJJwiC4A6d2Bxc4Il09EaxMEbhrjsPLeLvbn0Ef/3VB1mT6aIbISvpOtkVa1mEilW2lcn3Ej/mnpMudUJ0meEyOlxJCkccN667+7HCx9drXjq6CFoeo4WHuo60GOYY8mcuvLlO2TSslO+oKCwcUTLuRFGkx4OTE0fY4eSekym40OKHsNFjwy0OmxaOUD/Lj7+qkmpT2TXTVsVYvbAywFIiPpeJdG0tVHAda2l1V3ZSfw+uHeoiVf3i5FD06aSj/Rhwi0iRqqAcpyzNBwhQNxc/VyG7IitpK7QVF2r6Fc93mJVPk9fNTPBy2wFZQb/D/YwFYeN8J13ITmEirB6mO99a7F46kv3/ylw+Jx39vWm4q0KJfErEG4lIJwiC4ExGpJtfqXhmPeMq0tF+cSYmVORQazBWuCvZ3bS52X7qtp143Ue/WRhKfKzyvXDCzkbEeRjnpONPgoV6Tt00Wfj4eg1voe6CsXLSqTCqLtNJZ4SwsUV4I9yVc15QUUCPYSXN0fFIiU1HlJOOvIY66VzHa58L0IiEnQE0D1D+uUpstHXSpQn0y5+jwtanuy3MTBTXwOOO+dRJp8NdmSGSNOG9qwModROFWnDibDZQFx5XpDOvP06/RgX3b5fre2g4bbrsggNpe2xXXqYAS/yYc3qP5GWtMNCCuGu1a3Weq2uLcw+h+UO5+QAHHgVSGjbO3XgVVg8z9YX1hl0u3HW2Jty17CauRLpEhMuFu6qOJX8XJ50gCII7dCLODXcdeNyl9gldLnEWb3RyOuVhgVvoQqm42b7pmm/j+nv24QNffTD3N7qQ54bD0Yk5Z7FMJ82tICBOuvE5N9Ybw1GE3YeXCv+2XnfO6bgzTgKwGdrpXLnZCLf0dX3rnHSsvJr5cNey/FeDApHucJKTLjNWZHJhuo0VnLxSJiPicgKq3W9646Vlt+Soym+nMItGFNGuEA5tUA5AL+GDVFxgpktIC0eA7SYCsmIVt7qr6ZDiiB70OuI4Zc2cVW1mLjParw5TJKX5abmi8oiITtZ5ucr6pZx0KtyV8T3qStwhSLgr9zMG7HyMWacsv0qysDqMyNwcaLBhp6qvzmyPfy4fBfqL8e+dqfR5SqQrC3dVj9s66USkEwRBcIdObA4sMJ10ZDKyMEaFI+hiirOIV4IcXURyQm+K8sjZLLwfPriQeywb/uFJpKP5SxwmdPTcCkNgsi2FI441e48ulS4y1quTjn6uwSgam8WHrqLa5Qn6uequnlxTSjQfjCKnJPW0D3TcKfuYxSJdP9OOaku5PVYcQ+OpIOp6nBRpuKs6/urxfLuNc9JZjNWpSFdcNIK241ogIOuk47mvsuKCvxDJDjMRP5AVYLhzFFNY9ZHLLAiqzy/bdnS4a8gTd4qEImfRieZrUxWEPYw7bX3uu/Yr/jnVTZ3+PsZDrhhGx/02Mx9jpnqzOOnWLPnCEZapCZSTbtt58c/FQ0AvWUd0N6TPaxruOrUt+3f1egl3FQRB4EMnXGwn3ZiGu9IFAivcNXlth1St47Q3JLuuTXbPDxXkDizK9+Il3JXjpCPv3ya5UMbJ7bTeeOTgYunf1q1IZ5zn43J+qfN/mum6peNE/NPdNUVD0CdJ0SAX4YOKFJnCESUL3CF5j+0bY5Hu6FKvsK2JjvvmAJA9B7jnQ+pkTPsH1Fd3tSEVXMufs3++umgEfT/3whHpBpTOpcV2TPFz0tFcWtxKseZruU46sxuu/Yqi9JpsBXYFWMr7lHXdsoUiEurtrVKvh3DX4kqxvM+oHM9RxBf8QiJEOgukZNzn5mMc0uubKbYKqweNvgFSR13ledFfAgZJdMVJiUi3REW6mfS51tVdExGuM5kV+ZSTTsJdBUEQ+Aw9Cmt0IriwMj5uKZqw3TV8CkhvhB2yYOA46Zq4UCgqj1OmLZrvpSY3VG2/yASYk5OO7pKHIQ3JksnhseKOXUdK/zYu4pVvTHfBuHxOJXxMdXlVVCPDHWNTbKAM+hrVL9pX17ZaQX0uTPoe2zeowhH95G/USQfWuANkw125oa/qY9pUd6VuaxtsHNQHkpx0StgsImQKFYXVXZkJ79sZYYfXFhUqfIl03JQc5rH2UeQkm67CvS0lgvGFtaRfQYBO290VGUVRRsDijGFxv6jgx6tGrOYjSqQD3O8hVNDXx4t5Xviokpx10vHaElaPEbkeAdiJ3apoRNACtpwd/75YJtKp6q5lIp2q7kpc3dPETadEvlZNldgCRKQTBEEwoBNx7uKW7hgWFTdYLaitn1NZVE1qOu2QnesFoK6LsFG4q8rjVNRWGKY3btcJ8IDkJ7Jx0t3ywAFc+rHbcOuDB7HnSJoPjU4c2mFYubhtAjd8bT1zw/f2AwBeftFpub9xwsTGGXOxwRFloijCW//5u3jvtfdyu5XLSec6vpruGE4OJvqajJPOofKsGc5e5wCioaBbphORLhnLqDMm8FA4go7zvpx0gUW4cWMnXaNwVwsnHTcnXStkV8sszGnKDncNvYS70teyRTqzcISzsJP+zhWw6LEHaHVXD+GujDBo+hm5bkEg6/Dj5qRT1x7dtODmD20F6fFiV3f14WLU1ze/LWH1oOcEYLlhR8W46ZPi35cOAb355HFGuCsATJ+c/q5EOnHSCYIg8MkmXfe3s7wwRoUjMuGuHnbhfTgEACORcoOJ5uGicFdjkUsfc+1XxklXcdze+Mk7cO3dj+GXrv4P/Ne/uEnnnDPdMW1mQnIA+Ph/PIynvv1a/Ocjh53bWK/MLffxreS4/NKPnJ37+3qdlJvhRBwh/qEDC/j4fzyMP/vy99lisFmggRsmZuZEc8mbRD+TElAAt0qedHyheTXLFgzUzbF5Kp7Ezy4PMv3SVSmZlaDp67gFU9KcdPHP6uquWddjHeppVeeaEjK3zZTnpNPH3oOTLi0cwS8QwBUE9PEM/Djp6LmwxNxI9FU4gl5HITMUVDsPWyrcVQlFzHDXIGAV7jBzTobMDTsqHrZt83KV9a2gOIbrXJiGerd95WMklXXZjtTAz9xVWB1owZT4p4XYPUxyjbcngKmt8e+Lh0ucdEnDtuGuQCr8ASQnXTf7fAtEpBMEQTDIOOkYi1sgu/M+TpUk6SSJ8xnVpKbTCrVzgbNgyCZSthewigTQTPhH4GeXmuaRq/o+l0ghiAPzPdx0/4HM+4dB7ELhOjQA4K3//F3MrwzwO/9wh3Mb65W9R5cxHEXYMt3B0x+/Nff3cbomfZIPd3XfIMhUf2QWOFFj6zSzcISZDJ6zwKXjPTexf37hnX88895kk2NmIg6HUSkWqLADABNMJ1023NVXTrp69wJ1R9ugvtOqr1KlN9gy3Sl9Dj8PaRqm6y+XFslJ5+pMomLMmIW7+iockQl3DXjV2c3qj+k8xYMYxqjumhEiQyoqO3UrIx5yHfr0M06ozQHHeeKoUNTkbZaGYYBu20+eyLYH8VBYPczNLKtzf5CIdK2JNDS1NCedS7jrSfnfJdxVEASBD50gssNd14BIx3HSqQkSLRzhukMNZG+4TRdZ1EVj5nvhTlppXhsb99sPnZ0VhL5016MAqDsjTH7ynXQK2QPOM58IHhsm2loEAYCzt00DWL/V3ExHC3ezQcEN2dfhrolI576Ij3+ayaJdvs5sMZdUkHFZSNKhz6ZwBHWZbZyMz091ztIwMQBkc8BNSKH3suGIV/E30gvv+P9VYqRZfa+OIKgfEw9rka7cSccdWwtz0nELBIQhyWPG61cs+PFyj8X98BcGbR4ebogkYLrqXfqUPf/YYZJFxQscjr+Zd48b7qpzc5ENTveqs/HP0Et4dr5fLi5lIOvwU+N0j30dhVo4l8IRaw8z3NUqH6Nys7W7aTXWxbpw15K5j2orTOeXmCHhrqc8Kfm7hLsKgiCwyeak8xfuOk4iXY/kW1phuGN6WqQL2blegGxYaV2omMnsUnoTNfO9cCb52X6FRBAo75eaaCv3lgq5NN0xekLBEDaFchaISAcA//nWl+Dm3/9xnJwk6Xd1s4w75gJ0mXONZ8Lh/DjpVLjrYBQ5LUpplb/4J7/6YxCoXEfu7hizcETdWKEe77RCfY7OJ+GuA0NcmLAIs6/CFGo5ArUargJDJC0KN1aPWGp0VuP+0STcdcuUhZPOQ4oDLXowBT8aotobjpzCs0cFQgXPSedvI9EMB3Z3q6W/h9QJzygMo9rw5uZiFi/IFJEKjk3hCG41+zBIHbyuGz3q8wSZ8Gyew4+mV3EWzpM+tFs8R6SwuphOWauxosxJt6JEugbVXZXDjop0KoQWALb/YPJeyb1qJCKdIAiCM/Smz8nlBGTDY7iCHwDsOLCAg0nSbA7+ctKli0wfZewzIl1NHhrz8bmV9OaXTeDuIdy1yOFXMQlQx/clTz4VALDr0BKGoygX+sWdTI8zhxd6+JsbH8S+ueVV64OqqKxcdNtmunjclqnMQnlc6A1GeP3f345PfuMRdlv5whHun5OOW9wK1WphNE0SkjvlfjNy0iU/3BbxI3+LeHPcSYsgFAtYtPLphsRJ1xuOsDIYZhakQOqkc10sm/cfjrsyF+5aMY6NyCLdBpv8gspJt9XGScd02tBUDtxqmS0iLtD3aELWlcfPpUXHQG64X65whGPl+HyV5Ph3t3DXpJ3QLBzBDzfm3EfoXMSHky51FNHNP1cnHXFraied23eZKRzBdaQSh5+v6q70e5Rw1+PLIwcXsX+Ot57JFY6wmVMrkY466Ya9VIjrTKfPDWsKR2iRrpV/DABOemLy90TEEyedIAiCOz6ddANPYhgA7JtbxguuugE//M7rWe0A/nLSZcNd+Xk9aF6Vup1lc3GvwsSAfAJ35VzzUTjCxkmnzqGztk2j0wrQG46w9+gS+Xxp3wD33fNx5rJ/vBOXf+Ee/MZHvrlqfVBOOioKAangMU6T8s/duQefu3MPfv/T32G3ZS7aeSIdcdL1/SSWV9VdATf3Ti7EheFCGZDcYwAvHM7MldciylTRcEGddDPddCd+fnmQCe0CSE46VyddLk8hR6SLf+pxrOr4k4W1DXWLrOX+UOdG3FyVk86XM4nkfvNRbKBLRDqXcyzryuPfc6mbmC3S5XLS8Y49kBW7nao3G4JympaDKYYF5LzghruS4hh+CkfwCp1QEZ7rpKMbKm1PTrqssOZ6jqX5QCXc9fhzeKGH5135FfzI5bz1TFlOusrLe0icdN2ZbD45IOukq6vuGhWIdBMkXLYzmbyXKhwhIp0gNMJ158pkuT/E3XtmnUIYhPHBZ046OhHkhpLc++ic/p17jvmu7hq7DfjCB931rnOZmZOzBSLSlSWe9rNgq7fTq++92wpx1tZ4V+6Rg4upO6Zl5KRbh5PDf//ePgDAd3fPrlofFnrZcFdFmrx9fI47d6yhmE4FTrgrfS03sbxaGFGRzmWRlQtxYbhQ1JjT9uC0MRcMNA9b0TimPrsa75SYvLAyzFWwtSlYU0VepHP/LiND+Kiq7po66exEujRcqfjvR5f6+j03TbaLnwR+5ezinHTMMD2ymQW4jT9FQoWr4AT4zklnOunc2svlPKw5J6qgxwsgwiYzHybNCcgOdw3JHKXmQw6GI7z1n7+Lv/jy/YXt0XBXZyGS5PycYFaVprmB07BxV/fbKG2LKVBTV56Eux5/dhxc0L9zIklyRaRsrqMBqe4aBMDmM9O/tSaylVoDVd215NxQ4l1ARLqn/Rrw5J8DfuGDpF0JdxU8E0XRuhecrvrSvXj65ddj95Eldlu//uFv4uV/9jV89s49HnomrBbjWt2VuoG4k+mep371h/nFB2fBQN0jtUnXjQnV3DIR6czKacxQEhoaoSYBVQs2XbWxFeDsk2KR7uFDi2meKWNxyzlm40ortFuUH0vMcFfFOIa7zkyk1zdHVAPS61t9Bb6cdNxwVx1C2A5Y1aBNlxmvumu68AOIgMtwx5g5J4HicYxWGARSMXlupZ8L09Phrq4inXFOccZ9M4S1ahNEDW22o0Gd61lVdt081akU/mwcz1Vkq7v6yUmnKm+qbnPyHmbCLT3cw+Pf/W1KAozCMKYj1UPOSXV9+6zUy2nLvL5tP+M//ecufPw/HsZV196HvUfTdQv9nKpfrud+Kmzyx51UPOQ72LVAShyp7m2lczQJdz3+TJKNugVGQSotKOvr22LcV8UelLtt23np36iLDiA56cpEuqTvNCfdxAbgFz8KXPRK0o6Euwqe+bUPfxM/9Wc3reuB6y++8n0cWujhPdfey27r6w8eBAB8/OsPs9sSVo9BZmeZuyj1Vzii20pvarPL9gN9EXQXmfMZqZOOm8g3iqKMY61uR8xc4FABIZPvxYOTjuaHqhMPgVTA67RCPD6pJLrj4EKmSmzcHm8yPc7QsK7VQrkrZ4xw1w7TlXQsoJNWJUS4oq5BJfpwrnH6Wm64ayafloXAMBiO8KnbduIr9+7LPJ6GWxrJoh2+TlMo41TyNCuytolIVyTwDMhCEYDOS0fDXbWTrsVztJjjJSffau74VwgMpiuqjrpx/7AqGlER6kr75CysqQ2oMHWJuzuT0vtaEPBymRUXtHD/LmkfuJsW5vfvLqBkz/3USecg0hGRCOBv2GUKRyjRiRGy3zI+Y90c5eobH9S/X3vXY/p36i5uMV2kOtw1JOGujveQiLSVRltwBVLL3GMVDIiL2Uc+ZaEZdANrftl9XpGe99l2rZ10AHASFek2ZJ+rnXQNwl2L0E46+8+6+jNoYWyJogg33rcfd++dxR07j6x2d445nEHCZJzcGUJzvIa7Useax6TM3PM1E+7K2oUn4a564eE6AUt/pyEbZesPc0I1X1I4IpuUufz9v79vHh+5+aHCxXmRk65qEtAnLoxTN8c5KQ7O90oLR6xHJx0N61otVJ5C00nH3YU/FtDz+dBCj9WW+lwbJ+OJIUeQoW5ibrgrDSG0qaL6Pz7xn3jTNd/G//uJb2UWiWmeIyQ/PSzik2tSuyo8uHZoHrai8SJdKMbvuVFVeF0ZZJweADDR4QnLpijBqu5KktQD6fdQXDgi/mkb7qqOWdlXqQTsqsqugD8xphXyE96b4m2X4YCjIlHXQ+EIOgZyw//Nbrieq+q7T0PYVPsujrWsK49TZMZsL40ecBD0S1y3VafYcn+IBw+kYYJf/l66eTHMOPyYLtIof445uyIzOel41xFtqy4s3rYtei8ap/nAeoeemzRVTVNKw12rrm/lpFMiXZWTLqhz0iWPBzWSWpjcr8RJJ/iADnwH53kLhrUAd/FBGSd3htCcgU+RzmNbNAnwPOOmBvjLQ5NWdw3QCf1MwAAjR0tpuKsp0qXXsGorCOLFoU1Z9p/9i5vwts/djb+64YF83wrCcKvWRWlC+EC7mRZWiDtGO+l4k2nKuGUmUJN7H8yvDPChmx7CnoZpCRZ7JSJde/wm5bQvyi3k3lZ8MqgQWo6TjobeLrFz0qXXUTfJdVT1Hdyx83DShxHuf2w+1yflPlTXk8t1lApl8f91cnOHcTFXOIKGuxb0jY4TQHqexiJd/JycsMMMFVO4jtNAOtaY1V2LxldnJ13JgHZ0STnpyiu7AvwNEL2IbwVaRHVPUp/tE6eqNxUXdMi4h40283cXzEIFvpx0rHBXM38iNz8trVbKOC/KEt5XFXt45NBi5j7/6NG0crp6GZ07DUZuKYuoK2+CG+5K8ttxU6KMiuZh7BQmIbsIhdAcOn+fY6xncte3zVgxIIUjAOCkJ6R/Mx1xSnxrUjiiCF04wn5uJyKdUAod+A4u8EokrwW4ogdlnBZ+QnPouT8cRazFjC/HGpC9qXGddP5y0hWEuzInYIBdHiBzsTpfkJNOTYDV7nnVhG4hESA+9+18TsmiEKOqSQANldpAFt5p2GzWSSfhrtX85Ve+j3f86914+Z99rdHrdE46M9zVQy4n39CxwpeTToe7cpx0xyAnXZxTSAkMFdcRuS7u2nNU/6421aaS79UmBL0M093aZbhjTGGNClNFooD6nlT/N2REuqwrL3W0uH0HeQHFfcxJN0GMcOMikS75aV04QkUXlXyX6nyc7FSPL5xzAsi6p9MiFLz8V7n8Y4zzNaQVLhnhrvT6446H5n2Mm8dMXT8BwzVF7930Jzc/bRjGuTUBXl5N03VbNRd4KHHRqc9AN3PonIeG2bt8TFrsQRWOcHdFppsg3HDXTDoURh5SIL324sIw4+esX+/Q+yvLSZe7vuPHq510Ktw1Ec5Oe0r6t5mTs89VO4BNctIV0Wpnn2+BiHRCKXTycGI46STcVYgxb9Qcp5kZ7sopxEIXrJydJ8Cfk47mXmNX2zLyyNVNps1FNE0+ay5wmyyKHjm0mPl/LleehUNDHYN2K8i4Y9IE4sj0i5vgeRzx6aS7c9cRAM1ztZWFu7aYE/xjAV24HGE66dR5tkGFu7Jy0pFwV3ZOukSsaKX5nHrD8r7R8fOuPWmV4KXESaeqxHJCn8wk9Woh6RK2b447QRDoa73KSacLR5CcdLkQSW7YmXGus6pwm9U3K0L1dJEJy7brBBma17AKb046D4UjzOTmtpU8C9si4oLvcFd2Sg7jfOYLO0oETtpniJotck0C7mGSVBTgVLTPiwv1/dqRiHQ/dNYWAPH9UB0rWrSmRVJNOG02kOvbV+EImovR5ngdWezpz6vbKgp3ZeakC0NelV7BDTr2cUwH+bl+kue5akwcqMIRiZNuwynAJV8AnvgS4BmXZp/rUt21CAl3FXxCLyDurv5agOsQoHDzegiri6/dYLOtKOLlHht4uqkBZuEIftLpjocKWfTzZXZKy0Q64yZMq7vqymm5UJL642/m78rlyrOYHFJ3js4ztTzITcy5ib/HeUOgQ5x03MnvBadu1L832VBRO7QbTJEu4C26jwVZJ52fwjAbPTjpfIa76tBSUp2vV+mkS/udEemSfqiK1wFH9DCuSSUeujiozRA22m6RwDAg4wRg5qTLLj4mtKjpJ9yVM3aY4a5VIYTmc+uoyy9oCkFlqD5FUbkrr4oBre7KTCxvOru128PlfCUJ72m6BFexwiwcwdlIVJ9HiefcKp5mOLVL3/JOuuzjjdsj32W37X5e5M4JizFsx8FEpDt7C4D4+1rsDXOFsui14fI56TyFWzhCvX0raJbb8Wf/z814wVU3YNfhdNOUhruGNo6pCrI56STc9XiTWc+wwl3jn7nryMpJN5E+ds6PAa+5BvjBn8o+tyonXRQ5FI4QkU7wAD3BD8yv/3BXTglok3FeOAv1mAt3VvVTQ3zhhJPQUJs5bnVXRgXbq750L370in/H7iNLaVhnK0wFJ9fCEYZIV5dHLl/dtSDctYFzYYI4v+higAoFrZbd5LDOSdcywl1HkduOMEd8Oda0iUjHFZW3kvxT9z46Z/06FcKcc9K1eLvwxwKfOenUeZbmpBuPcFcaYmQj6tOx5J69s/r6LQ13ZeWkS0Q6leeLEcJGc9FVjT1mddeZApGubThtnMUF417EqWSYOunqQwi1k846J516XfHfUzdyjUjHFCroRkuHuZmSc015KHRCq4sC7iGv9DyPIl7qBXVKTXZ5IZJlBVicBKcSMczl2EdRlClqoR2DDEFff0aLecW+2Xgt9oTtG7RAeHixl3kNzdcGuG1E0eub6+ClBTJsQ1SXekM8fDAW5752/wH9OBVcj4UIL06648fQk0hnjq1W+Wm1k646rymA6px0VLirC3dVfxcnneADOtk6MZx0HnPSjVGeI98cXerjo7fswP659Svc5px0DCHEXAjx8r/5uakB7jnpDi/08Bdf+T72Hl3Gp765U09quq1QLxic842QiVYY1N9s84Uj8uGuTUJJztgypX9/bDY9v+nap01CXCpz0iV/64RhGsJGCkfoJPUkZMtlR5gKrOOW127kaRIGZBca32si0ulw1+wu5zg66XoZJx3vnqvOpemuctJxwl2Jk44d7pouTDs1i78oijLfz2JvqHMylYW7OlV/JMIhABK27y7s0EjMqsrSae7KfLiruYhnV2w03t9nuGtVzk9nJ13J57R10oXk7y6HjOakU9+h671tkFtI8p2f7TAtXAC4i67mZ+JsMishWF2Xrm3lhLWKcOr6PsU/aQg6fY9mbWXFMM41Web2t5pXtEJsnY6dOUcW+7miW3Re4VRsgzgZVU46140eKvilUQjVr3nwQFokiN4LqWuqrnJ2HfQ6knDX4w891pz1d2nhiKrre5AUXKFOujLCCicdFe7qqrtqJ53kpBM8kCkccQLkpPNpc17PTrr//S/fxf/+7F34tQ99Y7W7cszwmpNu5HMCnLblMyddE5Hun+/YrX/fdXgpdYyFgTe3QRhkK7KWLbzN74kKQfmy7NnH66AiNP08YRBoga1K4NGLMqO6a+raCfXfFS4TzRVPYcvHAiruzDGddNQFdHTJfidyoSQnnc+qur6gaRJmmU5ZdS0ppxnLSUc2KbhV0HXok8XCiH43T9g+AyAtHpGGu8bfq1qTuiy8TWcWJ2zfFBfo71Xhrq2icFfdFjLP8VGYB+Ddi1QXzIVRYbgrGjrpahZZQzK2VrZD3tBJkCECqjonnHOHlji7XZrLFo5IP6OrwGBuKnPStai+qaIervPqXM7D5KdTuKtPwY9uJFqk5LDql+GurNpooMKScpcfXuxli26RPJgAz0nXCkmYPdMV2aQi6/f3pSLdA/vT36lryqcIL+Guxx9f65n0/Ir/bxM2riusNnHSRUVOOvJYXbir5KQTfEJvFEeW1r9IB7hNAIpYz7sx/37PPgDA3Xtna565dsnnpHNfmJq5NzhOOq856RwLR9xPJk/f3X1UT2o67ZAdMpAmxDZCQUtutjmRbrmgcESQXRRV3bipGHeIhBuaTjqrtlSuvjAV6UZRKhqptRU3d0xWpPOXV9MHtG/c8Gx67jdxtpqOK4VOLjxOIh05n2cbCJFFaCddR4l07ufG8sCfSEevy25NjjX6nV985hYAwD17YxelKmChRMjQ0qFR3KdsyGmHkX/MdL/R34vDXUucdCvl+Stdz1lz84QzT1FzpdBYGBXNodTb2lZ3tQ13rXXSkT+7iHT9TDgcz2lj3o9Y1V2J85OGNboKDOb152MjcTIZd1zyOtJ2cuGuLk7ZMlc9w/0GGPlpWVV6kfysD9+kx2VL4qQ7bDjpWmEQb3JyXH4F4a6u9xDqpLX9Hh/YnxaMeIDMOennb2VEOo6Tjj93FZpD7+9+q7umGyCla/pBQU66MqoKR1BXnG24qzjpBB/QmxG3LLvClwjmC/MmvcQICcq0O14f0yubpjpe2xu3cwIoyknnz0nHK0KRvpYbPujqpFsk73v/vjktvmSruzouIofFk9ayCZ25iKbuo9zumsWiiLZ3mIRYZHLSkclhWVujUaTHgHYrxHS3pV0kj87GNnvl7KJuD5cdbzpxHj8nnb/zlVbqarJYUH2YzIl0SbtjNFjTnFKzDBGe5k1SIpZZDKUJKx4LR1BXRadV7dCgY9TZJ00DSPPjLvWyYXWcar3qbXROupZ7nim9YCgoHFE0XgyHWYFwppuKdAs6755yCyZOZdd0AsbH4eWki38q4a2quqt6lxpNTRNWCH7xe4wyz6trh/bXliiKMpXL+fkAs8KiOhacwhFhIsZ0uZtjx8DtP9nmFY44Vs5DIHV0cgRS1TeOk8503dps2BU56Y4s9jLrNVMIdplXUFF5wlN117CBcPjgfuqkSwU7eszoGMsJdw3DdMx3jQIRmjPMiHTu84qycFfzPbIvchDpinLSZcJd6wpHiEgneITejHyIdJf945142ftuzFSKW23MRLvckKwTgY2TNbsFDfju7qN4xrv+HZ/65k5vbfrAa046j4UjqPjFPVdpRcUmoscCWaSPIuBbjxwGEIe3dLUDxVMemhp3jFoAnLZpEgCwb25FL+zKc9qUT+bo8T2YyYOiJgGw2qHuG6JeEATYkCy09x5ZApCK3T6ddL0BrzKfb6i4ww53jej5and+DYYjfUxpURBgTJ10NNyV4aSjH0nnpGM46ejx5joN6HVZF2JEv5uTZuIFqQp1XkoKPU0bTjq3xdpI9wkAq5Jn88IRJU665QHmk00Hdc/lOunMTUk/OenqQ/XM59ZRld8OaOKkcx9bl/pD/T4bJ9upu5Ip0ilRh+PmMsM304qZjn0zvjNOTmU93qpwV+fw4Phnk3xt5W2p45Vt003QT19DRScf4iF135b1jQoS2km30M+JhwAZLxzOCyqS+gp3DQP74jc0pcX8ykBXdNepCcJs3k+b7/LG+/bjK/fuy/WrHYbpvYgR6i00g46lnPlhvnBE/XWUFo5okpOuoK1M4QjLcFcR6QQf0Juhjxxr13xrF+57bB7X3v0Yuy1fmIsDH+Ef6x2fTro3XfNt7J9bwZv+6dte2vP1Hfis7porHOEpJ90isxpxxknXoE/m+z6Y7HKeunFSTwqdC0eULGTKdjfVAuBxW+OCD73BCIcX+4Vt0Z34OocGkHXSlRehqBcX1AJKLb53H4mddJsmO7p/ai3psotrCsjj5KbzGYpLj6ltWzRMc0046ch12CTvngn9TH6qu6bHmyvSUfdCt13tAKLjyFYi0kVRhMW+ykmXddIBzRfyZlJ/jjPJHCuAanFNC04tlZMuHhfmVwZ64aLy1HHcgvS9FH5y0iHTt6Jjr8ZbSyMdGauLP6delNXmpMv3wRZ1/bXDANPdFikcwXMTKYGIE75puvLUuePyfVLXrYI1R0kaU+Otq+CnPqO6N/ootOFDIDUr0OvQbEZb5qZk/Lfi11CBeoty0i31DPEw7V/8GhdHcNJWyC8cERHBz/bYm2YOlRedHrPs8apv71c/9A38+oe/qa/topx06zmf+LhBN/PnVxjznZINI6Ai/YWLk64oJx0V3OoKR0h1V8EndNDvDyOnm1AR3NxEPjEdP5ykobkKWWO0WPbJJo9OOttE0jbsOLCAH73iy/jbrz3Ibss8LzgLXJ/nBV1kcc+vTE66Bk5BZUv/wdM2Zh4/ddMkO6+HGeJSl+BZLQCmuy1sSxbxjx5dLmwru2Arbo8KqjQnXVrsITsJKHNV0O9c5ddT4a17tJOuTZ7jvgAxBatxEekGw1E2jxyzXy456aiTTwkvCm4S/mOBmSfS1XVOxQ0VDspxsNNQWW5ibXpddmvCXdXistMKsDnZHJpd6mNlMMqF8zbNP/bNHYfw+r+/Hftml1PRo5V1oJhOexvMcYf+XnR9D42FesZJl4SIe3PS5RxT7t9lZCyMqkQU9ba2OenU8Sodpy2ddNmcVVZvrVEL+c1THQRBWkWV62I00y/4EJ04hU7o+3MdU3F78U+dk459vLL3b06IqrrGArJh59qW6hNLbC2Z71S1R4/LTDL2LfWGmUIb6vNxxgsaPaBckc5OuoLqrnXHy0zPoNIcDAsEP6D+M6p5FwA8cnAx85q4MIyEux5vfK1nzHQVNtdR6qSzKRxhUd01aNUvaCXcVfCJeXL72mHgJIj0jfmZXMP0gPzgznU6jSvKAQTw8xOZ7hYOf/zF7+HR2WW88/P3sNsyK5RxXEBDknwaYN6MHN1vRXCddM96wkmZx0/dNJGGuzpOzM3FV51jLV3Ehzg1CXl9LMn5pm/cRXkqyqrFljjp1Psrwa1uV5+OIzqMTYl0RxORjlxHesfbQQAxz6dxKR6RS0bOFOmyOeksRbrked1WmAmBANLQJ1dX0rHAPGauISAZkc5HdVeP4a5UlKpb4KrroR2GWqQ7utTP3HeUCGkV4pJwdLGPV33g6/jcnXvwiVsfySX177Q5hSOQaSvuW3m/RobgopyP872BzrG5IXHXcZwxcd+y789ZkKpzTDudKkSUNH+dXdt1gowpbJZBRcGmQsXRxVSkA8DOt5o6LLNFkVyGn/R+xA93pYdlosbZaoOa70wy20qdmtmNMReRLpdYnjH25yrQ+xBbDXdlVXvU/aVyVS72hoUOXp3SgXPMSM5D17kFdeWFlg52Mz+4ctJRgToI0iiEus+4J4lgAICHDi5k2spUd5Vw1+OGaQSy5XN37sEzLr8e//bdRwGUb+6b75F9c0856ZS7ri7UFZDCEYJfTOecL5FunpEg0jfmpIblpDMG9wWmgDWuTBBh7fAir+qvWXFxXFATIZ3PiZOTbqjaij9rb8gInXVwE5XRG7q1pZx0zzh3W+bxUzZNeq+AV5dnSleWbQU4fXMs0j2qRbrs4je0uHHTxw9mCkekE3MgXRyVuYtpDpbQEOmOJIs/GjbeZrg0TPGFe14cWujh/976CNvx7DsMN+vKs7uG1HsqJwCllUzKXfL1HCvM+8+s43dAzyMfY9ixCXcNakOOqWhPRToV6tptpVX5rEJcEq75z136932zy7nNgQ4jtLFwsRyUjxdm2KgKd40iYN9svJBInXS8c1b1ra6qrg1lIkrRd0ldPjbUOZ1SoaJ+CZOKYXbHbN/cMv7zkcP4jY98EwCw0cgdOmQKpOqcD2rubVWkBZayTjqnQicFgj7P1aI2OHltmSFsHPfbwJgLeMkHaLmRWEWVuFDWNyo4qjklFemo0KfONTfxNj1mXabDMlPswfJ4Kef31iTv3sGFeCwsCxGuuyzV5igQR90ANNUAEenWoZNuZTDEm665E5//9t7V7koGOqdrcq/96C07sG9uBf/jE9/KOOGLwl1Lx9cmTrrQ0klX247kpBM8knPSMW7cdII0P0bFGcyBgbOzbE6QFsfIMegTOnk4tMAT6SYLFs+udNv+2lIDuxIRXZMfx6+NzwtVtc9buCvXSUcLDjRoayFx0j3xlA06xHSyE2LTZJsf7lpiWy+bsKr3aRMnXS7ctShPRcEEMYqijEiScdIZeaPqHEB94/kAtIiooGHjnFxTOZGOKYb95sduwx985jv4/X/6Dqsd3/2ii2PbttREX+XUobQZx/xYYeZvcs1LRy+Xae2kYxSOIAIf1xGp+pZZsNU4UtutQDtPF3tDLSArUQGwDHFBHOb6kVse0v8/ML9CFr5h5qeLI9gcd4Bq563pSJvspJVE9yRjmQqBVZoUt3iBdjkxXCNmMYgwLBdR1EO2hSPqNmdGZHFd35bqb/37Hl7o4YVX3oCf/8tb9CZr6qRzd1cCRXmTso+7tGVWBXUKBSUHRueRY2xcmFEIvsJd7Qo/jfCOz92Nv7kxm/LEFHZSwY/vfgssRaLituKfad5c8rea6AEq0i31B4Vh9pzNP3UKtIIgPfeZYfZhUC3mU9S9+8ytqqp34qQrqfpbdx3tJU46JdKpOQUNd+VuQo0j13xrFz512y781v/9z9XuSgbXyCB63X53z9HcBojNhnwzJ13SXlVOutAiDZTkpBN8kivL7mF3DRivcNd84QiGGOMxj9k4Q2/UyhXkyoRHJ51PkU59l2qi6aPa2bSHsLNM8nymYyoT7tqgT4uJk25moo0LH7cZQJyPLs7b4x52A5QngK0Lh+u2Ql3h9bESJ12dBd587FChk85uwaDFBfKeP/z4rZnnbJ7Kh7v6yEnHFVG+9fBhAMDnv8Pbdc3nyuM5i51y0iknXcHYYLtYOJ6Y9xDXCq9U9Epz0vlJ5cDN4UedZrXhrkTsps5TJcRTJ3ZYI8ID8bXxqg98HTsPpa6KPUeWiTMLmZ9OThs97qSPVY1jpoAVBIF23T6qQ+MNJ52rSGcm9WcVyop/6iT1FcJHZAiRdai2ytxvZqGPKgLLRTwA3L9vPhcBsdlw0rk6bUqLD7kIwSVtcaoRA8Bkm+/293WO5Qs/xY9XCWtXfelefOjmh3D5F+7BT//51/Dd3UczfbLNdVtFbiPRQwEQJdgGQX0hCr3JEQZ6/MuEu2acdMl5wTjHwjA9953ndeS7pGJ+lbtV3a/OTIqCpeGu8d/TSp7Z/paxlzjpVLgrndet53DX2aXxWXNTXJ10dG4+vzIs3BirdWwOEtHWprprVU66SCvt9e1ITjrBJ+ZcxJcDaH6McrWZAwNn0mq+dr1WCaKD3jiFux4LJ12a/Njtu6TurOkJfiiJax65urZsBZTeYKTfd6bbwkWP2wQgruwKkATWTKeHOQErW5T2iBi2fWN8s83vuMbPzS7i822ZE9nZ5b6eRJrV9OpEtf4w+3wAeJoh0m0qEOnqJsG//uFv4FUfuKWy6MfymOSkM8VovgOLiHS24a7KSVcU7spMwn8sMK+bWUfXOV0wUieda/VrOtSww11JGFW9ky69jlphoKucfvIbOwGknw0wCkeUtFcUwr336BK5vu1yTlZRVTii6DZiFmAA0tB4VanazEnn6v4072uc7zJ1AGaddD4KR6inlZogCgSJMqpCjU32zS3nHtucFPhRrj1u0Y62Fp3cv0tTpOSMZfS4TOpwV4aTbmieY3z3FUCdmuXtffr23fr37+6exSUf/iYOLfTyieU5TjrToc8Q9KvGijJhLeuki8/NTOGIjJOOP46FQZCKdM7zYOi2WjXzMIXKSfe4LYlIp8JdTcHVcrNNuZKBNI0AHfc72i24/tZtG0jUhusc4FiQEekajDn751b07/PLg5ygD1icFyrctW1TOEJf5Pm/NQp3FZFO8Ig5eeBM6OjFOE5OOnNR7LpTBBSIdCeAk477XVKRjuu0odUbuZWIB7nFjOtEM/19upOEu7KSMqcN8qu7RpnfbY4ZTdg+3W3jJU8+Dd1WiOeefzKAdCHjWoClTAwrLRyhFvGtUOcuOZIIx2aIS90i3pwU94eR3s0tdUGU7Aar53fIOfnE7RsyIa60cITNZLo3GOEr9+7HN3ccxvV3P0b6bWw0jMm4Y56f3POVjs3W4a4DlcQ8P4EaS5HO+FxcJ10YpG7lUcQPVwLi64Iz0afXZX3YeBruCqTC9r/dFSeMVvknAbtk0YsFeWIPL/Z1FVWf7phM4YiK9orGNiXSKXLVXZmOFu0QZ8x3TBGlKr+gFvQs2w5rRJQmTjr1FJuv8rHZldxjqZMuPWYu57+ZR44lrBlCRZtRmTIT7uqjcETSN24RirJ0FVXNmfeYA/Mr+Mr39uWOVyoCM65vD2Jr5VhRGuod/2wFgQ73j510yeOFgh8vt2Z6fjmOO2TDlAopZf3qD0f6/ZWTTld3NY6ZjXgLAI8RkU6lkdDjSCv9jOtx3bZhIp3/cBz1vqHnuO05urAyyLidF1YGhU662gIlQ5WTzsJJV5mTbpB9TmU7yZxfwl0FH5gnNydMjy7afYh0V3zxHvz4e27QFbhcMQUTTtLQfOjs+AyGPqECB9fNRXPSLTALitCQNrMyVFNyOekcPye98fhIyuySPL8Mc1Jj812qfHTdVohuO8TFZ23Bd9/+Mrz+RecDIE46TyEudbth6vh2WwE2K5EumYBVhrsWTOiKhEWVuD/nXKjZDVafn75nGAb40fPSiribpvI56aomKvT7/vL39qX9LhAXx4F8uCs3J11zkc7GSTdOO+fqvFEijeu9Uh2qMAgy4+Ky47hojhWsnFXa8VEfdqbF7mTGTUPEgaxT1abS3zw5nr/wtDO1E2/X4TgUykcoYnGVxfL2qMtEQZ0P9P+c8DUg/R69OOlUlI9F9c1RwWesQoewlXzMZjnp7EWUfYno++pnnJV7PT3XXA5/TnRi5JFTgl96vnJyjyUCagB2gYC4D/FPtTngvmEX/zTFsCqBVH3+a3/7eXjFDz0OQCzuaIHUMl1FFWXFHry7bi1y0hWFu2YLR/hy0jHzMY7UORZkPmvZrZfO309PnHSHF/rJa8o2TKv7RvO7zq8M0B+O0nEkTCvYjsv8ySd0k9I1z+2xgJ5PtmMOddEBwNxKsZOuNjWEcsDZ5JJTTrqinHRRg3bESSf4xGURXwadVM55KBzx1199EA/uX8DVX3uA1Y45gRAnXT10UevzM3LFW3rz57aV5qRTE03e5AQg1V095aSzdb+VYS70bISPxUSkmyY7czTMmJu7pHwhUzw51+GurRBbp2PbunbSGW3RRXydk06JAcrJZE6m63aDVVvUSQcAP3JOWhG3qZOOfj+3JXnjij7LuGwOmGG4bCedg0BdmZOuIgRxtTBFOnZlxDAr0rkKpeZ56XqORVGkRSmbSn+m2G2KdO/6+Ysy/09zmRW/v7ovnL1tGu/5xadql4ZKJJ6rKm05jD1ycFHPJZoXjoh/Uv3K/JzaSccMuVTjslq08XLSZUWBqmql6XPt2q530uU3QUrbaiCGqXym5548ox9T81UqCHKq/qr+cAoOmOdYmyHeUpGY636L2zOddH7mArXOGPK3qU4LJ2+I5wMHF3p63qIcRT4EUnOscDEXF4p0NRuT1DGnC0f0aOGI9Lk8kS7+GZJxmhvu2iKhs0C5cK42k4IAOo2JEpdy4cYWDksgn+rg6FI/s/m6nsNd6XEeJ5GOFgOzHSf2GSLdwsqg0EWqfi3dnNHimoUMVpWTrkm4q+SkE3zis3AEXbT7HCQeSibXrvh0v50oIh39mFwnXSZ0lpmrMFOcpCCsyaUtHRbETBYNpK48XznpAN7xN8UdG+FDuR1VpVqTTtvP8bIt9pCGuwZEpItzyZk78UB1GBvNf6VFOuWkyzkXqneDh0aYnuInLzodQJwIfpKEettMpul5c2QxX9RCP29cRLpcdVc/1yTgUjiiPNx1nCblveQ8U84pV1GNhpQGZPHNbU/BdcoCyBaOKHPKknB2IFsh+eUXnYaffsoZmefXtafuC0oEfeIpGwAAd+w8kjzeStqJn1+1iP/wzQ/hxe/9Kj5000N43pVfwf/+7F3Jeyd9yYw78c/CwhEFAtYLfmB75jkbjZx0ruesDkXs8MUYU1ysypfXNCddnUjXJCddGu5qI9LFC0BVKRwAztseC3Z0w8VFDFNTTZ3KoW4RWdVWibPbyUlHjqX6jKyUHJ7DXdUa2sYRSY/LSRtUjtoVzK0okS6+7psIpFEU4ZGDi7ptUwzj5K/UY0WBoF927tPchkqkW+wXF45g5aQrELCcC9aQtuhnLWtvuZemqTA3TM3CPDbHfziKcmuCw6T4QJuE9HLTOYwj9NiMk0hHc/DajhNm3tD55eJw11o3fJOqrDonXVF11wZinwp3FZFO8IF5cvPC9NLX+hwkHjm0yHq9KSZwJq1mst1xWSz7ZujRSUfPMW64Kz3eHCddFEV6Eq7DXR0TKWdEOuWk85STDmBWijWdshZtKSGVJmyndDyFRejk2pYhqt1WiC1JuOtgFGF+ZZDbcaXtFU3oqGtHhaKqxP1m0u+63eC+IeopHrdlCv/+u8/HF9/4vMzjNlUb6Xc9tzzQE8mxddL5zklHxh3rnHTJjvxkQbirXsCM0XxcfXczE0qk44WnqtNPLZhdw11zY4WrSEfaiUOfksdrwtk7yQLq7JOm9d9O2TiZe36d20bdF2YSMe78UzYCSMOrVM47m3DXt3/ubnx/3zze8a93AwD+7tZHANBzLi/CF4a7qr6TcepnL35c5rXq/E1DSt0SgI/M+5qXnHTZjYuibqVFJuza1iJp6XlRPL4Wt2XntAGAx5IF4CkbJ/Evv/Vj+N2XXIBf+pGzc+/lkhNwaLj/OCHVZYUjnMRDInpokY4xVqvPM8F0a5rhm1Xnl34NcaZtm0mcdPM9zCf38Q2Je71JzsnPf2cvnnflV3Dll+7N9Cvn5GJcj0XhrmWHTc15wjDNSRdFab7NsKAtN1E5vYeodriuyCCAscFZItIl972pbirSqbDGMoG6akNlnkRvnbopW2AMSIoYWRa0WIvQ+6FrnttjQTYnnV1kEBVXgbgQpbqvT3ULNr7LzotGBR9UuGvBRekS7io56QQfuCziy6CL9qW+e5U5k52HluqfVIGZqFvCXeuhh8hXpT+AH6JKv7t5Rlv0PsGt7urbSZcPUXUXNl0Ev8VESJ2eKL4hpbuRfnPSAcW73j3tfgsx2WnpxeyRxX7hBDh1VZS/d6cV6lDUWSPBsBniQl9HUedip2B37bztG3TFMt0vi8k0PW8Go0h/X/mcdLxrsmOR58kGn4Ky2V7zcNf8RCwVbMdnnE7DXVVFVj/XkcoPZetANDEPkfNijbTTIgujusIw6ho+56Q0DFGFQVHq2pvXIl08fp1/6obM39V1b+PO2DRZPAYqwW+KCMOVhSO0JS19bPNUBx/9jWfg2eedhDf8+Pna+dMm44mLqyVfEInvpMs5nSyFyCrqQgj1Zo5NTroGoY2q6uMpmybw1LO24PUvOl+nc6AbMy5O8VzCe464U1I4glVhNAj0Z+WIt+rjKLeme+qL+KdOMVHjFozd8+lxScNdV/R1r5x0TSqyvi1xyH7gq3FqHS0EtpR4aN+WydAQuunvpYUjkodjJ106BpnFb+Ln2Dng/uqGB/BXN2RTB9FqsR1mQTB6vlJdvezcVwXKJtthJvR/brlfUF23fqxWERHddqg3d1S1WCA+lpkN4XWm0o2rk84cG2zGVbPwxfzyQKck2EjuyXXXUSquWYh0QYVI1yjctbmTzkL6E05UcuGunnLSRVHcVtHCqSncAcdc4HJCn8zXipPOpq30d7ZIR/q1yAidpQsXtTPjOmlNE+amk1ZfBVgAPzveTdrSTrpOiZOOmXw3nYDF/68r9pAKcfH/t053sffoMg4v9gqTyVaFBQ1IiKoW6ZSTzlgU1u0GD0rCXcuwy0mXFaZml/uY7LTyVbgdXZ+KTitEf8hztQIF46HnwhFRFNWGz6ljVpSTLj3mrG55RW0aqcWks6hmLOIn9djjqXAEM1ceEF+LdWKYzu2YLDapk46GJCpSQab4/RcMke6CUzdm/q4ctDbujLO2TeOuPbOZx1YGQ12shDrpqnLJ0dxPlOdfsB3PvyAb9toi48lgFKHpFCotHOEv91jqdIofPx7VXVMxpt5nYBO6DMTfnRI6Tp7JC8Aqp2kUueUy01U5fTjpStIv8Jx0gRcnnRnu6joPTitUK5Euebw0DDT9vRUEOCn5Dg/O9/T9XC3iA4vrW0HXKVEUZVIJ0LZ4Ycuk77poStmYmDjpklxx3XaI3mCE+ZV+pl9xW/XnxcLKAH/yb98DALzq6Wfi5CRMmFaR5Resge5zEMRC3SiqcNKpMbTbQqcVYrrbwmJvmKQySdrSuR3j/1cdfyXibJpsa9HvIHXSEVd33F8R6Y4H5gZpfxihZP9fozbBts10cWihh4WVgXZebpqyzPMcRangZiOuVeaka1LdtZV9jQXipBNKyRWO8BTuCvBdFRSfeeQ4O4hmuKvrQmbcMYsXcMiEuzLzyNHjP88InaWfj+s4UBOHuHoUP9w1l3/sOIe76h3pEhcJe8fVcL/VOdbobi+QJlw/stjPCX70eYWhsyTUVoe7ljrp8q/LtGXk0qrDZhJsjpkqhMMMveJuDnQLBC0XfG7ymO1Fkd3Yo0SuwuquWrAdn3Fa5WjZkOQgcxfV4p/qfFULTXMX2pacEOwhJ10Y1osx6n2UyPX4balIZxZXAOp3z1VI2Eyy+fJ4IvoBzZx0RQ6hR48uEyddOmmvdpmpsaX0rTRtptsjzbWq7kXu928zpLpK2IyM87GOuoX3wBBKqtDnWM0pe2QxETnCIOPIoLQs2yqChmICvFxmZYUjXMYyKuinwpr7/GmkRTq7udOdO4/gpvsP5B43XWZ1oiZdY7RaAU7akIa7qqIB2knXoDAM3Wjbc3S51O3vol+pORfNd1iXX1B9TNUvlXpEzQcyFS5b9ecFTYFwYD51l1HnZ1pUgbdZnauuW+akM8ZQNdYfJrl4c8XFKvqmvv+Nkx1sTtKi7DmaVvSeaIeZsWS9Oeno9zZOIl0uCsRiDaLOV+WUnV8ZYHYpFWEVleMrzS3XxElXlJMuahI2m8xZJNxV8IF5b/UV7gq458ZR0BxDHMHvmBaOGCeLhkdMRwuHTOEIj046Tlu0T5M6ZMPtc9IdbyV++KruCvCOvzpcaiJk01aRrZyiRKm+62SuZGIe97fchRIkHg1VPOLwYq8y30uh+42EzqZOOpWsOBEL9O5tdWXKgfH8OmwWWeZ5o74LXwKKomspLNahjqcuWuAoEOn2HEK91Q7rZGXhiPGZkKvvbiOzcIS5KEoLRzS/79KKrOo85bpjgKxDo7ySYfYaVnmmAOCUonDXmtBGM9x1giQmB+JFnOobUL2IV6E5b/uZJ+v7xJ4jy1oInbAsDBMZY1gVdCzjuKbSquX8cFflJKpaFCnXnW1OOlrVuwjzvKiiTghWHEpyHW2d7mSEDpe2ijCFxZAh7uTycrGcdND98jFWqy6otkZRtejx6x/5Jl7zwVvxj7ftNPqVdZnVhQdnQumJk643HGHP0TjXoNpctHUxjkYR9h5NE9Xf++hsabiliyNSiVG0EFfVRiJAKhsn76+iGlRxjEwO3kBtmtpt/h2YS0UwWriDjl9OuTANQb+uX2oMnawS6VRUg0XRFDpv3ZK0tetwLNJtmGjH7j4y7XFxRY4zdLwaJ5HOpWq8OjeU43N+ZZARYRWV95CooUgXVjnpRg3akequgkdygoBHBxB3wUZvRD6rZUpOunrod8kuHEFuHktM4ZYef45Il3HSqd1g5g4izffiMyedDyedLmhh46RTk50ST3pHJxjmiQtqB7guf4npQtk6k3fSUfdGVZLnbOEIlZMuEcLUfdgydLavBT+7VWldsmggL7AowcFlolMF3dXn5A5V56oSRHw66QA7AavSScdYXB0rcuGuTJFOfZWc6q5FzmLnwjA03DWk1V2Ln69zOyYfJAgCfPDXno63/NST8NSztuSeX1vd1chNBWRz2+lwV52kvt5Jd9GZW/DDj98KANh7dKnQSVflMjMXsFVw3R5apGNW3gSKwhGrPmP8s2l117LjbxYYqmyrJnxQcViLdN3S59QVJqnC3DRSBi0Xwc8U6WxzjxX2SwuoZI7i4bygG+ll51kURVoc/V+f+W7ub0DR+VX8vhknXVJUwSxwtVFXd43/X3e8Hp1dzsyLHjqwmAtb5jgiqxLeFxaZiaJcrr6pKiedRT5Gek+glTOpw5Lm1nURgnPnfk2/lo0xVM3HDi2kApMWu+sKBACYW1EiThruqkQ6tSGWyfc5TtWkPEDv13PLPDOET0yTjM24ozZeVfXmOZKTbhMR6So3VKgjzircVeWkq3DS2Yh0DjnpRKQTSvEZ7mo6RLhOOtozzkTT3El2SQhc1g9OKMk4QycP7MIRtC2m4EcHfE6lWDrZU4t7bg4mX04683xlVXdNjn3qpKs/ZvXhrvFnjGp2z+v6pG6wKn8JUDZpReb5m6fiBVZZ4Qidi6bgsKWFIwJtm1dOuiJnXNWCjRahsEGJklU5MfNOOuXyM0U63rhDw11551f8WrVQWmGO+XknnYVIV1E4YjyddHFfNmgnHbe6a3YR75ZYPv19ginu0Cp/tLprmRjTL7juXvSkU/G65z6h8Pl11WLVfWGGinQbiEiXTPJtFvFqLO60Apy+OS4Es/focmFF4bBChNdOOpvQzTDQfXPJn6vzhXmt7hr/38YtaLlnQfKPFf9di1Q2hSNsnXSJS2frTLlI19LiYe3b5jDDJDnijt6AMp10TlVnU0Hfj5MuOcfImFs2xtKHe8NRRiTKhZXWbKqYRWkA4I9/4SmZ5+ScdDVf5MMHFzP/P7zQy7v9Ge5KHX4/kRf0q+YVQPoZVPGItHAEcs+pTqOR3mMemy0Od6XXGet8NSvilrRljqHaSUcqe5rVXasOv3bSTXS0CP/wwYX4MZXioGZDeC1Dj/M4RXiZuoDN+GWGux5d6uvzO1s4Iv5ZOF5QkcymKqtNTjqrcFfJSSd4JJdTyGu4qz9xh9MvU0jjOen8Ha9xxqeTjt4MuYIffT3HlUd3StUOIjcXRysMMNHi71L7uibpjauJk262wFZOoflbXL7PojCmqvwldNEPxKFKAMoLR1S4KrT7rRXqndujSZ4iMxE/UOekG+WeX0XLwglhilI63NXjOA1kq7suMvJEqmtGiXTenXQW17hagEwWOOk4wtWxIIoifYz4hSPin2bYuJMLglwraS4z13En/mmG/JUtippU8aTtla2xdOEI4lyhIbTqurepGKjc1e0wxEkzanOgl3OBANUOXnMMq8OmyEwZuZx0nHQJxjlW5XRq+hmDmkV8k5x0tjnDlACwrcpJ56FIQNsQF+ra+sJ39uLid1yLF151Ax6bjUWsgeHU5pwTRdVdXa9v6vSixXrKNjlNofmevXP6dzWdTseKbH+r2lKv+a9PPSPzHHVN2gprSshRFKXRUP1yOfaqium0Zbir6UQG0vmbmg/Qa6KqYI2C3mOyTrqkP0GQrWzscG7ottS536o+/ktG8R21eXJoMVvsgbZpG+6qig+pHJS0mEilsLOGoedNz3Hj71iQy0lncW6tGOGuilYYZJyzlWN103BXdU0V5aRTj9mIfZKTTvCJ38IRhkjHHCho33xWy+TkaDlRwl2zhSOYC28ibHKdh1Rg9REG2goCPcnhhm+2wvDYhLs6JnimN64mOelUSMWGsnDXFjMswsj3AlS7BMwwKrVLemSxl5vk098rq7uGAU5LKkfuTZILm9X06O9VRSg6luKCelrljnffTqTjXpP043DEbnXMpro8wUm351B8SIe7FjjplBNyXJx0tB/+wl2TRbzFYq2uLYA4i5nhrqY7pqxfadi43VS1TkRR1ampk45WYVULNptFPHXSqdfNLQ/0BqRtCJspdtVhIyCWkYp0avOJ75hKv8vk8ZIwPcD+M9K9jSKX5cgQvKoILBfeKpSuyknnxf3WMJfZ3936MI4s9vHQgQV86ptx3jbzPumruqsaJ10dvPSrardCfezLIlTM43jP3rRasvrebcNKh0QIphtzVJBX84Q6EVjx8CHDSVew+ZdWlK5ua2UwxFv++Tt49hX/jg/f/BAAYLEqNL7C7Q+kx0XlWNs/t5LpT/wclVPZbvNvH3HSUTGSW7DGrIibzsOKn1+Wk+7QfIGTTrmnK44/3Vw+b/uGzN9osYG6ghZrFZ95xH3iUlxMbYKdNNPN5E/eONnOuNHTlBUFjdCLq4kDrkrwk5x0wvEmfwHxXRUK7oLNl1DkM0Q1Xyl2fAZDn/i0Tmd3eHht0b6wqpORyYkSnfgiHTyFu/q5juh32Cgn3UpN4Qi64+qU/yr+WeRYK64aqBY+8f9V5a4jS8XhrlbVXVsBztgSh6/tObKMKIoKxYLKIhSj/POrsHLSGeegmZNOL4iY1yQdq5d69pOJv7zh+3rxQdtRiyROTlMgv2ixC3eNx4GJgoq12kk3JhNy+t3rEGF2uGv8f9YinjrpVI5OpoM3l3S9zB1jVHeto07AWljJi3Q0vFuN902qu7ZboXYWzy0PtLBNheHq9rLfVR2s/GPJa6Y8hLuaIaxVAql6xPIjZgsGFXRRJ89vUDiibuGtktJvmyl2icdtxT+dkuebDiyLPKS9wQjfeviw/v8/37E7dtwm1586d9Pz3sXllPaLO0eh13EroPOnkuvb+HJv23FI/27e1+py0pXlKSyqAl25gCc8koS7PvXMzQCAwwv5qvF1RU4Ul3/+HnziPx7BnqPL+JN/+x72zS5jMRmPpgsE/UInXYFId+bW2Bn28KGFpF/ESWcxjtHUQ5lwY3IPoddZ3Zix3B/iZ//iJlzy4W/oTc5c4Yiafpnn98kbY+F872zaP31v06Jmeb90zrKpNh5/0nTmHKEbznU5TSmX/eOd+KW//vqaMGNkRDrm2tsneSdd/XFXBp+pbgunb5nUj5trkkohPuOks5ijV+WkU066wKIdlZMOUbErrwAR6YRS/Ia7+stJRy31ALdwRPYz8px0/o7XOEMnD9xdGZ/57eh358OtFot05S4uG4ZErFG7PrwCLKaozJ9MN8lJV1fdtUVyJrnkdxwWLL6qqwYmzzGcdIcX+/rYUDebbXXX0zbHN/+l/hBHFvsk4bzdZFqdizY5k+L3rBdRzPBOnZMueX8toHAdqeR7W+rZfYff3zeHd//bvXj75+7W51Gaky4pHDEYMQtRGE46i3vIcmXhCNXuOIp0PCedTuqfC4dzWMSTfk12fG1aqFCx6kWRdqRai93Vop/OAUXCy4oE3CbVXdth6qSbXe7rELaMk64iVE99JbZFFTiCq3qNcqhw8sCaeQ+rBFJanMAG+ryiY9YkDNpWkDlkUTiC47RJ89MmbVm4Nb+z+wiW+yM9d3hg/wIOLfQwb+RW9F7dlZmDF4jXrKqQVNm82kzQf/09+3DXnqOZtkz3VdnxMvPZKjYXfJ827isA2JGEu6oiNcXhrvXCzmgU4e+/8Yj+/3J/hE/fvluPR9MTeTdX0RwlI9Il73vWtnhDceehWBCjTjpdRbVqXkGru84XVHcNAgQk5LVOwLr30Tncuesobrh3P674wvcy6zXtuq39LtOxFQDO3hYLkTsOLCR9sqsqrUjDilvotEKcc/KM/lthRdCa0z+KIlzzrV249aFD+PL39lU/eQzIpCgaI/NILie8Rd/UdznRbuHMrVP68Y0TWTG+KrWNdrLZhKgCNTnpmoS7kudYuulEpBNKGddwV5/hXbnqrowFm3l8xmkw9InXcFevOemiwt8b90lP9lLXgmt1Vyr4dXVSZn/nvg8nXerasXfSbZgodhsEAcnjx0hinQ3ZKJ/QleWkO7LYK3TNVO3Ga9dOGGCy09JVH3cfWdKfu6itwtBZVZXSNiddq3xirjDHE9UndY5N+cr9Rr63RUsn3V170jClo0uxeKiuQZoU22c+Rpuxuig/mEK7F8ekwE8mBF0X2+Atln2Ew9GXKHeY6/c4NBwVdVWNdZi5dU66+GfZddQvcOY96fSNuefZhCLSyrNqoTe7PNBzm0ki/lUtJI9nTro0qb+HKp5Gv6sKNJibKXXQYbOovYG+R9e3F1iIYQB10tXnpHOJEk5TJiRuzQrhVnF3Mq4+9/yTtRB8ZKlPciuqypT152sZNGy5yxTp6EdpBQE6NYVm6Hj0E//lNADAl777aKYtdS3WFXMpd9LlF8824a5RFGkn3cWJSFdUNd4m/HxueaDvh699zrkA4tBSFe463bFz3RY56c5KnHQKGgJoszlDN2fp/d6sYmub+uXIUppv677H5jLnhO0xM4+xEukeScKPbSMtFGlu2vg4n7edinREINWiZvVnpNfH9x6drXjmeEC/f1d3/rEg56SzGHfSUOgQj9uSinSbjOvcqrqrTagrkLrkitxvLuGugHVeOhHphFLMsZgzofNZOMLc/fIpHnKEIpf4+uPFA/vn8eZPfwc7jRwbLvgq2uG7rb4nJ12m9LyaZDLDPzKhJCwnXXYi6urKy4S7NshJV+ekA0ilUheRTk3MC/PI5Z+vhgI16d6iRTrqfstXfCrOSZd1Z6Qhr0tpW0X5Syraalk6gOycdNkDMJt8F2phNsk8VxW0D4uWgvKdO4/q31WxDXVcaFJsH2P1VIPiBUowmSgS6RhJ4I8FdIHNDndNDo1Z3ZWbk66rF91ux8x0odQtsNRiyVbsrgttVB+FLuRf+cNn4X++6Hz83998ZtpOjSMviqLMeJHmpOtjudBJV94v9Yi1gFWRo7MOs3AEZ1NSu2MsHC0jPU7btU2PRdF6Oc1JVz++Vo35FO2ksxHpXMJdDeHcxgGkqm2esWVK39sOLfR0SLXaAGkxClxp120AkpOO79APLcJdqbB2URJSuvfocuZvgSHslB36og0+AHjLTz0ZYQC8LhHHgPQ7qPoa51cGmEvu+xc9Lu7bIZKTziwcUXVOqIIHGybaOuH90aW+TicxXeC6Lfou6QayOi5nbpvKPIeKFS2di7T8c9J5BS0UZQpltveQo0Sk23NkKVvsQp/72fcwMdOemEIkHR/CivmhQofPJufjE09J89JlnHQ1BS0Uaj4IAPc/Nl/53HGAHptxivByykk3SDdeH7clPS/MYnaVGypNhDX6PG511xbp48hOpLP0+gknIuYAyirQYFwpnHDXXG4ihuhhDlic6q50EbnUH47VYPjLf3MrHp1dxm07DuG633k+qy2vTjqPNmzaF865SidhOlzDMcE2LTjgMyfddLeF2eWBc1uuOelUiGVZ4QhA5XUaOn2flXnkKlwo6ulbktCW2eW+FhSpSFTlyksLR8Tf0+O2TOLOnVkn3YaCtqr61bLcBrPJKaTO6c1THRxd6usiHjqEravCXf2JdLaC3527jujf1U66Wd0ViD9D3rdkh3K8TXXj8dVmrNahh0UinRKTxzLc1c9i2SzQ4HJ/y2xacHN0NkwGnwphDcNdy5x5yR9Mp+5vv+SCzPPqhB16znTCMFM4whTCaL8KN/WVI624yzk4Tjoz3HU4ijAcRdZVqBWRIcYAdZsp2XG6jmxOuqpNkPoGbcNdbaq7+ijaoQQKm00CVQzglI0T2DzVwU4saRELSJ3drMIwRIyZYM5R6PsHQSqulzvp0vQWqljTo7NZkU6HB9eEGpc56S583GZ8+20vyxSQsPkeVfXPiXaI05MNu95ghIUk1NgMd60U6bQA3NE58o4u9XVbheGuRWHeUV6cPtMQsDZPpedv22L+Su8xi70hoihCEATkHpK01apvCwCOkgqss8sDzBLRLjDP/ZLjPzLuE1umO9g40daiKXUL1gl+9DOqtBe0eMSGAidd3e2Nipnf3XO04pnjQdZJNz7rUpecdCukqMgZJCedWRBE38N9OumqctI1ddJZrinFSSeUYlrnOSGEeScdI+TPuOg4zhF1w+Hm2gHSG8uUp8WyT9TE5/59/F2fY+Wk8yku+AirC4NALw65OelaQaAnFj7cRGnOKl511yCwD2HrDUb6Bl/lpOtYTuaKKFp8VblttEMjWeKqSmdRBOxJkhbTcMuqEFVdHEI56TanTrqicNeqyXTTaoY2Tjp13py0IZ6EK8E0ddJ5yklHzgPbth4+mDp0j2gnXRpa6PPcn6wJoaKYVeIoNgmnjyf0mpxs4G6takutZTjCTmYMa9uFPNW1lYY9xY/XFo7w5aRLul3XXq3Dj1wX7VaATbpwRL9QGK5OYp3tex2cvGh6rCA5Gl2+S/ox0tBl9beC8TD5aZ+Tjr5XuaPIJiedbbjrIYtwV10p1uHYq/urGgttQqpVIv9TNk1gSyK+7D4c39faYSqq+ajumknJ4VywJv09E4lQco7RkMrTN6uK6stJW+m4A1iEuxrCDmXDRLbyo26r4ntUjrDNUx3MdFv6ezswn1RRzYVuljaVEYCVSDe71NeOSLqRZZNGgxpIN0y0tctS9demLQX9roejCL1hnDtWhxtrJ53dOUaddACwKzlfaVu1lXqN+0QQBDhrWypGbpkpyiNX8RmNKu/USUeru9pWb14gYcEHSR6/cWWtOOns5nRp6PLZ5Jx4LXHKAjXnRRNhDSAiXdEOVIO2giAVBiXcVeCSLxzhMZeWB6eTwocgo6udMRZs6gaqw7GYg+Hde2bxln/+jt5NHRd8inR0ssttiy6cOOdq1jkSD/TcHEwtMqHmna/xa6cneOeYnhwHgd5drMt/NU8s/lVOujYjJ505MQfqdr2zDo12K8TGpG97jsST/SInXVXlNNV/WuG1KHS2ate1aXiX7lfFMVOT6ZNn4nCZY5aTjhxnG6F1NIp0PicgzgcIENEz5Ds0aL900vsGE7rinHTj5aTLXJPtNLTIpZhRWRVVziI+CNLqp+xxxzLpuimc11FbLVY56WouzLrFGi2KQ8Ndl/sjvfDOOulQ2p57Trrm34Ea92jlWTeRjjqm6h1Fo1Gzz5gJdy34CprkpLMJd13qDbWgXxXuWnd+VWEWCbCp7ro/EYS2b5zQlcv3HIlFj+luSx97H3kKWx7GabogDkmxgfLqrsRJl4h0jxoinQ53Jd91UQEiGrVQR+quLD9es0SkC4JAC2FqPq5D9i3OCXV/3DLdTVNyLPV0DripAtdtVQ5eM8x7exJCq/prtlUlRpqphxZXhpnzyAx3rZvXqU06xc7D6QZeLs1BjUhHDdSPI0UCqNvVSog0BHLquirKSdck3HWxN0AURVjuD/GKv7wZV3zxnsrXrgZj66RzKByRinQhnnHuNvx/L/sBfPQ3nqFzSCvSzZmCRpqGu+qcdEWT/YauPOWmk8IRAhdzoOI4NMxKj5zk+ebA7qO6q7pJcqq7qoGwSfhgFS//s6/hE//xCN50zZ2sdnxDb/g9pmsn66TjtdVzcABV9YmGd7k76dJJqM9w1xlm9Ucd4hKmLqe63XMVXjnVaVWGn9kmGC7sV0FemapwBjMvEpDusqokw0UVWYsn+VnXjhLpMuGuBbuuRUKWmSuvDhsRJe+kS3LSRVl3DLsAS8Nrcna5n7mO1U56eh2F2lHBEqj157QfX5fIhM6EuqnGwU1Hr0kqorhc4yPj/EvD4Zq3RRO46/HQ8Xg1TbpuCud16PxQpe3FP+tEv3ShXPx3ej/ohGHhpgU959IcWOVjWOOxgpWTLu0bZzMFKCoCUu6ksy8cUS3IpDnpLASZqsVagnLRdVthJizSpa0iBsORHq9UkQAbQWDfrAp3ndTiixLpNhS4ul3c6+qaCAN+4QjzvKgLj6chqkqkm18ZYG65n8tLRs+JyhQTFudYXbglkN7HNiXHXc0HVMVXnYvRQgSmRUnU93h4sa8FsmnLUNxUnM4+fjIR6airzsplZsz7FvvDrFPWTJlQc/IfqXDSBeZYURO6THP6UhGGCuk2QqRab6oN6ZmJti46QKs524azqzBlIB4LVgYjfOV7+3D7I0fw1199sPK1q0EmymicRDpj88Zmvrk8SKMjgiDAb73wiXj+Bdtzz6tMJ9BYWLOp7mrZlspLZ5mTTkQ6oZRh7gLy535b5jgqcuKhB3dGlx8qpvo11cDpYcO3dx310o4vhp4ca4DfnHRUYPVVOMI2D0cZdKLpRaQzXVPMHe8WmZjXLdbmVuKbSlWoK5DuVrpcS0U7qFUJi/WigExazz05m5uCOunSsLP8e5uuncdtoeGuKlF32lZaUS/flpkrrw71GasrlGVFOp2Tbuh33Gkagq7y7SjUTro6VzshdVS49S2KopzAULdYULvbQLGTjgrB4+CmK7omAbcFs5ncnOWkI4tfvehm5qxqWjjCOty1VvQbZd63tJ2aRby614RB/J7tVphZaANZJ11QsWBIBazKLml8FAHptkL9Hbhck1UVGyurcFu2T49FdWEeGyddvWvqMMkZViWW1oVclkEL8CgXvBaUK4SKg0m/Ttk4oVM57D6i0jjk70WscHayOeA8r9CCc1LpvWaTkxZYmu62tYD16NHlXF4yOl5XuSttKkHbVHel4a4A8IST44qgDyQpY9QcJU1QX97WoYW4ra0k3JVGyNhWjdfitLFJevLGYiedTVEF8/6y1Btkzkl1/HUak5rxQh039XXtPZIPd7Wt7krHaeoWpE66qg0QhTqf6ebX5a+4EG940fl46plb9GNKE6y7T5pV7xd7Qy0AAmku3HGBfp/jVN01F8lWc271h6N0HtiuFsUq3bLKxdY43LWquqtliYcqwa/o6XatCiciaWgEz00E5BfsvMIR2bb85DlS1c48hM4yk36b+KgS27EMF7LBV+43wHDlsau7+mlLh02QSaZ7IuV0kdklLhRX5446x2aY1R/pxFwLKDXnvnJubagR6dqWk7kiinbDq3aq1elDd9l/+OytmefQnHStirbUY+o7V0lp982t6BDODUX57TzkpLMRUdR3fZIKd+0NMBpF6TitJjoD93GaimGA3XeYE+mW4v9rQaQVsBaR5utsc372hiO9mCuq7kqFH9d++YRekzTU3uUaN68jH8JO7Lrlia1lC+/6cFfLwhE1TidTJCxtpzbcNd8vunnR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+PVf/3W8/OUvx5ve9Cb81V/9Fd73vvfhf//v/41Pf/rTW/wqNgm5YiLwpS99KQeQ33HHHfax5eXl/IlPfGJ+9dVXD/3dj3/84zmA/Hd+53c2epqKTcbKykr+wAMP5Hme51/+8pdzAPm//bf/tvK8N7zhDfns7Gz+93//9/axz3zmMzmA/EMf+tBmTVexSRh1XYTwute9Ls+yLP/GN76xgTNUbDbuueeefHV11Xns/vvvz6enp/Mf+ZEfqTz/oYceyhcXF/N3vOMdlXuPQqGYXIwSb3Y6nXx2djZ/+ctf7vzu//2//zcHkP/sz/7sps5ZsfEYNa549atfnc/Pz2/y7BRbgVHiitXV1fyee+6p/O6v/uqv5gDyz3zmM5syV8XmYJQ18e1vfztvtVr5q171Kud573vf+3IA+e///u9v2ny3ElruOiH4+Mc/jmazide//vX2sZmZGbzuda/DF7/4RXzjG9+o/d1zzz0XAHDs2LENnqViszE9PY0zzzxz3ed94hOfwA033IBzzjnHPnbttdfioosuwkc/+tGNnKJiCzDquvCxurqKT3ziE3je856Hs846awNmptgqPOc5z6koZi+88EJceumluO+++yrP/+Vf/mU86UlPwitf+crNmqJCoRgDjBJvdjodLC8v49ChQ87vnnHGGWg0Gpidnd3saSs2GLFxRa/Xw4kTJzZwRoqtxihxxdTUFJ7znOdUfvelL30pAATjD8X2xShr4otf/CK63S5uvfVW53nm/7/7u7+7OZPdYihJNyH46le/iosuugi7d+92HjflBH/2Z39mH8vzHI8++igefPBBfOELX8DP/uzPotls4nu+53s2ccaKccG3vvUtPPzww3jGM55R+dlVV12Fr371q1swK8U44o/+6I9w7Ngx/MiP/MhWT0WxCcjzHA899BAOHDjgPH7vvffiwx/+MP75P//nWoaiUOwwjBJvGp+6O++8E3fddRe+/vWv43/9r/+F17zmNdi7d69D8Cl2HpaWlrB7924sLi5i3759eOMb34hTp05t9bQUm4C6uMLHgw8+CADrPk+x/eGvidXVVQCoJHPm5uYAFNZdOwHqSTcheOCBB3D48OHK4+axb3/72/axhx56yHnuWWedhd/+7d9W09YdigceeAAAatfPY489htXVVUxPT2/21BRjhrvuugvT09N4+ctfvtVTUWwC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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "energy[(energy.index < test_start_dt) & (energy.index >= train_start_dt)][['load']].rename(columns={'load':'train'}) \\\n", + " .join(energy[test_start_dt:][['load']].rename(columns={'load':'test'}), how='outer') \\\n", + " .plot(y=['train', 'test'], figsize=(15, 8), fontsize=12)\n", + "plt.xlabel('timestamp', fontsize=12)\n", + "plt.ylabel('load', fontsize=12)\n", + "plt.show()" ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Training data shape: (1416, 1)\n", + "Test data shape: (48, 1)\n" + ] + } + ], + "source": [ + "train = energy.copy()[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']]\n", + "test = energy.copy()[energy.index >= test_start_dt][['load']]\n", + "\n", + "print('Training data shape: ', train.shape)\n", + "print('Test data shape: ', test.shape)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
load
2014-11-01 00:00:000.10
2014-11-01 01:00:000.07
2014-11-01 02:00:000.05
2014-11-01 03:00:000.04
2014-11-01 04:00:000.06
2014-11-01 05:00:000.10
2014-11-01 06:00:000.19
2014-11-01 07:00:000.31
2014-11-01 08:00:000.40
2014-11-01 09:00:000.48
\n", + "
" + ], + "text/plain": [ + " load\n", + "2014-11-01 00:00:00 0.10\n", + "2014-11-01 01:00:00 0.07\n", + "2014-11-01 02:00:00 0.05\n", + "2014-11-01 03:00:00 0.04\n", + "2014-11-01 04:00:00 0.06\n", + "2014-11-01 05:00:00 0.10\n", + "2014-11-01 06:00:00 0.19\n", + "2014-11-01 07:00:00 0.31\n", + "2014-11-01 08:00:00 0.40\n", + "2014-11-01 09:00:00 0.48" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "scaler = MinMaxScaler()\n", + "train['load'] = scaler.fit_transform(train)\n", + "train.head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjYAAAGhCAYAAAByPf5TAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAA3SUlEQVR4nO3deXhTVf7H8U/a0o0uUCi2YBEEKlJALIgDIg6CWtlUpIKKgOIwOggIFASRUcBpQRbF6Qi4/CgK6rA5AsMiMOAPcWEZQEbBMmpZiyyFLpSG0t7fHz7NzzQttOmS5Pb9ep48Pjn33JtvchL68dybE4thGIYAAABMwMvVBQAAAFQWgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANH1cXUJ0KCwt18uRJBQcHy2KxuLocAABQBoZhKDs7Ww0bNpSX19XnZGpUsDl58qSioqJcXQYAAHDCsWPHdP3111+1T40KNsHBwZJ+fWFCQkJcXA0AACiLrKwsRUVF2f6OX02NCjZFp59CQkIINgAAeJiyXEbCxcMAAMA0CDYAAMA0CDYAAMA0atQ1NgAA1zMMQ1euXFFBQYGrS4EbqVWrlry9vSt8HIINAKDaXL58Wenp6crNzXV1KXAzFotF119/vYKCgip0HIINAKBaFBYW6ueff5a3t7caNmwoX19fFkuFpF9n8c6cOaPjx4+rRYsWFZq5IdgAAKrF5cuXVVhYqKioKAUGBrq6HLiZ8PBwpaWlKT8/v0LBhouHAQDV6lpL4qNmqqzZO95dAADANAg2AABUkVdeeUXt2rUr1z6///3v9fzzz1drHdu2bZPFYtGFCxcq9XFd8ThcYwMAcLkmE/9ZbY+VNqNXtT1WQkKCRo4cWa59Vq1apVq1alVRReZHsAEAoJIZhqGCggIFBQWV++vLYWFhVVRVzcCpKAAArsFqtWrUqFFq0KCB/P391aVLF+3atcu2vegUy/r169W+fXv5+fnpiy++cDgFdOXKFY0aNUp16tRRvXr19MILL2jIkCF68MEHbX2Kn4pq0qSJEhMT9dRTTyk4OFiNGzfW22+/bVffCy+8oOjoaAUGBurGG2/UlClTlJ+fX6HnvHLlSsXExMjPz09NmjTRnDlz7LZ/8MEH6tChg4KDgxUREaHHHntMp0+ftuuzbt06RUdHKyAgQN26dVNaWlqFaioLgg0AANcwYcIErVy5UosXL9a///1vNW/eXPfdd58yMjLs+k2cOFEzZszQwYMH1bZtW4fjzJw5U0uXLtWiRYu0Y8cOZWVl6R//+Mc1H3/OnDnq0KGD9u7dqz/96U969tln9cMPP9i2BwcHKyUlRd9//73mzZund955R6+//rrTz3fPnj165JFHNHDgQB04cECvvPKKpkyZopSUFFuf/Px8TZ8+Xfv379c//vEPpaWlaejQobbtx44dU79+/dSnTx/t27dPTz/9tCZOnOh0TWXFqSgA8EAlXZNSndeO1CQXL17U/PnzlZKSovvvv1+S9M4772jTpk167733NH78eFvfadOm6Z577in1WH/96181adIkPfTQQ5Kk5ORkrVu37po19OzZU3/6058k/To78/rrr2vr1q266aabJEkvvfSSrW+TJk2UkJCgjz/+WBMmTCj/E5Y0d+5cde/eXVOmTJEkRUdH6/vvv9esWbNs4eWpp56y9b/xxhv15ptv6rbbblNOTo6CgoI0f/58NWvWzDbTc9NNN+nAgQOaOXOmUzWVFTM2AABcxY8//qj8/HzdcccdtrZatWqpY8eOOnjwoF3fDh06lHqczMxM/fLLL+rYsaOtzdvbW+3bt79mDb+d/bFYLIqIiLA77fP3v/9dd9xxhyIiIhQUFKSXXnpJR48eLdPzK8nBgwftnq8k3XHHHTp8+LDtN7727NmjPn36qHHjxgoODtZdd90lSbbHPXjwoG6//Xa7Y3Tq1MnpmsqKYAMAQCWpXbt2lRy3+LekLBaLCgsLJUlfffWVHn/8cfXs2VNr167V3r17NXnyZF2+fLlKapF+ncW67777FBISoqVLl2rXrl365JNPJKlKH7cs3CrY/OUvf5HFYlHr1q0dtn355Zfq0qWLAgMDFRERoVGjRiknJ8cFVQIAapJmzZrJ19dXO3bssLXl5+dr165datWqVZmPExoaquuuu87uouOCggL9+9//rlB9X375pW644QZNnjxZHTp0UIsWLXTkyJEKHfPmm2+2e76StGPHDkVHR8vb21uHDh3SuXPnNGPGDN15551q2bKlw4XDN998s3bu3GnX9vXXX1eorrJwm2Bz/PhxJSYmlph29+3bp+7duys3N1dz587V008/rbffflvx8fEuqBQAUJPUrl1bzz77rMaPH68NGzbo+++/1x/+8Afl5uZq2LBh5TrWyJEjlZSUpE8//VQ//PCDRo8erfPnz1fo5wRatGiho0eP6uOPP9aPP/6oN9980zZ74qxx48Zpy5Ytmj59ulJTU7V48WIlJycrISFBktS4cWP5+vrqr3/9q3766SetXr1a06dPtzvGM888o8OHD2v8+PH64Ycf9OGHH9pdfFxV3CbYJCQk6He/+12J5ydffPFF1a1bV9u2bdMzzzyjV199VcnJydqwYYM+++wzF1QLAKhJZsyYoYcfflhPPPGEYmNj9d///lcbN25U3bp1y3WcF154QY8++qgGDx6sTp06KSgoSPfdd5/8/f2drq1v374aM2aMnnvuObVr105ffvml7aJfZ8XGxmrZsmX6+OOP1bp1a/35z3/WtGnTbBcOh4eHKyUlRcuXL1erVq00Y8YMzZ492+4YjRs31sqVK/WPf/xDt9xyixYsWKDExMQK1VUWFsMwjCp/lGv43//9X919993au3evRo4cqbNnz+o///mPJCkrK0v16tXTmDFj9Nprr9n2uXz5surVq6cBAwbo3XffLdPjZGVlKTQ0VJmZmQoJCamS5wIA1cETvxWVl5enn3/+WU2bNq3QH3IzKSws1M0336xHHnnEYcajprna+6M8f79d/nXvgoICjRw5Uk8//bTatGnjsP3AgQO6cuWKw0yOr6+v2rVrp71791ZXqQAAVMiRI0f02Wef6a677pLValVycrJ+/vlnPfbYY64uzTRcHmwWLFigI0eOaPPmzSVuT09PlyRFRkY6bIuMjNT27dtLPbbVapXVarXdz8rKqmC1AAA4z8vLSykpKUpISJBhGGrdurU2b96sm2++2dWlmYZLg825c+f05z//WVOmTFF4eHiJfS5duiRJ8vPzc9jm7+9v216SpKQkTZ06tXKKBQAP44mnq8wuKirK4dtGqFwuvXj4pZdeUlhY2FV/+TQgIECS7GZeiuTl5dm2l2TSpEnKzMy03Y4dO1bxogEAgNty2YzN4cOH9fbbb+uNN97QyZMnbe15eXnKz89XWlqaQkJCbKegik5J/VZ6eroaNmxY6mP4+fmVONMDAADMyWUzNidOnFBhYaFGjRqlpk2b2m7ffPONUlNT1bRpU02bNk2tW7eWj4+Pdu/ebbf/5cuXtW/fPrtfTQUAuD83+DIu3FBlvS9cNmPTunXrEhcQeumll5Sdna158+apWbNmCg0NVY8ePbRkyRJNmTJFwcHBkn79ufScnBwW6QMAD1H0swC5ublXvYwANVPRTzF4e3tX6DguCzb169fXgw8+6ND+xhtvSJLdtr/85S/q3Lmz7rrrLg0fPlzHjx/XnDlzdO+99youLq56CgYAVIi3t7fq1KljW3o/MDCwQivuwjwKCwt15swZBQYGysenYtHE5V/3LovY2Fht3rxZL7zwgsaMGaPg4GANGzZMSUlJri4NAFAOERERkuTwu0KAl5eXGjduXOGw63bBZtu2bSW2d+nSha/IAYCHs1gsioyMVIMGDZSfn+/qcuBGfH195eVV8Ut/3S7YAADMz9vbu8LXUgAlcZsfwQQAAKgogg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANgg0AADANH1cXAACeoMnEf9rdT5vRy0WVALgaZmwAAIBpEGwAAIBpuDTYfPfdd4qPj9eNN96owMBA1a9fX127dtWaNWvs+g0dOlQWi8Xh1rJlSxdVDgAA3JFLr7E5cuSIsrOzNWTIEDVs2FC5ublauXKl+vbtq4ULF2r48OG2vn5+fnr33Xft9g8NDa3ukgEAgBtzabDp2bOnevbsadf23HPPqX379po7d65dsPHx8dGgQYOqu0QAAOBB3O4aG29vb0VFRenChQsO2woKCpSVlVX9RQEAAI/gFsHm4sWLOnv2rH788Ue9/vrrWr9+vbp3727XJzc3VyEhIQoNDVVYWJhGjBihnJwcF1UMAADckVusYzNu3DgtXLhQkuTl5aV+/fopOTnZtj0yMlITJkxQbGysCgsLtWHDBr311lvav3+/tm3bJh+fkp+G1WqV1Wq13We2BwAAc3OLYPP888+rf//+OnnypJYtW6aCggJdvnzZtj0pKcmu/8CBAxUdHa3JkydrxYoVGjhwYInHTUpK0tSpU6u0dgAA4D7c4lRUy5Yt1aNHDw0ePFhr165VTk6O+vTpI8MwSt1nzJgx8vLy0ubNm0vtM2nSJGVmZtpux44dq4ryAQCAm3CLYFNc//79tWvXLqWm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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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Xbt2kqTdu3dr8ODBSkpK0u23364WLVooPT3d1r9ly5aqU6eO3T4uXLhg16emuM2lqOTkZN19990qLi7WuXPn7NY988wzqlevnnbu3KmQkBBJP1+L/N3vfqePPvpIvXv3dkXJAICb3J49e7R9+3b17t1bkZGR2rNnj86ePavbbrtNkvTnP/9Zv//97xUZGam+ffsqLy9Pu3fv1vjx49WqVSsVFRXp9ddf18CBA7V7924tXLjwuu/3pz/9SQMGDFDTpk01dOhQeXl56eDBg/r3v/+t2bNnq1evXoqJidHo0aM1b9485ebm6tlnn63SMbVu3VqDBw/W7373Oy1atEjBwcF6+umn1bhxYw0ePNjWZ82aNfr0009Vr149paWl6aeffrIFn6CgII0dO1ZPPfWU6tevr8jISD377LPy8qqF8ymGG/jkk08Mb29v4+uvvzbuu+8+IzY21rYuJyfH8PHxMZ566im7baxWqxEUFGSMHTu20u+Tk5NjSDJycnKcVjsAuMKt0z4os3i6y5cvG999951x+fJlV5dSad99953Rp08fIyIiwvDz8zNiYmKM119/3a7PwoULjTZt2hh16tQxoqKijPHjx9vWpaWlGVFRUUZAQIDRp08fY/ny5YYk48KFC4ZhGMaSJUuM0NBQu/1t3rzZ6NatmxEQEGCEhIQY8fHxxltvvWVb//333xv33HOP4evra8TExBibN282JBnr16+v8Djuu+8+Y+LEibbX2dnZxiOPPGKEhobaaktPT7etP3/+vDF48GAjKCjIiIyMNP74xz8ao0aNMgYPHmzrk5eXZyQlJRmBgYHGLbfcYrz44otl3ueXrvfzr8rnt8Uw/v930lykuLhYnTp1UteuXbVw4ULdf//9OnfunP79739L+vl01z333KP33ntPw4cPt9v23nvvVUFBgb788stKvVdubq5CQ0OVk5NjO/MDAJ7IjF/3Liws1I8//qjmzZvX6v0icA/X+/lX5fPb5ZeiFi5cqGPHjmnbtm3lri+9ThgVFVVmXVRUlHbt2lXhvq1Wq6xWq+11bm5uNasFAADuzKXB5vz58/rTn/6k5557ThEREeX2uXz5siTJz8+vzDp/f3/b+vKkpqZq5syZzikWADyMGc/qADfi0m9F/fGPf1R4eLjGjx9fYZ/Sr8v98sxLqcLCwut+nW769OnKycmxLSdOnKh+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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "energy[(energy.index >= train_start_dt) & (energy.index < test_start_dt)][['load']].rename(columns={'load':'original load'}).plot.hist(bins=100, fontsize=12)\n", + "train.rename(columns={'load':'scaled load'}).plot.hist(bins=100, fontsize=12)\n", + "plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
load
2014-12-30 00:00:000.33
2014-12-30 01:00:000.29
2014-12-30 02:00:000.27
2014-12-30 03:00:000.27
2014-12-30 04:00:000.30
\n", + "
" + ], + "text/plain": [ + " load\n", + "2014-12-30 00:00:00 0.33\n", + "2014-12-30 01:00:00 0.29\n", + "2014-12-30 02:00:00 0.27\n", + "2014-12-30 03:00:00 0.27\n", + "2014-12-30 04:00:00 0.30" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "test['load'] = scaler.transform(test)\n", + "test.head()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } - ] -} \ No newline at end of file + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "orig_nbformat": 2 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/REGRESSION msLearn.md b/REGRESSION msLearn.md index 05a0b094..2cdab3d9 100644 --- a/REGRESSION msLearn.md +++ b/REGRESSION msLearn.md @@ -390,4 +390,47 @@ This is where Lasso comes in. In our analogy, Lasso is like a smart team captain Just like a good captain won’t pick a friend who can’t run fast or kick well, Lasso also ‘shrinks’ the importance of less useful features down to zero - effectively leaving them out of the model. -So, Lasso helps us make better decisions by focusing on what’s really important and ignoring what’s not. And just like picking the right team can help you win your soccer game, using Lasso can help make better predictions with data! \ No newline at end of file +So, Lasso helps us make better decisions by focusing on what’s really important and ignoring what’s not. And just like picking the right team can help you win your soccer game, using Lasso can help make better predictions with data! + + + +After formulating a hypothesis in a machine learning study, the typical steps are as follows: + +1. **Data Collection**: Gather the data that you’ll use to train and test your machine learning models. This could involve scraping websites, conducting surveys, performing experiments, or a number of other data-gathering activities. + +2. **Data Preprocessing**: Clean and format your data so it can be input into machine learning models. This often involves handling missing values, dealing with outliers, normalizing numerical data, and encoding categorical data. + +3. **Feature Selection/Engineering**: Identify which features (variables) in your dataset you will use to train your model. You might also create new features that can better represent the patterns in your data. + +4. **Model Selection**: Choose the type of model or models you’ll use, such as linear regression, decision trees, neural networks etc. This decision is often based on the nature of your data and the problem you’re trying to solve. + +5. **Training**: Train your model on a subset of your data. + +6. **Validation**: Validate your model’s performance using a different subset of your data (the validation set). This helps ensure that your model not only fits the training data well but can also generalize to new data. + +7. **Evaluation**: Evaluate your model using various metrics like accuracy, precision, recall, F1 score etc., depending on the problem at hand. + +8. **Hyperparameter Tuning**: Adjust the settings (hyperparameters) of your model to see if you can improve performance. + +9. **Testing**: Test your model on a test set that hasn’t been used during training or validation phases. + +10. **Interpretation**: Interpret the results and understand how well the model is performing and why it’s making the predictions it’s making. + +11. **Reporting**: Document all these steps, findings, and any conclusions you can draw in a clear and reproducible way. + + +For example, let’s say we’re working on a binary classification problem where we want to predict whether an email is spam or not (our hypothesis). We would: + +- Collect a dataset of emails that have been labeled as “spam” or “not spam”. +- Preprocess this data by cleaning up the email text (removing punctuation, making everything lowercase) and encoding our labels as 0 (not spam) and 1 (spam). +- Choose features like the frequency of certain words or characters. +- Split our dataset into training, validation, and test sets. +- Choose a model like logistic regression. +- Train our logistic regression model on our training set. +- Validate our model on our validation set. +- Evaluate its performance using metrics like accuracy. +- Tune any hyperparameters of our logistic regression model to try to improve performance. +- Test our model on our test set to get a final measure of its performance. +- Interpret our results and report them in a clear and understandable way. + +Remember that these steps might vary slightly depending on the specific problem or field of study. 😊 \ No newline at end of file