AXONVERTEX-AI-RESEARCH commited on
Commit
f8cab22
·
verified ·
1 Parent(s): dd1ebd3

Publish GraphShieldMistral interactive explorer (part 5)

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +1 -0
  2. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/INSTALLER +1 -0
  3. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/METADATA +110 -0
  4. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/RECORD +885 -0
  5. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/REQUESTED +0 -0
  6. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/WHEEL +4 -0
  7. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/entry_points.txt +4 -0
  8. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/AUTHORS.txt +888 -0
  9. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/LICENSE.txt +20 -0
  10. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt +13 -0
  11. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/certifi/LICENSE +20 -0
  12. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt +284 -0
  13. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/distro/LICENSE +202 -0
  14. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md +31 -0
  15. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/msgpack/COPYING +14 -0
  16. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE +3 -0
  17. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE +177 -0
  18. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD +23 -0
  19. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE +17 -0
  20. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE +21 -0
  21. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pygments/LICENSE +25 -0
  22. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE +21 -0
  23. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/requests/LICENSE +175 -0
  24. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE +13 -0
  25. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/rich/LICENSE +19 -0
  26. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli/LICENSE +21 -0
  27. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE +21 -0
  28. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/truststore/LICENSE +21 -0
  29. .venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt +21 -0
  30. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/connection.py +260 -0
  31. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/emscripten_fetch_worker.js +110 -0
  32. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/fetch.py +726 -0
  33. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/request.py +22 -0
  34. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/response.py +281 -0
  35. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py +563 -0
  36. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/socks.py +228 -0
  37. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/exceptions.py +335 -0
  38. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/fields.py +341 -0
  39. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/filepost.py +89 -0
  40. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/__init__.py +53 -0
  41. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/connection.py +356 -0
  42. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/probe.py +87 -0
  43. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/poolmanager.py +653 -0
  44. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/py.typed +2 -0
  45. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/response.py +1487 -0
  46. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/__init__.py +42 -0
  47. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/connection.py +137 -0
  48. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/proxy.py +43 -0
  49. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/request.py +254 -0
  50. .venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/response.py +101 -0
.gitattributes CHANGED
@@ -4,3 +4,4 @@
4
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/t64.exe filter=lfs diff=lfs merge=lfs -text
5
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
6
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
 
 
4
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/t64.exe filter=lfs diff=lfs merge=lfs -text
5
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/w64-arm.exe filter=lfs diff=lfs merge=lfs -text
6
  .venv/lib/python3.14/site-packages/pip/_vendor/distlib/w64.exe filter=lfs diff=lfs merge=lfs -text
7
+ .venv/lib/python3.14/site-packages/yaml/_yaml.cpython-314-darwin.so filter=lfs diff=lfs merge=lfs -text
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/METADATA ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: pip
3
+ Version: 26.2.1
4
+ Summary: The PyPA recommended tool for installing Python packages.
5
+ Author-email: The pip developers <distutils-sig@python.org>
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/x-rst
8
+ License-Expression: MIT
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Topic :: Software Development :: Build Tools
12
+ Classifier: Programming Language :: Python
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: 3.15
21
+ Classifier: Programming Language :: Python :: Implementation :: CPython
22
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
23
+ License-File: AUTHORS.txt
24
+ License-File: LICENSE.txt
25
+ License-File: src/pip/_vendor/cachecontrol/LICENSE.txt
26
+ License-File: src/pip/_vendor/certifi/LICENSE
27
+ License-File: src/pip/_vendor/distlib/LICENSE.txt
28
+ License-File: src/pip/_vendor/distro/LICENSE
29
+ License-File: src/pip/_vendor/idna/LICENSE.md
30
+ License-File: src/pip/_vendor/msgpack/COPYING
31
+ License-File: src/pip/_vendor/packaging/LICENSE
32
+ License-File: src/pip/_vendor/packaging/LICENSE.APACHE
33
+ License-File: src/pip/_vendor/packaging/LICENSE.BSD
34
+ License-File: src/pip/_vendor/pkg_resources/LICENSE
35
+ License-File: src/pip/_vendor/platformdirs/LICENSE
36
+ License-File: src/pip/_vendor/pygments/LICENSE
37
+ License-File: src/pip/_vendor/pyproject_hooks/LICENSE
38
+ License-File: src/pip/_vendor/requests/LICENSE
39
+ License-File: src/pip/_vendor/resolvelib/LICENSE
40
+ License-File: src/pip/_vendor/rich/LICENSE
41
+ License-File: src/pip/_vendor/tomli/LICENSE
42
+ License-File: src/pip/_vendor/tomli_w/LICENSE
43
+ License-File: src/pip/_vendor/truststore/LICENSE
44
+ License-File: src/pip/_vendor/urllib3/LICENSE.txt
45
+ Project-URL: Changelog, https://pip.pypa.io/en/stable/news/
46
+ Project-URL: Documentation, https://pip.pypa.io
47
+ Project-URL: Homepage, https://pip.pypa.io/
48
+ Project-URL: Source, https://github.com/pypa/pip
49
+
50
+ pip - The Python Package Installer
51
+ ==================================
52
+
53
+ .. |pypi-version| image:: https://img.shields.io/pypi/v/pip.svg
54
+ :target: https://pypi.org/project/pip/
55
+ :alt: PyPI
56
+
57
+ .. |python-versions| image:: https://img.shields.io/pypi/pyversions/pip
58
+ :target: https://pypi.org/project/pip
59
+ :alt: PyPI - Python Version
60
+
61
+ .. |docs-badge| image:: https://readthedocs.org/projects/pip/badge/?version=latest
62
+ :target: https://pip.pypa.io/en/latest
63
+ :alt: Documentation
64
+
65
+ |pypi-version| |python-versions| |docs-badge|
66
+
67
+ Pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
68
+
69
+ Please take a look at our documentation for how to install and use pip:
70
+
71
+ * `Installation`_
72
+ * `Usage`_
73
+
74
+ We release updates regularly, with a new version every 3 months. Find more details in our documentation:
75
+
76
+ * `Release notes`_
77
+ * `Release process`_
78
+
79
+ If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:
80
+
81
+ * `Issue tracking`_
82
+ * `Discourse channel`_
83
+ * `User IRC`_
84
+
85
+ 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:
86
+
87
+ * `GitHub page`_
88
+ * `Development documentation`_
89
+ * `Development IRC`_
90
+
91
+ Code of Conduct
92
+ ---------------
93
+
94
+ Everyone interacting in the pip project's codebases, issue trackers, chat
95
+ rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.
96
+
97
+ .. _package installer: https://packaging.python.org/guides/tool-recommendations/
98
+ .. _Python Package Index: https://pypi.org
99
+ .. _Installation: https://pip.pypa.io/en/stable/installation/
100
+ .. _Usage: https://pip.pypa.io/en/stable/
101
+ .. _Release notes: https://pip.pypa.io/en/stable/news.html
102
+ .. _Release process: https://pip.pypa.io/en/latest/development/release-process/
103
+ .. _GitHub page: https://github.com/pypa/pip
104
+ .. _Development documentation: https://pip.pypa.io/en/latest/development
105
+ .. _Issue tracking: https://github.com/pypa/pip/issues
106
+ .. _Discourse channel: https://discuss.python.org/c/packaging
107
+ .. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
108
+ .. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev
109
+ .. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
110
+
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/RECORD ADDED
@@ -0,0 +1,885 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ../../../bin/pip,sha256=XeGIH1LcpBCVlHyzVMhEwBtPhmEMwfq4otwt7tB9uFo,229
2
+ ../../../bin/pip3,sha256=XeGIH1LcpBCVlHyzVMhEwBtPhmEMwfq4otwt7tB9uFo,229
3
+ ../../../bin/pip3.14,sha256=XeGIH1LcpBCVlHyzVMhEwBtPhmEMwfq4otwt7tB9uFo,229
4
+ pip-26.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
5
+ pip-26.2.1.dist-info/METADATA,sha256=OlYQBYIoQfLEX0QvbHp1BRcsjDdsn-J02HbIrJEpaMs,4617
6
+ pip-26.2.1.dist-info/RECORD,,
7
+ pip-26.2.1.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ pip-26.2.1.dist-info/WHEEL,sha256=G2gURzTEtmeR8nrdXUJfNiB3VYVxigPQ-bEQujpNiNs,82
9
+ pip-26.2.1.dist-info/entry_points.txt,sha256=Vhf8s0IYgX37mtd4vGL73BPcxdKnqeCFPzB5-d30x8o,84
10
+ pip-26.2.1.dist-info/licenses/AUTHORS.txt,sha256=TrH7FwXi3viY6BvLoZw6rIBiDSe6NWnWpt97RinRtcI,12139
11
+ pip-26.2.1.dist-info/licenses/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093
12
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt,sha256=hu7uh74qQ_P_H1ZJb0UfaSQ5JvAl_tuwM2ZsMExMFhs,558
13
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/certifi/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989
14
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt,sha256=gI4QyKarjesUn_mz-xn0R6gICUYG1xKpylf-rTVSWZ0,14531
15
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/distro/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
16
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md,sha256=GppPDj1HmickDd1ZqRN6ZqtKD539yMphiMwL_YUYfwQ,1541
17
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/msgpack/COPYING,sha256=SS3tuoXaWHL3jmCRvNH-pHTWYNNay03ulkuKqz8AdCc,614
18
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197
19
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
20
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344
21
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
22
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE,sha256=KeD9YukphQ6G6yjD_czwzv30-pSHkBHP-z0NS-1tTbY,1089
23
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/pygments/LICENSE,sha256=qdZvHVJt8C4p3Oc0NtNOVuhjL0bCdbvf_HBWnogvnxc,1331
24
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE,sha256=GyKwSbUmfW38I6Z79KhNjsBLn9-xpR02DkK0NCyLQVQ,1081
25
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/requests/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
26
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE,sha256=84j9OMrRMRLB3A9mm76A5_hFQe26-3LzAw0sp2QsPJ0,751
27
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/rich/LICENSE,sha256=3u18F6QxgVgZCj6iOcyHmlpQJxzruYrnAl9I--WNyhU,1056
28
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli/LICENSE,sha256=uAgWsNUwuKzLTCIReDeQmEpuO2GSLCte6S8zcqsnQv4,1072
29
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE,sha256=uAgWsNUwuKzLTCIReDeQmEpuO2GSLCte6S8zcqsnQv4,1072
30
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/truststore/LICENSE,sha256=M757fo-k_Rmxdg4ajtimaL2rhSyRtpLdQUJLy3Jan8o,1086
31
+ pip-26.2.1.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt,sha256=Ew46ZNX91dCWp1JpRjSn2d8oRGnehuVzIQAmgEHj1oY,1093
32
+ pip/__init__.py,sha256=BKp2zqsPQ0HiktquNWN_L4cYsYMxPML7WI0TBMucBEM,355
33
+ pip/__main__.py,sha256=rOZRtrXjDBzY24niaxTnd9ZHHWL7B0EawVdLoJ3nI6c,874
34
+ pip/__pip-runner__.py,sha256=720Mt6h07Uce52v80EOF__JYauoLw9b7Pfs_5B91isg,1451
35
+ pip/__pycache__/__init__.cpython-314.pyc,,
36
+ pip/__pycache__/__main__.cpython-314.pyc,,
37
+ pip/__pycache__/__pip-runner__.cpython-314.pyc,,
38
+ pip/_internal/__init__.py,sha256=S7i9Dn9aSZS0MG-2Wrve3dV9TImPzvQn5jjhp9t_uf0,511
39
+ pip/_internal/__pycache__/__init__.cpython-314.pyc,,
40
+ pip/_internal/__pycache__/cache.cpython-314.pyc,,
41
+ pip/_internal/__pycache__/configuration.cpython-314.pyc,,
42
+ pip/_internal/__pycache__/exceptions.cpython-314.pyc,,
43
+ pip/_internal/__pycache__/main.cpython-314.pyc,,
44
+ pip/_internal/__pycache__/pyproject.cpython-314.pyc,,
45
+ pip/_internal/__pycache__/self_outdated_check.cpython-314.pyc,,
46
+ pip/_internal/__pycache__/wheel_builder.cpython-314.pyc,,
47
+ pip/_internal/build_env/__init__.py,sha256=AI5x2Kfv1exG1IbsNHuIV1agqNgstTj_LWpbwWLq8ok,788
48
+ pip/_internal/build_env/__pycache__/__init__.cpython-314.pyc,,
49
+ pip/_internal/build_env/__pycache__/base.cpython-314.pyc,,
50
+ pip/_internal/build_env/__pycache__/installer.cpython-314.pyc,,
51
+ pip/_internal/build_env/__pycache__/noop.cpython-314.pyc,,
52
+ pip/_internal/build_env/__pycache__/venv.cpython-314.pyc,,
53
+ pip/_internal/build_env/__pycache__/virtual.cpython-314.pyc,,
54
+ pip/_internal/build_env/base.py,sha256=7RHW5X-QSVWHeK7_5Uei9Gbq0q1pAXHF9tq7Mj3wtTs,3440
55
+ pip/_internal/build_env/installer.py,sha256=eMUytQCdBiQ9TgkaGeTAzq_IVBqLHyD9OJ_kNTIjjcM,13046
56
+ pip/_internal/build_env/noop.py,sha256=FXk9ZFTTN0s1cecZE6ycN2ZznBh75Ok2I3QXF8HTo6I,1001
57
+ pip/_internal/build_env/venv.py,sha256=PsDl0PpmB9jRNaIawhy6Xk9R8WcYoAogLS2afmZ9AQc,5692
58
+ pip/_internal/build_env/virtual.py,sha256=HsVRzzhgBGyy06DZBoO0PW_3kIEacy9S4TI5H1q72Hk,4858
59
+ pip/_internal/cache.py,sha256=eqMQVfpD8x7GcCO0V0z73mnjPIuSapMFoQ_WRE7iLY8,10457
60
+ pip/_internal/cli/__init__.py,sha256=Iqg_tKA771XuMO1P4t_sDHnSKPzkUb9D0DqunAmw_ko,131
61
+ pip/_internal/cli/__pycache__/__init__.cpython-314.pyc,,
62
+ pip/_internal/cli/__pycache__/autocompletion.cpython-314.pyc,,
63
+ pip/_internal/cli/__pycache__/base_command.cpython-314.pyc,,
64
+ pip/_internal/cli/__pycache__/cmdoptions.cpython-314.pyc,,
65
+ pip/_internal/cli/__pycache__/command_context.cpython-314.pyc,,
66
+ pip/_internal/cli/__pycache__/index_command.cpython-314.pyc,,
67
+ pip/_internal/cli/__pycache__/main.cpython-314.pyc,,
68
+ pip/_internal/cli/__pycache__/main_parser.cpython-314.pyc,,
69
+ pip/_internal/cli/__pycache__/parser.cpython-314.pyc,,
70
+ pip/_internal/cli/__pycache__/progress_bars.cpython-314.pyc,,
71
+ pip/_internal/cli/__pycache__/req_command.cpython-314.pyc,,
72
+ pip/_internal/cli/__pycache__/spinners.cpython-314.pyc,,
73
+ pip/_internal/cli/__pycache__/status_codes.cpython-314.pyc,,
74
+ pip/_internal/cli/autocompletion.py,sha256=gFtmiFhHccizyx4JPJnEKik-uftU7kwrUvm72cSFPHI,7353
75
+ pip/_internal/cli/base_command.py,sha256=yF5_mQEIrLG2G0nvymZS0nLhiDg4B0T89W5iX78H558,9431
76
+ pip/_internal/cli/cmdoptions.py,sha256=aBNxaIy4YV4AfjAqrG8RoZFcv7kwWzRAzg5mnZmOGDw,41180
77
+ pip/_internal/cli/command_context.py,sha256=kmu3EWZbfBega1oDamnGJTA_UaejhIQNuMj2CVmMXu0,817
78
+ pip/_internal/cli/index_command.py,sha256=_Qzc9oHnButVvD0wxYcHfe0uJZqRWOtIg5HaQpnSNeM,7504
79
+ pip/_internal/cli/main.py,sha256=O10guzBqF2MykAaZYo6sua097dXqC3nozKodtTOpHDc,3209
80
+ pip/_internal/cli/main_parser.py,sha256=7PhEfZ8AXiWUpTfB_KJMngI2sF8XIXl52alI1LZ_e_M,4368
81
+ pip/_internal/cli/parser.py,sha256=WvRHuI2MdFp187BWrY_D17L02asq9jmCnng81af52SQ,14147
82
+ pip/_internal/cli/progress_bars.py,sha256=13U3AY3DYwdEIwPYLtUn5B4QcpJUApLWCkfJ-u_PqzY,4706
83
+ pip/_internal/cli/req_command.py,sha256=wW-mRcPqPczeqxp9SQ_yh3YfrRAYAlEAZextlLcDbUc,18952
84
+ pip/_internal/cli/spinners.py,sha256=EJzZIZNyUtJljp3-WjcsyIrqxW-HUsfWzhuW84n_Tqw,7362
85
+ pip/_internal/cli/status_codes.py,sha256=9QhNe6hHqsiw5y5wufiNKBOgJjV0HF3I3P2K21nj-OM,136
86
+ pip/_internal/commands/__init__.py,sha256=aNeCbQurGWihfhQq7BqaLXHqWDQ0i3I04OS7kxK6plQ,4026
87
+ pip/_internal/commands/__pycache__/__init__.cpython-314.pyc,,
88
+ pip/_internal/commands/__pycache__/cache.cpython-314.pyc,,
89
+ pip/_internal/commands/__pycache__/check.cpython-314.pyc,,
90
+ pip/_internal/commands/__pycache__/completion.cpython-314.pyc,,
91
+ pip/_internal/commands/__pycache__/configuration.cpython-314.pyc,,
92
+ pip/_internal/commands/__pycache__/debug.cpython-314.pyc,,
93
+ pip/_internal/commands/__pycache__/download.cpython-314.pyc,,
94
+ pip/_internal/commands/__pycache__/freeze.cpython-314.pyc,,
95
+ pip/_internal/commands/__pycache__/hash.cpython-314.pyc,,
96
+ pip/_internal/commands/__pycache__/help.cpython-314.pyc,,
97
+ pip/_internal/commands/__pycache__/index.cpython-314.pyc,,
98
+ pip/_internal/commands/__pycache__/inspect.cpython-314.pyc,,
99
+ pip/_internal/commands/__pycache__/install.cpython-314.pyc,,
100
+ pip/_internal/commands/__pycache__/list.cpython-314.pyc,,
101
+ pip/_internal/commands/__pycache__/lock.cpython-314.pyc,,
102
+ pip/_internal/commands/__pycache__/search.cpython-314.pyc,,
103
+ pip/_internal/commands/__pycache__/show.cpython-314.pyc,,
104
+ pip/_internal/commands/__pycache__/uninstall.cpython-314.pyc,,
105
+ pip/_internal/commands/__pycache__/wheel.cpython-314.pyc,,
106
+ pip/_internal/commands/cache.py,sha256=YLZrLWNvChl0pImBkoSZGGD3fb2MfdYGpYF4J0aQs6w,9251
107
+ pip/_internal/commands/check.py,sha256=hVFBQezQ3zj4EydoWbFQj_afPUppMt7r9JPAlY22U6Y,2244
108
+ pip/_internal/commands/completion.py,sha256=LjvRIZ6QUiDXJL3IOMFeD-_J97HfjMGgEk0j2tWGu1U,4565
109
+ pip/_internal/commands/configuration.py,sha256=5M6KM30G3i6oMHAsVUSWP4E93cSSJQoJ6evURC754E8,10132
110
+ pip/_internal/commands/debug.py,sha256=tCWUOEyz2HdlLGTvzNqSZIAJQkQYCy58zBTdfIWyzSo,6556
111
+ pip/_internal/commands/download.py,sha256=cuXEj9PmoZ4kCsxm_BaZ_OkmIsV_gluLiOVSuOO2MS0,5404
112
+ pip/_internal/commands/freeze.py,sha256=Lg8EOokxnRZrwdLWJgLpBWxNUt7-HrkWlEC05e-vBww,3100
113
+ pip/_internal/commands/hash.py,sha256=GO9pRN3wXC2kQaovK57TaLYBMc3IltOH92O6QEw6YE0,1679
114
+ pip/_internal/commands/help.py,sha256=Bz3LcjNQXkz4Cu__pL4CZ86o4-HNLZj1NZWdlJhjuu0,1108
115
+ pip/_internal/commands/index.py,sha256=ny_hGzXuZHzjsq4CIJh_6YfZGVJm7G7LqQQdKTibJ_Q,5608
116
+ pip/_internal/commands/inspect.py,sha256=iiAM-JuL_Z1-QP34cgAloZPSr50Mc7wAvuFDRzHQrQk,3185
117
+ pip/_internal/commands/install.py,sha256=DREULA-TGbCKhqBBLkrbDKztyQ557QbDe6ZJUYuh2yk,33761
118
+ pip/_internal/commands/list.py,sha256=W-FyxXTrHJhqRl4ZoqFp68_5GAwC9GYuY6fhFTJdHzU,13908
119
+ pip/_internal/commands/lock.py,sha256=VhpNRWItLdqywSOIqXg3vuIyf59cozh09-Z6Z9cMiLM,5987
120
+ pip/_internal/commands/search.py,sha256=zbMsX_YASj6kXA6XIBgTDv0bGK51xG-CV3IynZJcE-c,5782
121
+ pip/_internal/commands/show.py,sha256=91_XljhCHWyCNfoFBa4XdacbumQgoNbhkcHHk_gcW9Y,8247
122
+ pip/_internal/commands/uninstall.py,sha256=CsOihqvb6ZA6O67L70oXeoLHeOfNzMM88H9g-9aocgw,3868
123
+ pip/_internal/commands/wheel.py,sha256=5m3NvVKatqLDOVoC_4WOFiDDrvQRjB52jkbvpbZApug,6187
124
+ pip/_internal/configuration.py,sha256=0eEdh1xTlOHhoCrTtwHYM5DEj7BbTmhIaCaNNj3srBM,14562
125
+ pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858
126
+ pip/_internal/distributions/__pycache__/__init__.cpython-314.pyc,,
127
+ pip/_internal/distributions/__pycache__/base.cpython-314.pyc,,
128
+ pip/_internal/distributions/__pycache__/installed.cpython-314.pyc,,
129
+ pip/_internal/distributions/__pycache__/sdist.cpython-314.pyc,,
130
+ pip/_internal/distributions/__pycache__/wheel.cpython-314.pyc,,
131
+ pip/_internal/distributions/base.py,sha256=BjYazg2EhbEgrO1W_JD6jEZIDVlUpA_WZkqU-NvCBkQ,1907
132
+ pip/_internal/distributions/installed.py,sha256=QPDhCqc-GTGiWZAAOFaVKMETg1m_kYuf6RBO9ZZlDqY,994
133
+ pip/_internal/distributions/sdist.py,sha256=hof85VbuXa_NydvFZj6zOtnxuPY15tsuCJVirLuNT-U,7783
134
+ pip/_internal/distributions/wheel.py,sha256=qOMVYzKT3tJsO0QundLjADcFiW_RODui4K51XRqMru8,1429
135
+ pip/_internal/exceptions.py,sha256=Zdu17pVbD1eI_yjg52Zd0ygAWDy8LtXS1Atfvn1pPts,38302
136
+ pip/_internal/index/__init__.py,sha256=tzwMH_fhQeubwMqHdSivasg1cRgTSbNg2CiMVnzMmyU,29
137
+ pip/_internal/index/__pycache__/__init__.cpython-314.pyc,,
138
+ pip/_internal/index/__pycache__/collector.cpython-314.pyc,,
139
+ pip/_internal/index/__pycache__/package_finder.cpython-314.pyc,,
140
+ pip/_internal/index/__pycache__/sources.cpython-314.pyc,,
141
+ pip/_internal/index/collector.py,sha256=bu-NBVToIeyYEbcv0_gtInAxsCK3E0yI6Je6yxAwE5k,16578
142
+ pip/_internal/index/package_finder.py,sha256=RoWK5rPkOcmOdiWEXhnk9aaFDgaj4QEE70FeQokqZf4,43149
143
+ pip/_internal/index/sources.py,sha256=fqqVli93Lr-HNk-wFD67yyfZzS6WeDkSZGv1RFw63QE,8621
144
+ pip/_internal/locations/__init__.py,sha256=iP9yVZn_4iPuNcaUNh2A_vJLcvUZ-8y4zvKLDVEqaM0,14022
145
+ pip/_internal/locations/__pycache__/__init__.cpython-314.pyc,,
146
+ pip/_internal/locations/__pycache__/_distutils.cpython-314.pyc,,
147
+ pip/_internal/locations/__pycache__/_sysconfig.cpython-314.pyc,,
148
+ pip/_internal/locations/__pycache__/base.cpython-314.pyc,,
149
+ pip/_internal/locations/_distutils.py,sha256=jpFj4V00rD9IR3vA9TqrGkwcdNVFc58LsChZavge9JY,5975
150
+ pip/_internal/locations/_sysconfig.py,sha256=HoZYQ1sVQD3IRpQCp4TpdTQLNrDFFzI9zRjXrTYnJWY,7788
151
+ pip/_internal/locations/base.py,sha256=5mVcXh9jnSepEO25aG2U-qZWguzeoOPIbT0mRiBDDME,2548
152
+ pip/_internal/main.py,sha256=1cHqjsfFCrMFf3B5twzocxTJUdHMLoXUpy5lJoFqUi8,338
153
+ pip/_internal/metadata/__init__.py,sha256=vp-JAxiWg_-l5F8AT0Jcey72uUnh8CDwwol9-KktHZ8,5824
154
+ pip/_internal/metadata/__pycache__/__init__.cpython-314.pyc,,
155
+ pip/_internal/metadata/__pycache__/_json.cpython-314.pyc,,
156
+ pip/_internal/metadata/__pycache__/base.cpython-314.pyc,,
157
+ pip/_internal/metadata/__pycache__/pkg_resources.cpython-314.pyc,,
158
+ pip/_internal/metadata/_json.py,sha256=hNvnMHOXLAyNlzirWhPL9Nx2CvCqa1iRma6Osq1YfV8,2711
159
+ pip/_internal/metadata/base.py,sha256=_o9lMyHmia4Ea9fhceyB9rp3jUUU8k7FmlhXB7N9_tM,25642
160
+ pip/_internal/metadata/importlib/__init__.py,sha256=jUUidoxnHcfITHHaAWG1G2i5fdBYklv_uJcjo2x7VYE,135
161
+ pip/_internal/metadata/importlib/__pycache__/__init__.cpython-314.pyc,,
162
+ pip/_internal/metadata/importlib/__pycache__/_compat.cpython-314.pyc,,
163
+ pip/_internal/metadata/importlib/__pycache__/_dists.cpython-314.pyc,,
164
+ pip/_internal/metadata/importlib/__pycache__/_envs.cpython-314.pyc,,
165
+ pip/_internal/metadata/importlib/_compat.py,sha256=sneVh4_6WxQZK4ljdl3ylVuP-q0ttSqbgl9mWt0HnOg,2804
166
+ pip/_internal/metadata/importlib/_dists.py,sha256=akX5xiLB_3dvbeb2gHL8i7wORi01_Cnty0HnKFQAF0Y,8717
167
+ pip/_internal/metadata/importlib/_envs.py,sha256=ulCRDEXYeinwS5AXL-Quj7C4Erk20kHhIwBmE2P3BYA,5590
168
+ pip/_internal/metadata/pkg_resources.py,sha256=NO76ZrfR2-LKJTyaXrmQoGhmJMArALvacrlZHViSDT8,10544
169
+ pip/_internal/models/__init__.py,sha256=AjmCEBxX_MH9f_jVjIGNCFJKYCYeSEe18yyvNx4uRKQ,62
170
+ pip/_internal/models/__pycache__/__init__.cpython-314.pyc,,
171
+ pip/_internal/models/__pycache__/candidate.cpython-314.pyc,,
172
+ pip/_internal/models/__pycache__/direct_url.cpython-314.pyc,,
173
+ pip/_internal/models/__pycache__/format_control.cpython-314.pyc,,
174
+ pip/_internal/models/__pycache__/index.cpython-314.pyc,,
175
+ pip/_internal/models/__pycache__/installation_report.cpython-314.pyc,,
176
+ pip/_internal/models/__pycache__/link.cpython-314.pyc,,
177
+ pip/_internal/models/__pycache__/release_control.cpython-314.pyc,,
178
+ pip/_internal/models/__pycache__/scheme.cpython-314.pyc,,
179
+ pip/_internal/models/__pycache__/search_scope.cpython-314.pyc,,
180
+ pip/_internal/models/__pycache__/selection_prefs.cpython-314.pyc,,
181
+ pip/_internal/models/__pycache__/target_python.cpython-314.pyc,,
182
+ pip/_internal/models/__pycache__/wheel.cpython-314.pyc,,
183
+ pip/_internal/models/candidate.py,sha256=MvANZJiHkw6Y4T-oYSM8710G6yYB4_DwofoD7BAmrnM,824
184
+ pip/_internal/models/direct_url.py,sha256=9RS3TQAXknwLd8JOOZWlbBV6WZFs9qn-YAYk0VQ8R_Q,944
185
+ pip/_internal/models/format_control.py,sha256=PwemYG1L27BM0f1KP61rm24wShENFyxqlD1TWu34alc,2471
186
+ pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030
187
+ pip/_internal/models/installation_report.py,sha256=U4MlXWFB-8ev_yheuMO9T2m_y5b4C-hOzVaoHVobl38,2846
188
+ pip/_internal/models/link.py,sha256=SSXtFO3YAreUYY2R0PqtKXbAe1vV9Bqt5r_qPN218zE,23474
189
+ pip/_internal/models/release_control.py,sha256=31Jh-ZHsTIBZLe-7uPNoYLiRSWXAjEI1jGNxwqLKd4A,3365
190
+ pip/_internal/models/scheme.py,sha256=G-O9KElabcXqbPwfE_66lzX5fGahh3Gu6DAkz_9ZhJw,558
191
+ pip/_internal/models/search_scope.py,sha256=_i-Gj_w_FwZAvTs7WhjslBDD70J-8hmIdjXByI8uEZQ,4461
192
+ pip/_internal/models/selection_prefs.py,sha256=0teekwSVxW5MOk0WPG5Novw5q_XJjxijcd75kZO6E9g,1503
193
+ pip/_internal/models/target_python.py,sha256=I0eFS-eia3kwhrOvgsphFZtNAB2IwXZ9Sr9fp6IjBP4,4243
194
+ pip/_internal/models/wheel.py,sha256=1SdfDvN7ALTsbyZ9EOsNy1GPirP1n6EjHyzPrZyLSh8,2920
195
+ pip/_internal/network/__init__.py,sha256=FMy06P__y6jMjUc8z3ZcQdKF-pmZ2zM14_vBeHPGhUI,49
196
+ pip/_internal/network/__pycache__/__init__.cpython-314.pyc,,
197
+ pip/_internal/network/__pycache__/auth.cpython-314.pyc,,
198
+ pip/_internal/network/__pycache__/cache.cpython-314.pyc,,
199
+ pip/_internal/network/__pycache__/download.cpython-314.pyc,,
200
+ pip/_internal/network/__pycache__/lazy_wheel.cpython-314.pyc,,
201
+ pip/_internal/network/__pycache__/session.cpython-314.pyc,,
202
+ pip/_internal/network/__pycache__/utils.cpython-314.pyc,,
203
+ pip/_internal/network/__pycache__/xmlrpc.cpython-314.pyc,,
204
+ pip/_internal/network/auth.py,sha256=TBpwe7zcaPuBdBldjAOZhf20lmkacpIgGA-AqLcr8eU,21545
205
+ pip/_internal/network/cache.py,sha256=6DlMXJ7pb35M1vgtTK0-L_kiHJFxf7t9zrfeJ9vqO34,4862
206
+ pip/_internal/network/download.py,sha256=SVrmKao567lfs8RaCdyuOitzIRCZp9Rf3RcDj_o8vkg,14618
207
+ pip/_internal/network/lazy_wheel.py,sha256=y9gVksdJCSjnLfYzs_m3DYUAtl3hc_k-xFPDBd9DgOs,7646
208
+ pip/_internal/network/session.py,sha256=2KqMv5Hu_PFRYRkDBhSjIbqbsBp0lXv4tqoLKnM2K6o,19924
209
+ pip/_internal/network/utils.py,sha256=OTA1vwFtu2Ee1zWrqLysBpRQGTjvXxCJJUTEqy7hNcA,8128
210
+ pip/_internal/network/xmlrpc.py,sha256=_-Rnk3vOff8uF9hAGmT6SLALflY1gMBcbGwS12fb_Y4,1830
211
+ pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
212
+ pip/_internal/operations/__pycache__/__init__.cpython-314.pyc,,
213
+ pip/_internal/operations/__pycache__/check.cpython-314.pyc,,
214
+ pip/_internal/operations/__pycache__/freeze.cpython-314.pyc,,
215
+ pip/_internal/operations/__pycache__/prepare.cpython-314.pyc,,
216
+ pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
217
+ pip/_internal/operations/build/__pycache__/__init__.cpython-314.pyc,,
218
+ pip/_internal/operations/build/__pycache__/build_tracker.cpython-314.pyc,,
219
+ pip/_internal/operations/build/__pycache__/metadata.cpython-314.pyc,,
220
+ pip/_internal/operations/build/__pycache__/metadata_editable.cpython-314.pyc,,
221
+ pip/_internal/operations/build/__pycache__/wheel.cpython-314.pyc,,
222
+ pip/_internal/operations/build/__pycache__/wheel_editable.cpython-314.pyc,,
223
+ pip/_internal/operations/build/build_tracker.py,sha256=W3b5cmkMWPaE6QIwfzsTayJo7-OlxFHWDxfPuax1KcE,4771
224
+ pip/_internal/operations/build/metadata.py,sha256=INHaeiRfOiLYCXApfDNRo9Cw2xI4VwTc0KItvfdfOjk,1421
225
+ pip/_internal/operations/build/metadata_editable.py,sha256=oWudMsnjy4loO_Jy7g4N9nxsnaEX_iDlVRgCy7pu1rs,1509
226
+ pip/_internal/operations/build/wheel.py,sha256=3bP-nNiJ4S8JvMaBnyessXQUBhxTqt1GBx6DQ1iPJDY,1136
227
+ pip/_internal/operations/build/wheel_editable.py,sha256=q3kfElclM6FutVbFwE87JOTpVWt5ixDf3_UkHAIVfz4,1478
228
+ pip/_internal/operations/check.py,sha256=k7mTjLb5yZbidYw8Nt9vu7_u1L1ekLOzUECeN4qcNsA,5891
229
+ pip/_internal/operations/freeze.py,sha256=PDdY-y_ZtZZJLAKcaWPIGRKAGW7DXR48f0aMRU0j7BA,9854
230
+ pip/_internal/operations/install/__init__.py,sha256=ak-UETcQPKlFZaWoYKWu5QVXbpFBvg0sXc3i0O4vSYY,50
231
+ pip/_internal/operations/install/__pycache__/__init__.cpython-314.pyc,,
232
+ pip/_internal/operations/install/__pycache__/wheel.cpython-314.pyc,,
233
+ pip/_internal/operations/install/wheel.py,sha256=qhFwJSShLm4quY8zIss_t-bff0YV49HTNAKfu4fSpic,29078
234
+ pip/_internal/operations/prepare.py,sha256=zLkVMSDu9cUR0KnDm3bZ3QvIeaErhJKrr109UyDMlKQ,35030
235
+ pip/_internal/pyproject.py,sha256=J-sTWqC-XfsKQgz9m1bypMWZPHItsSHzIN_NWeIRmhM,4555
236
+ pip/_internal/req/__init__.py,sha256=x3uB7ZW-l_MOPm8ldF8Gi0dh5C8W23dB_wOH2NmWpFc,3140
237
+ pip/_internal/req/__pycache__/__init__.cpython-314.pyc,,
238
+ pip/_internal/req/__pycache__/constructors.cpython-314.pyc,,
239
+ pip/_internal/req/__pycache__/pep723.cpython-314.pyc,,
240
+ pip/_internal/req/__pycache__/req_dependency_group.cpython-314.pyc,,
241
+ pip/_internal/req/__pycache__/req_file.cpython-314.pyc,,
242
+ pip/_internal/req/__pycache__/req_install.cpython-314.pyc,,
243
+ pip/_internal/req/__pycache__/req_set.cpython-314.pyc,,
244
+ pip/_internal/req/__pycache__/req_uninstall.cpython-314.pyc,,
245
+ pip/_internal/req/constructors.py,sha256=fwILg3OiIK_f13RUGX5zQyz4YasUMp7MC6u9uPvoGzw,22276
246
+ pip/_internal/req/pep723.py,sha256=JsG1p3CaVcW8cjclD2kDj7d9qtVrNQaevY_UnKh00tk,1242
247
+ pip/_internal/req/req_dependency_group.py,sha256=PrWKtlwI8xbWnWEKjXs9RkrpQx2_h02ABefYT0ZdeQg,3145
248
+ pip/_internal/req/req_file.py,sha256=dmGBSxZ9dj1eOq2NXv94bor0u1n8P4-AvmJL-vYzIsE,20644
249
+ pip/_internal/req/req_install.py,sha256=r289__WNVaTxpRtLFUz3FpNvdGv8yYa87G-QkP5DsJc,32173
250
+ pip/_internal/req/req_set.py,sha256=awkqIXnYA4Prmsj0Qb3zhqdbYUmXd-1o0P-KZ3mvRQs,2828
251
+ pip/_internal/req/req_uninstall.py,sha256=t5HSYuLoLxnF7jrcIBDjTEP-sjjr8O4fZouEqOkVM_c,24276
252
+ pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
253
+ pip/_internal/resolution/__pycache__/__init__.cpython-314.pyc,,
254
+ pip/_internal/resolution/__pycache__/base.cpython-314.pyc,,
255
+ pip/_internal/resolution/base.py,sha256=J9Fq3kFOjFj9gBShYQtldEFPrRGSWtsp-rO9rIc4W4g,573
256
+ pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
257
+ pip/_internal/resolution/legacy/__pycache__/__init__.cpython-314.pyc,,
258
+ pip/_internal/resolution/legacy/__pycache__/resolver.cpython-314.pyc,,
259
+ pip/_internal/resolution/legacy/resolver.py,sha256=2CVLIZLm_nXkfJTt5RKtIbIxvCkn9Gavf4Yp9c1IjDU,24110
260
+ pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
261
+ pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-314.pyc,,
262
+ pip/_internal/resolution/resolvelib/__pycache__/base.cpython-314.pyc,,
263
+ pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-314.pyc,,
264
+ pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-314.pyc,,
265
+ pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-314.pyc,,
266
+ pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-314.pyc,,
267
+ pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-314.pyc,,
268
+ pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-314.pyc,,
269
+ pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-314.pyc,,
270
+ pip/_internal/resolution/resolvelib/base.py,sha256=fo7ojoQtgjmQH5ca3VyKJAO3p5sHnihMDw79Z8_31-U,5900
271
+ pip/_internal/resolution/resolvelib/candidates.py,sha256=SEkpEH6T6zl7Ve7Dw9oIS6tnREj-1U_q4U-2xEH0ISc,20848
272
+ pip/_internal/resolution/resolvelib/factory.py,sha256=rqwnD4GWEdVgG7nGP6OGj493yiGW6jZr0cW_msMOK_U,36162
273
+ pip/_internal/resolution/resolvelib/found_candidates.py,sha256=F55YtXekKUbVwphlXska01LkdTGVgx1qONlLK7BX-HM,6005
274
+ pip/_internal/resolution/resolvelib/provider.py,sha256=Nkx4A16MOAxjCj9jFm8wmlMk5cbWh1YK2-UYWTKEJCw,12310
275
+ pip/_internal/resolution/resolvelib/reporter.py,sha256=tEC7MF8IqGU4Ww9t61YVfNFKtoaQpb6-AwLZptJz1VE,3918
276
+ pip/_internal/resolution/resolvelib/requirements.py,sha256=Izl9n8nc188lA1BSPS8QxfudfDQPHgngw-ij6hXt0nQ,8239
277
+ pip/_internal/resolution/resolvelib/resolver.py,sha256=wM3CcRTYPdjnQ1ai3YP6htFmkE32o1xx2RgjU-ykAjc,13849
278
+ pip/_internal/self_outdated_check.py,sha256=9XxOXPqsZlKceTP2tZS7I7rXjodnqd3GrIQ8U0_L8BM,8097
279
+ pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
280
+ pip/_internal/utils/__pycache__/__init__.cpython-314.pyc,,
281
+ pip/_internal/utils/__pycache__/_jaraco_text.cpython-314.pyc,,
282
+ pip/_internal/utils/__pycache__/_log.cpython-314.pyc,,
283
+ pip/_internal/utils/__pycache__/appdirs.cpython-314.pyc,,
284
+ pip/_internal/utils/__pycache__/compat.cpython-314.pyc,,
285
+ pip/_internal/utils/__pycache__/compatibility_tags.cpython-314.pyc,,
286
+ pip/_internal/utils/__pycache__/datetime.cpython-314.pyc,,
287
+ pip/_internal/utils/__pycache__/deprecation.cpython-314.pyc,,
288
+ pip/_internal/utils/__pycache__/direct_url_helpers.cpython-314.pyc,,
289
+ pip/_internal/utils/__pycache__/egg_link.cpython-314.pyc,,
290
+ pip/_internal/utils/__pycache__/entrypoints.cpython-314.pyc,,
291
+ pip/_internal/utils/__pycache__/filesystem.cpython-314.pyc,,
292
+ pip/_internal/utils/__pycache__/filetypes.cpython-314.pyc,,
293
+ pip/_internal/utils/__pycache__/glibc.cpython-314.pyc,,
294
+ pip/_internal/utils/__pycache__/hashes.cpython-314.pyc,,
295
+ pip/_internal/utils/__pycache__/logging.cpython-314.pyc,,
296
+ pip/_internal/utils/__pycache__/misc.cpython-314.pyc,,
297
+ pip/_internal/utils/__pycache__/packaging.cpython-314.pyc,,
298
+ pip/_internal/utils/__pycache__/pylock.cpython-314.pyc,,
299
+ pip/_internal/utils/__pycache__/retry.cpython-314.pyc,,
300
+ pip/_internal/utils/__pycache__/subprocess.cpython-314.pyc,,
301
+ pip/_internal/utils/__pycache__/temp_dir.cpython-314.pyc,,
302
+ pip/_internal/utils/__pycache__/unpacking.cpython-314.pyc,,
303
+ pip/_internal/utils/__pycache__/urls.cpython-314.pyc,,
304
+ pip/_internal/utils/__pycache__/virtualenv.cpython-314.pyc,,
305
+ pip/_internal/utils/__pycache__/wheel.cpython-314.pyc,,
306
+ pip/_internal/utils/_jaraco_text.py,sha256=M15uUPIh5NpP1tdUGBxRau6q1ZAEtI8-XyLEETscFfE,3350
307
+ pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015
308
+ pip/_internal/utils/appdirs.py,sha256=LrzDPZMKVh0rubtCx9vu3XlZbLCSug6VSj4Qsvt66BA,1681
309
+ pip/_internal/utils/compat.py,sha256=i2JUZXGrqP-ZoD8t4gwckBA3KYNUWCluvRDXScts5fE,2601
310
+ pip/_internal/utils/compatibility_tags.py,sha256=DiNSLqpuruXUamGQwOJ2WZByDGLTGaXi9O-Xf8fOi34,6630
311
+ pip/_internal/utils/datetime.py,sha256=kuJOf1mW8G5tRFN6jWardddS-9qSaR53lK1jmx3NTZY,868
312
+ pip/_internal/utils/deprecation.py,sha256=IQFumZa-XWJ3UoPnX4duwbf79CTzOZD_Vk1PkivAu4g,4537
313
+ pip/_internal/utils/direct_url_helpers.py,sha256=WCCPJnmoPHz7kiYePrEcVAen2lDpCT9WQVImoHHWCO8,3363
314
+ pip/_internal/utils/egg_link.py,sha256=YWfsrbmfcrfWgqQYy6OuIjsyb9IfL1q_2v4zsms1WjI,2459
315
+ pip/_internal/utils/entrypoints.py,sha256=uPjAyShKObdotjQjJUzprQ6r3xQvDIZwUYfHHqZ7Dok,3324
316
+ pip/_internal/utils/filesystem.py,sha256=gig73bOOS1NnDB94EDDvdDnHjQoeRz_TlfQPiCV7Me0,6812
317
+ pip/_internal/utils/filetypes.py,sha256=sEMa38qaqjvx1Zid3OCAUja31BOBU-USuSMPBvU3yjo,689
318
+ pip/_internal/utils/glibc.py,sha256=sEh8RJJLYSdRvTqAO4THVPPA-YSDVLD4SI9So-bxX1U,3726
319
+ pip/_internal/utils/hashes.py,sha256=38-bCOJSHippQ7r9RttrMHxb2mv3EARt1Gw8kFmW73g,5040
320
+ pip/_internal/utils/logging.py,sha256=hGTjBuIjNZxydV6vs4woxAbhkHI8L-9uCO14OCvPlA8,13919
321
+ pip/_internal/utils/misc.py,sha256=28LWQFvFWmrpJqMcV0soif1xnl3_gb25B3gG_iU5zhM,25408
322
+ pip/_internal/utils/packaging.py,sha256=s5tpUmFumwV0H9JSTzryrIY4JwQM8paGt7Sm7eNwt2Y,1601
323
+ pip/_internal/utils/pylock.py,sha256=XQTZ1ggh7yfpHfRdbvjSAe1peOtg2Z2xFrUeZ7wl4Ts,10290
324
+ pip/_internal/utils/retry.py,sha256=oOK3VGgKRKxSkXDPARf73cnQS3hDtnE9-feAg4AlNZE,1488
325
+ pip/_internal/utils/subprocess.py,sha256=nqNz2p3G4QANCCBcaJkqIQvQUYA50TwjZnoYjiyPxs8,9001
326
+ pip/_internal/utils/temp_dir.py,sha256=TDiL9BzEp2eHalQLH0rhyM3m2xuydEg9c6t1h4bT5l8,9303
327
+ pip/_internal/utils/unpacking.py,sha256=5i9Sn__SNElhoCXnLt2SvQaQ-SnTzcUaDH1_JI1THUw,14789
328
+ pip/_internal/utils/urls.py,sha256=JQWrRAoXHBpPsY9Aij61bsZjMQLCcuyrUO1R6W_BwIo,1647
329
+ pip/_internal/utils/virtualenv.py,sha256=9od4LsceDynUSsLTEXXgtumlUQ8VvKp86b2xzK0Yu3g,2272
330
+ pip/_internal/utils/wheel.py,sha256=YdRuj6MicG-Q9Mg03FbUv1WTLam6Lc7AgijY4voVyis,4468
331
+ pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596
332
+ pip/_internal/vcs/__pycache__/__init__.cpython-314.pyc,,
333
+ pip/_internal/vcs/__pycache__/bazaar.cpython-314.pyc,,
334
+ pip/_internal/vcs/__pycache__/git.cpython-314.pyc,,
335
+ pip/_internal/vcs/__pycache__/mercurial.cpython-314.pyc,,
336
+ pip/_internal/vcs/__pycache__/subversion.cpython-314.pyc,,
337
+ pip/_internal/vcs/__pycache__/versioncontrol.cpython-314.pyc,,
338
+ pip/_internal/vcs/bazaar.py,sha256=3W1eHjkYx2vc6boeb2NBh4I_rlGAXM-vrzfNhLm1Rxg,3734
339
+ pip/_internal/vcs/git.py,sha256=L52rqJN--Kq0kjAR8_9Si8RJEcNlULJdk6Vipg8ZlfA,19273
340
+ pip/_internal/vcs/mercurial.py,sha256=w1ZJWLKqNP1onEjkfjlwBVnMqPZNSIER8ayjQcnTq4w,5575
341
+ pip/_internal/vcs/subversion.py,sha256=uUgdPvxmvEB8Qwtjr0Hc0XgFjbiNi5cbvI4vARLOJXo,11787
342
+ pip/_internal/vcs/versioncontrol.py,sha256=JsUgTG53DkJPy5mXVBH7uqeFQyaL69707ibts5uCBYA,22579
343
+ pip/_internal/wheel_builder.py,sha256=kdPvAcxfknA8B_4g6hPDjB7C4uzL_cV5Vde2Oj2Ipzk,9146
344
+ pip/_vendor/README.rst,sha256=t7IinjaiuwUh812XmVApQHJb8pTw33U8A9URqy6GlF4,9222
345
+ pip/_vendor/__init__.py,sha256=WzusPTGWIMeQQWSVJ0h2rafGkVTa9WKJ2HT-2-EoZrU,4907
346
+ pip/_vendor/__pycache__/__init__.cpython-314.pyc,,
347
+ pip/_vendor/bom.cdx.json,sha256=eX4gCqf_8W-tn7Le6uzlCisr7GI-tsN1kXbu5s7hkyg,5319
348
+ pip/_vendor/cachecontrol/LICENSE.txt,sha256=hu7uh74qQ_P_H1ZJb0UfaSQ5JvAl_tuwM2ZsMExMFhs,558
349
+ pip/_vendor/cachecontrol/__init__.py,sha256=GxwRkm_TQBtPZpfpVK9r6S9dAy2DVnVgDVHJKTiPZ1k,820
350
+ pip/_vendor/cachecontrol/__pycache__/__init__.cpython-314.pyc,,
351
+ pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-314.pyc,,
352
+ pip/_vendor/cachecontrol/__pycache__/adapter.cpython-314.pyc,,
353
+ pip/_vendor/cachecontrol/__pycache__/cache.cpython-314.pyc,,
354
+ pip/_vendor/cachecontrol/__pycache__/controller.cpython-314.pyc,,
355
+ pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-314.pyc,,
356
+ pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-314.pyc,,
357
+ pip/_vendor/cachecontrol/__pycache__/serialize.cpython-314.pyc,,
358
+ pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-314.pyc,,
359
+ pip/_vendor/cachecontrol/_cmd.py,sha256=iist2EpzJvDVIhMAxXq8iFnTBsiZAd6iplxfmNboNyk,1737
360
+ pip/_vendor/cachecontrol/adapter.py,sha256=W-HW-l01gyCsnxkOyCbqx7sxrWYoBbKrDsKkVVQN6NE,6586
361
+ pip/_vendor/cachecontrol/cache.py,sha256=OXwv7Fn2AwnKNiahJHnjtvaKLndvVLv_-zO-ltlV9qI,1953
362
+ pip/_vendor/cachecontrol/caches/__init__.py,sha256=dtrrroK5BnADR1GWjCZ19aZ0tFsMfvFBtLQQU1sp_ag,303
363
+ pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-314.pyc,,
364
+ pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-314.pyc,,
365
+ pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-314.pyc,,
366
+ pip/_vendor/cachecontrol/caches/file_cache.py,sha256=d8upFmy_zwaCmlbWEVBlLXFddt8Zw8c5SFpxeOZsdfw,4117
367
+ pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=9rmqwtYu_ljVkW6_oLqbC7EaX_a8YT_yLuna-eS0dgo,1386
368
+ pip/_vendor/cachecontrol/controller.py,sha256=xBauC-vUSu5GsJsxD4-W-JaKqqbBz0MN6Zv8PA2N8hI,19102
369
+ pip/_vendor/cachecontrol/filewrapper.py,sha256=DhxC_rSk-beKdbsYhfvBUDovQHX9r3gHH_jP9-q_mKk,4354
370
+ pip/_vendor/cachecontrol/heuristics.py,sha256=gqMXU8w0gQuEQiSdu3Yg-0vd9kW7nrWKbLca75rheGE,4881
371
+ pip/_vendor/cachecontrol/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
372
+ pip/_vendor/cachecontrol/serialize.py,sha256=HQd2IllQ05HzPkVLMXTF2uX5mjEQjDBkxCqUJUODpZk,5163
373
+ pip/_vendor/cachecontrol/wrapper.py,sha256=hsGc7g8QGQTT-4f8tgz3AM5qwScg6FO0BSdLSRdEvpU,1417
374
+ pip/_vendor/certifi/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989
375
+ pip/_vendor/certifi/__init__.py,sha256=-W1R_y8WCaSkT1tdjuxH_zTBZY1YH6xQgdN1nbBajOE,94
376
+ pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255
377
+ pip/_vendor/certifi/__pycache__/__init__.cpython-314.pyc,,
378
+ pip/_vendor/certifi/__pycache__/__main__.cpython-314.pyc,,
379
+ pip/_vendor/certifi/__pycache__/core.cpython-314.pyc,,
380
+ pip/_vendor/certifi/cacert.pem,sha256=u8fpwB11UbuKFZtd7dmJuO484QWv9SK2jrGwG_hUyrA,234354
381
+ pip/_vendor/certifi/core.py,sha256=gu_ECVI1m3Rq0ytpsNE61hgQGcKaOAt9Rs9G8KsTCOI,3442
382
+ pip/_vendor/certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
383
+ pip/_vendor/distlib/LICENSE.txt,sha256=gI4QyKarjesUn_mz-xn0R6gICUYG1xKpylf-rTVSWZ0,14531
384
+ pip/_vendor/distlib/__init__.py,sha256=tmYThB1xmgfRjRtyy8YP0i0ymrF2n6eVswcwK6OYbcc,625
385
+ pip/_vendor/distlib/__pycache__/__init__.cpython-314.pyc,,
386
+ pip/_vendor/distlib/__pycache__/compat.cpython-314.pyc,,
387
+ pip/_vendor/distlib/__pycache__/resources.cpython-314.pyc,,
388
+ pip/_vendor/distlib/__pycache__/scripts.cpython-314.pyc,,
389
+ pip/_vendor/distlib/__pycache__/util.cpython-314.pyc,,
390
+ pip/_vendor/distlib/compat.py,sha256=HTzhOY98c_fyMVE7xtVuZZ-AVkN4-RGes-hWmvuwquk,40605
391
+ pip/_vendor/distlib/resources.py,sha256=wZt_Ako8TY-L6ZIAmP42J7MNX0XTEF6gkM0Om5F7UPY,11350
392
+ pip/_vendor/distlib/scripts.py,sha256=rVm4A-YfGQDpsORwOy7AwepyRTayuy6rc-MnaCMBAcM,18835
393
+ pip/_vendor/distlib/t32.exe,sha256=a0GV5kCoWsMutvliiCKmIgV98eRZ33wXoS-XrqvJQVs,97792
394
+ pip/_vendor/distlib/t64-arm.exe,sha256=68TAa32V504xVBnufojh0PcenpR3U4wAqTqf-MZqbPw,182784
395
+ pip/_vendor/distlib/t64.exe,sha256=gaYY8hy4fbkHYTTnA4i26ct8IQZzkBG2pRdy0iyuBrc,108032
396
+ pip/_vendor/distlib/util.py,sha256=n2QDXvB0XtwrtehygnwdLgLkLia58sZjzgZPKyD6rAE,68167
397
+ pip/_vendor/distlib/w32.exe,sha256=R4csx3-OGM9kL4aPIzQKRo5TfmRSHZo6QWyLhDhNBks,91648
398
+ pip/_vendor/distlib/w64-arm.exe,sha256=xdyYhKj0WDcVUOCb05blQYvzdYIKMbmJn2SZvzkcey4,168448
399
+ pip/_vendor/distlib/w64.exe,sha256=ejGf-rojoBfXseGLpya6bFTFPWRG21X5KvU8J5iU-K0,101888
400
+ pip/_vendor/distro/LICENSE,sha256=y16Ofl9KOYjhBjwULGDcLfdWBfTEZRXnduOspt-XbhQ,11325
401
+ pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981
402
+ pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64
403
+ pip/_vendor/distro/__pycache__/__init__.cpython-314.pyc,,
404
+ pip/_vendor/distro/__pycache__/__main__.cpython-314.pyc,,
405
+ pip/_vendor/distro/__pycache__/distro.cpython-314.pyc,,
406
+ pip/_vendor/distro/distro.py,sha256=XqbefacAhDT4zr_trnbA15eY8vdK4GTghgmvUGrEM_4,49430
407
+ pip/_vendor/distro/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
408
+ pip/_vendor/idna/LICENSE.md,sha256=GppPDj1HmickDd1ZqRN6ZqtKD539yMphiMwL_YUYfwQ,1541
409
+ pip/_vendor/idna/__init__.py,sha256=MPqNDLZbXqGaNdXxAFhiqFPKEQXju2jNQhCey6-5eJM,868
410
+ pip/_vendor/idna/__main__.py,sha256=4JMK66Wj4uLZTKbF-sT3LAxOsr6buig77PmOkJCRRxw,83
411
+ pip/_vendor/idna/__pycache__/__init__.cpython-314.pyc,,
412
+ pip/_vendor/idna/__pycache__/__main__.cpython-314.pyc,,
413
+ pip/_vendor/idna/__pycache__/cli.cpython-314.pyc,,
414
+ pip/_vendor/idna/__pycache__/codec.cpython-314.pyc,,
415
+ pip/_vendor/idna/__pycache__/compat.cpython-314.pyc,,
416
+ pip/_vendor/idna/__pycache__/core.cpython-314.pyc,,
417
+ pip/_vendor/idna/__pycache__/idnadata.cpython-314.pyc,,
418
+ pip/_vendor/idna/__pycache__/intranges.cpython-314.pyc,,
419
+ pip/_vendor/idna/__pycache__/package_data.cpython-314.pyc,,
420
+ pip/_vendor/idna/__pycache__/uts46data.cpython-314.pyc,,
421
+ pip/_vendor/idna/cli.py,sha256=swqJLMNc8Uzs60KziNpbWnHuqlG3WRQwJSbo4n8xDAo,4139
422
+ pip/_vendor/idna/codec.py,sha256=JRbo-f7pEkLdWeiH89Z72UR4VBYhvKDFrQBeNX6sRDE,5040
423
+ pip/_vendor/idna/compat.py,sha256=AepA39ceRHxkfHP41-FvKW5Ki-f4PfUZ90RUMlCNdmo,1353
424
+ pip/_vendor/idna/core.py,sha256=SfOr1xO3PoE0RDYx7bMciAnjiyjJPbPw_93AB5IUYOw,24685
425
+ pip/_vendor/idna/idnadata.py,sha256=Af-mo8WBmkhAK6TyXKOQH88OX0mQNDKtdL7UWtQpppk,44862
426
+ pip/_vendor/idna/intranges.py,sha256=g49scLSkqJtAhLmOODa7hVHriSjmb60tiTsEoocJdBI,1851
427
+ pip/_vendor/idna/package_data.py,sha256=TeI94EqAFAFaXfBJwsOPUMLn2969uirPa-DaeaceAyU,21
428
+ pip/_vendor/idna/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
429
+ pip/_vendor/idna/uts46data.py,sha256=jujNz5QqWMcJf-XYLv4X1jBvb5FlI0t6-e1mILsgbPk,234325
430
+ pip/_vendor/msgpack/COPYING,sha256=SS3tuoXaWHL3jmCRvNH-pHTWYNNay03ulkuKqz8AdCc,614
431
+ pip/_vendor/msgpack/__init__.py,sha256=RA8gcqK17YpkxBnNwXJVa1oa2LygWDgfF1nA1NPw3mo,1109
432
+ pip/_vendor/msgpack/__pycache__/__init__.cpython-314.pyc,,
433
+ pip/_vendor/msgpack/__pycache__/exceptions.cpython-314.pyc,,
434
+ pip/_vendor/msgpack/__pycache__/ext.cpython-314.pyc,,
435
+ pip/_vendor/msgpack/__pycache__/fallback.cpython-314.pyc,,
436
+ pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081
437
+ pip/_vendor/msgpack/ext.py,sha256=kteJv03n9tYzd5oo3xYopVTo4vRaAxonBQQJhXohZZo,5726
438
+ pip/_vendor/msgpack/fallback.py,sha256=0g1Pzp0vtmBEmJ5w9F3s_-JMVURP8RS4G1cc5TRaAsI,32390
439
+ pip/_vendor/packaging/LICENSE,sha256=ytHvW9NA1z4HS6YU0m996spceUDD2MNIUuZcSQlobEg,197
440
+ pip/_vendor/packaging/LICENSE.APACHE,sha256=DVQuDIgE45qn836wDaWnYhSdxoLXgpRRKH4RuTjpRZQ,10174
441
+ pip/_vendor/packaging/LICENSE.BSD,sha256=tw5-m3QvHMb5SLNMFqo5_-zpQZY2S8iP8NIYDwAo-sU,1344
442
+ pip/_vendor/packaging/__init__.py,sha256=QhMEdPu2XogrJzV3S0KWS6t7l0I9k8EeDRJl4fnw87s,494
443
+ pip/_vendor/packaging/__pycache__/__init__.cpython-314.pyc,,
444
+ pip/_vendor/packaging/__pycache__/_elffile.cpython-314.pyc,,
445
+ pip/_vendor/packaging/__pycache__/_manylinux.cpython-314.pyc,,
446
+ pip/_vendor/packaging/__pycache__/_musllinux.cpython-314.pyc,,
447
+ pip/_vendor/packaging/__pycache__/_parser.cpython-314.pyc,,
448
+ pip/_vendor/packaging/__pycache__/_structures.cpython-314.pyc,,
449
+ pip/_vendor/packaging/__pycache__/_tokenizer.cpython-314.pyc,,
450
+ pip/_vendor/packaging/__pycache__/dependency_groups.cpython-314.pyc,,
451
+ pip/_vendor/packaging/__pycache__/direct_url.cpython-314.pyc,,
452
+ pip/_vendor/packaging/__pycache__/errors.cpython-314.pyc,,
453
+ pip/_vendor/packaging/__pycache__/markers.cpython-314.pyc,,
454
+ pip/_vendor/packaging/__pycache__/metadata.cpython-314.pyc,,
455
+ pip/_vendor/packaging/__pycache__/pylock.cpython-314.pyc,,
456
+ pip/_vendor/packaging/__pycache__/requirements.cpython-314.pyc,,
457
+ pip/_vendor/packaging/__pycache__/specifiers.cpython-314.pyc,,
458
+ pip/_vendor/packaging/__pycache__/tags.cpython-314.pyc,,
459
+ pip/_vendor/packaging/__pycache__/utils.cpython-314.pyc,,
460
+ pip/_vendor/packaging/__pycache__/version.cpython-314.pyc,,
461
+ pip/_vendor/packaging/_elffile.py,sha256=-sKkptYqzYw2-x3QByJa5mB4rfPWu1pxkZHRx1WAFCY,3211
462
+ pip/_vendor/packaging/_manylinux.py,sha256=Hf6nB0cOrayEs96-p3oIXAgGnFquv20DO5l-o2_Xnv0,9559
463
+ pip/_vendor/packaging/_musllinux.py,sha256=Z6swjH3MA7XS3qXnmMN7QPhqP3fnoYI0eQ18e9-HgAE,2707
464
+ pip/_vendor/packaging/_parser.py,sha256=Kf2nsDw4c54X82pY8ba4F02Bve6OygGMAjL-Begqcew,11698
465
+ pip/_vendor/packaging/_structures.py,sha256=60jRbF78p8z5MKnNd6cAprgOadCJHV0DlmUmRBqFZcs,1109
466
+ pip/_vendor/packaging/_tokenizer.py,sha256=tFU2Wr-ZZJdAbkXLEJo7qUQDJaIkfft9DqaifiEND7A,5391
467
+ pip/_vendor/packaging/dependency_groups.py,sha256=XZIAVFK9uHG4RCGprmJn3VInUWMesxha_kytJuMO9eY,10218
468
+ pip/_vendor/packaging/direct_url.py,sha256=eKmbDiPP1sLV4Mj_kCSZqqknrIyVO9Sr7JpF8KCjp4U,10917
469
+ pip/_vendor/packaging/errors.py,sha256=6hfEYXAf8v_IF65-lFadJOMIieBP2xIKtyEXjG1nGIs,2680
470
+ pip/_vendor/packaging/licenses/__init__.py,sha256=_Jx0XRiD_58palsWnyLrLuh59ZpGCPIPXLKdZo9OJvQ,7293
471
+ pip/_vendor/packaging/licenses/__pycache__/__init__.cpython-314.pyc,,
472
+ pip/_vendor/packaging/licenses/__pycache__/_spdx.cpython-314.pyc,,
473
+ pip/_vendor/packaging/licenses/_spdx.py,sha256=WW7DXiyg68up_YND_wpRYlr1SHhiV4FfJLQffghhMxQ,51122
474
+ pip/_vendor/packaging/markers.py,sha256=QixBVcb9D2HjwEYiuhpNkbqk9znPRbU8zNX0kR1RIrU,17067
475
+ pip/_vendor/packaging/metadata.py,sha256=crAh0E3GVGVqPlu6EdRFsaG-Y6UYznTUqjuGKRGPv6c,38770
476
+ pip/_vendor/packaging/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
477
+ pip/_vendor/packaging/pylock.py,sha256=G_1gncTmDbRLY1jo4VDI9Uw-b5IErh_Q9V_BbVJTmD8,33890
478
+ pip/_vendor/packaging/requirements.py,sha256=Q-BdEHVW5K785GBXt7RcP4UEsdIKWoWFqlrHjR4WV50,4395
479
+ pip/_vendor/packaging/specifiers.py,sha256=3XBcSslm-YQEEEO_zrv4F6dR5wRxs4ErJvJ0vjNBfGM,71550
480
+ pip/_vendor/packaging/tags.py,sha256=ANYHZxYQVp9BlOQYOHU5ArDNVIpTFl4KlbocYVBWnFs,34236
481
+ pip/_vendor/packaging/utils.py,sha256=M7-JMKic2sP1YtV_8aW7eVGB-x3ADuKCiSrsVeCd2Uo,9848
482
+ pip/_vendor/packaging/version.py,sha256=Mcu7Tf6Y1i0gQ4FXv4t0g8cbL5joAEshjgIpz_2vISI,38393
483
+ pip/_vendor/pkg_resources/LICENSE,sha256=htoPAa6uRjSKPD1GUZXcHOzN55956HdppkuNoEsqR0E,1023
484
+ pip/_vendor/pkg_resources/__init__.py,sha256=vbTJ0_ruUgGxQjlEqsruFmiNPVyh2t9q-zyTDT053xI,124451
485
+ pip/_vendor/pkg_resources/__pycache__/__init__.cpython-314.pyc,,
486
+ pip/_vendor/platformdirs/LICENSE,sha256=KeD9YukphQ6G6yjD_czwzv30-pSHkBHP-z0NS-1tTbY,1089
487
+ pip/_vendor/platformdirs/__init__.py,sha256=gBmL_J_KdPgKiwM3dHCo-y-8CbS06QCa1XIhJ9bIgew,32389
488
+ pip/_vendor/platformdirs/__main__.py,sha256=DQ1o1E1l0Ghuitj4uQJKAPwkcKbGzkzO0sbhzd9RbUc,1773
489
+ pip/_vendor/platformdirs/__pycache__/__init__.cpython-314.pyc,,
490
+ pip/_vendor/platformdirs/__pycache__/__main__.cpython-314.pyc,,
491
+ pip/_vendor/platformdirs/__pycache__/_xdg.cpython-314.pyc,,
492
+ pip/_vendor/platformdirs/__pycache__/android.cpython-314.pyc,,
493
+ pip/_vendor/platformdirs/__pycache__/api.cpython-314.pyc,,
494
+ pip/_vendor/platformdirs/__pycache__/macos.cpython-314.pyc,,
495
+ pip/_vendor/platformdirs/__pycache__/unix.cpython-314.pyc,,
496
+ pip/_vendor/platformdirs/__pycache__/version.cpython-314.pyc,,
497
+ pip/_vendor/platformdirs/__pycache__/windows.cpython-314.pyc,,
498
+ pip/_vendor/platformdirs/_xdg.py,sha256=5w6S07vVabEROhaUB_X7i0hmLNbdYtC9aEvPbsEIS8M,7894
499
+ pip/_vendor/platformdirs/android.py,sha256=BBj3wfw-dfuVxsCsKsvFByKVspRDgfv8gwIzhpE1JRQ,11566
500
+ pip/_vendor/platformdirs/api.py,sha256=EaIsFgXGu8cDTb41WM3hse_SrIoOUht8_TCo5XdOOSM,14887
501
+ pip/_vendor/platformdirs/macos.py,sha256=PWudeDZAY9UuwLP_5rN3exSRFtYdY542hDhjah4dSWA,9538
502
+ pip/_vendor/platformdirs/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
503
+ pip/_vendor/platformdirs/unix.py,sha256=X7Cip1xOHFOnSVveqKWzU1P7jn4zuDGpRgmVxJnk4vk,13317
504
+ pip/_vendor/platformdirs/version.py,sha256=dJvdm7L_7wobEcxrNoJtH7CtmYcG_VR5yNmtBshJ-xs,522
505
+ pip/_vendor/platformdirs/windows.py,sha256=YOdSGNhdpxm_ydZq7uG74i9mX2_WWbcMSA4fobXwL0M,15798
506
+ pip/_vendor/pygments/LICENSE,sha256=qdZvHVJt8C4p3Oc0NtNOVuhjL0bCdbvf_HBWnogvnxc,1331
507
+ pip/_vendor/pygments/__init__.py,sha256=Xnd_7fJUqU_6D0bxXW0qS9M_OE9G6VW8YNPbGLWoKwQ,2986
508
+ pip/_vendor/pygments/__main__.py,sha256=IqAQ_836Kv2CTx8r6Ie6duRQuYSPl85sbYomEwIsY14,356
509
+ pip/_vendor/pygments/__pycache__/__init__.cpython-314.pyc,,
510
+ pip/_vendor/pygments/__pycache__/__main__.cpython-314.pyc,,
511
+ pip/_vendor/pygments/__pycache__/console.cpython-314.pyc,,
512
+ pip/_vendor/pygments/__pycache__/filter.cpython-314.pyc,,
513
+ pip/_vendor/pygments/__pycache__/formatter.cpython-314.pyc,,
514
+ pip/_vendor/pygments/__pycache__/lexer.cpython-314.pyc,,
515
+ pip/_vendor/pygments/__pycache__/modeline.cpython-314.pyc,,
516
+ pip/_vendor/pygments/__pycache__/plugin.cpython-314.pyc,,
517
+ pip/_vendor/pygments/__pycache__/regexopt.cpython-314.pyc,,
518
+ pip/_vendor/pygments/__pycache__/scanner.cpython-314.pyc,,
519
+ pip/_vendor/pygments/__pycache__/sphinxext.cpython-314.pyc,,
520
+ pip/_vendor/pygments/__pycache__/style.cpython-314.pyc,,
521
+ pip/_vendor/pygments/__pycache__/token.cpython-314.pyc,,
522
+ pip/_vendor/pygments/__pycache__/unistring.cpython-314.pyc,,
523
+ pip/_vendor/pygments/__pycache__/util.cpython-314.pyc,,
524
+ pip/_vendor/pygments/console.py,sha256=C189JAwhC1Qh0AKgshzb1wVDzFqBnv1VZ45kTEDIO30,1721
525
+ pip/_vendor/pygments/filter.py,sha256=1dnbkq2AdC3AkHt3DaXwnOkTBLChl1kR6naSLwnr_tc,1913
526
+ pip/_vendor/pygments/filters/__init__.py,sha256=Prd6xUK_7kw0rQv_OXPY3871RzwtWKGp_g7SddYHBXg,40397
527
+ pip/_vendor/pygments/filters/__pycache__/__init__.cpython-314.pyc,,
528
+ pip/_vendor/pygments/formatter.py,sha256=EuAXPX6c3XQkCt3lD0VhSPSZByG7YQk8HrCwxlf-CZQ,4393
529
+ pip/_vendor/pygments/formatters/__init__.py,sha256=EYLDCIgBHL_DkuhNRQZlHpS2_UE5-MfsGL1hMcOa95w,5388
530
+ pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-314.pyc,,
531
+ pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-314.pyc,,
532
+ pip/_vendor/pygments/formatters/_mapping.py,sha256=1Cw37FuQlNacnxRKmtlPX4nyLoX9_ttko5ZwscNUZZ4,4176
533
+ pip/_vendor/pygments/lexer.py,sha256=wSXDzt2fNZJSrlfdIfnKVlheRpFkszkPmgwBJevbBNo,35394
534
+ pip/_vendor/pygments/lexers/__init__.py,sha256=s8I_tVlotrM8cFTGlnjw45UY5sj5jhDwdQzOOjhzgNg,12118
535
+ pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-314.pyc,,
536
+ pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-314.pyc,,
537
+ pip/_vendor/pygments/lexers/__pycache__/python.cpython-314.pyc,,
538
+ pip/_vendor/pygments/lexers/_mapping.py,sha256=wGAYjOBprDVZA01eocwcLJ6L8biM9rP2jxwr1bQJ96M,77934
539
+ pip/_vendor/pygments/lexers/python.py,sha256=TqyfQOPhCYPx35apQL65CAj9k-4BxuzLq8MDfdm2jvE,54250
540
+ pip/_vendor/pygments/modeline.py,sha256=me8g5rySidvPtMBOrDy2O1sMqZd02lBHMY5KDZefUws,1008
541
+ pip/_vendor/pygments/plugin.py,sha256=P6zIw-vkSQ0k1WKHrzbBTjpwlCZPbR-6Qe_dO9Bjdu0,1928
542
+ pip/_vendor/pygments/regexopt.py,sha256=d2hTvazlow5zzZIOCVnfeEG2CY0GrY_igH1kCSSf7ow,3308
543
+ pip/_vendor/pygments/scanner.py,sha256=DtoLi1pOKpNu-6jiakJpSQLUi_ep29SQQhv7oAwYWME,3095
544
+ pip/_vendor/pygments/sphinxext.py,sha256=RflpnfXB4rZLYyZ-OQ_igntVOlB8jG42xFYgEVIyHf8,7984
545
+ pip/_vendor/pygments/style.py,sha256=wJSXOXjehGYxI6e3DGaUtONeWuhmTfswfkysrL9Was0,6423
546
+ pip/_vendor/pygments/styles/__init__.py,sha256=kYdCGK8gZ1V8wfFQETOzpPmZTJ1nMB0b1iNlU8dHQ9E,2045
547
+ pip/_vendor/pygments/styles/__pycache__/__init__.cpython-314.pyc,,
548
+ pip/_vendor/pygments/styles/__pycache__/_mapping.cpython-314.pyc,,
549
+ pip/_vendor/pygments/styles/_mapping.py,sha256=6lovFUE29tz6EsV3XYY4hgozJ7q1JL7cfO3UOlgnS8w,3312
550
+ pip/_vendor/pygments/token.py,sha256=DVil5T2ltHkTgQTUYy1dMtgyigjavCs1ypE4Qf2CrGo,6229
551
+ pip/_vendor/pygments/unistring.py,sha256=Z4w4HfOVUhueCURRkfhAqQ2b-69UzkhY4xuHevYEy5g,63211
552
+ pip/_vendor/pygments/util.py,sha256=zk935tJSpwSA9zxNmV1TuhcEP0MfboXiRZSGQnLPEqk,10046
553
+ pip/_vendor/pyproject_hooks/LICENSE,sha256=GyKwSbUmfW38I6Z79KhNjsBLn9-xpR02DkK0NCyLQVQ,1081
554
+ pip/_vendor/pyproject_hooks/__init__.py,sha256=cPB_a9LXz5xvsRbX1o2qyAdjLatZJdQ_Lc5McNX-X7Y,691
555
+ pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-314.pyc,,
556
+ pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-314.pyc,,
557
+ pip/_vendor/pyproject_hooks/_impl.py,sha256=jY-raxnmyRyB57ruAitrJRUzEexuAhGTpgMygqx67Z4,14936
558
+ pip/_vendor/pyproject_hooks/_in_process/__init__.py,sha256=MJNPpfIxcO-FghxpBbxkG1rFiQf6HOUbV4U5mq0HFns,557
559
+ pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-314.pyc,,
560
+ pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-314.pyc,,
561
+ pip/_vendor/pyproject_hooks/_in_process/_in_process.py,sha256=qcXMhmx__MIJq10gGHW3mA4Tl8dy8YzHMccwnNoKlw0,12216
562
+ pip/_vendor/pyproject_hooks/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
563
+ pip/_vendor/requests/LICENSE,sha256=CeipvOyAZxBGUsFoaFqwkx54aPnIKEtm9a5u2uXxEws,10142
564
+ pip/_vendor/requests/__init__.py,sha256=nC2attFwdoYN-oE6-vQW4ciuvIu7J2P_TU1qQ2DcueE,5873
565
+ pip/_vendor/requests/__pycache__/__init__.cpython-314.pyc,,
566
+ pip/_vendor/requests/__pycache__/__version__.cpython-314.pyc,,
567
+ pip/_vendor/requests/__pycache__/_internal_utils.cpython-314.pyc,,
568
+ pip/_vendor/requests/__pycache__/_types.cpython-314.pyc,,
569
+ pip/_vendor/requests/__pycache__/adapters.cpython-314.pyc,,
570
+ pip/_vendor/requests/__pycache__/api.cpython-314.pyc,,
571
+ pip/_vendor/requests/__pycache__/auth.cpython-314.pyc,,
572
+ pip/_vendor/requests/__pycache__/certs.cpython-314.pyc,,
573
+ pip/_vendor/requests/__pycache__/compat.cpython-314.pyc,,
574
+ pip/_vendor/requests/__pycache__/cookies.cpython-314.pyc,,
575
+ pip/_vendor/requests/__pycache__/exceptions.cpython-314.pyc,,
576
+ pip/_vendor/requests/__pycache__/help.cpython-314.pyc,,
577
+ pip/_vendor/requests/__pycache__/hooks.cpython-314.pyc,,
578
+ pip/_vendor/requests/__pycache__/models.cpython-314.pyc,,
579
+ pip/_vendor/requests/__pycache__/packages.cpython-314.pyc,,
580
+ pip/_vendor/requests/__pycache__/sessions.cpython-314.pyc,,
581
+ pip/_vendor/requests/__pycache__/status_codes.cpython-314.pyc,,
582
+ pip/_vendor/requests/__pycache__/structures.cpython-314.pyc,,
583
+ pip/_vendor/requests/__pycache__/utils.cpython-314.pyc,,
584
+ pip/_vendor/requests/__version__.py,sha256=q7qQZwsDcKPcQNl8LepGo11L7JQf8Q18PPMJjvBKF_k,435
585
+ pip/_vendor/requests/_internal_utils.py,sha256=TH2NEyyYmPx9cV5HPzrHR4XdxKuW0skkD4eDXcbZgf8,1542
586
+ pip/_vendor/requests/_types.py,sha256=0G33n1SiecDMP67FlsRGJG1a0U7f1SnrMo3vvWKkSok,5838
587
+ pip/_vendor/requests/adapters.py,sha256=5kSKhXlJuR_enrOjd3khSGpRBj1WqCh08Qssu0CEZ8M,28208
588
+ pip/_vendor/requests/api.py,sha256=TRVICsBG8Ikgl5joZQR270oo6-b4G0AHWPjvQuxrVQk,7152
589
+ pip/_vendor/requests/auth.py,sha256=6TlRpVLUw8X9m4Sl4dSbA8qrpHI8T_ES2mBTYA7IWmU,12233
590
+ pip/_vendor/requests/certs.py,sha256=eD1G0RoMZ3kA0lydkw7oo0lmcKqvD1hhz6yOlgSKm8w,442
591
+ pip/_vendor/requests/compat.py,sha256=1UheFGomceWe7aysgboYWxcEOH_HpQFmKhIyPiAanog,2035
592
+ pip/_vendor/requests/cookies.py,sha256=ChzmFA8rlCBSLFCA41bmifp5bCUi9VyhCCb17Y4Kcjw,21549
593
+ pip/_vendor/requests/exceptions.py,sha256=Am6y4ncoBptpmesOjRxc5iiuBDYjx3UN1oRVBlNgRyE,4576
594
+ pip/_vendor/requests/help.py,sha256=TVWejkCROwKexHHB44KCZSr-c0o5XakNL7LT1UJlRy8,4114
595
+ pip/_vendor/requests/hooks.py,sha256=69igJHXTGg5HOo9VPpUB_0NkW5VjiFrVKETnpj8Ndqs,1138
596
+ pip/_vendor/requests/models.py,sha256=99d7WF4pR35NHo9jrbGiBocZ3LCMsloVU0DAcQ49x3Q,41848
597
+ pip/_vendor/requests/packages.py,sha256=_ZQDCJTJ8SP3kVWunSqBsRZNPzj2c1WFVqbdr08pz3U,1057
598
+ pip/_vendor/requests/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
599
+ pip/_vendor/requests/sessions.py,sha256=lvuzC7vwalmlJo0TtXiFFJdWqj8xaVtcFeQd17svZ6Y,34248
600
+ pip/_vendor/requests/status_codes.py,sha256=GVD0fInPGAGXh-B9jOSPZtazjmIvfZTXCpAkf-5sBA4,4351
601
+ pip/_vendor/requests/structures.py,sha256=upRgw5B48l5vHSokrJQaxvjS7pcZf6jI0MJi2KHmegI,4134
602
+ pip/_vendor/requests/utils.py,sha256=u7MICyzQTvfUa3asg9nBvcrnhSIPEc6qhJSxiGGwTOk,36334
603
+ pip/_vendor/resolvelib/LICENSE,sha256=84j9OMrRMRLB3A9mm76A5_hFQe26-3LzAw0sp2QsPJ0,751
604
+ pip/_vendor/resolvelib/__init__.py,sha256=yoX-d4STvwGGCiQRE5cJC9Cter69SgVgqClxOCvSP7M,541
605
+ pip/_vendor/resolvelib/__pycache__/__init__.cpython-314.pyc,,
606
+ pip/_vendor/resolvelib/__pycache__/providers.cpython-314.pyc,,
607
+ pip/_vendor/resolvelib/__pycache__/reporters.cpython-314.pyc,,
608
+ pip/_vendor/resolvelib/__pycache__/structs.cpython-314.pyc,,
609
+ pip/_vendor/resolvelib/providers.py,sha256=pIWJbIdJJ9GFtNbtwTH0Ia43Vj6hYCEJj2DOLue15FM,8914
610
+ pip/_vendor/resolvelib/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
611
+ pip/_vendor/resolvelib/reporters.py,sha256=pNJf4nFxLpAeKxlBUi2GEj0a2Ij1nikY0UabTKXesT4,2037
612
+ pip/_vendor/resolvelib/resolvers/__init__.py,sha256=728M3EvmnPbVXS7ExXlv2kMu6b7wEsoPutEfl-uVk_I,640
613
+ pip/_vendor/resolvelib/resolvers/__pycache__/__init__.cpython-314.pyc,,
614
+ pip/_vendor/resolvelib/resolvers/__pycache__/abstract.cpython-314.pyc,,
615
+ pip/_vendor/resolvelib/resolvers/__pycache__/criterion.cpython-314.pyc,,
616
+ pip/_vendor/resolvelib/resolvers/__pycache__/exceptions.cpython-314.pyc,,
617
+ pip/_vendor/resolvelib/resolvers/__pycache__/resolution.cpython-314.pyc,,
618
+ pip/_vendor/resolvelib/resolvers/abstract.py,sha256=CNeQPnpAudY77nmzOkONSmAgRlzIf06X-X9mvRYODms,1543
619
+ pip/_vendor/resolvelib/resolvers/criterion.py,sha256=lcmZGv5sKHOnFD_RzZwvlGSj19MeA-5rCMpdf2Sgw7Y,1768
620
+ pip/_vendor/resolvelib/resolvers/exceptions.py,sha256=ln_jaQtgLlRUSFY627yiHG2gD7AgaXzRKaElFVh7fDQ,1768
621
+ pip/_vendor/resolvelib/resolvers/resolution.py,sha256=3J_zkW-sD3EY-BlNXjyln__njpyH5n0UZJT6uV7CheA,24212
622
+ pip/_vendor/resolvelib/structs.py,sha256=pu-EJiR2IBITr2SQeNPRa0rXhjlStfmO_GEgAhr3004,6420
623
+ pip/_vendor/rich/LICENSE,sha256=3u18F6QxgVgZCj6iOcyHmlpQJxzruYrnAl9I--WNyhU,1056
624
+ pip/_vendor/rich/__init__.py,sha256=dRxjIL-SbFVY0q3IjSMrfgBTHrm1LZDgLOygVBwiYZc,6090
625
+ pip/_vendor/rich/__main__.py,sha256=e_aVC-tDzarWQW9SuZMuCgBr6ODV_iDNV2Wh2xkxOlw,7896
626
+ pip/_vendor/rich/__pycache__/__init__.cpython-314.pyc,,
627
+ pip/_vendor/rich/__pycache__/__main__.cpython-314.pyc,,
628
+ pip/_vendor/rich/__pycache__/_cell_widths.cpython-314.pyc,,
629
+ pip/_vendor/rich/__pycache__/_emoji_codes.cpython-314.pyc,,
630
+ pip/_vendor/rich/__pycache__/_emoji_replace.cpython-314.pyc,,
631
+ pip/_vendor/rich/__pycache__/_export_format.cpython-314.pyc,,
632
+ pip/_vendor/rich/__pycache__/_extension.cpython-314.pyc,,
633
+ pip/_vendor/rich/__pycache__/_fileno.cpython-314.pyc,,
634
+ pip/_vendor/rich/__pycache__/_inspect.cpython-314.pyc,,
635
+ pip/_vendor/rich/__pycache__/_log_render.cpython-314.pyc,,
636
+ pip/_vendor/rich/__pycache__/_loop.cpython-314.pyc,,
637
+ pip/_vendor/rich/__pycache__/_null_file.cpython-314.pyc,,
638
+ pip/_vendor/rich/__pycache__/_palettes.cpython-314.pyc,,
639
+ pip/_vendor/rich/__pycache__/_pick.cpython-314.pyc,,
640
+ pip/_vendor/rich/__pycache__/_ratio.cpython-314.pyc,,
641
+ pip/_vendor/rich/__pycache__/_spinners.cpython-314.pyc,,
642
+ pip/_vendor/rich/__pycache__/_stack.cpython-314.pyc,,
643
+ pip/_vendor/rich/__pycache__/_timer.cpython-314.pyc,,
644
+ pip/_vendor/rich/__pycache__/_win32_console.cpython-314.pyc,,
645
+ pip/_vendor/rich/__pycache__/_windows.cpython-314.pyc,,
646
+ pip/_vendor/rich/__pycache__/_windows_renderer.cpython-314.pyc,,
647
+ pip/_vendor/rich/__pycache__/_wrap.cpython-314.pyc,,
648
+ pip/_vendor/rich/__pycache__/abc.cpython-314.pyc,,
649
+ pip/_vendor/rich/__pycache__/align.cpython-314.pyc,,
650
+ pip/_vendor/rich/__pycache__/ansi.cpython-314.pyc,,
651
+ pip/_vendor/rich/__pycache__/bar.cpython-314.pyc,,
652
+ pip/_vendor/rich/__pycache__/box.cpython-314.pyc,,
653
+ pip/_vendor/rich/__pycache__/cells.cpython-314.pyc,,
654
+ pip/_vendor/rich/__pycache__/color.cpython-314.pyc,,
655
+ pip/_vendor/rich/__pycache__/color_triplet.cpython-314.pyc,,
656
+ pip/_vendor/rich/__pycache__/columns.cpython-314.pyc,,
657
+ pip/_vendor/rich/__pycache__/console.cpython-314.pyc,,
658
+ pip/_vendor/rich/__pycache__/constrain.cpython-314.pyc,,
659
+ pip/_vendor/rich/__pycache__/containers.cpython-314.pyc,,
660
+ pip/_vendor/rich/__pycache__/control.cpython-314.pyc,,
661
+ pip/_vendor/rich/__pycache__/default_styles.cpython-314.pyc,,
662
+ pip/_vendor/rich/__pycache__/diagnose.cpython-314.pyc,,
663
+ pip/_vendor/rich/__pycache__/emoji.cpython-314.pyc,,
664
+ pip/_vendor/rich/__pycache__/errors.cpython-314.pyc,,
665
+ pip/_vendor/rich/__pycache__/file_proxy.cpython-314.pyc,,
666
+ pip/_vendor/rich/__pycache__/filesize.cpython-314.pyc,,
667
+ pip/_vendor/rich/__pycache__/highlighter.cpython-314.pyc,,
668
+ pip/_vendor/rich/__pycache__/json.cpython-314.pyc,,
669
+ pip/_vendor/rich/__pycache__/jupyter.cpython-314.pyc,,
670
+ pip/_vendor/rich/__pycache__/layout.cpython-314.pyc,,
671
+ pip/_vendor/rich/__pycache__/live.cpython-314.pyc,,
672
+ pip/_vendor/rich/__pycache__/live_render.cpython-314.pyc,,
673
+ pip/_vendor/rich/__pycache__/logging.cpython-314.pyc,,
674
+ pip/_vendor/rich/__pycache__/markup.cpython-314.pyc,,
675
+ pip/_vendor/rich/__pycache__/measure.cpython-314.pyc,,
676
+ pip/_vendor/rich/__pycache__/padding.cpython-314.pyc,,
677
+ pip/_vendor/rich/__pycache__/pager.cpython-314.pyc,,
678
+ pip/_vendor/rich/__pycache__/palette.cpython-314.pyc,,
679
+ pip/_vendor/rich/__pycache__/panel.cpython-314.pyc,,
680
+ pip/_vendor/rich/__pycache__/pretty.cpython-314.pyc,,
681
+ pip/_vendor/rich/__pycache__/progress.cpython-314.pyc,,
682
+ pip/_vendor/rich/__pycache__/progress_bar.cpython-314.pyc,,
683
+ pip/_vendor/rich/__pycache__/prompt.cpython-314.pyc,,
684
+ pip/_vendor/rich/__pycache__/protocol.cpython-314.pyc,,
685
+ pip/_vendor/rich/__pycache__/region.cpython-314.pyc,,
686
+ pip/_vendor/rich/__pycache__/repr.cpython-314.pyc,,
687
+ pip/_vendor/rich/__pycache__/rule.cpython-314.pyc,,
688
+ pip/_vendor/rich/__pycache__/scope.cpython-314.pyc,,
689
+ pip/_vendor/rich/__pycache__/screen.cpython-314.pyc,,
690
+ pip/_vendor/rich/__pycache__/segment.cpython-314.pyc,,
691
+ pip/_vendor/rich/__pycache__/spinner.cpython-314.pyc,,
692
+ pip/_vendor/rich/__pycache__/status.cpython-314.pyc,,
693
+ pip/_vendor/rich/__pycache__/style.cpython-314.pyc,,
694
+ pip/_vendor/rich/__pycache__/styled.cpython-314.pyc,,
695
+ pip/_vendor/rich/__pycache__/syntax.cpython-314.pyc,,
696
+ pip/_vendor/rich/__pycache__/table.cpython-314.pyc,,
697
+ pip/_vendor/rich/__pycache__/terminal_theme.cpython-314.pyc,,
698
+ pip/_vendor/rich/__pycache__/text.cpython-314.pyc,,
699
+ pip/_vendor/rich/__pycache__/theme.cpython-314.pyc,,
700
+ pip/_vendor/rich/__pycache__/themes.cpython-314.pyc,,
701
+ pip/_vendor/rich/__pycache__/traceback.cpython-314.pyc,,
702
+ pip/_vendor/rich/__pycache__/tree.cpython-314.pyc,,
703
+ pip/_vendor/rich/_cell_widths.py,sha256=fbmeyetEdHjzE_Vx2l1uK7tnPOhMs2X1lJfO3vsKDpA,10209
704
+ pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235
705
+ pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064
706
+ pip/_vendor/rich/_export_format.py,sha256=RI08pSrm5tBSzPMvnbTqbD9WIalaOoN5d4M1RTmLq1Y,2128
707
+ pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265
708
+ pip/_vendor/rich/_fileno.py,sha256=HWZxP5C2ajMbHryvAQZseflVfQoGzsKOHzKGsLD8ynQ,799
709
+ pip/_vendor/rich/_inspect.py,sha256=ROT0PLC2GMWialWZkqJIjmYq7INRijQQkoSokWTaAiI,9656
710
+ pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225
711
+ pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236
712
+ pip/_vendor/rich/_null_file.py,sha256=ADGKp1yt-k70FMKV6tnqCqecB-rSJzp-WQsD7LPL-kg,1394
713
+ pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063
714
+ pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423
715
+ pip/_vendor/rich/_ratio.py,sha256=IOtl78sQCYZsmHyxhe45krkb68u9xVz7zFsXVJD-b2Y,5325
716
+ pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919
717
+ pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351
718
+ pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417
719
+ pip/_vendor/rich/_win32_console.py,sha256=BSaDRIMwBLITn_m0mTRLPqME5q-quGdSMuYMpYeYJwc,22755
720
+ pip/_vendor/rich/_windows.py,sha256=aBwaD_S56SbgopIvayVmpk0Y28uwY2C5Bab1wl3Bp-I,1925
721
+ pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783
722
+ pip/_vendor/rich/_wrap.py,sha256=FlSsom5EX0LVkA3KWy34yHnCfLtqX-ZIepXKh-70rpc,3404
723
+ pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890
724
+ pip/_vendor/rich/align.py,sha256=dg-7uY0ukMLLlUEsBDRLva22_sQgIJD4BK0dmZHFHug,10324
725
+ pip/_vendor/rich/ansi.py,sha256=Avs1LHbSdcyOvDOdpELZUoULcBiYewY76eNBp6uFBhs,6921
726
+ pip/_vendor/rich/bar.py,sha256=ldbVHOzKJOnflVNuv1xS7g6dLX2E3wMnXkdPbpzJTcs,3263
727
+ pip/_vendor/rich/box.py,sha256=kmavBc_dn73L_g_8vxWSwYJD2uzBXOUFTtJOfpbczcM,10686
728
+ pip/_vendor/rich/cells.py,sha256=KrQkj5-LghCCpJLSNQIyAZjndc4bnEqOEmi5YuZ9UCY,5130
729
+ pip/_vendor/rich/color.py,sha256=3HSULVDj7qQkXUdFWv78JOiSZzfy5y1nkcYhna296V0,18211
730
+ pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054
731
+ pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131
732
+ pip/_vendor/rich/console.py,sha256=t9azZpmRMVU5cphVBZSShNsmBxd2-IAWcTTlhor-E1s,100849
733
+ pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288
734
+ pip/_vendor/rich/containers.py,sha256=c_56TxcedGYqDepHBMTuZdUIijitAQgnox-Qde0Z1qo,5502
735
+ pip/_vendor/rich/control.py,sha256=EUTSUFLQbxY6Zmo_sdM-5Ls323vIHTBfN8TPulqeHUY,6487
736
+ pip/_vendor/rich/default_styles.py,sha256=khQFqqaoDs3bprMqWpHw8nO5UpG2DN6QtuTd6LzZwYc,8257
737
+ pip/_vendor/rich/diagnose.py,sha256=fJl1TItRn19gGwouqTg-8zPUW3YqQBqGltrfPQs1H9w,1025
738
+ pip/_vendor/rich/emoji.py,sha256=Wd4bQubZdSy6-PyrRQNuMHtn2VkljK9uPZPVlu2cmx0,2367
739
+ pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642
740
+ pip/_vendor/rich/file_proxy.py,sha256=Tl9THMDZ-Pk5Wm8sI1gGg_U5DhusmxD-FZ0fUbcU0W0,1683
741
+ pip/_vendor/rich/filesize.py,sha256=_iz9lIpRgvW7MNSeCZnLg-HwzbP4GETg543WqD8SFs0,2484
742
+ pip/_vendor/rich/highlighter.py,sha256=G_sn-8DKjM1sEjLG_oc4ovkWmiUpWvj8bXi0yed2LnY,9586
743
+ pip/_vendor/rich/json.py,sha256=vVEoKdawoJRjAFayPwXkMBPLy7RSTs-f44wSQDR2nJ0,5031
744
+ pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252
745
+ pip/_vendor/rich/layout.py,sha256=ajkSFAtEVv9EFTcFs-w4uZfft7nEXhNzL7ZVdgrT5rI,14004
746
+ pip/_vendor/rich/live.py,sha256=tF3ukAAJZ_N2ZbGclqZ-iwLoIoZ8f0HHUz79jAyJqj8,15180
747
+ pip/_vendor/rich/live_render.py,sha256=It_39YdzrBm8o3LL0kaGorPFg-BfZWAcrBjLjFokbx4,3521
748
+ pip/_vendor/rich/logging.py,sha256=5KaPPSMP9FxcXPBcKM4cGd_zW78PMgf-YbMVnvfSw0o,12468
749
+ pip/_vendor/rich/markup.py,sha256=3euGKP5s41NCQwaSjTnJxus5iZMHjxpIM0W6fCxra38,8451
750
+ pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305
751
+ pip/_vendor/rich/padding.py,sha256=KVEI3tOwo9sgK1YNSuH__M1_jUWmLZwRVV_KmOtVzyM,4908
752
+ pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828
753
+ pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396
754
+ pip/_vendor/rich/panel.py,sha256=9sQl00hPIqH5G2gALQo4NepFwpP0k9wT-s_gOms5pIc,11157
755
+ pip/_vendor/rich/pretty.py,sha256=gy3S72u4FRg2ytoo7N1ZDWDIvB4unbzd5iUGdgm-8fc,36391
756
+ pip/_vendor/rich/progress.py,sha256=CUc2lkU-X59mVdGfjMCBkZeiGPL3uxdONjhNJF2T7wY,60408
757
+ pip/_vendor/rich/progress_bar.py,sha256=mZTPpJUwcfcdgQCTTz3kyY-fc79ddLwtx6Ghhxfo064,8162
758
+ pip/_vendor/rich/prompt.py,sha256=l0RhQU-0UVTV9e08xW1BbIj0Jq2IXyChX4lC0lFNzt4,12447
759
+ pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391
760
+ pip/_vendor/rich/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
761
+ pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166
762
+ pip/_vendor/rich/repr.py,sha256=5MZJZmONgC6kud-QW-_m1okXwL2aR6u6y-pUcUCJz28,4431
763
+ pip/_vendor/rich/rule.py,sha256=0fNaS_aERa3UMRc3T5WMpN_sumtDxfaor2y3of1ftBk,4602
764
+ pip/_vendor/rich/scope.py,sha256=TMUU8qo17thyqQCPqjDLYpg_UU1k5qVd-WwiJvnJVas,2843
765
+ pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591
766
+ pip/_vendor/rich/segment.py,sha256=otnKeKGEV-WRlQVosfJVeFDcDxAKHpvJ_hLzSu5lumM,24743
767
+ pip/_vendor/rich/spinner.py,sha256=onIhpKlljRHppTZasxO8kXgtYyCHUkpSgKglRJ3o51g,4214
768
+ pip/_vendor/rich/status.py,sha256=kkPph3YeAZBo-X-4wPp8gTqZyU466NLwZBA4PZTTewo,4424
769
+ pip/_vendor/rich/style.py,sha256=W9Ccy8Py8lNICtlfcp-ryzMTuQaGxAU3av7-g5fHu0s,26990
770
+ pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258
771
+ pip/_vendor/rich/syntax.py,sha256=eDKIRwl--eZ0Lwo2da2RRtfutXGavrJO61Cl5OkS59U,36371
772
+ pip/_vendor/rich/table.py,sha256=ZmT7V7MMCOYKw7TGY9SZLyYDf6JdM-WVf07FdVuVhTI,40049
773
+ pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370
774
+ pip/_vendor/rich/text.py,sha256=AO7JPCz6-gaN1thVLXMBntEmDPVYFgFNG1oM61_sanU,47552
775
+ pip/_vendor/rich/theme.py,sha256=oNyhXhGagtDlbDye3tVu3esWOWk0vNkuxFw-_unlaK0,3771
776
+ pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102
777
+ pip/_vendor/rich/traceback.py,sha256=c0WmB_L04_UfZbLaoH982_U_s7eosxKMUiAVmDPdRYU,35861
778
+ pip/_vendor/rich/tree.py,sha256=yWnQ6rAvRGJ3qZGqBrxS2SW2TKBTNrP0SdY8QxOFPuw,9451
779
+ pip/_vendor/tomli/LICENSE,sha256=uAgWsNUwuKzLTCIReDeQmEpuO2GSLCte6S8zcqsnQv4,1072
780
+ pip/_vendor/tomli/__init__.py,sha256=nrBC18DbXRTCFo7ElG5BDeWpHJzOhokvXk215GM8Z2I,314
781
+ pip/_vendor/tomli/__pycache__/__init__.cpython-314.pyc,,
782
+ pip/_vendor/tomli/__pycache__/_parser.cpython-314.pyc,,
783
+ pip/_vendor/tomli/__pycache__/_re.cpython-314.pyc,,
784
+ pip/_vendor/tomli/__pycache__/_types.cpython-314.pyc,,
785
+ pip/_vendor/tomli/_parser.py,sha256=pBIjTIa_cQs2HglDJ2lh8OJfptfDa6eg5-7Iej4BjHs,26440
786
+ pip/_vendor/tomli/_re.py,sha256=oSNZ_ilFI6chEuQ01YRSoUydBQr_okF_mSdHTkFmv90,3396
787
+ pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254
788
+ pip/_vendor/tomli/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
789
+ pip/_vendor/tomli_w/LICENSE,sha256=uAgWsNUwuKzLTCIReDeQmEpuO2GSLCte6S8zcqsnQv4,1072
790
+ pip/_vendor/tomli_w/__init__.py,sha256=0F8yDtXx3Uunhm874KrAcP76srsM98y7WyHQwCulZbo,169
791
+ pip/_vendor/tomli_w/__pycache__/__init__.cpython-314.pyc,,
792
+ pip/_vendor/tomli_w/__pycache__/_writer.cpython-314.pyc,,
793
+ pip/_vendor/tomli_w/_writer.py,sha256=dsifFS2xYf1i76mmRyfz9y125xC7Z_HQ845ZKhJsYXs,6961
794
+ pip/_vendor/tomli_w/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
795
+ pip/_vendor/truststore/LICENSE,sha256=M757fo-k_Rmxdg4ajtimaL2rhSyRtpLdQUJLy3Jan8o,1086
796
+ pip/_vendor/truststore/__init__.py,sha256=Bu7kqkmpunhLsj5xCu8gT_25ktoPXcSnwe8VHk1GmJo,1320
797
+ pip/_vendor/truststore/__pycache__/__init__.cpython-314.pyc,,
798
+ pip/_vendor/truststore/__pycache__/_api.cpython-314.pyc,,
799
+ pip/_vendor/truststore/__pycache__/_macos.cpython-314.pyc,,
800
+ pip/_vendor/truststore/__pycache__/_openssl.cpython-314.pyc,,
801
+ pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-314.pyc,,
802
+ pip/_vendor/truststore/__pycache__/_windows.cpython-314.pyc,,
803
+ pip/_vendor/truststore/_api.py,sha256=CYJCV5BTfttZYfqY3movdMBE-8az7uhET_LYbKT2Nn4,11413
804
+ pip/_vendor/truststore/_macos.py,sha256=nZlLkOmszUE0g6ryRwBVGY5COzPyudcsiJtDWarM5LQ,20503
805
+ pip/_vendor/truststore/_openssl.py,sha256=zB-SQvJydks7tQ0yIwrP6GD3fQNSSaPiq7zw4yF5T40,2412
806
+ pip/_vendor/truststore/_ssl_constants.py,sha256=NUD4fVKdSD02ri7-db0tnO0VqLP9aHuzmStcW7tAl08,1130
807
+ pip/_vendor/truststore/_windows.py,sha256=rAHyKYD8M7t-bXfG8VgOVa3TpfhVhbt4rZQlO45YuP8,17993
808
+ pip/_vendor/truststore/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
809
+ pip/_vendor/urllib3/LICENSE.txt,sha256=Ew46ZNX91dCWp1JpRjSn2d8oRGnehuVzIQAmgEHj1oY,1093
810
+ pip/_vendor/urllib3/__init__.py,sha256=JMo1tg1nIV1AeJ2vENC_Txfl0e5h6Gzl9DGVk1rWRbo,6979
811
+ pip/_vendor/urllib3/__pycache__/__init__.cpython-314.pyc,,
812
+ pip/_vendor/urllib3/__pycache__/_base_connection.cpython-314.pyc,,
813
+ pip/_vendor/urllib3/__pycache__/_collections.cpython-314.pyc,,
814
+ pip/_vendor/urllib3/__pycache__/_request_methods.cpython-314.pyc,,
815
+ pip/_vendor/urllib3/__pycache__/_version.cpython-314.pyc,,
816
+ pip/_vendor/urllib3/__pycache__/connection.cpython-314.pyc,,
817
+ pip/_vendor/urllib3/__pycache__/connectionpool.cpython-314.pyc,,
818
+ pip/_vendor/urllib3/__pycache__/exceptions.cpython-314.pyc,,
819
+ pip/_vendor/urllib3/__pycache__/fields.cpython-314.pyc,,
820
+ pip/_vendor/urllib3/__pycache__/filepost.cpython-314.pyc,,
821
+ pip/_vendor/urllib3/__pycache__/poolmanager.cpython-314.pyc,,
822
+ pip/_vendor/urllib3/__pycache__/response.cpython-314.pyc,,
823
+ pip/_vendor/urllib3/_base_connection.py,sha256=HzcSEHexgDrRUr60jNniB2KQjdw97SedD5luRfHtCXg,5580
824
+ pip/_vendor/urllib3/_collections.py,sha256=aOVm2mKilvuvT1efAGtkA7pi65C1NC3HJfpFxvYBS8A,17522
825
+ pip/_vendor/urllib3/_request_methods.py,sha256=gCeF85SO_UU4WoPwYHIoz_tw-eM_EVOkLFp8OFsC7DA,9931
826
+ pip/_vendor/urllib3/_version.py,sha256=-gMrKhsPiOj0XzUezVFa59d1S6QgQiKgQT5gGgyM8-w,520
827
+ pip/_vendor/urllib3/connection.py,sha256=Zos3qxKDW9-GQ6aVqfBQVRM5soB0IjHxY_xXWpJaFTI,42786
828
+ pip/_vendor/urllib3/connectionpool.py,sha256=sGFnddXYwlx7KC4JCP1gKvdNGLNK-YTCJDdGACGj3Y8,44164
829
+ pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
830
+ pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-314.pyc,,
831
+ pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-314.pyc,,
832
+ pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-314.pyc,,
833
+ pip/_vendor/urllib3/contrib/emscripten/__init__.py,sha256=ZruXaWKVzAEJdqNH3NEh0mrHrw--2VZYb0zX0RonNZA,870
834
+ pip/_vendor/urllib3/contrib/emscripten/__pycache__/__init__.cpython-314.pyc,,
835
+ pip/_vendor/urllib3/contrib/emscripten/__pycache__/connection.cpython-314.pyc,,
836
+ pip/_vendor/urllib3/contrib/emscripten/__pycache__/fetch.cpython-314.pyc,,
837
+ pip/_vendor/urllib3/contrib/emscripten/__pycache__/request.cpython-314.pyc,,
838
+ pip/_vendor/urllib3/contrib/emscripten/__pycache__/response.cpython-314.pyc,,
839
+ pip/_vendor/urllib3/contrib/emscripten/connection.py,sha256=giElsBoUsKVURbZzb8GCrJmqW23Xnvj2aNyQVF42slg,8960
840
+ pip/_vendor/urllib3/contrib/emscripten/emscripten_fetch_worker.js,sha256=z1k3zZ4_hDKd3-tN7wzz8LHjHC2pxN_uu8B3k9D9A3c,3677
841
+ pip/_vendor/urllib3/contrib/emscripten/fetch.py,sha256=5xcd--viFxZd2nBy0aK73dtJ9Tsh1yYZU_SUXwnwibk,23520
842
+ pip/_vendor/urllib3/contrib/emscripten/request.py,sha256=mL28szy1KvE3NJhWor5jNmarp8gwplDU-7gwGZY5g0Q,566
843
+ pip/_vendor/urllib3/contrib/emscripten/response.py,sha256=CDpY0GFoluR3IxECkM2gH5uDfYDM0EL1FWr7B76wtgM,9719
844
+ pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=Pi_qwvdl83tNpuj1k5pCpP_gmxlk4BfFrTlAeg-qZ_U,19760
845
+ pip/_vendor/urllib3/contrib/socks.py,sha256=rSuklfha4-vto-8qSLhSPmf5lmRPIYuqdAxKe9bg2RA,7639
846
+ pip/_vendor/urllib3/exceptions.py,sha256=hQPHoqo4yw46esNSVkciVQXVUgAxWAglsh6MbyQta-Q,9945
847
+ pip/_vendor/urllib3/fields.py,sha256=aGLFAVZpVU-FbJlllve4Ahg0-pH9ZZBQ2Iz7lfpkjkM,10801
848
+ pip/_vendor/urllib3/filepost.py,sha256=U8eNZ-mpKKHhrlbHEEiTxxgK16IejhEa7uz42yqA_dI,2388
849
+ pip/_vendor/urllib3/http2/__init__.py,sha256=xzrASH7R5ANRkPJOot5lGnATOq3KKuyXzI42rcnwmqs,1741
850
+ pip/_vendor/urllib3/http2/__pycache__/__init__.cpython-314.pyc,,
851
+ pip/_vendor/urllib3/http2/__pycache__/connection.cpython-314.pyc,,
852
+ pip/_vendor/urllib3/http2/__pycache__/probe.cpython-314.pyc,,
853
+ pip/_vendor/urllib3/http2/connection.py,sha256=bHMH6fNvatwXPrKqrcn74yA3pUWcqPDppnK1LcKCbP8,12578
854
+ pip/_vendor/urllib3/http2/probe.py,sha256=nnAkqbhAakOiF75rz7W0udZ38Eeh_uD8fjV74N73FEI,3014
855
+ pip/_vendor/urllib3/poolmanager.py,sha256=grIrETG1rgHYBaQau1yN4xxfK8U9CKVRYmwBXW_kdSo,23929
856
+ pip/_vendor/urllib3/py.typed,sha256=UaCuPFa3H8UAakbt-5G8SPacldTOGvJv18pPjUJ5gDY,93
857
+ pip/_vendor/urllib3/response.py,sha256=DzBM-dzl6x_h2EZGc9iw0gbOkQ36bolC7WESH4TurH8,53031
858
+ pip/_vendor/urllib3/util/__init__.py,sha256=-qeS0QceivazvBEKDNFCAI-6ACcdDOE4TMvo7SLNlAQ,1001
859
+ pip/_vendor/urllib3/util/__pycache__/__init__.cpython-314.pyc,,
860
+ pip/_vendor/urllib3/util/__pycache__/connection.cpython-314.pyc,,
861
+ pip/_vendor/urllib3/util/__pycache__/proxy.cpython-314.pyc,,
862
+ pip/_vendor/urllib3/util/__pycache__/request.cpython-314.pyc,,
863
+ pip/_vendor/urllib3/util/__pycache__/response.cpython-314.pyc,,
864
+ pip/_vendor/urllib3/util/__pycache__/retry.cpython-314.pyc,,
865
+ pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-314.pyc,,
866
+ pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-314.pyc,,
867
+ pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-314.pyc,,
868
+ pip/_vendor/urllib3/util/__pycache__/timeout.cpython-314.pyc,,
869
+ pip/_vendor/urllib3/util/__pycache__/url.cpython-314.pyc,,
870
+ pip/_vendor/urllib3/util/__pycache__/util.cpython-314.pyc,,
871
+ pip/_vendor/urllib3/util/__pycache__/wait.cpython-314.pyc,,
872
+ pip/_vendor/urllib3/util/connection.py,sha256=JjO722lzHlzLXPTkr9ZWBdhseXnMVjMSb1DJLVrXSnQ,4444
873
+ pip/_vendor/urllib3/util/proxy.py,sha256=seP8-Q5B6bB0dMtwPj-YcZZQ30vHuLqRu-tI0JZ2fzs,1148
874
+ pip/_vendor/urllib3/util/request.py,sha256=p9Ki9eo1tFBO-jqV_7KmmJ60RKqoY2r4ao0SmaHLyOs,8086
875
+ pip/_vendor/urllib3/util/response.py,sha256=vQE639uoEhj1vpjEdxu5lNIhJCSUZkd7pqllUI0BZOA,3374
876
+ pip/_vendor/urllib3/util/retry.py,sha256=2YnSX-_FecMShD61Mx5s68J0_btUHZrrc_BkFVRS1P4,19577
877
+ pip/_vendor/urllib3/util/ssl_.py,sha256=Oqe3rIhUU3e3GVgZob2hxmR8Q0ZDhrhESPlPP_GLaVQ,17742
878
+ pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ft44KJzTzGMmKff_ZXP91li2V4WhmvEy16PKBcv4vZk,5479
879
+ pip/_vendor/urllib3/util/ssltransport.py,sha256=Ez4O8pR_vT8dan_FvqBYS6dgDfBXEMfVfrzcdUoWfi4,8847
880
+ pip/_vendor/urllib3/util/timeout.py,sha256=vsUJRpO0nfKk-y1OKlgFGY1ONJGPgkaZ7B7kruEpVYw,10363
881
+ pip/_vendor/urllib3/util/url.py,sha256=PEDQMypidude0nAZctLLiFK9epN-LPnSH7KpOLLwqH0,15256
882
+ pip/_vendor/urllib3/util/util.py,sha256=j3lbZK1jPyiwD34T8IgJzdWEZVT-4E-0vYIJi9UjeNA,1146
883
+ pip/_vendor/urllib3/util/wait.py,sha256=_ph8IrUR3sqPqi0OopQgJUlH4wzkGeM5CiyA7XGGtmI,4423
884
+ pip/_vendor/vendor.txt,sha256=PfDJYBv6Lg3KI8xXSk-QCk1_2tBgqyA_q4NUNQ7ZMyA,317
885
+ pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/REQUESTED ADDED
File without changes
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: flit 3.12.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/entry_points.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ [console_scripts]
2
+ pip=pip._internal.cli.main:main
3
+ pip3=pip._internal.cli.main:main
4
+
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/AUTHORS.txt ADDED
@@ -0,0 +1,888 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @Switch01
2
+ A_Rog
3
+ Aakanksha Agrawal
4
+ Aarni Koskela
5
+ abdul rawoof
6
+ Abdul Rawoof Khan
7
+ Abhinav Sagar
8
+ ABHYUDAY PRATAP SINGH
9
+ abs51295
10
+ AceGentile
11
+ Adam Chainz
12
+ Adam Tse
13
+ Adam Turner
14
+ Adam Wentz
15
+ admin
16
+ Adolfo Ochagavía
17
+ Adrien Morison
18
+ Agus
19
+ ahayrapetyan
20
+ Ahilya
21
+ AinsworthK
22
+ Akash Srivastava
23
+ Alan Yee
24
+ Albert Tugushev
25
+ Albert-Guan
26
+ albertg
27
+ Alberto Sottile
28
+ Aleks Bunin
29
+ Ales Erjavec
30
+ Alessandro Molina
31
+ Alethea Flowers
32
+ Alex Gaynor
33
+ Alex Grönholm
34
+ Alex Hedges
35
+ Alex Loosley
36
+ Alex Morega
37
+ Alex Stachowiak
38
+ Alexander Regueiro
39
+ Alexander Shtyrov
40
+ Alexandre Conrad
41
+ Alexey Popravka
42
+ Aleš Erjavec
43
+ Alli
44
+ Aman
45
+ Ami Fischman
46
+ Ananya Maiti
47
+ Anatoly Techtonik
48
+ Anders Kaseorg
49
+ Andre Aguiar
50
+ Andrea Corna
51
+ Andreas Lutro
52
+ Andrei Geacar
53
+ Andrew Gaul
54
+ Andrew Shymanel
55
+ Andrey Bienkowski
56
+ Andrey Bulgakov
57
+ Andrés Delfino
58
+ Andy Freeland
59
+ Andy Kluger
60
+ Ani Hayrapetyan
61
+ Aniruddha Basak
62
+ Anish Tambe
63
+ Anrs Hu
64
+ Anthony Sottile
65
+ Antoine Lambert
66
+ Antoine Musso
67
+ Anton Ovchinnikov
68
+ Anton Patrushev
69
+ Anton Zelenov
70
+ Antonio Alvarado Hernandez
71
+ Antony Lee
72
+ Antti Kaihola
73
+ Anubhav Patel
74
+ Anudit Nagar
75
+ Anuj Godase
76
+ AQNOUCH Mohammed
77
+ AraHaan
78
+ Aren Siekmeier
79
+ arena
80
+ arenasys
81
+ Arindam Choudhury
82
+ Armin Ronacher
83
+ Arnon Yaari
84
+ Artem
85
+ Arun Babu Neelicattu
86
+ Ashley Manton
87
+ Ashwin Ramaswami
88
+ atse
89
+ Atsushi Odagiri
90
+ Avinash Karhana
91
+ Avner Cohen
92
+ Awit (Ah-Wit) Ghirmai
93
+ Baptiste Mispelon
94
+ Barney Gale
95
+ barneygale
96
+ Bartek Ogryczak
97
+ Bastian Venthur
98
+ Ben Bodenmiller
99
+ Ben Darnell
100
+ Ben Hoyt
101
+ Ben Mares
102
+ Ben Rosser
103
+ Bence Nagy
104
+ Benjamin Peterson
105
+ Benjamin VanEvery
106
+ Benoit Pierre
107
+ Berker Peksag
108
+ Bernard
109
+ Bernard Tyers
110
+ Bernardo B. Marques
111
+ Bernhard M. Wiedemann
112
+ Bertil Hatt
113
+ Bhavam Vidyarthi
114
+ Blazej Michalik
115
+ Bogdan Opanchuk
116
+ BorisZZZ
117
+ Brad Erickson
118
+ Bradley Ayers
119
+ Bradley Reynolds
120
+ Branch Vincent
121
+ Brandon L. Reiss
122
+ Brandt Bucher
123
+ Brannon Dorsey
124
+ Brett Randall
125
+ Brett Rosen
126
+ Brian Cristante
127
+ Brian Rosner
128
+ briantracy
129
+ BrownTruck
130
+ Bruno Oliveira
131
+ Bruno Renié
132
+ Bruno S
133
+ Bstrdsmkr
134
+ Buck Golemon
135
+ burrows
136
+ Bussonnier Matthias
137
+ bwoodsend
138
+ c22
139
+ Caleb Brown
140
+ Caleb Martinez
141
+ Calvin Smith
142
+ Carl Meyer
143
+ Carlos Liam
144
+ Carol Willing
145
+ Carter Thayer
146
+ Cass
147
+ Chandrasekhar Atina
148
+ Charlie Marsh
149
+ charwick
150
+ Chih-Hsuan Yen
151
+ Chris Brinker
152
+ Chris Hunt
153
+ Chris Jerdonek
154
+ Chris Kuehl
155
+ Chris Markiewicz
156
+ Chris McDonough
157
+ Chris Pawley
158
+ Chris Pryer
159
+ Chris Wolfe
160
+ Christian Clauss
161
+ Christian Heimes
162
+ Christian Oudard
163
+ Christoph Reiter
164
+ Christopher Hunt
165
+ Christopher Snyder
166
+ chrysle
167
+ cjc7373
168
+ Clark Boylan
169
+ Claudio Jolowicz
170
+ Clay McClure
171
+ Cody
172
+ Cody Soyland
173
+ Colin Watson
174
+ Collin Anderson
175
+ Connor Osborn
176
+ Cooper Lees
177
+ Cooper Ry Lees
178
+ Cory Benfield
179
+ Cory Wright
180
+ Craig Kerstiens
181
+ Cristian Sorinel
182
+ Cristina
183
+ Cristina Muñoz
184
+ ctg123
185
+ Curtis Doty
186
+ cytolentino
187
+ Daan De Meyer
188
+ Dale
189
+ Damian
190
+ Damian Quiroga
191
+ Damian Shaw
192
+ Dan Black
193
+ Dan Savilonis
194
+ Dan Sully
195
+ Dane Hillard
196
+ daniel
197
+ Daniel Collins
198
+ Daniel Hahler
199
+ Daniel Hollas
200
+ Daniel Holth
201
+ Daniel Jost
202
+ Daniel Katz
203
+ Daniel Shaulov
204
+ Daniele Esposti
205
+ Daniele Nicolodi
206
+ Daniele Procida
207
+ Daniil Konovalenko
208
+ Danny Hermes
209
+ Danny McClanahan
210
+ Darren Kavanagh
211
+ Dav Clark
212
+ Dave Abrahams
213
+ Dave Jones
214
+ David Aguilar
215
+ David Black
216
+ David Bordeynik
217
+ David Caro
218
+ David D Lowe
219
+ David Evans
220
+ David Hewitt
221
+ David Linke
222
+ David Poggi
223
+ David Poznik
224
+ David Pursehouse
225
+ David Runge
226
+ David Tucker
227
+ David Wales
228
+ Davidovich
229
+ Dayna Blackwell
230
+ ddelange
231
+ Deepak Sharma
232
+ Deepyaman Datta
233
+ Denis Roussel (ACSONE)
234
+ Denise Yu
235
+ dependabot[bot]
236
+ dereksz
237
+ derwolfe
238
+ Desetude
239
+ developer
240
+ Devesh Kumar
241
+ Devesh Kumar Singh
242
+ devsagul
243
+ Dewank Pant
244
+ Diego Caraballo
245
+ Diego Ramirez
246
+ DiegoCaraballo
247
+ Dimitri Merejkowsky
248
+ Dimitri Papadopoulos
249
+ Dimitri Papadopoulos Orfanos
250
+ Dirk Stolle
251
+ dkjsone
252
+ Dmitrii Sutiagin
253
+ Dmitry Gladkov
254
+ Dmitry Volodin
255
+ Domen Kožar
256
+ Dominic Davis-Foster
257
+ Donald Stufft
258
+ Dongweiming
259
+ doron zarhi
260
+ Dos Moonen
261
+ Douglas Thor
262
+ DrFeathers
263
+ Dustin Ingram
264
+ Dustin Rodrigues
265
+ Dwayne Bailey
266
+ Ed Morley
267
+ Edgar Ramírez
268
+ Edgar Ramírez Mondragón
269
+ Ee Durbin
270
+ Efflam Lemaillet
271
+ efflamlemaillet
272
+ Eitan Adler
273
+ ekristina
274
+ elainechan
275
+ Eli Schwartz
276
+ Elisha Hollander
277
+ Ellen Marie Dash
278
+ Emil Burzo
279
+ Emil Styrke
280
+ Emmanuel Arias
281
+ Endoh Takanao
282
+ enoch
283
+ Erdinc Mutlu
284
+ Eric Cousineau
285
+ Eric Gillingham
286
+ Eric Hanchrow
287
+ Eric Hopper
288
+ Erik M. Bray
289
+ Erik Rose
290
+ Erwin Janssen
291
+ Eugene Vereshchagin
292
+ everdimension
293
+ Federico
294
+ Felipe Peter
295
+ Felix Yan
296
+ fiber-space
297
+ Filip Kokosiński
298
+ Filipe Laíns
299
+ Finn Womack
300
+ finnagin
301
+ Flavio Amurrio
302
+ Florian Briand
303
+ Florian Rathgeber
304
+ Francesco
305
+ Francesco Montesano
306
+ Fredrik Orderud
307
+ Fredrik Roubert
308
+ Frost Ming
309
+ Gabriel Curio
310
+ Gabriel de Perthuis
311
+ Garry Polley
312
+ gavin
313
+ gdanielson
314
+ Gene Wood
315
+ Geoffrey Sneddon
316
+ George Margaritis
317
+ George Song
318
+ Georgi Valkov
319
+ Georgy Pchelkin
320
+ Gertjan van Zwieten
321
+ ghost
322
+ Giancarlo Cicellyn Comneno
323
+ Giftlin Rajaiah
324
+ gizmoguy1
325
+ gkdoc
326
+ Godefroid Chapelle
327
+ Gopinath M
328
+ GOTO Hayato
329
+ gousaiyang
330
+ gpiks
331
+ Greg Roodt
332
+ Greg Ward
333
+ Guido Diepen
334
+ Guilherme Espada
335
+ Guillaume Seguin
336
+ gutsytechster
337
+ Guy Rozendorn
338
+ Guy Tuval
339
+ gzpan123
340
+ Hanjun Kim
341
+ Hari Charan
342
+ Harsh Vardhan
343
+ Harsha Sai
344
+ harupy
345
+ Harutaka Kawamura
346
+ Hasan-8326
347
+ hauntsaninja
348
+ Henrich Hartzer
349
+ Henry Schreiner
350
+ Herbert Pfennig
351
+ Holly Stotelmyer
352
+ Honnix
353
+ Hsiaoming Yang
354
+ Hugo
355
+ Hugo Lopes Tavares
356
+ Hugo van Kemenade
357
+ Hugues Bruant
358
+ Hynek Schlawack
359
+ iamsrp-deshaw
360
+ Ian Bicking
361
+ Ian Cordasco
362
+ Ian Lee
363
+ Ian Stapleton Cordasco
364
+ Ian Wienand
365
+ Igor Kuzmitshov
366
+ Igor Sobreira
367
+ Ikko Ashimine
368
+ Ilan Schnell
369
+ Illia Volochii
370
+ Ilya Abdolmanafi
371
+ Ilya Baryshev
372
+ Inada Naoki
373
+ Ionel Cristian Mărieș
374
+ Ionel Maries Cristian
375
+ Itamar Turner-Trauring
376
+ iTrooz
377
+ Ivan Pozdeev
378
+ J. Nick Koston
379
+ Jacob Kim
380
+ Jacob Walls
381
+ Jaime Sanz
382
+ Jake Lishman
383
+ jakirkham
384
+ Jakub Kuczys
385
+ Jakub Stasiak
386
+ Jakub Vysoky
387
+ Jakub Wilk
388
+ James
389
+ James Cleveland
390
+ James Curtin
391
+ James Firth
392
+ James Gerity
393
+ James Polley
394
+ Jan Pokorný
395
+ Jannis Leidel
396
+ Jarek Potiuk
397
+ jarondl
398
+ Jason Curtis
399
+ Jason R. Coombs
400
+ JasonMo
401
+ JasonMo1
402
+ Jay Graves
403
+ Jean Abou Samra
404
+ Jean-Christophe Fillion-Robin
405
+ Jeff Barber
406
+ Jeff Dairiki
407
+ Jeff Widman
408
+ Jelmer Vernooij
409
+ jenix21
410
+ Jeremy Fleischman
411
+ Jeremy Stanley
412
+ Jeremy Zafran
413
+ Jesse Rittner
414
+ Jiashuo Li
415
+ Jim Fisher
416
+ Jim Garrison
417
+ Jinzhe Zeng
418
+ Jiun Bae
419
+ Jivan Amara
420
+ Joa
421
+ Joe Bylund
422
+ Joe Michelini
423
+ Johannes Altmanninger
424
+ John Paton
425
+ John Sirois
426
+ John T. Wodder II
427
+ John-Scott Atlakson
428
+ johnthagen
429
+ Jon Banafato
430
+ Jon Dufresne
431
+ Jon Parise
432
+ Jonas Nockert
433
+ Jonathan Herbert
434
+ Joonatan Partanen
435
+ Joost Molenaar
436
+ Jorge Niedbalski
437
+ Joseph Bylund
438
+ Joseph Long
439
+ Josh Bronson
440
+ Josh Cannon
441
+ Josh Hansen
442
+ Josh Schneier
443
+ Joshua
444
+ JoshuaPerdue
445
+ Jost Migenda
446
+ Juan Luis Cano Rodríguez
447
+ Juanjo Bazán
448
+ Judah Rand
449
+ Julian Berman
450
+ Julian Gethmann
451
+ Julien Demoor
452
+ Julien Stephan
453
+ July Tikhonov
454
+ Jussi Kukkonen
455
+ Justin van Heek
456
+ jwg4
457
+ Jyrki Pulliainen
458
+ Kai Chen
459
+ Kai Mueller
460
+ Kamal Bin Mustafa
461
+ Karolina Surma
462
+ kasium
463
+ kaustav haldar
464
+ Kaz Nishimura
465
+ keanemind
466
+ Keith Maxwell
467
+ Kelsey Hightower
468
+ Kenneth Belitzky
469
+ Kenneth Reitz
470
+ Kevin Burke
471
+ Kevin Carter
472
+ Kevin Frommelt
473
+ Kevin R Patterson
474
+ Kevin Turcios
475
+ Kexuan Sun
476
+ Kit Randel
477
+ Klaas van Schelven
478
+ KOLANICH
479
+ konstin
480
+ kpinc
481
+ Krishan Bhasin
482
+ Krishna Oza
483
+ Kumar McMillan
484
+ Kuntal Majumder
485
+ Kurt McKee
486
+ Kyle Persohn
487
+ lakshmanaram
488
+ Laszlo Kiss-Kollar
489
+ Laurent Bristiel
490
+ Laurent LAPORTE
491
+ Laurie O
492
+ Laurie Opperman
493
+ layday
494
+ Leon Sasson
495
+ Lev Givon
496
+ Lincoln de Sousa
497
+ Lipis
498
+ lorddavidiii
499
+ Loren Carvalho
500
+ Louis Liu
501
+ Lucas Cimon
502
+ Ludovic Gasc
503
+ Luis Carlos
504
+ Luis Medel
505
+ Lukas Geiger
506
+ Lukas Juhrich
507
+ Luke Macken
508
+ Luo Jiebin
509
+ luojiebin
510
+ luz.paz
511
+ László Kiss Kollár
512
+ M00nL1ght
513
+ MajorTanya
514
+ Malcolm Smith
515
+ Marc Abramowitz
516
+ Marc Tamlyn
517
+ Marcus Smith
518
+ Mariatta
519
+ Mark Kohler
520
+ Mark McLoughlin
521
+ Mark Williams
522
+ Markus Hametner
523
+ Martey Dodoo
524
+ Martin Fischer
525
+ Martin Häcker
526
+ Martin Pavlasek
527
+ Masaki
528
+ Masklinn
529
+ Matej Stuchlik
530
+ Mateusz Sokół
531
+ Mathew Jennings
532
+ Mathieu Bridon
533
+ Mathieu Kniewallner
534
+ Matt Bacchi
535
+ Matt Good
536
+ Matt Maker
537
+ Matt Robenolt
538
+ Matt Wozniski
539
+ matthew
540
+ Matthew Einhorn
541
+ Matthew Feickert
542
+ Matthew Gilliard
543
+ Matthew Hughes
544
+ Matthew Iversen
545
+ Matthew Treinish
546
+ Matthew Trumbell
547
+ Matthew Willson
548
+ Matthias Bussonnier
549
+ mattip
550
+ Maurits van Rees
551
+ Max W Chase
552
+ Maxim Kurnikov
553
+ Maxime Rouyrre
554
+ mayeut
555
+ mbaluna
556
+ Md Sujauddin Sekh
557
+ mdebi
558
+ Meet Vasita
559
+ memoselyk
560
+ meowmeowcat
561
+ Michael
562
+ Michael Aquilina
563
+ Michael E. Karpeles
564
+ Michael Klich
565
+ Michael Mintz
566
+ Michael Williamson
567
+ michaelpacer
568
+ Michał Górny
569
+ Mickaël Schoentgen
570
+ Miguel Araujo Perez
571
+ Mihir Singh
572
+ Mike
573
+ Mike Hendricks
574
+ Min RK
575
+ MinRK
576
+ Miro Hrončok
577
+ Mohsen Fooladnezhad
578
+ Monica Baluna
579
+ montefra
580
+ Monty Taylor
581
+ morotti
582
+ mrKazzila
583
+ Muha Ajjan
584
+ MUTHUSRIHEMADHARSHINI S A
585
+ Nadav Wexler
586
+ Nahuel Ambrosini
587
+ Nate Coraor
588
+ Nate Prewitt
589
+ Nathan Houghton
590
+ Nathaniel J. Smith
591
+ Nehal J Wani
592
+ Neil Botelho
593
+ Nguyễn Gia Phong
594
+ Nicholas Serra
595
+ Nick Coghlan
596
+ Nick Stenning
597
+ Nick Timkovich
598
+ Nicolas Bock
599
+ Nicole Harris
600
+ Nikhil Benesch
601
+ Nikhil Ladha
602
+ Nikita Chepanov
603
+ Nikolay Korolev
604
+ Nipunn Koorapati
605
+ Nitesh Sharma
606
+ Niyas Sait
607
+ Noah
608
+ Noah Gorny
609
+ Nok Lam Chan
610
+ Norbert Manthey
611
+ Nothing-991
612
+ Nowell Strite
613
+ NtaleGrey
614
+ nucccc
615
+ nvdv
616
+ OBITORASU
617
+ Ofek Lev
618
+ ofrinevo
619
+ Oleg Burnaev
620
+ Oliver Freund
621
+ Oliver Jeeves
622
+ Oliver Mannion
623
+ Oliver Tonnhofer
624
+ Olivier Girardot
625
+ Olivier Grisel
626
+ Ollie Rutherfurd
627
+ Omar Abdalgwad
628
+ OMOTO Kenji
629
+ Omry Yadan
630
+ onlinejudge95
631
+ Oren Held
632
+ Oscar Benjamin
633
+ oxygen dioxide
634
+ Oz N Tiram
635
+ Pachwenko
636
+ Paresh Joshi
637
+ Patrick Dubroy
638
+ Patrick Jenkins
639
+ Patrick Lawson
640
+ patricktokeeffe
641
+ Patrik Kopkan
642
+ Paul Ganssle
643
+ Paul Kehrer
644
+ Paul Moore
645
+ Paul Nasrat
646
+ Paul Oswald
647
+ Paul van der Linden
648
+ Paulus Schoutsen
649
+ Pavel Safronov
650
+ Pavithra Eswaramoorthy
651
+ Pawel Jasinski
652
+ Paweł Szramowski
653
+ Pekka Klärck
654
+ Peter Gessler
655
+ Peter Lisák
656
+ Peter Shen
657
+ Peter Waller
658
+ Petr Viktorin
659
+ petr-tik
660
+ Phaneendra Chiruvella
661
+ Phil Elson
662
+ Phil Freo
663
+ Phil Pennock
664
+ Phil Whelan
665
+ Philip Jägenstedt
666
+ Philip Molloy
667
+ Philippe Ombredanne
668
+ Pi Delport
669
+ Pierre-Yves Rofes
670
+ Pieter Degroote
671
+ pip
672
+ Prabakaran Kumaresshan
673
+ Prabhjyotsing Surjit Singh Sodhi
674
+ Prabhu Marappan
675
+ Pradyun Gedam
676
+ Prashant Sharma
677
+ Pratik Mallya
678
+ pre-commit-ci[bot]
679
+ Preet Thakkar
680
+ Preston Holmes
681
+ Przemek Wrzos
682
+ Pulkit Goyal
683
+ q0w
684
+ Qiangning Hong
685
+ Qiming Xu
686
+ qraqras
687
+ Quentin Lee
688
+ Quentin Pradet
689
+ R. David Murray
690
+ Rafael Caricio
691
+ RAHUL KUMAR
692
+ rahulkotargasthi
693
+ Ralf Schmitt
694
+ Ran Benita
695
+ Randy Döring
696
+ Razzi Abuissa
697
+ rdb
698
+ Reece Dunham
699
+ Remi Rampin
700
+ Rene Dudfield
701
+ Riccardo Magliocchetti
702
+ Riccardo Schirone
703
+ Richard Jones
704
+ Richard Si
705
+ Ricky Ng-Adam
706
+ Rishi
707
+ rmorotti
708
+ RobberPhex
709
+ Robert Collins
710
+ Robert McGibbon
711
+ Robert Pollak
712
+ Robert T. McGibbon
713
+ robin elisha robinson
714
+ Rodney, Tiara
715
+ Roey Berman
716
+ Rohan Jain
717
+ Roman Bogorodskiy
718
+ Roman Donchenko
719
+ Romuald Brunet
720
+ ronaudinho
721
+ Ronny Pfannschmidt
722
+ Rory McCann
723
+ Ross Brattain
724
+ Roy Wellington Ⅳ
725
+ RoyS
726
+ Ruairidh MacLeod
727
+ Russell Keith-Magee
728
+ Ryan Shepherd
729
+ Ryan Wooden
730
+ ryneeverett
731
+ Ryuma Asai
732
+ S. Guliaev
733
+ Sachi King
734
+ Sai Sridhar Tarra
735
+ Salvatore Rinchiera
736
+ sandeepkiran-js
737
+ Sander Van Balen
738
+ Savio Jomton
739
+ schlamar
740
+ Scott Kitterman
741
+ Sean
742
+ seanj
743
+ Sebastian Höffner
744
+ Sebastian Jordan
745
+ Sebastian Schaetz
746
+ Segev Finer
747
+ SeongSoo Cho
748
+ Sepehr Rasouli
749
+ sepehrrasooli
750
+ Sergey Vasilyev
751
+ Seth Michael Larson
752
+ Seth Woodworth
753
+ Shahar Epstein
754
+ Shantanu
755
+ shenxianpeng
756
+ shireenrao
757
+ Shivam Shrey
758
+ Shivansh-007
759
+ Shixian Sheng
760
+ Shlomi Fish
761
+ Shovan Maity
762
+ Shubham Nagure
763
+ Simeon Visser
764
+ Simon Cross
765
+ Simon Pichugin
766
+ sinoroc
767
+ sinscary
768
+ snook92
769
+ socketubs
770
+ Sorin Sbarnea
771
+ Srinivas Nyayapati
772
+ Srishti Hegde
773
+ Stavros Korokithakis
774
+ Stefan Scherfke
775
+ Stefano Rivera
776
+ Stephan Erb
777
+ Stephane Chazelas
778
+ Stephen Payne
779
+ Stephen Rosen
780
+ stepshal
781
+ Steve (Gadget) Barnes
782
+ Steve Barnes
783
+ Steve Dower
784
+ Steve Kowalik
785
+ Steven Myint
786
+ Steven Silvester
787
+ stonebig
788
+ studioj
789
+ Stéphane Bidoul
790
+ Stéphane Bidoul (ACSONE)
791
+ Stéphane Klein
792
+ Sumana Harihareswara
793
+ Surbhi Sharma
794
+ Sviatoslav Sydorenko
795
+ Sviatoslav Sydorenko (Святослав Сидоренко)
796
+ Swat009
797
+ Sylvain
798
+ S​age Abdullah
799
+ Takayuki SHIMIZUKAWA
800
+ Taneli Hukkinen
801
+ tbeswick
802
+ Terrance
803
+ Thiago
804
+ Thijs Triemstra
805
+ Thomas Fenzl
806
+ Thomas Grainger
807
+ Thomas Guettler
808
+ Thomas Johansson
809
+ Thomas Kluyver
810
+ Thomas Smith
811
+ Thomas VINCENT
812
+ Tim D. Smith
813
+ Tim Gates
814
+ Tim Harder
815
+ Tim Heap
816
+ tim smith
817
+ tinruufu
818
+ Tobias Hermann
819
+ Tom Forbes
820
+ Tom Freudenheim
821
+ Tom V
822
+ Tomas Hrnciar
823
+ Tomas Orsava
824
+ Tomer Chachamu
825
+ Tommi Enenkel | AnB
826
+ Tomáš Hrnčiar
827
+ Tony Beswick
828
+ Tony Narlock
829
+ Tony Zhaocheng Tan
830
+ TonyBeswick
831
+ toonarmycaptain
832
+ Toshio Kuratomi
833
+ toxinu
834
+ Travis Swicegood
835
+ Tushar Sadhwani
836
+ Tzu-ping Chung
837
+ Valentin Haenel
838
+ Victor Stinner
839
+ victorvpaulo
840
+ Vikram - Google
841
+ Viktor Szépe
842
+ Ville Skyttä
843
+ Vinay Sajip
844
+ Vincent Fazio
845
+ Vincent Philippon
846
+ Vinicyus Macedo
847
+ Vipul Kumar
848
+ Vitaly Babiy
849
+ Vladimir Fokow
850
+ Vladimir Rutsky
851
+ W. Trevor King
852
+ Weida Hong
853
+ Wil Tan
854
+ Wilfred Hughes
855
+ William Edwards
856
+ William ML Leslie
857
+ William T Olson
858
+ William Woodruff
859
+ Wilson Mo
860
+ wim glenn
861
+ Winson Luk
862
+ Wolfgang Maier
863
+ Wu Zhenyu
864
+ XAMES3
865
+ Xavier Fernandez
866
+ Xianpeng Shen
867
+ xoviat
868
+ xtreak
869
+ YAMAMOTO Takashi
870
+ Yash
871
+ Yashraj
872
+ Yen Chi Hsuan
873
+ Yeray Diaz Diaz
874
+ Youngkwang Yang
875
+ Yoval P
876
+ Yu Jian
877
+ Yuan Jing Vincent Yan
878
+ Yuki Kobayashi
879
+ Yusuke Hayashi
880
+ Zachary Ware
881
+ zackzack38
882
+ Zearin
883
+ Zhiping Deng
884
+ ziebam
885
+ Zvezdan Petkovic
886
+ Łukasz Langa
887
+ Роман Донченко
888
+ Семён Марьясин
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2008-present The pip developers (see AUTHORS.txt file)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/cachecontrol/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright 2012-2021 Eric Larson
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/certifi/LICENSE ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ This package contains a modified version of ca-bundle.crt:
2
+
3
+ ca-bundle.crt -- Bundle of CA Root Certificates
4
+
5
+ This is a bundle of X.509 certificates of public Certificate Authorities
6
+ (CA). These were automatically extracted from Mozilla's root certificates
7
+ file (certdata.txt). This file can be found in the mozilla source tree:
8
+ https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt
9
+ It contains the certificates in PEM format and therefore
10
+ can be directly used with curl / libcurl / php_curl, or with
11
+ an Apache+mod_ssl webserver for SSL client authentication.
12
+ Just configure this file as the SSLCACertificateFile.#
13
+
14
+ ***** BEGIN LICENSE BLOCK *****
15
+ This Source Code Form is subject to the terms of the Mozilla Public License,
16
+ v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain
17
+ one at http://mozilla.org/MPL/2.0/.
18
+
19
+ ***** END LICENSE BLOCK *****
20
+ @(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/distlib/LICENSE.txt ADDED
@@ -0,0 +1,284 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ A. HISTORY OF THE SOFTWARE
2
+ ==========================
3
+
4
+ Python was created in the early 1990s by Guido van Rossum at Stichting
5
+ Mathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands
6
+ as a successor of a language called ABC. Guido remains Python's
7
+ principal author, although it includes many contributions from others.
8
+
9
+ In 1995, Guido continued his work on Python at the Corporation for
10
+ National Research Initiatives (CNRI, see http://www.cnri.reston.va.us)
11
+ in Reston, Virginia where he released several versions of the
12
+ software.
13
+
14
+ In May 2000, Guido and the Python core development team moved to
15
+ BeOpen.com to form the BeOpen PythonLabs team. In October of the same
16
+ year, the PythonLabs team moved to Digital Creations (now Zope
17
+ Corporation, see http://www.zope.com). In 2001, the Python Software
18
+ Foundation (PSF, see http://www.python.org/psf/) was formed, a
19
+ non-profit organization created specifically to own Python-related
20
+ Intellectual Property. Zope Corporation is a sponsoring member of
21
+ the PSF.
22
+
23
+ All Python releases are Open Source (see http://www.opensource.org for
24
+ the Open Source Definition). Historically, most, but not all, Python
25
+ releases have also been GPL-compatible; the table below summarizes
26
+ the various releases.
27
+
28
+ Release Derived Year Owner GPL-
29
+ from compatible? (1)
30
+
31
+ 0.9.0 thru 1.2 1991-1995 CWI yes
32
+ 1.3 thru 1.5.2 1.2 1995-1999 CNRI yes
33
+ 1.6 1.5.2 2000 CNRI no
34
+ 2.0 1.6 2000 BeOpen.com no
35
+ 1.6.1 1.6 2001 CNRI yes (2)
36
+ 2.1 2.0+1.6.1 2001 PSF no
37
+ 2.0.1 2.0+1.6.1 2001 PSF yes
38
+ 2.1.1 2.1+2.0.1 2001 PSF yes
39
+ 2.2 2.1.1 2001 PSF yes
40
+ 2.1.2 2.1.1 2002 PSF yes
41
+ 2.1.3 2.1.2 2002 PSF yes
42
+ 2.2.1 2.2 2002 PSF yes
43
+ 2.2.2 2.2.1 2002 PSF yes
44
+ 2.2.3 2.2.2 2003 PSF yes
45
+ 2.3 2.2.2 2002-2003 PSF yes
46
+ 2.3.1 2.3 2002-2003 PSF yes
47
+ 2.3.2 2.3.1 2002-2003 PSF yes
48
+ 2.3.3 2.3.2 2002-2003 PSF yes
49
+ 2.3.4 2.3.3 2004 PSF yes
50
+ 2.3.5 2.3.4 2005 PSF yes
51
+ 2.4 2.3 2004 PSF yes
52
+ 2.4.1 2.4 2005 PSF yes
53
+ 2.4.2 2.4.1 2005 PSF yes
54
+ 2.4.3 2.4.2 2006 PSF yes
55
+ 2.4.4 2.4.3 2006 PSF yes
56
+ 2.5 2.4 2006 PSF yes
57
+ 2.5.1 2.5 2007 PSF yes
58
+ 2.5.2 2.5.1 2008 PSF yes
59
+ 2.5.3 2.5.2 2008 PSF yes
60
+ 2.6 2.5 2008 PSF yes
61
+ 2.6.1 2.6 2008 PSF yes
62
+ 2.6.2 2.6.1 2009 PSF yes
63
+ 2.6.3 2.6.2 2009 PSF yes
64
+ 2.6.4 2.6.3 2009 PSF yes
65
+ 2.6.5 2.6.4 2010 PSF yes
66
+ 3.0 2.6 2008 PSF yes
67
+ 3.0.1 3.0 2009 PSF yes
68
+ 3.1 3.0.1 2009 PSF yes
69
+ 3.1.1 3.1 2009 PSF yes
70
+ 3.1.2 3.1 2010 PSF yes
71
+ 3.2 3.1 2010 PSF yes
72
+
73
+ Footnotes:
74
+
75
+ (1) GPL-compatible doesn't mean that we're distributing Python under
76
+ the GPL. All Python licenses, unlike the GPL, let you distribute
77
+ a modified version without making your changes open source. The
78
+ GPL-compatible licenses make it possible to combine Python with
79
+ other software that is released under the GPL; the others don't.
80
+
81
+ (2) According to Richard Stallman, 1.6.1 is not GPL-compatible,
82
+ because its license has a choice of law clause. According to
83
+ CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1
84
+ is "not incompatible" with the GPL.
85
+
86
+ Thanks to the many outside volunteers who have worked under Guido's
87
+ direction to make these releases possible.
88
+
89
+
90
+ B. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON
91
+ ===============================================================
92
+
93
+ PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
94
+ --------------------------------------------
95
+
96
+ 1. This LICENSE AGREEMENT is between the Python Software Foundation
97
+ ("PSF"), and the Individual or Organization ("Licensee") accessing and
98
+ otherwise using this software ("Python") in source or binary form and
99
+ its associated documentation.
100
+
101
+ 2. Subject to the terms and conditions of this License Agreement, PSF hereby
102
+ grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,
103
+ analyze, test, perform and/or display publicly, prepare derivative works,
104
+ distribute, and otherwise use Python alone or in any derivative version,
105
+ provided, however, that PSF's License Agreement and PSF's notice of copyright,
106
+ i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
107
+ Python Software Foundation; All Rights Reserved" are retained in Python alone or
108
+ in any derivative version prepared by Licensee.
109
+
110
+ 3. In the event Licensee prepares a derivative work that is based on
111
+ or incorporates Python or any part thereof, and wants to make
112
+ the derivative work available to others as provided herein, then
113
+ Licensee hereby agrees to include in any such work a brief summary of
114
+ the changes made to Python.
115
+
116
+ 4. PSF is making Python available to Licensee on an "AS IS"
117
+ basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
118
+ IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND
119
+ DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
120
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT
121
+ INFRINGE ANY THIRD PARTY RIGHTS.
122
+
123
+ 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
124
+ FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
125
+ A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,
126
+ OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
127
+
128
+ 6. This License Agreement will automatically terminate upon a material
129
+ breach of its terms and conditions.
130
+
131
+ 7. Nothing in this License Agreement shall be deemed to create any
132
+ relationship of agency, partnership, or joint venture between PSF and
133
+ Licensee. This License Agreement does not grant permission to use PSF
134
+ trademarks or trade name in a trademark sense to endorse or promote
135
+ products or services of Licensee, or any third party.
136
+
137
+ 8. By copying, installing or otherwise using Python, Licensee
138
+ agrees to be bound by the terms and conditions of this License
139
+ Agreement.
140
+
141
+
142
+ BEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0
143
+ -------------------------------------------
144
+
145
+ BEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1
146
+
147
+ 1. This LICENSE AGREEMENT is between BeOpen.com ("BeOpen"), having an
148
+ office at 160 Saratoga Avenue, Santa Clara, CA 95051, and the
149
+ Individual or Organization ("Licensee") accessing and otherwise using
150
+ this software in source or binary form and its associated
151
+ documentation ("the Software").
152
+
153
+ 2. Subject to the terms and conditions of this BeOpen Python License
154
+ Agreement, BeOpen hereby grants Licensee a non-exclusive,
155
+ royalty-free, world-wide license to reproduce, analyze, test, perform
156
+ and/or display publicly, prepare derivative works, distribute, and
157
+ otherwise use the Software alone or in any derivative version,
158
+ provided, however, that the BeOpen Python License is retained in the
159
+ Software, alone or in any derivative version prepared by Licensee.
160
+
161
+ 3. BeOpen is making the Software available to Licensee on an "AS IS"
162
+ basis. BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
163
+ IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND
164
+ DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
165
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT
166
+ INFRINGE ANY THIRD PARTY RIGHTS.
167
+
168
+ 4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE
169
+ SOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS
170
+ AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY
171
+ DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
172
+
173
+ 5. This License Agreement will automatically terminate upon a material
174
+ breach of its terms and conditions.
175
+
176
+ 6. This License Agreement shall be governed by and interpreted in all
177
+ respects by the law of the State of California, excluding conflict of
178
+ law provisions. Nothing in this License Agreement shall be deemed to
179
+ create any relationship of agency, partnership, or joint venture
180
+ between BeOpen and Licensee. This License Agreement does not grant
181
+ permission to use BeOpen trademarks or trade names in a trademark
182
+ sense to endorse or promote products or services of Licensee, or any
183
+ third party. As an exception, the "BeOpen Python" logos available at
184
+ http://www.pythonlabs.com/logos.html may be used according to the
185
+ permissions granted on that web page.
186
+
187
+ 7. By copying, installing or otherwise using the software, Licensee
188
+ agrees to be bound by the terms and conditions of this License
189
+ Agreement.
190
+
191
+
192
+ CNRI LICENSE AGREEMENT FOR PYTHON 1.6.1
193
+ ---------------------------------------
194
+
195
+ 1. This LICENSE AGREEMENT is between the Corporation for National
196
+ Research Initiatives, having an office at 1895 Preston White Drive,
197
+ Reston, VA 20191 ("CNRI"), and the Individual or Organization
198
+ ("Licensee") accessing and otherwise using Python 1.6.1 software in
199
+ source or binary form and its associated documentation.
200
+
201
+ 2. Subject to the terms and conditions of this License Agreement, CNRI
202
+ hereby grants Licensee a nonexclusive, royalty-free, world-wide
203
+ license to reproduce, analyze, test, perform and/or display publicly,
204
+ prepare derivative works, distribute, and otherwise use Python 1.6.1
205
+ alone or in any derivative version, provided, however, that CNRI's
206
+ License Agreement and CNRI's notice of copyright, i.e., "Copyright (c)
207
+ 1995-2001 Corporation for National Research Initiatives; All Rights
208
+ Reserved" are retained in Python 1.6.1 alone or in any derivative
209
+ version prepared by Licensee. Alternately, in lieu of CNRI's License
210
+ Agreement, Licensee may substitute the following text (omitting the
211
+ quotes): "Python 1.6.1 is made available subject to the terms and
212
+ conditions in CNRI's License Agreement. This Agreement together with
213
+ Python 1.6.1 may be located on the Internet using the following
214
+ unique, persistent identifier (known as a handle): 1895.22/1013. This
215
+ Agreement may also be obtained from a proxy server on the Internet
216
+ using the following URL: http://hdl.handle.net/1895.22/1013".
217
+
218
+ 3. In the event Licensee prepares a derivative work that is based on
219
+ or incorporates Python 1.6.1 or any part thereof, and wants to make
220
+ the derivative work available to others as provided herein, then
221
+ Licensee hereby agrees to include in any such work a brief summary of
222
+ the changes made to Python 1.6.1.
223
+
224
+ 4. CNRI is making Python 1.6.1 available to Licensee on an "AS IS"
225
+ basis. CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR
226
+ IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND
227
+ DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS
228
+ FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT
229
+ INFRINGE ANY THIRD PARTY RIGHTS.
230
+
231
+ 5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON
232
+ 1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS
233
+ A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,
234
+ OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.
235
+
236
+ 6. This License Agreement will automatically terminate upon a material
237
+ breach of its terms and conditions.
238
+
239
+ 7. This License Agreement shall be governed by the federal
240
+ intellectual property law of the United States, including without
241
+ limitation the federal copyright law, and, to the extent such
242
+ U.S. federal law does not apply, by the law of the Commonwealth of
243
+ Virginia, excluding Virginia's conflict of law provisions.
244
+ Notwithstanding the foregoing, with regard to derivative works based
245
+ on Python 1.6.1 that incorporate non-separable material that was
246
+ previously distributed under the GNU General Public License (GPL), the
247
+ law of the Commonwealth of Virginia shall govern this License
248
+ Agreement only as to issues arising under or with respect to
249
+ Paragraphs 4, 5, and 7 of this License Agreement. Nothing in this
250
+ License Agreement shall be deemed to create any relationship of
251
+ agency, partnership, or joint venture between CNRI and Licensee. This
252
+ License Agreement does not grant permission to use CNRI trademarks or
253
+ trade name in a trademark sense to endorse or promote products or
254
+ services of Licensee, or any third party.
255
+
256
+ 8. By clicking on the "ACCEPT" button where indicated, or by copying,
257
+ installing or otherwise using Python 1.6.1, Licensee agrees to be
258
+ bound by the terms and conditions of this License Agreement.
259
+
260
+ ACCEPT
261
+
262
+
263
+ CWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2
264
+ --------------------------------------------------
265
+
266
+ Copyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,
267
+ The Netherlands. All rights reserved.
268
+
269
+ Permission to use, copy, modify, and distribute this software and its
270
+ documentation for any purpose and without fee is hereby granted,
271
+ provided that the above copyright notice appear in all copies and that
272
+ both that copyright notice and this permission notice appear in
273
+ supporting documentation, and that the name of Stichting Mathematisch
274
+ Centrum or CWI not be used in advertising or publicity pertaining to
275
+ distribution of the software without specific, written prior
276
+ permission.
277
+
278
+ STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
279
+ THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
280
+ FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
281
+ FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
282
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
283
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
284
+ OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/distro/LICENSE ADDED
@@ -0,0 +1,202 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+
178
+ APPENDIX: How to apply the Apache License to your work.
179
+
180
+ To apply the Apache License to your work, attach the following
181
+ boilerplate notice, with the fields enclosed by brackets "{}"
182
+ replaced with your own identifying information. (Don't include
183
+ the brackets!) The text should be enclosed in the appropriate
184
+ comment syntax for the file format. We also recommend that a
185
+ file or class name and description of purpose be included on the
186
+ same "printed page" as the copyright notice for easier
187
+ identification within third-party archives.
188
+
189
+ Copyright {yyyy} {name of copyright owner}
190
+
191
+ Licensed under the Apache License, Version 2.0 (the "License");
192
+ you may not use this file except in compliance with the License.
193
+ You may obtain a copy of the License at
194
+
195
+ http://www.apache.org/licenses/LICENSE-2.0
196
+
197
+ Unless required by applicable law or agreed to in writing, software
198
+ distributed under the License is distributed on an "AS IS" BASIS,
199
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200
+ See the License for the specific language governing permissions and
201
+ limitations under the License.
202
+
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/idna/LICENSE.md ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2013-2026, Kim Davies and contributors.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are
8
+ met:
9
+
10
+ 1. Redistributions of source code must retain the above copyright
11
+ notice, this list of conditions and the following disclaimer.
12
+
13
+ 2. Redistributions in binary form must reproduce the above copyright
14
+ notice, this list of conditions and the following disclaimer in the
15
+ documentation and/or other materials provided with the distribution.
16
+
17
+ 3. Neither the name of the copyright holder nor the names of its
18
+ contributors may be used to endorse or promote products derived from
19
+ this software without specific prior written permission.
20
+
21
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
27
+ TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/msgpack/COPYING ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (C) 2008-2011 INADA Naoki <songofacandy@gmail.com>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
14
+
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ This software is made available under the terms of *either* of the licenses
2
+ found in LICENSE.APACHE or LICENSE.BSD. Contributions to this software is made
3
+ under the terms of *both* these licenses.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.APACHE ADDED
@@ -0,0 +1,177 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/packaging/LICENSE.BSD ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) Donald Stufft and individual contributors.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ 1. Redistributions of source code must retain the above copyright notice,
8
+ this list of conditions and the following disclaimer.
9
+
10
+ 2. Redistributions in binary form must reproduce the above copyright
11
+ notice, this list of conditions and the following disclaimer in the
12
+ documentation and/or other materials provided with the distribution.
13
+
14
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
15
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
18
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
20
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
21
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
22
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pkg_resources/LICENSE ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Permission is hereby granted, free of charge, to any person obtaining a copy
2
+ of this software and associated documentation files (the "Software"), to
3
+ deal in the Software without restriction, including without limitation the
4
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
5
+ sell copies of the Software, and to permit persons to whom the Software is
6
+ furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in
9
+ all copies or substantial portions of the Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
16
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
17
+ IN THE SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/platformdirs/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2010-202x The platformdirs developers
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pygments/LICENSE ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2006-2022 by the respective authors (see AUTHORS file).
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ * Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ * Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the distribution.
14
+
15
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
18
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
19
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
25
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/pyproject_hooks/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Thomas Kluyver
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/requests/LICENSE ADDED
@@ -0,0 +1,175 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/resolvelib/LICENSE ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2018, Tzu-ping Chung <uranusjr@gmail.com>
2
+
3
+ Permission to use, copy, modify, and distribute this software for any
4
+ purpose with or without fee is hereby granted, provided that the above
5
+ copyright notice and this permission notice appear in all copies.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
10
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/rich/LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2020 Will McGugan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Taneli Hukkinen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/tomli_w/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2021 Taneli Hukkinen
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/truststore/LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2022 Seth Michael Larson
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
.venv/lib/python3.14/site-packages/pip-26.2.1.dist-info/licenses/src/pip/_vendor/urllib3/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2008-2020 Andrey Petrov and contributors.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/connection.py ADDED
@@ -0,0 +1,260 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import typing
5
+
6
+ # use http.client.HTTPException for consistency with non-emscripten
7
+ from http.client import HTTPException as HTTPException # noqa: F401
8
+ from http.client import ResponseNotReady
9
+
10
+ from ..._base_connection import _TYPE_BODY
11
+ from ...connection import HTTPConnection, ProxyConfig, port_by_scheme
12
+ from ...exceptions import TimeoutError
13
+ from ...response import BaseHTTPResponse
14
+ from ...util.connection import _TYPE_SOCKET_OPTIONS
15
+ from ...util.timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
16
+ from ...util.url import Url
17
+ from .fetch import _RequestError, _TimeoutError, send_request, send_streaming_request
18
+ from .request import EmscriptenRequest
19
+ from .response import EmscriptenHttpResponseWrapper, EmscriptenResponse
20
+
21
+ if typing.TYPE_CHECKING:
22
+ from ..._base_connection import BaseHTTPConnection, BaseHTTPSConnection
23
+
24
+
25
+ class EmscriptenHTTPConnection:
26
+ default_port: typing.ClassVar[int] = port_by_scheme["http"]
27
+ default_socket_options: typing.ClassVar[_TYPE_SOCKET_OPTIONS]
28
+
29
+ timeout: None | (float)
30
+
31
+ host: str
32
+ port: int
33
+ blocksize: int
34
+ source_address: tuple[str, int] | None
35
+ socket_options: _TYPE_SOCKET_OPTIONS | None
36
+
37
+ proxy: Url | None
38
+ proxy_config: ProxyConfig | None
39
+
40
+ is_verified: bool = False
41
+ proxy_is_verified: bool | None = None
42
+
43
+ response_class: type[BaseHTTPResponse] = EmscriptenHttpResponseWrapper
44
+ _response: EmscriptenResponse | None
45
+
46
+ def __init__(
47
+ self,
48
+ host: str,
49
+ port: int = 0,
50
+ *,
51
+ timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
52
+ source_address: tuple[str, int] | None = None,
53
+ blocksize: int = 8192,
54
+ socket_options: _TYPE_SOCKET_OPTIONS | None = None,
55
+ proxy: Url | None = None,
56
+ proxy_config: ProxyConfig | None = None,
57
+ ) -> None:
58
+ self.host = host
59
+ self.port = port
60
+ self.timeout = timeout if isinstance(timeout, float) else 0.0
61
+ self.scheme = "http"
62
+ self._closed = True
63
+ self._response = None
64
+ # ignore these things because we don't
65
+ # have control over that stuff
66
+ self.proxy = None
67
+ self.proxy_config = None
68
+ self.blocksize = blocksize
69
+ self.source_address = None
70
+ self.socket_options = None
71
+ self.is_verified = False
72
+
73
+ def set_tunnel(
74
+ self,
75
+ host: str,
76
+ port: int | None = 0,
77
+ headers: typing.Mapping[str, str] | None = None,
78
+ scheme: str = "http",
79
+ ) -> None:
80
+ pass
81
+
82
+ def connect(self) -> None:
83
+ pass
84
+
85
+ def request(
86
+ self,
87
+ method: str,
88
+ url: str,
89
+ body: _TYPE_BODY | None = None,
90
+ headers: typing.Mapping[str, str] | None = None,
91
+ # We know *at least* botocore is depending on the order of the
92
+ # first 3 parameters so to be safe we only mark the later ones
93
+ # as keyword-only to ensure we have space to extend.
94
+ *,
95
+ chunked: bool = False,
96
+ preload_content: bool = True,
97
+ decode_content: bool = True,
98
+ enforce_content_length: bool = True,
99
+ ) -> None:
100
+ self._closed = False
101
+ if url.startswith("/"):
102
+ if self.port is not None:
103
+ port = f":{self.port}"
104
+ else:
105
+ port = ""
106
+ # no scheme / host / port included, make a full url
107
+ url = f"{self.scheme}://{self.host}{port}{url}"
108
+ request = EmscriptenRequest(
109
+ url=url,
110
+ method=method,
111
+ timeout=self.timeout if self.timeout else 0,
112
+ decode_content=decode_content,
113
+ )
114
+ request.set_body(body)
115
+ if headers:
116
+ for k, v in headers.items():
117
+ request.set_header(k, v)
118
+ self._response = None
119
+ try:
120
+ if not preload_content:
121
+ self._response = send_streaming_request(request)
122
+ if self._response is None:
123
+ self._response = send_request(request)
124
+ except _TimeoutError as e:
125
+ raise TimeoutError(e.message) from e
126
+ except _RequestError as e:
127
+ raise HTTPException(e.message) from e
128
+
129
+ def getresponse(self) -> BaseHTTPResponse:
130
+ if self._response is not None:
131
+ return EmscriptenHttpResponseWrapper(
132
+ internal_response=self._response,
133
+ url=self._response.request.url,
134
+ connection=self,
135
+ )
136
+ else:
137
+ raise ResponseNotReady()
138
+
139
+ def close(self) -> None:
140
+ self._closed = True
141
+ self._response = None
142
+
143
+ @property
144
+ def is_closed(self) -> bool:
145
+ """Whether the connection either is brand new or has been previously closed.
146
+ If this property is True then both ``is_connected`` and ``has_connected_to_proxy``
147
+ properties must be False.
148
+ """
149
+ return self._closed
150
+
151
+ @property
152
+ def is_connected(self) -> bool:
153
+ """Whether the connection is actively connected to any origin (proxy or target)"""
154
+ return True
155
+
156
+ @property
157
+ def has_connected_to_proxy(self) -> bool:
158
+ """Whether the connection has successfully connected to its proxy.
159
+ This returns False if no proxy is in use. Used to determine whether
160
+ errors are coming from the proxy layer or from tunnelling to the target origin.
161
+ """
162
+ return False
163
+
164
+
165
+ class EmscriptenHTTPSConnection(EmscriptenHTTPConnection):
166
+ default_port = port_by_scheme["https"]
167
+ # all this is basically ignored, as browser handles https
168
+ cert_reqs: int | str | None = None
169
+ ca_certs: str | None = None
170
+ ca_cert_dir: str | None = None
171
+ ca_cert_data: None | str | bytes = None
172
+ cert_file: str | None
173
+ key_file: str | None
174
+ key_password: str | None
175
+ ssl_context: typing.Any | None
176
+ ssl_version: int | str | None = None
177
+ ssl_minimum_version: int | None = None
178
+ ssl_maximum_version: int | None = None
179
+ assert_hostname: None | str | typing.Literal[False]
180
+ assert_fingerprint: str | None = None
181
+
182
+ def __init__(
183
+ self,
184
+ host: str,
185
+ port: int = 0,
186
+ *,
187
+ timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
188
+ source_address: tuple[str, int] | None = None,
189
+ blocksize: int = 16384,
190
+ socket_options: (
191
+ None | _TYPE_SOCKET_OPTIONS
192
+ ) = HTTPConnection.default_socket_options,
193
+ proxy: Url | None = None,
194
+ proxy_config: ProxyConfig | None = None,
195
+ cert_reqs: int | str | None = None,
196
+ assert_hostname: None | str | typing.Literal[False] = None,
197
+ assert_fingerprint: str | None = None,
198
+ server_hostname: str | None = None,
199
+ ssl_context: typing.Any | None = None,
200
+ ca_certs: str | None = None,
201
+ ca_cert_dir: str | None = None,
202
+ ca_cert_data: None | str | bytes = None,
203
+ ssl_minimum_version: int | None = None,
204
+ ssl_maximum_version: int | None = None,
205
+ ssl_version: int | str | None = None, # Deprecated
206
+ cert_file: str | None = None,
207
+ key_file: str | None = None,
208
+ key_password: str | None = None,
209
+ ) -> None:
210
+ super().__init__(
211
+ host,
212
+ port=port,
213
+ timeout=timeout,
214
+ source_address=source_address,
215
+ blocksize=blocksize,
216
+ socket_options=socket_options,
217
+ proxy=proxy,
218
+ proxy_config=proxy_config,
219
+ )
220
+ self.scheme = "https"
221
+
222
+ self.key_file = key_file
223
+ self.cert_file = cert_file
224
+ self.key_password = key_password
225
+ self.ssl_context = ssl_context
226
+ self.server_hostname = server_hostname
227
+ self.assert_hostname = assert_hostname
228
+ self.assert_fingerprint = assert_fingerprint
229
+ self.ssl_version = ssl_version
230
+ self.ssl_minimum_version = ssl_minimum_version
231
+ self.ssl_maximum_version = ssl_maximum_version
232
+ self.ca_certs = ca_certs and os.path.expanduser(ca_certs)
233
+ self.ca_cert_dir = ca_cert_dir and os.path.expanduser(ca_cert_dir)
234
+ self.ca_cert_data = ca_cert_data
235
+
236
+ self.cert_reqs = None
237
+
238
+ # The browser will automatically verify all requests.
239
+ # We have no control over that setting.
240
+ self.is_verified = True
241
+
242
+ def set_cert(
243
+ self,
244
+ key_file: str | None = None,
245
+ cert_file: str | None = None,
246
+ cert_reqs: int | str | None = None,
247
+ key_password: str | None = None,
248
+ ca_certs: str | None = None,
249
+ assert_hostname: None | str | typing.Literal[False] = None,
250
+ assert_fingerprint: str | None = None,
251
+ ca_cert_dir: str | None = None,
252
+ ca_cert_data: None | str | bytes = None,
253
+ ) -> None:
254
+ pass
255
+
256
+
257
+ # verify that this class implements BaseHTTP(s) connection correctly
258
+ if typing.TYPE_CHECKING:
259
+ _supports_http_protocol: BaseHTTPConnection = EmscriptenHTTPConnection("", 0)
260
+ _supports_https_protocol: BaseHTTPSConnection = EmscriptenHTTPSConnection("", 0)
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/emscripten_fetch_worker.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ let Status = {
2
+ SUCCESS_HEADER: -1,
3
+ SUCCESS_EOF: -2,
4
+ ERROR_TIMEOUT: -3,
5
+ ERROR_EXCEPTION: -4,
6
+ };
7
+
8
+ let connections = new Map();
9
+ let nextConnectionID = 1;
10
+ const encoder = new TextEncoder();
11
+
12
+ self.addEventListener("message", async function (event) {
13
+ if (event.data.close) {
14
+ let connectionID = event.data.close;
15
+ connections.delete(connectionID);
16
+ return;
17
+ } else if (event.data.getMore) {
18
+ let connectionID = event.data.getMore;
19
+ let { curOffset, value, reader, intBuffer, byteBuffer } =
20
+ connections.get(connectionID);
21
+ // if we still have some in buffer, then just send it back straight away
22
+ if (!value || curOffset >= value.length) {
23
+ // read another buffer if required
24
+ try {
25
+ let readResponse = await reader.read();
26
+
27
+ if (readResponse.done) {
28
+ // read everything - clear connection and return
29
+ connections.delete(connectionID);
30
+ Atomics.store(intBuffer, 0, Status.SUCCESS_EOF);
31
+ Atomics.notify(intBuffer, 0);
32
+ // finished reading successfully
33
+ // return from event handler
34
+ return;
35
+ }
36
+ curOffset = 0;
37
+ connections.get(connectionID).value = readResponse.value;
38
+ value = readResponse.value;
39
+ } catch (error) {
40
+ console.log("Request exception:", error);
41
+ let errorBytes = encoder.encode(error.message);
42
+ let written = errorBytes.length;
43
+ byteBuffer.set(errorBytes);
44
+ intBuffer[1] = written;
45
+ Atomics.store(intBuffer, 0, Status.ERROR_EXCEPTION);
46
+ Atomics.notify(intBuffer, 0);
47
+ }
48
+ }
49
+
50
+ // send as much buffer as we can
51
+ let curLen = value.length - curOffset;
52
+ if (curLen > byteBuffer.length) {
53
+ curLen = byteBuffer.length;
54
+ }
55
+ byteBuffer.set(value.subarray(curOffset, curOffset + curLen), 0);
56
+
57
+ Atomics.store(intBuffer, 0, curLen); // store current length in bytes
58
+ Atomics.notify(intBuffer, 0);
59
+ curOffset += curLen;
60
+ connections.get(connectionID).curOffset = curOffset;
61
+
62
+ return;
63
+ } else {
64
+ // start fetch
65
+ let connectionID = nextConnectionID;
66
+ nextConnectionID += 1;
67
+ const intBuffer = new Int32Array(event.data.buffer);
68
+ const byteBuffer = new Uint8Array(event.data.buffer, 8);
69
+ try {
70
+ const response = await fetch(event.data.url, event.data.fetchParams);
71
+ // return the headers first via textencoder
72
+ var headers = [];
73
+ for (const pair of response.headers.entries()) {
74
+ headers.push([pair[0], pair[1]]);
75
+ }
76
+ let headerObj = {
77
+ headers: headers,
78
+ status: response.status,
79
+ connectionID,
80
+ };
81
+ const headerText = JSON.stringify(headerObj);
82
+ let headerBytes = encoder.encode(headerText);
83
+ let written = headerBytes.length;
84
+ byteBuffer.set(headerBytes);
85
+ intBuffer[1] = written;
86
+ // make a connection
87
+ connections.set(connectionID, {
88
+ reader: response.body.getReader(),
89
+ intBuffer: intBuffer,
90
+ byteBuffer: byteBuffer,
91
+ value: undefined,
92
+ curOffset: 0,
93
+ });
94
+ // set header ready
95
+ Atomics.store(intBuffer, 0, Status.SUCCESS_HEADER);
96
+ Atomics.notify(intBuffer, 0);
97
+ // all fetching after this goes through a new postmessage call with getMore
98
+ // this allows for parallel requests
99
+ } catch (error) {
100
+ console.log("Request exception:", error);
101
+ let errorBytes = encoder.encode(error.message);
102
+ let written = errorBytes.length;
103
+ byteBuffer.set(errorBytes);
104
+ intBuffer[1] = written;
105
+ Atomics.store(intBuffer, 0, Status.ERROR_EXCEPTION);
106
+ Atomics.notify(intBuffer, 0);
107
+ }
108
+ }
109
+ });
110
+ self.postMessage({ inited: true });
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/fetch.py ADDED
@@ -0,0 +1,726 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Support for streaming http requests in emscripten.
3
+
4
+ A few caveats -
5
+
6
+ If your browser (or Node.js) has WebAssembly JavaScript Promise Integration enabled
7
+ https://github.com/WebAssembly/js-promise-integration/blob/main/proposals/js-promise-integration/Overview.md
8
+ *and* you launch pyodide using `pyodide.runPythonAsync`, this will fetch data using the
9
+ JavaScript asynchronous fetch api (wrapped via `pyodide.ffi.call_sync`). In this case
10
+ timeouts and streaming should just work.
11
+
12
+ Otherwise, it uses a combination of XMLHttpRequest and a web-worker for streaming.
13
+
14
+ This approach has several caveats:
15
+
16
+ Firstly, you can't do streaming http in the main UI thread, because atomics.wait isn't allowed.
17
+ Streaming only works if you're running pyodide in a web worker.
18
+
19
+ Secondly, this uses an extra web worker and SharedArrayBuffer to do the asynchronous fetch
20
+ operation, so it requires that you have crossOriginIsolation enabled, by serving over https
21
+ (or from localhost) with the two headers below set:
22
+
23
+ Cross-Origin-Opener-Policy: same-origin
24
+ Cross-Origin-Embedder-Policy: require-corp
25
+
26
+ You can tell if cross origin isolation is successfully enabled by looking at the global crossOriginIsolated variable in
27
+ JavaScript console. If it isn't, streaming requests will fallback to XMLHttpRequest, i.e. getting the whole
28
+ request into a buffer and then returning it. it shows a warning in the JavaScript console in this case.
29
+
30
+ Finally, the webworker which does the streaming fetch is created on initial import, but will only be started once
31
+ control is returned to javascript. Call `await wait_for_streaming_ready()` to wait for streaming fetch.
32
+
33
+ NB: in this code, there are a lot of JavaScript objects. They are named js_*
34
+ to make it clear what type of object they are.
35
+ """
36
+
37
+ from __future__ import annotations
38
+
39
+ import io
40
+ import json
41
+ from email.parser import Parser
42
+ from importlib.resources import files
43
+ from typing import TYPE_CHECKING, Any
44
+
45
+ import js # type: ignore[import-not-found]
46
+ from pyodide.ffi import ( # type: ignore[import-not-found]
47
+ JsArray,
48
+ JsException,
49
+ JsProxy,
50
+ to_js,
51
+ )
52
+
53
+ if TYPE_CHECKING:
54
+ from typing_extensions import Buffer
55
+
56
+ from .request import EmscriptenRequest
57
+ from .response import EmscriptenResponse
58
+
59
+ """
60
+ There are some headers that trigger unintended CORS preflight requests.
61
+ See also https://github.com/koenvo/pyodide-http/issues/22
62
+ """
63
+ HEADERS_TO_IGNORE = ("user-agent",)
64
+
65
+ SUCCESS_HEADER = -1
66
+ SUCCESS_EOF = -2
67
+ ERROR_TIMEOUT = -3
68
+ ERROR_EXCEPTION = -4
69
+
70
+
71
+ class _RequestError(Exception):
72
+ def __init__(
73
+ self,
74
+ message: str | None = None,
75
+ *,
76
+ request: EmscriptenRequest | None = None,
77
+ response: EmscriptenResponse | None = None,
78
+ ):
79
+ self.request = request
80
+ self.response = response
81
+ self.message = message
82
+ super().__init__(self.message)
83
+
84
+
85
+ class _StreamingError(_RequestError):
86
+ pass
87
+
88
+
89
+ class _TimeoutError(_RequestError):
90
+ pass
91
+
92
+
93
+ def _obj_from_dict(dict_val: dict[str, Any]) -> JsProxy:
94
+ return to_js(dict_val, dict_converter=js.Object.fromEntries)
95
+
96
+
97
+ class _ReadStream(io.RawIOBase):
98
+ def __init__(
99
+ self,
100
+ int_buffer: JsArray,
101
+ byte_buffer: JsArray,
102
+ timeout: float,
103
+ worker: JsProxy,
104
+ connection_id: int,
105
+ request: EmscriptenRequest,
106
+ ):
107
+ self.int_buffer = int_buffer
108
+ self.byte_buffer = byte_buffer
109
+ self.read_pos = 0
110
+ self.read_len = 0
111
+ self.connection_id = connection_id
112
+ self.worker = worker
113
+ self.timeout = int(1000 * timeout) if timeout > 0 else None
114
+ self.is_live = True
115
+ self._is_closed = False
116
+ self.request: EmscriptenRequest | None = request
117
+
118
+ def __del__(self) -> None:
119
+ self.close()
120
+
121
+ # this is compatible with _base_connection
122
+ def is_closed(self) -> bool:
123
+ return self._is_closed
124
+
125
+ # for compatibility with RawIOBase
126
+ @property
127
+ def closed(self) -> bool:
128
+ return self.is_closed()
129
+
130
+ def close(self) -> None:
131
+ if self.is_closed():
132
+ return
133
+ self.read_len = 0
134
+ self.read_pos = 0
135
+ self.int_buffer = None
136
+ self.byte_buffer = None
137
+ self._is_closed = True
138
+ self.request = None
139
+ if self.is_live:
140
+ self.worker.postMessage(_obj_from_dict({"close": self.connection_id}))
141
+ self.is_live = False
142
+ super().close()
143
+
144
+ def readable(self) -> bool:
145
+ return True
146
+
147
+ def writable(self) -> bool:
148
+ return False
149
+
150
+ def seekable(self) -> bool:
151
+ return False
152
+
153
+ def readinto(self, byte_obj: Buffer) -> int:
154
+ if not self.int_buffer:
155
+ raise _StreamingError(
156
+ "No buffer for stream in _ReadStream.readinto",
157
+ request=self.request,
158
+ response=None,
159
+ )
160
+ if self.read_len == 0:
161
+ # wait for the worker to send something
162
+ js.Atomics.store(self.int_buffer, 0, ERROR_TIMEOUT)
163
+ self.worker.postMessage(_obj_from_dict({"getMore": self.connection_id}))
164
+ if (
165
+ js.Atomics.wait(self.int_buffer, 0, ERROR_TIMEOUT, self.timeout)
166
+ == "timed-out"
167
+ ):
168
+ raise _TimeoutError
169
+ data_len = self.int_buffer[0]
170
+ if data_len > 0:
171
+ self.read_len = data_len
172
+ self.read_pos = 0
173
+ elif data_len == ERROR_EXCEPTION:
174
+ string_len = self.int_buffer[1]
175
+ # decode the error string
176
+ js_decoder = js.TextDecoder.new()
177
+ json_str = js_decoder.decode(self.byte_buffer.slice(0, string_len))
178
+ raise _StreamingError(
179
+ f"Exception thrown in fetch: {json_str}",
180
+ request=self.request,
181
+ response=None,
182
+ )
183
+ else:
184
+ # EOF, free the buffers and return zero
185
+ # and free the request
186
+ self.is_live = False
187
+ self.close()
188
+ return 0
189
+ # copy from int32array to python bytes
190
+ ret_length = min(self.read_len, len(memoryview(byte_obj)))
191
+ subarray = self.byte_buffer.subarray(
192
+ self.read_pos, self.read_pos + ret_length
193
+ ).to_py()
194
+ memoryview(byte_obj)[0:ret_length] = subarray
195
+ self.read_len -= ret_length
196
+ self.read_pos += ret_length
197
+ return ret_length
198
+
199
+
200
+ class _StreamingFetcher:
201
+ def __init__(self) -> None:
202
+ # make web-worker and data buffer on startup
203
+ self.streaming_ready = False
204
+ streaming_worker_code = (
205
+ files(__package__)
206
+ .joinpath("emscripten_fetch_worker.js")
207
+ .read_text(encoding="utf-8")
208
+ )
209
+ js_data_blob = js.Blob.new(
210
+ to_js([streaming_worker_code], create_pyproxies=False),
211
+ _obj_from_dict({"type": "application/javascript"}),
212
+ )
213
+
214
+ def promise_resolver(js_resolve_fn: JsProxy, js_reject_fn: JsProxy) -> None:
215
+ def onMsg(e: JsProxy) -> None:
216
+ self.streaming_ready = True
217
+ js_resolve_fn(e)
218
+
219
+ def onErr(e: JsProxy) -> None:
220
+ js_reject_fn(e) # Defensive: never happens in ci
221
+
222
+ self.js_worker.onmessage = onMsg
223
+ self.js_worker.onerror = onErr
224
+
225
+ js_data_url = js.URL.createObjectURL(js_data_blob)
226
+ self.js_worker = js.globalThis.Worker.new(js_data_url)
227
+ self.js_worker_ready_promise = js.globalThis.Promise.new(promise_resolver)
228
+
229
+ def send(self, request: EmscriptenRequest) -> EmscriptenResponse:
230
+ headers = {
231
+ k: v for k, v in request.headers.items() if k not in HEADERS_TO_IGNORE
232
+ }
233
+
234
+ body = request.body
235
+ fetch_data = {"headers": headers, "body": to_js(body), "method": request.method}
236
+ # start the request off in the worker
237
+ timeout = int(1000 * request.timeout) if request.timeout > 0 else None
238
+ js_shared_buffer = js.SharedArrayBuffer.new(1048576)
239
+ js_int_buffer = js.Int32Array.new(js_shared_buffer)
240
+ js_byte_buffer = js.Uint8Array.new(js_shared_buffer, 8)
241
+
242
+ js.Atomics.store(js_int_buffer, 0, ERROR_TIMEOUT)
243
+ js.Atomics.notify(js_int_buffer, 0)
244
+ js_absolute_url = js.URL.new(request.url, js.location).href
245
+ self.js_worker.postMessage(
246
+ _obj_from_dict(
247
+ {
248
+ "buffer": js_shared_buffer,
249
+ "url": js_absolute_url,
250
+ "fetchParams": fetch_data,
251
+ }
252
+ )
253
+ )
254
+ # wait for the worker to send something
255
+ js.Atomics.wait(js_int_buffer, 0, ERROR_TIMEOUT, timeout)
256
+ if js_int_buffer[0] == ERROR_TIMEOUT:
257
+ raise _TimeoutError(
258
+ "Timeout connecting to streaming request",
259
+ request=request,
260
+ response=None,
261
+ )
262
+ elif js_int_buffer[0] == SUCCESS_HEADER:
263
+ # got response
264
+ # header length is in second int of intBuffer
265
+ string_len = js_int_buffer[1]
266
+ # decode the rest to a JSON string
267
+ js_decoder = js.TextDecoder.new()
268
+ # this does a copy (the slice) because decode can't work on shared array
269
+ # for some silly reason
270
+ json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len))
271
+ # get it as an object
272
+ response_obj = json.loads(json_str)
273
+ return EmscriptenResponse(
274
+ request=request,
275
+ status_code=response_obj["status"],
276
+ headers=response_obj["headers"],
277
+ body=_ReadStream(
278
+ js_int_buffer,
279
+ js_byte_buffer,
280
+ request.timeout,
281
+ self.js_worker,
282
+ response_obj["connectionID"],
283
+ request,
284
+ ),
285
+ )
286
+ elif js_int_buffer[0] == ERROR_EXCEPTION:
287
+ string_len = js_int_buffer[1]
288
+ # decode the error string
289
+ js_decoder = js.TextDecoder.new()
290
+ json_str = js_decoder.decode(js_byte_buffer.slice(0, string_len))
291
+ raise _StreamingError(
292
+ f"Exception thrown in fetch: {json_str}", request=request, response=None
293
+ )
294
+ else:
295
+ raise _StreamingError(
296
+ f"Unknown status from worker in fetch: {js_int_buffer[0]}",
297
+ request=request,
298
+ response=None,
299
+ )
300
+
301
+
302
+ class _JSPIReadStream(io.RawIOBase):
303
+ """
304
+ A read stream that uses pyodide.ffi.run_sync to read from a JavaScript fetch
305
+ response. This requires support for WebAssembly JavaScript Promise Integration
306
+ in the containing browser, and for pyodide to be launched via runPythonAsync.
307
+
308
+ :param js_read_stream:
309
+ The JavaScript stream reader
310
+
311
+ :param timeout:
312
+ Timeout in seconds
313
+
314
+ :param request:
315
+ The request we're handling
316
+
317
+ :param response:
318
+ The response this stream relates to
319
+
320
+ :param js_abort_controller:
321
+ A JavaScript AbortController object, used for timeouts
322
+ """
323
+
324
+ def __init__(
325
+ self,
326
+ js_read_stream: Any,
327
+ timeout: float,
328
+ request: EmscriptenRequest,
329
+ response: EmscriptenResponse,
330
+ js_abort_controller: Any, # JavaScript AbortController for timeouts
331
+ ):
332
+ self.js_read_stream = js_read_stream
333
+ self.timeout = timeout
334
+ self._is_closed = False
335
+ self._is_done = False
336
+ self.request: EmscriptenRequest | None = request
337
+ self.response: EmscriptenResponse | None = response
338
+ self.current_buffer = None
339
+ self.current_buffer_pos = 0
340
+ self.js_abort_controller = js_abort_controller
341
+
342
+ def __del__(self) -> None:
343
+ self.close()
344
+
345
+ # this is compatible with _base_connection
346
+ def is_closed(self) -> bool:
347
+ return self._is_closed
348
+
349
+ # for compatibility with RawIOBase
350
+ @property
351
+ def closed(self) -> bool:
352
+ return self.is_closed()
353
+
354
+ def close(self) -> None:
355
+ if self.is_closed():
356
+ return
357
+ self.read_len = 0
358
+ self.read_pos = 0
359
+ self.js_read_stream.cancel()
360
+ self.js_read_stream = None
361
+ self._is_closed = True
362
+ self._is_done = True
363
+ self.request = None
364
+ self.response = None
365
+ super().close()
366
+
367
+ def readable(self) -> bool:
368
+ return True
369
+
370
+ def writable(self) -> bool:
371
+ return False
372
+
373
+ def seekable(self) -> bool:
374
+ return False
375
+
376
+ def _get_next_buffer(self) -> bool:
377
+ result_js = _run_sync_with_timeout(
378
+ self.js_read_stream.read(),
379
+ self.timeout,
380
+ self.js_abort_controller,
381
+ request=self.request,
382
+ response=self.response,
383
+ )
384
+ if result_js.done:
385
+ self._is_done = True
386
+ return False
387
+ else:
388
+ self.current_buffer = result_js.value.to_py()
389
+ self.current_buffer_pos = 0
390
+ return True
391
+
392
+ def readinto(self, byte_obj: Buffer) -> int:
393
+ if self.current_buffer is None:
394
+ if not self._get_next_buffer() or self.current_buffer is None:
395
+ self.close()
396
+ return 0
397
+ ret_length = min(
398
+ len(byte_obj), len(self.current_buffer) - self.current_buffer_pos
399
+ )
400
+ byte_obj[0:ret_length] = self.current_buffer[
401
+ self.current_buffer_pos : self.current_buffer_pos + ret_length
402
+ ]
403
+ self.current_buffer_pos += ret_length
404
+ if self.current_buffer_pos == len(self.current_buffer):
405
+ self.current_buffer = None
406
+ return ret_length
407
+
408
+
409
+ # check if we are in a worker or not
410
+ def is_in_browser_main_thread() -> bool:
411
+ return hasattr(js, "window") and hasattr(js, "self") and js.self == js.window
412
+
413
+
414
+ def is_cross_origin_isolated() -> bool:
415
+ return hasattr(js, "crossOriginIsolated") and js.crossOriginIsolated
416
+
417
+
418
+ def is_in_node() -> bool:
419
+ return (
420
+ hasattr(js, "process")
421
+ and hasattr(js.process, "release")
422
+ and hasattr(js.process.release, "name")
423
+ and js.process.release.name == "node"
424
+ )
425
+
426
+
427
+ def is_worker_available() -> bool:
428
+ return hasattr(js, "Worker") and hasattr(js, "Blob")
429
+
430
+
431
+ _fetcher: _StreamingFetcher | None = None
432
+
433
+ if is_worker_available() and (
434
+ (is_cross_origin_isolated() and not is_in_browser_main_thread())
435
+ and (not is_in_node())
436
+ ):
437
+ _fetcher = _StreamingFetcher()
438
+ else:
439
+ _fetcher = None
440
+
441
+
442
+ NODE_JSPI_ERROR = (
443
+ "urllib3 only works in Node.js with pyodide.runPythonAsync"
444
+ " and requires the flag --experimental-wasm-stack-switching in "
445
+ " versions of node <24."
446
+ )
447
+
448
+
449
+ def send_streaming_request(request: EmscriptenRequest) -> EmscriptenResponse | None:
450
+ if has_jspi():
451
+ return send_jspi_request(request, True)
452
+ elif is_in_node():
453
+ raise _RequestError(
454
+ message=NODE_JSPI_ERROR,
455
+ request=request,
456
+ response=None,
457
+ )
458
+
459
+ if _fetcher and streaming_ready():
460
+ return _fetcher.send(request)
461
+ else:
462
+ _show_streaming_warning()
463
+ return None
464
+
465
+
466
+ _SHOWN_TIMEOUT_WARNING = False
467
+
468
+
469
+ def _show_timeout_warning() -> None:
470
+ global _SHOWN_TIMEOUT_WARNING
471
+ if not _SHOWN_TIMEOUT_WARNING:
472
+ _SHOWN_TIMEOUT_WARNING = True
473
+ message = "Warning: Timeout is not available on main browser thread"
474
+ js.console.warn(message)
475
+
476
+
477
+ _SHOWN_STREAMING_WARNING = False
478
+
479
+
480
+ def _show_streaming_warning() -> None:
481
+ global _SHOWN_STREAMING_WARNING
482
+ if not _SHOWN_STREAMING_WARNING:
483
+ _SHOWN_STREAMING_WARNING = True
484
+ message = "Can't stream HTTP requests because: \n"
485
+ if not is_cross_origin_isolated():
486
+ message += " Page is not cross-origin isolated\n"
487
+ if is_in_browser_main_thread():
488
+ message += " Python is running in main browser thread\n"
489
+ if not is_worker_available():
490
+ message += " Worker or Blob classes are not available in this environment." # Defensive: this is always False in browsers that we test in
491
+ if streaming_ready() is False:
492
+ message += """ Streaming fetch worker isn't ready. If you want to be sure that streaming fetch
493
+ is working, you need to call: 'await urllib3.contrib.emscripten.fetch.wait_for_streaming_ready()`"""
494
+ from js import console
495
+
496
+ console.warn(message)
497
+
498
+
499
+ def send_request(request: EmscriptenRequest) -> EmscriptenResponse:
500
+ if has_jspi():
501
+ return send_jspi_request(request, False)
502
+ elif is_in_node():
503
+ raise _RequestError(
504
+ message=NODE_JSPI_ERROR,
505
+ request=request,
506
+ response=None,
507
+ )
508
+ try:
509
+ js_xhr = js.XMLHttpRequest.new()
510
+
511
+ if not is_in_browser_main_thread():
512
+ js_xhr.responseType = "arraybuffer"
513
+ if request.timeout:
514
+ js_xhr.timeout = int(request.timeout * 1000)
515
+ else:
516
+ js_xhr.overrideMimeType("text/plain; charset=ISO-8859-15")
517
+ if request.timeout:
518
+ # timeout isn't available on the main thread - show a warning in console
519
+ # if it is set
520
+ _show_timeout_warning()
521
+
522
+ js_xhr.open(request.method, request.url, False)
523
+ for name, value in request.headers.items():
524
+ if name.lower() not in HEADERS_TO_IGNORE:
525
+ js_xhr.setRequestHeader(name, value)
526
+
527
+ js_xhr.send(to_js(request.body))
528
+
529
+ headers = dict(Parser().parsestr(js_xhr.getAllResponseHeaders()))
530
+
531
+ if not is_in_browser_main_thread():
532
+ body = js_xhr.response.to_py().tobytes()
533
+ else:
534
+ body = js_xhr.response.encode("ISO-8859-15")
535
+ return EmscriptenResponse(
536
+ status_code=js_xhr.status, headers=headers, body=body, request=request
537
+ )
538
+ except JsException as err:
539
+ if err.name == "TimeoutError":
540
+ raise _TimeoutError(err.message, request=request)
541
+ elif err.name == "NetworkError":
542
+ raise _RequestError(err.message, request=request)
543
+ else:
544
+ # general http error
545
+ raise _RequestError(err.message, request=request)
546
+
547
+
548
+ def send_jspi_request(
549
+ request: EmscriptenRequest, streaming: bool
550
+ ) -> EmscriptenResponse:
551
+ """
552
+ Send a request using WebAssembly JavaScript Promise Integration
553
+ to wrap the asynchronous JavaScript fetch api (experimental).
554
+
555
+ :param request:
556
+ Request to send
557
+
558
+ :param streaming:
559
+ Whether to stream the response
560
+
561
+ :return: The response object
562
+ :rtype: EmscriptenResponse
563
+ """
564
+ timeout = request.timeout
565
+ js_abort_controller = js.AbortController.new()
566
+ headers = {k: v for k, v in request.headers.items() if k not in HEADERS_TO_IGNORE}
567
+ req_body = request.body
568
+ fetch_data = {
569
+ "headers": headers,
570
+ "body": to_js(req_body),
571
+ "method": request.method,
572
+ "signal": js_abort_controller.signal,
573
+ }
574
+ # Node.js returns the whole response (unlike opaqueredirect in browsers),
575
+ # so urllib3 can set `redirect: manual` to control redirects itself.
576
+ # https://stackoverflow.com/a/78524615
577
+ if _is_node_js():
578
+ fetch_data["redirect"] = "manual"
579
+ # Call JavaScript fetch (async api, returns a promise)
580
+ fetcher_promise_js = js.fetch(request.url, _obj_from_dict(fetch_data))
581
+ # Now suspend WebAssembly until we resolve that promise
582
+ # or time out.
583
+ response_js = _run_sync_with_timeout(
584
+ fetcher_promise_js,
585
+ timeout,
586
+ js_abort_controller,
587
+ request=request,
588
+ response=None,
589
+ )
590
+ headers = {}
591
+ header_iter = response_js.headers.entries()
592
+ while True:
593
+ iter_value_js = header_iter.next()
594
+ if getattr(iter_value_js, "done", False):
595
+ break
596
+ else:
597
+ headers[str(iter_value_js.value[0])] = str(iter_value_js.value[1])
598
+ status_code = response_js.status
599
+ body: bytes | io.RawIOBase = b""
600
+
601
+ response = EmscriptenResponse(
602
+ status_code=status_code, headers=headers, body=b"", request=request
603
+ )
604
+ if streaming:
605
+ # get via inputstream
606
+ if response_js.body is not None:
607
+ # get a reader from the fetch response
608
+ body_stream_js = response_js.body.getReader()
609
+ body = _JSPIReadStream(
610
+ body_stream_js, timeout, request, response, js_abort_controller
611
+ )
612
+ else:
613
+ # get directly via arraybuffer
614
+ # n.b. this is another async JavaScript call.
615
+ body = _run_sync_with_timeout(
616
+ response_js.arrayBuffer(),
617
+ timeout,
618
+ js_abort_controller,
619
+ request=request,
620
+ response=response,
621
+ ).to_py()
622
+ response.body = body
623
+ return response
624
+
625
+
626
+ def _run_sync_with_timeout(
627
+ promise: Any,
628
+ timeout: float,
629
+ js_abort_controller: Any,
630
+ request: EmscriptenRequest | None,
631
+ response: EmscriptenResponse | None,
632
+ ) -> Any:
633
+ """
634
+ Await a JavaScript promise synchronously with a timeout which is implemented
635
+ via the AbortController
636
+
637
+ :param promise:
638
+ Javascript promise to await
639
+
640
+ :param timeout:
641
+ Timeout in seconds
642
+
643
+ :param js_abort_controller:
644
+ A JavaScript AbortController object, used on timeout
645
+
646
+ :param request:
647
+ The request being handled
648
+
649
+ :param response:
650
+ The response being handled (if it exists yet)
651
+
652
+ :raises _TimeoutError: If the request times out
653
+ :raises _RequestError: If the request raises a JavaScript exception
654
+
655
+ :return: The result of awaiting the promise.
656
+ """
657
+ timer_id = None
658
+ if timeout > 0:
659
+ timer_id = js.setTimeout(
660
+ js_abort_controller.abort.bind(js_abort_controller), int(timeout * 1000)
661
+ )
662
+ try:
663
+ from pyodide.ffi import run_sync
664
+
665
+ # run_sync here uses WebAssembly JavaScript Promise Integration to
666
+ # suspend python until the JavaScript promise resolves.
667
+ return run_sync(promise)
668
+ except JsException as err:
669
+ if err.name == "AbortError":
670
+ raise _TimeoutError(
671
+ message="Request timed out", request=request, response=response
672
+ )
673
+ else:
674
+ raise _RequestError(message=err.message, request=request, response=response)
675
+ finally:
676
+ if timer_id is not None:
677
+ js.clearTimeout(timer_id)
678
+
679
+
680
+ def has_jspi() -> bool:
681
+ """
682
+ Return true if jspi can be used.
683
+
684
+ This requires both browser support and also WebAssembly
685
+ to be in the correct state - i.e. that the javascript
686
+ call into python was async not sync.
687
+
688
+ :return: True if jspi can be used.
689
+ :rtype: bool
690
+ """
691
+ try:
692
+ from pyodide.ffi import can_run_sync, run_sync # noqa: F401
693
+
694
+ return bool(can_run_sync())
695
+ except ImportError:
696
+ return False
697
+
698
+
699
+ def _is_node_js() -> bool:
700
+ """
701
+ Check if we are in Node.js.
702
+
703
+ :return: True if we are in Node.js.
704
+ :rtype: bool
705
+ """
706
+ return (
707
+ hasattr(js, "process")
708
+ and hasattr(js.process, "release")
709
+ # According to the Node.js documentation, the release name is always "node".
710
+ and js.process.release.name == "node"
711
+ )
712
+
713
+
714
+ def streaming_ready() -> bool | None:
715
+ if _fetcher:
716
+ return _fetcher.streaming_ready
717
+ else:
718
+ return None # no fetcher, return None to signify that
719
+
720
+
721
+ async def wait_for_streaming_ready() -> bool:
722
+ if _fetcher:
723
+ await _fetcher.js_worker_ready_promise
724
+ return True
725
+ else:
726
+ return False
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/request.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+
5
+ from ..._base_connection import _TYPE_BODY
6
+
7
+
8
+ @dataclass
9
+ class EmscriptenRequest:
10
+ method: str
11
+ url: str
12
+ params: dict[str, str] | None = None
13
+ body: _TYPE_BODY | None = None
14
+ headers: dict[str, str] = field(default_factory=dict)
15
+ timeout: float = 0
16
+ decode_content: bool = True
17
+
18
+ def set_header(self, name: str, value: str) -> None:
19
+ self.headers[name.capitalize()] = value
20
+
21
+ def set_body(self, body: _TYPE_BODY | None) -> None:
22
+ self.body = body
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/emscripten/response.py ADDED
@@ -0,0 +1,281 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json as _json
4
+ import logging
5
+ import typing
6
+ from contextlib import contextmanager
7
+ from dataclasses import dataclass
8
+ from http.client import HTTPException as HTTPException
9
+ from io import BytesIO, IOBase
10
+
11
+ from ...exceptions import InvalidHeader, TimeoutError
12
+ from ...response import BaseHTTPResponse
13
+ from ...util.retry import Retry
14
+ from .request import EmscriptenRequest
15
+
16
+ if typing.TYPE_CHECKING:
17
+ from ..._base_connection import BaseHTTPConnection, BaseHTTPSConnection
18
+
19
+ log = logging.getLogger(__name__)
20
+
21
+
22
+ @dataclass
23
+ class EmscriptenResponse:
24
+ status_code: int
25
+ headers: dict[str, str]
26
+ body: IOBase | bytes
27
+ request: EmscriptenRequest
28
+
29
+
30
+ class EmscriptenHttpResponseWrapper(BaseHTTPResponse):
31
+ def __init__(
32
+ self,
33
+ internal_response: EmscriptenResponse,
34
+ url: str | None = None,
35
+ connection: BaseHTTPConnection | BaseHTTPSConnection | None = None,
36
+ ):
37
+ self._pool = None # set by pool class
38
+ self._body = None
39
+ self._uncached_read_occurred = False
40
+ self._response = internal_response
41
+ self._url = url
42
+ self._connection = connection
43
+ self._closed = False
44
+ super().__init__(
45
+ headers=internal_response.headers,
46
+ status=internal_response.status_code,
47
+ request_url=url,
48
+ version=0,
49
+ version_string="HTTP/?",
50
+ reason="",
51
+ decode_content=True,
52
+ )
53
+ self.length_remaining = self._init_length(self._response.request.method)
54
+ self.length_is_certain = False
55
+
56
+ @property
57
+ def url(self) -> str | None:
58
+ return self._url
59
+
60
+ @url.setter
61
+ def url(self, url: str | None) -> None:
62
+ self._url = url
63
+
64
+ @property
65
+ def connection(self) -> BaseHTTPConnection | BaseHTTPSConnection | None:
66
+ return self._connection
67
+
68
+ @property
69
+ def retries(self) -> Retry | None:
70
+ return self._retries
71
+
72
+ @retries.setter
73
+ def retries(self, retries: Retry | None) -> None:
74
+ # Override the request_url if retries has a redirect location.
75
+ self._retries = retries
76
+
77
+ def stream(
78
+ self, amt: int | None = 2**16, decode_content: bool | None = None
79
+ ) -> typing.Generator[bytes]:
80
+ """
81
+ A generator wrapper for the read() method. A call will block until
82
+ ``amt`` bytes have been read from the connection or until the
83
+ connection is closed.
84
+
85
+ :param amt:
86
+ How much of the content to read. The generator will return up to
87
+ much data per iteration, but may return less. This is particularly
88
+ likely when using compressed data. However, the empty string will
89
+ never be returned.
90
+
91
+ :param decode_content:
92
+ If True, will attempt to decode the body based on the
93
+ 'content-encoding' header.
94
+ """
95
+ while True:
96
+ data = self.read(amt=amt, decode_content=decode_content)
97
+
98
+ if data:
99
+ yield data
100
+ else:
101
+ break
102
+
103
+ def _init_length(self, request_method: str | None) -> int | None:
104
+ length: int | None
105
+ content_length: str | None = self.headers.get("content-length")
106
+
107
+ if content_length is not None:
108
+ try:
109
+ # RFC 7230 section 3.3.2 specifies multiple content lengths can
110
+ # be sent in a single Content-Length header
111
+ # (e.g. Content-Length: 42, 42). This line ensures the values
112
+ # are all valid ints and that as long as the `set` length is 1,
113
+ # all values are the same. Otherwise, the header is invalid.
114
+ lengths = {int(val) for val in content_length.split(",")}
115
+ if len(lengths) > 1:
116
+ raise InvalidHeader(
117
+ "Content-Length contained multiple "
118
+ "unmatching values (%s)" % content_length
119
+ )
120
+ length = lengths.pop()
121
+ except ValueError:
122
+ length = None
123
+ else:
124
+ if length < 0:
125
+ length = None
126
+
127
+ else: # if content_length is None
128
+ length = None
129
+
130
+ # Check for responses that shouldn't include a body
131
+ if (
132
+ self.status in (204, 304)
133
+ or 100 <= self.status < 200
134
+ or request_method == "HEAD"
135
+ ):
136
+ length = 0
137
+
138
+ return length
139
+
140
+ def read(
141
+ self,
142
+ amt: int | None = None,
143
+ decode_content: bool | None = None, # ignored because browser decodes always
144
+ cache_content: bool = False,
145
+ ) -> bytes:
146
+ if (
147
+ self._closed
148
+ or self._response is None
149
+ or (isinstance(self._response.body, IOBase) and self._response.body.closed)
150
+ ):
151
+ return b""
152
+
153
+ with self._error_catcher():
154
+ # body has been preloaded as a string by XmlHttpRequest
155
+ if not isinstance(self._response.body, IOBase):
156
+ self.length_remaining = len(self._response.body)
157
+ self.length_is_certain = True
158
+ # wrap body in IOStream
159
+ self._response.body = BytesIO(self._response.body)
160
+ if amt is not None and amt >= 0:
161
+ # don't cache partial content
162
+ cache_content = False
163
+ data = self._response.body.read(amt)
164
+ self._uncached_read_occurred = True
165
+ else: # read all we can (and cache it)
166
+ data = self._response.body.read()
167
+ if cache_content and not self._uncached_read_occurred:
168
+ self._body = data
169
+ else:
170
+ self._uncached_read_occurred = True
171
+ if self.length_remaining is not None:
172
+ self.length_remaining = max(self.length_remaining - len(data), 0)
173
+ if len(data) == 0 or (
174
+ self.length_is_certain and self.length_remaining == 0
175
+ ):
176
+ # definitely finished reading, close response stream
177
+ self._response.body.close()
178
+ return typing.cast(bytes, data)
179
+
180
+ def read_chunked(
181
+ self,
182
+ amt: int | None = None,
183
+ decode_content: bool | None = None,
184
+ ) -> typing.Generator[bytes]:
185
+ # chunked is handled by browser
186
+ while True:
187
+ bytes = self.read(amt, decode_content)
188
+ if not bytes:
189
+ break
190
+ yield bytes
191
+
192
+ def release_conn(self) -> None:
193
+ if not self._pool or not self._connection:
194
+ return None
195
+
196
+ self._pool._put_conn(self._connection)
197
+ self._connection = None
198
+
199
+ def drain_conn(self) -> None:
200
+ self.close()
201
+
202
+ @property
203
+ def data(self) -> bytes:
204
+ if self._body:
205
+ return self._body
206
+ else:
207
+ return self.read(cache_content=True)
208
+
209
+ def json(self) -> typing.Any:
210
+ """
211
+ Deserializes the body of the HTTP response as a Python object.
212
+
213
+ The body of the HTTP response must be encoded using UTF-8, as per
214
+ `RFC 8529 Section 8.1 <https://www.rfc-editor.org/rfc/rfc8259#section-8.1>`_.
215
+
216
+ To use a custom JSON decoder pass the result of :attr:`HTTPResponse.data` to
217
+ your custom decoder instead.
218
+
219
+ If the body of the HTTP response is not decodable to UTF-8, a
220
+ `UnicodeDecodeError` will be raised. If the body of the HTTP response is not a
221
+ valid JSON document, a `json.JSONDecodeError` will be raised.
222
+
223
+ Read more :ref:`here <json_content>`.
224
+
225
+ :returns: The body of the HTTP response as a Python object.
226
+ """
227
+ data = self.data.decode("utf-8")
228
+ return _json.loads(data)
229
+
230
+ def close(self) -> None:
231
+ if not self._closed:
232
+ if isinstance(self._response.body, IOBase):
233
+ self._response.body.close()
234
+ if self._connection:
235
+ self._connection.close()
236
+ self._connection = None
237
+ self._closed = True
238
+
239
+ @contextmanager
240
+ def _error_catcher(self) -> typing.Generator[None]:
241
+ """
242
+ Catch Emscripten specific exceptions thrown by fetch.py,
243
+ instead re-raising urllib3 variants, so that low-level exceptions
244
+ are not leaked in the high-level api.
245
+
246
+ On exit, release the connection back to the pool.
247
+ """
248
+ from .fetch import _RequestError, _TimeoutError # avoid circular import
249
+
250
+ clean_exit = False
251
+
252
+ try:
253
+ yield
254
+ # If no exception is thrown, we should avoid cleaning up
255
+ # unnecessarily.
256
+ clean_exit = True
257
+ except _TimeoutError as e:
258
+ raise TimeoutError(str(e))
259
+ except _RequestError as e:
260
+ raise HTTPException(str(e))
261
+ finally:
262
+ # If we didn't terminate cleanly, we need to throw away our
263
+ # connection.
264
+ if not clean_exit:
265
+ # The response may not be closed but we're not going to use it
266
+ # anymore so close it now
267
+ if (
268
+ isinstance(self._response.body, IOBase)
269
+ and not self._response.body.closed
270
+ ):
271
+ self._response.body.close()
272
+ # release the connection back to the pool
273
+ self.release_conn()
274
+ else:
275
+ # If we have read everything from the response stream,
276
+ # return the connection back to the pool.
277
+ if (
278
+ isinstance(self._response.body, IOBase)
279
+ and self._response.body.closed
280
+ ):
281
+ self.release_conn()
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/pyopenssl.py ADDED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Module for using pyOpenSSL as a TLS backend. This module was relevant before
3
+ the standard library ``ssl`` module supported SNI, but now that we've dropped
4
+ support for Python 2.7 all relevant Python versions support SNI so
5
+ **this module is no longer recommended**.
6
+
7
+ This needs the following packages installed:
8
+
9
+ * `pyOpenSSL`_ (tested with 19.0.0)
10
+ * `cryptography`_ (minimum 2.3, from pyopenssl)
11
+ * `idna`_ (minimum 2.1, from cryptography)
12
+
13
+ However, pyOpenSSL depends on cryptography, so while we use all three directly here we
14
+ end up having relatively few packages required.
15
+
16
+ You can install them with the following command:
17
+
18
+ .. code-block:: bash
19
+
20
+ $ python -m pip install pyopenssl cryptography idna
21
+
22
+ To activate certificate checking, call
23
+ :func:`~urllib3.contrib.pyopenssl.inject_into_urllib3` from your Python code
24
+ before you begin making HTTP requests. This can be done in a ``sitecustomize``
25
+ module, or at any other time before your application begins using ``urllib3``,
26
+ like this:
27
+
28
+ .. code-block:: python
29
+
30
+ try:
31
+ import pip._vendor.urllib3.contrib.pyopenssl as pyopenssl
32
+ pyopenssl.inject_into_urllib3()
33
+ except ImportError:
34
+ pass
35
+
36
+ .. _pyopenssl: https://www.pyopenssl.org
37
+ .. _cryptography: https://cryptography.io
38
+ .. _idna: https://github.com/kjd/idna
39
+ """
40
+
41
+ from __future__ import annotations
42
+
43
+ import OpenSSL.SSL # type: ignore[import-not-found]
44
+ from cryptography import x509
45
+
46
+ try:
47
+ from cryptography.x509 import UnsupportedExtension # type: ignore[attr-defined]
48
+ except ImportError:
49
+ # UnsupportedExtension is gone in cryptography >= 2.1.0
50
+ class UnsupportedExtension(Exception): # type: ignore[no-redef]
51
+ pass
52
+
53
+
54
+ import logging
55
+ import ssl
56
+ import typing
57
+ from io import BytesIO
58
+ from socket import socket as socket_cls
59
+
60
+ from .. import util
61
+
62
+ if typing.TYPE_CHECKING:
63
+ from OpenSSL.crypto import X509 # type: ignore[import-not-found]
64
+
65
+
66
+ __all__ = ["inject_into_urllib3", "extract_from_urllib3"]
67
+
68
+ # Map from urllib3 to PyOpenSSL compatible parameter-values.
69
+ _openssl_versions: dict[int, int] = {
70
+ util.ssl_.PROTOCOL_TLS: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined]
71
+ util.ssl_.PROTOCOL_TLS_CLIENT: OpenSSL.SSL.SSLv23_METHOD, # type: ignore[attr-defined]
72
+ ssl.PROTOCOL_TLSv1: OpenSSL.SSL.TLSv1_METHOD,
73
+ }
74
+
75
+ if hasattr(ssl, "PROTOCOL_TLSv1_1") and hasattr(OpenSSL.SSL, "TLSv1_1_METHOD"):
76
+ _openssl_versions[ssl.PROTOCOL_TLSv1_1] = OpenSSL.SSL.TLSv1_1_METHOD
77
+
78
+ if hasattr(ssl, "PROTOCOL_TLSv1_2") and hasattr(OpenSSL.SSL, "TLSv1_2_METHOD"):
79
+ _openssl_versions[ssl.PROTOCOL_TLSv1_2] = OpenSSL.SSL.TLSv1_2_METHOD
80
+
81
+
82
+ _stdlib_to_openssl_verify = {
83
+ ssl.CERT_NONE: OpenSSL.SSL.VERIFY_NONE,
84
+ ssl.CERT_OPTIONAL: OpenSSL.SSL.VERIFY_PEER,
85
+ ssl.CERT_REQUIRED: OpenSSL.SSL.VERIFY_PEER
86
+ + OpenSSL.SSL.VERIFY_FAIL_IF_NO_PEER_CERT,
87
+ }
88
+ _openssl_to_stdlib_verify = {v: k for k, v in _stdlib_to_openssl_verify.items()}
89
+
90
+ # The SSLvX values are the most likely to be missing in the future
91
+ # but we check them all just to be sure.
92
+ _OP_NO_SSLv2_OR_SSLv3: int = getattr(OpenSSL.SSL, "OP_NO_SSLv2", 0) | getattr(
93
+ OpenSSL.SSL, "OP_NO_SSLv3", 0
94
+ )
95
+ _OP_NO_TLSv1: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1", 0)
96
+ _OP_NO_TLSv1_1: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_1", 0)
97
+ _OP_NO_TLSv1_2: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_2", 0)
98
+ _OP_NO_TLSv1_3: int = getattr(OpenSSL.SSL, "OP_NO_TLSv1_3", 0)
99
+
100
+ _openssl_to_ssl_minimum_version: dict[int, int] = {
101
+ ssl.TLSVersion.MINIMUM_SUPPORTED: _OP_NO_SSLv2_OR_SSLv3,
102
+ ssl.TLSVersion.TLSv1: _OP_NO_SSLv2_OR_SSLv3,
103
+ ssl.TLSVersion.TLSv1_1: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1,
104
+ ssl.TLSVersion.TLSv1_2: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1,
105
+ ssl.TLSVersion.TLSv1_3: (
106
+ _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2
107
+ ),
108
+ ssl.TLSVersion.MAXIMUM_SUPPORTED: (
109
+ _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2
110
+ ),
111
+ }
112
+ _openssl_to_ssl_maximum_version: dict[int, int] = {
113
+ ssl.TLSVersion.MINIMUM_SUPPORTED: (
114
+ _OP_NO_SSLv2_OR_SSLv3
115
+ | _OP_NO_TLSv1
116
+ | _OP_NO_TLSv1_1
117
+ | _OP_NO_TLSv1_2
118
+ | _OP_NO_TLSv1_3
119
+ ),
120
+ ssl.TLSVersion.TLSv1: (
121
+ _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_1 | _OP_NO_TLSv1_2 | _OP_NO_TLSv1_3
122
+ ),
123
+ ssl.TLSVersion.TLSv1_1: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_2 | _OP_NO_TLSv1_3,
124
+ ssl.TLSVersion.TLSv1_2: _OP_NO_SSLv2_OR_SSLv3 | _OP_NO_TLSv1_3,
125
+ ssl.TLSVersion.TLSv1_3: _OP_NO_SSLv2_OR_SSLv3,
126
+ ssl.TLSVersion.MAXIMUM_SUPPORTED: _OP_NO_SSLv2_OR_SSLv3,
127
+ }
128
+
129
+ # OpenSSL will only write 16K at a time
130
+ SSL_WRITE_BLOCKSIZE = 16384
131
+
132
+ orig_util_SSLContext = util.ssl_.SSLContext
133
+
134
+
135
+ log = logging.getLogger(__name__)
136
+
137
+
138
+ def inject_into_urllib3() -> None:
139
+ "Monkey-patch urllib3 with PyOpenSSL-backed SSL-support."
140
+
141
+ _validate_dependencies_met()
142
+
143
+ util.SSLContext = PyOpenSSLContext # type: ignore[assignment]
144
+ util.ssl_.SSLContext = PyOpenSSLContext # type: ignore[assignment]
145
+ util.IS_PYOPENSSL = True
146
+ util.ssl_.IS_PYOPENSSL = True
147
+
148
+
149
+ def extract_from_urllib3() -> None:
150
+ "Undo monkey-patching by :func:`inject_into_urllib3`."
151
+
152
+ util.SSLContext = orig_util_SSLContext
153
+ util.ssl_.SSLContext = orig_util_SSLContext
154
+ util.IS_PYOPENSSL = False
155
+ util.ssl_.IS_PYOPENSSL = False
156
+
157
+
158
+ def _validate_dependencies_met() -> None:
159
+ """
160
+ Verifies that PyOpenSSL's package-level dependencies have been met.
161
+ Throws `ImportError` if they are not met.
162
+ """
163
+ # Method added in `cryptography==1.1`; not available in older versions
164
+ from cryptography.x509.extensions import Extensions
165
+
166
+ if getattr(Extensions, "get_extension_for_class", None) is None:
167
+ raise ImportError(
168
+ "'cryptography' module missing required functionality. "
169
+ "Try upgrading to v1.3.4 or newer."
170
+ )
171
+
172
+ # pyOpenSSL 0.14 and above use cryptography for OpenSSL bindings. The _x509
173
+ # attribute is only present on those versions.
174
+ from OpenSSL.crypto import X509
175
+
176
+ x509 = X509()
177
+ if getattr(x509, "_x509", None) is None:
178
+ raise ImportError(
179
+ "'pyOpenSSL' module missing required functionality. "
180
+ "Try upgrading to v0.14 or newer."
181
+ )
182
+
183
+
184
+ def _dnsname_to_stdlib(name: str) -> str | None:
185
+ """
186
+ Converts a dNSName SubjectAlternativeName field to the form used by the
187
+ standard library on the given Python version.
188
+
189
+ Cryptography produces a dNSName as a unicode string that was idna-decoded
190
+ from ASCII bytes. We need to idna-encode that string to get it back, and
191
+ then on Python 3 we also need to convert to unicode via UTF-8 (the stdlib
192
+ uses PyUnicode_FromStringAndSize on it, which decodes via UTF-8).
193
+
194
+ If the name cannot be idna-encoded then we return None signalling that
195
+ the name given should be skipped.
196
+ """
197
+
198
+ def idna_encode(name: str) -> bytes | None:
199
+ """
200
+ Borrowed wholesale from the Python Cryptography Project. It turns out
201
+ that we can't just safely call `idna.encode`: it can explode for
202
+ wildcard names. This avoids that problem.
203
+ """
204
+ from pip._vendor import idna
205
+
206
+ try:
207
+ for prefix in ["*.", "."]:
208
+ if name.startswith(prefix):
209
+ name = name[len(prefix) :]
210
+ return prefix.encode("ascii") + idna.encode(name)
211
+ return idna.encode(name)
212
+ except idna.core.IDNAError:
213
+ return None
214
+
215
+ # Don't send IPv6 addresses through the IDNA encoder.
216
+ if ":" in name:
217
+ return name
218
+
219
+ encoded_name = idna_encode(name)
220
+ if encoded_name is None:
221
+ return None
222
+ return encoded_name.decode("utf-8")
223
+
224
+
225
+ def get_subj_alt_name(peer_cert: X509) -> list[tuple[str, str]]:
226
+ """
227
+ Given an PyOpenSSL certificate, provides all the subject alternative names.
228
+ """
229
+ cert = peer_cert.to_cryptography()
230
+
231
+ # We want to find the SAN extension. Ask Cryptography to locate it (it's
232
+ # faster than looping in Python)
233
+ try:
234
+ ext = cert.extensions.get_extension_for_class(x509.SubjectAlternativeName).value
235
+ except x509.ExtensionNotFound:
236
+ # No such extension, return the empty list.
237
+ return []
238
+ except (
239
+ x509.DuplicateExtension,
240
+ UnsupportedExtension,
241
+ x509.UnsupportedGeneralNameType,
242
+ UnicodeError,
243
+ ) as e:
244
+ # A problem has been found with the quality of the certificate. Assume
245
+ # no SAN field is present.
246
+ log.warning(
247
+ "A problem was encountered with the certificate that prevented "
248
+ "urllib3 from finding the SubjectAlternativeName field. This can "
249
+ "affect certificate validation. The error was %s",
250
+ e,
251
+ )
252
+ return []
253
+
254
+ # We want to return dNSName and iPAddress fields. We need to cast the IPs
255
+ # back to strings because the match_hostname function wants them as
256
+ # strings.
257
+ # Sadly the DNS names need to be idna encoded and then, on Python 3, UTF-8
258
+ # decoded. This is pretty frustrating, but that's what the standard library
259
+ # does with certificates, and so we need to attempt to do the same.
260
+ # We also want to skip over names which cannot be idna encoded.
261
+ names = [
262
+ ("DNS", name)
263
+ for name in map(_dnsname_to_stdlib, ext.get_values_for_type(x509.DNSName))
264
+ if name is not None
265
+ ]
266
+ names.extend(
267
+ ("IP Address", str(name)) for name in ext.get_values_for_type(x509.IPAddress)
268
+ )
269
+
270
+ return names
271
+
272
+
273
+ class WrappedSocket:
274
+ """API-compatibility wrapper for Python OpenSSL's Connection-class."""
275
+
276
+ def __init__(
277
+ self,
278
+ connection: OpenSSL.SSL.Connection,
279
+ socket: socket_cls,
280
+ suppress_ragged_eofs: bool = True,
281
+ ) -> None:
282
+ self.connection = connection
283
+ self.socket = socket
284
+ self.suppress_ragged_eofs = suppress_ragged_eofs
285
+ self._io_refs = 0
286
+ self._closed = False
287
+
288
+ def fileno(self) -> int:
289
+ return self.socket.fileno()
290
+
291
+ # Copy-pasted from Python 3.5 source code
292
+ def _decref_socketios(self) -> None:
293
+ if self._io_refs > 0:
294
+ self._io_refs -= 1
295
+ if self._closed:
296
+ self.close()
297
+
298
+ def recv(self, *args: typing.Any, **kwargs: typing.Any) -> bytes:
299
+ try:
300
+ data = self.connection.recv(*args, **kwargs)
301
+ except OpenSSL.SSL.SysCallError as e:
302
+ if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"):
303
+ return b""
304
+ else:
305
+ raise OSError(e.args[0], str(e)) from e
306
+ except OpenSSL.SSL.ZeroReturnError:
307
+ if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
308
+ return b""
309
+ else:
310
+ raise
311
+ except OpenSSL.SSL.WantReadError as e:
312
+ if not util.wait_for_read(self.socket, self.socket.gettimeout()):
313
+ raise TimeoutError("The read operation timed out") from e
314
+ else:
315
+ return self.recv(*args, **kwargs)
316
+
317
+ # TLS 1.3 post-handshake authentication
318
+ except OpenSSL.SSL.Error as e:
319
+ raise ssl.SSLError(f"read error: {e!r}") from e
320
+ else:
321
+ return data # type: ignore[no-any-return]
322
+
323
+ def recv_into(self, *args: typing.Any, **kwargs: typing.Any) -> int:
324
+ try:
325
+ return self.connection.recv_into(*args, **kwargs) # type: ignore[no-any-return]
326
+ except OpenSSL.SSL.SysCallError as e:
327
+ if self.suppress_ragged_eofs and e.args == (-1, "Unexpected EOF"):
328
+ return 0
329
+ else:
330
+ raise OSError(e.args[0], str(e)) from e
331
+ except OpenSSL.SSL.ZeroReturnError:
332
+ if self.connection.get_shutdown() == OpenSSL.SSL.RECEIVED_SHUTDOWN:
333
+ return 0
334
+ else:
335
+ raise
336
+ except OpenSSL.SSL.WantReadError as e:
337
+ if not util.wait_for_read(self.socket, self.socket.gettimeout()):
338
+ raise TimeoutError("The read operation timed out") from e
339
+ else:
340
+ return self.recv_into(*args, **kwargs)
341
+
342
+ # TLS 1.3 post-handshake authentication
343
+ except OpenSSL.SSL.Error as e:
344
+ raise ssl.SSLError(f"read error: {e!r}") from e
345
+
346
+ def settimeout(self, timeout: float) -> None:
347
+ return self.socket.settimeout(timeout)
348
+
349
+ def _send_until_done(self, data: bytes) -> int:
350
+ while True:
351
+ try:
352
+ return self.connection.send(data) # type: ignore[no-any-return]
353
+ except OpenSSL.SSL.WantWriteError as e:
354
+ if not util.wait_for_write(self.socket, self.socket.gettimeout()):
355
+ raise TimeoutError() from e
356
+ continue
357
+ except OpenSSL.SSL.SysCallError as e:
358
+ raise OSError(e.args[0], str(e)) from e
359
+
360
+ def sendall(self, data: bytes) -> None:
361
+ total_sent = 0
362
+ while total_sent < len(data):
363
+ sent = self._send_until_done(
364
+ data[total_sent : total_sent + SSL_WRITE_BLOCKSIZE]
365
+ )
366
+ total_sent += sent
367
+
368
+ def shutdown(self, how: int) -> None:
369
+ try:
370
+ self.connection.shutdown()
371
+ except OpenSSL.SSL.Error as e:
372
+ raise ssl.SSLError(f"shutdown error: {e!r}") from e
373
+
374
+ def close(self) -> None:
375
+ self._closed = True
376
+ if self._io_refs <= 0:
377
+ self._real_close()
378
+
379
+ def _real_close(self) -> None:
380
+ try:
381
+ return self.connection.close() # type: ignore[no-any-return]
382
+ except OpenSSL.SSL.Error:
383
+ return
384
+
385
+ def getpeercert(
386
+ self, binary_form: bool = False
387
+ ) -> dict[str, list[typing.Any]] | None:
388
+ x509 = self.connection.get_peer_certificate()
389
+
390
+ if not x509:
391
+ return x509 # type: ignore[no-any-return]
392
+
393
+ if binary_form:
394
+ return OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_ASN1, x509) # type: ignore[no-any-return]
395
+
396
+ return {
397
+ "subject": ((("commonName", x509.get_subject().CN),),), # type: ignore[dict-item]
398
+ "subjectAltName": get_subj_alt_name(x509),
399
+ }
400
+
401
+ def version(self) -> str:
402
+ return self.connection.get_protocol_version_name() # type: ignore[no-any-return]
403
+
404
+ def selected_alpn_protocol(self) -> str | None:
405
+ alpn_proto = self.connection.get_alpn_proto_negotiated()
406
+ return alpn_proto.decode() if alpn_proto else None
407
+
408
+
409
+ WrappedSocket.makefile = socket_cls.makefile # type: ignore[attr-defined]
410
+
411
+
412
+ class PyOpenSSLContext:
413
+ """
414
+ I am a wrapper class for the PyOpenSSL ``Context`` object. I am responsible
415
+ for translating the interface of the standard library ``SSLContext`` object
416
+ to calls into PyOpenSSL.
417
+ """
418
+
419
+ def __init__(self, protocol: int) -> None:
420
+ self.protocol = _openssl_versions[protocol]
421
+ self._ctx = OpenSSL.SSL.Context(self.protocol)
422
+ self._options = 0
423
+ self.check_hostname = False
424
+ self._minimum_version: int = ssl.TLSVersion.MINIMUM_SUPPORTED
425
+ self._maximum_version: int = ssl.TLSVersion.MAXIMUM_SUPPORTED
426
+ self._verify_flags: int = ssl.VERIFY_X509_TRUSTED_FIRST
427
+
428
+ @property
429
+ def options(self) -> int:
430
+ return self._options
431
+
432
+ @options.setter
433
+ def options(self, value: int) -> None:
434
+ self._options = value
435
+ self._set_ctx_options()
436
+
437
+ @property
438
+ def verify_flags(self) -> int:
439
+ return self._verify_flags
440
+
441
+ @verify_flags.setter
442
+ def verify_flags(self, value: int) -> None:
443
+ self._verify_flags = value
444
+ self._ctx.get_cert_store().set_flags(self._verify_flags)
445
+
446
+ @property
447
+ def verify_mode(self) -> int:
448
+ return _openssl_to_stdlib_verify[self._ctx.get_verify_mode()]
449
+
450
+ @verify_mode.setter
451
+ def verify_mode(self, value: ssl.VerifyMode) -> None:
452
+ self._ctx.set_verify(_stdlib_to_openssl_verify[value], _verify_callback)
453
+
454
+ def set_default_verify_paths(self) -> None:
455
+ self._ctx.set_default_verify_paths()
456
+
457
+ def set_ciphers(self, ciphers: bytes | str) -> None:
458
+ if isinstance(ciphers, str):
459
+ ciphers = ciphers.encode("utf-8")
460
+ self._ctx.set_cipher_list(ciphers)
461
+
462
+ def load_verify_locations(
463
+ self,
464
+ cafile: str | None = None,
465
+ capath: str | None = None,
466
+ cadata: bytes | None = None,
467
+ ) -> None:
468
+ if cafile is not None:
469
+ cafile = cafile.encode("utf-8") # type: ignore[assignment]
470
+ if capath is not None:
471
+ capath = capath.encode("utf-8") # type: ignore[assignment]
472
+ try:
473
+ self._ctx.load_verify_locations(cafile, capath)
474
+ if cadata is not None:
475
+ self._ctx.load_verify_locations(BytesIO(cadata))
476
+ except OpenSSL.SSL.Error as e:
477
+ raise ssl.SSLError(f"unable to load trusted certificates: {e!r}") from e
478
+
479
+ def load_cert_chain(
480
+ self,
481
+ certfile: str,
482
+ keyfile: str | None = None,
483
+ password: str | None = None,
484
+ ) -> None:
485
+ try:
486
+ self._ctx.use_certificate_chain_file(certfile)
487
+ if password is not None:
488
+ if not isinstance(password, bytes):
489
+ password = password.encode("utf-8") # type: ignore[assignment]
490
+ self._ctx.set_passwd_cb(lambda *_: password)
491
+ self._ctx.use_privatekey_file(keyfile or certfile)
492
+ except OpenSSL.SSL.Error as e:
493
+ raise ssl.SSLError(f"Unable to load certificate chain: {e!r}") from e
494
+
495
+ def set_alpn_protocols(self, protocols: list[bytes | str]) -> None:
496
+ protocols = [util.util.to_bytes(p, "ascii") for p in protocols]
497
+ return self._ctx.set_alpn_protos(protocols) # type: ignore[no-any-return]
498
+
499
+ def wrap_socket(
500
+ self,
501
+ sock: socket_cls,
502
+ server_side: bool = False,
503
+ do_handshake_on_connect: bool = True,
504
+ suppress_ragged_eofs: bool = True,
505
+ server_hostname: bytes | str | None = None,
506
+ ) -> WrappedSocket:
507
+ cnx = OpenSSL.SSL.Connection(self._ctx, sock)
508
+
509
+ # If server_hostname is an IP, don't use it for SNI, per RFC6066 Section 3
510
+ if server_hostname and not util.ssl_.is_ipaddress(server_hostname):
511
+ if isinstance(server_hostname, str):
512
+ server_hostname = server_hostname.encode("utf-8")
513
+ cnx.set_tlsext_host_name(server_hostname)
514
+
515
+ cnx.set_connect_state()
516
+
517
+ while True:
518
+ try:
519
+ cnx.do_handshake()
520
+ except OpenSSL.SSL.WantReadError as e:
521
+ if not util.wait_for_read(sock, sock.gettimeout()):
522
+ raise TimeoutError("select timed out") from e
523
+ continue
524
+ except OpenSSL.SSL.Error as e:
525
+ raise ssl.SSLError(f"bad handshake: {e!r}") from e
526
+ break
527
+
528
+ return WrappedSocket(cnx, sock)
529
+
530
+ def _set_ctx_options(self) -> None:
531
+ self._ctx.set_options(
532
+ self._options
533
+ | _openssl_to_ssl_minimum_version[self._minimum_version]
534
+ | _openssl_to_ssl_maximum_version[self._maximum_version]
535
+ )
536
+
537
+ @property
538
+ def minimum_version(self) -> int:
539
+ return self._minimum_version
540
+
541
+ @minimum_version.setter
542
+ def minimum_version(self, minimum_version: int) -> None:
543
+ self._minimum_version = minimum_version
544
+ self._set_ctx_options()
545
+
546
+ @property
547
+ def maximum_version(self) -> int:
548
+ return self._maximum_version
549
+
550
+ @maximum_version.setter
551
+ def maximum_version(self, maximum_version: int) -> None:
552
+ self._maximum_version = maximum_version
553
+ self._set_ctx_options()
554
+
555
+
556
+ def _verify_callback(
557
+ cnx: OpenSSL.SSL.Connection,
558
+ x509: X509,
559
+ err_no: int,
560
+ err_depth: int,
561
+ return_code: int,
562
+ ) -> bool:
563
+ return err_no == 0
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/contrib/socks.py ADDED
@@ -0,0 +1,228 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ This module contains provisional support for SOCKS proxies from within
3
+ urllib3. This module supports SOCKS4, SOCKS4A (an extension of SOCKS4), and
4
+ SOCKS5. To enable its functionality, either install PySocks or install this
5
+ module with the ``socks`` extra.
6
+
7
+ The SOCKS implementation supports the full range of urllib3 features. It also
8
+ supports the following SOCKS features:
9
+
10
+ - SOCKS4A (``proxy_url='socks4a://...``)
11
+ - SOCKS4 (``proxy_url='socks4://...``)
12
+ - SOCKS5 with remote DNS (``proxy_url='socks5h://...``)
13
+ - SOCKS5 with local DNS (``proxy_url='socks5://...``)
14
+ - Usernames and passwords for the SOCKS proxy
15
+
16
+ .. note::
17
+ It is recommended to use ``socks5h://`` or ``socks4a://`` schemes in
18
+ your ``proxy_url`` to ensure that DNS resolution is done from the remote
19
+ server instead of client-side when connecting to a domain name.
20
+
21
+ SOCKS4 supports IPv4 and domain names with the SOCKS4A extension. SOCKS5
22
+ supports IPv4, IPv6, and domain names.
23
+
24
+ When connecting to a SOCKS4 proxy the ``username`` portion of the ``proxy_url``
25
+ will be sent as the ``userid`` section of the SOCKS request:
26
+
27
+ .. code-block:: python
28
+
29
+ proxy_url="socks4a://<userid>@proxy-host"
30
+
31
+ When connecting to a SOCKS5 proxy the ``username`` and ``password`` portion
32
+ of the ``proxy_url`` will be sent as the username/password to authenticate
33
+ with the proxy:
34
+
35
+ .. code-block:: python
36
+
37
+ proxy_url="socks5h://<username>:<password>@proxy-host"
38
+
39
+ """
40
+
41
+ from __future__ import annotations
42
+
43
+ try:
44
+ import socks # type: ignore[import-untyped]
45
+ except ImportError:
46
+ import warnings
47
+
48
+ from ..exceptions import DependencyWarning
49
+
50
+ warnings.warn(
51
+ (
52
+ "SOCKS support in urllib3 requires the installation of optional "
53
+ "dependencies: specifically, PySocks. For more information, see "
54
+ "https://urllib3.readthedocs.io/en/latest/advanced-usage.html#socks-proxies"
55
+ ),
56
+ DependencyWarning,
57
+ )
58
+ raise
59
+
60
+ import typing
61
+ from socket import timeout as SocketTimeout
62
+
63
+ from ..connection import HTTPConnection, HTTPSConnection
64
+ from ..connectionpool import HTTPConnectionPool, HTTPSConnectionPool
65
+ from ..exceptions import ConnectTimeoutError, NewConnectionError
66
+ from ..poolmanager import PoolManager
67
+ from ..util.url import parse_url
68
+
69
+ try:
70
+ import ssl
71
+ except ImportError:
72
+ ssl = None # type: ignore[assignment]
73
+
74
+
75
+ class _TYPE_SOCKS_OPTIONS(typing.TypedDict):
76
+ socks_version: int
77
+ proxy_host: str | None
78
+ proxy_port: str | None
79
+ username: str | None
80
+ password: str | None
81
+ rdns: bool
82
+
83
+
84
+ class SOCKSConnection(HTTPConnection):
85
+ """
86
+ A plain-text HTTP connection that connects via a SOCKS proxy.
87
+ """
88
+
89
+ def __init__(
90
+ self,
91
+ _socks_options: _TYPE_SOCKS_OPTIONS,
92
+ *args: typing.Any,
93
+ **kwargs: typing.Any,
94
+ ) -> None:
95
+ self._socks_options = _socks_options
96
+ super().__init__(*args, **kwargs)
97
+
98
+ def _new_conn(self) -> socks.socksocket:
99
+ """
100
+ Establish a new connection via the SOCKS proxy.
101
+ """
102
+ extra_kw: dict[str, typing.Any] = {}
103
+ if self.source_address:
104
+ extra_kw["source_address"] = self.source_address
105
+
106
+ if self.socket_options:
107
+ extra_kw["socket_options"] = self.socket_options
108
+
109
+ try:
110
+ conn = socks.create_connection(
111
+ (self.host, self.port),
112
+ proxy_type=self._socks_options["socks_version"],
113
+ proxy_addr=self._socks_options["proxy_host"],
114
+ proxy_port=self._socks_options["proxy_port"],
115
+ proxy_username=self._socks_options["username"],
116
+ proxy_password=self._socks_options["password"],
117
+ proxy_rdns=self._socks_options["rdns"],
118
+ timeout=self.timeout,
119
+ **extra_kw,
120
+ )
121
+
122
+ except SocketTimeout as e:
123
+ raise ConnectTimeoutError(
124
+ self,
125
+ f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
126
+ ) from e
127
+
128
+ except socks.ProxyError as e:
129
+ # This is fragile as hell, but it seems to be the only way to raise
130
+ # useful errors here.
131
+ if e.socket_err:
132
+ error = e.socket_err
133
+ if isinstance(error, SocketTimeout):
134
+ raise ConnectTimeoutError(
135
+ self,
136
+ f"Connection to {self.host} timed out. (connect timeout={self.timeout})",
137
+ ) from e
138
+ else:
139
+ # Adding `from e` messes with coverage somehow, so it's omitted.
140
+ # See #2386.
141
+ raise NewConnectionError(
142
+ self, f"Failed to establish a new connection: {error}"
143
+ )
144
+ else: # Defensive: see https://github.com/urllib3/urllib3/pull/3728#pullrequestreview-3816302703
145
+ raise NewConnectionError(
146
+ self, f"Failed to establish a new connection: {e}"
147
+ ) from e
148
+
149
+ except OSError as e: # Defensive: PySocks should catch all these.
150
+ raise NewConnectionError(
151
+ self, f"Failed to establish a new connection: {e}"
152
+ ) from e
153
+
154
+ return conn
155
+
156
+
157
+ # We don't need to duplicate the Verified/Unverified distinction from
158
+ # urllib3/connection.py here because the HTTPSConnection will already have been
159
+ # correctly set to either the Verified or Unverified form by that module. This
160
+ # means the SOCKSHTTPSConnection will automatically be the correct type.
161
+ class SOCKSHTTPSConnection(SOCKSConnection, HTTPSConnection):
162
+ pass
163
+
164
+
165
+ class SOCKSHTTPConnectionPool(HTTPConnectionPool):
166
+ ConnectionCls = SOCKSConnection
167
+
168
+
169
+ class SOCKSHTTPSConnectionPool(HTTPSConnectionPool):
170
+ ConnectionCls = SOCKSHTTPSConnection
171
+
172
+
173
+ class SOCKSProxyManager(PoolManager):
174
+ """
175
+ A version of the urllib3 ProxyManager that routes connections via the
176
+ defined SOCKS proxy.
177
+ """
178
+
179
+ pool_classes_by_scheme = {
180
+ "http": SOCKSHTTPConnectionPool,
181
+ "https": SOCKSHTTPSConnectionPool,
182
+ }
183
+
184
+ def __init__(
185
+ self,
186
+ proxy_url: str,
187
+ username: str | None = None,
188
+ password: str | None = None,
189
+ num_pools: int = 10,
190
+ headers: typing.Mapping[str, str] | None = None,
191
+ **connection_pool_kw: typing.Any,
192
+ ):
193
+ parsed = parse_url(proxy_url)
194
+
195
+ if username is None and password is None and parsed.auth is not None:
196
+ split = parsed.auth.split(":")
197
+ if len(split) == 2:
198
+ username, password = split
199
+ if parsed.scheme == "socks5":
200
+ socks_version = socks.PROXY_TYPE_SOCKS5
201
+ rdns = False
202
+ elif parsed.scheme == "socks5h":
203
+ socks_version = socks.PROXY_TYPE_SOCKS5
204
+ rdns = True
205
+ elif parsed.scheme == "socks4":
206
+ socks_version = socks.PROXY_TYPE_SOCKS4
207
+ rdns = False
208
+ elif parsed.scheme == "socks4a":
209
+ socks_version = socks.PROXY_TYPE_SOCKS4
210
+ rdns = True
211
+ else:
212
+ raise ValueError(f"Unable to determine SOCKS version from {proxy_url}")
213
+
214
+ self.proxy_url = proxy_url
215
+
216
+ socks_options = {
217
+ "socks_version": socks_version,
218
+ "proxy_host": parsed.host,
219
+ "proxy_port": parsed.port,
220
+ "username": username,
221
+ "password": password,
222
+ "rdns": rdns,
223
+ }
224
+ connection_pool_kw["_socks_options"] = socks_options
225
+
226
+ super().__init__(num_pools, headers, **connection_pool_kw)
227
+
228
+ self.pool_classes_by_scheme = SOCKSProxyManager.pool_classes_by_scheme
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/exceptions.py ADDED
@@ -0,0 +1,335 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import socket
4
+ import typing
5
+ import warnings
6
+ from email.errors import MessageDefect
7
+ from http.client import IncompleteRead as httplib_IncompleteRead
8
+
9
+ if typing.TYPE_CHECKING:
10
+ from .connection import HTTPConnection
11
+ from .connectionpool import ConnectionPool
12
+ from .response import HTTPResponse
13
+ from .util.retry import Retry
14
+
15
+ # Base Exceptions
16
+
17
+
18
+ class HTTPError(Exception):
19
+ """Base exception used by this module."""
20
+
21
+
22
+ class HTTPWarning(Warning):
23
+ """Base warning used by this module."""
24
+
25
+
26
+ _TYPE_REDUCE_RESULT = tuple[typing.Callable[..., object], tuple[object, ...]]
27
+
28
+
29
+ class PoolError(HTTPError):
30
+ """Base exception for errors caused within a pool."""
31
+
32
+ def __init__(self, pool: ConnectionPool, message: str) -> None:
33
+ self.pool = pool
34
+ self._message = message
35
+ super().__init__(f"{pool}: {message}")
36
+
37
+ def __reduce__(self) -> _TYPE_REDUCE_RESULT:
38
+ # For pickling purposes.
39
+ return self.__class__, (None, self._message)
40
+
41
+
42
+ class RequestError(PoolError):
43
+ """Base exception for PoolErrors that have associated URLs."""
44
+
45
+ def __init__(self, pool: ConnectionPool, url: str | None, message: str) -> None:
46
+ self.url = url
47
+ super().__init__(pool, message)
48
+
49
+ def __reduce__(self) -> _TYPE_REDUCE_RESULT:
50
+ # For pickling purposes.
51
+ return self.__class__, (None, self.url, self._message)
52
+
53
+
54
+ class SSLError(HTTPError):
55
+ """Raised when SSL certificate fails in an HTTPS connection."""
56
+
57
+
58
+ class ProxyError(HTTPError):
59
+ """Raised when the connection to a proxy fails."""
60
+
61
+ # The original error is also available as __cause__.
62
+ original_error: Exception
63
+
64
+ def __init__(self, message: str, error: Exception) -> None:
65
+ super().__init__(message, error)
66
+ self.original_error = error
67
+
68
+
69
+ class DecodeError(HTTPError):
70
+ """Raised when automatic decoding based on Content-Type fails."""
71
+
72
+
73
+ class ProtocolError(HTTPError):
74
+ """Raised when something unexpected happens mid-request/response."""
75
+
76
+
77
+ #: Renamed to ProtocolError but aliased for backwards compatibility.
78
+ ConnectionError = ProtocolError
79
+
80
+
81
+ # Leaf Exceptions
82
+
83
+
84
+ class MaxRetryError(RequestError):
85
+ """Raised when the maximum number of retries is exceeded.
86
+
87
+ :param pool: The connection pool
88
+ :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool`
89
+ :param str url: The requested Url
90
+ :param reason: The underlying error
91
+ :type reason: :class:`Exception`
92
+
93
+ """
94
+
95
+ def __init__(
96
+ self, pool: ConnectionPool, url: str | None, reason: Exception | None = None
97
+ ) -> None:
98
+ self.reason = reason
99
+
100
+ message = f"Max retries exceeded with url: {url} (Caused by {reason!r})"
101
+
102
+ super().__init__(pool, url, message)
103
+
104
+ def __reduce__(self) -> _TYPE_REDUCE_RESULT:
105
+ # For pickling purposes.
106
+ return self.__class__, (None, self.url, self.reason)
107
+
108
+
109
+ class HostChangedError(RequestError):
110
+ """Raised when an existing pool gets a request for a foreign host."""
111
+
112
+ def __init__(
113
+ self, pool: ConnectionPool, url: str, retries: Retry | int = 3
114
+ ) -> None:
115
+ message = f"Tried to open a foreign host with url: {url}"
116
+ super().__init__(pool, url, message)
117
+ self.retries = retries
118
+
119
+
120
+ class TimeoutStateError(HTTPError):
121
+ """Raised when passing an invalid state to a timeout"""
122
+
123
+
124
+ class TimeoutError(HTTPError):
125
+ """Raised when a socket timeout error occurs.
126
+
127
+ Catching this error will catch both :exc:`ReadTimeoutErrors
128
+ <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`.
129
+ """
130
+
131
+
132
+ class ReadTimeoutError(TimeoutError, RequestError):
133
+ """Raised when a socket timeout occurs while receiving data from a server"""
134
+
135
+
136
+ # This timeout error does not have a URL attached and needs to inherit from the
137
+ # base HTTPError
138
+ class ConnectTimeoutError(TimeoutError):
139
+ """Raised when a socket timeout occurs while connecting to a server"""
140
+
141
+
142
+ class NewConnectionError(ConnectTimeoutError, HTTPError):
143
+ """Raised when we fail to establish a new connection. Usually ECONNREFUSED."""
144
+
145
+ def __init__(self, conn: HTTPConnection, message: str) -> None:
146
+ self.conn = conn
147
+ self._message = message
148
+ super().__init__(f"{conn}: {message}")
149
+
150
+ def __reduce__(self) -> _TYPE_REDUCE_RESULT:
151
+ # For pickling purposes.
152
+ return self.__class__, (None, self._message)
153
+
154
+ @property
155
+ def pool(self) -> HTTPConnection:
156
+ warnings.warn(
157
+ "The 'pool' property is deprecated and will be removed "
158
+ "in urllib3 v3.0. Use 'conn' instead.",
159
+ FutureWarning,
160
+ stacklevel=2,
161
+ )
162
+
163
+ return self.conn
164
+
165
+
166
+ class NameResolutionError(NewConnectionError):
167
+ """Raised when host name resolution fails."""
168
+
169
+ def __init__(self, host: str, conn: HTTPConnection, reason: socket.gaierror):
170
+ message = f"Failed to resolve '{host}' ({reason})"
171
+ self._host = host
172
+ self._reason = reason
173
+ super().__init__(conn, message)
174
+
175
+ def __reduce__(self) -> _TYPE_REDUCE_RESULT:
176
+ # For pickling purposes.
177
+ return self.__class__, (self._host, None, self._reason)
178
+
179
+
180
+ class EmptyPoolError(PoolError):
181
+ """Raised when a pool runs out of connections and no more are allowed."""
182
+
183
+
184
+ class FullPoolError(PoolError):
185
+ """Raised when we try to add a connection to a full pool in blocking mode."""
186
+
187
+
188
+ class ClosedPoolError(PoolError):
189
+ """Raised when a request enters a pool after the pool has been closed."""
190
+
191
+
192
+ class LocationValueError(ValueError, HTTPError):
193
+ """Raised when there is something wrong with a given URL input."""
194
+
195
+
196
+ class LocationParseError(LocationValueError):
197
+ """Raised when get_host or similar fails to parse the URL input."""
198
+
199
+ def __init__(self, location: str) -> None:
200
+ message = f"Failed to parse: {location}"
201
+ super().__init__(message)
202
+
203
+ self.location = location
204
+
205
+
206
+ class URLSchemeUnknown(LocationValueError):
207
+ """Raised when a URL input has an unsupported scheme."""
208
+
209
+ def __init__(self, scheme: str):
210
+ message = f"Not supported URL scheme {scheme}"
211
+ super().__init__(message)
212
+
213
+ self.scheme = scheme
214
+
215
+
216
+ class ResponseError(HTTPError):
217
+ """Used as a container for an error reason supplied in a MaxRetryError."""
218
+
219
+ GENERIC_ERROR = "too many error responses"
220
+ SPECIFIC_ERROR = "too many {status_code} error responses"
221
+
222
+
223
+ class SecurityWarning(HTTPWarning):
224
+ """Warned when performing security reducing actions"""
225
+
226
+
227
+ class InsecureRequestWarning(SecurityWarning):
228
+ """Warned when making an unverified HTTPS request."""
229
+
230
+
231
+ class NotOpenSSLWarning(SecurityWarning):
232
+ """Warned when using unsupported SSL library"""
233
+
234
+
235
+ class SystemTimeWarning(SecurityWarning):
236
+ """Warned when system time is suspected to be wrong"""
237
+
238
+
239
+ class InsecurePlatformWarning(SecurityWarning):
240
+ """Warned when certain TLS/SSL configuration is not available on a platform."""
241
+
242
+
243
+ class DependencyWarning(HTTPWarning):
244
+ """
245
+ Warned when an attempt is made to import a module with missing optional
246
+ dependencies.
247
+ """
248
+
249
+
250
+ class ResponseNotChunked(ProtocolError, ValueError):
251
+ """Response needs to be chunked in order to read it as chunks."""
252
+
253
+
254
+ class BodyNotHttplibCompatible(HTTPError):
255
+ """
256
+ Body should be :class:`http.client.HTTPResponse` like
257
+ (have an fp attribute which returns raw chunks) for read_chunked().
258
+ """
259
+
260
+
261
+ class IncompleteRead(HTTPError, httplib_IncompleteRead):
262
+ """
263
+ Response length doesn't match expected Content-Length
264
+
265
+ Subclass of :class:`http.client.IncompleteRead` to allow int value
266
+ for ``partial`` to avoid creating large objects on streamed reads.
267
+ """
268
+
269
+ partial: int # type: ignore[assignment]
270
+ expected: int
271
+
272
+ def __init__(self, partial: int, expected: int) -> None:
273
+ self.partial = partial
274
+ self.expected = expected
275
+
276
+ def __repr__(self) -> str:
277
+ return "IncompleteRead(%i bytes read, %i more expected)" % (
278
+ self.partial,
279
+ self.expected,
280
+ )
281
+
282
+
283
+ class InvalidChunkLength(HTTPError, httplib_IncompleteRead):
284
+ """Invalid chunk length in a chunked response."""
285
+
286
+ def __init__(self, response: HTTPResponse, length: bytes) -> None:
287
+ self.partial: int = response.tell() # type: ignore[assignment]
288
+ self.expected: int | None = response.length_remaining
289
+ self.response = response
290
+ self.length = length
291
+
292
+ def __repr__(self) -> str:
293
+ return "InvalidChunkLength(got length %r, %i bytes read)" % (
294
+ self.length,
295
+ self.partial,
296
+ )
297
+
298
+
299
+ class InvalidHeader(HTTPError):
300
+ """The header provided was somehow invalid."""
301
+
302
+
303
+ class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
304
+ """ProxyManager does not support the supplied scheme"""
305
+
306
+ # TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
307
+
308
+ def __init__(self, scheme: str | None) -> None:
309
+ # 'localhost' is here because our URL parser parses
310
+ # localhost:8080 -> scheme=localhost, remove if we fix this.
311
+ if scheme == "localhost":
312
+ scheme = None
313
+ if scheme is None:
314
+ message = "Proxy URL had no scheme, should start with http:// or https://"
315
+ else:
316
+ message = f"Proxy URL had unsupported scheme {scheme}, should use http:// or https://"
317
+ super().__init__(message)
318
+
319
+
320
+ class ProxySchemeUnsupported(ValueError):
321
+ """Fetching HTTPS resources through HTTPS proxies is unsupported"""
322
+
323
+
324
+ class HeaderParsingError(HTTPError):
325
+ """Raised by assert_header_parsing, but we convert it to a log.warning statement."""
326
+
327
+ def __init__(
328
+ self, defects: list[MessageDefect], unparsed_data: bytes | str | None
329
+ ) -> None:
330
+ message = f"{defects or 'Unknown'}, unparsed data: {unparsed_data!r}"
331
+ super().__init__(message)
332
+
333
+
334
+ class UnrewindableBodyError(HTTPError):
335
+ """urllib3 encountered an error when trying to rewind a body"""
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/fields.py ADDED
@@ -0,0 +1,341 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import email.utils
4
+ import mimetypes
5
+ import typing
6
+
7
+ _TYPE_FIELD_VALUE = typing.Union[str, bytes]
8
+ _TYPE_FIELD_VALUE_TUPLE = typing.Union[
9
+ _TYPE_FIELD_VALUE,
10
+ tuple[str, _TYPE_FIELD_VALUE],
11
+ tuple[str, _TYPE_FIELD_VALUE, str],
12
+ ]
13
+
14
+
15
+ def guess_content_type(
16
+ filename: str | None, default: str = "application/octet-stream"
17
+ ) -> str:
18
+ """
19
+ Guess the "Content-Type" of a file.
20
+
21
+ :param filename:
22
+ The filename to guess the "Content-Type" of using :mod:`mimetypes`.
23
+ :param default:
24
+ If no "Content-Type" can be guessed, default to `default`.
25
+ """
26
+ if filename:
27
+ return mimetypes.guess_type(filename)[0] or default
28
+ return default
29
+
30
+
31
+ def format_header_param_rfc2231(name: str, value: _TYPE_FIELD_VALUE) -> str:
32
+ """
33
+ Helper function to format and quote a single header parameter using the
34
+ strategy defined in RFC 2231.
35
+
36
+ Particularly useful for header parameters which might contain
37
+ non-ASCII values, like file names. This follows
38
+ `RFC 2388 Section 4.4 <https://tools.ietf.org/html/rfc2388#section-4.4>`_.
39
+
40
+ :param name:
41
+ The name of the parameter, a string expected to be ASCII only.
42
+ :param value:
43
+ The value of the parameter, provided as ``bytes`` or `str``.
44
+ :returns:
45
+ An RFC-2231-formatted unicode string.
46
+
47
+ .. deprecated:: 2.0.0
48
+ Will be removed in urllib3 v3.0. This is not valid for
49
+ ``multipart/form-data`` header parameters.
50
+ """
51
+ import warnings
52
+
53
+ warnings.warn(
54
+ "'format_header_param_rfc2231' is insecure, deprecated and will be "
55
+ "removed in urllib3 v3.0. This is not valid for "
56
+ "multipart/form-data header parameters.",
57
+ FutureWarning,
58
+ stacklevel=2,
59
+ )
60
+
61
+ if isinstance(value, bytes):
62
+ value = value.decode("utf-8")
63
+
64
+ if not any(ch in value for ch in '"\\\r\n'):
65
+ result = f'{name}="{value}"'
66
+ try:
67
+ result.encode("ascii")
68
+ except (UnicodeEncodeError, UnicodeDecodeError):
69
+ pass
70
+ else:
71
+ return result
72
+
73
+ value = email.utils.encode_rfc2231(value, "utf-8")
74
+ value = f"{name}*={value}"
75
+
76
+ return value
77
+
78
+
79
+ def format_multipart_header_param(name: str, value: _TYPE_FIELD_VALUE) -> str:
80
+ """
81
+ Format and quote a single multipart header parameter.
82
+
83
+ This follows the `WHATWG HTML Standard`_ as of 2021/06/10, matching
84
+ the behavior of current browser and curl versions. Values are
85
+ assumed to be UTF-8. The ``\\n``, ``\\r``, and ``"`` characters are
86
+ percent encoded.
87
+
88
+ .. _WHATWG HTML Standard:
89
+ https://html.spec.whatwg.org/multipage/
90
+ form-control-infrastructure.html#multipart-form-data
91
+
92
+ :param name:
93
+ The name of the parameter, an ASCII-only ``str``.
94
+ :param value:
95
+ The value of the parameter, a ``str`` or UTF-8 encoded
96
+ ``bytes``.
97
+ :returns:
98
+ A string ``name="value"`` with the escaped value.
99
+
100
+ .. versionchanged:: 2.0.0
101
+ Matches the WHATWG HTML Standard as of 2021/06/10. Control
102
+ characters are no longer percent encoded.
103
+
104
+ .. versionchanged:: 2.0.0
105
+ Renamed from ``format_header_param_html5`` and
106
+ ``format_header_param``. The old names will be removed in
107
+ urllib3 v3.0.
108
+ """
109
+ if isinstance(value, bytes):
110
+ value = value.decode("utf-8")
111
+
112
+ # percent encode \n \r "
113
+ value = value.translate({10: "%0A", 13: "%0D", 34: "%22"})
114
+ return f'{name}="{value}"'
115
+
116
+
117
+ def format_header_param_html5(name: str, value: _TYPE_FIELD_VALUE) -> str:
118
+ """
119
+ .. deprecated:: 2.0.0
120
+ Renamed to :func:`format_multipart_header_param`. Will be
121
+ removed in urllib3 v3.0.
122
+ """
123
+ import warnings
124
+
125
+ warnings.warn(
126
+ "'format_header_param_html5' has been renamed to "
127
+ "'format_multipart_header_param'. The old name will be "
128
+ "removed in urllib3 v3.0.",
129
+ FutureWarning,
130
+ stacklevel=2,
131
+ )
132
+ return format_multipart_header_param(name, value)
133
+
134
+
135
+ def format_header_param(name: str, value: _TYPE_FIELD_VALUE) -> str:
136
+ """
137
+ .. deprecated:: 2.0.0
138
+ Renamed to :func:`format_multipart_header_param`. Will be
139
+ removed in urllib3 v3.0.
140
+ """
141
+ import warnings
142
+
143
+ warnings.warn(
144
+ "'format_header_param' has been renamed to "
145
+ "'format_multipart_header_param'. The old name will be "
146
+ "removed in urllib3 v3.0.",
147
+ FutureWarning,
148
+ stacklevel=2,
149
+ )
150
+ return format_multipart_header_param(name, value)
151
+
152
+
153
+ class RequestField:
154
+ """
155
+ A data container for request body parameters.
156
+
157
+ :param name:
158
+ The name of this request field. Must be unicode.
159
+ :param data:
160
+ The data/value body.
161
+ :param filename:
162
+ An optional filename of the request field. Must be unicode.
163
+ :param headers:
164
+ An optional dict-like object of headers to initially use for the field.
165
+
166
+ .. versionchanged:: 2.0.0
167
+ The ``header_formatter`` parameter is deprecated and will
168
+ be removed in urllib3 v3.0.
169
+ """
170
+
171
+ def __init__(
172
+ self,
173
+ name: str,
174
+ data: _TYPE_FIELD_VALUE,
175
+ filename: str | None = None,
176
+ headers: typing.Mapping[str, str] | None = None,
177
+ header_formatter: typing.Callable[[str, _TYPE_FIELD_VALUE], str] | None = None,
178
+ ):
179
+ self._name = name
180
+ self._filename = filename
181
+ self.data = data
182
+ self.headers: dict[str, str | None] = {}
183
+ if headers:
184
+ self.headers = dict(headers)
185
+
186
+ if header_formatter is not None:
187
+ import warnings
188
+
189
+ warnings.warn(
190
+ "The 'header_formatter' parameter is deprecated and "
191
+ "will be removed in urllib3 v3.0.",
192
+ FutureWarning,
193
+ stacklevel=2,
194
+ )
195
+ self.header_formatter = header_formatter
196
+ else:
197
+ self.header_formatter = format_multipart_header_param
198
+
199
+ @classmethod
200
+ def from_tuples(
201
+ cls,
202
+ fieldname: str,
203
+ value: _TYPE_FIELD_VALUE_TUPLE,
204
+ header_formatter: typing.Callable[[str, _TYPE_FIELD_VALUE], str] | None = None,
205
+ ) -> RequestField:
206
+ """
207
+ A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters.
208
+
209
+ Supports constructing :class:`~urllib3.fields.RequestField` from
210
+ parameter of key/value strings AND key/filetuple. A filetuple is a
211
+ (filename, data, MIME type) tuple where the MIME type is optional.
212
+ For example::
213
+
214
+ 'foo': 'bar',
215
+ 'fakefile': ('foofile.txt', 'contents of foofile'),
216
+ 'realfile': ('barfile.txt', open('realfile').read()),
217
+ 'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'),
218
+ 'nonamefile': 'contents of nonamefile field',
219
+
220
+ Field names and filenames must be unicode.
221
+ """
222
+ filename: str | None
223
+ content_type: str | None
224
+ data: _TYPE_FIELD_VALUE
225
+
226
+ if isinstance(value, tuple):
227
+ if len(value) == 3:
228
+ filename, data, content_type = value
229
+ else:
230
+ filename, data = value
231
+ content_type = guess_content_type(filename)
232
+ else:
233
+ filename = None
234
+ content_type = None
235
+ data = value
236
+
237
+ request_param = cls(
238
+ fieldname, data, filename=filename, header_formatter=header_formatter
239
+ )
240
+ request_param.make_multipart(content_type=content_type)
241
+
242
+ return request_param
243
+
244
+ def _render_part(self, name: str, value: _TYPE_FIELD_VALUE) -> str:
245
+ """
246
+ Override this method to change how each multipart header
247
+ parameter is formatted. By default, this calls
248
+ :func:`format_multipart_header_param`.
249
+
250
+ :param name:
251
+ The name of the parameter, an ASCII-only ``str``.
252
+ :param value:
253
+ The value of the parameter, a ``str`` or UTF-8 encoded
254
+ ``bytes``.
255
+
256
+ :meta public:
257
+ """
258
+ return self.header_formatter(name, value)
259
+
260
+ def _render_parts(
261
+ self,
262
+ header_parts: (
263
+ dict[str, _TYPE_FIELD_VALUE | None]
264
+ | typing.Sequence[tuple[str, _TYPE_FIELD_VALUE | None]]
265
+ ),
266
+ ) -> str:
267
+ """
268
+ Helper function to format and quote a single header.
269
+
270
+ Useful for single headers that are composed of multiple items. E.g.,
271
+ 'Content-Disposition' fields.
272
+
273
+ :param header_parts:
274
+ A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format
275
+ as `k1="v1"; k2="v2"; ...`.
276
+ """
277
+ iterable: typing.Iterable[tuple[str, _TYPE_FIELD_VALUE | None]]
278
+
279
+ parts = []
280
+ if isinstance(header_parts, dict):
281
+ iterable = header_parts.items()
282
+ else:
283
+ iterable = header_parts
284
+
285
+ for name, value in iterable:
286
+ if value is not None:
287
+ parts.append(self._render_part(name, value))
288
+
289
+ return "; ".join(parts)
290
+
291
+ def render_headers(self) -> str:
292
+ """
293
+ Renders the headers for this request field.
294
+ """
295
+ lines = []
296
+
297
+ sort_keys = ["Content-Disposition", "Content-Type", "Content-Location"]
298
+ for sort_key in sort_keys:
299
+ if self.headers.get(sort_key, False):
300
+ lines.append(f"{sort_key}: {self.headers[sort_key]}")
301
+
302
+ for header_name, header_value in self.headers.items():
303
+ if header_name not in sort_keys:
304
+ if header_value:
305
+ lines.append(f"{header_name}: {header_value}")
306
+
307
+ lines.append("\r\n")
308
+ return "\r\n".join(lines)
309
+
310
+ def make_multipart(
311
+ self,
312
+ content_disposition: str | None = None,
313
+ content_type: str | None = None,
314
+ content_location: str | None = None,
315
+ ) -> None:
316
+ """
317
+ Makes this request field into a multipart request field.
318
+
319
+ This method overrides "Content-Disposition", "Content-Type" and
320
+ "Content-Location" headers to the request parameter.
321
+
322
+ :param content_disposition:
323
+ The 'Content-Disposition' of the request body. Defaults to 'form-data'
324
+ :param content_type:
325
+ The 'Content-Type' of the request body.
326
+ :param content_location:
327
+ The 'Content-Location' of the request body.
328
+
329
+ """
330
+ content_disposition = (content_disposition or "form-data") + "; ".join(
331
+ [
332
+ "",
333
+ self._render_parts(
334
+ (("name", self._name), ("filename", self._filename))
335
+ ),
336
+ ]
337
+ )
338
+
339
+ self.headers["Content-Disposition"] = content_disposition
340
+ self.headers["Content-Type"] = content_type
341
+ self.headers["Content-Location"] = content_location
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/filepost.py ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import binascii
4
+ import codecs
5
+ import os
6
+ import typing
7
+ from io import BytesIO
8
+
9
+ from .fields import _TYPE_FIELD_VALUE_TUPLE, RequestField
10
+
11
+ writer = codecs.lookup("utf-8")[3]
12
+
13
+ _TYPE_FIELDS_SEQUENCE = typing.Sequence[
14
+ typing.Union[tuple[str, _TYPE_FIELD_VALUE_TUPLE], RequestField]
15
+ ]
16
+ _TYPE_FIELDS = typing.Union[
17
+ _TYPE_FIELDS_SEQUENCE,
18
+ typing.Mapping[str, _TYPE_FIELD_VALUE_TUPLE],
19
+ ]
20
+
21
+
22
+ def choose_boundary() -> str:
23
+ """
24
+ Our embarrassingly-simple replacement for mimetools.choose_boundary.
25
+ """
26
+ return binascii.hexlify(os.urandom(16)).decode()
27
+
28
+
29
+ def iter_field_objects(fields: _TYPE_FIELDS) -> typing.Iterable[RequestField]:
30
+ """
31
+ Iterate over fields.
32
+
33
+ Supports list of (k, v) tuples and dicts, and lists of
34
+ :class:`~urllib3.fields.RequestField`.
35
+
36
+ """
37
+ iterable: typing.Iterable[RequestField | tuple[str, _TYPE_FIELD_VALUE_TUPLE]]
38
+
39
+ if isinstance(fields, typing.Mapping):
40
+ iterable = fields.items()
41
+ else:
42
+ iterable = fields
43
+
44
+ for field in iterable:
45
+ if isinstance(field, RequestField):
46
+ yield field
47
+ else:
48
+ yield RequestField.from_tuples(*field)
49
+
50
+
51
+ def encode_multipart_formdata(
52
+ fields: _TYPE_FIELDS, boundary: str | None = None
53
+ ) -> tuple[bytes, str]:
54
+ """
55
+ Encode a dictionary of ``fields`` using the multipart/form-data MIME format.
56
+
57
+ :param fields:
58
+ Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`).
59
+ Values are processed by :func:`urllib3.fields.RequestField.from_tuples`.
60
+
61
+ :param boundary:
62
+ If not specified, then a random boundary will be generated using
63
+ :func:`urllib3.filepost.choose_boundary`.
64
+ """
65
+ body = BytesIO()
66
+ if boundary is None:
67
+ boundary = choose_boundary()
68
+
69
+ for field in iter_field_objects(fields):
70
+ body.write(f"--{boundary}\r\n".encode("latin-1"))
71
+
72
+ writer(body).write(field.render_headers())
73
+ data = field.data
74
+
75
+ if isinstance(data, int):
76
+ data = str(data) # Backwards compatibility
77
+
78
+ if isinstance(data, str):
79
+ writer(body).write(data)
80
+ else:
81
+ body.write(data)
82
+
83
+ body.write(b"\r\n")
84
+
85
+ body.write(f"--{boundary}--\r\n".encode("latin-1"))
86
+
87
+ content_type = f"multipart/form-data; boundary={boundary}"
88
+
89
+ return body.getvalue(), content_type
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/__init__.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ from importlib.metadata import version
4
+
5
+ __all__ = [
6
+ "inject_into_urllib3",
7
+ "extract_from_urllib3",
8
+ ]
9
+
10
+ import typing
11
+
12
+ orig_HTTPSConnection: typing.Any = None
13
+
14
+
15
+ def inject_into_urllib3() -> None:
16
+ # First check if h2 version is valid
17
+ h2_version = version("h2")
18
+ if not h2_version.startswith("4."):
19
+ raise ImportError(
20
+ "urllib3 v2 supports h2 version 4.x.x, currently "
21
+ f"the 'h2' module is compiled with {h2_version!r}. "
22
+ "See: https://github.com/urllib3/urllib3/issues/3290"
23
+ )
24
+
25
+ # Import here to avoid circular dependencies.
26
+ from .. import connection as urllib3_connection
27
+ from .. import util as urllib3_util
28
+ from ..connectionpool import HTTPSConnectionPool
29
+ from ..util import ssl_ as urllib3_util_ssl
30
+ from .connection import HTTP2Connection
31
+
32
+ global orig_HTTPSConnection
33
+ orig_HTTPSConnection = urllib3_connection.HTTPSConnection
34
+
35
+ HTTPSConnectionPool.ConnectionCls = HTTP2Connection
36
+ urllib3_connection.HTTPSConnection = HTTP2Connection # type: ignore[misc]
37
+
38
+ # TODO: Offer 'http/1.1' as well, but for testing purposes this is handy.
39
+ urllib3_util.ALPN_PROTOCOLS = ["h2"]
40
+ urllib3_util_ssl.ALPN_PROTOCOLS = ["h2"]
41
+
42
+
43
+ def extract_from_urllib3() -> None:
44
+ from .. import connection as urllib3_connection
45
+ from .. import util as urllib3_util
46
+ from ..connectionpool import HTTPSConnectionPool
47
+ from ..util import ssl_ as urllib3_util_ssl
48
+
49
+ HTTPSConnectionPool.ConnectionCls = orig_HTTPSConnection
50
+ urllib3_connection.HTTPSConnection = orig_HTTPSConnection # type: ignore[misc]
51
+
52
+ urllib3_util.ALPN_PROTOCOLS = ["http/1.1"]
53
+ urllib3_util_ssl.ALPN_PROTOCOLS = ["http/1.1"]
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/connection.py ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ import re
5
+ import threading
6
+ import types
7
+ import typing
8
+
9
+ import h2.config
10
+ import h2.connection
11
+ import h2.events
12
+
13
+ from .._base_connection import _TYPE_BODY
14
+ from .._collections import HTTPHeaderDict
15
+ from ..connection import HTTPSConnection, _get_default_user_agent
16
+ from ..exceptions import ConnectionError
17
+ from ..response import BaseHTTPResponse
18
+
19
+ orig_HTTPSConnection = HTTPSConnection
20
+
21
+ T = typing.TypeVar("T")
22
+
23
+ log = logging.getLogger(__name__)
24
+
25
+ RE_IS_LEGAL_HEADER_NAME = re.compile(rb"^[!#$%&'*+\-.^_`|~0-9a-z]+$")
26
+ RE_IS_ILLEGAL_HEADER_VALUE = re.compile(rb"[\0\x00\x0a\x0d\r\n]|^[ \r\n\t]|[ \r\n\t]$")
27
+
28
+
29
+ def _is_legal_header_name(name: bytes) -> bool:
30
+ """
31
+ "An implementation that validates fields according to the definitions in Sections
32
+ 5.1 and 5.5 of [HTTP] only needs an additional check that field names do not
33
+ include uppercase characters." (https://httpwg.org/specs/rfc9113.html#n-field-validity)
34
+
35
+ `http.client._is_legal_header_name` does not validate the field name according to the
36
+ HTTP 1.1 spec, so we do that here, in addition to checking for uppercase characters.
37
+
38
+ This does not allow for the `:` character in the header name, so should not
39
+ be used to validate pseudo-headers.
40
+ """
41
+ return bool(RE_IS_LEGAL_HEADER_NAME.match(name))
42
+
43
+
44
+ def _is_illegal_header_value(value: bytes) -> bool:
45
+ """
46
+ "A field value MUST NOT contain the zero value (ASCII NUL, 0x00), line feed
47
+ (ASCII LF, 0x0a), or carriage return (ASCII CR, 0x0d) at any position. A field
48
+ value MUST NOT start or end with an ASCII whitespace character (ASCII SP or HTAB,
49
+ 0x20 or 0x09)." (https://httpwg.org/specs/rfc9113.html#n-field-validity)
50
+ """
51
+ return bool(RE_IS_ILLEGAL_HEADER_VALUE.search(value))
52
+
53
+
54
+ class _LockedObject(typing.Generic[T]):
55
+ """
56
+ A wrapper class that hides a specific object behind a lock.
57
+ The goal here is to provide a simple way to protect access to an object
58
+ that cannot safely be simultaneously accessed from multiple threads. The
59
+ intended use of this class is simple: take hold of it with a context
60
+ manager, which returns the protected object.
61
+ """
62
+
63
+ __slots__ = (
64
+ "lock",
65
+ "_obj",
66
+ )
67
+
68
+ def __init__(self, obj: T):
69
+ self.lock = threading.RLock()
70
+ self._obj = obj
71
+
72
+ def __enter__(self) -> T:
73
+ self.lock.acquire()
74
+ return self._obj
75
+
76
+ def __exit__(
77
+ self,
78
+ exc_type: type[BaseException] | None,
79
+ exc_val: BaseException | None,
80
+ exc_tb: types.TracebackType | None,
81
+ ) -> None:
82
+ self.lock.release()
83
+
84
+
85
+ class HTTP2Connection(HTTPSConnection):
86
+ def __init__(
87
+ self, host: str, port: int | None = None, **kwargs: typing.Any
88
+ ) -> None:
89
+ self._h2_conn = self._new_h2_conn()
90
+ self._h2_stream: int | None = None
91
+ self._headers: list[tuple[bytes, bytes]] = []
92
+
93
+ if "proxy" in kwargs or "proxy_config" in kwargs: # Defensive:
94
+ raise NotImplementedError("Proxies aren't supported with HTTP/2")
95
+
96
+ super().__init__(host, port, **kwargs)
97
+
98
+ if self._tunnel_host is not None:
99
+ raise NotImplementedError("Tunneling isn't supported with HTTP/2")
100
+
101
+ def _new_h2_conn(self) -> _LockedObject[h2.connection.H2Connection]:
102
+ config = h2.config.H2Configuration(client_side=True)
103
+ return _LockedObject(h2.connection.H2Connection(config=config))
104
+
105
+ def connect(self) -> None:
106
+ super().connect()
107
+ with self._h2_conn as conn:
108
+ conn.initiate_connection()
109
+ if data_to_send := conn.data_to_send():
110
+ self.sock.sendall(data_to_send)
111
+
112
+ def putrequest( # type: ignore[override]
113
+ self,
114
+ method: str,
115
+ url: str,
116
+ **kwargs: typing.Any,
117
+ ) -> None:
118
+ """putrequest
119
+ This deviates from the HTTPConnection method signature since we never need to override
120
+ sending accept-encoding headers or the host header.
121
+ """
122
+ if "skip_host" in kwargs:
123
+ raise NotImplementedError("`skip_host` isn't supported")
124
+ if "skip_accept_encoding" in kwargs:
125
+ raise NotImplementedError("`skip_accept_encoding` isn't supported")
126
+
127
+ self._request_url = url or "/"
128
+ self._validate_path(url) # type: ignore[attr-defined]
129
+
130
+ if ":" in self.host:
131
+ authority = f"[{self.host}]:{self.port or 443}"
132
+ else:
133
+ authority = f"{self.host}:{self.port or 443}"
134
+
135
+ self._headers.append((b":scheme", b"https"))
136
+ self._headers.append((b":method", method.encode()))
137
+ self._headers.append((b":authority", authority.encode()))
138
+ self._headers.append((b":path", url.encode()))
139
+
140
+ with self._h2_conn as conn:
141
+ self._h2_stream = conn.get_next_available_stream_id()
142
+
143
+ def putheader(self, header: str | bytes, *values: str | bytes) -> None: # type: ignore[override]
144
+ # TODO SKIPPABLE_HEADERS from urllib3 are ignored.
145
+ header = header.encode() if isinstance(header, str) else header
146
+ header = header.lower() # A lot of upstream code uses capitalized headers.
147
+ if not _is_legal_header_name(header):
148
+ raise ValueError(f"Illegal header name {str(header)}")
149
+
150
+ for value in values:
151
+ value = value.encode() if isinstance(value, str) else value
152
+ if _is_illegal_header_value(value):
153
+ raise ValueError(f"Illegal header value {str(value)}")
154
+ self._headers.append((header, value))
155
+
156
+ def endheaders(self, message_body: typing.Any = None) -> None: # type: ignore[override]
157
+ if self._h2_stream is None:
158
+ raise ConnectionError("Must call `putrequest` first.")
159
+
160
+ with self._h2_conn as conn:
161
+ conn.send_headers(
162
+ stream_id=self._h2_stream,
163
+ headers=self._headers,
164
+ end_stream=(message_body is None),
165
+ )
166
+ if data_to_send := conn.data_to_send():
167
+ self.sock.sendall(data_to_send)
168
+ self._headers = [] # Reset headers for the next request.
169
+
170
+ def send(self, data: typing.Any) -> None:
171
+ """Send data to the server.
172
+ `data` can be: `str`, `bytes`, an iterable, or file-like objects
173
+ that support a .read() method.
174
+ """
175
+ if self._h2_stream is None:
176
+ raise ConnectionError("Must call `putrequest` first.")
177
+
178
+ with self._h2_conn as conn:
179
+ if data_to_send := conn.data_to_send():
180
+ self.sock.sendall(data_to_send)
181
+
182
+ if hasattr(data, "read"): # file-like objects
183
+ while True:
184
+ chunk = data.read(self.blocksize)
185
+ if not chunk:
186
+ break
187
+ if isinstance(chunk, str):
188
+ chunk = chunk.encode()
189
+ conn.send_data(self._h2_stream, chunk, end_stream=False)
190
+ if data_to_send := conn.data_to_send():
191
+ self.sock.sendall(data_to_send)
192
+ conn.end_stream(self._h2_stream)
193
+ return
194
+
195
+ if isinstance(data, str): # str -> bytes
196
+ data = data.encode()
197
+
198
+ try:
199
+ if isinstance(data, bytes):
200
+ conn.send_data(self._h2_stream, data, end_stream=True)
201
+ if data_to_send := conn.data_to_send():
202
+ self.sock.sendall(data_to_send)
203
+ else:
204
+ for chunk in data:
205
+ conn.send_data(self._h2_stream, chunk, end_stream=False)
206
+ if data_to_send := conn.data_to_send():
207
+ self.sock.sendall(data_to_send)
208
+ conn.end_stream(self._h2_stream)
209
+ except TypeError:
210
+ raise TypeError(
211
+ "`data` should be str, bytes, iterable, or file. got %r"
212
+ % type(data)
213
+ )
214
+
215
+ def set_tunnel(
216
+ self,
217
+ host: str,
218
+ port: int | None = None,
219
+ headers: typing.Mapping[str, str] | None = None,
220
+ scheme: str = "http",
221
+ ) -> None:
222
+ raise NotImplementedError(
223
+ "HTTP/2 does not support setting up a tunnel through a proxy"
224
+ )
225
+
226
+ def getresponse( # type: ignore[override]
227
+ self,
228
+ ) -> HTTP2Response:
229
+ status = None
230
+ data = bytearray()
231
+ with self._h2_conn as conn:
232
+ end_stream = False
233
+ while not end_stream:
234
+ # TODO: Arbitrary read value.
235
+ if received_data := self.sock.recv(65535):
236
+ events = conn.receive_data(received_data)
237
+ for event in events:
238
+ if isinstance(event, h2.events.ResponseReceived):
239
+ headers = HTTPHeaderDict()
240
+ for header, value in event.headers:
241
+ if header == b":status":
242
+ status = int(value.decode())
243
+ else:
244
+ headers.add(
245
+ header.decode("ascii"), value.decode("ascii")
246
+ )
247
+
248
+ elif isinstance(event, h2.events.DataReceived):
249
+ data += event.data
250
+ conn.acknowledge_received_data(
251
+ event.flow_controlled_length, event.stream_id
252
+ )
253
+
254
+ elif isinstance(event, h2.events.StreamEnded):
255
+ end_stream = True
256
+
257
+ if data_to_send := conn.data_to_send():
258
+ self.sock.sendall(data_to_send)
259
+
260
+ assert status is not None
261
+ return HTTP2Response(
262
+ status=status,
263
+ headers=headers,
264
+ request_url=self._request_url,
265
+ data=bytes(data),
266
+ )
267
+
268
+ def request( # type: ignore[override]
269
+ self,
270
+ method: str,
271
+ url: str,
272
+ body: _TYPE_BODY | None = None,
273
+ headers: typing.Mapping[str, str] | None = None,
274
+ *,
275
+ preload_content: bool = True,
276
+ decode_content: bool = True,
277
+ enforce_content_length: bool = True,
278
+ **kwargs: typing.Any,
279
+ ) -> None:
280
+ """Send an HTTP/2 request"""
281
+ if "chunked" in kwargs:
282
+ # TODO this is often present from upstream.
283
+ # raise NotImplementedError("`chunked` isn't supported with HTTP/2")
284
+ pass
285
+
286
+ if self.sock is not None:
287
+ self.sock.settimeout(self.timeout)
288
+
289
+ self.putrequest(method, url)
290
+
291
+ headers = headers or {}
292
+ for k, v in headers.items():
293
+ if k.lower() == "transfer-encoding" and v == "chunked":
294
+ continue
295
+ else:
296
+ self.putheader(k, v)
297
+
298
+ if b"user-agent" not in dict(self._headers):
299
+ self.putheader(b"user-agent", _get_default_user_agent())
300
+
301
+ if body:
302
+ self.endheaders(message_body=body)
303
+ self.send(body)
304
+ else:
305
+ self.endheaders()
306
+
307
+ def close(self) -> None:
308
+ with self._h2_conn as conn:
309
+ try:
310
+ conn.close_connection()
311
+ if data := conn.data_to_send():
312
+ self.sock.sendall(data)
313
+ except Exception:
314
+ pass
315
+
316
+ # Reset all our HTTP/2 connection state.
317
+ self._h2_conn = self._new_h2_conn()
318
+ self._h2_stream = None
319
+ self._headers = []
320
+
321
+ super().close()
322
+
323
+
324
+ class HTTP2Response(BaseHTTPResponse):
325
+ # TODO: This is a woefully incomplete response object, but works for non-streaming.
326
+ def __init__(
327
+ self,
328
+ status: int,
329
+ headers: HTTPHeaderDict,
330
+ request_url: str,
331
+ data: bytes,
332
+ decode_content: bool = False, # TODO: support decoding
333
+ ) -> None:
334
+ super().__init__(
335
+ status=status,
336
+ headers=headers,
337
+ # Following CPython, we map HTTP versions to major * 10 + minor integers
338
+ version=20,
339
+ version_string="HTTP/2",
340
+ # No reason phrase in HTTP/2
341
+ reason=None,
342
+ decode_content=decode_content,
343
+ request_url=request_url,
344
+ )
345
+ self._data = data
346
+ self.length_remaining = 0
347
+
348
+ @property
349
+ def data(self) -> bytes:
350
+ return self._data
351
+
352
+ def get_redirect_location(self) -> None:
353
+ return None
354
+
355
+ def close(self) -> None:
356
+ pass
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/http2/probe.py ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import threading
4
+
5
+
6
+ class _HTTP2ProbeCache:
7
+ __slots__ = (
8
+ "_lock",
9
+ "_cache_locks",
10
+ "_cache_values",
11
+ )
12
+
13
+ def __init__(self) -> None:
14
+ self._lock = threading.Lock()
15
+ self._cache_locks: dict[tuple[str, int], threading.RLock] = {}
16
+ self._cache_values: dict[tuple[str, int], bool | None] = {}
17
+
18
+ def acquire_and_get(self, host: str, port: int) -> bool | None:
19
+ # By the end of this block we know that
20
+ # _cache_[values,locks] is available.
21
+ value = None
22
+ with self._lock:
23
+ key = (host, port)
24
+ try:
25
+ value = self._cache_values[key]
26
+ # If it's a known value we return right away.
27
+ if value is not None:
28
+ return value
29
+ except KeyError:
30
+ self._cache_locks[key] = threading.RLock()
31
+ self._cache_values[key] = None
32
+
33
+ # If the value is unknown, we acquire the lock to signal
34
+ # to the requesting thread that the probe is in progress
35
+ # or that the current thread needs to return their findings.
36
+ key_lock = self._cache_locks[key]
37
+ key_lock.acquire()
38
+ try:
39
+ # If the by the time we get the lock the value has been
40
+ # updated we want to return the updated value.
41
+ value = self._cache_values[key]
42
+
43
+ # In case an exception like KeyboardInterrupt is raised here.
44
+ except BaseException as e: # Defensive:
45
+ assert not isinstance(e, KeyError) # KeyError shouldn't be possible.
46
+ key_lock.release()
47
+ raise
48
+
49
+ return value
50
+
51
+ def set_and_release(
52
+ self, host: str, port: int, supports_http2: bool | None
53
+ ) -> None:
54
+ key = (host, port)
55
+ key_lock = self._cache_locks[key]
56
+ with key_lock: # Uses an RLock, so can be locked again from same thread.
57
+ if supports_http2 is None and self._cache_values[key] is not None:
58
+ raise ValueError(
59
+ "Cannot reset HTTP/2 support for origin after value has been set."
60
+ ) # Defensive: not expected in normal usage
61
+
62
+ self._cache_values[key] = supports_http2
63
+ key_lock.release()
64
+
65
+ def _values(self) -> dict[tuple[str, int], bool | None]:
66
+ """This function is for testing purposes only. Gets the current state of the probe cache"""
67
+ with self._lock:
68
+ return {k: v for k, v in self._cache_values.items()}
69
+
70
+ def _reset(self) -> None:
71
+ """This function is for testing purposes only. Reset the cache values"""
72
+ with self._lock:
73
+ self._cache_locks = {}
74
+ self._cache_values = {}
75
+
76
+
77
+ _HTTP2_PROBE_CACHE = _HTTP2ProbeCache()
78
+
79
+ set_and_release = _HTTP2_PROBE_CACHE.set_and_release
80
+ acquire_and_get = _HTTP2_PROBE_CACHE.acquire_and_get
81
+ _values = _HTTP2_PROBE_CACHE._values
82
+ _reset = _HTTP2_PROBE_CACHE._reset
83
+
84
+ __all__ = [
85
+ "set_and_release",
86
+ "acquire_and_get",
87
+ ]
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/poolmanager.py ADDED
@@ -0,0 +1,653 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import functools
4
+ import logging
5
+ import typing
6
+ import warnings
7
+ from types import TracebackType
8
+ from urllib.parse import urljoin
9
+
10
+ from ._collections import HTTPHeaderDict, RecentlyUsedContainer
11
+ from ._request_methods import RequestMethods
12
+ from .connection import ProxyConfig
13
+ from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme
14
+ from .exceptions import (
15
+ LocationValueError,
16
+ MaxRetryError,
17
+ ProxySchemeUnknown,
18
+ URLSchemeUnknown,
19
+ )
20
+ from .response import BaseHTTPResponse
21
+ from .util.connection import _TYPE_SOCKET_OPTIONS
22
+ from .util.proxy import connection_requires_http_tunnel
23
+ from .util.retry import Retry
24
+ from .util.timeout import Timeout
25
+ from .util.url import Url, parse_url
26
+
27
+ if typing.TYPE_CHECKING:
28
+ import ssl
29
+
30
+ from typing_extensions import Self
31
+
32
+ __all__ = ["PoolManager", "ProxyManager", "proxy_from_url"]
33
+
34
+
35
+ log = logging.getLogger(__name__)
36
+
37
+ SSL_KEYWORDS = (
38
+ "key_file",
39
+ "cert_file",
40
+ "cert_reqs",
41
+ "ca_certs",
42
+ "ca_cert_data",
43
+ "ssl_version",
44
+ "ssl_minimum_version",
45
+ "ssl_maximum_version",
46
+ "ca_cert_dir",
47
+ "ssl_context",
48
+ "key_password",
49
+ "server_hostname",
50
+ )
51
+ # Default value for `blocksize` - a new parameter introduced to
52
+ # http.client.HTTPConnection & http.client.HTTPSConnection in Python 3.7
53
+ _DEFAULT_BLOCKSIZE = 16384
54
+
55
+
56
+ class PoolKey(typing.NamedTuple):
57
+ """
58
+ All known keyword arguments that could be provided to the pool manager, its
59
+ pools, or the underlying connections.
60
+
61
+ All custom key schemes should include the fields in this key at a minimum.
62
+ """
63
+
64
+ key_scheme: str
65
+ key_host: str
66
+ key_port: int | None
67
+ key_timeout: Timeout | float | int | None
68
+ key_retries: Retry | bool | int | None
69
+ key_block: bool | None
70
+ key_source_address: tuple[str, int] | None
71
+ key_key_file: str | None
72
+ key_key_password: str | None
73
+ key_cert_file: str | None
74
+ key_cert_reqs: str | None
75
+ key_ca_certs: str | None
76
+ key_ca_cert_data: str | bytes | None
77
+ key_ssl_version: int | str | None
78
+ key_ssl_minimum_version: ssl.TLSVersion | None
79
+ key_ssl_maximum_version: ssl.TLSVersion | None
80
+ key_ca_cert_dir: str | None
81
+ key_ssl_context: ssl.SSLContext | None
82
+ key_maxsize: int | None
83
+ key_headers: frozenset[tuple[str, str]] | None
84
+ key__proxy: Url | None
85
+ key__proxy_headers: frozenset[tuple[str, str]] | None
86
+ key__proxy_config: ProxyConfig | None
87
+ key_socket_options: _TYPE_SOCKET_OPTIONS | None
88
+ key__socks_options: frozenset[tuple[str, str]] | None
89
+ key_assert_hostname: bool | str | None
90
+ key_assert_fingerprint: str | None
91
+ key_server_hostname: str | None
92
+ key_blocksize: int | None
93
+
94
+
95
+ def _default_key_normalizer(
96
+ key_class: type[PoolKey], request_context: dict[str, typing.Any]
97
+ ) -> PoolKey:
98
+ """
99
+ Create a pool key out of a request context dictionary.
100
+
101
+ According to RFC 3986, both the scheme and host are case-insensitive.
102
+ Therefore, this function normalizes both before constructing the pool
103
+ key for an HTTPS request. If you wish to change this behaviour, provide
104
+ alternate callables to ``key_fn_by_scheme``.
105
+
106
+ :param key_class:
107
+ The class to use when constructing the key. This should be a namedtuple
108
+ with the ``scheme`` and ``host`` keys at a minimum.
109
+ :type key_class: namedtuple
110
+ :param request_context:
111
+ A dictionary-like object that contain the context for a request.
112
+ :type request_context: dict
113
+
114
+ :return: A namedtuple that can be used as a connection pool key.
115
+ :rtype: PoolKey
116
+ """
117
+ # Since we mutate the dictionary, make a copy first
118
+ context = request_context.copy()
119
+ context["scheme"] = context["scheme"].lower()
120
+ context["host"] = context["host"].lower()
121
+
122
+ # These are both dictionaries and need to be transformed into frozensets
123
+ for key in ("headers", "_proxy_headers", "_socks_options"):
124
+ if key in context and context[key] is not None:
125
+ context[key] = frozenset(context[key].items())
126
+
127
+ # The socket_options key may be a list and needs to be transformed into a
128
+ # tuple.
129
+ socket_opts = context.get("socket_options")
130
+ if socket_opts is not None:
131
+ context["socket_options"] = tuple(socket_opts)
132
+
133
+ # Map the kwargs to the names in the namedtuple - this is necessary since
134
+ # namedtuples can't have fields starting with '_'.
135
+ for key in list(context.keys()):
136
+ context["key_" + key] = context.pop(key)
137
+
138
+ # Default to ``None`` for keys missing from the context
139
+ for field in key_class._fields:
140
+ if field not in context:
141
+ context[field] = None
142
+
143
+ # Default key_blocksize to _DEFAULT_BLOCKSIZE if missing from the context
144
+ if context.get("key_blocksize") is None:
145
+ context["key_blocksize"] = _DEFAULT_BLOCKSIZE
146
+
147
+ return key_class(**context)
148
+
149
+
150
+ #: A dictionary that maps a scheme to a callable that creates a pool key.
151
+ #: This can be used to alter the way pool keys are constructed, if desired.
152
+ #: Each PoolManager makes a copy of this dictionary so they can be configured
153
+ #: globally here, or individually on the instance.
154
+ key_fn_by_scheme = {
155
+ "http": functools.partial(_default_key_normalizer, PoolKey),
156
+ "https": functools.partial(_default_key_normalizer, PoolKey),
157
+ }
158
+
159
+ pool_classes_by_scheme = {"http": HTTPConnectionPool, "https": HTTPSConnectionPool}
160
+
161
+
162
+ class PoolManager(RequestMethods):
163
+ """
164
+ Allows for arbitrary requests while transparently keeping track of
165
+ necessary connection pools for you.
166
+
167
+ :param num_pools:
168
+ Number of connection pools to cache before discarding the least
169
+ recently used pool.
170
+
171
+ :param headers:
172
+ Headers to include with all requests, unless other headers are given
173
+ explicitly.
174
+
175
+ :param \\**connection_pool_kw:
176
+ Additional parameters are used to create fresh
177
+ :class:`urllib3.connectionpool.ConnectionPool` instances.
178
+
179
+ Example:
180
+
181
+ .. code-block:: python
182
+
183
+ from pip._vendor import urllib3
184
+
185
+ http = urllib3.PoolManager(num_pools=2)
186
+
187
+ resp1 = http.request("GET", "https://google.com/")
188
+ resp2 = http.request("GET", "https://google.com/mail")
189
+ resp3 = http.request("GET", "https://yahoo.com/")
190
+
191
+ print(len(http.pools))
192
+ # 2
193
+
194
+ """
195
+
196
+ proxy: Url | None = None
197
+ proxy_config: ProxyConfig | None = None
198
+
199
+ def __init__(
200
+ self,
201
+ num_pools: int = 10,
202
+ headers: typing.Mapping[str, str] | None = None,
203
+ **connection_pool_kw: typing.Any,
204
+ ) -> None:
205
+ super().__init__(headers)
206
+ # PoolManager handles redirects itself in PoolManager.urlopen().
207
+ # It always passes redirect=False to the underlying connection pool to
208
+ # suppress per-pool redirect handling. If the user supplied a non-Retry
209
+ # value (int/bool/etc) for retries and we let the pool normalize it
210
+ # while redirect=False, the resulting Retry object would have redirect
211
+ # handling disabled, which can interfere with PoolManager's own
212
+ # redirect logic. Normalize here so redirects remain governed solely by
213
+ # PoolManager logic.
214
+ if "retries" in connection_pool_kw:
215
+ retries = connection_pool_kw["retries"]
216
+ if not isinstance(retries, Retry):
217
+ retries = Retry.from_int(retries)
218
+ connection_pool_kw = connection_pool_kw.copy()
219
+ connection_pool_kw["retries"] = retries
220
+ self.connection_pool_kw = connection_pool_kw
221
+
222
+ self.pools: RecentlyUsedContainer[PoolKey, HTTPConnectionPool]
223
+ self.pools = RecentlyUsedContainer(num_pools)
224
+
225
+ # Locally set the pool classes and keys so other PoolManagers can
226
+ # override them.
227
+ self.pool_classes_by_scheme = pool_classes_by_scheme
228
+ self.key_fn_by_scheme = key_fn_by_scheme.copy()
229
+
230
+ def __enter__(self) -> Self:
231
+ return self
232
+
233
+ def __exit__(
234
+ self,
235
+ exc_type: type[BaseException] | None,
236
+ exc_val: BaseException | None,
237
+ exc_tb: TracebackType | None,
238
+ ) -> typing.Literal[False]:
239
+ self.clear()
240
+ # Return False to re-raise any potential exceptions
241
+ return False
242
+
243
+ def _new_pool(
244
+ self,
245
+ scheme: str,
246
+ host: str,
247
+ port: int,
248
+ request_context: dict[str, typing.Any] | None = None,
249
+ ) -> HTTPConnectionPool:
250
+ """
251
+ Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and
252
+ any additional pool keyword arguments.
253
+
254
+ If ``request_context`` is provided, it is provided as keyword arguments
255
+ to the pool class used. This method is used to actually create the
256
+ connection pools handed out by :meth:`connection_from_url` and
257
+ companion methods. It is intended to be overridden for customization.
258
+ """
259
+ pool_cls: type[HTTPConnectionPool] = self.pool_classes_by_scheme[scheme]
260
+ if request_context is None:
261
+ request_context = self.connection_pool_kw.copy()
262
+
263
+ # Default blocksize to _DEFAULT_BLOCKSIZE if missing or explicitly
264
+ # set to 'None' in the request_context.
265
+ if request_context.get("blocksize") is None:
266
+ request_context["blocksize"] = _DEFAULT_BLOCKSIZE
267
+
268
+ # Although the context has everything necessary to create the pool,
269
+ # this function has historically only used the scheme, host, and port
270
+ # in the positional args. When an API change is acceptable these can
271
+ # be removed.
272
+ for key in ("scheme", "host", "port"):
273
+ request_context.pop(key, None)
274
+
275
+ if scheme == "http":
276
+ for kw in SSL_KEYWORDS:
277
+ request_context.pop(kw, None)
278
+
279
+ return pool_cls(host, port, **request_context)
280
+
281
+ def clear(self) -> None:
282
+ """
283
+ Empty our store of pools and direct them all to close.
284
+
285
+ This will not affect in-flight connections, but they will not be
286
+ re-used after completion.
287
+ """
288
+ self.pools.clear()
289
+
290
+ def connection_from_host(
291
+ self,
292
+ host: str | None,
293
+ port: int | None = None,
294
+ scheme: str | None = "http",
295
+ pool_kwargs: dict[str, typing.Any] | None = None,
296
+ ) -> HTTPConnectionPool:
297
+ """
298
+ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme.
299
+
300
+ If ``port`` isn't given, it will be derived from the ``scheme`` using
301
+ ``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is
302
+ provided, it is merged with the instance's ``connection_pool_kw``
303
+ variable and used to create the new connection pool, if one is
304
+ needed.
305
+ """
306
+
307
+ if not host:
308
+ raise LocationValueError("No host specified.")
309
+
310
+ request_context = self._merge_pool_kwargs(pool_kwargs)
311
+ request_context["scheme"] = scheme or "http"
312
+ if not port:
313
+ port = port_by_scheme.get(request_context["scheme"].lower(), 80)
314
+ request_context["port"] = port
315
+ request_context["host"] = host
316
+
317
+ return self.connection_from_context(request_context)
318
+
319
+ def connection_from_context(
320
+ self, request_context: dict[str, typing.Any]
321
+ ) -> HTTPConnectionPool:
322
+ """
323
+ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context.
324
+
325
+ ``request_context`` must at least contain the ``scheme`` key and its
326
+ value must be a key in ``key_fn_by_scheme`` instance variable.
327
+ """
328
+ if "strict" in request_context:
329
+ warnings.warn(
330
+ "The 'strict' parameter is no longer needed on Python 3+. "
331
+ "This will raise an error in urllib3 v3.0.",
332
+ FutureWarning,
333
+ )
334
+ request_context.pop("strict")
335
+
336
+ scheme = request_context["scheme"].lower()
337
+ pool_key_constructor = self.key_fn_by_scheme.get(scheme)
338
+ if not pool_key_constructor:
339
+ raise URLSchemeUnknown(scheme)
340
+ pool_key = pool_key_constructor(request_context)
341
+
342
+ return self.connection_from_pool_key(pool_key, request_context=request_context)
343
+
344
+ def connection_from_pool_key(
345
+ self, pool_key: PoolKey, request_context: dict[str, typing.Any]
346
+ ) -> HTTPConnectionPool:
347
+ """
348
+ Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key.
349
+
350
+ ``pool_key`` should be a namedtuple that only contains immutable
351
+ objects. At a minimum it must have the ``scheme``, ``host``, and
352
+ ``port`` fields.
353
+ """
354
+ with self.pools.lock:
355
+ # If the scheme, host, or port doesn't match existing open
356
+ # connections, open a new ConnectionPool.
357
+ pool = self.pools.get(pool_key)
358
+ if pool:
359
+ return pool
360
+
361
+ # Make a fresh ConnectionPool of the desired type
362
+ scheme = request_context["scheme"]
363
+ host = request_context["host"]
364
+ port = request_context["port"]
365
+ pool = self._new_pool(scheme, host, port, request_context=request_context)
366
+ self.pools[pool_key] = pool
367
+
368
+ return pool
369
+
370
+ def connection_from_url(
371
+ self, url: str, pool_kwargs: dict[str, typing.Any] | None = None
372
+ ) -> HTTPConnectionPool:
373
+ """
374
+ Similar to :func:`urllib3.connectionpool.connection_from_url`.
375
+
376
+ If ``pool_kwargs`` is not provided and a new pool needs to be
377
+ constructed, ``self.connection_pool_kw`` is used to initialize
378
+ the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs``
379
+ is provided, it is used instead. Note that if a new pool does not
380
+ need to be created for the request, the provided ``pool_kwargs`` are
381
+ not used.
382
+ """
383
+ u = parse_url(url)
384
+ return self.connection_from_host(
385
+ u.host, port=u.port, scheme=u.scheme, pool_kwargs=pool_kwargs
386
+ )
387
+
388
+ def _merge_pool_kwargs(
389
+ self, override: dict[str, typing.Any] | None
390
+ ) -> dict[str, typing.Any]:
391
+ """
392
+ Merge a dictionary of override values for self.connection_pool_kw.
393
+
394
+ This does not modify self.connection_pool_kw and returns a new dict.
395
+ Any keys in the override dictionary with a value of ``None`` are
396
+ removed from the merged dictionary.
397
+ """
398
+ base_pool_kwargs = self.connection_pool_kw.copy()
399
+ if override:
400
+ for key, value in override.items():
401
+ if value is None:
402
+ try:
403
+ del base_pool_kwargs[key]
404
+ except KeyError:
405
+ pass
406
+ else:
407
+ base_pool_kwargs[key] = value
408
+ return base_pool_kwargs
409
+
410
+ def _proxy_requires_url_absolute_form(self, parsed_url: Url) -> bool:
411
+ """
412
+ Indicates if the proxy requires the complete destination URL in the
413
+ request. Normally this is only needed when not using an HTTP CONNECT
414
+ tunnel.
415
+ """
416
+ if self.proxy is None:
417
+ return False
418
+
419
+ return not connection_requires_http_tunnel(
420
+ self.proxy, self.proxy_config, parsed_url.scheme
421
+ )
422
+
423
+ def urlopen( # type: ignore[override]
424
+ self, method: str, url: str, redirect: bool = True, **kw: typing.Any
425
+ ) -> BaseHTTPResponse:
426
+ """
427
+ Same as :meth:`urllib3.HTTPConnectionPool.urlopen`
428
+ with custom cross-host redirect logic and only sends the request-uri
429
+ portion of the ``url``.
430
+
431
+ The given ``url`` parameter must be absolute, such that an appropriate
432
+ :class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
433
+ """
434
+ u = parse_url(url)
435
+
436
+ if u.scheme is None:
437
+ warnings.warn(
438
+ "URLs without a scheme (ie 'https://') are deprecated and will raise an error "
439
+ "in urllib3 v3.0. To avoid this FutureWarning ensure all URLs "
440
+ "start with 'https://' or 'http://'. Read more in this issue: "
441
+ "https://github.com/urllib3/urllib3/issues/2920",
442
+ category=FutureWarning,
443
+ stacklevel=2,
444
+ )
445
+
446
+ conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
447
+
448
+ kw["assert_same_host"] = False
449
+ kw["redirect"] = False
450
+
451
+ if "headers" not in kw:
452
+ kw["headers"] = self.headers
453
+
454
+ if self._proxy_requires_url_absolute_form(u):
455
+ response = conn.urlopen(method, url, **kw)
456
+ else:
457
+ response = conn.urlopen(method, u.request_uri, **kw)
458
+
459
+ redirect_location = redirect and response.get_redirect_location()
460
+ if not redirect_location:
461
+ return response
462
+
463
+ # Support relative URLs for redirecting.
464
+ redirect_location = urljoin(url, redirect_location)
465
+
466
+ if response.status == 303:
467
+ # Change the method according to RFC 9110, Section 15.4.4.
468
+ method = "GET"
469
+ # And lose the body not to transfer anything sensitive.
470
+ kw["body"] = None
471
+ kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change()
472
+
473
+ retries = kw.get("retries", response.retries)
474
+ if not isinstance(retries, Retry):
475
+ retries = Retry.from_int(retries, redirect=redirect)
476
+
477
+ # Strip headers marked as unsafe to forward to the redirected location.
478
+ # Check remove_headers_on_redirect to avoid a potential network call within
479
+ # conn.is_same_host() which may use socket.gethostbyname() in the future.
480
+ if retries.remove_headers_on_redirect and not conn.is_same_host(
481
+ redirect_location
482
+ ):
483
+ new_headers = kw["headers"].copy()
484
+ for header in kw["headers"]:
485
+ if header.lower() in retries.remove_headers_on_redirect:
486
+ new_headers.pop(header, None)
487
+ kw["headers"] = new_headers
488
+
489
+ try:
490
+ retries = retries.increment(method, url, response=response, _pool=conn)
491
+ except MaxRetryError:
492
+ if retries.raise_on_redirect:
493
+ response.drain_conn()
494
+ raise
495
+ return response
496
+
497
+ kw["retries"] = retries
498
+ kw["redirect"] = redirect
499
+
500
+ log.info("Redirecting %s -> %s", url, redirect_location)
501
+
502
+ response.drain_conn()
503
+ return self.urlopen(method, redirect_location, **kw)
504
+
505
+
506
+ class ProxyManager(PoolManager):
507
+ """
508
+ Behaves just like :class:`PoolManager`, but sends all requests through
509
+ the defined proxy, using the CONNECT method for HTTPS URLs.
510
+
511
+ :param proxy_url:
512
+ The URL of the proxy to be used.
513
+
514
+ :param proxy_headers:
515
+ A dictionary containing headers that will be sent to the proxy. In case
516
+ of HTTP they are being sent with each request, while in the
517
+ HTTPS/CONNECT case they are sent only once. Could be used for proxy
518
+ authentication.
519
+
520
+ :param proxy_ssl_context:
521
+ The proxy SSL context is used to establish the TLS connection to the
522
+ proxy when using HTTPS proxies.
523
+
524
+ :param use_forwarding_for_https:
525
+ (Defaults to False) If set to True will forward requests to the HTTPS
526
+ proxy to be made on behalf of the client instead of creating a TLS
527
+ tunnel via the CONNECT method. **Enabling this flag means that request
528
+ and response headers and content will be visible from the HTTPS proxy**
529
+ whereas tunneling keeps request and response headers and content
530
+ private. IP address, target hostname, SNI, and port are always visible
531
+ to an HTTPS proxy even when this flag is disabled.
532
+
533
+ :param proxy_assert_hostname:
534
+ The hostname of the certificate to verify against.
535
+
536
+ :param proxy_assert_fingerprint:
537
+ The fingerprint of the certificate to verify against.
538
+
539
+ Example:
540
+
541
+ .. code-block:: python
542
+
543
+ from pip._vendor import urllib3
544
+
545
+ proxy = urllib3.ProxyManager("https://localhost:3128/")
546
+
547
+ resp1 = proxy.request("GET", "http://google.com/")
548
+ resp2 = proxy.request("GET", "http://httpbin.org/")
549
+
550
+ # One pool was shared by both plain HTTP requests.
551
+ print(len(proxy.pools))
552
+ # 1
553
+
554
+ resp3 = proxy.request("GET", "https://httpbin.org/")
555
+ resp4 = proxy.request("GET", "https://twitter.com/")
556
+
557
+ # A separate pool was added for each HTTPS target.
558
+ print(len(proxy.pools))
559
+ # 3
560
+
561
+ """
562
+
563
+ def __init__(
564
+ self,
565
+ proxy_url: str,
566
+ num_pools: int = 10,
567
+ headers: typing.Mapping[str, str] | None = None,
568
+ proxy_headers: typing.Mapping[str, str] | None = None,
569
+ proxy_ssl_context: ssl.SSLContext | None = None,
570
+ use_forwarding_for_https: bool = False,
571
+ proxy_assert_hostname: None | str | typing.Literal[False] = None,
572
+ proxy_assert_fingerprint: str | None = None,
573
+ **connection_pool_kw: typing.Any,
574
+ ) -> None:
575
+ if isinstance(proxy_url, HTTPConnectionPool):
576
+ str_proxy_url = f"{proxy_url.scheme}://{proxy_url.host}:{proxy_url.port}"
577
+ else:
578
+ str_proxy_url = proxy_url
579
+ proxy = parse_url(str_proxy_url)
580
+
581
+ if proxy.scheme not in ("http", "https"):
582
+ raise ProxySchemeUnknown(proxy.scheme)
583
+
584
+ if not proxy.port:
585
+ port = port_by_scheme.get(proxy.scheme, 80)
586
+ proxy = proxy._replace(port=port)
587
+
588
+ self.proxy = proxy
589
+ self.proxy_headers = proxy_headers or {}
590
+ self.proxy_ssl_context = proxy_ssl_context
591
+ self.proxy_config = ProxyConfig(
592
+ proxy_ssl_context,
593
+ use_forwarding_for_https,
594
+ proxy_assert_hostname,
595
+ proxy_assert_fingerprint,
596
+ )
597
+
598
+ connection_pool_kw["_proxy"] = self.proxy
599
+ connection_pool_kw["_proxy_headers"] = self.proxy_headers
600
+ connection_pool_kw["_proxy_config"] = self.proxy_config
601
+
602
+ super().__init__(num_pools, headers, **connection_pool_kw)
603
+
604
+ def connection_from_host(
605
+ self,
606
+ host: str | None,
607
+ port: int | None = None,
608
+ scheme: str | None = "http",
609
+ pool_kwargs: dict[str, typing.Any] | None = None,
610
+ ) -> HTTPConnectionPool:
611
+ if scheme == "https":
612
+ return super().connection_from_host(
613
+ host, port, scheme, pool_kwargs=pool_kwargs
614
+ )
615
+
616
+ return super().connection_from_host(
617
+ self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs # type: ignore[union-attr]
618
+ )
619
+
620
+ def _set_proxy_headers(
621
+ self, url: str, headers: typing.Mapping[str, str] | None = None
622
+ ) -> typing.Mapping[str, str]:
623
+ """
624
+ Sets headers needed by proxies: specifically, the Accept and Host
625
+ headers. Only sets headers not provided by the user.
626
+ """
627
+ headers_ = {"Accept": "*/*"}
628
+
629
+ netloc = parse_url(url).netloc
630
+ if netloc:
631
+ headers_["Host"] = netloc
632
+
633
+ if headers:
634
+ headers_.update(headers)
635
+ return headers_
636
+
637
+ def urlopen( # type: ignore[override]
638
+ self, method: str, url: str, redirect: bool = True, **kw: typing.Any
639
+ ) -> BaseHTTPResponse:
640
+ "Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
641
+ u = parse_url(url)
642
+ if not connection_requires_http_tunnel(self.proxy, self.proxy_config, u.scheme):
643
+ # For connections using HTTP CONNECT, httplib sets the necessary
644
+ # headers on the CONNECT to the proxy. If we're not using CONNECT,
645
+ # we'll definitely need to set 'Host' at the very least.
646
+ headers = kw.get("headers", self.headers)
647
+ kw["headers"] = self._set_proxy_headers(url, headers)
648
+
649
+ return super().urlopen(method, url, redirect=redirect, **kw)
650
+
651
+
652
+ def proxy_from_url(url: str, **kw: typing.Any) -> ProxyManager:
653
+ return ProxyManager(proxy_url=url, **kw)
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/py.typed ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ # Instruct type checkers to look for inline type annotations in this package.
2
+ # See PEP 561.
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/response.py ADDED
@@ -0,0 +1,1487 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import collections
4
+ import io
5
+ import json as _json
6
+ import logging
7
+ import socket
8
+ import sys
9
+ import typing
10
+ import warnings
11
+ import zlib
12
+ from contextlib import contextmanager
13
+ from http.client import HTTPMessage as _HttplibHTTPMessage
14
+ from http.client import HTTPResponse as _HttplibHTTPResponse
15
+ from socket import timeout as SocketTimeout
16
+
17
+ if typing.TYPE_CHECKING:
18
+ from ._base_connection import BaseHTTPConnection
19
+
20
+ brotli = None
21
+
22
+ from . import util
23
+ from ._base_connection import _TYPE_BODY
24
+ from ._collections import HTTPHeaderDict
25
+ from .connection import BaseSSLError, HTTPConnection, HTTPException
26
+ from .exceptions import (
27
+ BodyNotHttplibCompatible,
28
+ DecodeError,
29
+ DependencyWarning,
30
+ HTTPError,
31
+ IncompleteRead,
32
+ InvalidChunkLength,
33
+ InvalidHeader,
34
+ ProtocolError,
35
+ ReadTimeoutError,
36
+ ResponseNotChunked,
37
+ SSLError,
38
+ )
39
+ from .util.response import is_fp_closed, is_response_to_head
40
+ from .util.retry import Retry
41
+
42
+ if typing.TYPE_CHECKING:
43
+ from .connectionpool import HTTPConnectionPool
44
+
45
+ log = logging.getLogger(__name__)
46
+
47
+
48
+ class ContentDecoder:
49
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
50
+ raise NotImplementedError()
51
+
52
+ @property
53
+ def has_unconsumed_tail(self) -> bool:
54
+ raise NotImplementedError()
55
+
56
+ def flush(self) -> bytes:
57
+ raise NotImplementedError()
58
+
59
+
60
+ class DeflateDecoder(ContentDecoder):
61
+ def __init__(self) -> None:
62
+ self._first_try = True
63
+ self._first_try_data = b""
64
+ self._unfed_data = b""
65
+ self._obj = zlib.decompressobj()
66
+
67
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
68
+ data = self._unfed_data + data
69
+ self._unfed_data = b""
70
+ if not data and not self._obj.unconsumed_tail:
71
+ return data
72
+ original_max_length = max_length
73
+ if original_max_length < 0:
74
+ max_length = 0
75
+ elif original_max_length == 0:
76
+ # We should not pass 0 to the zlib decompressor because 0 is
77
+ # the default value that will make zlib decompress without a
78
+ # length limit.
79
+ # Data should be stored for subsequent calls.
80
+ self._unfed_data = data
81
+ return b""
82
+
83
+ # Subsequent calls always reuse `self._obj`. zlib requires
84
+ # passing the unconsumed tail if decompression is to continue.
85
+ if not self._first_try:
86
+ return self._obj.decompress(
87
+ self._obj.unconsumed_tail + data, max_length=max_length
88
+ )
89
+
90
+ # First call tries with RFC 1950 ZLIB format.
91
+ self._first_try_data += data
92
+ try:
93
+ decompressed = self._obj.decompress(data, max_length=max_length)
94
+ if decompressed:
95
+ self._first_try = False
96
+ self._first_try_data = b""
97
+ return decompressed
98
+ # On failure, it falls back to RFC 1951 DEFLATE format.
99
+ except zlib.error:
100
+ self._first_try = False
101
+ self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
102
+ try:
103
+ return self.decompress(
104
+ self._first_try_data, max_length=original_max_length
105
+ )
106
+ finally:
107
+ self._first_try_data = b""
108
+
109
+ @property
110
+ def has_unconsumed_tail(self) -> bool:
111
+ return bool(self._unfed_data) or (
112
+ bool(self._obj.unconsumed_tail) and not self._first_try
113
+ )
114
+
115
+ def flush(self) -> bytes:
116
+ return self._obj.flush()
117
+
118
+
119
+ class GzipDecoderState:
120
+ FIRST_MEMBER = 0
121
+ OTHER_MEMBERS = 1
122
+ SWALLOW_DATA = 2
123
+
124
+
125
+ class GzipDecoder(ContentDecoder):
126
+ def __init__(self) -> None:
127
+ self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
128
+ self._state = GzipDecoderState.FIRST_MEMBER
129
+ self._unconsumed_tail = b""
130
+
131
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
132
+ ret = bytearray()
133
+ if self._state == GzipDecoderState.SWALLOW_DATA:
134
+ return bytes(ret)
135
+
136
+ if max_length == 0:
137
+ # We should not pass 0 to the zlib decompressor because 0 is
138
+ # the default value that will make zlib decompress without a
139
+ # length limit.
140
+ # Data should be stored for subsequent calls.
141
+ self._unconsumed_tail += data
142
+ return b""
143
+
144
+ # zlib requires passing the unconsumed tail to the subsequent
145
+ # call if decompression is to continue.
146
+ data = self._unconsumed_tail + data
147
+ if not data and self._obj.eof:
148
+ return bytes(ret)
149
+
150
+ while True:
151
+ try:
152
+ ret += self._obj.decompress(
153
+ data, max_length=max(max_length - len(ret), 0)
154
+ )
155
+ except zlib.error:
156
+ previous_state = self._state
157
+ # Ignore data after the first error
158
+ self._state = GzipDecoderState.SWALLOW_DATA
159
+ self._unconsumed_tail = b""
160
+ if previous_state == GzipDecoderState.OTHER_MEMBERS:
161
+ # Allow trailing garbage acceptable in other gzip clients
162
+ return bytes(ret)
163
+ raise
164
+
165
+ self._unconsumed_tail = data = (
166
+ self._obj.unconsumed_tail or self._obj.unused_data
167
+ )
168
+ if max_length > 0 and len(ret) >= max_length:
169
+ break
170
+
171
+ if not data:
172
+ return bytes(ret)
173
+ # When the end of a gzip member is reached, a new decompressor
174
+ # must be created for unused (possibly future) data.
175
+ if self._obj.eof:
176
+ self._state = GzipDecoderState.OTHER_MEMBERS
177
+ self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
178
+
179
+ return bytes(ret)
180
+
181
+ @property
182
+ def has_unconsumed_tail(self) -> bool:
183
+ return bool(self._unconsumed_tail)
184
+
185
+ def flush(self) -> bytes:
186
+ return self._obj.flush()
187
+
188
+
189
+ if brotli is not None:
190
+
191
+ class BrotliDecoder(ContentDecoder):
192
+ # Supports both 'brotlipy' and 'Brotli' packages
193
+ # since they share an import name. The top branches
194
+ # are for 'brotlipy' and bottom branches for 'Brotli'
195
+ def __init__(self) -> None:
196
+ self._obj = brotli.Decompressor()
197
+ if hasattr(self._obj, "decompress"):
198
+ setattr(self, "_decompress", self._obj.decompress)
199
+ else:
200
+ setattr(self, "_decompress", self._obj.process)
201
+
202
+ # Requires Brotli >= 1.2.0 for `output_buffer_limit`.
203
+ def _decompress(self, data: bytes, output_buffer_limit: int = -1) -> bytes:
204
+ raise NotImplementedError()
205
+
206
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
207
+ try:
208
+ if max_length > 0:
209
+ return self._decompress(data, output_buffer_limit=max_length)
210
+ else:
211
+ return self._decompress(data)
212
+ except TypeError:
213
+ # Fallback for Brotli/brotlicffi/brotlipy versions without
214
+ # the `output_buffer_limit` parameter.
215
+ warnings.warn(
216
+ "Brotli >= 1.2.0 is required to prevent decompression bombs.",
217
+ DependencyWarning,
218
+ )
219
+ return self._decompress(data)
220
+
221
+ @property
222
+ def has_unconsumed_tail(self) -> bool:
223
+ try:
224
+ return not self._obj.can_accept_more_data()
225
+ except AttributeError:
226
+ return False
227
+
228
+ def flush(self) -> bytes:
229
+ if hasattr(self._obj, "flush"):
230
+ return self._obj.flush() # type: ignore[no-any-return]
231
+ return b""
232
+
233
+
234
+ try:
235
+ if sys.version_info >= (3, 14):
236
+ from compression import zstd
237
+ else:
238
+ from backports import zstd
239
+ except ImportError:
240
+ HAS_ZSTD = False
241
+ else:
242
+ HAS_ZSTD = True
243
+
244
+ class ZstdDecoder(ContentDecoder):
245
+ def __init__(self) -> None:
246
+ self._obj = zstd.ZstdDecompressor()
247
+
248
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
249
+ if not data and not self.has_unconsumed_tail:
250
+ return b""
251
+ if self._obj.eof:
252
+ data = self._obj.unused_data + data
253
+ self._obj = zstd.ZstdDecompressor()
254
+ part = self._obj.decompress(data, max_length=max_length)
255
+ length = len(part)
256
+ data_parts = [part]
257
+ # Every loop iteration is supposed to read data from a separate frame.
258
+ # The loop breaks when:
259
+ # - enough data is read;
260
+ # - no more unused data is available;
261
+ # - end of the last read frame has not been reached (i.e.,
262
+ # more data has to be fed).
263
+ while (
264
+ self._obj.eof
265
+ and self._obj.unused_data
266
+ and (max_length < 0 or length < max_length)
267
+ ):
268
+ unused_data = self._obj.unused_data
269
+ if not self._obj.needs_input:
270
+ self._obj = zstd.ZstdDecompressor()
271
+ part = self._obj.decompress(
272
+ unused_data,
273
+ max_length=(max_length - length) if max_length > 0 else -1,
274
+ )
275
+ if part_length := len(part):
276
+ data_parts.append(part)
277
+ length += part_length
278
+ elif self._obj.needs_input:
279
+ break
280
+ return b"".join(data_parts)
281
+
282
+ @property
283
+ def has_unconsumed_tail(self) -> bool:
284
+ return not (self._obj.needs_input or self._obj.eof) or bool(
285
+ self._obj.unused_data
286
+ )
287
+
288
+ def flush(self) -> bytes:
289
+ if not self._obj.eof:
290
+ raise DecodeError("Zstandard data is incomplete")
291
+ return b""
292
+
293
+
294
+ class MultiDecoder(ContentDecoder):
295
+ """
296
+ From RFC7231:
297
+ If one or more encodings have been applied to a representation, the
298
+ sender that applied the encodings MUST generate a Content-Encoding
299
+ header field that lists the content codings in the order in which
300
+ they were applied.
301
+ """
302
+
303
+ # Maximum allowed number of chained HTTP encodings in the
304
+ # Content-Encoding header.
305
+ max_decode_links = 5
306
+
307
+ def __init__(self, modes: str) -> None:
308
+ encodings = [m.strip() for m in modes.split(",")]
309
+ if len(encodings) > self.max_decode_links:
310
+ raise DecodeError(
311
+ "Too many content encodings in the chain: "
312
+ f"{len(encodings)} > {self.max_decode_links}"
313
+ )
314
+ self._decoders = [_get_decoder(e) for e in encodings]
315
+
316
+ def flush(self) -> bytes:
317
+ return self._decoders[0].flush()
318
+
319
+ def decompress(self, data: bytes, max_length: int = -1) -> bytes:
320
+ if max_length <= 0:
321
+ for d in reversed(self._decoders):
322
+ data = d.decompress(data)
323
+ return data
324
+
325
+ ret = bytearray()
326
+ # Every while loop iteration goes through all decoders once.
327
+ # It exits when enough data is read or no more data can be read.
328
+ # It is possible that the while loop iteration does not produce
329
+ # any data because we retrieve up to `max_length` from every
330
+ # decoder, and the amount of bytes may be insufficient for the
331
+ # next decoder to produce enough/any output.
332
+ while True:
333
+ any_data = False
334
+ for d in reversed(self._decoders):
335
+ data = d.decompress(data, max_length=max_length - len(ret))
336
+ if data:
337
+ any_data = True
338
+ # We should not break when no data is returned because
339
+ # next decoders may produce data even with empty input.
340
+ ret += data
341
+ if not any_data or len(ret) >= max_length:
342
+ return bytes(ret)
343
+ data = b""
344
+
345
+ @property
346
+ def has_unconsumed_tail(self) -> bool:
347
+ return any(d.has_unconsumed_tail for d in self._decoders)
348
+
349
+
350
+ def _get_decoder(mode: str) -> ContentDecoder:
351
+ if "," in mode:
352
+ return MultiDecoder(mode)
353
+
354
+ # According to RFC 9110 section 8.4.1.3, recipients should
355
+ # consider x-gzip equivalent to gzip
356
+ if mode in ("gzip", "x-gzip"):
357
+ return GzipDecoder()
358
+
359
+ if brotli is not None and mode == "br":
360
+ return BrotliDecoder()
361
+
362
+ if HAS_ZSTD and mode == "zstd":
363
+ return ZstdDecoder()
364
+
365
+ return DeflateDecoder()
366
+
367
+
368
+ class BytesQueueBuffer:
369
+ """Memory-efficient bytes buffer
370
+
371
+ To return decoded data in read() and still follow the BufferedIOBase API, we need a
372
+ buffer to always return the correct amount of bytes.
373
+
374
+ This buffer should be filled using calls to put()
375
+
376
+ Our maximum memory usage is determined by the sum of the size of:
377
+
378
+ * self.buffer, which contains the full data
379
+ * the largest chunk that we will copy in get()
380
+ """
381
+
382
+ def __init__(self) -> None:
383
+ self.buffer: typing.Deque[bytes | memoryview[bytes]] = collections.deque()
384
+ self._size: int = 0
385
+
386
+ def __len__(self) -> int:
387
+ return self._size
388
+
389
+ def put(self, data: bytes) -> None:
390
+ self.buffer.append(data)
391
+ self._size += len(data)
392
+
393
+ def get(self, n: int) -> bytes:
394
+ if n == 0:
395
+ return b""
396
+ elif not self.buffer:
397
+ raise RuntimeError("buffer is empty")
398
+ elif n < 0:
399
+ raise ValueError("n should be > 0")
400
+
401
+ if len(self.buffer[0]) == n and isinstance(self.buffer[0], bytes):
402
+ self._size -= n
403
+ return self.buffer.popleft()
404
+
405
+ fetched = 0
406
+ ret = io.BytesIO()
407
+ while fetched < n:
408
+ remaining = n - fetched
409
+ chunk = self.buffer.popleft()
410
+ chunk_length = len(chunk)
411
+ if remaining < chunk_length:
412
+ chunk = memoryview(chunk)
413
+ left_chunk, right_chunk = chunk[:remaining], chunk[remaining:]
414
+ ret.write(left_chunk)
415
+ self.buffer.appendleft(right_chunk)
416
+ self._size -= remaining
417
+ break
418
+ else:
419
+ ret.write(chunk)
420
+ self._size -= chunk_length
421
+ fetched += chunk_length
422
+
423
+ if not self.buffer:
424
+ break
425
+
426
+ return ret.getvalue()
427
+
428
+ def get_all(self) -> bytes:
429
+ buffer = self.buffer
430
+ if not buffer:
431
+ assert self._size == 0
432
+ return b""
433
+ if len(buffer) == 1:
434
+ result = buffer.pop()
435
+ if isinstance(result, memoryview):
436
+ result = result.tobytes()
437
+ else:
438
+ ret = io.BytesIO()
439
+ ret.writelines(buffer.popleft() for _ in range(len(buffer)))
440
+ result = ret.getvalue()
441
+ self._size = 0
442
+ return result
443
+
444
+
445
+ class BaseHTTPResponse(io.IOBase):
446
+ CONTENT_DECODERS = ["gzip", "x-gzip", "deflate"]
447
+ if brotli is not None:
448
+ CONTENT_DECODERS += ["br"]
449
+ if HAS_ZSTD:
450
+ CONTENT_DECODERS += ["zstd"]
451
+ REDIRECT_STATUSES = [301, 302, 303, 307, 308]
452
+
453
+ DECODER_ERROR_CLASSES: tuple[type[Exception], ...] = (IOError, zlib.error)
454
+ if brotli is not None:
455
+ DECODER_ERROR_CLASSES += (brotli.error,)
456
+
457
+ if HAS_ZSTD:
458
+ DECODER_ERROR_CLASSES += (zstd.ZstdError,)
459
+
460
+ def __init__(
461
+ self,
462
+ *,
463
+ headers: typing.Mapping[str, str] | typing.Mapping[bytes, bytes] | None = None,
464
+ status: int,
465
+ version: int,
466
+ version_string: str,
467
+ reason: str | None,
468
+ decode_content: bool,
469
+ request_url: str | None,
470
+ retries: Retry | None = None,
471
+ ) -> None:
472
+ if isinstance(headers, HTTPHeaderDict):
473
+ self.headers = headers
474
+ else:
475
+ self.headers = HTTPHeaderDict(headers) # type: ignore[arg-type]
476
+ self.status = status
477
+ self.version = version
478
+ self.version_string = version_string
479
+ self.reason = reason
480
+ self.decode_content = decode_content
481
+ self._has_decoded_content = False
482
+ self._request_url: str | None = request_url
483
+ self.retries = retries
484
+
485
+ self.chunked = False
486
+ tr_enc = self.headers.get("transfer-encoding", "").lower()
487
+ # Don't incur the penalty of creating a list and then discarding it
488
+ encodings = (enc.strip() for enc in tr_enc.split(","))
489
+ if "chunked" in encodings:
490
+ self.chunked = True
491
+
492
+ self._decoder: ContentDecoder | None = None
493
+ self.length_remaining: int | None
494
+
495
+ def get_redirect_location(self) -> str | None | typing.Literal[False]:
496
+ """
497
+ Should we redirect and where to?
498
+
499
+ :returns: Truthy redirect location string if we got a redirect status
500
+ code and valid location. ``None`` if redirect status and no
501
+ location. ``False`` if not a redirect status code.
502
+ """
503
+ if self.status in self.REDIRECT_STATUSES:
504
+ return self.headers.get("location")
505
+ return False
506
+
507
+ @property
508
+ def data(self) -> bytes:
509
+ raise NotImplementedError()
510
+
511
+ def json(self) -> typing.Any:
512
+ """
513
+ Deserializes the body of the HTTP response as a Python object.
514
+
515
+ The body of the HTTP response must be encoded using UTF-8, as per
516
+ `RFC 8529 Section 8.1 <https://www.rfc-editor.org/rfc/rfc8259#section-8.1>`_.
517
+
518
+ To use a custom JSON decoder pass the result of :attr:`HTTPResponse.data` to
519
+ your custom decoder instead.
520
+
521
+ If the body of the HTTP response is not decodable to UTF-8, a
522
+ `UnicodeDecodeError` will be raised. If the body of the HTTP response is not a
523
+ valid JSON document, a `json.JSONDecodeError` will be raised.
524
+
525
+ Read more :ref:`here <json_content>`.
526
+
527
+ :returns: The body of the HTTP response as a Python object.
528
+ """
529
+ data = self.data.decode("utf-8")
530
+ return _json.loads(data)
531
+
532
+ @property
533
+ def url(self) -> str | None:
534
+ raise NotImplementedError()
535
+
536
+ @url.setter
537
+ def url(self, url: str | None) -> None:
538
+ raise NotImplementedError()
539
+
540
+ @property
541
+ def connection(self) -> BaseHTTPConnection | None:
542
+ raise NotImplementedError()
543
+
544
+ @property
545
+ def retries(self) -> Retry | None:
546
+ return self._retries
547
+
548
+ @retries.setter
549
+ def retries(self, retries: Retry | None) -> None:
550
+ # Override the request_url if retries has a redirect location.
551
+ if retries is not None and retries.history:
552
+ self.url = retries.history[-1].redirect_location
553
+ self._retries = retries
554
+
555
+ def stream(
556
+ self, amt: int | None = 2**16, decode_content: bool | None = None
557
+ ) -> typing.Iterator[bytes]:
558
+ raise NotImplementedError()
559
+
560
+ def read(
561
+ self,
562
+ amt: int | None = None,
563
+ decode_content: bool | None = None,
564
+ cache_content: bool = False,
565
+ ) -> bytes:
566
+ raise NotImplementedError()
567
+
568
+ def read1(
569
+ self,
570
+ amt: int | None = None,
571
+ decode_content: bool | None = None,
572
+ ) -> bytes:
573
+ raise NotImplementedError()
574
+
575
+ def read_chunked(
576
+ self,
577
+ amt: int | None = None,
578
+ decode_content: bool | None = None,
579
+ ) -> typing.Iterator[bytes]:
580
+ raise NotImplementedError()
581
+
582
+ def release_conn(self) -> None:
583
+ raise NotImplementedError()
584
+
585
+ def drain_conn(self) -> None:
586
+ raise NotImplementedError()
587
+
588
+ def shutdown(self) -> None:
589
+ raise NotImplementedError()
590
+
591
+ def close(self) -> None:
592
+ raise NotImplementedError()
593
+
594
+ def _init_decoder(self) -> None:
595
+ """
596
+ Set-up the _decoder attribute if necessary.
597
+ """
598
+ # Note: content-encoding value should be case-insensitive, per RFC 7230
599
+ # Section 3.2
600
+ content_encoding = self.headers.get("content-encoding", "").lower()
601
+ if self._decoder is None:
602
+ if content_encoding in self.CONTENT_DECODERS:
603
+ self._decoder = _get_decoder(content_encoding)
604
+ elif "," in content_encoding:
605
+ encodings = [
606
+ e.strip()
607
+ for e in content_encoding.split(",")
608
+ if e.strip() in self.CONTENT_DECODERS
609
+ ]
610
+ if encodings:
611
+ self._decoder = _get_decoder(content_encoding)
612
+
613
+ def _decode(
614
+ self,
615
+ data: bytes,
616
+ decode_content: bool | None,
617
+ flush_decoder: bool,
618
+ max_length: int | None = None,
619
+ ) -> bytes:
620
+ """
621
+ Decode the data passed in and potentially flush the decoder.
622
+ """
623
+ if not decode_content:
624
+ if self._has_decoded_content:
625
+ raise RuntimeError(
626
+ "Calling read(decode_content=False) is not supported after "
627
+ "read(decode_content=True) was called."
628
+ )
629
+ return data
630
+
631
+ if max_length is None or flush_decoder:
632
+ max_length = -1
633
+
634
+ try:
635
+ if self._decoder:
636
+ data = self._decoder.decompress(data, max_length=max_length)
637
+ self._has_decoded_content = True
638
+ except self.DECODER_ERROR_CLASSES as e:
639
+ content_encoding = self.headers.get("content-encoding", "").lower()
640
+ raise DecodeError(
641
+ "Received response with content-encoding: %s, but "
642
+ "failed to decode it." % content_encoding,
643
+ e,
644
+ ) from e
645
+ if flush_decoder:
646
+ data += self._flush_decoder()
647
+
648
+ return data
649
+
650
+ def _flush_decoder(self) -> bytes:
651
+ """
652
+ Flushes the decoder. Should only be called if the decoder is actually
653
+ being used.
654
+ """
655
+ if self._decoder:
656
+ return self._decoder.decompress(b"") + self._decoder.flush()
657
+ return b""
658
+
659
+ # Compatibility methods for `io` module
660
+ def readinto(self, b: bytearray | memoryview[int]) -> int:
661
+ temp = self.read(len(b))
662
+ if len(temp) == 0:
663
+ return 0
664
+ else:
665
+ b[: len(temp)] = temp
666
+ return len(temp)
667
+
668
+ # Methods used by dependent libraries
669
+ def getheaders(self) -> HTTPHeaderDict:
670
+ return self.headers
671
+
672
+ def getheader(self, name: str, default: str | None = None) -> str | None:
673
+ return self.headers.get(name, default)
674
+
675
+ # Compatibility method for http.cookiejar
676
+ def info(self) -> HTTPHeaderDict:
677
+ return self.headers
678
+
679
+ def geturl(self) -> str | None:
680
+ return self.url
681
+
682
+
683
+ class HTTPResponse(BaseHTTPResponse):
684
+ """
685
+ HTTP Response container.
686
+
687
+ Backwards-compatible with :class:`http.client.HTTPResponse` but the response ``body`` is
688
+ loaded and decoded on-demand when the ``data`` property is accessed. This
689
+ class is also compatible with the Python standard library's :mod:`io`
690
+ module, and can hence be treated as a readable object in the context of that
691
+ framework.
692
+
693
+ Extra parameters for behaviour not present in :class:`http.client.HTTPResponse`:
694
+
695
+ :param preload_content:
696
+ If True, the response's body will be preloaded during construction.
697
+
698
+ :param decode_content:
699
+ If True, will attempt to decode the body based on the
700
+ 'content-encoding' header.
701
+
702
+ :param original_response:
703
+ When this HTTPResponse wrapper is generated from an :class:`http.client.HTTPResponse`
704
+ object, it's convenient to include the original for debug purposes. It's
705
+ otherwise unused.
706
+
707
+ :param retries:
708
+ The retries contains the last :class:`~urllib3.util.retry.Retry` that
709
+ was used during the request.
710
+
711
+ :param enforce_content_length:
712
+ Enforce content length checking. Body returned by server must match
713
+ value of Content-Length header, if present. Otherwise, raise error.
714
+ """
715
+
716
+ def __init__(
717
+ self,
718
+ body: _TYPE_BODY = "",
719
+ headers: typing.Mapping[str, str] | typing.Mapping[bytes, bytes] | None = None,
720
+ status: int = 0,
721
+ version: int = 0,
722
+ version_string: str = "HTTP/?",
723
+ reason: str | None = None,
724
+ preload_content: bool = True,
725
+ decode_content: bool = True,
726
+ original_response: _HttplibHTTPResponse | None = None,
727
+ pool: HTTPConnectionPool | None = None,
728
+ connection: HTTPConnection | None = None,
729
+ msg: _HttplibHTTPMessage | None = None,
730
+ retries: Retry | None = None,
731
+ enforce_content_length: bool = True,
732
+ request_method: str | None = None,
733
+ request_url: str | None = None,
734
+ auto_close: bool = True,
735
+ sock_shutdown: typing.Callable[[int], None] | None = None,
736
+ ) -> None:
737
+ super().__init__(
738
+ headers=headers,
739
+ status=status,
740
+ version=version,
741
+ version_string=version_string,
742
+ reason=reason,
743
+ decode_content=decode_content,
744
+ request_url=request_url,
745
+ retries=retries,
746
+ )
747
+
748
+ self.enforce_content_length = enforce_content_length
749
+ self.auto_close = auto_close
750
+
751
+ self._body = None
752
+ self._uncached_read_occurred = False
753
+ self._fp: _HttplibHTTPResponse | None = None
754
+ self._original_response = original_response
755
+ self._fp_bytes_read = 0
756
+ self.msg = msg
757
+
758
+ if body and isinstance(body, (str, bytes)):
759
+ self._body = body
760
+
761
+ self._pool = pool
762
+ self._connection = connection
763
+
764
+ if hasattr(body, "read"):
765
+ self._fp = body # type: ignore[assignment]
766
+ self._sock_shutdown = sock_shutdown
767
+
768
+ # Are we using the chunked-style of transfer encoding?
769
+ self.chunk_left: int | None = None
770
+
771
+ # Determine length of response
772
+ self.length_remaining = self._init_length(request_method)
773
+
774
+ # Used to return the correct amount of bytes for partial read()s
775
+ self._decoded_buffer = BytesQueueBuffer()
776
+
777
+ # If requested, preload the body.
778
+ if preload_content and not self._body:
779
+ self._body = self.read(decode_content=decode_content)
780
+
781
+ def release_conn(self) -> None:
782
+ if not self._pool or not self._connection:
783
+ return None
784
+
785
+ self._pool._put_conn(self._connection)
786
+ self._connection = None
787
+
788
+ def drain_conn(self) -> None:
789
+ """
790
+ Read and discard any remaining HTTP response data in the response connection.
791
+
792
+ Unread data in the HTTPResponse connection blocks the connection from being released back to the pool.
793
+ """
794
+ try:
795
+ self._raw_read()
796
+ except (HTTPError, OSError, BaseSSLError, HTTPException):
797
+ pass
798
+ if self._has_decoded_content:
799
+ # `_raw_read` skips decompression, so we should clean up the
800
+ # decoder to avoid keeping unnecessary data in memory.
801
+ self._decoded_buffer = BytesQueueBuffer()
802
+ self._decoder = None
803
+
804
+ @property
805
+ def data(self) -> bytes:
806
+ # For backwards-compat with earlier urllib3 0.4 and earlier.
807
+ if self._body:
808
+ return self._body # type: ignore[return-value]
809
+
810
+ if self._fp:
811
+ return self.read(cache_content=True)
812
+
813
+ return None # type: ignore[return-value]
814
+
815
+ @property
816
+ def connection(self) -> HTTPConnection | None:
817
+ return self._connection
818
+
819
+ def isclosed(self) -> bool:
820
+ return is_fp_closed(self._fp)
821
+
822
+ def tell(self) -> int:
823
+ """
824
+ Obtain the number of bytes pulled over the wire so far. May differ from
825
+ the amount of content returned by :meth:`HTTPResponse.read`
826
+ if bytes are encoded on the wire (e.g, compressed).
827
+ """
828
+ return self._fp_bytes_read
829
+
830
+ def _init_length(self, request_method: str | None) -> int | None:
831
+ """
832
+ Set initial length value for Response content if available.
833
+ """
834
+ length: int | None
835
+ content_length: str | None = self.headers.get("content-length")
836
+
837
+ if content_length is not None:
838
+ if self.chunked:
839
+ # This Response will fail with an IncompleteRead if it can't be
840
+ # received as chunked. This method falls back to attempt reading
841
+ # the response before raising an exception.
842
+ log.warning(
843
+ "Received response with both Content-Length and "
844
+ "Transfer-Encoding set. This is expressly forbidden "
845
+ "by RFC 7230 sec 3.3.2. Ignoring Content-Length and "
846
+ "attempting to process response as Transfer-Encoding: "
847
+ "chunked."
848
+ )
849
+ return None
850
+
851
+ try:
852
+ # RFC 7230 section 3.3.2 specifies multiple content lengths can
853
+ # be sent in a single Content-Length header
854
+ # (e.g. Content-Length: 42, 42). This line ensures the values
855
+ # are all valid ints and that as long as the `set` length is 1,
856
+ # all values are the same. Otherwise, the header is invalid.
857
+ lengths = {int(val) for val in content_length.split(",")}
858
+ if len(lengths) > 1:
859
+ raise InvalidHeader(
860
+ "Content-Length contained multiple "
861
+ "unmatching values (%s)" % content_length
862
+ )
863
+ length = lengths.pop()
864
+ except ValueError:
865
+ length = None
866
+ else:
867
+ if length < 0:
868
+ length = None
869
+
870
+ else: # if content_length is None
871
+ length = None
872
+
873
+ # Convert status to int for comparison
874
+ # In some cases, httplib returns a status of "_UNKNOWN"
875
+ try:
876
+ status = int(self.status)
877
+ except ValueError:
878
+ status = 0
879
+
880
+ # Check for responses that shouldn't include a body
881
+ if status in (204, 304) or 100 <= status < 200 or request_method == "HEAD":
882
+ length = 0
883
+
884
+ return length
885
+
886
+ @contextmanager
887
+ def _error_catcher(self) -> typing.Generator[None]:
888
+ """
889
+ Catch low-level python exceptions, instead re-raising urllib3
890
+ variants, so that low-level exceptions are not leaked in the
891
+ high-level api.
892
+
893
+ On exit, release the connection back to the pool.
894
+ """
895
+ clean_exit = False
896
+
897
+ try:
898
+ try:
899
+ yield
900
+
901
+ except SocketTimeout as e:
902
+ # FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
903
+ # there is yet no clean way to get at it from this context.
904
+ raise ReadTimeoutError(self._pool, None, "Read timed out.") from e # type: ignore[arg-type]
905
+
906
+ except BaseSSLError as e:
907
+ # SSL errors related to framing/MAC get wrapped and reraised here
908
+ raise SSLError(e) from e
909
+
910
+ except IncompleteRead as e:
911
+ if (
912
+ e.expected is not None
913
+ and e.partial is not None
914
+ and e.expected == -e.partial
915
+ ):
916
+ arg = "Response may not contain content."
917
+ else:
918
+ arg = f"Connection broken: {e!r}"
919
+ raise ProtocolError(arg, e) from e
920
+
921
+ except (HTTPException, OSError) as e:
922
+ raise ProtocolError(f"Connection broken: {e!r}", e) from e
923
+
924
+ # If no exception is thrown, we should avoid cleaning up
925
+ # unnecessarily.
926
+ clean_exit = True
927
+ finally:
928
+ # If we didn't terminate cleanly, we need to throw away our
929
+ # connection.
930
+ if not clean_exit:
931
+ # The response may not be closed but we're not going to use it
932
+ # anymore so close it now to ensure that the connection is
933
+ # released back to the pool.
934
+ if self._original_response:
935
+ self._original_response.close()
936
+
937
+ # Closing the response may not actually be sufficient to close
938
+ # everything, so if we have a hold of the connection close that
939
+ # too.
940
+ if self._connection:
941
+ self._connection.close()
942
+
943
+ # If we hold the original response but it's closed now, we should
944
+ # return the connection back to the pool.
945
+ if self._original_response and self._original_response.isclosed():
946
+ self.release_conn()
947
+
948
+ def _fp_read(
949
+ self,
950
+ amt: int | None = None,
951
+ *,
952
+ read1: bool = False,
953
+ ) -> bytes:
954
+ """
955
+ Read a response with the thought that reading the number of bytes
956
+ larger than can fit in a 32-bit int at a time via SSL in some
957
+ known cases leads to an overflow error that has to be prevented
958
+ if `amt` or `self.length_remaining` indicate that a problem may
959
+ happen.
960
+
961
+ This happens to urllib3 injected with pyOpenSSL-backed SSL-support.
962
+ """
963
+ assert self._fp
964
+ c_int_max = 2**31 - 1
965
+ if (
966
+ (amt and amt > c_int_max)
967
+ or (
968
+ amt is None
969
+ and self.length_remaining
970
+ and self.length_remaining > c_int_max
971
+ )
972
+ ) and util.IS_PYOPENSSL:
973
+ if read1:
974
+ return self._fp.read1(c_int_max)
975
+ buffer = io.BytesIO()
976
+ # Besides `max_chunk_amt` being a maximum chunk size, it
977
+ # affects memory overhead of reading a response by this
978
+ # method in CPython.
979
+ # `c_int_max` equal to 2 GiB - 1 byte is the actual maximum
980
+ # chunk size that does not lead to an overflow error, but
981
+ # 256 MiB is a compromise.
982
+ max_chunk_amt = 2**28
983
+ while amt is None or amt != 0:
984
+ if amt is not None:
985
+ chunk_amt = min(amt, max_chunk_amt)
986
+ amt -= chunk_amt
987
+ else:
988
+ chunk_amt = max_chunk_amt
989
+ data = self._fp.read(chunk_amt)
990
+ if not data:
991
+ break
992
+ buffer.write(data)
993
+ del data # to reduce peak memory usage by `max_chunk_amt`.
994
+ return buffer.getvalue()
995
+ elif read1:
996
+ return self._fp.read1(amt) if amt is not None else self._fp.read1()
997
+ else:
998
+ # StringIO doesn't like amt=None
999
+ return self._fp.read(amt) if amt is not None else self._fp.read()
1000
+
1001
+ def _raw_read(
1002
+ self,
1003
+ amt: int | None = None,
1004
+ *,
1005
+ read1: bool = False,
1006
+ ) -> bytes:
1007
+ """
1008
+ Reads `amt` of bytes from the socket.
1009
+ """
1010
+ if self._fp is None:
1011
+ return None # type: ignore[return-value]
1012
+
1013
+ fp_closed = getattr(self._fp, "closed", False)
1014
+
1015
+ with self._error_catcher():
1016
+ data = self._fp_read(amt, read1=read1) if not fp_closed else b""
1017
+ if amt is not None and amt != 0 and not data:
1018
+ # Platform-specific: Buggy versions of Python.
1019
+ # Close the connection when no data is returned
1020
+ #
1021
+ # This is redundant to what httplib/http.client _should_
1022
+ # already do. However, versions of python released before
1023
+ # December 15, 2012 (http://bugs.python.org/issue16298) do
1024
+ # not properly close the connection in all cases. There is
1025
+ # no harm in redundantly calling close.
1026
+ self._fp.close()
1027
+ if (
1028
+ self.enforce_content_length
1029
+ and self.length_remaining is not None
1030
+ and self.length_remaining != 0
1031
+ ):
1032
+ # This is an edge case that httplib failed to cover due
1033
+ # to concerns of backward compatibility. We're
1034
+ # addressing it here to make sure IncompleteRead is
1035
+ # raised during streaming, so all calls with incorrect
1036
+ # Content-Length are caught.
1037
+ raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
1038
+ elif read1 and (
1039
+ (amt != 0 and not data) or self.length_remaining == len(data)
1040
+ ):
1041
+ # All data has been read, but `self._fp.read1` in
1042
+ # CPython 3.12 and older doesn't always close
1043
+ # `http.client.HTTPResponse`, so we close it here.
1044
+ # See https://github.com/python/cpython/issues/113199
1045
+ self._fp.close()
1046
+
1047
+ if data:
1048
+ self._fp_bytes_read += len(data)
1049
+ if self.length_remaining is not None:
1050
+ self.length_remaining -= len(data)
1051
+ return data
1052
+
1053
+ def read(
1054
+ self,
1055
+ amt: int | None = None,
1056
+ decode_content: bool | None = None,
1057
+ cache_content: bool = False,
1058
+ ) -> bytes:
1059
+ """
1060
+ Similar to :meth:`http.client.HTTPResponse.read`, but with two additional
1061
+ parameters: ``decode_content`` and ``cache_content``.
1062
+
1063
+ :param amt:
1064
+ How much of the content to read. If specified, caching is skipped
1065
+ because it doesn't make sense to cache partial content as the full
1066
+ response.
1067
+
1068
+ :param decode_content:
1069
+ If True, will attempt to decode the body based on the
1070
+ 'content-encoding' header.
1071
+
1072
+ :param cache_content:
1073
+ If True, will save the returned data such that the same result is
1074
+ returned despite of the state of the underlying file object. This
1075
+ is useful if you want the ``.data`` property to continue working
1076
+ after having ``.read()`` the file object. (Overridden if ``amt`` is
1077
+ set.)
1078
+ """
1079
+ self._init_decoder()
1080
+ if decode_content is None:
1081
+ decode_content = self.decode_content
1082
+
1083
+ if amt and amt < 0:
1084
+ # Negative numbers and `None` should be treated the same.
1085
+ amt = None
1086
+ elif amt is not None:
1087
+ cache_content = False
1088
+
1089
+ if (
1090
+ self._decoder
1091
+ and self._decoder.has_unconsumed_tail
1092
+ and len(self._decoded_buffer) < amt
1093
+ ):
1094
+ decoded_data = self._decode(
1095
+ b"",
1096
+ decode_content,
1097
+ flush_decoder=False,
1098
+ max_length=amt - len(self._decoded_buffer),
1099
+ )
1100
+ self._decoded_buffer.put(decoded_data)
1101
+ if len(self._decoded_buffer) >= amt:
1102
+ return self._decoded_buffer.get(amt)
1103
+
1104
+ data = self._raw_read(amt)
1105
+ if not cache_content:
1106
+ self._uncached_read_occurred = True
1107
+
1108
+ flush_decoder = amt is None or (amt != 0 and not data)
1109
+
1110
+ if (
1111
+ not data
1112
+ and len(self._decoded_buffer) == 0
1113
+ and not (self._decoder and self._decoder.has_unconsumed_tail)
1114
+ ):
1115
+ return data
1116
+
1117
+ if amt is None:
1118
+ data = self._decode(data, decode_content, flush_decoder)
1119
+ # It's possible that there is buffered decoded data after a
1120
+ # partial read.
1121
+ if decode_content and len(self._decoded_buffer) > 0:
1122
+ self._decoded_buffer.put(data)
1123
+ data = self._decoded_buffer.get_all()
1124
+
1125
+ if cache_content and not self._uncached_read_occurred:
1126
+ self._body = data
1127
+ else:
1128
+ # do not waste memory on buffer when not decoding
1129
+ if not decode_content:
1130
+ if self._has_decoded_content:
1131
+ raise RuntimeError(
1132
+ "Calling read(decode_content=False) is not supported after "
1133
+ "read(decode_content=True) was called."
1134
+ )
1135
+ return data
1136
+
1137
+ decoded_data = self._decode(
1138
+ data,
1139
+ decode_content,
1140
+ flush_decoder,
1141
+ max_length=amt - len(self._decoded_buffer),
1142
+ )
1143
+ self._decoded_buffer.put(decoded_data)
1144
+
1145
+ while len(self._decoded_buffer) < amt and data:
1146
+ # TODO make sure to initially read enough data to get past the headers
1147
+ # For example, the GZ file header takes 10 bytes, we don't want to read
1148
+ # it one byte at a time
1149
+ data = self._raw_read(amt)
1150
+ decoded_data = self._decode(
1151
+ data,
1152
+ decode_content,
1153
+ flush_decoder,
1154
+ max_length=amt - len(self._decoded_buffer),
1155
+ )
1156
+ self._decoded_buffer.put(decoded_data)
1157
+ data = self._decoded_buffer.get(amt)
1158
+
1159
+ return data
1160
+
1161
+ def read1(
1162
+ self,
1163
+ amt: int | None = None,
1164
+ decode_content: bool | None = None,
1165
+ ) -> bytes:
1166
+ """
1167
+ Similar to ``http.client.HTTPResponse.read1`` and documented
1168
+ in :meth:`io.BufferedReader.read1`, but with an additional parameter:
1169
+ ``decode_content``.
1170
+
1171
+ :param amt:
1172
+ How much of the content to read.
1173
+
1174
+ :param decode_content:
1175
+ If True, will attempt to decode the body based on the
1176
+ 'content-encoding' header.
1177
+ """
1178
+ if decode_content is None:
1179
+ decode_content = self.decode_content
1180
+ if amt and amt < 0:
1181
+ # Negative numbers and `None` should be treated the same.
1182
+ amt = None
1183
+ # try and respond without going to the network
1184
+ if self._has_decoded_content:
1185
+ if not decode_content:
1186
+ raise RuntimeError(
1187
+ "Calling read1(decode_content=False) is not supported after "
1188
+ "read1(decode_content=True) was called."
1189
+ )
1190
+ if (
1191
+ self._decoder
1192
+ and self._decoder.has_unconsumed_tail
1193
+ and (amt is None or len(self._decoded_buffer) < amt)
1194
+ ):
1195
+ decoded_data = self._decode(
1196
+ b"",
1197
+ decode_content,
1198
+ flush_decoder=False,
1199
+ max_length=(
1200
+ amt - len(self._decoded_buffer) if amt is not None else None
1201
+ ),
1202
+ )
1203
+ self._decoded_buffer.put(decoded_data)
1204
+ if len(self._decoded_buffer) > 0:
1205
+ if amt is None:
1206
+ return self._decoded_buffer.get_all()
1207
+ return self._decoded_buffer.get(amt)
1208
+ if amt == 0:
1209
+ return b""
1210
+
1211
+ # FIXME, this method's type doesn't say returning None is possible
1212
+ data = self._raw_read(amt, read1=True)
1213
+ self._uncached_read_occurred = True
1214
+ if not decode_content or data is None:
1215
+ return data
1216
+
1217
+ self._init_decoder()
1218
+ while True:
1219
+ flush_decoder = not data
1220
+ decoded_data = self._decode(
1221
+ data, decode_content, flush_decoder, max_length=amt
1222
+ )
1223
+ self._decoded_buffer.put(decoded_data)
1224
+ if decoded_data or flush_decoder:
1225
+ break
1226
+ data = self._raw_read(8192, read1=True)
1227
+
1228
+ if amt is None:
1229
+ return self._decoded_buffer.get_all()
1230
+ return self._decoded_buffer.get(amt)
1231
+
1232
+ def stream(
1233
+ self, amt: int | None = 2**16, decode_content: bool | None = None
1234
+ ) -> typing.Generator[bytes]:
1235
+ """
1236
+ A generator wrapper for the read() method. A call will block until
1237
+ ``amt`` bytes have been read from the connection or until the
1238
+ connection is closed.
1239
+
1240
+ :param amt:
1241
+ How much of the content to read. The generator will return up to
1242
+ much data per iteration, but may return less. This is particularly
1243
+ likely when using compressed data. However, the empty string will
1244
+ never be returned.
1245
+
1246
+ :param decode_content:
1247
+ If True, will attempt to decode the body based on the
1248
+ 'content-encoding' header.
1249
+ """
1250
+ if amt == 0:
1251
+ return
1252
+
1253
+ if self.chunked and self.supports_chunked_reads():
1254
+ yield from self.read_chunked(amt, decode_content=decode_content)
1255
+ else:
1256
+ while (
1257
+ not is_fp_closed(self._fp)
1258
+ or len(self._decoded_buffer) > 0
1259
+ or (self._decoder and self._decoder.has_unconsumed_tail)
1260
+ ):
1261
+ data = self.read(amt=amt, decode_content=decode_content)
1262
+
1263
+ if data:
1264
+ yield data
1265
+
1266
+ # Overrides from io.IOBase
1267
+ def readable(self) -> bool:
1268
+ return True
1269
+
1270
+ def shutdown(self) -> None:
1271
+ if not self._sock_shutdown:
1272
+ raise ValueError("Cannot shutdown socket as self._sock_shutdown is not set")
1273
+ if self._connection is None:
1274
+ raise RuntimeError(
1275
+ "Cannot shutdown as connection has already been released to the pool"
1276
+ )
1277
+ self._sock_shutdown(socket.SHUT_RD)
1278
+
1279
+ def close(self) -> None:
1280
+ self._sock_shutdown = None
1281
+
1282
+ if not self.closed and self._fp:
1283
+ self._fp.close()
1284
+
1285
+ if self._connection:
1286
+ self._connection.close()
1287
+
1288
+ if not self.auto_close:
1289
+ io.IOBase.close(self)
1290
+
1291
+ @property
1292
+ def closed(self) -> bool:
1293
+ if not self.auto_close:
1294
+ return io.IOBase.closed.__get__(self) # type: ignore[no-any-return]
1295
+ elif self._fp is None:
1296
+ return True
1297
+ elif hasattr(self._fp, "isclosed"):
1298
+ return self._fp.isclosed()
1299
+ elif hasattr(self._fp, "closed"):
1300
+ return self._fp.closed
1301
+ else:
1302
+ return True
1303
+
1304
+ def fileno(self) -> int:
1305
+ if self._fp is None:
1306
+ raise OSError("HTTPResponse has no file to get a fileno from")
1307
+ elif hasattr(self._fp, "fileno"):
1308
+ return self._fp.fileno()
1309
+ else:
1310
+ raise OSError(
1311
+ "The file-like object this HTTPResponse is wrapped "
1312
+ "around has no file descriptor"
1313
+ )
1314
+
1315
+ def flush(self) -> None:
1316
+ if (
1317
+ self._fp is not None
1318
+ and hasattr(self._fp, "flush")
1319
+ and not getattr(self._fp, "closed", False)
1320
+ ):
1321
+ return self._fp.flush()
1322
+
1323
+ def supports_chunked_reads(self) -> bool:
1324
+ """
1325
+ Checks if the underlying file-like object looks like a
1326
+ :class:`http.client.HTTPResponse` object. We do this by testing for
1327
+ the fp attribute. If it is present we assume it returns raw chunks as
1328
+ processed by read_chunked().
1329
+ """
1330
+ return hasattr(self._fp, "fp")
1331
+
1332
+ def _update_chunk_length(self) -> None:
1333
+ # First, we'll figure out length of a chunk and then
1334
+ # we'll try to read it from socket.
1335
+ if self.chunk_left is not None:
1336
+ return None
1337
+ line = self._fp.fp.readline() # type: ignore[union-attr]
1338
+ line = line.split(b";", 1)[0]
1339
+ try:
1340
+ self.chunk_left = int(line, 16)
1341
+ except ValueError:
1342
+ self.close()
1343
+ if line:
1344
+ # Invalid chunked protocol response, abort.
1345
+ raise InvalidChunkLength(self, line) from None
1346
+ else:
1347
+ # Truncated at start of next chunk
1348
+ raise ProtocolError("Response ended prematurely") from None
1349
+
1350
+ def _handle_chunk(self, amt: int | None) -> bytes:
1351
+ returned_chunk = None
1352
+ if amt is None:
1353
+ chunk = self._fp._safe_read(self.chunk_left) # type: ignore[union-attr]
1354
+ returned_chunk = chunk
1355
+ self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk.
1356
+ self.chunk_left = None
1357
+ elif self.chunk_left is not None and amt < self.chunk_left:
1358
+ value = self._fp._safe_read(amt) # type: ignore[union-attr]
1359
+ self.chunk_left = self.chunk_left - amt
1360
+ returned_chunk = value
1361
+ elif amt == self.chunk_left:
1362
+ value = self._fp._safe_read(amt) # type: ignore[union-attr]
1363
+ self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk.
1364
+ self.chunk_left = None
1365
+ returned_chunk = value
1366
+ else: # amt > self.chunk_left
1367
+ returned_chunk = self._fp._safe_read(self.chunk_left) # type: ignore[union-attr]
1368
+ self._fp._safe_read(2) # type: ignore[union-attr] # Toss the CRLF at the end of the chunk.
1369
+ self.chunk_left = None
1370
+ return returned_chunk # type: ignore[no-any-return]
1371
+
1372
+ def read_chunked(
1373
+ self, amt: int | None = None, decode_content: bool | None = None
1374
+ ) -> typing.Generator[bytes]:
1375
+ """
1376
+ Similar to :meth:`HTTPResponse.read`, but with an additional
1377
+ parameter: ``decode_content``.
1378
+
1379
+ :param amt:
1380
+ How much of the content to read. If specified, caching is skipped
1381
+ because it doesn't make sense to cache partial content as the full
1382
+ response.
1383
+
1384
+ :param decode_content:
1385
+ If True, will attempt to decode the body based on the
1386
+ 'content-encoding' header.
1387
+ """
1388
+ self._init_decoder()
1389
+ # FIXME: Rewrite this method and make it a class with a better structured logic.
1390
+ if not self.chunked:
1391
+ raise ResponseNotChunked(
1392
+ "Response is not chunked. "
1393
+ "Header 'transfer-encoding: chunked' is missing."
1394
+ )
1395
+ if not self.supports_chunked_reads():
1396
+ raise BodyNotHttplibCompatible(
1397
+ "Body should be http.client.HTTPResponse like. "
1398
+ "It should have have an fp attribute which returns raw chunks."
1399
+ )
1400
+
1401
+ with self._error_catcher():
1402
+ # Don't bother reading the body of a HEAD request.
1403
+ if self._original_response and is_response_to_head(self._original_response):
1404
+ self._original_response.close()
1405
+ return None
1406
+
1407
+ # If a response is already read and closed
1408
+ # then return immediately.
1409
+ if self._fp.fp is None: # type: ignore[union-attr]
1410
+ return None
1411
+
1412
+ if amt == 0:
1413
+ return
1414
+ elif amt and amt < 0:
1415
+ # Negative numbers and `None` should be treated the same,
1416
+ # but httplib handles only `None` correctly.
1417
+ amt = None
1418
+
1419
+ while True:
1420
+ # First, check if any data is left in the decoder's buffer.
1421
+ if self._decoder and self._decoder.has_unconsumed_tail:
1422
+ chunk = b""
1423
+ else:
1424
+ self._update_chunk_length()
1425
+ self._uncached_read_occurred = True
1426
+ if self.chunk_left == 0:
1427
+ break
1428
+ chunk = self._handle_chunk(amt)
1429
+ decoded = self._decode(
1430
+ chunk,
1431
+ decode_content=decode_content,
1432
+ flush_decoder=False,
1433
+ max_length=amt,
1434
+ )
1435
+ if decoded:
1436
+ yield decoded
1437
+
1438
+ if decode_content:
1439
+ # On CPython and PyPy, we should never need to flush the
1440
+ # decoder. However, on Jython we *might* need to, so
1441
+ # lets defensively do it anyway.
1442
+ decoded = self._flush_decoder()
1443
+ if decoded: # Platform-specific: Jython.
1444
+ yield decoded
1445
+
1446
+ # Chunk content ends with \r\n: discard it.
1447
+ while self._fp is not None:
1448
+ line = self._fp.fp.readline()
1449
+ if not line:
1450
+ # Some sites may not end with '\r\n'.
1451
+ break
1452
+ if line == b"\r\n":
1453
+ break
1454
+
1455
+ # We read everything; close the "file".
1456
+ if self._original_response:
1457
+ self._original_response.close()
1458
+
1459
+ @property
1460
+ def url(self) -> str | None:
1461
+ """
1462
+ Returns the URL that was the source of this response.
1463
+ If the request that generated this response redirected, this method
1464
+ will return the final redirect location.
1465
+ """
1466
+ return self._request_url
1467
+
1468
+ @url.setter
1469
+ def url(self, url: str | None) -> None:
1470
+ self._request_url = url
1471
+
1472
+ def __iter__(self) -> typing.Iterator[bytes]:
1473
+ buffer: list[bytes] = []
1474
+ for chunk in self.stream(decode_content=True):
1475
+ if b"\n" in chunk:
1476
+ chunks = chunk.split(b"\n")
1477
+ yield b"".join(buffer) + chunks[0] + b"\n"
1478
+ for x in chunks[1:-1]:
1479
+ yield x + b"\n"
1480
+ if chunks[-1]:
1481
+ buffer = [chunks[-1]]
1482
+ else:
1483
+ buffer = []
1484
+ else:
1485
+ buffer.append(chunk)
1486
+ if buffer:
1487
+ yield b"".join(buffer)
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/__init__.py ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # For backwards compatibility, provide imports that used to be here.
2
+ from __future__ import annotations
3
+
4
+ from .connection import is_connection_dropped
5
+ from .request import SKIP_HEADER, SKIPPABLE_HEADERS, make_headers
6
+ from .response import is_fp_closed
7
+ from .retry import Retry
8
+ from .ssl_ import (
9
+ ALPN_PROTOCOLS,
10
+ IS_PYOPENSSL,
11
+ SSLContext,
12
+ assert_fingerprint,
13
+ create_urllib3_context,
14
+ resolve_cert_reqs,
15
+ resolve_ssl_version,
16
+ ssl_wrap_socket,
17
+ )
18
+ from .timeout import Timeout
19
+ from .url import Url, parse_url
20
+ from .wait import wait_for_read, wait_for_write
21
+
22
+ __all__ = (
23
+ "IS_PYOPENSSL",
24
+ "SSLContext",
25
+ "ALPN_PROTOCOLS",
26
+ "Retry",
27
+ "Timeout",
28
+ "Url",
29
+ "assert_fingerprint",
30
+ "create_urllib3_context",
31
+ "is_connection_dropped",
32
+ "is_fp_closed",
33
+ "parse_url",
34
+ "make_headers",
35
+ "resolve_cert_reqs",
36
+ "resolve_ssl_version",
37
+ "ssl_wrap_socket",
38
+ "wait_for_read",
39
+ "wait_for_write",
40
+ "SKIP_HEADER",
41
+ "SKIPPABLE_HEADERS",
42
+ )
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/connection.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import socket
4
+ import typing
5
+
6
+ from ..exceptions import LocationParseError
7
+ from .timeout import _DEFAULT_TIMEOUT, _TYPE_TIMEOUT
8
+
9
+ _TYPE_SOCKET_OPTIONS = list[tuple[int, int, typing.Union[int, bytes]]]
10
+
11
+ if typing.TYPE_CHECKING:
12
+ from .._base_connection import BaseHTTPConnection
13
+
14
+
15
+ def is_connection_dropped(conn: BaseHTTPConnection) -> bool: # Platform-specific
16
+ """
17
+ Returns True if the connection is dropped and should be closed.
18
+ :param conn: :class:`urllib3.connection.HTTPConnection` object.
19
+ """
20
+ return not conn.is_connected
21
+
22
+
23
+ # This function is copied from socket.py in the Python 2.7 standard
24
+ # library test suite. Added to its signature is only `socket_options`.
25
+ # One additional modification is that we avoid binding to IPv6 servers
26
+ # discovered in DNS if the system doesn't have IPv6 functionality.
27
+ def create_connection(
28
+ address: tuple[str, int],
29
+ timeout: _TYPE_TIMEOUT = _DEFAULT_TIMEOUT,
30
+ source_address: tuple[str, int] | None = None,
31
+ socket_options: _TYPE_SOCKET_OPTIONS | None = None,
32
+ ) -> socket.socket:
33
+ """Connect to *address* and return the socket object.
34
+
35
+ Convenience function. Connect to *address* (a 2-tuple ``(host,
36
+ port)``) and return the socket object. Passing the optional
37
+ *timeout* parameter will set the timeout on the socket instance
38
+ before attempting to connect. If no *timeout* is supplied, the
39
+ global default timeout setting returned by :func:`socket.getdefaulttimeout`
40
+ is used. If *source_address* is set it must be a tuple of (host, port)
41
+ for the socket to bind as a source address before making the connection.
42
+ An host of '' or port 0 tells the OS to use the default.
43
+ """
44
+
45
+ host, port = address
46
+ if host.startswith("["):
47
+ host = host.strip("[]")
48
+ err = None
49
+
50
+ # Using the value from allowed_gai_family() in the context of getaddrinfo lets
51
+ # us select whether to work with IPv4 DNS records, IPv6 records, or both.
52
+ # The original create_connection function always returns all records.
53
+ family = allowed_gai_family()
54
+
55
+ try:
56
+ host.encode("idna")
57
+ except UnicodeError:
58
+ raise LocationParseError(f"'{host}', label empty or too long") from None
59
+
60
+ for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
61
+ af, socktype, proto, canonname, sa = res
62
+ sock = None
63
+ try:
64
+ sock = socket.socket(af, socktype, proto)
65
+
66
+ # If provided, set socket level options before connecting.
67
+ _set_socket_options(sock, socket_options)
68
+
69
+ if timeout is not _DEFAULT_TIMEOUT:
70
+ sock.settimeout(timeout)
71
+ if source_address:
72
+ sock.bind(source_address)
73
+ sock.connect(sa)
74
+ # Break explicitly a reference cycle
75
+ err = None
76
+ return sock
77
+
78
+ except OSError as _:
79
+ err = _
80
+ if sock is not None:
81
+ sock.close()
82
+
83
+ if err is not None:
84
+ try:
85
+ raise err
86
+ finally:
87
+ # Break explicitly a reference cycle
88
+ err = None
89
+ else:
90
+ raise OSError("getaddrinfo returns an empty list")
91
+
92
+
93
+ def _set_socket_options(
94
+ sock: socket.socket, options: _TYPE_SOCKET_OPTIONS | None
95
+ ) -> None:
96
+ if options is None:
97
+ return
98
+
99
+ for opt in options:
100
+ sock.setsockopt(*opt)
101
+
102
+
103
+ def allowed_gai_family() -> socket.AddressFamily:
104
+ """This function is designed to work in the context of
105
+ getaddrinfo, where family=socket.AF_UNSPEC is the default and
106
+ will perform a DNS search for both IPv6 and IPv4 records."""
107
+
108
+ family = socket.AF_INET
109
+ if HAS_IPV6:
110
+ family = socket.AF_UNSPEC
111
+ return family
112
+
113
+
114
+ def _has_ipv6(host: str) -> bool:
115
+ """Returns True if the system can bind an IPv6 address."""
116
+ sock = None
117
+ has_ipv6 = False
118
+
119
+ if socket.has_ipv6:
120
+ # has_ipv6 returns true if cPython was compiled with IPv6 support.
121
+ # It does not tell us if the system has IPv6 support enabled. To
122
+ # determine that we must bind to an IPv6 address.
123
+ # https://github.com/urllib3/urllib3/pull/611
124
+ # https://bugs.python.org/issue658327
125
+ try:
126
+ sock = socket.socket(socket.AF_INET6)
127
+ sock.bind((host, 0))
128
+ has_ipv6 = True
129
+ except Exception:
130
+ pass
131
+
132
+ if sock:
133
+ sock.close()
134
+ return has_ipv6
135
+
136
+
137
+ HAS_IPV6 = _has_ipv6("::1")
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/proxy.py ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import typing
4
+
5
+ from .url import Url
6
+
7
+ if typing.TYPE_CHECKING:
8
+ from ..connection import ProxyConfig
9
+
10
+
11
+ def connection_requires_http_tunnel(
12
+ proxy_url: Url | None = None,
13
+ proxy_config: ProxyConfig | None = None,
14
+ destination_scheme: str | None = None,
15
+ ) -> bool:
16
+ """
17
+ Returns True if the connection requires an HTTP CONNECT through the proxy.
18
+
19
+ :param URL proxy_url:
20
+ URL of the proxy.
21
+ :param ProxyConfig proxy_config:
22
+ Proxy configuration from poolmanager.py
23
+ :param str destination_scheme:
24
+ The scheme of the destination. (i.e https, http, etc)
25
+ """
26
+ # If we're not using a proxy, no way to use a tunnel.
27
+ if proxy_url is None:
28
+ return False
29
+
30
+ # HTTP destinations never require tunneling, we always forward.
31
+ if destination_scheme == "http":
32
+ return False
33
+
34
+ # Support for forwarding with HTTPS proxies and HTTPS destinations.
35
+ if (
36
+ proxy_url.scheme == "https"
37
+ and proxy_config
38
+ and proxy_config.use_forwarding_for_https
39
+ ):
40
+ return False
41
+
42
+ # Otherwise always use a tunnel.
43
+ return True
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/request.py ADDED
@@ -0,0 +1,254 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import io
4
+ import sys
5
+ import typing
6
+ from base64 import b64encode
7
+ from enum import Enum
8
+
9
+ from ..exceptions import UnrewindableBodyError
10
+ from .util import to_bytes
11
+
12
+ if typing.TYPE_CHECKING:
13
+ from typing import Final
14
+
15
+ # Pass as a value within ``headers`` to skip
16
+ # emitting some HTTP headers that are added automatically.
17
+ # The only headers that are supported are ``Accept-Encoding``,
18
+ # ``Host``, and ``User-Agent``.
19
+ SKIP_HEADER = "@@@SKIP_HEADER@@@"
20
+ SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"])
21
+
22
+ ACCEPT_ENCODING = "gzip,deflate"
23
+
24
+ try:
25
+ if sys.version_info >= (3, 14):
26
+ from compression import zstd as _unused_module_zstd # noqa: F401
27
+ else:
28
+ from backports import zstd as _unused_module_zstd # noqa: F401
29
+ except ImportError:
30
+ pass
31
+ else:
32
+ ACCEPT_ENCODING += ",zstd"
33
+
34
+
35
+ class _TYPE_FAILEDTELL(Enum):
36
+ token = 0
37
+
38
+
39
+ _FAILEDTELL: Final[_TYPE_FAILEDTELL] = _TYPE_FAILEDTELL.token
40
+
41
+ _TYPE_BODY_POSITION = typing.Union[int, _TYPE_FAILEDTELL]
42
+
43
+ # When sending a request with these methods we aren't expecting
44
+ # a body so don't need to set an explicit 'Content-Length: 0'
45
+ # The reason we do this in the negative instead of tracking methods
46
+ # which 'should' have a body is because unknown methods should be
47
+ # treated as if they were 'POST' which *does* expect a body.
48
+ _METHODS_NOT_EXPECTING_BODY = {"GET", "HEAD", "DELETE", "TRACE", "OPTIONS", "CONNECT"}
49
+
50
+
51
+ def make_headers(
52
+ keep_alive: bool | None = None,
53
+ accept_encoding: bool | list[str] | str | None = None,
54
+ user_agent: str | None = None,
55
+ basic_auth: str | None = None,
56
+ proxy_basic_auth: str | None = None,
57
+ disable_cache: bool | None = None,
58
+ ) -> dict[str, str]:
59
+ """
60
+ Shortcuts for generating request headers.
61
+
62
+ :param keep_alive:
63
+ If ``True``, adds 'connection: keep-alive' header.
64
+
65
+ :param accept_encoding:
66
+ Can be a boolean, list, or string.
67
+ ``True`` translates to 'gzip,deflate'. If the dependencies for
68
+ Brotli (either the ``brotli`` or ``brotlicffi`` package) and/or
69
+ Zstandard (the ``backports.zstd`` package for Python before 3.14)
70
+ algorithms are installed, then their encodings are
71
+ included in the string ('br' and 'zstd', respectively).
72
+ List will get joined by comma.
73
+ String will be used as provided.
74
+
75
+ :param user_agent:
76
+ String representing the user-agent you want, such as
77
+ "python-urllib3/0.6"
78
+
79
+ :param basic_auth:
80
+ Colon-separated username:password string for 'authorization: basic ...'
81
+ auth header.
82
+
83
+ :param proxy_basic_auth:
84
+ Colon-separated username:password string for 'proxy-authorization: basic ...'
85
+ auth header.
86
+
87
+ :param disable_cache:
88
+ If ``True``, adds 'cache-control: no-cache' header.
89
+
90
+ Example:
91
+
92
+ .. code-block:: python
93
+
94
+ from pip._vendor import urllib3
95
+
96
+ print(urllib3.util.make_headers(keep_alive=True, user_agent="Batman/1.0"))
97
+ # {'connection': 'keep-alive', 'user-agent': 'Batman/1.0'}
98
+ print(urllib3.util.make_headers(accept_encoding=True))
99
+ # {'accept-encoding': 'gzip,deflate'}
100
+ """
101
+ headers: dict[str, str] = {}
102
+ if accept_encoding:
103
+ if isinstance(accept_encoding, str):
104
+ pass
105
+ elif isinstance(accept_encoding, list):
106
+ accept_encoding = ",".join(accept_encoding)
107
+ else:
108
+ accept_encoding = ACCEPT_ENCODING
109
+ headers["accept-encoding"] = accept_encoding
110
+
111
+ if user_agent:
112
+ headers["user-agent"] = user_agent
113
+
114
+ if keep_alive:
115
+ headers["connection"] = "keep-alive"
116
+
117
+ if basic_auth:
118
+ headers["authorization"] = (
119
+ f"Basic {b64encode(basic_auth.encode('latin-1')).decode()}"
120
+ )
121
+
122
+ if proxy_basic_auth:
123
+ headers["proxy-authorization"] = (
124
+ f"Basic {b64encode(proxy_basic_auth.encode('latin-1')).decode()}"
125
+ )
126
+
127
+ if disable_cache:
128
+ headers["cache-control"] = "no-cache"
129
+
130
+ return headers
131
+
132
+
133
+ def set_file_position(
134
+ body: typing.Any, pos: _TYPE_BODY_POSITION | None
135
+ ) -> _TYPE_BODY_POSITION | None:
136
+ """
137
+ If a position is provided, move file to that point.
138
+ Otherwise, we'll attempt to record a position for future use.
139
+ """
140
+ if pos is not None:
141
+ rewind_body(body, pos)
142
+ elif getattr(body, "tell", None) is not None:
143
+ try:
144
+ pos = body.tell()
145
+ except OSError:
146
+ # This differentiates from None, allowing us to catch
147
+ # a failed `tell()` later when trying to rewind the body.
148
+ pos = _FAILEDTELL
149
+
150
+ return pos
151
+
152
+
153
+ def rewind_body(body: typing.IO[typing.AnyStr], body_pos: _TYPE_BODY_POSITION) -> None:
154
+ """
155
+ Attempt to rewind body to a certain position.
156
+ Primarily used for request redirects and retries.
157
+
158
+ :param body:
159
+ File-like object that supports seek.
160
+
161
+ :param int pos:
162
+ Position to seek to in file.
163
+ """
164
+ body_seek = getattr(body, "seek", None)
165
+ if body_seek is not None and isinstance(body_pos, int):
166
+ try:
167
+ body_seek(body_pos)
168
+ except OSError as e:
169
+ raise UnrewindableBodyError(
170
+ "An error occurred when rewinding request body for redirect/retry."
171
+ ) from e
172
+ elif body_pos is _FAILEDTELL:
173
+ raise UnrewindableBodyError(
174
+ "Unable to record file position for rewinding "
175
+ "request body during a redirect/retry."
176
+ )
177
+ else:
178
+ raise ValueError(
179
+ f"body_pos must be of type integer, instead it was {type(body_pos)}."
180
+ )
181
+
182
+
183
+ class ChunksAndContentLength(typing.NamedTuple):
184
+ chunks: typing.Iterable[bytes] | None
185
+ content_length: int | None
186
+
187
+
188
+ def body_to_chunks(
189
+ body: typing.Any | None, method: str, blocksize: int
190
+ ) -> ChunksAndContentLength:
191
+ """Takes the HTTP request method, body, and blocksize and
192
+ transforms them into an iterable of chunks to pass to
193
+ socket.sendall() and an optional 'Content-Length' header.
194
+
195
+ A 'Content-Length' of 'None' indicates the length of the body
196
+ can't be determined so should use 'Transfer-Encoding: chunked'
197
+ for framing instead.
198
+ """
199
+
200
+ chunks: typing.Iterable[bytes] | None
201
+ content_length: int | None
202
+
203
+ # No body, we need to make a recommendation on 'Content-Length'
204
+ # based on whether that request method is expected to have
205
+ # a body or not.
206
+ if body is None:
207
+ chunks = None
208
+ if method.upper() not in _METHODS_NOT_EXPECTING_BODY:
209
+ content_length = 0
210
+ else:
211
+ content_length = None
212
+
213
+ # Bytes or strings become bytes
214
+ elif isinstance(body, (str, bytes)):
215
+ chunks = (to_bytes(body),)
216
+ content_length = len(chunks[0])
217
+
218
+ # File-like object, TODO: use seek() and tell() for length?
219
+ elif hasattr(body, "read"):
220
+
221
+ def chunk_readable() -> typing.Iterable[bytes]:
222
+ encode = isinstance(body, io.TextIOBase)
223
+ while True:
224
+ datablock = body.read(blocksize)
225
+ if not datablock:
226
+ break
227
+ if encode:
228
+ datablock = datablock.encode("utf-8")
229
+ yield datablock
230
+
231
+ chunks = chunk_readable()
232
+ content_length = None
233
+
234
+ # Otherwise we need to start checking via duck-typing.
235
+ else:
236
+ try:
237
+ # Check if the body implements the buffer API.
238
+ mv = memoryview(body)
239
+ except TypeError:
240
+ try:
241
+ # Check if the body is an iterable
242
+ chunks = iter(body)
243
+ content_length = None
244
+ except TypeError:
245
+ raise TypeError(
246
+ f"'body' must be a bytes-like object, file-like "
247
+ f"object, or iterable. Instead was {body!r}"
248
+ ) from None
249
+ else:
250
+ # Since it implements the buffer API can be passed directly to socket.sendall()
251
+ chunks = (body,)
252
+ content_length = mv.nbytes
253
+
254
+ return ChunksAndContentLength(chunks=chunks, content_length=content_length)
.venv/lib/python3.14/site-packages/pip/_vendor/urllib3/util/response.py ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import http.client as httplib
4
+ from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect
5
+
6
+ from ..exceptions import HeaderParsingError
7
+
8
+
9
+ def is_fp_closed(obj: object) -> bool:
10
+ """
11
+ Checks whether a given file-like object is closed.
12
+
13
+ :param obj:
14
+ The file-like object to check.
15
+ """
16
+
17
+ try:
18
+ # Check `isclosed()` first, in case Python3 doesn't set `closed`.
19
+ # GH Issue #928
20
+ return obj.isclosed() # type: ignore[no-any-return, attr-defined]
21
+ except AttributeError:
22
+ pass
23
+
24
+ try:
25
+ # Check via the official file-like-object way.
26
+ return obj.closed # type: ignore[no-any-return, attr-defined]
27
+ except AttributeError:
28
+ pass
29
+
30
+ try:
31
+ # Check if the object is a container for another file-like object that
32
+ # gets released on exhaustion (e.g. HTTPResponse).
33
+ return obj.fp is None # type: ignore[attr-defined]
34
+ except AttributeError:
35
+ pass
36
+
37
+ raise ValueError("Unable to determine whether fp is closed.")
38
+
39
+
40
+ def assert_header_parsing(headers: httplib.HTTPMessage) -> None:
41
+ """
42
+ Asserts whether all headers have been successfully parsed.
43
+ Extracts encountered errors from the result of parsing headers.
44
+
45
+ Only works on Python 3.
46
+
47
+ :param http.client.HTTPMessage headers: Headers to verify.
48
+
49
+ :raises urllib3.exceptions.HeaderParsingError:
50
+ If parsing errors are found.
51
+ """
52
+
53
+ # This will fail silently if we pass in the wrong kind of parameter.
54
+ # To make debugging easier add an explicit check.
55
+ if not isinstance(headers, httplib.HTTPMessage):
56
+ raise TypeError(f"expected httplib.Message, got {type(headers)}.")
57
+
58
+ unparsed_data = None
59
+
60
+ # get_payload is actually email.message.Message.get_payload;
61
+ # we're only interested in the result if it's not a multipart message
62
+ if not headers.is_multipart():
63
+ payload = headers.get_payload()
64
+
65
+ if isinstance(payload, (bytes, str)):
66
+ unparsed_data = payload
67
+
68
+ # httplib is assuming a response body is available
69
+ # when parsing headers even when httplib only sends
70
+ # header data to parse_headers() This results in
71
+ # defects on multipart responses in particular.
72
+ # See: https://github.com/urllib3/urllib3/issues/800
73
+
74
+ # So we ignore the following defects:
75
+ # - StartBoundaryNotFoundDefect:
76
+ # The claimed start boundary was never found.
77
+ # - MultipartInvariantViolationDefect:
78
+ # A message claimed to be a multipart but no subparts were found.
79
+ defects = [
80
+ defect
81
+ for defect in headers.defects
82
+ if not isinstance(
83
+ defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect)
84
+ )
85
+ ]
86
+
87
+ if defects or unparsed_data:
88
+ raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
89
+
90
+
91
+ def is_response_to_head(response: httplib.HTTPResponse) -> bool:
92
+ """
93
+ Checks whether the request of a response has been a HEAD-request.
94
+
95
+ :param http.client.HTTPResponse response:
96
+ Response to check if the originating request
97
+ used 'HEAD' as a method.
98
+ """
99
+ # FIXME: Can we do this somehow without accessing private httplib _method?
100
+ method_str = response._method # type: str # type: ignore[attr-defined]
101
+ return method_str.upper() == "HEAD"