Initial public upload from Projekte/Sidecar-Workspace (part 6)
Browse filesThis view is limited to 50 files because it contains too many changes. See raw diff
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt +760 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER +1 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/LICENSE.txt +20 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA +88 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD +1005 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED +0 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL +5 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt +4 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt +1 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py +323 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py +274 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py +98 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py +0 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py +0 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py +51 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py +155 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py +1076 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py +556 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py +191 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py +879 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py +49 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py +149 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py +57 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py +22 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py +137 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py +107 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py +622 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py +495 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py +159 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py +221 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py +271 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py +435 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py +152 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/vendor.txt +24 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py +342 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py +231 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py +59 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py +153 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py +325 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/py.typed +4 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/INSTALLER +1 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/METADATA +152 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/RECORD +23 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/WHEEL +5 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE +21 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/top_level.txt +1 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/__init__.py +30 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_callers.py +169 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_hooks.py +714 -0
- Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_manager.py +523 -0
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt
ADDED
|
@@ -0,0 +1,760 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
@Switch01
|
| 2 |
+
A_Rog
|
| 3 |
+
Aakanksha Agrawal
|
| 4 |
+
Abhinav Sagar
|
| 5 |
+
ABHYUDAY PRATAP SINGH
|
| 6 |
+
abs51295
|
| 7 |
+
AceGentile
|
| 8 |
+
Adam Chainz
|
| 9 |
+
Adam Tse
|
| 10 |
+
Adam Wentz
|
| 11 |
+
admin
|
| 12 |
+
Adrien Morison
|
| 13 |
+
ahayrapetyan
|
| 14 |
+
Ahilya
|
| 15 |
+
AinsworthK
|
| 16 |
+
Akash Srivastava
|
| 17 |
+
Alan Yee
|
| 18 |
+
Albert Tugushev
|
| 19 |
+
Albert-Guan
|
| 20 |
+
albertg
|
| 21 |
+
Alberto Sottile
|
| 22 |
+
Aleks Bunin
|
| 23 |
+
Ales Erjavec
|
| 24 |
+
Alethea Flowers
|
| 25 |
+
Alex Gaynor
|
| 26 |
+
Alex Grönholm
|
| 27 |
+
Alex Hedges
|
| 28 |
+
Alex Loosley
|
| 29 |
+
Alex Morega
|
| 30 |
+
Alex Stachowiak
|
| 31 |
+
Alexander Shtyrov
|
| 32 |
+
Alexandre Conrad
|
| 33 |
+
Alexey Popravka
|
| 34 |
+
Aleš Erjavec
|
| 35 |
+
Alli
|
| 36 |
+
Ami Fischman
|
| 37 |
+
Ananya Maiti
|
| 38 |
+
Anatoly Techtonik
|
| 39 |
+
Anders Kaseorg
|
| 40 |
+
Andre Aguiar
|
| 41 |
+
Andreas Lutro
|
| 42 |
+
Andrei Geacar
|
| 43 |
+
Andrew Gaul
|
| 44 |
+
Andrew Shymanel
|
| 45 |
+
Andrey Bienkowski
|
| 46 |
+
Andrey Bulgakov
|
| 47 |
+
Andrés Delfino
|
| 48 |
+
Andy Freeland
|
| 49 |
+
Andy Kluger
|
| 50 |
+
Ani Hayrapetyan
|
| 51 |
+
Aniruddha Basak
|
| 52 |
+
Anish Tambe
|
| 53 |
+
Anrs Hu
|
| 54 |
+
Anthony Sottile
|
| 55 |
+
Antoine Musso
|
| 56 |
+
Anton Ovchinnikov
|
| 57 |
+
Anton Patrushev
|
| 58 |
+
Antonio Alvarado Hernandez
|
| 59 |
+
Antony Lee
|
| 60 |
+
Antti Kaihola
|
| 61 |
+
Anubhav Patel
|
| 62 |
+
Anudit Nagar
|
| 63 |
+
Anuj Godase
|
| 64 |
+
AQNOUCH Mohammed
|
| 65 |
+
AraHaan
|
| 66 |
+
Arindam Choudhury
|
| 67 |
+
Armin Ronacher
|
| 68 |
+
Artem
|
| 69 |
+
Arun Babu Neelicattu
|
| 70 |
+
Ashley Manton
|
| 71 |
+
Ashwin Ramaswami
|
| 72 |
+
atse
|
| 73 |
+
Atsushi Odagiri
|
| 74 |
+
Avinash Karhana
|
| 75 |
+
Avner Cohen
|
| 76 |
+
Awit (Ah-Wit) Ghirmai
|
| 77 |
+
Baptiste Mispelon
|
| 78 |
+
Barney Gale
|
| 79 |
+
barneygale
|
| 80 |
+
Bartek Ogryczak
|
| 81 |
+
Bastian Venthur
|
| 82 |
+
Ben Bodenmiller
|
| 83 |
+
Ben Darnell
|
| 84 |
+
Ben Hoyt
|
| 85 |
+
Ben Mares
|
| 86 |
+
Ben Rosser
|
| 87 |
+
Bence Nagy
|
| 88 |
+
Benjamin Peterson
|
| 89 |
+
Benjamin VanEvery
|
| 90 |
+
Benoit Pierre
|
| 91 |
+
Berker Peksag
|
| 92 |
+
Bernard
|
| 93 |
+
Bernard Tyers
|
| 94 |
+
Bernardo B. Marques
|
| 95 |
+
Bernhard M. Wiedemann
|
| 96 |
+
Bertil Hatt
|
| 97 |
+
Bhavam Vidyarthi
|
| 98 |
+
Blazej Michalik
|
| 99 |
+
Bogdan Opanchuk
|
| 100 |
+
BorisZZZ
|
| 101 |
+
Brad Erickson
|
| 102 |
+
Bradley Ayers
|
| 103 |
+
Brandon L. Reiss
|
| 104 |
+
Brandt Bucher
|
| 105 |
+
Brett Randall
|
| 106 |
+
Brett Rosen
|
| 107 |
+
Brian Cristante
|
| 108 |
+
Brian Rosner
|
| 109 |
+
briantracy
|
| 110 |
+
BrownTruck
|
| 111 |
+
Bruno Oliveira
|
| 112 |
+
Bruno Renié
|
| 113 |
+
Bruno S
|
| 114 |
+
Bstrdsmkr
|
| 115 |
+
Buck Golemon
|
| 116 |
+
burrows
|
| 117 |
+
Bussonnier Matthias
|
| 118 |
+
bwoodsend
|
| 119 |
+
c22
|
| 120 |
+
Caleb Martinez
|
| 121 |
+
Calvin Smith
|
| 122 |
+
Carl Meyer
|
| 123 |
+
Carlos Liam
|
| 124 |
+
Carol Willing
|
| 125 |
+
Carter Thayer
|
| 126 |
+
Cass
|
| 127 |
+
Chandrasekhar Atina
|
| 128 |
+
Chih-Hsuan Yen
|
| 129 |
+
Chris Brinker
|
| 130 |
+
Chris Hunt
|
| 131 |
+
Chris Jerdonek
|
| 132 |
+
Chris Kuehl
|
| 133 |
+
Chris McDonough
|
| 134 |
+
Chris Pawley
|
| 135 |
+
Chris Pryer
|
| 136 |
+
Chris Wolfe
|
| 137 |
+
Christian Clauss
|
| 138 |
+
Christian Heimes
|
| 139 |
+
Christian Oudard
|
| 140 |
+
Christoph Reiter
|
| 141 |
+
Christopher Hunt
|
| 142 |
+
Christopher Snyder
|
| 143 |
+
cjc7373
|
| 144 |
+
Clark Boylan
|
| 145 |
+
Claudio Jolowicz
|
| 146 |
+
Clay McClure
|
| 147 |
+
Cody
|
| 148 |
+
Cody Soyland
|
| 149 |
+
Colin Watson
|
| 150 |
+
Collin Anderson
|
| 151 |
+
Connor Osborn
|
| 152 |
+
Cooper Lees
|
| 153 |
+
Cooper Ry Lees
|
| 154 |
+
Cory Benfield
|
| 155 |
+
Cory Wright
|
| 156 |
+
Craig Kerstiens
|
| 157 |
+
Cristian Sorinel
|
| 158 |
+
Cristina
|
| 159 |
+
Cristina Muñoz
|
| 160 |
+
Curtis Doty
|
| 161 |
+
cytolentino
|
| 162 |
+
Daan De Meyer
|
| 163 |
+
Dale
|
| 164 |
+
Damian
|
| 165 |
+
Damian Quiroga
|
| 166 |
+
Damian Shaw
|
| 167 |
+
Dan Black
|
| 168 |
+
Dan Savilonis
|
| 169 |
+
Dan Sully
|
| 170 |
+
Dane Hillard
|
| 171 |
+
daniel
|
| 172 |
+
Daniel Collins
|
| 173 |
+
Daniel Hahler
|
| 174 |
+
Daniel Holth
|
| 175 |
+
Daniel Jost
|
| 176 |
+
Daniel Katz
|
| 177 |
+
Daniel Shaulov
|
| 178 |
+
Daniele Esposti
|
| 179 |
+
Daniele Nicolodi
|
| 180 |
+
Daniele Procida
|
| 181 |
+
Daniil Konovalenko
|
| 182 |
+
Danny Hermes
|
| 183 |
+
Danny McClanahan
|
| 184 |
+
Darren Kavanagh
|
| 185 |
+
Dav Clark
|
| 186 |
+
Dave Abrahams
|
| 187 |
+
Dave Jones
|
| 188 |
+
David Aguilar
|
| 189 |
+
David Black
|
| 190 |
+
David Bordeynik
|
| 191 |
+
David Caro
|
| 192 |
+
David D Lowe
|
| 193 |
+
David Evans
|
| 194 |
+
David Hewitt
|
| 195 |
+
David Linke
|
| 196 |
+
David Poggi
|
| 197 |
+
David Pursehouse
|
| 198 |
+
David Runge
|
| 199 |
+
David Tucker
|
| 200 |
+
David Wales
|
| 201 |
+
Davidovich
|
| 202 |
+
ddelange
|
| 203 |
+
Deepak Sharma
|
| 204 |
+
Deepyaman Datta
|
| 205 |
+
Denise Yu
|
| 206 |
+
dependabot[bot]
|
| 207 |
+
derwolfe
|
| 208 |
+
Desetude
|
| 209 |
+
Devesh Kumar Singh
|
| 210 |
+
Diego Caraballo
|
| 211 |
+
Diego Ramirez
|
| 212 |
+
DiegoCaraballo
|
| 213 |
+
Dimitri Merejkowsky
|
| 214 |
+
Dimitri Papadopoulos
|
| 215 |
+
Dirk Stolle
|
| 216 |
+
Dmitry Gladkov
|
| 217 |
+
Dmitry Volodin
|
| 218 |
+
Domen Kožar
|
| 219 |
+
Dominic Davis-Foster
|
| 220 |
+
Donald Stufft
|
| 221 |
+
Dongweiming
|
| 222 |
+
doron zarhi
|
| 223 |
+
Dos Moonen
|
| 224 |
+
Douglas Thor
|
| 225 |
+
DrFeathers
|
| 226 |
+
Dustin Ingram
|
| 227 |
+
Dwayne Bailey
|
| 228 |
+
Ed Morley
|
| 229 |
+
Edgar Ramírez
|
| 230 |
+
Edgar Ramírez Mondragón
|
| 231 |
+
Ee Durbin
|
| 232 |
+
Efflam Lemaillet
|
| 233 |
+
efflamlemaillet
|
| 234 |
+
Eitan Adler
|
| 235 |
+
ekristina
|
| 236 |
+
elainechan
|
| 237 |
+
Eli Schwartz
|
| 238 |
+
Elisha Hollander
|
| 239 |
+
Ellen Marie Dash
|
| 240 |
+
Emil Burzo
|
| 241 |
+
Emil Styrke
|
| 242 |
+
Emmanuel Arias
|
| 243 |
+
Endoh Takanao
|
| 244 |
+
enoch
|
| 245 |
+
Erdinc Mutlu
|
| 246 |
+
Eric Cousineau
|
| 247 |
+
Eric Gillingham
|
| 248 |
+
Eric Hanchrow
|
| 249 |
+
Eric Hopper
|
| 250 |
+
Erik M. Bray
|
| 251 |
+
Erik Rose
|
| 252 |
+
Erwin Janssen
|
| 253 |
+
Eugene Vereshchagin
|
| 254 |
+
everdimension
|
| 255 |
+
Federico
|
| 256 |
+
Felipe Peter
|
| 257 |
+
Felix Yan
|
| 258 |
+
fiber-space
|
| 259 |
+
Filip Kokosiński
|
| 260 |
+
Filipe Laíns
|
| 261 |
+
Finn Womack
|
| 262 |
+
finnagin
|
| 263 |
+
Flavio Amurrio
|
| 264 |
+
Florian Briand
|
| 265 |
+
Florian Rathgeber
|
| 266 |
+
Francesco
|
| 267 |
+
Francesco Montesano
|
| 268 |
+
Frost Ming
|
| 269 |
+
Gabriel Curio
|
| 270 |
+
Gabriel de Perthuis
|
| 271 |
+
Garry Polley
|
| 272 |
+
gavin
|
| 273 |
+
gdanielson
|
| 274 |
+
Geoffrey Sneddon
|
| 275 |
+
George Song
|
| 276 |
+
Georgi Valkov
|
| 277 |
+
Georgy Pchelkin
|
| 278 |
+
ghost
|
| 279 |
+
Giftlin Rajaiah
|
| 280 |
+
gizmoguy1
|
| 281 |
+
gkdoc
|
| 282 |
+
Godefroid Chapelle
|
| 283 |
+
Gopinath M
|
| 284 |
+
GOTO Hayato
|
| 285 |
+
gousaiyang
|
| 286 |
+
gpiks
|
| 287 |
+
Greg Roodt
|
| 288 |
+
Greg Ward
|
| 289 |
+
Guilherme Espada
|
| 290 |
+
Guillaume Seguin
|
| 291 |
+
gutsytechster
|
| 292 |
+
Guy Rozendorn
|
| 293 |
+
Guy Tuval
|
| 294 |
+
gzpan123
|
| 295 |
+
Hanjun Kim
|
| 296 |
+
Hari Charan
|
| 297 |
+
Harsh Vardhan
|
| 298 |
+
harupy
|
| 299 |
+
Harutaka Kawamura
|
| 300 |
+
hauntsaninja
|
| 301 |
+
Henrich Hartzer
|
| 302 |
+
Henry Schreiner
|
| 303 |
+
Herbert Pfennig
|
| 304 |
+
Holly Stotelmyer
|
| 305 |
+
Honnix
|
| 306 |
+
Hsiaoming Yang
|
| 307 |
+
Hugo Lopes Tavares
|
| 308 |
+
Hugo van Kemenade
|
| 309 |
+
Hugues Bruant
|
| 310 |
+
Hynek Schlawack
|
| 311 |
+
Ian Bicking
|
| 312 |
+
Ian Cordasco
|
| 313 |
+
Ian Lee
|
| 314 |
+
Ian Stapleton Cordasco
|
| 315 |
+
Ian Wienand
|
| 316 |
+
Igor Kuzmitshov
|
| 317 |
+
Igor Sobreira
|
| 318 |
+
Ilan Schnell
|
| 319 |
+
Illia Volochii
|
| 320 |
+
Ilya Baryshev
|
| 321 |
+
Inada Naoki
|
| 322 |
+
Ionel Cristian Mărieș
|
| 323 |
+
Ionel Maries Cristian
|
| 324 |
+
Itamar Turner-Trauring
|
| 325 |
+
Ivan Pozdeev
|
| 326 |
+
J. Nick Koston
|
| 327 |
+
Jacob Kim
|
| 328 |
+
Jacob Walls
|
| 329 |
+
Jaime Sanz
|
| 330 |
+
jakirkham
|
| 331 |
+
Jakub Kuczys
|
| 332 |
+
Jakub Stasiak
|
| 333 |
+
Jakub Vysoky
|
| 334 |
+
Jakub Wilk
|
| 335 |
+
James Cleveland
|
| 336 |
+
James Curtin
|
| 337 |
+
James Firth
|
| 338 |
+
James Gerity
|
| 339 |
+
James Polley
|
| 340 |
+
Jan Pokorný
|
| 341 |
+
Jannis Leidel
|
| 342 |
+
Jarek Potiuk
|
| 343 |
+
jarondl
|
| 344 |
+
Jason Curtis
|
| 345 |
+
Jason R. Coombs
|
| 346 |
+
JasonMo
|
| 347 |
+
JasonMo1
|
| 348 |
+
Jay Graves
|
| 349 |
+
Jean Abou Samra
|
| 350 |
+
Jean-Christophe Fillion-Robin
|
| 351 |
+
Jeff Barber
|
| 352 |
+
Jeff Dairiki
|
| 353 |
+
Jeff Widman
|
| 354 |
+
Jelmer Vernooij
|
| 355 |
+
jenix21
|
| 356 |
+
Jeremy Stanley
|
| 357 |
+
Jeremy Zafran
|
| 358 |
+
Jesse Rittner
|
| 359 |
+
Jiashuo Li
|
| 360 |
+
Jim Fisher
|
| 361 |
+
Jim Garrison
|
| 362 |
+
Jiun Bae
|
| 363 |
+
Jivan Amara
|
| 364 |
+
Joe Bylund
|
| 365 |
+
Joe Michelini
|
| 366 |
+
John Paton
|
| 367 |
+
John T. Wodder II
|
| 368 |
+
John-Scott Atlakson
|
| 369 |
+
johnthagen
|
| 370 |
+
Jon Banafato
|
| 371 |
+
Jon Dufresne
|
| 372 |
+
Jon Parise
|
| 373 |
+
Jonas Nockert
|
| 374 |
+
Jonathan Herbert
|
| 375 |
+
Joonatan Partanen
|
| 376 |
+
Joost Molenaar
|
| 377 |
+
Jorge Niedbalski
|
| 378 |
+
Joseph Bylund
|
| 379 |
+
Joseph Long
|
| 380 |
+
Josh Bronson
|
| 381 |
+
Josh Hansen
|
| 382 |
+
Josh Schneier
|
| 383 |
+
Joshua
|
| 384 |
+
Juan Luis Cano Rodríguez
|
| 385 |
+
Juanjo Bazán
|
| 386 |
+
Judah Rand
|
| 387 |
+
Julian Berman
|
| 388 |
+
Julian Gethmann
|
| 389 |
+
Julien Demoor
|
| 390 |
+
Jussi Kukkonen
|
| 391 |
+
jwg4
|
| 392 |
+
Jyrki Pulliainen
|
| 393 |
+
Kai Chen
|
| 394 |
+
Kai Mueller
|
| 395 |
+
Kamal Bin Mustafa
|
| 396 |
+
kasium
|
| 397 |
+
kaustav haldar
|
| 398 |
+
keanemind
|
| 399 |
+
Keith Maxwell
|
| 400 |
+
Kelsey Hightower
|
| 401 |
+
Kenneth Belitzky
|
| 402 |
+
Kenneth Reitz
|
| 403 |
+
Kevin Burke
|
| 404 |
+
Kevin Carter
|
| 405 |
+
Kevin Frommelt
|
| 406 |
+
Kevin R Patterson
|
| 407 |
+
Kexuan Sun
|
| 408 |
+
Kit Randel
|
| 409 |
+
Klaas van Schelven
|
| 410 |
+
KOLANICH
|
| 411 |
+
kpinc
|
| 412 |
+
Krishna Oza
|
| 413 |
+
Kumar McMillan
|
| 414 |
+
Kurt McKee
|
| 415 |
+
Kyle Persohn
|
| 416 |
+
lakshmanaram
|
| 417 |
+
Laszlo Kiss-Kollar
|
| 418 |
+
Laurent Bristiel
|
| 419 |
+
Laurent LAPORTE
|
| 420 |
+
Laurie O
|
| 421 |
+
Laurie Opperman
|
| 422 |
+
layday
|
| 423 |
+
Leon Sasson
|
| 424 |
+
Lev Givon
|
| 425 |
+
Lincoln de Sousa
|
| 426 |
+
Lipis
|
| 427 |
+
lorddavidiii
|
| 428 |
+
Loren Carvalho
|
| 429 |
+
Lucas Cimon
|
| 430 |
+
Ludovic Gasc
|
| 431 |
+
Lukas Geiger
|
| 432 |
+
Lukas Juhrich
|
| 433 |
+
Luke Macken
|
| 434 |
+
Luo Jiebin
|
| 435 |
+
luojiebin
|
| 436 |
+
luz.paz
|
| 437 |
+
László Kiss Kollár
|
| 438 |
+
M00nL1ght
|
| 439 |
+
Marc Abramowitz
|
| 440 |
+
Marc Tamlyn
|
| 441 |
+
Marcus Smith
|
| 442 |
+
Mariatta
|
| 443 |
+
Mark Kohler
|
| 444 |
+
Mark Williams
|
| 445 |
+
Markus Hametner
|
| 446 |
+
Martey Dodoo
|
| 447 |
+
Martin Fischer
|
| 448 |
+
Martin Häcker
|
| 449 |
+
Martin Pavlasek
|
| 450 |
+
Masaki
|
| 451 |
+
Masklinn
|
| 452 |
+
Matej Stuchlik
|
| 453 |
+
Mathew Jennings
|
| 454 |
+
Mathieu Bridon
|
| 455 |
+
Mathieu Kniewallner
|
| 456 |
+
Matt Bacchi
|
| 457 |
+
Matt Good
|
| 458 |
+
Matt Maker
|
| 459 |
+
Matt Robenolt
|
| 460 |
+
matthew
|
| 461 |
+
Matthew Einhorn
|
| 462 |
+
Matthew Feickert
|
| 463 |
+
Matthew Gilliard
|
| 464 |
+
Matthew Iversen
|
| 465 |
+
Matthew Treinish
|
| 466 |
+
Matthew Trumbell
|
| 467 |
+
Matthew Willson
|
| 468 |
+
Matthias Bussonnier
|
| 469 |
+
mattip
|
| 470 |
+
Maurits van Rees
|
| 471 |
+
Max W Chase
|
| 472 |
+
Maxim Kurnikov
|
| 473 |
+
Maxime Rouyrre
|
| 474 |
+
mayeut
|
| 475 |
+
mbaluna
|
| 476 |
+
mdebi
|
| 477 |
+
memoselyk
|
| 478 |
+
meowmeowcat
|
| 479 |
+
Michael
|
| 480 |
+
Michael Aquilina
|
| 481 |
+
Michael E. Karpeles
|
| 482 |
+
Michael Klich
|
| 483 |
+
Michael Mintz
|
| 484 |
+
Michael Williamson
|
| 485 |
+
michaelpacer
|
| 486 |
+
Michał Górny
|
| 487 |
+
Mickaël Schoentgen
|
| 488 |
+
Miguel Araujo Perez
|
| 489 |
+
Mihir Singh
|
| 490 |
+
Mike
|
| 491 |
+
Mike Hendricks
|
| 492 |
+
Min RK
|
| 493 |
+
MinRK
|
| 494 |
+
Miro Hrončok
|
| 495 |
+
Monica Baluna
|
| 496 |
+
montefra
|
| 497 |
+
Monty Taylor
|
| 498 |
+
Muha Ajjan
|
| 499 |
+
Nadav Wexler
|
| 500 |
+
Nahuel Ambrosini
|
| 501 |
+
Nate Coraor
|
| 502 |
+
Nate Prewitt
|
| 503 |
+
Nathan Houghton
|
| 504 |
+
Nathaniel J. Smith
|
| 505 |
+
Nehal J Wani
|
| 506 |
+
Neil Botelho
|
| 507 |
+
Nguyễn Gia Phong
|
| 508 |
+
Nicholas Serra
|
| 509 |
+
Nick Coghlan
|
| 510 |
+
Nick Stenning
|
| 511 |
+
Nick Timkovich
|
| 512 |
+
Nicolas Bock
|
| 513 |
+
Nicole Harris
|
| 514 |
+
Nikhil Benesch
|
| 515 |
+
Nikhil Ladha
|
| 516 |
+
Nikita Chepanov
|
| 517 |
+
Nikolay Korolev
|
| 518 |
+
Nipunn Koorapati
|
| 519 |
+
Nitesh Sharma
|
| 520 |
+
Niyas Sait
|
| 521 |
+
Noah
|
| 522 |
+
Noah Gorny
|
| 523 |
+
Nowell Strite
|
| 524 |
+
NtaleGrey
|
| 525 |
+
nvdv
|
| 526 |
+
OBITORASU
|
| 527 |
+
Ofek Lev
|
| 528 |
+
ofrinevo
|
| 529 |
+
Oliver Freund
|
| 530 |
+
Oliver Jeeves
|
| 531 |
+
Oliver Mannion
|
| 532 |
+
Oliver Tonnhofer
|
| 533 |
+
Olivier Girardot
|
| 534 |
+
Olivier Grisel
|
| 535 |
+
Ollie Rutherfurd
|
| 536 |
+
OMOTO Kenji
|
| 537 |
+
Omry Yadan
|
| 538 |
+
onlinejudge95
|
| 539 |
+
Oren Held
|
| 540 |
+
Oscar Benjamin
|
| 541 |
+
Oz N Tiram
|
| 542 |
+
Pachwenko
|
| 543 |
+
Patrick Dubroy
|
| 544 |
+
Patrick Jenkins
|
| 545 |
+
Patrick Lawson
|
| 546 |
+
patricktokeeffe
|
| 547 |
+
Patrik Kopkan
|
| 548 |
+
Paul Ganssle
|
| 549 |
+
Paul Kehrer
|
| 550 |
+
Paul Moore
|
| 551 |
+
Paul Nasrat
|
| 552 |
+
Paul Oswald
|
| 553 |
+
Paul van der Linden
|
| 554 |
+
Paulus Schoutsen
|
| 555 |
+
Pavel Safronov
|
| 556 |
+
Pavithra Eswaramoorthy
|
| 557 |
+
Pawel Jasinski
|
| 558 |
+
Paweł Szramowski
|
| 559 |
+
Pekka Klärck
|
| 560 |
+
Peter Gessler
|
| 561 |
+
Peter Lisák
|
| 562 |
+
Peter Waller
|
| 563 |
+
petr-tik
|
| 564 |
+
Phaneendra Chiruvella
|
| 565 |
+
Phil Elson
|
| 566 |
+
Phil Freo
|
| 567 |
+
Phil Pennock
|
| 568 |
+
Phil Whelan
|
| 569 |
+
Philip Jägenstedt
|
| 570 |
+
Philip Molloy
|
| 571 |
+
Philippe Ombredanne
|
| 572 |
+
Pi Delport
|
| 573 |
+
Pierre-Yves Rofes
|
| 574 |
+
Pieter Degroote
|
| 575 |
+
pip
|
| 576 |
+
Prabakaran Kumaresshan
|
| 577 |
+
Prabhjyotsing Surjit Singh Sodhi
|
| 578 |
+
Prabhu Marappan
|
| 579 |
+
Pradyun Gedam
|
| 580 |
+
Prashant Sharma
|
| 581 |
+
Pratik Mallya
|
| 582 |
+
pre-commit-ci[bot]
|
| 583 |
+
Preet Thakkar
|
| 584 |
+
Preston Holmes
|
| 585 |
+
Przemek Wrzos
|
| 586 |
+
Pulkit Goyal
|
| 587 |
+
q0w
|
| 588 |
+
Qiangning Hong
|
| 589 |
+
Qiming Xu
|
| 590 |
+
Quentin Lee
|
| 591 |
+
Quentin Pradet
|
| 592 |
+
R. David Murray
|
| 593 |
+
Rafael Caricio
|
| 594 |
+
Ralf Schmitt
|
| 595 |
+
Razzi Abuissa
|
| 596 |
+
rdb
|
| 597 |
+
Reece Dunham
|
| 598 |
+
Remi Rampin
|
| 599 |
+
Rene Dudfield
|
| 600 |
+
Riccardo Magliocchetti
|
| 601 |
+
Riccardo Schirone
|
| 602 |
+
Richard Jones
|
| 603 |
+
Richard Si
|
| 604 |
+
Ricky Ng-Adam
|
| 605 |
+
Rishi
|
| 606 |
+
RobberPhex
|
| 607 |
+
Robert Collins
|
| 608 |
+
Robert McGibbon
|
| 609 |
+
Robert Pollak
|
| 610 |
+
Robert T. McGibbon
|
| 611 |
+
robin elisha robinson
|
| 612 |
+
Roey Berman
|
| 613 |
+
Rohan Jain
|
| 614 |
+
Roman Bogorodskiy
|
| 615 |
+
Roman Donchenko
|
| 616 |
+
Romuald Brunet
|
| 617 |
+
ronaudinho
|
| 618 |
+
Ronny Pfannschmidt
|
| 619 |
+
Rory McCann
|
| 620 |
+
Ross Brattain
|
| 621 |
+
Roy Wellington Ⅳ
|
| 622 |
+
Ruairidh MacLeod
|
| 623 |
+
Russell Keith-Magee
|
| 624 |
+
Ryan Shepherd
|
| 625 |
+
Ryan Wooden
|
| 626 |
+
ryneeverett
|
| 627 |
+
Sachi King
|
| 628 |
+
Salvatore Rinchiera
|
| 629 |
+
sandeepkiran-js
|
| 630 |
+
Sander Van Balen
|
| 631 |
+
Savio Jomton
|
| 632 |
+
schlamar
|
| 633 |
+
Scott Kitterman
|
| 634 |
+
Sean
|
| 635 |
+
seanj
|
| 636 |
+
Sebastian Jordan
|
| 637 |
+
Sebastian Schaetz
|
| 638 |
+
Segev Finer
|
| 639 |
+
SeongSoo Cho
|
| 640 |
+
Sergey Vasilyev
|
| 641 |
+
Seth Michael Larson
|
| 642 |
+
Seth Woodworth
|
| 643 |
+
Shahar Epstein
|
| 644 |
+
Shantanu
|
| 645 |
+
shireenrao
|
| 646 |
+
Shivansh-007
|
| 647 |
+
Shlomi Fish
|
| 648 |
+
Shovan Maity
|
| 649 |
+
Simeon Visser
|
| 650 |
+
Simon Cross
|
| 651 |
+
Simon Pichugin
|
| 652 |
+
sinoroc
|
| 653 |
+
sinscary
|
| 654 |
+
snook92
|
| 655 |
+
socketubs
|
| 656 |
+
Sorin Sbarnea
|
| 657 |
+
Srinivas Nyayapati
|
| 658 |
+
Stavros Korokithakis
|
| 659 |
+
Stefan Scherfke
|
| 660 |
+
Stefano Rivera
|
| 661 |
+
Stephan Erb
|
| 662 |
+
Stephen Rosen
|
| 663 |
+
stepshal
|
| 664 |
+
Steve (Gadget) Barnes
|
| 665 |
+
Steve Barnes
|
| 666 |
+
Steve Dower
|
| 667 |
+
Steve Kowalik
|
| 668 |
+
Steven Myint
|
| 669 |
+
Steven Silvester
|
| 670 |
+
stonebig
|
| 671 |
+
studioj
|
| 672 |
+
Stéphane Bidoul
|
| 673 |
+
Stéphane Bidoul (ACSONE)
|
| 674 |
+
Stéphane Klein
|
| 675 |
+
Sumana Harihareswara
|
| 676 |
+
Surbhi Sharma
|
| 677 |
+
Sviatoslav Sydorenko
|
| 678 |
+
Swat009
|
| 679 |
+
Sylvain
|
| 680 |
+
Takayuki SHIMIZUKAWA
|
| 681 |
+
Taneli Hukkinen
|
| 682 |
+
tbeswick
|
| 683 |
+
Thiago
|
| 684 |
+
Thijs Triemstra
|
| 685 |
+
Thomas Fenzl
|
| 686 |
+
Thomas Grainger
|
| 687 |
+
Thomas Guettler
|
| 688 |
+
Thomas Johansson
|
| 689 |
+
Thomas Kluyver
|
| 690 |
+
Thomas Smith
|
| 691 |
+
Thomas VINCENT
|
| 692 |
+
Tim D. Smith
|
| 693 |
+
Tim Gates
|
| 694 |
+
Tim Harder
|
| 695 |
+
Tim Heap
|
| 696 |
+
tim smith
|
| 697 |
+
tinruufu
|
| 698 |
+
Tobias Hermann
|
| 699 |
+
Tom Forbes
|
| 700 |
+
Tom Freudenheim
|
| 701 |
+
Tom V
|
| 702 |
+
Tomas Hrnciar
|
| 703 |
+
Tomas Orsava
|
| 704 |
+
Tomer Chachamu
|
| 705 |
+
Tommi Enenkel | AnB
|
| 706 |
+
Tomáš Hrnčiar
|
| 707 |
+
Tony Beswick
|
| 708 |
+
Tony Narlock
|
| 709 |
+
Tony Zhaocheng Tan
|
| 710 |
+
TonyBeswick
|
| 711 |
+
toonarmycaptain
|
| 712 |
+
Toshio Kuratomi
|
| 713 |
+
toxinu
|
| 714 |
+
Travis Swicegood
|
| 715 |
+
Tushar Sadhwani
|
| 716 |
+
Tzu-ping Chung
|
| 717 |
+
Valentin Haenel
|
| 718 |
+
Victor Stinner
|
| 719 |
+
victorvpaulo
|
| 720 |
+
Vikram - Google
|
| 721 |
+
Viktor Szépe
|
| 722 |
+
Ville Skyttä
|
| 723 |
+
Vinay Sajip
|
| 724 |
+
Vincent Philippon
|
| 725 |
+
Vinicyus Macedo
|
| 726 |
+
Vipul Kumar
|
| 727 |
+
Vitaly Babiy
|
| 728 |
+
Vladimir Fokow
|
| 729 |
+
Vladimir Rutsky
|
| 730 |
+
W. Trevor King
|
| 731 |
+
Wil Tan
|
| 732 |
+
Wilfred Hughes
|
| 733 |
+
William Edwards
|
| 734 |
+
William ML Leslie
|
| 735 |
+
William T Olson
|
| 736 |
+
William Woodruff
|
| 737 |
+
Wilson Mo
|
| 738 |
+
wim glenn
|
| 739 |
+
Winson Luk
|
| 740 |
+
Wolfgang Maier
|
| 741 |
+
Wu Zhenyu
|
| 742 |
+
XAMES3
|
| 743 |
+
Xavier Fernandez
|
| 744 |
+
xoviat
|
| 745 |
+
xtreak
|
| 746 |
+
YAMAMOTO Takashi
|
| 747 |
+
Yen Chi Hsuan
|
| 748 |
+
Yeray Diaz Diaz
|
| 749 |
+
Yoval P
|
| 750 |
+
Yu Jian
|
| 751 |
+
Yuan Jing Vincent Yan
|
| 752 |
+
Yusuke Hayashi
|
| 753 |
+
Zearin
|
| 754 |
+
Zhiping Deng
|
| 755 |
+
ziebam
|
| 756 |
+
Zvezdan Petkovic
|
| 757 |
+
Łukasz Langa
|
| 758 |
+
Роман Донченко
|
| 759 |
+
Семён Марьясин
|
| 760 |
+
rekcäH nitraM
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/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.
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.1
|
| 2 |
+
Name: pip
|
| 3 |
+
Version: 24.0
|
| 4 |
+
Summary: The PyPA recommended tool for installing Python packages.
|
| 5 |
+
Author-email: The pip developers <distutils-sig@python.org>
|
| 6 |
+
License: MIT
|
| 7 |
+
Project-URL: Homepage, https://pip.pypa.io/
|
| 8 |
+
Project-URL: Documentation, https://pip.pypa.io
|
| 9 |
+
Project-URL: Source, https://github.com/pypa/pip
|
| 10 |
+
Project-URL: Changelog, https://pip.pypa.io/en/stable/news/
|
| 11 |
+
Classifier: Development Status :: 5 - Production/Stable
|
| 12 |
+
Classifier: Intended Audience :: Developers
|
| 13 |
+
Classifier: License :: OSI Approved :: MIT License
|
| 14 |
+
Classifier: Topic :: Software Development :: Build Tools
|
| 15 |
+
Classifier: Programming Language :: Python
|
| 16 |
+
Classifier: Programming Language :: Python :: 3
|
| 17 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
| 18 |
+
Classifier: Programming Language :: Python :: 3.7
|
| 19 |
+
Classifier: Programming Language :: Python :: 3.8
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 24 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 25 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 26 |
+
Requires-Python: >=3.7
|
| 27 |
+
Description-Content-Type: text/x-rst
|
| 28 |
+
License-File: LICENSE.txt
|
| 29 |
+
License-File: AUTHORS.txt
|
| 30 |
+
|
| 31 |
+
pip - The Python Package Installer
|
| 32 |
+
==================================
|
| 33 |
+
|
| 34 |
+
.. image:: https://img.shields.io/pypi/v/pip.svg
|
| 35 |
+
:target: https://pypi.org/project/pip/
|
| 36 |
+
:alt: PyPI
|
| 37 |
+
|
| 38 |
+
.. image:: https://img.shields.io/pypi/pyversions/pip
|
| 39 |
+
:target: https://pypi.org/project/pip
|
| 40 |
+
:alt: PyPI - Python Version
|
| 41 |
+
|
| 42 |
+
.. image:: https://readthedocs.org/projects/pip/badge/?version=latest
|
| 43 |
+
:target: https://pip.pypa.io/en/latest
|
| 44 |
+
:alt: Documentation
|
| 45 |
+
|
| 46 |
+
pip is the `package installer`_ for Python. You can use pip to install packages from the `Python Package Index`_ and other indexes.
|
| 47 |
+
|
| 48 |
+
Please take a look at our documentation for how to install and use pip:
|
| 49 |
+
|
| 50 |
+
* `Installation`_
|
| 51 |
+
* `Usage`_
|
| 52 |
+
|
| 53 |
+
We release updates regularly, with a new version every 3 months. Find more details in our documentation:
|
| 54 |
+
|
| 55 |
+
* `Release notes`_
|
| 56 |
+
* `Release process`_
|
| 57 |
+
|
| 58 |
+
If you find bugs, need help, or want to talk to the developers, please use our mailing lists or chat rooms:
|
| 59 |
+
|
| 60 |
+
* `Issue tracking`_
|
| 61 |
+
* `Discourse channel`_
|
| 62 |
+
* `User IRC`_
|
| 63 |
+
|
| 64 |
+
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:
|
| 65 |
+
|
| 66 |
+
* `GitHub page`_
|
| 67 |
+
* `Development documentation`_
|
| 68 |
+
* `Development IRC`_
|
| 69 |
+
|
| 70 |
+
Code of Conduct
|
| 71 |
+
---------------
|
| 72 |
+
|
| 73 |
+
Everyone interacting in the pip project's codebases, issue trackers, chat
|
| 74 |
+
rooms, and mailing lists is expected to follow the `PSF Code of Conduct`_.
|
| 75 |
+
|
| 76 |
+
.. _package installer: https://packaging.python.org/guides/tool-recommendations/
|
| 77 |
+
.. _Python Package Index: https://pypi.org
|
| 78 |
+
.. _Installation: https://pip.pypa.io/en/stable/installation/
|
| 79 |
+
.. _Usage: https://pip.pypa.io/en/stable/
|
| 80 |
+
.. _Release notes: https://pip.pypa.io/en/stable/news.html
|
| 81 |
+
.. _Release process: https://pip.pypa.io/en/latest/development/release-process/
|
| 82 |
+
.. _GitHub page: https://github.com/pypa/pip
|
| 83 |
+
.. _Development documentation: https://pip.pypa.io/en/latest/development
|
| 84 |
+
.. _Issue tracking: https://github.com/pypa/pip/issues
|
| 85 |
+
.. _Discourse channel: https://discuss.python.org/c/packaging
|
| 86 |
+
.. _User IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa
|
| 87 |
+
.. _Development IRC: https://kiwiirc.com/nextclient/#ircs://irc.libera.chat:+6697/pypa-dev
|
| 88 |
+
.. _PSF Code of Conduct: https://github.com/pypa/.github/blob/main/CODE_OF_CONDUCT.md
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,1005 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
../../../bin/pip,sha256=mgfaJsPZOeoIWapwBi1KFA3xpKgK5lsiMMr405n-HHw,281
|
| 2 |
+
../../../bin/pip3,sha256=mgfaJsPZOeoIWapwBi1KFA3xpKgK5lsiMMr405n-HHw,281
|
| 3 |
+
../../../bin/pip3.12,sha256=mgfaJsPZOeoIWapwBi1KFA3xpKgK5lsiMMr405n-HHw,281
|
| 4 |
+
pip-24.0.dist-info/AUTHORS.txt,sha256=SwXm4nkwRkmtnO1ZY-dLy7EPeoQNXMNLby5CN3GlNhY,10388
|
| 5 |
+
pip-24.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 6 |
+
pip-24.0.dist-info/LICENSE.txt,sha256=Y0MApmnUmurmWxLGxIySTFGkzfPR_whtw0VtyLyqIQQ,1093
|
| 7 |
+
pip-24.0.dist-info/METADATA,sha256=kNEfJ3_Vho2mee4lfJdlbd5RHIqsfQJSMUB-bOkIOeI,3581
|
| 8 |
+
pip-24.0.dist-info/RECORD,,
|
| 9 |
+
pip-24.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 10 |
+
pip-24.0.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
|
| 11 |
+
pip-24.0.dist-info/entry_points.txt,sha256=Fa_c0b-xGFaYxagIruvpJD6qqXmNTA02vAVIkmMj-9o,125
|
| 12 |
+
pip-24.0.dist-info/top_level.txt,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 13 |
+
pip/__init__.py,sha256=oAk1nFpLmUVS5Ln7NxvNoGUn5Vkn6FGQjPaNDf8Q8pk,355
|
| 14 |
+
pip/__main__.py,sha256=WzbhHXTbSE6gBY19mNN9m4s5o_365LOvTYSgqgbdBhE,854
|
| 15 |
+
pip/__pip-runner__.py,sha256=EnrfKmKMzWAdqg_JicLCOP9Y95Ux7zHh4ObvqLtQcjo,1444
|
| 16 |
+
pip/__pycache__/__init__.cpython-312.pyc,,
|
| 17 |
+
pip/__pycache__/__main__.cpython-312.pyc,,
|
| 18 |
+
pip/__pycache__/__pip-runner__.cpython-312.pyc,,
|
| 19 |
+
pip/_internal/__init__.py,sha256=iqZ5-YQsQV08tkUc7L806Reop6tguLFWf70ySF6be0Y,515
|
| 20 |
+
pip/_internal/__pycache__/__init__.cpython-312.pyc,,
|
| 21 |
+
pip/_internal/__pycache__/build_env.cpython-312.pyc,,
|
| 22 |
+
pip/_internal/__pycache__/cache.cpython-312.pyc,,
|
| 23 |
+
pip/_internal/__pycache__/configuration.cpython-312.pyc,,
|
| 24 |
+
pip/_internal/__pycache__/exceptions.cpython-312.pyc,,
|
| 25 |
+
pip/_internal/__pycache__/main.cpython-312.pyc,,
|
| 26 |
+
pip/_internal/__pycache__/pyproject.cpython-312.pyc,,
|
| 27 |
+
pip/_internal/__pycache__/self_outdated_check.cpython-312.pyc,,
|
| 28 |
+
pip/_internal/__pycache__/wheel_builder.cpython-312.pyc,,
|
| 29 |
+
pip/_internal/build_env.py,sha256=1ESpqw0iupS_K7phZK5zshVE5Czy9BtGLFU4W6Enva8,10243
|
| 30 |
+
pip/_internal/cache.py,sha256=uiYD-9F0Bv1C8ZyWE85lpzDmQf7hcUkgL99GmI8I41Q,10370
|
| 31 |
+
pip/_internal/cli/__init__.py,sha256=FkHBgpxxb-_gd6r1FjnNhfMOzAUYyXoXKJ6abijfcFU,132
|
| 32 |
+
pip/_internal/cli/__pycache__/__init__.cpython-312.pyc,,
|
| 33 |
+
pip/_internal/cli/__pycache__/autocompletion.cpython-312.pyc,,
|
| 34 |
+
pip/_internal/cli/__pycache__/base_command.cpython-312.pyc,,
|
| 35 |
+
pip/_internal/cli/__pycache__/cmdoptions.cpython-312.pyc,,
|
| 36 |
+
pip/_internal/cli/__pycache__/command_context.cpython-312.pyc,,
|
| 37 |
+
pip/_internal/cli/__pycache__/main.cpython-312.pyc,,
|
| 38 |
+
pip/_internal/cli/__pycache__/main_parser.cpython-312.pyc,,
|
| 39 |
+
pip/_internal/cli/__pycache__/parser.cpython-312.pyc,,
|
| 40 |
+
pip/_internal/cli/__pycache__/progress_bars.cpython-312.pyc,,
|
| 41 |
+
pip/_internal/cli/__pycache__/req_command.cpython-312.pyc,,
|
| 42 |
+
pip/_internal/cli/__pycache__/spinners.cpython-312.pyc,,
|
| 43 |
+
pip/_internal/cli/__pycache__/status_codes.cpython-312.pyc,,
|
| 44 |
+
pip/_internal/cli/autocompletion.py,sha256=_br_5NgSxSuvPjMF0MLHzS5s6BpSkQAQHKrLK89VauM,6690
|
| 45 |
+
pip/_internal/cli/base_command.py,sha256=iuVWGa2oTq7gBReo0er3Z0tXJ2oqBIC6QjDHcnDhKXY,8733
|
| 46 |
+
pip/_internal/cli/cmdoptions.py,sha256=V8ggG6AtHpHKkH_6tRU0mhJaZTeqtrFpu75ghvMXXJk,30063
|
| 47 |
+
pip/_internal/cli/command_context.py,sha256=RHgIPwtObh5KhMrd3YZTkl8zbVG-6Okml7YbFX4Ehg0,774
|
| 48 |
+
pip/_internal/cli/main.py,sha256=Uzxt_YD1hIvB1AW5mxt6IVcht5G712AtMqdo51UMhmQ,2816
|
| 49 |
+
pip/_internal/cli/main_parser.py,sha256=laDpsuBDl6kyfywp9eMMA9s84jfH2TJJn-vmL0GG90w,4338
|
| 50 |
+
pip/_internal/cli/parser.py,sha256=KW6C3-7-4ErTNB0TfLTKwOdHcd-qefCeGnrOoE2r0RQ,10781
|
| 51 |
+
pip/_internal/cli/progress_bars.py,sha256=So4mPoSjXkXiSHiTzzquH3VVyVD_njXlHJSExYPXAow,1968
|
| 52 |
+
pip/_internal/cli/req_command.py,sha256=c7_XHABnXmD3_qlK9-r37KqdKBAcgmVKvQ2WcTrNLfc,18369
|
| 53 |
+
pip/_internal/cli/spinners.py,sha256=hIJ83GerdFgFCdobIA23Jggetegl_uC4Sp586nzFbPE,5118
|
| 54 |
+
pip/_internal/cli/status_codes.py,sha256=sEFHUaUJbqv8iArL3HAtcztWZmGOFX01hTesSytDEh0,116
|
| 55 |
+
pip/_internal/commands/__init__.py,sha256=5oRO9O3dM2vGuh0bFw4HOVletryrz5HHMmmPWwJrH9U,3882
|
| 56 |
+
pip/_internal/commands/__pycache__/__init__.cpython-312.pyc,,
|
| 57 |
+
pip/_internal/commands/__pycache__/cache.cpython-312.pyc,,
|
| 58 |
+
pip/_internal/commands/__pycache__/check.cpython-312.pyc,,
|
| 59 |
+
pip/_internal/commands/__pycache__/completion.cpython-312.pyc,,
|
| 60 |
+
pip/_internal/commands/__pycache__/configuration.cpython-312.pyc,,
|
| 61 |
+
pip/_internal/commands/__pycache__/debug.cpython-312.pyc,,
|
| 62 |
+
pip/_internal/commands/__pycache__/download.cpython-312.pyc,,
|
| 63 |
+
pip/_internal/commands/__pycache__/freeze.cpython-312.pyc,,
|
| 64 |
+
pip/_internal/commands/__pycache__/hash.cpython-312.pyc,,
|
| 65 |
+
pip/_internal/commands/__pycache__/help.cpython-312.pyc,,
|
| 66 |
+
pip/_internal/commands/__pycache__/index.cpython-312.pyc,,
|
| 67 |
+
pip/_internal/commands/__pycache__/inspect.cpython-312.pyc,,
|
| 68 |
+
pip/_internal/commands/__pycache__/install.cpython-312.pyc,,
|
| 69 |
+
pip/_internal/commands/__pycache__/list.cpython-312.pyc,,
|
| 70 |
+
pip/_internal/commands/__pycache__/search.cpython-312.pyc,,
|
| 71 |
+
pip/_internal/commands/__pycache__/show.cpython-312.pyc,,
|
| 72 |
+
pip/_internal/commands/__pycache__/uninstall.cpython-312.pyc,,
|
| 73 |
+
pip/_internal/commands/__pycache__/wheel.cpython-312.pyc,,
|
| 74 |
+
pip/_internal/commands/cache.py,sha256=xg76_ZFEBC6zoQ3gXLRfMZJft4z2a0RwH4GEFZC6nnU,7944
|
| 75 |
+
pip/_internal/commands/check.py,sha256=Rb13Q28yoLh0j1gpx5SU0jlResNct21eQCRsnaO9xKA,1782
|
| 76 |
+
pip/_internal/commands/completion.py,sha256=HT4lD0bgsflHq2IDgYfiEdp7IGGtE7s6MgI3xn0VQEw,4287
|
| 77 |
+
pip/_internal/commands/configuration.py,sha256=n98enwp6y0b5G6fiRQjaZo43FlJKYve_daMhN-4BRNc,9766
|
| 78 |
+
pip/_internal/commands/debug.py,sha256=63972uUCeMIGOdMMVeIUGrOjTOqTVWplFC82a-hcKyA,6777
|
| 79 |
+
pip/_internal/commands/download.py,sha256=e4hw088zGo26WmJaMIRvCniLlLmoOjqolGyfHjsCkCQ,5335
|
| 80 |
+
pip/_internal/commands/freeze.py,sha256=qrIHS_-c6JPrQ92hMhAv9kkl0bHgFpRLwYJDdbcYr1o,3243
|
| 81 |
+
pip/_internal/commands/hash.py,sha256=EVVOuvGtoPEdFi8SNnmdqlCQrhCxV-kJsdwtdcCnXGQ,1703
|
| 82 |
+
pip/_internal/commands/help.py,sha256=gcc6QDkcgHMOuAn5UxaZwAStsRBrnGSn_yxjS57JIoM,1132
|
| 83 |
+
pip/_internal/commands/index.py,sha256=CNXQer_PeZKSJooURcCFCBEKGfwyNoUWYP_MWczAcOM,4775
|
| 84 |
+
pip/_internal/commands/inspect.py,sha256=2wSPt9yfr3r6g-s2S5L6PvRtaHNVyb4TuodMStJ39cw,3188
|
| 85 |
+
pip/_internal/commands/install.py,sha256=VxDd-BD3a27ApeE2OK34rfBXS6Zo2wtemK9-HCwPqxM,28782
|
| 86 |
+
pip/_internal/commands/list.py,sha256=-QbpPuGDiGN1SdThsk2ml8beBnepliefbGhMAN8tkzU,12547
|
| 87 |
+
pip/_internal/commands/search.py,sha256=sbBZiARRc050QquOKcCvOr2K3XLsoYebLKZGRi__iUI,5697
|
| 88 |
+
pip/_internal/commands/show.py,sha256=t5jia4zcYJRJZy4U_Von7zMl03hJmmcofj6oDNTnj7Y,6419
|
| 89 |
+
pip/_internal/commands/uninstall.py,sha256=OIqO9tqadY8kM4HwhFf1Q62fUIp7v8KDrTRo8yWMz7Y,3886
|
| 90 |
+
pip/_internal/commands/wheel.py,sha256=CSnX8Pmf1oPCnd7j7bn1_f58G9KHNiAblvVJ5zykN-A,6476
|
| 91 |
+
pip/_internal/configuration.py,sha256=XkAiBS0hpzsM-LF0Qu5hvPWO_Bs67-oQKRYFBuMbESs,14006
|
| 92 |
+
pip/_internal/distributions/__init__.py,sha256=Hq6kt6gXBgjNit5hTTWLAzeCNOKoB-N0pGYSqehrli8,858
|
| 93 |
+
pip/_internal/distributions/__pycache__/__init__.cpython-312.pyc,,
|
| 94 |
+
pip/_internal/distributions/__pycache__/base.cpython-312.pyc,,
|
| 95 |
+
pip/_internal/distributions/__pycache__/installed.cpython-312.pyc,,
|
| 96 |
+
pip/_internal/distributions/__pycache__/sdist.cpython-312.pyc,,
|
| 97 |
+
pip/_internal/distributions/__pycache__/wheel.cpython-312.pyc,,
|
| 98 |
+
pip/_internal/distributions/base.py,sha256=oRSEvnv2ZjBnargamnv2fcJa1n6gUDKaW0g6CWSEpWs,1743
|
| 99 |
+
pip/_internal/distributions/installed.py,sha256=QinHFbWAQ8oE0pbD8MFZWkwlnfU1QYTccA1vnhrlYOU,842
|
| 100 |
+
pip/_internal/distributions/sdist.py,sha256=4K3V0VNMllHbBzCJibjwd_tylUKpmIdu2AQyhplvCQo,6709
|
| 101 |
+
pip/_internal/distributions/wheel.py,sha256=-ma3sOtUQj0AxXCEb6_Fhmjl3nh4k3A0HC2taAb2N-4,1277
|
| 102 |
+
pip/_internal/exceptions.py,sha256=TmF1iNFEneSWaemwlg6a5bpPuq2cMHK7d1-SvjsQHb0,23634
|
| 103 |
+
pip/_internal/index/__init__.py,sha256=vpt-JeTZefh8a-FC22ZeBSXFVbuBcXSGiILhQZJaNpQ,30
|
| 104 |
+
pip/_internal/index/__pycache__/__init__.cpython-312.pyc,,
|
| 105 |
+
pip/_internal/index/__pycache__/collector.cpython-312.pyc,,
|
| 106 |
+
pip/_internal/index/__pycache__/package_finder.cpython-312.pyc,,
|
| 107 |
+
pip/_internal/index/__pycache__/sources.cpython-312.pyc,,
|
| 108 |
+
pip/_internal/index/collector.py,sha256=sH0tL_cOoCk6pLLfCSGVjFM4rPEJtllF-VobvAvLSH4,16590
|
| 109 |
+
pip/_internal/index/package_finder.py,sha256=S_nC8gzVIMY6ikWfKoSOzRtoesUqnfNhAPl_BwSOusA,37843
|
| 110 |
+
pip/_internal/index/sources.py,sha256=dJegiR9f86kslaAHcv9-R5L_XBf5Rzm_FkyPteDuPxI,8688
|
| 111 |
+
pip/_internal/locations/__init__.py,sha256=Dh8LJWG8LRlDK4JIj9sfRF96TREzE--N_AIlx7Tqoe4,15365
|
| 112 |
+
pip/_internal/locations/__pycache__/__init__.cpython-312.pyc,,
|
| 113 |
+
pip/_internal/locations/__pycache__/_distutils.cpython-312.pyc,,
|
| 114 |
+
pip/_internal/locations/__pycache__/_sysconfig.cpython-312.pyc,,
|
| 115 |
+
pip/_internal/locations/__pycache__/base.cpython-312.pyc,,
|
| 116 |
+
pip/_internal/locations/_distutils.py,sha256=H9ZHK_35rdDV1Qsmi4QeaBULjFT4Mbu6QuoVGkJ6QHI,6009
|
| 117 |
+
pip/_internal/locations/_sysconfig.py,sha256=jyNVtUfMIf0mtyY-Xp1m9yQ8iwECozSVVFmjkN9a2yw,7680
|
| 118 |
+
pip/_internal/locations/base.py,sha256=RQiPi1d4FVM2Bxk04dQhXZ2PqkeljEL2fZZ9SYqIQ78,2556
|
| 119 |
+
pip/_internal/main.py,sha256=r-UnUe8HLo5XFJz8inTcOOTiu_sxNhgHb6VwlGUllOI,340
|
| 120 |
+
pip/_internal/metadata/__init__.py,sha256=9pU3W3s-6HtjFuYhWcLTYVmSaziklPv7k2x8p7X1GmA,4339
|
| 121 |
+
pip/_internal/metadata/__pycache__/__init__.cpython-312.pyc,,
|
| 122 |
+
pip/_internal/metadata/__pycache__/_json.cpython-312.pyc,,
|
| 123 |
+
pip/_internal/metadata/__pycache__/base.cpython-312.pyc,,
|
| 124 |
+
pip/_internal/metadata/__pycache__/pkg_resources.cpython-312.pyc,,
|
| 125 |
+
pip/_internal/metadata/_json.py,sha256=Rz5M5ciSNvITwaTQR6NfN8TgKgM5WfTws4D6CFknovE,2627
|
| 126 |
+
pip/_internal/metadata/base.py,sha256=l3Wgku4xlgr8s4p6fS-3qQ4QKOpPbWLRwi5d9omEFG4,25907
|
| 127 |
+
pip/_internal/metadata/importlib/__init__.py,sha256=jUUidoxnHcfITHHaAWG1G2i5fdBYklv_uJcjo2x7VYE,135
|
| 128 |
+
pip/_internal/metadata/importlib/__pycache__/__init__.cpython-312.pyc,,
|
| 129 |
+
pip/_internal/metadata/importlib/__pycache__/_compat.cpython-312.pyc,,
|
| 130 |
+
pip/_internal/metadata/importlib/__pycache__/_dists.cpython-312.pyc,,
|
| 131 |
+
pip/_internal/metadata/importlib/__pycache__/_envs.cpython-312.pyc,,
|
| 132 |
+
pip/_internal/metadata/importlib/_compat.py,sha256=GAe_prIfCE4iUylrnr_2dJRlkkBVRUbOidEoID7LPoE,1882
|
| 133 |
+
pip/_internal/metadata/importlib/_dists.py,sha256=UPl1wUujFqiwiltRJ1tMF42WRINO1sSpNNlYQ2mX0mk,8297
|
| 134 |
+
pip/_internal/metadata/importlib/_envs.py,sha256=XTaFIYERP2JF0QUZuPx2ETiugXbPEcZ8q8ZKeht6Lpc,7456
|
| 135 |
+
pip/_internal/metadata/pkg_resources.py,sha256=opjw4IBSqHvie6sXJ_cbT42meygoPEUfNURJuWZY7sk,10035
|
| 136 |
+
pip/_internal/models/__init__.py,sha256=3DHUd_qxpPozfzouoqa9g9ts1Czr5qaHfFxbnxriepM,63
|
| 137 |
+
pip/_internal/models/__pycache__/__init__.cpython-312.pyc,,
|
| 138 |
+
pip/_internal/models/__pycache__/candidate.cpython-312.pyc,,
|
| 139 |
+
pip/_internal/models/__pycache__/direct_url.cpython-312.pyc,,
|
| 140 |
+
pip/_internal/models/__pycache__/format_control.cpython-312.pyc,,
|
| 141 |
+
pip/_internal/models/__pycache__/index.cpython-312.pyc,,
|
| 142 |
+
pip/_internal/models/__pycache__/installation_report.cpython-312.pyc,,
|
| 143 |
+
pip/_internal/models/__pycache__/link.cpython-312.pyc,,
|
| 144 |
+
pip/_internal/models/__pycache__/scheme.cpython-312.pyc,,
|
| 145 |
+
pip/_internal/models/__pycache__/search_scope.cpython-312.pyc,,
|
| 146 |
+
pip/_internal/models/__pycache__/selection_prefs.cpython-312.pyc,,
|
| 147 |
+
pip/_internal/models/__pycache__/target_python.cpython-312.pyc,,
|
| 148 |
+
pip/_internal/models/__pycache__/wheel.cpython-312.pyc,,
|
| 149 |
+
pip/_internal/models/candidate.py,sha256=hEPu8VdGE5qVASv6vLz-R-Rgh5-7LMbai1jgthMCd8M,931
|
| 150 |
+
pip/_internal/models/direct_url.py,sha256=FwouYBKcqckh7B-k2H3HVgRhhFTukFwqiS3kfvtFLSk,6889
|
| 151 |
+
pip/_internal/models/format_control.py,sha256=wtsQqSK9HaUiNxQEuB-C62eVimw6G4_VQFxV9-_KDBE,2486
|
| 152 |
+
pip/_internal/models/index.py,sha256=tYnL8oxGi4aSNWur0mG8DAP7rC6yuha_MwJO8xw0crI,1030
|
| 153 |
+
pip/_internal/models/installation_report.py,sha256=zRVZoaz-2vsrezj_H3hLOhMZCK9c7TbzWgC-jOalD00,2818
|
| 154 |
+
pip/_internal/models/link.py,sha256=XirOAGv1jgMu7vu87kuPbohGj7VHpwVrd2q3KUgVQNg,20777
|
| 155 |
+
pip/_internal/models/scheme.py,sha256=3EFQp_ICu_shH1-TBqhl0QAusKCPDFOlgHFeN4XowWs,738
|
| 156 |
+
pip/_internal/models/search_scope.py,sha256=ASVyyZxiJILw7bTIVVpJx8J293M3Hk5F33ilGn0e80c,4643
|
| 157 |
+
pip/_internal/models/selection_prefs.py,sha256=KZdi66gsR-_RUXUr9uejssk3rmTHrQVJWeNA2sV-VSY,1907
|
| 158 |
+
pip/_internal/models/target_python.py,sha256=34EkorrMuRvRp-bjqHKJ-bOO71m9xdjN2b8WWFEC2HU,4272
|
| 159 |
+
pip/_internal/models/wheel.py,sha256=YqazoIZyma_Q1ejFa1C7NHKQRRWlvWkdK96VRKmDBeI,3600
|
| 160 |
+
pip/_internal/network/__init__.py,sha256=jf6Tt5nV_7zkARBrKojIXItgejvoegVJVKUbhAa5Ioc,50
|
| 161 |
+
pip/_internal/network/__pycache__/__init__.cpython-312.pyc,,
|
| 162 |
+
pip/_internal/network/__pycache__/auth.cpython-312.pyc,,
|
| 163 |
+
pip/_internal/network/__pycache__/cache.cpython-312.pyc,,
|
| 164 |
+
pip/_internal/network/__pycache__/download.cpython-312.pyc,,
|
| 165 |
+
pip/_internal/network/__pycache__/lazy_wheel.cpython-312.pyc,,
|
| 166 |
+
pip/_internal/network/__pycache__/session.cpython-312.pyc,,
|
| 167 |
+
pip/_internal/network/__pycache__/utils.cpython-312.pyc,,
|
| 168 |
+
pip/_internal/network/__pycache__/xmlrpc.cpython-312.pyc,,
|
| 169 |
+
pip/_internal/network/auth.py,sha256=TC-OcW2KU4W6R1hU4qPgQXvVH54adACpZz6sWq-R9NA,20541
|
| 170 |
+
pip/_internal/network/cache.py,sha256=48A971qCzKNFvkb57uGEk7-0xaqPS0HWj2711QNTxkU,3935
|
| 171 |
+
pip/_internal/network/download.py,sha256=i0Tn55CD5D7XYEFY3TxiYaCf0OaaTQ6SScNgCsSeV14,6086
|
| 172 |
+
pip/_internal/network/lazy_wheel.py,sha256=2PXVduYZPCPZkkQFe1J1GbfHJWeCU--FXonGyIfw9eU,7638
|
| 173 |
+
pip/_internal/network/session.py,sha256=9tqEDD8JiVaFdplOEXJxNo9cjRfBZ6RIa0yQQ_qBNiM,18698
|
| 174 |
+
pip/_internal/network/utils.py,sha256=6A5SrUJEEUHxbGtbscwU2NpCyz-3ztiDlGWHpRRhsJ8,4073
|
| 175 |
+
pip/_internal/network/xmlrpc.py,sha256=sAxzOacJ-N1NXGPvap9jC3zuYWSnnv3GXtgR2-E2APA,1838
|
| 176 |
+
pip/_internal/operations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 177 |
+
pip/_internal/operations/__pycache__/__init__.cpython-312.pyc,,
|
| 178 |
+
pip/_internal/operations/__pycache__/check.cpython-312.pyc,,
|
| 179 |
+
pip/_internal/operations/__pycache__/freeze.cpython-312.pyc,,
|
| 180 |
+
pip/_internal/operations/__pycache__/prepare.cpython-312.pyc,,
|
| 181 |
+
pip/_internal/operations/build/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 182 |
+
pip/_internal/operations/build/__pycache__/__init__.cpython-312.pyc,,
|
| 183 |
+
pip/_internal/operations/build/__pycache__/build_tracker.cpython-312.pyc,,
|
| 184 |
+
pip/_internal/operations/build/__pycache__/metadata.cpython-312.pyc,,
|
| 185 |
+
pip/_internal/operations/build/__pycache__/metadata_editable.cpython-312.pyc,,
|
| 186 |
+
pip/_internal/operations/build/__pycache__/metadata_legacy.cpython-312.pyc,,
|
| 187 |
+
pip/_internal/operations/build/__pycache__/wheel.cpython-312.pyc,,
|
| 188 |
+
pip/_internal/operations/build/__pycache__/wheel_editable.cpython-312.pyc,,
|
| 189 |
+
pip/_internal/operations/build/__pycache__/wheel_legacy.cpython-312.pyc,,
|
| 190 |
+
pip/_internal/operations/build/build_tracker.py,sha256=z-H5DOknZdBa3dh2Vq6VBMY5qLYIKmlj2p6CGZK5Lc8,4832
|
| 191 |
+
pip/_internal/operations/build/metadata.py,sha256=9S0CUD8U3QqZeXp-Zyt8HxwU90lE4QrnYDgrqZDzBnc,1422
|
| 192 |
+
pip/_internal/operations/build/metadata_editable.py,sha256=VLL7LvntKE8qxdhUdEJhcotFzUsOSI8NNS043xULKew,1474
|
| 193 |
+
pip/_internal/operations/build/metadata_legacy.py,sha256=o-eU21As175hDC7dluM1fJJ_FqokTIShyWpjKaIpHZw,2198
|
| 194 |
+
pip/_internal/operations/build/wheel.py,sha256=sT12FBLAxDC6wyrDorh8kvcZ1jG5qInCRWzzP-UkJiQ,1075
|
| 195 |
+
pip/_internal/operations/build/wheel_editable.py,sha256=yOtoH6zpAkoKYEUtr8FhzrYnkNHQaQBjWQ2HYae1MQg,1417
|
| 196 |
+
pip/_internal/operations/build/wheel_legacy.py,sha256=C9j6rukgQI1n_JeQLoZGuDdfUwzCXShyIdPTp6edbMQ,3064
|
| 197 |
+
pip/_internal/operations/check.py,sha256=fsqA88iGaqftCr2tlP3sSU202CSkoODRtW0O-JU9M4Y,6806
|
| 198 |
+
pip/_internal/operations/freeze.py,sha256=uqoeTAf6HOYVMR2UgAT8N85UZoGEVEoQdan_Ao6SOfk,9816
|
| 199 |
+
pip/_internal/operations/install/__init__.py,sha256=mX7hyD2GNBO2mFGokDQ30r_GXv7Y_PLdtxcUv144e-s,51
|
| 200 |
+
pip/_internal/operations/install/__pycache__/__init__.cpython-312.pyc,,
|
| 201 |
+
pip/_internal/operations/install/__pycache__/editable_legacy.cpython-312.pyc,,
|
| 202 |
+
pip/_internal/operations/install/__pycache__/wheel.cpython-312.pyc,,
|
| 203 |
+
pip/_internal/operations/install/editable_legacy.py,sha256=YeR0KadWXw_ZheC1NtAG1qVIEkOgRGHc23x-YtGW7NU,1282
|
| 204 |
+
pip/_internal/operations/install/wheel.py,sha256=9hGb1c4bRnPIb2FG7CtUSPfPxqprmHQBtwIAlWPNTtE,27311
|
| 205 |
+
pip/_internal/operations/prepare.py,sha256=57Oq87HfunX3Rbqp47FdaJr9cHbAKUm_3gv7WhBAqbE,28128
|
| 206 |
+
pip/_internal/pyproject.py,sha256=4Xszp11xgr126yzG6BbJA0oaQ9WXuhb0jyUb-y_6lPQ,7152
|
| 207 |
+
pip/_internal/req/__init__.py,sha256=TELFgZOof3lhMmaICVWL9U7PlhXo9OufokbMAJ6J2GI,2738
|
| 208 |
+
pip/_internal/req/__pycache__/__init__.cpython-312.pyc,,
|
| 209 |
+
pip/_internal/req/__pycache__/constructors.cpython-312.pyc,,
|
| 210 |
+
pip/_internal/req/__pycache__/req_file.cpython-312.pyc,,
|
| 211 |
+
pip/_internal/req/__pycache__/req_install.cpython-312.pyc,,
|
| 212 |
+
pip/_internal/req/__pycache__/req_set.cpython-312.pyc,,
|
| 213 |
+
pip/_internal/req/__pycache__/req_uninstall.cpython-312.pyc,,
|
| 214 |
+
pip/_internal/req/constructors.py,sha256=8hlY56imEthLORRwmloyKz3YOyXymIaKsNB6P9ewvNI,19018
|
| 215 |
+
pip/_internal/req/req_file.py,sha256=M8ttOZL-PwAj7scPElhW3ZD2hiD9mm_6FJAGIbwAzEI,17790
|
| 216 |
+
pip/_internal/req/req_install.py,sha256=wtOPxkyRSM8comTks8oL1Gp2oyGqbH7JwIDRci2QiPk,35460
|
| 217 |
+
pip/_internal/req/req_set.py,sha256=iMYDUToSgkxFyrP_OrTtPSgw4dwjRyGRDpGooTqeA4Y,4704
|
| 218 |
+
pip/_internal/req/req_uninstall.py,sha256=nmvTQaRCC0iu-5Tw0djlXJhSj6WmqHRvT3qkkEdC35E,24551
|
| 219 |
+
pip/_internal/resolution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 220 |
+
pip/_internal/resolution/__pycache__/__init__.cpython-312.pyc,,
|
| 221 |
+
pip/_internal/resolution/__pycache__/base.cpython-312.pyc,,
|
| 222 |
+
pip/_internal/resolution/base.py,sha256=qlmh325SBVfvG6Me9gc5Nsh5sdwHBwzHBq6aEXtKsLA,583
|
| 223 |
+
pip/_internal/resolution/legacy/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 224 |
+
pip/_internal/resolution/legacy/__pycache__/__init__.cpython-312.pyc,,
|
| 225 |
+
pip/_internal/resolution/legacy/__pycache__/resolver.cpython-312.pyc,,
|
| 226 |
+
pip/_internal/resolution/legacy/resolver.py,sha256=Xk24jQ62GvLr4Mc7IjN_qiO88qp0BImzVmPIFz9QLOE,24025
|
| 227 |
+
pip/_internal/resolution/resolvelib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 228 |
+
pip/_internal/resolution/resolvelib/__pycache__/__init__.cpython-312.pyc,,
|
| 229 |
+
pip/_internal/resolution/resolvelib/__pycache__/base.cpython-312.pyc,,
|
| 230 |
+
pip/_internal/resolution/resolvelib/__pycache__/candidates.cpython-312.pyc,,
|
| 231 |
+
pip/_internal/resolution/resolvelib/__pycache__/factory.cpython-312.pyc,,
|
| 232 |
+
pip/_internal/resolution/resolvelib/__pycache__/found_candidates.cpython-312.pyc,,
|
| 233 |
+
pip/_internal/resolution/resolvelib/__pycache__/provider.cpython-312.pyc,,
|
| 234 |
+
pip/_internal/resolution/resolvelib/__pycache__/reporter.cpython-312.pyc,,
|
| 235 |
+
pip/_internal/resolution/resolvelib/__pycache__/requirements.cpython-312.pyc,,
|
| 236 |
+
pip/_internal/resolution/resolvelib/__pycache__/resolver.cpython-312.pyc,,
|
| 237 |
+
pip/_internal/resolution/resolvelib/base.py,sha256=jg5COmHLhmBIKOR-4spdJD3jyULYa1BdsqiBu2YJnJ4,5173
|
| 238 |
+
pip/_internal/resolution/resolvelib/candidates.py,sha256=19Ki91Po-MSxBknGIfOGkaWkFdOznN0W_nKv7jL28L0,21052
|
| 239 |
+
pip/_internal/resolution/resolvelib/factory.py,sha256=vqqk-hjchdhShwWVdeW2_A-5ZblLhE_nC_v3Mhz4Svc,32292
|
| 240 |
+
pip/_internal/resolution/resolvelib/found_candidates.py,sha256=hvL3Hoa9VaYo-qEOZkBi2Iqw251UDxPz-uMHVaWmLpE,5705
|
| 241 |
+
pip/_internal/resolution/resolvelib/provider.py,sha256=4t23ivjruqM6hKBX1KpGiTt-M4HGhRcZnGLV0c01K7U,9824
|
| 242 |
+
pip/_internal/resolution/resolvelib/reporter.py,sha256=YFm9hQvz4DFCbjZeFTQ56hTz3Ac-mDBnHkeNRVvMHLY,3100
|
| 243 |
+
pip/_internal/resolution/resolvelib/requirements.py,sha256=-kJONP0WjDfdTvBAs2vUXPgAnOyNIBEAXY4b72ogtPE,5696
|
| 244 |
+
pip/_internal/resolution/resolvelib/resolver.py,sha256=nLJOsVMEVi2gQUVJoUFKMZAeu2f7GRMjGMvNSWyz0Bc,12592
|
| 245 |
+
pip/_internal/self_outdated_check.py,sha256=saxQLB8UzIFtMScquytG10TOTsYVFJQ_mkW1NY-46wE,8378
|
| 246 |
+
pip/_internal/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 247 |
+
pip/_internal/utils/__pycache__/__init__.cpython-312.pyc,,
|
| 248 |
+
pip/_internal/utils/__pycache__/_jaraco_text.cpython-312.pyc,,
|
| 249 |
+
pip/_internal/utils/__pycache__/_log.cpython-312.pyc,,
|
| 250 |
+
pip/_internal/utils/__pycache__/appdirs.cpython-312.pyc,,
|
| 251 |
+
pip/_internal/utils/__pycache__/compat.cpython-312.pyc,,
|
| 252 |
+
pip/_internal/utils/__pycache__/compatibility_tags.cpython-312.pyc,,
|
| 253 |
+
pip/_internal/utils/__pycache__/datetime.cpython-312.pyc,,
|
| 254 |
+
pip/_internal/utils/__pycache__/deprecation.cpython-312.pyc,,
|
| 255 |
+
pip/_internal/utils/__pycache__/direct_url_helpers.cpython-312.pyc,,
|
| 256 |
+
pip/_internal/utils/__pycache__/egg_link.cpython-312.pyc,,
|
| 257 |
+
pip/_internal/utils/__pycache__/encoding.cpython-312.pyc,,
|
| 258 |
+
pip/_internal/utils/__pycache__/entrypoints.cpython-312.pyc,,
|
| 259 |
+
pip/_internal/utils/__pycache__/filesystem.cpython-312.pyc,,
|
| 260 |
+
pip/_internal/utils/__pycache__/filetypes.cpython-312.pyc,,
|
| 261 |
+
pip/_internal/utils/__pycache__/glibc.cpython-312.pyc,,
|
| 262 |
+
pip/_internal/utils/__pycache__/hashes.cpython-312.pyc,,
|
| 263 |
+
pip/_internal/utils/__pycache__/logging.cpython-312.pyc,,
|
| 264 |
+
pip/_internal/utils/__pycache__/misc.cpython-312.pyc,,
|
| 265 |
+
pip/_internal/utils/__pycache__/models.cpython-312.pyc,,
|
| 266 |
+
pip/_internal/utils/__pycache__/packaging.cpython-312.pyc,,
|
| 267 |
+
pip/_internal/utils/__pycache__/setuptools_build.cpython-312.pyc,,
|
| 268 |
+
pip/_internal/utils/__pycache__/subprocess.cpython-312.pyc,,
|
| 269 |
+
pip/_internal/utils/__pycache__/temp_dir.cpython-312.pyc,,
|
| 270 |
+
pip/_internal/utils/__pycache__/unpacking.cpython-312.pyc,,
|
| 271 |
+
pip/_internal/utils/__pycache__/urls.cpython-312.pyc,,
|
| 272 |
+
pip/_internal/utils/__pycache__/virtualenv.cpython-312.pyc,,
|
| 273 |
+
pip/_internal/utils/__pycache__/wheel.cpython-312.pyc,,
|
| 274 |
+
pip/_internal/utils/_jaraco_text.py,sha256=yvDGelTVugRayPaOF2k4ab0Ky4d3uOkAfuOQjASjImY,3351
|
| 275 |
+
pip/_internal/utils/_log.py,sha256=-jHLOE_THaZz5BFcCnoSL9EYAtJ0nXem49s9of4jvKw,1015
|
| 276 |
+
pip/_internal/utils/appdirs.py,sha256=swgcTKOm3daLeXTW6v5BUS2Ti2RvEnGRQYH_yDXklAo,1665
|
| 277 |
+
pip/_internal/utils/compat.py,sha256=ACyBfLgj3_XG-iA5omEDrXqDM0cQKzi8h8HRBInzG6Q,1884
|
| 278 |
+
pip/_internal/utils/compatibility_tags.py,sha256=ydin8QG8BHqYRsPY4OL6cmb44CbqXl1T0xxS97VhHkk,5377
|
| 279 |
+
pip/_internal/utils/datetime.py,sha256=m21Y3wAtQc-ji6Veb6k_M5g6A0ZyFI4egchTdnwh-pQ,242
|
| 280 |
+
pip/_internal/utils/deprecation.py,sha256=NKo8VqLioJ4nnXXGmW4KdasxF90EFHkZaHeX1fT08C8,3627
|
| 281 |
+
pip/_internal/utils/direct_url_helpers.py,sha256=6F1tc2rcKaCZmgfVwsE6ObIe_Pux23mUVYA-2D9wCFc,3206
|
| 282 |
+
pip/_internal/utils/egg_link.py,sha256=0FePZoUYKv4RGQ2t6x7w5Z427wbA_Uo3WZnAkrgsuqo,2463
|
| 283 |
+
pip/_internal/utils/encoding.py,sha256=qqsXDtiwMIjXMEiIVSaOjwH5YmirCaK-dIzb6-XJsL0,1169
|
| 284 |
+
pip/_internal/utils/entrypoints.py,sha256=YlhLTRl2oHBAuqhc-zmL7USS67TPWVHImjeAQHreZTQ,3064
|
| 285 |
+
pip/_internal/utils/filesystem.py,sha256=RhMIXUaNVMGjc3rhsDahWQ4MavvEQDdqXqgq-F6fpw8,5122
|
| 286 |
+
pip/_internal/utils/filetypes.py,sha256=i8XAQ0eFCog26Fw9yV0Yb1ygAqKYB1w9Cz9n0fj8gZU,716
|
| 287 |
+
pip/_internal/utils/glibc.py,sha256=Mesxxgg3BLxheLZx-dSf30b6gKpOgdVXw6W--uHSszQ,3113
|
| 288 |
+
pip/_internal/utils/hashes.py,sha256=MjOigC75z6qoRMkgHiHqot7eqxfwDZSrEflJMPm-bHE,5118
|
| 289 |
+
pip/_internal/utils/logging.py,sha256=fdtuZJ-AKkqwDTANDvGcBEpssL8el7T1jnwk1CnZl3Y,11603
|
| 290 |
+
pip/_internal/utils/misc.py,sha256=fNXwaeeikvnUt4CPMFIL4-IQbZDxxjj4jDpzCi4ZsOw,23623
|
| 291 |
+
pip/_internal/utils/models.py,sha256=5GoYU586SrxURMvDn_jBMJInitviJg4O5-iOU-6I0WY,1193
|
| 292 |
+
pip/_internal/utils/packaging.py,sha256=5Wm6_x7lKrlqVjPI5MBN_RurcRHwVYoQ7Ksrs84de7s,2108
|
| 293 |
+
pip/_internal/utils/setuptools_build.py,sha256=ouXpud-jeS8xPyTPsXJ-m34NPvK5os45otAzdSV_IJE,4435
|
| 294 |
+
pip/_internal/utils/subprocess.py,sha256=zzdimb75jVLE1GU4WlTZ055gczhD7n1y1xTcNc7vNZQ,9207
|
| 295 |
+
pip/_internal/utils/temp_dir.py,sha256=DUAw22uFruQdK43i2L2K53C-CDjRCPeAsBKJpu-rHQ4,9312
|
| 296 |
+
pip/_internal/utils/unpacking.py,sha256=SBb2iV1crb89MDRTEKY86R4A_UOWApTQn9VQVcMDOlE,8821
|
| 297 |
+
pip/_internal/utils/urls.py,sha256=AhaesUGl-9it6uvG6fsFPOr9ynFpGaTMk4t5XTX7Z_Q,1759
|
| 298 |
+
pip/_internal/utils/virtualenv.py,sha256=S6f7csYorRpiD6cvn3jISZYc3I8PJC43H5iMFpRAEDU,3456
|
| 299 |
+
pip/_internal/utils/wheel.py,sha256=i4BwUNHattzN0ixy3HBAF04tZPRh2CcxaT6t86viwkE,4499
|
| 300 |
+
pip/_internal/vcs/__init__.py,sha256=UAqvzpbi0VbZo3Ub6skEeZAw-ooIZR-zX_WpCbxyCoU,596
|
| 301 |
+
pip/_internal/vcs/__pycache__/__init__.cpython-312.pyc,,
|
| 302 |
+
pip/_internal/vcs/__pycache__/bazaar.cpython-312.pyc,,
|
| 303 |
+
pip/_internal/vcs/__pycache__/git.cpython-312.pyc,,
|
| 304 |
+
pip/_internal/vcs/__pycache__/mercurial.cpython-312.pyc,,
|
| 305 |
+
pip/_internal/vcs/__pycache__/subversion.cpython-312.pyc,,
|
| 306 |
+
pip/_internal/vcs/__pycache__/versioncontrol.cpython-312.pyc,,
|
| 307 |
+
pip/_internal/vcs/bazaar.py,sha256=j0oin0fpGRHcCFCxEcpPCQoFEvA-DMLULKdGP8Nv76o,3519
|
| 308 |
+
pip/_internal/vcs/git.py,sha256=CeKBGJnl6uskvvjkAUXrJVxbHJrpS_B_pyfFdjL3CRc,18121
|
| 309 |
+
pip/_internal/vcs/mercurial.py,sha256=oULOhzJ2Uie-06d1omkL-_Gc6meGaUkyogvqG9ZCyPs,5249
|
| 310 |
+
pip/_internal/vcs/subversion.py,sha256=vhZs8L-TNggXqM1bbhl-FpbxE3TrIB6Tgnx8fh3S2HE,11729
|
| 311 |
+
pip/_internal/vcs/versioncontrol.py,sha256=3eIjtOMYvOY5qP6BMYIYDZ375CSuec6kSEB0bOo1cSs,22787
|
| 312 |
+
pip/_internal/wheel_builder.py,sha256=qTTzQV8F6b1jNsFCda1TRQC8J7gK-m7iuRNgKo7Dj68,11801
|
| 313 |
+
pip/_vendor/__init__.py,sha256=U51NPwXdA-wXOiANIQncYjcMp6txgeOL5nHxksJeyas,4993
|
| 314 |
+
pip/_vendor/__pycache__/__init__.cpython-312.pyc,,
|
| 315 |
+
pip/_vendor/__pycache__/six.cpython-312.pyc,,
|
| 316 |
+
pip/_vendor/__pycache__/typing_extensions.cpython-312.pyc,,
|
| 317 |
+
pip/_vendor/cachecontrol/__init__.py,sha256=ctHagMhQXuvQDdm4TirZrwDOT5H8oBNAJqzdKI6sovk,676
|
| 318 |
+
pip/_vendor/cachecontrol/__pycache__/__init__.cpython-312.pyc,,
|
| 319 |
+
pip/_vendor/cachecontrol/__pycache__/_cmd.cpython-312.pyc,,
|
| 320 |
+
pip/_vendor/cachecontrol/__pycache__/adapter.cpython-312.pyc,,
|
| 321 |
+
pip/_vendor/cachecontrol/__pycache__/cache.cpython-312.pyc,,
|
| 322 |
+
pip/_vendor/cachecontrol/__pycache__/controller.cpython-312.pyc,,
|
| 323 |
+
pip/_vendor/cachecontrol/__pycache__/filewrapper.cpython-312.pyc,,
|
| 324 |
+
pip/_vendor/cachecontrol/__pycache__/heuristics.cpython-312.pyc,,
|
| 325 |
+
pip/_vendor/cachecontrol/__pycache__/serialize.cpython-312.pyc,,
|
| 326 |
+
pip/_vendor/cachecontrol/__pycache__/wrapper.cpython-312.pyc,,
|
| 327 |
+
pip/_vendor/cachecontrol/_cmd.py,sha256=iist2EpzJvDVIhMAxXq8iFnTBsiZAd6iplxfmNboNyk,1737
|
| 328 |
+
pip/_vendor/cachecontrol/adapter.py,sha256=_CcWvUP9048qAZjsNqViaHbdcLs9mmFNixVfpO7oebE,6392
|
| 329 |
+
pip/_vendor/cachecontrol/cache.py,sha256=OTQj72tUf8C1uEgczdl3Gc8vkldSzsTITKtDGKMx4z8,1952
|
| 330 |
+
pip/_vendor/cachecontrol/caches/__init__.py,sha256=dtrrroK5BnADR1GWjCZ19aZ0tFsMfvFBtLQQU1sp_ag,303
|
| 331 |
+
pip/_vendor/cachecontrol/caches/__pycache__/__init__.cpython-312.pyc,,
|
| 332 |
+
pip/_vendor/cachecontrol/caches/__pycache__/file_cache.cpython-312.pyc,,
|
| 333 |
+
pip/_vendor/cachecontrol/caches/__pycache__/redis_cache.cpython-312.pyc,,
|
| 334 |
+
pip/_vendor/cachecontrol/caches/file_cache.py,sha256=3z8AWKD-vfKeiJqIzLmJyIYtR2yd6Tsh3u1TyLRQoIQ,5352
|
| 335 |
+
pip/_vendor/cachecontrol/caches/redis_cache.py,sha256=9rmqwtYu_ljVkW6_oLqbC7EaX_a8YT_yLuna-eS0dgo,1386
|
| 336 |
+
pip/_vendor/cachecontrol/controller.py,sha256=keCFA3ZaNVaWTwHd6F1zqWhb4vyvNx_UvZuo5iIYMfo,18384
|
| 337 |
+
pip/_vendor/cachecontrol/filewrapper.py,sha256=STttGmIPBvZzt2b51dUOwoWX5crcMCpKZOisM3f5BNc,4292
|
| 338 |
+
pip/_vendor/cachecontrol/heuristics.py,sha256=fdFbk9W8IeLrjteIz_fK4mj2HD_Y7COXF2Uc8TgjT1c,4828
|
| 339 |
+
pip/_vendor/cachecontrol/serialize.py,sha256=0dHeMaDwysVAAnGVlhMOP4tDliohgNK0Jxk_zsOiWxw,7173
|
| 340 |
+
pip/_vendor/cachecontrol/wrapper.py,sha256=hsGc7g8QGQTT-4f8tgz3AM5qwScg6FO0BSdLSRdEvpU,1417
|
| 341 |
+
pip/_vendor/certifi/__init__.py,sha256=L_j-d0kYuA_MzA2_2hraF1ovf6KT6DTquRdV3paQwOk,94
|
| 342 |
+
pip/_vendor/certifi/__main__.py,sha256=1k3Cr95vCxxGRGDljrW3wMdpZdL3Nhf0u1n-k2qdsCY,255
|
| 343 |
+
pip/_vendor/certifi/__pycache__/__init__.cpython-312.pyc,,
|
| 344 |
+
pip/_vendor/certifi/__pycache__/__main__.cpython-312.pyc,,
|
| 345 |
+
pip/_vendor/certifi/__pycache__/core.cpython-312.pyc,,
|
| 346 |
+
pip/_vendor/certifi/cacert.pem,sha256=eU0Dn_3yd8BH4m8sfVj4Glhl2KDrcCSg-sEWT-pNJ88,281617
|
| 347 |
+
pip/_vendor/certifi/core.py,sha256=DNTl8b_B6C4vO3Vc9_q2uvwHpNnBQoy5onDC4McImxc,4531
|
| 348 |
+
pip/_vendor/chardet/__init__.py,sha256=57R-HSxj0PWmILMN0GFmUNqEMfrEVSamXyjD-W6_fbs,4797
|
| 349 |
+
pip/_vendor/chardet/__pycache__/__init__.cpython-312.pyc,,
|
| 350 |
+
pip/_vendor/chardet/__pycache__/big5freq.cpython-312.pyc,,
|
| 351 |
+
pip/_vendor/chardet/__pycache__/big5prober.cpython-312.pyc,,
|
| 352 |
+
pip/_vendor/chardet/__pycache__/chardistribution.cpython-312.pyc,,
|
| 353 |
+
pip/_vendor/chardet/__pycache__/charsetgroupprober.cpython-312.pyc,,
|
| 354 |
+
pip/_vendor/chardet/__pycache__/charsetprober.cpython-312.pyc,,
|
| 355 |
+
pip/_vendor/chardet/__pycache__/codingstatemachine.cpython-312.pyc,,
|
| 356 |
+
pip/_vendor/chardet/__pycache__/codingstatemachinedict.cpython-312.pyc,,
|
| 357 |
+
pip/_vendor/chardet/__pycache__/cp949prober.cpython-312.pyc,,
|
| 358 |
+
pip/_vendor/chardet/__pycache__/enums.cpython-312.pyc,,
|
| 359 |
+
pip/_vendor/chardet/__pycache__/escprober.cpython-312.pyc,,
|
| 360 |
+
pip/_vendor/chardet/__pycache__/escsm.cpython-312.pyc,,
|
| 361 |
+
pip/_vendor/chardet/__pycache__/eucjpprober.cpython-312.pyc,,
|
| 362 |
+
pip/_vendor/chardet/__pycache__/euckrfreq.cpython-312.pyc,,
|
| 363 |
+
pip/_vendor/chardet/__pycache__/euckrprober.cpython-312.pyc,,
|
| 364 |
+
pip/_vendor/chardet/__pycache__/euctwfreq.cpython-312.pyc,,
|
| 365 |
+
pip/_vendor/chardet/__pycache__/euctwprober.cpython-312.pyc,,
|
| 366 |
+
pip/_vendor/chardet/__pycache__/gb2312freq.cpython-312.pyc,,
|
| 367 |
+
pip/_vendor/chardet/__pycache__/gb2312prober.cpython-312.pyc,,
|
| 368 |
+
pip/_vendor/chardet/__pycache__/hebrewprober.cpython-312.pyc,,
|
| 369 |
+
pip/_vendor/chardet/__pycache__/jisfreq.cpython-312.pyc,,
|
| 370 |
+
pip/_vendor/chardet/__pycache__/johabfreq.cpython-312.pyc,,
|
| 371 |
+
pip/_vendor/chardet/__pycache__/johabprober.cpython-312.pyc,,
|
| 372 |
+
pip/_vendor/chardet/__pycache__/jpcntx.cpython-312.pyc,,
|
| 373 |
+
pip/_vendor/chardet/__pycache__/langbulgarianmodel.cpython-312.pyc,,
|
| 374 |
+
pip/_vendor/chardet/__pycache__/langgreekmodel.cpython-312.pyc,,
|
| 375 |
+
pip/_vendor/chardet/__pycache__/langhebrewmodel.cpython-312.pyc,,
|
| 376 |
+
pip/_vendor/chardet/__pycache__/langhungarianmodel.cpython-312.pyc,,
|
| 377 |
+
pip/_vendor/chardet/__pycache__/langrussianmodel.cpython-312.pyc,,
|
| 378 |
+
pip/_vendor/chardet/__pycache__/langthaimodel.cpython-312.pyc,,
|
| 379 |
+
pip/_vendor/chardet/__pycache__/langturkishmodel.cpython-312.pyc,,
|
| 380 |
+
pip/_vendor/chardet/__pycache__/latin1prober.cpython-312.pyc,,
|
| 381 |
+
pip/_vendor/chardet/__pycache__/macromanprober.cpython-312.pyc,,
|
| 382 |
+
pip/_vendor/chardet/__pycache__/mbcharsetprober.cpython-312.pyc,,
|
| 383 |
+
pip/_vendor/chardet/__pycache__/mbcsgroupprober.cpython-312.pyc,,
|
| 384 |
+
pip/_vendor/chardet/__pycache__/mbcssm.cpython-312.pyc,,
|
| 385 |
+
pip/_vendor/chardet/__pycache__/resultdict.cpython-312.pyc,,
|
| 386 |
+
pip/_vendor/chardet/__pycache__/sbcharsetprober.cpython-312.pyc,,
|
| 387 |
+
pip/_vendor/chardet/__pycache__/sbcsgroupprober.cpython-312.pyc,,
|
| 388 |
+
pip/_vendor/chardet/__pycache__/sjisprober.cpython-312.pyc,,
|
| 389 |
+
pip/_vendor/chardet/__pycache__/universaldetector.cpython-312.pyc,,
|
| 390 |
+
pip/_vendor/chardet/__pycache__/utf1632prober.cpython-312.pyc,,
|
| 391 |
+
pip/_vendor/chardet/__pycache__/utf8prober.cpython-312.pyc,,
|
| 392 |
+
pip/_vendor/chardet/__pycache__/version.cpython-312.pyc,,
|
| 393 |
+
pip/_vendor/chardet/big5freq.py,sha256=ltcfP-3PjlNHCoo5e4a7C4z-2DhBTXRfY6jbMbB7P30,31274
|
| 394 |
+
pip/_vendor/chardet/big5prober.py,sha256=lPMfwCX6v2AaPgvFh_cSWZcgLDbWiFCHLZ_p9RQ9uxE,1763
|
| 395 |
+
pip/_vendor/chardet/chardistribution.py,sha256=13B8XUG4oXDuLdXvfbIWwLFeR-ZU21AqTS1zcdON8bU,10032
|
| 396 |
+
pip/_vendor/chardet/charsetgroupprober.py,sha256=UKK3SaIZB2PCdKSIS0gnvMtLR9JJX62M-fZJu3OlWyg,3915
|
| 397 |
+
pip/_vendor/chardet/charsetprober.py,sha256=L3t8_wIOov8em-vZWOcbkdsrwe43N6_gqNh5pH7WPd4,5420
|
| 398 |
+
pip/_vendor/chardet/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 399 |
+
pip/_vendor/chardet/cli/__pycache__/__init__.cpython-312.pyc,,
|
| 400 |
+
pip/_vendor/chardet/cli/__pycache__/chardetect.cpython-312.pyc,,
|
| 401 |
+
pip/_vendor/chardet/cli/chardetect.py,sha256=zibMVg5RpKb-ME9_7EYG4ZM2Sf07NHcQzZ12U-rYJho,3242
|
| 402 |
+
pip/_vendor/chardet/codingstatemachine.py,sha256=K7k69sw3jY5DmTXoSJQVsUtFIQKYPQVOSJJhBuGv_yE,3732
|
| 403 |
+
pip/_vendor/chardet/codingstatemachinedict.py,sha256=0GY3Hi2qIZvDrOOJ3AtqppM1RsYxr_66ER4EHjuMiMc,542
|
| 404 |
+
pip/_vendor/chardet/cp949prober.py,sha256=0jKRV7fECuWI16rNnks0ZECKA1iZYCIEaP8A1ZvjUSI,1860
|
| 405 |
+
pip/_vendor/chardet/enums.py,sha256=TzECiZoCKNMqgwU76cPCeKWFBqaWvAdLMev5_bCkhY8,1683
|
| 406 |
+
pip/_vendor/chardet/escprober.py,sha256=Kho48X65xE0scFylIdeJjM2bcbvRvv0h0WUbMWrJD3A,4006
|
| 407 |
+
pip/_vendor/chardet/escsm.py,sha256=AqyXpA2FQFD7k-buBty_7itGEYkhmVa8X09NLRul3QM,12176
|
| 408 |
+
pip/_vendor/chardet/eucjpprober.py,sha256=5KYaM9fsxkRYzw1b5k0fL-j_-ezIw-ij9r97a9MHxLY,3934
|
| 409 |
+
pip/_vendor/chardet/euckrfreq.py,sha256=3mHuRvXfsq_QcQysDQFb8qSudvTiol71C6Ic2w57tKM,13566
|
| 410 |
+
pip/_vendor/chardet/euckrprober.py,sha256=hiFT6wM174GIwRvqDsIcuOc-dDsq2uPKMKbyV8-1Xnc,1753
|
| 411 |
+
pip/_vendor/chardet/euctwfreq.py,sha256=2alILE1Lh5eqiFJZjzRkMQXolNJRHY5oBQd-vmZYFFM,36913
|
| 412 |
+
pip/_vendor/chardet/euctwprober.py,sha256=NxbpNdBtU0VFI0bKfGfDkpP7S2_8_6FlO87dVH0ogws,1753
|
| 413 |
+
pip/_vendor/chardet/gb2312freq.py,sha256=49OrdXzD-HXqwavkqjo8Z7gvs58hONNzDhAyMENNkvY,20735
|
| 414 |
+
pip/_vendor/chardet/gb2312prober.py,sha256=KPEBueaSLSvBpFeINMu0D6TgHcR90e5PaQawifzF4o0,1759
|
| 415 |
+
pip/_vendor/chardet/hebrewprober.py,sha256=96T_Lj_OmW-fK7JrSHojYjyG3fsGgbzkoTNleZ3kfYE,14537
|
| 416 |
+
pip/_vendor/chardet/jisfreq.py,sha256=mm8tfrwqhpOd3wzZKS4NJqkYBQVcDfTM2JiQ5aW932E,25796
|
| 417 |
+
pip/_vendor/chardet/johabfreq.py,sha256=dBpOYG34GRX6SL8k_LbS9rxZPMjLjoMlgZ03Pz5Hmqc,42498
|
| 418 |
+
pip/_vendor/chardet/johabprober.py,sha256=O1Qw9nVzRnun7vZp4UZM7wvJSv9W941mEU9uDMnY3DU,1752
|
| 419 |
+
pip/_vendor/chardet/jpcntx.py,sha256=uhHrYWkLxE_rF5OkHKInm0HUsrjgKHHVQvtt3UcvotA,27055
|
| 420 |
+
pip/_vendor/chardet/langbulgarianmodel.py,sha256=vmbvYFP8SZkSxoBvLkFqKiH1sjma5ihk3PTpdy71Rr4,104562
|
| 421 |
+
pip/_vendor/chardet/langgreekmodel.py,sha256=JfB7bupjjJH2w3X_mYnQr9cJA_7EuITC2cRW13fUjeI,98484
|
| 422 |
+
pip/_vendor/chardet/langhebrewmodel.py,sha256=3HXHaLQPNAGcXnJjkIJfozNZLTvTJmf4W5Awi6zRRKc,98196
|
| 423 |
+
pip/_vendor/chardet/langhungarianmodel.py,sha256=WxbeQIxkv8YtApiNqxQcvj-tMycsoI4Xy-fwkDHpP_Y,101363
|
| 424 |
+
pip/_vendor/chardet/langrussianmodel.py,sha256=s395bTZ87ESTrZCOdgXbEjZ9P1iGPwCl_8xSsac_DLY,128035
|
| 425 |
+
pip/_vendor/chardet/langthaimodel.py,sha256=7bJlQitRpTnVGABmbSznHnJwOHDy3InkTvtFUx13WQI,102774
|
| 426 |
+
pip/_vendor/chardet/langturkishmodel.py,sha256=XY0eGdTIy4eQ9Xg1LVPZacb-UBhHBR-cq0IpPVHowKc,95372
|
| 427 |
+
pip/_vendor/chardet/latin1prober.py,sha256=p15EEmFbmQUwbKLC7lOJVGHEZwcG45ubEZYTGu01J5g,5380
|
| 428 |
+
pip/_vendor/chardet/macromanprober.py,sha256=9anfzmY6TBfUPDyBDOdY07kqmTHpZ1tK0jL-p1JWcOY,6077
|
| 429 |
+
pip/_vendor/chardet/mbcharsetprober.py,sha256=Wr04WNI4F3X_VxEverNG-H25g7u-MDDKlNt-JGj-_uU,3715
|
| 430 |
+
pip/_vendor/chardet/mbcsgroupprober.py,sha256=iRpaNBjV0DNwYPu_z6TiHgRpwYahiM7ztI_4kZ4Uz9A,2131
|
| 431 |
+
pip/_vendor/chardet/mbcssm.py,sha256=hUtPvDYgWDaA2dWdgLsshbwRfm3Q5YRlRogdmeRUNQw,30391
|
| 432 |
+
pip/_vendor/chardet/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 433 |
+
pip/_vendor/chardet/metadata/__pycache__/__init__.cpython-312.pyc,,
|
| 434 |
+
pip/_vendor/chardet/metadata/__pycache__/languages.cpython-312.pyc,,
|
| 435 |
+
pip/_vendor/chardet/metadata/languages.py,sha256=FhvBIdZFxRQ-dTwkb_0madRKgVBCaUMQz9I5xqjE5iQ,13560
|
| 436 |
+
pip/_vendor/chardet/resultdict.py,sha256=ez4FRvN5KaSosJeJ2WzUyKdDdg35HDy_SSLPXKCdt5M,402
|
| 437 |
+
pip/_vendor/chardet/sbcharsetprober.py,sha256=-nd3F90i7GpXLjehLVHqVBE0KlWzGvQUPETLBNn4o6U,6400
|
| 438 |
+
pip/_vendor/chardet/sbcsgroupprober.py,sha256=gcgI0fOfgw_3YTClpbra_MNxwyEyJ3eUXraoLHYb59E,4137
|
| 439 |
+
pip/_vendor/chardet/sjisprober.py,sha256=aqQufMzRw46ZpFlzmYaYeT2-nzmKb-hmcrApppJ862k,4007
|
| 440 |
+
pip/_vendor/chardet/universaldetector.py,sha256=xYBrg4x0dd9WnT8qclfADVD9ondrUNkqPmvte1pa520,14848
|
| 441 |
+
pip/_vendor/chardet/utf1632prober.py,sha256=pw1epGdMj1hDGiCu1AHqqzOEfjX8MVdiW7O1BlT8-eQ,8505
|
| 442 |
+
pip/_vendor/chardet/utf8prober.py,sha256=8m08Ub5490H4jQ6LYXvFysGtgKoKsHUd2zH_i8_TnVw,2812
|
| 443 |
+
pip/_vendor/chardet/version.py,sha256=lGtJcxGM44Qz4Cbk4rbbmrKxnNr1-97U25TameLehZw,244
|
| 444 |
+
pip/_vendor/colorama/__init__.py,sha256=wePQA4U20tKgYARySLEC047ucNX-g8pRLpYBuiHlLb8,266
|
| 445 |
+
pip/_vendor/colorama/__pycache__/__init__.cpython-312.pyc,,
|
| 446 |
+
pip/_vendor/colorama/__pycache__/ansi.cpython-312.pyc,,
|
| 447 |
+
pip/_vendor/colorama/__pycache__/ansitowin32.cpython-312.pyc,,
|
| 448 |
+
pip/_vendor/colorama/__pycache__/initialise.cpython-312.pyc,,
|
| 449 |
+
pip/_vendor/colorama/__pycache__/win32.cpython-312.pyc,,
|
| 450 |
+
pip/_vendor/colorama/__pycache__/winterm.cpython-312.pyc,,
|
| 451 |
+
pip/_vendor/colorama/ansi.py,sha256=Top4EeEuaQdBWdteKMEcGOTeKeF19Q-Wo_6_Cj5kOzQ,2522
|
| 452 |
+
pip/_vendor/colorama/ansitowin32.py,sha256=vPNYa3OZbxjbuFyaVo0Tmhmy1FZ1lKMWCnT7odXpItk,11128
|
| 453 |
+
pip/_vendor/colorama/initialise.py,sha256=-hIny86ClXo39ixh5iSCfUIa2f_h_bgKRDW7gqs-KLU,3325
|
| 454 |
+
pip/_vendor/colorama/tests/__init__.py,sha256=MkgPAEzGQd-Rq0w0PZXSX2LadRWhUECcisJY8lSrm4Q,75
|
| 455 |
+
pip/_vendor/colorama/tests/__pycache__/__init__.cpython-312.pyc,,
|
| 456 |
+
pip/_vendor/colorama/tests/__pycache__/ansi_test.cpython-312.pyc,,
|
| 457 |
+
pip/_vendor/colorama/tests/__pycache__/ansitowin32_test.cpython-312.pyc,,
|
| 458 |
+
pip/_vendor/colorama/tests/__pycache__/initialise_test.cpython-312.pyc,,
|
| 459 |
+
pip/_vendor/colorama/tests/__pycache__/isatty_test.cpython-312.pyc,,
|
| 460 |
+
pip/_vendor/colorama/tests/__pycache__/utils.cpython-312.pyc,,
|
| 461 |
+
pip/_vendor/colorama/tests/__pycache__/winterm_test.cpython-312.pyc,,
|
| 462 |
+
pip/_vendor/colorama/tests/ansi_test.py,sha256=FeViDrUINIZcr505PAxvU4AjXz1asEiALs9GXMhwRaE,2839
|
| 463 |
+
pip/_vendor/colorama/tests/ansitowin32_test.py,sha256=RN7AIhMJ5EqDsYaCjVo-o4u8JzDD4ukJbmevWKS70rY,10678
|
| 464 |
+
pip/_vendor/colorama/tests/initialise_test.py,sha256=BbPy-XfyHwJ6zKozuQOvNvQZzsx9vdb_0bYXn7hsBTc,6741
|
| 465 |
+
pip/_vendor/colorama/tests/isatty_test.py,sha256=Pg26LRpv0yQDB5Ac-sxgVXG7hsA1NYvapFgApZfYzZg,1866
|
| 466 |
+
pip/_vendor/colorama/tests/utils.py,sha256=1IIRylG39z5-dzq09R_ngufxyPZxgldNbrxKxUGwGKE,1079
|
| 467 |
+
pip/_vendor/colorama/tests/winterm_test.py,sha256=qoWFPEjym5gm2RuMwpf3pOis3a5r_PJZFCzK254JL8A,3709
|
| 468 |
+
pip/_vendor/colorama/win32.py,sha256=YQOKwMTwtGBbsY4dL5HYTvwTeP9wIQra5MvPNddpxZs,6181
|
| 469 |
+
pip/_vendor/colorama/winterm.py,sha256=XCQFDHjPi6AHYNdZwy0tA02H-Jh48Jp-HvCjeLeLp3U,7134
|
| 470 |
+
pip/_vendor/distlib/__init__.py,sha256=hJKF7FHoqbmGckncDuEINWo_OYkDNiHODtYXSMcvjcc,625
|
| 471 |
+
pip/_vendor/distlib/__pycache__/__init__.cpython-312.pyc,,
|
| 472 |
+
pip/_vendor/distlib/__pycache__/compat.cpython-312.pyc,,
|
| 473 |
+
pip/_vendor/distlib/__pycache__/database.cpython-312.pyc,,
|
| 474 |
+
pip/_vendor/distlib/__pycache__/index.cpython-312.pyc,,
|
| 475 |
+
pip/_vendor/distlib/__pycache__/locators.cpython-312.pyc,,
|
| 476 |
+
pip/_vendor/distlib/__pycache__/manifest.cpython-312.pyc,,
|
| 477 |
+
pip/_vendor/distlib/__pycache__/markers.cpython-312.pyc,,
|
| 478 |
+
pip/_vendor/distlib/__pycache__/metadata.cpython-312.pyc,,
|
| 479 |
+
pip/_vendor/distlib/__pycache__/resources.cpython-312.pyc,,
|
| 480 |
+
pip/_vendor/distlib/__pycache__/scripts.cpython-312.pyc,,
|
| 481 |
+
pip/_vendor/distlib/__pycache__/util.cpython-312.pyc,,
|
| 482 |
+
pip/_vendor/distlib/__pycache__/version.cpython-312.pyc,,
|
| 483 |
+
pip/_vendor/distlib/__pycache__/wheel.cpython-312.pyc,,
|
| 484 |
+
pip/_vendor/distlib/compat.py,sha256=Un-uIBvy02w-D267OG4VEhuddqWgKj9nNkxVltAb75w,41487
|
| 485 |
+
pip/_vendor/distlib/database.py,sha256=0V9Qvs0Vrxa2F_-hLWitIyVyRifJ0pCxyOI-kEOBwsA,51965
|
| 486 |
+
pip/_vendor/distlib/index.py,sha256=lTbw268rRhj8dw1sib3VZ_0EhSGgoJO3FKJzSFMOaeA,20797
|
| 487 |
+
pip/_vendor/distlib/locators.py,sha256=o1r_M86_bRLafSpetmyfX8KRtFu-_Q58abvQrnOSnbA,51767
|
| 488 |
+
pip/_vendor/distlib/manifest.py,sha256=3qfmAmVwxRqU1o23AlfXrQGZzh6g_GGzTAP_Hb9C5zQ,14168
|
| 489 |
+
pip/_vendor/distlib/markers.py,sha256=n3DfOh1yvZ_8EW7atMyoYeZFXjYla0Nz0itQlojCd0A,5268
|
| 490 |
+
pip/_vendor/distlib/metadata.py,sha256=pB9WZ9mBfmQxc9OVIldLS5CjOoQRvKAvUwwQyKwKQtQ,39693
|
| 491 |
+
pip/_vendor/distlib/resources.py,sha256=LwbPksc0A1JMbi6XnuPdMBUn83X7BPuFNWqPGEKI698,10820
|
| 492 |
+
pip/_vendor/distlib/scripts.py,sha256=nQFXN6G7nOWNDUyxirUep-3WOlJhB7McvCs9zOnkGTI,18315
|
| 493 |
+
pip/_vendor/distlib/util.py,sha256=XSznxEi_i3T20UJuaVc0qXHz5ksGUCW1khYlBprN_QE,67530
|
| 494 |
+
pip/_vendor/distlib/version.py,sha256=9pXkduchve_aN7JG6iL9VTYV_kqNSGoc2Dwl8JuySnQ,23747
|
| 495 |
+
pip/_vendor/distlib/wheel.py,sha256=FVQCve8u-L0QYk5-YTZc7s4WmNQdvjRWTK08KXzZVX4,43958
|
| 496 |
+
pip/_vendor/distro/__init__.py,sha256=2fHjF-SfgPvjyNZ1iHh_wjqWdR_Yo5ODHwZC0jLBPhc,981
|
| 497 |
+
pip/_vendor/distro/__main__.py,sha256=bu9d3TifoKciZFcqRBuygV3GSuThnVD_m2IK4cz96Vs,64
|
| 498 |
+
pip/_vendor/distro/__pycache__/__init__.cpython-312.pyc,,
|
| 499 |
+
pip/_vendor/distro/__pycache__/__main__.cpython-312.pyc,,
|
| 500 |
+
pip/_vendor/distro/__pycache__/distro.cpython-312.pyc,,
|
| 501 |
+
pip/_vendor/distro/distro.py,sha256=UZO1LjIhtFCMdlbiz39gj3raV-Amf3SBwzGzfApiMHw,49330
|
| 502 |
+
pip/_vendor/idna/__init__.py,sha256=KJQN1eQBr8iIK5SKrJ47lXvxG0BJ7Lm38W4zT0v_8lk,849
|
| 503 |
+
pip/_vendor/idna/__pycache__/__init__.cpython-312.pyc,,
|
| 504 |
+
pip/_vendor/idna/__pycache__/codec.cpython-312.pyc,,
|
| 505 |
+
pip/_vendor/idna/__pycache__/compat.cpython-312.pyc,,
|
| 506 |
+
pip/_vendor/idna/__pycache__/core.cpython-312.pyc,,
|
| 507 |
+
pip/_vendor/idna/__pycache__/idnadata.cpython-312.pyc,,
|
| 508 |
+
pip/_vendor/idna/__pycache__/intranges.cpython-312.pyc,,
|
| 509 |
+
pip/_vendor/idna/__pycache__/package_data.cpython-312.pyc,,
|
| 510 |
+
pip/_vendor/idna/__pycache__/uts46data.cpython-312.pyc,,
|
| 511 |
+
pip/_vendor/idna/codec.py,sha256=6ly5odKfqrytKT9_7UrlGklHnf1DSK2r9C6cSM4sa28,3374
|
| 512 |
+
pip/_vendor/idna/compat.py,sha256=0_sOEUMT4CVw9doD3vyRhX80X19PwqFoUBs7gWsFME4,321
|
| 513 |
+
pip/_vendor/idna/core.py,sha256=kkCFNJOrE6I3WwBTXcGNuc24V_QZQ8AULE6EYe1iHlU,12813
|
| 514 |
+
pip/_vendor/idna/idnadata.py,sha256=9NIhTqC2piUpeIMOGZ9Bu_7eAFQ-Ic8TkP_hOzUpnDc,78344
|
| 515 |
+
pip/_vendor/idna/intranges.py,sha256=YBr4fRYuWH7kTKS2tXlFjM24ZF1Pdvcir-aywniInqg,1881
|
| 516 |
+
pip/_vendor/idna/package_data.py,sha256=C_jHJzmX8PI4xq0jpzmcTMxpb5lDsq4o5VyxQzlVrZE,21
|
| 517 |
+
pip/_vendor/idna/uts46data.py,sha256=zvjZU24s58_uAS850Mcd0NnD0X7_gCMAMjzWNIeUJdc,206539
|
| 518 |
+
pip/_vendor/msgpack/__init__.py,sha256=hyGhlnmcJkxryJBKC3X5FnEph375kQoL_mG8LZUuXgY,1132
|
| 519 |
+
pip/_vendor/msgpack/__pycache__/__init__.cpython-312.pyc,,
|
| 520 |
+
pip/_vendor/msgpack/__pycache__/exceptions.cpython-312.pyc,,
|
| 521 |
+
pip/_vendor/msgpack/__pycache__/ext.cpython-312.pyc,,
|
| 522 |
+
pip/_vendor/msgpack/__pycache__/fallback.cpython-312.pyc,,
|
| 523 |
+
pip/_vendor/msgpack/exceptions.py,sha256=dCTWei8dpkrMsQDcjQk74ATl9HsIBH0ybt8zOPNqMYc,1081
|
| 524 |
+
pip/_vendor/msgpack/ext.py,sha256=C5MK8JhVYGYFWPvxsORsqZAnvOXefYQ57m1Ym0luW5M,6079
|
| 525 |
+
pip/_vendor/msgpack/fallback.py,sha256=tvNBHyxxFbuVlC8GZShETClJxjLiDMOja4XwwyvNm2g,34544
|
| 526 |
+
pip/_vendor/packaging/__about__.py,sha256=ugASIO2w1oUyH8_COqQ2X_s0rDhjbhQC3yJocD03h2c,661
|
| 527 |
+
pip/_vendor/packaging/__init__.py,sha256=b9Kk5MF7KxhhLgcDmiUWukN-LatWFxPdNug0joPhHSk,497
|
| 528 |
+
pip/_vendor/packaging/__pycache__/__about__.cpython-312.pyc,,
|
| 529 |
+
pip/_vendor/packaging/__pycache__/__init__.cpython-312.pyc,,
|
| 530 |
+
pip/_vendor/packaging/__pycache__/_manylinux.cpython-312.pyc,,
|
| 531 |
+
pip/_vendor/packaging/__pycache__/_musllinux.cpython-312.pyc,,
|
| 532 |
+
pip/_vendor/packaging/__pycache__/_structures.cpython-312.pyc,,
|
| 533 |
+
pip/_vendor/packaging/__pycache__/markers.cpython-312.pyc,,
|
| 534 |
+
pip/_vendor/packaging/__pycache__/requirements.cpython-312.pyc,,
|
| 535 |
+
pip/_vendor/packaging/__pycache__/specifiers.cpython-312.pyc,,
|
| 536 |
+
pip/_vendor/packaging/__pycache__/tags.cpython-312.pyc,,
|
| 537 |
+
pip/_vendor/packaging/__pycache__/utils.cpython-312.pyc,,
|
| 538 |
+
pip/_vendor/packaging/__pycache__/version.cpython-312.pyc,,
|
| 539 |
+
pip/_vendor/packaging/_manylinux.py,sha256=XcbiXB-qcjv3bcohp6N98TMpOP4_j3m-iOA8ptK2GWY,11488
|
| 540 |
+
pip/_vendor/packaging/_musllinux.py,sha256=_KGgY_qc7vhMGpoqss25n2hiLCNKRtvz9mCrS7gkqyc,4378
|
| 541 |
+
pip/_vendor/packaging/_structures.py,sha256=q3eVNmbWJGG_S0Dit_S3Ao8qQqz_5PYTXFAKBZe5yr4,1431
|
| 542 |
+
pip/_vendor/packaging/markers.py,sha256=AJBOcY8Oq0kYc570KuuPTkvuqjAlhufaE2c9sCUbm64,8487
|
| 543 |
+
pip/_vendor/packaging/requirements.py,sha256=NtDlPBtojpn1IUC85iMjPNsUmufjpSlwnNA-Xb4m5NA,4676
|
| 544 |
+
pip/_vendor/packaging/specifiers.py,sha256=LRQ0kFsHrl5qfcFNEEJrIFYsnIHQUJXY9fIsakTrrqE,30110
|
| 545 |
+
pip/_vendor/packaging/tags.py,sha256=lmsnGNiJ8C4D_Pf9PbM0qgbZvD9kmB9lpZBQUZa3R_Y,15699
|
| 546 |
+
pip/_vendor/packaging/utils.py,sha256=dJjeat3BS-TYn1RrUFVwufUMasbtzLfYRoy_HXENeFQ,4200
|
| 547 |
+
pip/_vendor/packaging/version.py,sha256=_fLRNrFrxYcHVfyo8vk9j8s6JM8N_xsSxVFr6RJyco8,14665
|
| 548 |
+
pip/_vendor/pkg_resources/__init__.py,sha256=hTAeJCNYb7dJseIDVsYK3mPQep_gphj4tQh-bspX8bg,109364
|
| 549 |
+
pip/_vendor/pkg_resources/__pycache__/__init__.cpython-312.pyc,,
|
| 550 |
+
pip/_vendor/platformdirs/__init__.py,sha256=SkhEYVyC_HUHC6KX7n4M_6coyRMtEB38QMyOYIAX6Yk,20155
|
| 551 |
+
pip/_vendor/platformdirs/__main__.py,sha256=fVvSiTzr2-RM6IsjWjj4fkaOtDOgDhUWv6sA99do4CQ,1476
|
| 552 |
+
pip/_vendor/platformdirs/__pycache__/__init__.cpython-312.pyc,,
|
| 553 |
+
pip/_vendor/platformdirs/__pycache__/__main__.cpython-312.pyc,,
|
| 554 |
+
pip/_vendor/platformdirs/__pycache__/android.cpython-312.pyc,,
|
| 555 |
+
pip/_vendor/platformdirs/__pycache__/api.cpython-312.pyc,,
|
| 556 |
+
pip/_vendor/platformdirs/__pycache__/macos.cpython-312.pyc,,
|
| 557 |
+
pip/_vendor/platformdirs/__pycache__/unix.cpython-312.pyc,,
|
| 558 |
+
pip/_vendor/platformdirs/__pycache__/version.cpython-312.pyc,,
|
| 559 |
+
pip/_vendor/platformdirs/__pycache__/windows.cpython-312.pyc,,
|
| 560 |
+
pip/_vendor/platformdirs/android.py,sha256=y_EEMKwYl2-bzYBDovksSn8m76on0Lda8eyJksVQE9U,7211
|
| 561 |
+
pip/_vendor/platformdirs/api.py,sha256=jWtX06jAJytYrkJDOqEls97mCkyHRSZkoqUlbMK5Qew,7132
|
| 562 |
+
pip/_vendor/platformdirs/macos.py,sha256=LueVOoVgGWDBwQb8OFwXkVKfVn33CM1Lkwf1-A86tRQ,3678
|
| 563 |
+
pip/_vendor/platformdirs/unix.py,sha256=22JhR8ZY0aLxSVCFnKrc6f1iz6Gv42K24Daj7aTjfSg,8809
|
| 564 |
+
pip/_vendor/platformdirs/version.py,sha256=mavZTQIJIXfdewEaSTn7EWrNfPZWeRofb-74xqW5f2M,160
|
| 565 |
+
pip/_vendor/platformdirs/windows.py,sha256=4TtbPGoWG2PRgI11uquDa7eRk8TcxvnUNuuMGZItnXc,9573
|
| 566 |
+
pip/_vendor/pygments/__init__.py,sha256=6AuDljQtvf89DTNUyWM7k3oUlP_lq70NU-INKKteOBY,2983
|
| 567 |
+
pip/_vendor/pygments/__main__.py,sha256=es8EKMvXj5yToIfQ-pf3Dv5TnIeeM6sME0LW-n4ecHo,353
|
| 568 |
+
pip/_vendor/pygments/__pycache__/__init__.cpython-312.pyc,,
|
| 569 |
+
pip/_vendor/pygments/__pycache__/__main__.cpython-312.pyc,,
|
| 570 |
+
pip/_vendor/pygments/__pycache__/cmdline.cpython-312.pyc,,
|
| 571 |
+
pip/_vendor/pygments/__pycache__/console.cpython-312.pyc,,
|
| 572 |
+
pip/_vendor/pygments/__pycache__/filter.cpython-312.pyc,,
|
| 573 |
+
pip/_vendor/pygments/__pycache__/formatter.cpython-312.pyc,,
|
| 574 |
+
pip/_vendor/pygments/__pycache__/lexer.cpython-312.pyc,,
|
| 575 |
+
pip/_vendor/pygments/__pycache__/modeline.cpython-312.pyc,,
|
| 576 |
+
pip/_vendor/pygments/__pycache__/plugin.cpython-312.pyc,,
|
| 577 |
+
pip/_vendor/pygments/__pycache__/regexopt.cpython-312.pyc,,
|
| 578 |
+
pip/_vendor/pygments/__pycache__/scanner.cpython-312.pyc,,
|
| 579 |
+
pip/_vendor/pygments/__pycache__/sphinxext.cpython-312.pyc,,
|
| 580 |
+
pip/_vendor/pygments/__pycache__/style.cpython-312.pyc,,
|
| 581 |
+
pip/_vendor/pygments/__pycache__/token.cpython-312.pyc,,
|
| 582 |
+
pip/_vendor/pygments/__pycache__/unistring.cpython-312.pyc,,
|
| 583 |
+
pip/_vendor/pygments/__pycache__/util.cpython-312.pyc,,
|
| 584 |
+
pip/_vendor/pygments/cmdline.py,sha256=byxYJp9gnjVeyhRlZ3UTMgo_LhkXh1afvN8wJBtAcc8,23685
|
| 585 |
+
pip/_vendor/pygments/console.py,sha256=2wZ5W-U6TudJD1_NLUwjclMpbomFM91lNv11_60sfGY,1697
|
| 586 |
+
pip/_vendor/pygments/filter.py,sha256=j5aLM9a9wSx6eH1oy473oSkJ02hGWNptBlVo4s1g_30,1938
|
| 587 |
+
pip/_vendor/pygments/filters/__init__.py,sha256=h_koYkUFo-FFUxjs564JHUAz7O3yJpVwI6fKN3MYzG0,40386
|
| 588 |
+
pip/_vendor/pygments/filters/__pycache__/__init__.cpython-312.pyc,,
|
| 589 |
+
pip/_vendor/pygments/formatter.py,sha256=J9OL9hXLJKZk7moUgKwpjW9HNf4WlJFg_o_-Z_S_tTY,4178
|
| 590 |
+
pip/_vendor/pygments/formatters/__init__.py,sha256=_xgAcdFKr0QNYwh_i98AU9hvfP3X2wAkhElFcRRF3Uo,5424
|
| 591 |
+
pip/_vendor/pygments/formatters/__pycache__/__init__.cpython-312.pyc,,
|
| 592 |
+
pip/_vendor/pygments/formatters/__pycache__/_mapping.cpython-312.pyc,,
|
| 593 |
+
pip/_vendor/pygments/formatters/__pycache__/bbcode.cpython-312.pyc,,
|
| 594 |
+
pip/_vendor/pygments/formatters/__pycache__/groff.cpython-312.pyc,,
|
| 595 |
+
pip/_vendor/pygments/formatters/__pycache__/html.cpython-312.pyc,,
|
| 596 |
+
pip/_vendor/pygments/formatters/__pycache__/img.cpython-312.pyc,,
|
| 597 |
+
pip/_vendor/pygments/formatters/__pycache__/irc.cpython-312.pyc,,
|
| 598 |
+
pip/_vendor/pygments/formatters/__pycache__/latex.cpython-312.pyc,,
|
| 599 |
+
pip/_vendor/pygments/formatters/__pycache__/other.cpython-312.pyc,,
|
| 600 |
+
pip/_vendor/pygments/formatters/__pycache__/pangomarkup.cpython-312.pyc,,
|
| 601 |
+
pip/_vendor/pygments/formatters/__pycache__/rtf.cpython-312.pyc,,
|
| 602 |
+
pip/_vendor/pygments/formatters/__pycache__/svg.cpython-312.pyc,,
|
| 603 |
+
pip/_vendor/pygments/formatters/__pycache__/terminal.cpython-312.pyc,,
|
| 604 |
+
pip/_vendor/pygments/formatters/__pycache__/terminal256.cpython-312.pyc,,
|
| 605 |
+
pip/_vendor/pygments/formatters/_mapping.py,sha256=1Cw37FuQlNacnxRKmtlPX4nyLoX9_ttko5ZwscNUZZ4,4176
|
| 606 |
+
pip/_vendor/pygments/formatters/bbcode.py,sha256=r1b7wzWTJouADDLh-Z11iRi4iQxD0JKJ1qHl6mOYxsA,3314
|
| 607 |
+
pip/_vendor/pygments/formatters/groff.py,sha256=xy8Zf3tXOo6MWrXh7yPGWx3lVEkg_DhY4CxmsDb0IVo,5094
|
| 608 |
+
pip/_vendor/pygments/formatters/html.py,sha256=PIzAyilNqaTzSSP2slDG2VDLE3qNioWy2rgtSSoviuI,35610
|
| 609 |
+
pip/_vendor/pygments/formatters/img.py,sha256=XKXmg2_XONrR4mtq2jfEU8XCsoln3VSGTw-UYiEokys,21938
|
| 610 |
+
pip/_vendor/pygments/formatters/irc.py,sha256=Ep-m8jd3voFO6Fv57cUGFmz6JVA67IEgyiBOwv0N4a0,4981
|
| 611 |
+
pip/_vendor/pygments/formatters/latex.py,sha256=FGzJ-YqSTE8z_voWPdzvLY5Tq8jE_ygjGjM6dXZJ8-k,19351
|
| 612 |
+
pip/_vendor/pygments/formatters/other.py,sha256=gPxkk5BdAzWTCgbEHg1lpLi-1F6ZPh5A_aotgLXHnzg,5073
|
| 613 |
+
pip/_vendor/pygments/formatters/pangomarkup.py,sha256=6LKnQc8yh49f802bF0sPvbzck4QivMYqqoXAPaYP8uU,2212
|
| 614 |
+
pip/_vendor/pygments/formatters/rtf.py,sha256=aA0v_psW6KZI3N18TKDifxeL6mcF8EDXcPXDWI4vhVQ,5014
|
| 615 |
+
pip/_vendor/pygments/formatters/svg.py,sha256=dQONWypbzfvzGCDtdp3M_NJawScJvM2DiHbx1k-ww7g,7335
|
| 616 |
+
pip/_vendor/pygments/formatters/terminal.py,sha256=FG-rpjRpFmNpiGB4NzIucvxq6sQIXB3HOTo2meTKtrU,4674
|
| 617 |
+
pip/_vendor/pygments/formatters/terminal256.py,sha256=13SJ3D5pFdqZ9zROE6HbWnBDwHvOGE8GlsmqGhprRp4,11753
|
| 618 |
+
pip/_vendor/pygments/lexer.py,sha256=2BpqLlT2ExvOOi7vnjK5nB4Fp-m52ldiPaXMox5uwug,34618
|
| 619 |
+
pip/_vendor/pygments/lexers/__init__.py,sha256=j5KEi5O_VQ5GS59H49l-10gzUOkWKxlwGeVMlGO2MMk,12130
|
| 620 |
+
pip/_vendor/pygments/lexers/__pycache__/__init__.cpython-312.pyc,,
|
| 621 |
+
pip/_vendor/pygments/lexers/__pycache__/_mapping.cpython-312.pyc,,
|
| 622 |
+
pip/_vendor/pygments/lexers/__pycache__/python.cpython-312.pyc,,
|
| 623 |
+
pip/_vendor/pygments/lexers/_mapping.py,sha256=Hts4r_ZQ8icftGM7gkBPeED5lyVSv4affFgXYE6Ap04,72281
|
| 624 |
+
pip/_vendor/pygments/lexers/python.py,sha256=c7jnmKFU9DLxTJW0UbwXt6Z9FJqbBlVsWA1Qr9xSA_w,53424
|
| 625 |
+
pip/_vendor/pygments/modeline.py,sha256=eF2vO4LpOGoPvIKKkbPfnyut8hT4UiebZPpb-BYGQdI,986
|
| 626 |
+
pip/_vendor/pygments/plugin.py,sha256=j1Fh310RbV2DQ9nvkmkqvlj38gdyuYKllLnGxbc8sJM,2591
|
| 627 |
+
pip/_vendor/pygments/regexopt.py,sha256=jg1ALogcYGU96TQS9isBl6dCrvw5y5--BP_K-uFk_8s,3072
|
| 628 |
+
pip/_vendor/pygments/scanner.py,sha256=b_nu5_f3HCgSdp5S_aNRBQ1MSCm4ZjDwec2OmTRickw,3092
|
| 629 |
+
pip/_vendor/pygments/sphinxext.py,sha256=wBFYm180qea9JKt__UzhRlNRNhczPDFDaqGD21sbuso,6882
|
| 630 |
+
pip/_vendor/pygments/style.py,sha256=C4qyoJrUTkq-OV3iO-8Vz3UtWYpJwSTdh5_vlGCGdNQ,6257
|
| 631 |
+
pip/_vendor/pygments/styles/__init__.py,sha256=he7HjQx7sC0d2kfTVLjUs0J15mtToJM6M1brwIm9--Q,3700
|
| 632 |
+
pip/_vendor/pygments/styles/__pycache__/__init__.cpython-312.pyc,,
|
| 633 |
+
pip/_vendor/pygments/token.py,sha256=seNsmcch9OEHXYirh8Ool7w8xDhfNTbLj5rHAC-gc_o,6184
|
| 634 |
+
pip/_vendor/pygments/unistring.py,sha256=FaUfG14NBJEKLQoY9qj6JYeXrpYcLmKulghdxOGFaOc,63223
|
| 635 |
+
pip/_vendor/pygments/util.py,sha256=AEVY0qonyyEMgv4Do2dINrrqUAwUk2XYSqHM650uzek,10230
|
| 636 |
+
pip/_vendor/pyparsing/__init__.py,sha256=9m1JbE2JTLdBG0Mb6B0lEaZj181Wx5cuPXZpsbHEYgE,9116
|
| 637 |
+
pip/_vendor/pyparsing/__pycache__/__init__.cpython-312.pyc,,
|
| 638 |
+
pip/_vendor/pyparsing/__pycache__/actions.cpython-312.pyc,,
|
| 639 |
+
pip/_vendor/pyparsing/__pycache__/common.cpython-312.pyc,,
|
| 640 |
+
pip/_vendor/pyparsing/__pycache__/core.cpython-312.pyc,,
|
| 641 |
+
pip/_vendor/pyparsing/__pycache__/exceptions.cpython-312.pyc,,
|
| 642 |
+
pip/_vendor/pyparsing/__pycache__/helpers.cpython-312.pyc,,
|
| 643 |
+
pip/_vendor/pyparsing/__pycache__/results.cpython-312.pyc,,
|
| 644 |
+
pip/_vendor/pyparsing/__pycache__/testing.cpython-312.pyc,,
|
| 645 |
+
pip/_vendor/pyparsing/__pycache__/unicode.cpython-312.pyc,,
|
| 646 |
+
pip/_vendor/pyparsing/__pycache__/util.cpython-312.pyc,,
|
| 647 |
+
pip/_vendor/pyparsing/actions.py,sha256=05uaIPOznJPQ7VgRdmGCmG4sDnUPtwgv5qOYIqbL2UY,6567
|
| 648 |
+
pip/_vendor/pyparsing/common.py,sha256=p-3c83E5-DjlkF35G0O9-kjQRpoejP-2_z0hxZ-eol4,13387
|
| 649 |
+
pip/_vendor/pyparsing/core.py,sha256=yvuRlLpXSF8mgk-QhiW3OVLqD9T0rsj9tbibhRH4Yaw,224445
|
| 650 |
+
pip/_vendor/pyparsing/diagram/__init__.py,sha256=nxmDOoYF9NXuLaGYy01tKFjkNReWJlrGFuJNWEiTo84,24215
|
| 651 |
+
pip/_vendor/pyparsing/diagram/__pycache__/__init__.cpython-312.pyc,,
|
| 652 |
+
pip/_vendor/pyparsing/exceptions.py,sha256=6Jc6W1eDZBzyFu1J0YrcdNFVBC-RINujZmveSnB8Rxw,9523
|
| 653 |
+
pip/_vendor/pyparsing/helpers.py,sha256=BZJHCA8SS0pYio30KGQTc9w2qMOaK4YpZ7hcvHbnTgk,38646
|
| 654 |
+
pip/_vendor/pyparsing/results.py,sha256=9dyqQ-w3MjfmxWbFt8KEPU6IfXeyRdoWp2Og802rUQY,26692
|
| 655 |
+
pip/_vendor/pyparsing/testing.py,sha256=eJncg0p83zm1FTPvM9auNT6oavIvXaibmRFDf1qmwkY,13488
|
| 656 |
+
pip/_vendor/pyparsing/unicode.py,sha256=fAPdsJiARFbkPAih6NkYry0dpj4jPqelGVMlE4wWFW8,10646
|
| 657 |
+
pip/_vendor/pyparsing/util.py,sha256=vTMzTdwSDyV8d_dSgquUTdWgBFoA_W30nfxEJDsshRQ,8670
|
| 658 |
+
pip/_vendor/pyproject_hooks/__init__.py,sha256=kCehmy0UaBa9oVMD7ZIZrnswfnP3LXZ5lvnNJAL5JBM,491
|
| 659 |
+
pip/_vendor/pyproject_hooks/__pycache__/__init__.cpython-312.pyc,,
|
| 660 |
+
pip/_vendor/pyproject_hooks/__pycache__/_compat.cpython-312.pyc,,
|
| 661 |
+
pip/_vendor/pyproject_hooks/__pycache__/_impl.cpython-312.pyc,,
|
| 662 |
+
pip/_vendor/pyproject_hooks/_compat.py,sha256=by6evrYnqkisiM-MQcvOKs5bgDMzlOSgZqRHNqf04zE,138
|
| 663 |
+
pip/_vendor/pyproject_hooks/_impl.py,sha256=61GJxzQip0IInhuO69ZI5GbNQ82XEDUB_1Gg5_KtUoc,11920
|
| 664 |
+
pip/_vendor/pyproject_hooks/_in_process/__init__.py,sha256=9gQATptbFkelkIy0OfWFEACzqxXJMQDWCH9rBOAZVwQ,546
|
| 665 |
+
pip/_vendor/pyproject_hooks/_in_process/__pycache__/__init__.cpython-312.pyc,,
|
| 666 |
+
pip/_vendor/pyproject_hooks/_in_process/__pycache__/_in_process.cpython-312.pyc,,
|
| 667 |
+
pip/_vendor/pyproject_hooks/_in_process/_in_process.py,sha256=m2b34c917IW5o-Q_6TYIHlsK9lSUlNiyrITTUH_zwew,10927
|
| 668 |
+
pip/_vendor/requests/__init__.py,sha256=owujob4dk45Siy4EYtbCKR6wcFph7E04a_v_OuAacBA,5169
|
| 669 |
+
pip/_vendor/requests/__pycache__/__init__.cpython-312.pyc,,
|
| 670 |
+
pip/_vendor/requests/__pycache__/__version__.cpython-312.pyc,,
|
| 671 |
+
pip/_vendor/requests/__pycache__/_internal_utils.cpython-312.pyc,,
|
| 672 |
+
pip/_vendor/requests/__pycache__/adapters.cpython-312.pyc,,
|
| 673 |
+
pip/_vendor/requests/__pycache__/api.cpython-312.pyc,,
|
| 674 |
+
pip/_vendor/requests/__pycache__/auth.cpython-312.pyc,,
|
| 675 |
+
pip/_vendor/requests/__pycache__/certs.cpython-312.pyc,,
|
| 676 |
+
pip/_vendor/requests/__pycache__/compat.cpython-312.pyc,,
|
| 677 |
+
pip/_vendor/requests/__pycache__/cookies.cpython-312.pyc,,
|
| 678 |
+
pip/_vendor/requests/__pycache__/exceptions.cpython-312.pyc,,
|
| 679 |
+
pip/_vendor/requests/__pycache__/help.cpython-312.pyc,,
|
| 680 |
+
pip/_vendor/requests/__pycache__/hooks.cpython-312.pyc,,
|
| 681 |
+
pip/_vendor/requests/__pycache__/models.cpython-312.pyc,,
|
| 682 |
+
pip/_vendor/requests/__pycache__/packages.cpython-312.pyc,,
|
| 683 |
+
pip/_vendor/requests/__pycache__/sessions.cpython-312.pyc,,
|
| 684 |
+
pip/_vendor/requests/__pycache__/status_codes.cpython-312.pyc,,
|
| 685 |
+
pip/_vendor/requests/__pycache__/structures.cpython-312.pyc,,
|
| 686 |
+
pip/_vendor/requests/__pycache__/utils.cpython-312.pyc,,
|
| 687 |
+
pip/_vendor/requests/__version__.py,sha256=ssI3Ezt7PaxgkOW45GhtwPUclo_SO_ygtIm4A74IOfw,435
|
| 688 |
+
pip/_vendor/requests/_internal_utils.py,sha256=nMQymr4hs32TqVo5AbCrmcJEhvPUh7xXlluyqwslLiQ,1495
|
| 689 |
+
pip/_vendor/requests/adapters.py,sha256=idj6cZcId3L5xNNeJ7ieOLtw3awJk5A64xUfetHwq3M,19697
|
| 690 |
+
pip/_vendor/requests/api.py,sha256=q61xcXq4tmiImrvcSVLTbFyCiD2F-L_-hWKGbz4y8vg,6449
|
| 691 |
+
pip/_vendor/requests/auth.py,sha256=h-HLlVx9j8rKV5hfSAycP2ApOSglTz77R0tz7qCbbEE,10187
|
| 692 |
+
pip/_vendor/requests/certs.py,sha256=PVPooB0jP5hkZEULSCwC074532UFbR2Ptgu0I5zwmCs,575
|
| 693 |
+
pip/_vendor/requests/compat.py,sha256=IhK9quyX0RRuWTNcg6d2JGSAOUbM6mym2p_2XjLTwf4,1286
|
| 694 |
+
pip/_vendor/requests/cookies.py,sha256=kD3kNEcCj-mxbtf5fJsSaT86eGoEYpD3X0CSgpzl7BM,18560
|
| 695 |
+
pip/_vendor/requests/exceptions.py,sha256=FA-_kVwBZ2jhXauRctN_ewHVK25b-fj0Azyz1THQ0Kk,3823
|
| 696 |
+
pip/_vendor/requests/help.py,sha256=FnAAklv8MGm_qb2UilDQgS6l0cUttiCFKUjx0zn2XNA,3879
|
| 697 |
+
pip/_vendor/requests/hooks.py,sha256=CiuysiHA39V5UfcCBXFIx83IrDpuwfN9RcTUgv28ftQ,733
|
| 698 |
+
pip/_vendor/requests/models.py,sha256=dDZ-iThotky-Noq9yy97cUEJhr3wnY6mv-xR_ePg_lk,35288
|
| 699 |
+
pip/_vendor/requests/packages.py,sha256=njJmVifY4aSctuW3PP5EFRCxjEwMRDO6J_feG2dKWsI,695
|
| 700 |
+
pip/_vendor/requests/sessions.py,sha256=-LvTzrPtetSTrR3buxu4XhdgMrJFLB1q5D7P--L2Xhw,30373
|
| 701 |
+
pip/_vendor/requests/status_codes.py,sha256=FvHmT5uH-_uimtRz5hH9VCbt7VV-Nei2J9upbej6j8g,4235
|
| 702 |
+
pip/_vendor/requests/structures.py,sha256=-IbmhVz06S-5aPSZuUthZ6-6D9XOjRuTXHOabY041XM,2912
|
| 703 |
+
pip/_vendor/requests/utils.py,sha256=BvQDKkLuXCSaVfSW_1blUN0IzJSfNC8njNr8vhKj76Y,33189
|
| 704 |
+
pip/_vendor/resolvelib/__init__.py,sha256=h509TdEcpb5-44JonaU3ex2TM15GVBLjM9CNCPwnTTs,537
|
| 705 |
+
pip/_vendor/resolvelib/__pycache__/__init__.cpython-312.pyc,,
|
| 706 |
+
pip/_vendor/resolvelib/__pycache__/providers.cpython-312.pyc,,
|
| 707 |
+
pip/_vendor/resolvelib/__pycache__/reporters.cpython-312.pyc,,
|
| 708 |
+
pip/_vendor/resolvelib/__pycache__/resolvers.cpython-312.pyc,,
|
| 709 |
+
pip/_vendor/resolvelib/__pycache__/structs.cpython-312.pyc,,
|
| 710 |
+
pip/_vendor/resolvelib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 711 |
+
pip/_vendor/resolvelib/compat/__pycache__/__init__.cpython-312.pyc,,
|
| 712 |
+
pip/_vendor/resolvelib/compat/__pycache__/collections_abc.cpython-312.pyc,,
|
| 713 |
+
pip/_vendor/resolvelib/compat/collections_abc.py,sha256=uy8xUZ-NDEw916tugUXm8HgwCGiMO0f-RcdnpkfXfOs,156
|
| 714 |
+
pip/_vendor/resolvelib/providers.py,sha256=fuuvVrCetu5gsxPB43ERyjfO8aReS3rFQHpDgiItbs4,5871
|
| 715 |
+
pip/_vendor/resolvelib/reporters.py,sha256=TSbRmWzTc26w0ggsV1bxVpeWDB8QNIre6twYl7GIZBE,1601
|
| 716 |
+
pip/_vendor/resolvelib/resolvers.py,sha256=G8rsLZSq64g5VmIq-lB7UcIJ1gjAxIQJmTF4REZleQ0,20511
|
| 717 |
+
pip/_vendor/resolvelib/structs.py,sha256=0_1_XO8z_CLhegP3Vpf9VJ3zJcfLm0NOHRM-i0Ykz3o,4963
|
| 718 |
+
pip/_vendor/rich/__init__.py,sha256=dRxjIL-SbFVY0q3IjSMrfgBTHrm1LZDgLOygVBwiYZc,6090
|
| 719 |
+
pip/_vendor/rich/__main__.py,sha256=TT8sb9PTnsnKhhrGuHkLN0jdN0dtKhtPkEr9CidDbPM,8478
|
| 720 |
+
pip/_vendor/rich/__pycache__/__init__.cpython-312.pyc,,
|
| 721 |
+
pip/_vendor/rich/__pycache__/__main__.cpython-312.pyc,,
|
| 722 |
+
pip/_vendor/rich/__pycache__/_cell_widths.cpython-312.pyc,,
|
| 723 |
+
pip/_vendor/rich/__pycache__/_emoji_codes.cpython-312.pyc,,
|
| 724 |
+
pip/_vendor/rich/__pycache__/_emoji_replace.cpython-312.pyc,,
|
| 725 |
+
pip/_vendor/rich/__pycache__/_export_format.cpython-312.pyc,,
|
| 726 |
+
pip/_vendor/rich/__pycache__/_extension.cpython-312.pyc,,
|
| 727 |
+
pip/_vendor/rich/__pycache__/_fileno.cpython-312.pyc,,
|
| 728 |
+
pip/_vendor/rich/__pycache__/_inspect.cpython-312.pyc,,
|
| 729 |
+
pip/_vendor/rich/__pycache__/_log_render.cpython-312.pyc,,
|
| 730 |
+
pip/_vendor/rich/__pycache__/_loop.cpython-312.pyc,,
|
| 731 |
+
pip/_vendor/rich/__pycache__/_null_file.cpython-312.pyc,,
|
| 732 |
+
pip/_vendor/rich/__pycache__/_palettes.cpython-312.pyc,,
|
| 733 |
+
pip/_vendor/rich/__pycache__/_pick.cpython-312.pyc,,
|
| 734 |
+
pip/_vendor/rich/__pycache__/_ratio.cpython-312.pyc,,
|
| 735 |
+
pip/_vendor/rich/__pycache__/_spinners.cpython-312.pyc,,
|
| 736 |
+
pip/_vendor/rich/__pycache__/_stack.cpython-312.pyc,,
|
| 737 |
+
pip/_vendor/rich/__pycache__/_timer.cpython-312.pyc,,
|
| 738 |
+
pip/_vendor/rich/__pycache__/_win32_console.cpython-312.pyc,,
|
| 739 |
+
pip/_vendor/rich/__pycache__/_windows.cpython-312.pyc,,
|
| 740 |
+
pip/_vendor/rich/__pycache__/_windows_renderer.cpython-312.pyc,,
|
| 741 |
+
pip/_vendor/rich/__pycache__/_wrap.cpython-312.pyc,,
|
| 742 |
+
pip/_vendor/rich/__pycache__/abc.cpython-312.pyc,,
|
| 743 |
+
pip/_vendor/rich/__pycache__/align.cpython-312.pyc,,
|
| 744 |
+
pip/_vendor/rich/__pycache__/ansi.cpython-312.pyc,,
|
| 745 |
+
pip/_vendor/rich/__pycache__/bar.cpython-312.pyc,,
|
| 746 |
+
pip/_vendor/rich/__pycache__/box.cpython-312.pyc,,
|
| 747 |
+
pip/_vendor/rich/__pycache__/cells.cpython-312.pyc,,
|
| 748 |
+
pip/_vendor/rich/__pycache__/color.cpython-312.pyc,,
|
| 749 |
+
pip/_vendor/rich/__pycache__/color_triplet.cpython-312.pyc,,
|
| 750 |
+
pip/_vendor/rich/__pycache__/columns.cpython-312.pyc,,
|
| 751 |
+
pip/_vendor/rich/__pycache__/console.cpython-312.pyc,,
|
| 752 |
+
pip/_vendor/rich/__pycache__/constrain.cpython-312.pyc,,
|
| 753 |
+
pip/_vendor/rich/__pycache__/containers.cpython-312.pyc,,
|
| 754 |
+
pip/_vendor/rich/__pycache__/control.cpython-312.pyc,,
|
| 755 |
+
pip/_vendor/rich/__pycache__/default_styles.cpython-312.pyc,,
|
| 756 |
+
pip/_vendor/rich/__pycache__/diagnose.cpython-312.pyc,,
|
| 757 |
+
pip/_vendor/rich/__pycache__/emoji.cpython-312.pyc,,
|
| 758 |
+
pip/_vendor/rich/__pycache__/errors.cpython-312.pyc,,
|
| 759 |
+
pip/_vendor/rich/__pycache__/file_proxy.cpython-312.pyc,,
|
| 760 |
+
pip/_vendor/rich/__pycache__/filesize.cpython-312.pyc,,
|
| 761 |
+
pip/_vendor/rich/__pycache__/highlighter.cpython-312.pyc,,
|
| 762 |
+
pip/_vendor/rich/__pycache__/json.cpython-312.pyc,,
|
| 763 |
+
pip/_vendor/rich/__pycache__/jupyter.cpython-312.pyc,,
|
| 764 |
+
pip/_vendor/rich/__pycache__/layout.cpython-312.pyc,,
|
| 765 |
+
pip/_vendor/rich/__pycache__/live.cpython-312.pyc,,
|
| 766 |
+
pip/_vendor/rich/__pycache__/live_render.cpython-312.pyc,,
|
| 767 |
+
pip/_vendor/rich/__pycache__/logging.cpython-312.pyc,,
|
| 768 |
+
pip/_vendor/rich/__pycache__/markup.cpython-312.pyc,,
|
| 769 |
+
pip/_vendor/rich/__pycache__/measure.cpython-312.pyc,,
|
| 770 |
+
pip/_vendor/rich/__pycache__/padding.cpython-312.pyc,,
|
| 771 |
+
pip/_vendor/rich/__pycache__/pager.cpython-312.pyc,,
|
| 772 |
+
pip/_vendor/rich/__pycache__/palette.cpython-312.pyc,,
|
| 773 |
+
pip/_vendor/rich/__pycache__/panel.cpython-312.pyc,,
|
| 774 |
+
pip/_vendor/rich/__pycache__/pretty.cpython-312.pyc,,
|
| 775 |
+
pip/_vendor/rich/__pycache__/progress.cpython-312.pyc,,
|
| 776 |
+
pip/_vendor/rich/__pycache__/progress_bar.cpython-312.pyc,,
|
| 777 |
+
pip/_vendor/rich/__pycache__/prompt.cpython-312.pyc,,
|
| 778 |
+
pip/_vendor/rich/__pycache__/protocol.cpython-312.pyc,,
|
| 779 |
+
pip/_vendor/rich/__pycache__/region.cpython-312.pyc,,
|
| 780 |
+
pip/_vendor/rich/__pycache__/repr.cpython-312.pyc,,
|
| 781 |
+
pip/_vendor/rich/__pycache__/rule.cpython-312.pyc,,
|
| 782 |
+
pip/_vendor/rich/__pycache__/scope.cpython-312.pyc,,
|
| 783 |
+
pip/_vendor/rich/__pycache__/screen.cpython-312.pyc,,
|
| 784 |
+
pip/_vendor/rich/__pycache__/segment.cpython-312.pyc,,
|
| 785 |
+
pip/_vendor/rich/__pycache__/spinner.cpython-312.pyc,,
|
| 786 |
+
pip/_vendor/rich/__pycache__/status.cpython-312.pyc,,
|
| 787 |
+
pip/_vendor/rich/__pycache__/style.cpython-312.pyc,,
|
| 788 |
+
pip/_vendor/rich/__pycache__/styled.cpython-312.pyc,,
|
| 789 |
+
pip/_vendor/rich/__pycache__/syntax.cpython-312.pyc,,
|
| 790 |
+
pip/_vendor/rich/__pycache__/table.cpython-312.pyc,,
|
| 791 |
+
pip/_vendor/rich/__pycache__/terminal_theme.cpython-312.pyc,,
|
| 792 |
+
pip/_vendor/rich/__pycache__/text.cpython-312.pyc,,
|
| 793 |
+
pip/_vendor/rich/__pycache__/theme.cpython-312.pyc,,
|
| 794 |
+
pip/_vendor/rich/__pycache__/themes.cpython-312.pyc,,
|
| 795 |
+
pip/_vendor/rich/__pycache__/traceback.cpython-312.pyc,,
|
| 796 |
+
pip/_vendor/rich/__pycache__/tree.cpython-312.pyc,,
|
| 797 |
+
pip/_vendor/rich/_cell_widths.py,sha256=2n4EiJi3X9sqIq0O16kUZ_zy6UYMd3xFfChlKfnW1Hc,10096
|
| 798 |
+
pip/_vendor/rich/_emoji_codes.py,sha256=hu1VL9nbVdppJrVoijVshRlcRRe_v3dju3Mmd2sKZdY,140235
|
| 799 |
+
pip/_vendor/rich/_emoji_replace.py,sha256=n-kcetsEUx2ZUmhQrfeMNc-teeGhpuSQ5F8VPBsyvDo,1064
|
| 800 |
+
pip/_vendor/rich/_export_format.py,sha256=qxgV3nKnXQu1hfbnRVswPYy-AwIg1X0LSC47cK5s8jk,2100
|
| 801 |
+
pip/_vendor/rich/_extension.py,sha256=Xt47QacCKwYruzjDi-gOBq724JReDj9Cm9xUi5fr-34,265
|
| 802 |
+
pip/_vendor/rich/_fileno.py,sha256=HWZxP5C2ajMbHryvAQZseflVfQoGzsKOHzKGsLD8ynQ,799
|
| 803 |
+
pip/_vendor/rich/_inspect.py,sha256=oZJGw31e64dwXSCmrDnvZbwVb1ZKhWfU8wI3VWohjJk,9695
|
| 804 |
+
pip/_vendor/rich/_log_render.py,sha256=1ByI0PA1ZpxZY3CGJOK54hjlq4X-Bz_boIjIqCd8Kns,3225
|
| 805 |
+
pip/_vendor/rich/_loop.py,sha256=hV_6CLdoPm0va22Wpw4zKqM0RYsz3TZxXj0PoS-9eDQ,1236
|
| 806 |
+
pip/_vendor/rich/_null_file.py,sha256=tGSXk_v-IZmbj1GAzHit8A3kYIQMiCpVsCFfsC-_KJ4,1387
|
| 807 |
+
pip/_vendor/rich/_palettes.py,sha256=cdev1JQKZ0JvlguV9ipHgznTdnvlIzUFDBb0It2PzjI,7063
|
| 808 |
+
pip/_vendor/rich/_pick.py,sha256=evDt8QN4lF5CiwrUIXlOJCntitBCOsI3ZLPEIAVRLJU,423
|
| 809 |
+
pip/_vendor/rich/_ratio.py,sha256=2lLSliL025Y-YMfdfGbutkQDevhcyDqc-DtUYW9mU70,5472
|
| 810 |
+
pip/_vendor/rich/_spinners.py,sha256=U2r1_g_1zSjsjiUdAESc2iAMc3i4ri_S8PYP6kQ5z1I,19919
|
| 811 |
+
pip/_vendor/rich/_stack.py,sha256=-C8OK7rxn3sIUdVwxZBBpeHhIzX0eI-VM3MemYfaXm0,351
|
| 812 |
+
pip/_vendor/rich/_timer.py,sha256=zelxbT6oPFZnNrwWPpc1ktUeAT-Vc4fuFcRZLQGLtMI,417
|
| 813 |
+
pip/_vendor/rich/_win32_console.py,sha256=P0vxI2fcndym1UU1S37XAzQzQnkyY7YqAKmxm24_gug,22820
|
| 814 |
+
pip/_vendor/rich/_windows.py,sha256=dvNl9TmfPzNVxiKk5WDFihErZ5796g2UC9-KGGyfXmk,1926
|
| 815 |
+
pip/_vendor/rich/_windows_renderer.py,sha256=t74ZL3xuDCP3nmTp9pH1L5LiI2cakJuQRQleHCJerlk,2783
|
| 816 |
+
pip/_vendor/rich/_wrap.py,sha256=xfV_9t0Sg6rzimmrDru8fCVmUlalYAcHLDfrJZnbbwQ,1840
|
| 817 |
+
pip/_vendor/rich/abc.py,sha256=ON-E-ZqSSheZ88VrKX2M3PXpFbGEUUZPMa_Af0l-4f0,890
|
| 818 |
+
pip/_vendor/rich/align.py,sha256=Ji-Yokfkhnfe_xMmr4ISjZB07TJXggBCOYoYa-HDAr8,10368
|
| 819 |
+
pip/_vendor/rich/ansi.py,sha256=iD6532QYqnBm6hADulKjrV8l8kFJ-9fEVooHJHH3hMg,6906
|
| 820 |
+
pip/_vendor/rich/bar.py,sha256=a7UD303BccRCrEhGjfMElpv5RFYIinaAhAuqYqhUvmw,3264
|
| 821 |
+
pip/_vendor/rich/box.py,sha256=FJ6nI3jD7h2XNFU138bJUt2HYmWOlRbltoCEuIAZhew,9842
|
| 822 |
+
pip/_vendor/rich/cells.py,sha256=627ztJs9zOL-38HJ7kXBerR-gT8KBfYC8UzEwMJDYYo,4509
|
| 823 |
+
pip/_vendor/rich/color.py,sha256=9Gh958U3f75WVdLTeC0U9nkGTn2n0wnojKpJ6jQEkIE,18224
|
| 824 |
+
pip/_vendor/rich/color_triplet.py,sha256=3lhQkdJbvWPoLDO-AnYImAWmJvV5dlgYNCVZ97ORaN4,1054
|
| 825 |
+
pip/_vendor/rich/columns.py,sha256=HUX0KcMm9dsKNi11fTbiM_h2iDtl8ySCaVcxlalEzq8,7131
|
| 826 |
+
pip/_vendor/rich/console.py,sha256=pDvkbLkvtZIMIwQx_jkZ-seyNl4zGBLviXoWXte9fwg,99218
|
| 827 |
+
pip/_vendor/rich/constrain.py,sha256=1VIPuC8AgtKWrcncQrjBdYqA3JVWysu6jZo1rrh7c7Q,1288
|
| 828 |
+
pip/_vendor/rich/containers.py,sha256=aKgm5UDHn5Nmui6IJaKdsZhbHClh_X7D-_Wg8Ehrr7s,5497
|
| 829 |
+
pip/_vendor/rich/control.py,sha256=DSkHTUQLorfSERAKE_oTAEUFefZnZp4bQb4q8rHbKws,6630
|
| 830 |
+
pip/_vendor/rich/default_styles.py,sha256=-Fe318kMVI_IwciK5POpThcO0-9DYJ67TZAN6DlmlmM,8082
|
| 831 |
+
pip/_vendor/rich/diagnose.py,sha256=an6uouwhKPAlvQhYpNNpGq9EJysfMIOvvCbO3oSoR24,972
|
| 832 |
+
pip/_vendor/rich/emoji.py,sha256=omTF9asaAnsM4yLY94eR_9dgRRSm1lHUszX20D1yYCQ,2501
|
| 833 |
+
pip/_vendor/rich/errors.py,sha256=5pP3Kc5d4QJ_c0KFsxrfyhjiPVe7J1zOqSFbFAzcV-Y,642
|
| 834 |
+
pip/_vendor/rich/file_proxy.py,sha256=Tl9THMDZ-Pk5Wm8sI1gGg_U5DhusmxD-FZ0fUbcU0W0,1683
|
| 835 |
+
pip/_vendor/rich/filesize.py,sha256=9fTLAPCAwHmBXdRv7KZU194jSgNrRb6Wx7RIoBgqeKY,2508
|
| 836 |
+
pip/_vendor/rich/highlighter.py,sha256=p3C1g4QYzezFKdR7NF9EhPbzQDvdPUhGRgSyGGEmPko,9584
|
| 837 |
+
pip/_vendor/rich/json.py,sha256=EYp9ucj-nDjYDkHCV6Mk1ve8nUOpuFLaW76X50Mis2M,5032
|
| 838 |
+
pip/_vendor/rich/jupyter.py,sha256=QyoKoE_8IdCbrtiSHp9TsTSNyTHY0FO5whE7jOTd9UE,3252
|
| 839 |
+
pip/_vendor/rich/layout.py,sha256=RFYL6HdCFsHf9WRpcvi3w-fpj-8O5dMZ8W96VdKNdbI,14007
|
| 840 |
+
pip/_vendor/rich/live.py,sha256=vZzYvu7fqwlv3Gthl2xiw1Dc_O80VlGcCV0DOHwCyDM,14273
|
| 841 |
+
pip/_vendor/rich/live_render.py,sha256=zElm3PrfSIvjOce28zETHMIUf9pFYSUA5o0AflgUP64,3667
|
| 842 |
+
pip/_vendor/rich/logging.py,sha256=uB-cB-3Q4bmXDLLpbOWkmFviw-Fde39zyMV6tKJ2WHQ,11903
|
| 843 |
+
pip/_vendor/rich/markup.py,sha256=xzF4uAafiEeEYDJYt_vUnJOGoTU8RrH-PH7WcWYXjCg,8198
|
| 844 |
+
pip/_vendor/rich/measure.py,sha256=HmrIJX8sWRTHbgh8MxEay_83VkqNW_70s8aKP5ZcYI8,5305
|
| 845 |
+
pip/_vendor/rich/padding.py,sha256=kTFGsdGe0os7tXLnHKpwTI90CXEvrceeZGCshmJy5zw,4970
|
| 846 |
+
pip/_vendor/rich/pager.py,sha256=SO_ETBFKbg3n_AgOzXm41Sv36YxXAyI3_R-KOY2_uSc,828
|
| 847 |
+
pip/_vendor/rich/palette.py,sha256=lInvR1ODDT2f3UZMfL1grq7dY_pDdKHw4bdUgOGaM4Y,3396
|
| 848 |
+
pip/_vendor/rich/panel.py,sha256=wGMe40J8KCGgQoM0LyjRErmGIkv2bsYA71RCXThD0xE,10574
|
| 849 |
+
pip/_vendor/rich/pretty.py,sha256=eLEYN9xVaMNuA6EJVYm4li7HdOHxCqmVKvnOqJpyFt0,35852
|
| 850 |
+
pip/_vendor/rich/progress.py,sha256=n4KF9vky8_5iYeXcyZPEvzyLplWlDvFLkM5JI0Bs08A,59706
|
| 851 |
+
pip/_vendor/rich/progress_bar.py,sha256=cEoBfkc3lLwqba4XKsUpy4vSQKDh2QQ5J2J94-ACFoo,8165
|
| 852 |
+
pip/_vendor/rich/prompt.py,sha256=x0mW-pIPodJM4ry6grgmmLrl8VZp99kqcmdnBe70YYA,11303
|
| 853 |
+
pip/_vendor/rich/protocol.py,sha256=5hHHDDNHckdk8iWH5zEbi-zuIVSF5hbU2jIo47R7lTE,1391
|
| 854 |
+
pip/_vendor/rich/region.py,sha256=rNT9xZrVZTYIXZC0NYn41CJQwYNbR-KecPOxTgQvB8Y,166
|
| 855 |
+
pip/_vendor/rich/repr.py,sha256=9Z8otOmM-tyxnyTodvXlectP60lwahjGiDTrbrxPSTg,4431
|
| 856 |
+
pip/_vendor/rich/rule.py,sha256=0fNaS_aERa3UMRc3T5WMpN_sumtDxfaor2y3of1ftBk,4602
|
| 857 |
+
pip/_vendor/rich/scope.py,sha256=TMUU8qo17thyqQCPqjDLYpg_UU1k5qVd-WwiJvnJVas,2843
|
| 858 |
+
pip/_vendor/rich/screen.py,sha256=YoeReESUhx74grqb0mSSb9lghhysWmFHYhsbMVQjXO8,1591
|
| 859 |
+
pip/_vendor/rich/segment.py,sha256=XLnJEFvcV3bjaVzMNUJiem3n8lvvI9TJ5PTu-IG2uTg,24247
|
| 860 |
+
pip/_vendor/rich/spinner.py,sha256=15koCmF0DQeD8-k28Lpt6X_zJQUlzEhgo_6A6uy47lc,4339
|
| 861 |
+
pip/_vendor/rich/status.py,sha256=gJsIXIZeSo3urOyxRUjs6VrhX5CZrA0NxIQ-dxhCnwo,4425
|
| 862 |
+
pip/_vendor/rich/style.py,sha256=3hiocH_4N8vwRm3-8yFWzM7tSwjjEven69XqWasSQwM,27073
|
| 863 |
+
pip/_vendor/rich/styled.py,sha256=eZNnzGrI4ki_54pgY3Oj0T-x3lxdXTYh4_ryDB24wBU,1258
|
| 864 |
+
pip/_vendor/rich/syntax.py,sha256=jgDiVCK6cpR0NmBOpZmIu-Ud4eaW7fHvjJZkDbjpcSA,35173
|
| 865 |
+
pip/_vendor/rich/table.py,sha256=-WzesL-VJKsaiDU3uyczpJMHy6VCaSewBYJwx8RudI8,39684
|
| 866 |
+
pip/_vendor/rich/terminal_theme.py,sha256=1j5-ufJfnvlAo5Qsi_ACZiXDmwMXzqgmFByObT9-yJY,3370
|
| 867 |
+
pip/_vendor/rich/text.py,sha256=_8JBlSau0c2z8ENOZMi1hJ7M1ZGY408E4-hXjHyyg1A,45525
|
| 868 |
+
pip/_vendor/rich/theme.py,sha256=belFJogzA0W0HysQabKaHOc3RWH2ko3fQAJhoN-AFdo,3777
|
| 869 |
+
pip/_vendor/rich/themes.py,sha256=0xgTLozfabebYtcJtDdC5QkX5IVUEaviqDUJJh4YVFk,102
|
| 870 |
+
pip/_vendor/rich/traceback.py,sha256=yCLVrCtyoFNENd9mkm2xeG3KmqkTwH9xpFOO7p2Bq0A,29604
|
| 871 |
+
pip/_vendor/rich/tree.py,sha256=BMbUYNjS9uodNPfvtY_odmU09GA5QzcMbQ5cJZhllQI,9169
|
| 872 |
+
pip/_vendor/six.py,sha256=TOOfQi7nFGfMrIvtdr6wX4wyHH8M7aknmuLfo2cBBrM,34549
|
| 873 |
+
pip/_vendor/tenacity/__init__.py,sha256=3kvAL6KClq8GFo2KFhmOzskRKSDQI-ubrlfZ8AQEEI0,20493
|
| 874 |
+
pip/_vendor/tenacity/__pycache__/__init__.cpython-312.pyc,,
|
| 875 |
+
pip/_vendor/tenacity/__pycache__/_asyncio.cpython-312.pyc,,
|
| 876 |
+
pip/_vendor/tenacity/__pycache__/_utils.cpython-312.pyc,,
|
| 877 |
+
pip/_vendor/tenacity/__pycache__/after.cpython-312.pyc,,
|
| 878 |
+
pip/_vendor/tenacity/__pycache__/before.cpython-312.pyc,,
|
| 879 |
+
pip/_vendor/tenacity/__pycache__/before_sleep.cpython-312.pyc,,
|
| 880 |
+
pip/_vendor/tenacity/__pycache__/nap.cpython-312.pyc,,
|
| 881 |
+
pip/_vendor/tenacity/__pycache__/retry.cpython-312.pyc,,
|
| 882 |
+
pip/_vendor/tenacity/__pycache__/stop.cpython-312.pyc,,
|
| 883 |
+
pip/_vendor/tenacity/__pycache__/tornadoweb.cpython-312.pyc,,
|
| 884 |
+
pip/_vendor/tenacity/__pycache__/wait.cpython-312.pyc,,
|
| 885 |
+
pip/_vendor/tenacity/_asyncio.py,sha256=Qi6wgQsGa9MQibYRy3OXqcDQswIZZ00dLOoSUGN-6o8,3551
|
| 886 |
+
pip/_vendor/tenacity/_utils.py,sha256=ubs6a7sxj3JDNRKWCyCU2j5r1CB7rgyONgZzYZq6D_4,2179
|
| 887 |
+
pip/_vendor/tenacity/after.py,sha256=S5NCISScPeIrKwIeXRwdJl3kV9Q4nqZfnNPDx6Hf__g,1682
|
| 888 |
+
pip/_vendor/tenacity/before.py,sha256=dIZE9gmBTffisfwNkK0F1xFwGPV41u5GK70UY4Pi5Kc,1562
|
| 889 |
+
pip/_vendor/tenacity/before_sleep.py,sha256=YmpgN9Y7HGlH97U24vvq_YWb5deaK4_DbiD8ZuFmy-E,2372
|
| 890 |
+
pip/_vendor/tenacity/nap.py,sha256=fRWvnz1aIzbIq9Ap3gAkAZgDH6oo5zxMrU6ZOVByq0I,1383
|
| 891 |
+
pip/_vendor/tenacity/retry.py,sha256=jrzD_mxA5mSTUEdiYB7SHpxltjhPSYZSnSRATb-ggRc,8746
|
| 892 |
+
pip/_vendor/tenacity/stop.py,sha256=YMJs7ZgZfND65PRLqlGB_agpfGXlemx_5Hm4PKnBqpQ,3086
|
| 893 |
+
pip/_vendor/tenacity/tornadoweb.py,sha256=po29_F1Mt8qZpsFjX7EVwAT0ydC_NbVia9gVi7R_wXA,2142
|
| 894 |
+
pip/_vendor/tenacity/wait.py,sha256=3FcBJoCDgym12_dN6xfK8C1gROY0Hn4NSI2u8xv50uE,8024
|
| 895 |
+
pip/_vendor/tomli/__init__.py,sha256=JhUwV66DB1g4Hvt1UQCVMdfCu-IgAV8FXmvDU9onxd4,396
|
| 896 |
+
pip/_vendor/tomli/__pycache__/__init__.cpython-312.pyc,,
|
| 897 |
+
pip/_vendor/tomli/__pycache__/_parser.cpython-312.pyc,,
|
| 898 |
+
pip/_vendor/tomli/__pycache__/_re.cpython-312.pyc,,
|
| 899 |
+
pip/_vendor/tomli/__pycache__/_types.cpython-312.pyc,,
|
| 900 |
+
pip/_vendor/tomli/_parser.py,sha256=g9-ENaALS-B8dokYpCuzUFalWlog7T-SIYMjLZSWrtM,22633
|
| 901 |
+
pip/_vendor/tomli/_re.py,sha256=dbjg5ChZT23Ka9z9DHOXfdtSpPwUfdgMXnj8NOoly-w,2943
|
| 902 |
+
pip/_vendor/tomli/_types.py,sha256=-GTG2VUqkpxwMqzmVO4F7ybKddIbAnuAHXfmWQcTi3Q,254
|
| 903 |
+
pip/_vendor/truststore/__init__.py,sha256=qzTLSH8PvAkY1fr6QQ2vV-KwE_M83wdXugtpJaP_AbM,403
|
| 904 |
+
pip/_vendor/truststore/__pycache__/__init__.cpython-312.pyc,,
|
| 905 |
+
pip/_vendor/truststore/__pycache__/_api.cpython-312.pyc,,
|
| 906 |
+
pip/_vendor/truststore/__pycache__/_macos.cpython-312.pyc,,
|
| 907 |
+
pip/_vendor/truststore/__pycache__/_openssl.cpython-312.pyc,,
|
| 908 |
+
pip/_vendor/truststore/__pycache__/_ssl_constants.cpython-312.pyc,,
|
| 909 |
+
pip/_vendor/truststore/__pycache__/_windows.cpython-312.pyc,,
|
| 910 |
+
pip/_vendor/truststore/_api.py,sha256=xjuEu_rlH4hcdJTROImEyOEqdw-F8t5vO2H2BToY0Ro,9893
|
| 911 |
+
pip/_vendor/truststore/_macos.py,sha256=BjvAKoAjXhdIPuxpY124HJIFswDb0pq8DjynzJOVwqc,17694
|
| 912 |
+
pip/_vendor/truststore/_openssl.py,sha256=LLUZ7ZGaio-i5dpKKjKCSeSufmn6T8pi9lDcFnvSyq0,2324
|
| 913 |
+
pip/_vendor/truststore/_ssl_constants.py,sha256=NUD4fVKdSD02ri7-db0tnO0VqLP9aHuzmStcW7tAl08,1130
|
| 914 |
+
pip/_vendor/truststore/_windows.py,sha256=1x_EhROeJ9QK1sMAjfnZC7awYI8UnBJYL-TjACUYI4A,17468
|
| 915 |
+
pip/_vendor/typing_extensions.py,sha256=EWpcpyQnVmc48E9fSyPGs-vXgHcAk9tQABQIxmMsCGk,111130
|
| 916 |
+
pip/_vendor/urllib3/__init__.py,sha256=iXLcYiJySn0GNbWOOZDDApgBL1JgP44EZ8i1760S8Mc,3333
|
| 917 |
+
pip/_vendor/urllib3/__pycache__/__init__.cpython-312.pyc,,
|
| 918 |
+
pip/_vendor/urllib3/__pycache__/_collections.cpython-312.pyc,,
|
| 919 |
+
pip/_vendor/urllib3/__pycache__/_version.cpython-312.pyc,,
|
| 920 |
+
pip/_vendor/urllib3/__pycache__/connection.cpython-312.pyc,,
|
| 921 |
+
pip/_vendor/urllib3/__pycache__/connectionpool.cpython-312.pyc,,
|
| 922 |
+
pip/_vendor/urllib3/__pycache__/exceptions.cpython-312.pyc,,
|
| 923 |
+
pip/_vendor/urllib3/__pycache__/fields.cpython-312.pyc,,
|
| 924 |
+
pip/_vendor/urllib3/__pycache__/filepost.cpython-312.pyc,,
|
| 925 |
+
pip/_vendor/urllib3/__pycache__/poolmanager.cpython-312.pyc,,
|
| 926 |
+
pip/_vendor/urllib3/__pycache__/request.cpython-312.pyc,,
|
| 927 |
+
pip/_vendor/urllib3/__pycache__/response.cpython-312.pyc,,
|
| 928 |
+
pip/_vendor/urllib3/_collections.py,sha256=pyASJJhW7wdOpqJj9QJA8FyGRfr8E8uUUhqUvhF0728,11372
|
| 929 |
+
pip/_vendor/urllib3/_version.py,sha256=azoM7M7BUADl2kBhMVR6PPf2GhBDI90me1fcnzTwdcw,64
|
| 930 |
+
pip/_vendor/urllib3/connection.py,sha256=92k9td_y4PEiTIjNufCUa1NzMB3J3w0LEdyokYgXnW8,20300
|
| 931 |
+
pip/_vendor/urllib3/connectionpool.py,sha256=Be6q65SR9laoikg-h_jmc_p8OWtEmwgq_Om_Xtig-2M,40285
|
| 932 |
+
pip/_vendor/urllib3/contrib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 933 |
+
pip/_vendor/urllib3/contrib/__pycache__/__init__.cpython-312.pyc,,
|
| 934 |
+
pip/_vendor/urllib3/contrib/__pycache__/_appengine_environ.cpython-312.pyc,,
|
| 935 |
+
pip/_vendor/urllib3/contrib/__pycache__/appengine.cpython-312.pyc,,
|
| 936 |
+
pip/_vendor/urllib3/contrib/__pycache__/ntlmpool.cpython-312.pyc,,
|
| 937 |
+
pip/_vendor/urllib3/contrib/__pycache__/pyopenssl.cpython-312.pyc,,
|
| 938 |
+
pip/_vendor/urllib3/contrib/__pycache__/securetransport.cpython-312.pyc,,
|
| 939 |
+
pip/_vendor/urllib3/contrib/__pycache__/socks.cpython-312.pyc,,
|
| 940 |
+
pip/_vendor/urllib3/contrib/_appengine_environ.py,sha256=bDbyOEhW2CKLJcQqAKAyrEHN-aklsyHFKq6vF8ZFsmk,957
|
| 941 |
+
pip/_vendor/urllib3/contrib/_securetransport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 942 |
+
pip/_vendor/urllib3/contrib/_securetransport/__pycache__/__init__.cpython-312.pyc,,
|
| 943 |
+
pip/_vendor/urllib3/contrib/_securetransport/__pycache__/bindings.cpython-312.pyc,,
|
| 944 |
+
pip/_vendor/urllib3/contrib/_securetransport/__pycache__/low_level.cpython-312.pyc,,
|
| 945 |
+
pip/_vendor/urllib3/contrib/_securetransport/bindings.py,sha256=4Xk64qIkPBt09A5q-RIFUuDhNc9mXilVapm7WnYnzRw,17632
|
| 946 |
+
pip/_vendor/urllib3/contrib/_securetransport/low_level.py,sha256=B2JBB2_NRP02xK6DCa1Pa9IuxrPwxzDzZbixQkb7U9M,13922
|
| 947 |
+
pip/_vendor/urllib3/contrib/appengine.py,sha256=VR68eAVE137lxTgjBDwCna5UiBZTOKa01Aj_-5BaCz4,11036
|
| 948 |
+
pip/_vendor/urllib3/contrib/ntlmpool.py,sha256=NlfkW7WMdW8ziqudopjHoW299og1BTWi0IeIibquFwk,4528
|
| 949 |
+
pip/_vendor/urllib3/contrib/pyopenssl.py,sha256=hDJh4MhyY_p-oKlFcYcQaVQRDv6GMmBGuW9yjxyeejM,17081
|
| 950 |
+
pip/_vendor/urllib3/contrib/securetransport.py,sha256=yhZdmVjY6PI6EeFbp7qYOp6-vp1Rkv2NMuOGaEj7pmc,34448
|
| 951 |
+
pip/_vendor/urllib3/contrib/socks.py,sha256=aRi9eWXo9ZEb95XUxef4Z21CFlnnjbEiAo9HOseoMt4,7097
|
| 952 |
+
pip/_vendor/urllib3/exceptions.py,sha256=0Mnno3KHTNfXRfY7638NufOPkUb6mXOm-Lqj-4x2w8A,8217
|
| 953 |
+
pip/_vendor/urllib3/fields.py,sha256=kvLDCg_JmH1lLjUUEY_FLS8UhY7hBvDPuVETbY8mdrM,8579
|
| 954 |
+
pip/_vendor/urllib3/filepost.py,sha256=5b_qqgRHVlL7uLtdAYBzBh-GHmU5AfJVt_2N0XS3PeY,2440
|
| 955 |
+
pip/_vendor/urllib3/packages/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 956 |
+
pip/_vendor/urllib3/packages/__pycache__/__init__.cpython-312.pyc,,
|
| 957 |
+
pip/_vendor/urllib3/packages/__pycache__/six.cpython-312.pyc,,
|
| 958 |
+
pip/_vendor/urllib3/packages/backports/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
| 959 |
+
pip/_vendor/urllib3/packages/backports/__pycache__/__init__.cpython-312.pyc,,
|
| 960 |
+
pip/_vendor/urllib3/packages/backports/__pycache__/makefile.cpython-312.pyc,,
|
| 961 |
+
pip/_vendor/urllib3/packages/backports/__pycache__/weakref_finalize.cpython-312.pyc,,
|
| 962 |
+
pip/_vendor/urllib3/packages/backports/makefile.py,sha256=nbzt3i0agPVP07jqqgjhaYjMmuAi_W5E0EywZivVO8E,1417
|
| 963 |
+
pip/_vendor/urllib3/packages/backports/weakref_finalize.py,sha256=tRCal5OAhNSRyb0DhHp-38AtIlCsRP8BxF3NX-6rqIA,5343
|
| 964 |
+
pip/_vendor/urllib3/packages/six.py,sha256=b9LM0wBXv7E7SrbCjAm4wwN-hrH-iNxv18LgWNMMKPo,34665
|
| 965 |
+
pip/_vendor/urllib3/poolmanager.py,sha256=mJmZWy_Mb4-dHbmNCKbDqv3fZS9UF_2bVDuiECHyPaI,20943
|
| 966 |
+
pip/_vendor/urllib3/request.py,sha256=YTWFNr7QIwh7E1W9dde9LM77v2VWTJ5V78XuTTw7D1A,6691
|
| 967 |
+
pip/_vendor/urllib3/response.py,sha256=fmDJAFkG71uFTn-sVSTh2Iw0WmcXQYqkbRjihvwBjU8,30641
|
| 968 |
+
pip/_vendor/urllib3/util/__init__.py,sha256=JEmSmmqqLyaw8P51gUImZh8Gwg9i1zSe-DoqAitn2nc,1155
|
| 969 |
+
pip/_vendor/urllib3/util/__pycache__/__init__.cpython-312.pyc,,
|
| 970 |
+
pip/_vendor/urllib3/util/__pycache__/connection.cpython-312.pyc,,
|
| 971 |
+
pip/_vendor/urllib3/util/__pycache__/proxy.cpython-312.pyc,,
|
| 972 |
+
pip/_vendor/urllib3/util/__pycache__/queue.cpython-312.pyc,,
|
| 973 |
+
pip/_vendor/urllib3/util/__pycache__/request.cpython-312.pyc,,
|
| 974 |
+
pip/_vendor/urllib3/util/__pycache__/response.cpython-312.pyc,,
|
| 975 |
+
pip/_vendor/urllib3/util/__pycache__/retry.cpython-312.pyc,,
|
| 976 |
+
pip/_vendor/urllib3/util/__pycache__/ssl_.cpython-312.pyc,,
|
| 977 |
+
pip/_vendor/urllib3/util/__pycache__/ssl_match_hostname.cpython-312.pyc,,
|
| 978 |
+
pip/_vendor/urllib3/util/__pycache__/ssltransport.cpython-312.pyc,,
|
| 979 |
+
pip/_vendor/urllib3/util/__pycache__/timeout.cpython-312.pyc,,
|
| 980 |
+
pip/_vendor/urllib3/util/__pycache__/url.cpython-312.pyc,,
|
| 981 |
+
pip/_vendor/urllib3/util/__pycache__/wait.cpython-312.pyc,,
|
| 982 |
+
pip/_vendor/urllib3/util/connection.py,sha256=5Lx2B1PW29KxBn2T0xkN1CBgRBa3gGVJBKoQoRogEVk,4901
|
| 983 |
+
pip/_vendor/urllib3/util/proxy.py,sha256=zUvPPCJrp6dOF0N4GAVbOcl6o-4uXKSrGiTkkr5vUS4,1605
|
| 984 |
+
pip/_vendor/urllib3/util/queue.py,sha256=nRgX8_eX-_VkvxoX096QWoz8Ps0QHUAExILCY_7PncM,498
|
| 985 |
+
pip/_vendor/urllib3/util/request.py,sha256=C0OUt2tcU6LRiQJ7YYNP9GvPrSvl7ziIBekQ-5nlBZk,3997
|
| 986 |
+
pip/_vendor/urllib3/util/response.py,sha256=GJpg3Egi9qaJXRwBh5wv-MNuRWan5BIu40oReoxWP28,3510
|
| 987 |
+
pip/_vendor/urllib3/util/retry.py,sha256=6ENvOZ8PBDzh8kgixpql9lIrb2dxH-k7ZmBanJF2Ng4,22050
|
| 988 |
+
pip/_vendor/urllib3/util/ssl_.py,sha256=X4-AqW91aYPhPx6-xbf66yHFQKbqqfC_5Zt4WkLX1Hc,17177
|
| 989 |
+
pip/_vendor/urllib3/util/ssl_match_hostname.py,sha256=Ir4cZVEjmAk8gUAIHWSi7wtOO83UCYABY2xFD1Ql_WA,5758
|
| 990 |
+
pip/_vendor/urllib3/util/ssltransport.py,sha256=NA-u5rMTrDFDFC8QzRKUEKMG0561hOD4qBTr3Z4pv6E,6895
|
| 991 |
+
pip/_vendor/urllib3/util/timeout.py,sha256=cwq4dMk87mJHSBktK1miYJ-85G-3T3RmT20v7SFCpno,10168
|
| 992 |
+
pip/_vendor/urllib3/util/url.py,sha256=lCAE7M5myA8EDdW0sJuyyZhVB9K_j38ljWhHAnFaWoE,14296
|
| 993 |
+
pip/_vendor/urllib3/util/wait.py,sha256=fOX0_faozG2P7iVojQoE1mbydweNyTcm-hXEfFrTtLI,5403
|
| 994 |
+
pip/_vendor/vendor.txt,sha256=4NKk7fQhVsZw0U-0zmm9Q2LgGyaPXacFbnJAaS0Q6EY,493
|
| 995 |
+
pip/_vendor/webencodings/__init__.py,sha256=qOBJIuPy_4ByYH6W_bNgJF-qYQ2DoU-dKsDu5yRWCXg,10579
|
| 996 |
+
pip/_vendor/webencodings/__pycache__/__init__.cpython-312.pyc,,
|
| 997 |
+
pip/_vendor/webencodings/__pycache__/labels.cpython-312.pyc,,
|
| 998 |
+
pip/_vendor/webencodings/__pycache__/mklabels.cpython-312.pyc,,
|
| 999 |
+
pip/_vendor/webencodings/__pycache__/tests.cpython-312.pyc,,
|
| 1000 |
+
pip/_vendor/webencodings/__pycache__/x_user_defined.cpython-312.pyc,,
|
| 1001 |
+
pip/_vendor/webencodings/labels.py,sha256=4AO_KxTddqGtrL9ns7kAPjb0CcN6xsCIxbK37HY9r3E,8979
|
| 1002 |
+
pip/_vendor/webencodings/mklabels.py,sha256=GYIeywnpaLnP0GSic8LFWgd0UVvO_l1Nc6YoF-87R_4,1305
|
| 1003 |
+
pip/_vendor/webencodings/tests.py,sha256=OtGLyjhNY1fvkW1GvLJ_FV9ZoqC9Anyjr7q3kxTbzNs,6563
|
| 1004 |
+
pip/_vendor/webencodings/x_user_defined.py,sha256=yOqWSdmpytGfUgh_Z6JYgDNhoc-BAHyyeeT15Fr42tM,4307
|
| 1005 |
+
pip/py.typed,sha256=EBVvvPRTn_eIpz5e5QztSCdrMX7Qwd7VP93RSoIlZ2I,286
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED
ADDED
|
File without changes
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: bdist_wheel (0.42.0)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.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 |
+
pip3.12 = pip._internal.cli.main:main
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip-24.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/exceptions.py
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
from .packages.six.moves.http_client import IncompleteRead as httplib_IncompleteRead
|
| 4 |
+
|
| 5 |
+
# Base Exceptions
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class HTTPError(Exception):
|
| 9 |
+
"""Base exception used by this module."""
|
| 10 |
+
|
| 11 |
+
pass
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class HTTPWarning(Warning):
|
| 15 |
+
"""Base warning used by this module."""
|
| 16 |
+
|
| 17 |
+
pass
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
class PoolError(HTTPError):
|
| 21 |
+
"""Base exception for errors caused within a pool."""
|
| 22 |
+
|
| 23 |
+
def __init__(self, pool, message):
|
| 24 |
+
self.pool = pool
|
| 25 |
+
HTTPError.__init__(self, "%s: %s" % (pool, message))
|
| 26 |
+
|
| 27 |
+
def __reduce__(self):
|
| 28 |
+
# For pickling purposes.
|
| 29 |
+
return self.__class__, (None, None)
|
| 30 |
+
|
| 31 |
+
|
| 32 |
+
class RequestError(PoolError):
|
| 33 |
+
"""Base exception for PoolErrors that have associated URLs."""
|
| 34 |
+
|
| 35 |
+
def __init__(self, pool, url, message):
|
| 36 |
+
self.url = url
|
| 37 |
+
PoolError.__init__(self, pool, message)
|
| 38 |
+
|
| 39 |
+
def __reduce__(self):
|
| 40 |
+
# For pickling purposes.
|
| 41 |
+
return self.__class__, (None, self.url, None)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class SSLError(HTTPError):
|
| 45 |
+
"""Raised when SSL certificate fails in an HTTPS connection."""
|
| 46 |
+
|
| 47 |
+
pass
|
| 48 |
+
|
| 49 |
+
|
| 50 |
+
class ProxyError(HTTPError):
|
| 51 |
+
"""Raised when the connection to a proxy fails."""
|
| 52 |
+
|
| 53 |
+
def __init__(self, message, error, *args):
|
| 54 |
+
super(ProxyError, self).__init__(message, error, *args)
|
| 55 |
+
self.original_error = error
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
class DecodeError(HTTPError):
|
| 59 |
+
"""Raised when automatic decoding based on Content-Type fails."""
|
| 60 |
+
|
| 61 |
+
pass
|
| 62 |
+
|
| 63 |
+
|
| 64 |
+
class ProtocolError(HTTPError):
|
| 65 |
+
"""Raised when something unexpected happens mid-request/response."""
|
| 66 |
+
|
| 67 |
+
pass
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
#: Renamed to ProtocolError but aliased for backwards compatibility.
|
| 71 |
+
ConnectionError = ProtocolError
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
# Leaf Exceptions
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
class MaxRetryError(RequestError):
|
| 78 |
+
"""Raised when the maximum number of retries is exceeded.
|
| 79 |
+
|
| 80 |
+
:param pool: The connection pool
|
| 81 |
+
:type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool`
|
| 82 |
+
:param string url: The requested Url
|
| 83 |
+
:param exceptions.Exception reason: The underlying error
|
| 84 |
+
|
| 85 |
+
"""
|
| 86 |
+
|
| 87 |
+
def __init__(self, pool, url, reason=None):
|
| 88 |
+
self.reason = reason
|
| 89 |
+
|
| 90 |
+
message = "Max retries exceeded with url: %s (Caused by %r)" % (url, reason)
|
| 91 |
+
|
| 92 |
+
RequestError.__init__(self, pool, url, message)
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
class HostChangedError(RequestError):
|
| 96 |
+
"""Raised when an existing pool gets a request for a foreign host."""
|
| 97 |
+
|
| 98 |
+
def __init__(self, pool, url, retries=3):
|
| 99 |
+
message = "Tried to open a foreign host with url: %s" % url
|
| 100 |
+
RequestError.__init__(self, pool, url, message)
|
| 101 |
+
self.retries = retries
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
class TimeoutStateError(HTTPError):
|
| 105 |
+
"""Raised when passing an invalid state to a timeout"""
|
| 106 |
+
|
| 107 |
+
pass
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
class TimeoutError(HTTPError):
|
| 111 |
+
"""Raised when a socket timeout error occurs.
|
| 112 |
+
|
| 113 |
+
Catching this error will catch both :exc:`ReadTimeoutErrors
|
| 114 |
+
<ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`.
|
| 115 |
+
"""
|
| 116 |
+
|
| 117 |
+
pass
|
| 118 |
+
|
| 119 |
+
|
| 120 |
+
class ReadTimeoutError(TimeoutError, RequestError):
|
| 121 |
+
"""Raised when a socket timeout occurs while receiving data from a server"""
|
| 122 |
+
|
| 123 |
+
pass
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
# This timeout error does not have a URL attached and needs to inherit from the
|
| 127 |
+
# base HTTPError
|
| 128 |
+
class ConnectTimeoutError(TimeoutError):
|
| 129 |
+
"""Raised when a socket timeout occurs while connecting to a server"""
|
| 130 |
+
|
| 131 |
+
pass
|
| 132 |
+
|
| 133 |
+
|
| 134 |
+
class NewConnectionError(ConnectTimeoutError, PoolError):
|
| 135 |
+
"""Raised when we fail to establish a new connection. Usually ECONNREFUSED."""
|
| 136 |
+
|
| 137 |
+
pass
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
class EmptyPoolError(PoolError):
|
| 141 |
+
"""Raised when a pool runs out of connections and no more are allowed."""
|
| 142 |
+
|
| 143 |
+
pass
|
| 144 |
+
|
| 145 |
+
|
| 146 |
+
class ClosedPoolError(PoolError):
|
| 147 |
+
"""Raised when a request enters a pool after the pool has been closed."""
|
| 148 |
+
|
| 149 |
+
pass
|
| 150 |
+
|
| 151 |
+
|
| 152 |
+
class LocationValueError(ValueError, HTTPError):
|
| 153 |
+
"""Raised when there is something wrong with a given URL input."""
|
| 154 |
+
|
| 155 |
+
pass
|
| 156 |
+
|
| 157 |
+
|
| 158 |
+
class LocationParseError(LocationValueError):
|
| 159 |
+
"""Raised when get_host or similar fails to parse the URL input."""
|
| 160 |
+
|
| 161 |
+
def __init__(self, location):
|
| 162 |
+
message = "Failed to parse: %s" % location
|
| 163 |
+
HTTPError.__init__(self, message)
|
| 164 |
+
|
| 165 |
+
self.location = location
|
| 166 |
+
|
| 167 |
+
|
| 168 |
+
class URLSchemeUnknown(LocationValueError):
|
| 169 |
+
"""Raised when a URL input has an unsupported scheme."""
|
| 170 |
+
|
| 171 |
+
def __init__(self, scheme):
|
| 172 |
+
message = "Not supported URL scheme %s" % scheme
|
| 173 |
+
super(URLSchemeUnknown, self).__init__(message)
|
| 174 |
+
|
| 175 |
+
self.scheme = scheme
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
class ResponseError(HTTPError):
|
| 179 |
+
"""Used as a container for an error reason supplied in a MaxRetryError."""
|
| 180 |
+
|
| 181 |
+
GENERIC_ERROR = "too many error responses"
|
| 182 |
+
SPECIFIC_ERROR = "too many {status_code} error responses"
|
| 183 |
+
|
| 184 |
+
|
| 185 |
+
class SecurityWarning(HTTPWarning):
|
| 186 |
+
"""Warned when performing security reducing actions"""
|
| 187 |
+
|
| 188 |
+
pass
|
| 189 |
+
|
| 190 |
+
|
| 191 |
+
class SubjectAltNameWarning(SecurityWarning):
|
| 192 |
+
"""Warned when connecting to a host with a certificate missing a SAN."""
|
| 193 |
+
|
| 194 |
+
pass
|
| 195 |
+
|
| 196 |
+
|
| 197 |
+
class InsecureRequestWarning(SecurityWarning):
|
| 198 |
+
"""Warned when making an unverified HTTPS request."""
|
| 199 |
+
|
| 200 |
+
pass
|
| 201 |
+
|
| 202 |
+
|
| 203 |
+
class SystemTimeWarning(SecurityWarning):
|
| 204 |
+
"""Warned when system time is suspected to be wrong"""
|
| 205 |
+
|
| 206 |
+
pass
|
| 207 |
+
|
| 208 |
+
|
| 209 |
+
class InsecurePlatformWarning(SecurityWarning):
|
| 210 |
+
"""Warned when certain TLS/SSL configuration is not available on a platform."""
|
| 211 |
+
|
| 212 |
+
pass
|
| 213 |
+
|
| 214 |
+
|
| 215 |
+
class SNIMissingWarning(HTTPWarning):
|
| 216 |
+
"""Warned when making a HTTPS request without SNI available."""
|
| 217 |
+
|
| 218 |
+
pass
|
| 219 |
+
|
| 220 |
+
|
| 221 |
+
class DependencyWarning(HTTPWarning):
|
| 222 |
+
"""
|
| 223 |
+
Warned when an attempt is made to import a module with missing optional
|
| 224 |
+
dependencies.
|
| 225 |
+
"""
|
| 226 |
+
|
| 227 |
+
pass
|
| 228 |
+
|
| 229 |
+
|
| 230 |
+
class ResponseNotChunked(ProtocolError, ValueError):
|
| 231 |
+
"""Response needs to be chunked in order to read it as chunks."""
|
| 232 |
+
|
| 233 |
+
pass
|
| 234 |
+
|
| 235 |
+
|
| 236 |
+
class BodyNotHttplibCompatible(HTTPError):
|
| 237 |
+
"""
|
| 238 |
+
Body should be :class:`http.client.HTTPResponse` like
|
| 239 |
+
(have an fp attribute which returns raw chunks) for read_chunked().
|
| 240 |
+
"""
|
| 241 |
+
|
| 242 |
+
pass
|
| 243 |
+
|
| 244 |
+
|
| 245 |
+
class IncompleteRead(HTTPError, httplib_IncompleteRead):
|
| 246 |
+
"""
|
| 247 |
+
Response length doesn't match expected Content-Length
|
| 248 |
+
|
| 249 |
+
Subclass of :class:`http.client.IncompleteRead` to allow int value
|
| 250 |
+
for ``partial`` to avoid creating large objects on streamed reads.
|
| 251 |
+
"""
|
| 252 |
+
|
| 253 |
+
def __init__(self, partial, expected):
|
| 254 |
+
super(IncompleteRead, self).__init__(partial, expected)
|
| 255 |
+
|
| 256 |
+
def __repr__(self):
|
| 257 |
+
return "IncompleteRead(%i bytes read, %i more expected)" % (
|
| 258 |
+
self.partial,
|
| 259 |
+
self.expected,
|
| 260 |
+
)
|
| 261 |
+
|
| 262 |
+
|
| 263 |
+
class InvalidChunkLength(HTTPError, httplib_IncompleteRead):
|
| 264 |
+
"""Invalid chunk length in a chunked response."""
|
| 265 |
+
|
| 266 |
+
def __init__(self, response, length):
|
| 267 |
+
super(InvalidChunkLength, self).__init__(
|
| 268 |
+
response.tell(), response.length_remaining
|
| 269 |
+
)
|
| 270 |
+
self.response = response
|
| 271 |
+
self.length = length
|
| 272 |
+
|
| 273 |
+
def __repr__(self):
|
| 274 |
+
return "InvalidChunkLength(got length %r, %i bytes read)" % (
|
| 275 |
+
self.length,
|
| 276 |
+
self.partial,
|
| 277 |
+
)
|
| 278 |
+
|
| 279 |
+
|
| 280 |
+
class InvalidHeader(HTTPError):
|
| 281 |
+
"""The header provided was somehow invalid."""
|
| 282 |
+
|
| 283 |
+
pass
|
| 284 |
+
|
| 285 |
+
|
| 286 |
+
class ProxySchemeUnknown(AssertionError, URLSchemeUnknown):
|
| 287 |
+
"""ProxyManager does not support the supplied scheme"""
|
| 288 |
+
|
| 289 |
+
# TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
|
| 290 |
+
|
| 291 |
+
def __init__(self, scheme):
|
| 292 |
+
# 'localhost' is here because our URL parser parses
|
| 293 |
+
# localhost:8080 -> scheme=localhost, remove if we fix this.
|
| 294 |
+
if scheme == "localhost":
|
| 295 |
+
scheme = None
|
| 296 |
+
if scheme is None:
|
| 297 |
+
message = "Proxy URL had no scheme, should start with http:// or https://"
|
| 298 |
+
else:
|
| 299 |
+
message = (
|
| 300 |
+
"Proxy URL had unsupported scheme %s, should use http:// or https://"
|
| 301 |
+
% scheme
|
| 302 |
+
)
|
| 303 |
+
super(ProxySchemeUnknown, self).__init__(message)
|
| 304 |
+
|
| 305 |
+
|
| 306 |
+
class ProxySchemeUnsupported(ValueError):
|
| 307 |
+
"""Fetching HTTPS resources through HTTPS proxies is unsupported"""
|
| 308 |
+
|
| 309 |
+
pass
|
| 310 |
+
|
| 311 |
+
|
| 312 |
+
class HeaderParsingError(HTTPError):
|
| 313 |
+
"""Raised by assert_header_parsing, but we convert it to a log.warning statement."""
|
| 314 |
+
|
| 315 |
+
def __init__(self, defects, unparsed_data):
|
| 316 |
+
message = "%s, unparsed data: %r" % (defects or "Unknown", unparsed_data)
|
| 317 |
+
super(HeaderParsingError, self).__init__(message)
|
| 318 |
+
|
| 319 |
+
|
| 320 |
+
class UnrewindableBodyError(HTTPError):
|
| 321 |
+
"""urllib3 encountered an error when trying to rewind a body"""
|
| 322 |
+
|
| 323 |
+
pass
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/fields.py
ADDED
|
@@ -0,0 +1,274 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import email.utils
|
| 4 |
+
import mimetypes
|
| 5 |
+
import re
|
| 6 |
+
|
| 7 |
+
from .packages import six
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
def guess_content_type(filename, default="application/octet-stream"):
|
| 11 |
+
"""
|
| 12 |
+
Guess the "Content-Type" of a file.
|
| 13 |
+
|
| 14 |
+
:param filename:
|
| 15 |
+
The filename to guess the "Content-Type" of using :mod:`mimetypes`.
|
| 16 |
+
:param default:
|
| 17 |
+
If no "Content-Type" can be guessed, default to `default`.
|
| 18 |
+
"""
|
| 19 |
+
if filename:
|
| 20 |
+
return mimetypes.guess_type(filename)[0] or default
|
| 21 |
+
return default
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
def format_header_param_rfc2231(name, value):
|
| 25 |
+
"""
|
| 26 |
+
Helper function to format and quote a single header parameter using the
|
| 27 |
+
strategy defined in RFC 2231.
|
| 28 |
+
|
| 29 |
+
Particularly useful for header parameters which might contain
|
| 30 |
+
non-ASCII values, like file names. This follows
|
| 31 |
+
`RFC 2388 Section 4.4 <https://tools.ietf.org/html/rfc2388#section-4.4>`_.
|
| 32 |
+
|
| 33 |
+
:param name:
|
| 34 |
+
The name of the parameter, a string expected to be ASCII only.
|
| 35 |
+
:param value:
|
| 36 |
+
The value of the parameter, provided as ``bytes`` or `str``.
|
| 37 |
+
:ret:
|
| 38 |
+
An RFC-2231-formatted unicode string.
|
| 39 |
+
"""
|
| 40 |
+
if isinstance(value, six.binary_type):
|
| 41 |
+
value = value.decode("utf-8")
|
| 42 |
+
|
| 43 |
+
if not any(ch in value for ch in '"\\\r\n'):
|
| 44 |
+
result = u'%s="%s"' % (name, value)
|
| 45 |
+
try:
|
| 46 |
+
result.encode("ascii")
|
| 47 |
+
except (UnicodeEncodeError, UnicodeDecodeError):
|
| 48 |
+
pass
|
| 49 |
+
else:
|
| 50 |
+
return result
|
| 51 |
+
|
| 52 |
+
if six.PY2: # Python 2:
|
| 53 |
+
value = value.encode("utf-8")
|
| 54 |
+
|
| 55 |
+
# encode_rfc2231 accepts an encoded string and returns an ascii-encoded
|
| 56 |
+
# string in Python 2 but accepts and returns unicode strings in Python 3
|
| 57 |
+
value = email.utils.encode_rfc2231(value, "utf-8")
|
| 58 |
+
value = "%s*=%s" % (name, value)
|
| 59 |
+
|
| 60 |
+
if six.PY2: # Python 2:
|
| 61 |
+
value = value.decode("utf-8")
|
| 62 |
+
|
| 63 |
+
return value
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
_HTML5_REPLACEMENTS = {
|
| 67 |
+
u"\u0022": u"%22",
|
| 68 |
+
# Replace "\" with "\\".
|
| 69 |
+
u"\u005C": u"\u005C\u005C",
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
# All control characters from 0x00 to 0x1F *except* 0x1B.
|
| 73 |
+
_HTML5_REPLACEMENTS.update(
|
| 74 |
+
{
|
| 75 |
+
six.unichr(cc): u"%{:02X}".format(cc)
|
| 76 |
+
for cc in range(0x00, 0x1F + 1)
|
| 77 |
+
if cc not in (0x1B,)
|
| 78 |
+
}
|
| 79 |
+
)
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
def _replace_multiple(value, needles_and_replacements):
|
| 83 |
+
def replacer(match):
|
| 84 |
+
return needles_and_replacements[match.group(0)]
|
| 85 |
+
|
| 86 |
+
pattern = re.compile(
|
| 87 |
+
r"|".join([re.escape(needle) for needle in needles_and_replacements.keys()])
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
result = pattern.sub(replacer, value)
|
| 91 |
+
|
| 92 |
+
return result
|
| 93 |
+
|
| 94 |
+
|
| 95 |
+
def format_header_param_html5(name, value):
|
| 96 |
+
"""
|
| 97 |
+
Helper function to format and quote a single header parameter using the
|
| 98 |
+
HTML5 strategy.
|
| 99 |
+
|
| 100 |
+
Particularly useful for header parameters which might contain
|
| 101 |
+
non-ASCII values, like file names. This follows the `HTML5 Working Draft
|
| 102 |
+
Section 4.10.22.7`_ and matches the behavior of curl and modern browsers.
|
| 103 |
+
|
| 104 |
+
.. _HTML5 Working Draft Section 4.10.22.7:
|
| 105 |
+
https://w3c.github.io/html/sec-forms.html#multipart-form-data
|
| 106 |
+
|
| 107 |
+
:param name:
|
| 108 |
+
The name of the parameter, a string expected to be ASCII only.
|
| 109 |
+
:param value:
|
| 110 |
+
The value of the parameter, provided as ``bytes`` or `str``.
|
| 111 |
+
:ret:
|
| 112 |
+
A unicode string, stripped of troublesome characters.
|
| 113 |
+
"""
|
| 114 |
+
if isinstance(value, six.binary_type):
|
| 115 |
+
value = value.decode("utf-8")
|
| 116 |
+
|
| 117 |
+
value = _replace_multiple(value, _HTML5_REPLACEMENTS)
|
| 118 |
+
|
| 119 |
+
return u'%s="%s"' % (name, value)
|
| 120 |
+
|
| 121 |
+
|
| 122 |
+
# For backwards-compatibility.
|
| 123 |
+
format_header_param = format_header_param_html5
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
class RequestField(object):
|
| 127 |
+
"""
|
| 128 |
+
A data container for request body parameters.
|
| 129 |
+
|
| 130 |
+
:param name:
|
| 131 |
+
The name of this request field. Must be unicode.
|
| 132 |
+
:param data:
|
| 133 |
+
The data/value body.
|
| 134 |
+
:param filename:
|
| 135 |
+
An optional filename of the request field. Must be unicode.
|
| 136 |
+
:param headers:
|
| 137 |
+
An optional dict-like object of headers to initially use for the field.
|
| 138 |
+
:param header_formatter:
|
| 139 |
+
An optional callable that is used to encode and format the headers. By
|
| 140 |
+
default, this is :func:`format_header_param_html5`.
|
| 141 |
+
"""
|
| 142 |
+
|
| 143 |
+
def __init__(
|
| 144 |
+
self,
|
| 145 |
+
name,
|
| 146 |
+
data,
|
| 147 |
+
filename=None,
|
| 148 |
+
headers=None,
|
| 149 |
+
header_formatter=format_header_param_html5,
|
| 150 |
+
):
|
| 151 |
+
self._name = name
|
| 152 |
+
self._filename = filename
|
| 153 |
+
self.data = data
|
| 154 |
+
self.headers = {}
|
| 155 |
+
if headers:
|
| 156 |
+
self.headers = dict(headers)
|
| 157 |
+
self.header_formatter = header_formatter
|
| 158 |
+
|
| 159 |
+
@classmethod
|
| 160 |
+
def from_tuples(cls, fieldname, value, header_formatter=format_header_param_html5):
|
| 161 |
+
"""
|
| 162 |
+
A :class:`~urllib3.fields.RequestField` factory from old-style tuple parameters.
|
| 163 |
+
|
| 164 |
+
Supports constructing :class:`~urllib3.fields.RequestField` from
|
| 165 |
+
parameter of key/value strings AND key/filetuple. A filetuple is a
|
| 166 |
+
(filename, data, MIME type) tuple where the MIME type is optional.
|
| 167 |
+
For example::
|
| 168 |
+
|
| 169 |
+
'foo': 'bar',
|
| 170 |
+
'fakefile': ('foofile.txt', 'contents of foofile'),
|
| 171 |
+
'realfile': ('barfile.txt', open('realfile').read()),
|
| 172 |
+
'typedfile': ('bazfile.bin', open('bazfile').read(), 'image/jpeg'),
|
| 173 |
+
'nonamefile': 'contents of nonamefile field',
|
| 174 |
+
|
| 175 |
+
Field names and filenames must be unicode.
|
| 176 |
+
"""
|
| 177 |
+
if isinstance(value, tuple):
|
| 178 |
+
if len(value) == 3:
|
| 179 |
+
filename, data, content_type = value
|
| 180 |
+
else:
|
| 181 |
+
filename, data = value
|
| 182 |
+
content_type = guess_content_type(filename)
|
| 183 |
+
else:
|
| 184 |
+
filename = None
|
| 185 |
+
content_type = None
|
| 186 |
+
data = value
|
| 187 |
+
|
| 188 |
+
request_param = cls(
|
| 189 |
+
fieldname, data, filename=filename, header_formatter=header_formatter
|
| 190 |
+
)
|
| 191 |
+
request_param.make_multipart(content_type=content_type)
|
| 192 |
+
|
| 193 |
+
return request_param
|
| 194 |
+
|
| 195 |
+
def _render_part(self, name, value):
|
| 196 |
+
"""
|
| 197 |
+
Overridable helper function to format a single header parameter. By
|
| 198 |
+
default, this calls ``self.header_formatter``.
|
| 199 |
+
|
| 200 |
+
:param name:
|
| 201 |
+
The name of the parameter, a string expected to be ASCII only.
|
| 202 |
+
:param value:
|
| 203 |
+
The value of the parameter, provided as a unicode string.
|
| 204 |
+
"""
|
| 205 |
+
|
| 206 |
+
return self.header_formatter(name, value)
|
| 207 |
+
|
| 208 |
+
def _render_parts(self, header_parts):
|
| 209 |
+
"""
|
| 210 |
+
Helper function to format and quote a single header.
|
| 211 |
+
|
| 212 |
+
Useful for single headers that are composed of multiple items. E.g.,
|
| 213 |
+
'Content-Disposition' fields.
|
| 214 |
+
|
| 215 |
+
:param header_parts:
|
| 216 |
+
A sequence of (k, v) tuples or a :class:`dict` of (k, v) to format
|
| 217 |
+
as `k1="v1"; k2="v2"; ...`.
|
| 218 |
+
"""
|
| 219 |
+
parts = []
|
| 220 |
+
iterable = header_parts
|
| 221 |
+
if isinstance(header_parts, dict):
|
| 222 |
+
iterable = header_parts.items()
|
| 223 |
+
|
| 224 |
+
for name, value in iterable:
|
| 225 |
+
if value is not None:
|
| 226 |
+
parts.append(self._render_part(name, value))
|
| 227 |
+
|
| 228 |
+
return u"; ".join(parts)
|
| 229 |
+
|
| 230 |
+
def render_headers(self):
|
| 231 |
+
"""
|
| 232 |
+
Renders the headers for this request field.
|
| 233 |
+
"""
|
| 234 |
+
lines = []
|
| 235 |
+
|
| 236 |
+
sort_keys = ["Content-Disposition", "Content-Type", "Content-Location"]
|
| 237 |
+
for sort_key in sort_keys:
|
| 238 |
+
if self.headers.get(sort_key, False):
|
| 239 |
+
lines.append(u"%s: %s" % (sort_key, self.headers[sort_key]))
|
| 240 |
+
|
| 241 |
+
for header_name, header_value in self.headers.items():
|
| 242 |
+
if header_name not in sort_keys:
|
| 243 |
+
if header_value:
|
| 244 |
+
lines.append(u"%s: %s" % (header_name, header_value))
|
| 245 |
+
|
| 246 |
+
lines.append(u"\r\n")
|
| 247 |
+
return u"\r\n".join(lines)
|
| 248 |
+
|
| 249 |
+
def make_multipart(
|
| 250 |
+
self, content_disposition=None, content_type=None, content_location=None
|
| 251 |
+
):
|
| 252 |
+
"""
|
| 253 |
+
Makes this request field into a multipart request field.
|
| 254 |
+
|
| 255 |
+
This method overrides "Content-Disposition", "Content-Type" and
|
| 256 |
+
"Content-Location" headers to the request parameter.
|
| 257 |
+
|
| 258 |
+
:param content_type:
|
| 259 |
+
The 'Content-Type' of the request body.
|
| 260 |
+
:param content_location:
|
| 261 |
+
The 'Content-Location' of the request body.
|
| 262 |
+
|
| 263 |
+
"""
|
| 264 |
+
self.headers["Content-Disposition"] = content_disposition or u"form-data"
|
| 265 |
+
self.headers["Content-Disposition"] += u"; ".join(
|
| 266 |
+
[
|
| 267 |
+
u"",
|
| 268 |
+
self._render_parts(
|
| 269 |
+
((u"name", self._name), (u"filename", self._filename))
|
| 270 |
+
),
|
| 271 |
+
]
|
| 272 |
+
)
|
| 273 |
+
self.headers["Content-Type"] = content_type
|
| 274 |
+
self.headers["Content-Location"] = content_location
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/filepost.py
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import binascii
|
| 4 |
+
import codecs
|
| 5 |
+
import os
|
| 6 |
+
from io import BytesIO
|
| 7 |
+
|
| 8 |
+
from .fields import RequestField
|
| 9 |
+
from .packages import six
|
| 10 |
+
from .packages.six import b
|
| 11 |
+
|
| 12 |
+
writer = codecs.lookup("utf-8")[3]
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
def choose_boundary():
|
| 16 |
+
"""
|
| 17 |
+
Our embarrassingly-simple replacement for mimetools.choose_boundary.
|
| 18 |
+
"""
|
| 19 |
+
boundary = binascii.hexlify(os.urandom(16))
|
| 20 |
+
if not six.PY2:
|
| 21 |
+
boundary = boundary.decode("ascii")
|
| 22 |
+
return boundary
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def iter_field_objects(fields):
|
| 26 |
+
"""
|
| 27 |
+
Iterate over fields.
|
| 28 |
+
|
| 29 |
+
Supports list of (k, v) tuples and dicts, and lists of
|
| 30 |
+
:class:`~urllib3.fields.RequestField`.
|
| 31 |
+
|
| 32 |
+
"""
|
| 33 |
+
if isinstance(fields, dict):
|
| 34 |
+
i = six.iteritems(fields)
|
| 35 |
+
else:
|
| 36 |
+
i = iter(fields)
|
| 37 |
+
|
| 38 |
+
for field in i:
|
| 39 |
+
if isinstance(field, RequestField):
|
| 40 |
+
yield field
|
| 41 |
+
else:
|
| 42 |
+
yield RequestField.from_tuples(*field)
|
| 43 |
+
|
| 44 |
+
|
| 45 |
+
def iter_fields(fields):
|
| 46 |
+
"""
|
| 47 |
+
.. deprecated:: 1.6
|
| 48 |
+
|
| 49 |
+
Iterate over fields.
|
| 50 |
+
|
| 51 |
+
The addition of :class:`~urllib3.fields.RequestField` makes this function
|
| 52 |
+
obsolete. Instead, use :func:`iter_field_objects`, which returns
|
| 53 |
+
:class:`~urllib3.fields.RequestField` objects.
|
| 54 |
+
|
| 55 |
+
Supports list of (k, v) tuples and dicts.
|
| 56 |
+
"""
|
| 57 |
+
if isinstance(fields, dict):
|
| 58 |
+
return ((k, v) for k, v in six.iteritems(fields))
|
| 59 |
+
|
| 60 |
+
return ((k, v) for k, v in fields)
|
| 61 |
+
|
| 62 |
+
|
| 63 |
+
def encode_multipart_formdata(fields, boundary=None):
|
| 64 |
+
"""
|
| 65 |
+
Encode a dictionary of ``fields`` using the multipart/form-data MIME format.
|
| 66 |
+
|
| 67 |
+
:param fields:
|
| 68 |
+
Dictionary of fields or list of (key, :class:`~urllib3.fields.RequestField`).
|
| 69 |
+
|
| 70 |
+
:param boundary:
|
| 71 |
+
If not specified, then a random boundary will be generated using
|
| 72 |
+
:func:`urllib3.filepost.choose_boundary`.
|
| 73 |
+
"""
|
| 74 |
+
body = BytesIO()
|
| 75 |
+
if boundary is None:
|
| 76 |
+
boundary = choose_boundary()
|
| 77 |
+
|
| 78 |
+
for field in iter_field_objects(fields):
|
| 79 |
+
body.write(b("--%s\r\n" % (boundary)))
|
| 80 |
+
|
| 81 |
+
writer(body).write(field.render_headers())
|
| 82 |
+
data = field.data
|
| 83 |
+
|
| 84 |
+
if isinstance(data, int):
|
| 85 |
+
data = str(data) # Backwards compatibility
|
| 86 |
+
|
| 87 |
+
if isinstance(data, six.text_type):
|
| 88 |
+
writer(body).write(data)
|
| 89 |
+
else:
|
| 90 |
+
body.write(data)
|
| 91 |
+
|
| 92 |
+
body.write(b"\r\n")
|
| 93 |
+
|
| 94 |
+
body.write(b("--%s--\r\n" % (boundary)))
|
| 95 |
+
|
| 96 |
+
content_type = str("multipart/form-data; boundary=%s" % boundary)
|
| 97 |
+
|
| 98 |
+
return body.getvalue(), content_type
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/__init__.py
ADDED
|
File without changes
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/__init__.py
ADDED
|
File without changes
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/makefile.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
backports.makefile
|
| 4 |
+
~~~~~~~~~~~~~~~~~~
|
| 5 |
+
|
| 6 |
+
Backports the Python 3 ``socket.makefile`` method for use with anything that
|
| 7 |
+
wants to create a "fake" socket object.
|
| 8 |
+
"""
|
| 9 |
+
import io
|
| 10 |
+
from socket import SocketIO
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
def backport_makefile(
|
| 14 |
+
self, mode="r", buffering=None, encoding=None, errors=None, newline=None
|
| 15 |
+
):
|
| 16 |
+
"""
|
| 17 |
+
Backport of ``socket.makefile`` from Python 3.5.
|
| 18 |
+
"""
|
| 19 |
+
if not set(mode) <= {"r", "w", "b"}:
|
| 20 |
+
raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
|
| 21 |
+
writing = "w" in mode
|
| 22 |
+
reading = "r" in mode or not writing
|
| 23 |
+
assert reading or writing
|
| 24 |
+
binary = "b" in mode
|
| 25 |
+
rawmode = ""
|
| 26 |
+
if reading:
|
| 27 |
+
rawmode += "r"
|
| 28 |
+
if writing:
|
| 29 |
+
rawmode += "w"
|
| 30 |
+
raw = SocketIO(self, rawmode)
|
| 31 |
+
self._makefile_refs += 1
|
| 32 |
+
if buffering is None:
|
| 33 |
+
buffering = -1
|
| 34 |
+
if buffering < 0:
|
| 35 |
+
buffering = io.DEFAULT_BUFFER_SIZE
|
| 36 |
+
if buffering == 0:
|
| 37 |
+
if not binary:
|
| 38 |
+
raise ValueError("unbuffered streams must be binary")
|
| 39 |
+
return raw
|
| 40 |
+
if reading and writing:
|
| 41 |
+
buffer = io.BufferedRWPair(raw, raw, buffering)
|
| 42 |
+
elif reading:
|
| 43 |
+
buffer = io.BufferedReader(raw, buffering)
|
| 44 |
+
else:
|
| 45 |
+
assert writing
|
| 46 |
+
buffer = io.BufferedWriter(raw, buffering)
|
| 47 |
+
if binary:
|
| 48 |
+
return buffer
|
| 49 |
+
text = io.TextIOWrapper(buffer, encoding, errors, newline)
|
| 50 |
+
text.mode = mode
|
| 51 |
+
return text
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/backports/weakref_finalize.py
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# -*- coding: utf-8 -*-
|
| 2 |
+
"""
|
| 3 |
+
backports.weakref_finalize
|
| 4 |
+
~~~~~~~~~~~~~~~~~~
|
| 5 |
+
|
| 6 |
+
Backports the Python 3 ``weakref.finalize`` method.
|
| 7 |
+
"""
|
| 8 |
+
from __future__ import absolute_import
|
| 9 |
+
|
| 10 |
+
import itertools
|
| 11 |
+
import sys
|
| 12 |
+
from weakref import ref
|
| 13 |
+
|
| 14 |
+
__all__ = ["weakref_finalize"]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class weakref_finalize(object):
|
| 18 |
+
"""Class for finalization of weakrefable objects
|
| 19 |
+
finalize(obj, func, *args, **kwargs) returns a callable finalizer
|
| 20 |
+
object which will be called when obj is garbage collected. The
|
| 21 |
+
first time the finalizer is called it evaluates func(*arg, **kwargs)
|
| 22 |
+
and returns the result. After this the finalizer is dead, and
|
| 23 |
+
calling it just returns None.
|
| 24 |
+
When the program exits any remaining finalizers for which the
|
| 25 |
+
atexit attribute is true will be run in reverse order of creation.
|
| 26 |
+
By default atexit is true.
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
# Finalizer objects don't have any state of their own. They are
|
| 30 |
+
# just used as keys to lookup _Info objects in the registry. This
|
| 31 |
+
# ensures that they cannot be part of a ref-cycle.
|
| 32 |
+
|
| 33 |
+
__slots__ = ()
|
| 34 |
+
_registry = {}
|
| 35 |
+
_shutdown = False
|
| 36 |
+
_index_iter = itertools.count()
|
| 37 |
+
_dirty = False
|
| 38 |
+
_registered_with_atexit = False
|
| 39 |
+
|
| 40 |
+
class _Info(object):
|
| 41 |
+
__slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
|
| 42 |
+
|
| 43 |
+
def __init__(self, obj, func, *args, **kwargs):
|
| 44 |
+
if not self._registered_with_atexit:
|
| 45 |
+
# We may register the exit function more than once because
|
| 46 |
+
# of a thread race, but that is harmless
|
| 47 |
+
import atexit
|
| 48 |
+
|
| 49 |
+
atexit.register(self._exitfunc)
|
| 50 |
+
weakref_finalize._registered_with_atexit = True
|
| 51 |
+
info = self._Info()
|
| 52 |
+
info.weakref = ref(obj, self)
|
| 53 |
+
info.func = func
|
| 54 |
+
info.args = args
|
| 55 |
+
info.kwargs = kwargs or None
|
| 56 |
+
info.atexit = True
|
| 57 |
+
info.index = next(self._index_iter)
|
| 58 |
+
self._registry[self] = info
|
| 59 |
+
weakref_finalize._dirty = True
|
| 60 |
+
|
| 61 |
+
def __call__(self, _=None):
|
| 62 |
+
"""If alive then mark as dead and return func(*args, **kwargs);
|
| 63 |
+
otherwise return None"""
|
| 64 |
+
info = self._registry.pop(self, None)
|
| 65 |
+
if info and not self._shutdown:
|
| 66 |
+
return info.func(*info.args, **(info.kwargs or {}))
|
| 67 |
+
|
| 68 |
+
def detach(self):
|
| 69 |
+
"""If alive then mark as dead and return (obj, func, args, kwargs);
|
| 70 |
+
otherwise return None"""
|
| 71 |
+
info = self._registry.get(self)
|
| 72 |
+
obj = info and info.weakref()
|
| 73 |
+
if obj is not None and self._registry.pop(self, None):
|
| 74 |
+
return (obj, info.func, info.args, info.kwargs or {})
|
| 75 |
+
|
| 76 |
+
def peek(self):
|
| 77 |
+
"""If alive then return (obj, func, args, kwargs);
|
| 78 |
+
otherwise return None"""
|
| 79 |
+
info = self._registry.get(self)
|
| 80 |
+
obj = info and info.weakref()
|
| 81 |
+
if obj is not None:
|
| 82 |
+
return (obj, info.func, info.args, info.kwargs or {})
|
| 83 |
+
|
| 84 |
+
@property
|
| 85 |
+
def alive(self):
|
| 86 |
+
"""Whether finalizer is alive"""
|
| 87 |
+
return self in self._registry
|
| 88 |
+
|
| 89 |
+
@property
|
| 90 |
+
def atexit(self):
|
| 91 |
+
"""Whether finalizer should be called at exit"""
|
| 92 |
+
info = self._registry.get(self)
|
| 93 |
+
return bool(info) and info.atexit
|
| 94 |
+
|
| 95 |
+
@atexit.setter
|
| 96 |
+
def atexit(self, value):
|
| 97 |
+
info = self._registry.get(self)
|
| 98 |
+
if info:
|
| 99 |
+
info.atexit = bool(value)
|
| 100 |
+
|
| 101 |
+
def __repr__(self):
|
| 102 |
+
info = self._registry.get(self)
|
| 103 |
+
obj = info and info.weakref()
|
| 104 |
+
if obj is None:
|
| 105 |
+
return "<%s object at %#x; dead>" % (type(self).__name__, id(self))
|
| 106 |
+
else:
|
| 107 |
+
return "<%s object at %#x; for %r at %#x>" % (
|
| 108 |
+
type(self).__name__,
|
| 109 |
+
id(self),
|
| 110 |
+
type(obj).__name__,
|
| 111 |
+
id(obj),
|
| 112 |
+
)
|
| 113 |
+
|
| 114 |
+
@classmethod
|
| 115 |
+
def _select_for_exit(cls):
|
| 116 |
+
# Return live finalizers marked for exit, oldest first
|
| 117 |
+
L = [(f, i) for (f, i) in cls._registry.items() if i.atexit]
|
| 118 |
+
L.sort(key=lambda item: item[1].index)
|
| 119 |
+
return [f for (f, i) in L]
|
| 120 |
+
|
| 121 |
+
@classmethod
|
| 122 |
+
def _exitfunc(cls):
|
| 123 |
+
# At shutdown invoke finalizers for which atexit is true.
|
| 124 |
+
# This is called once all other non-daemonic threads have been
|
| 125 |
+
# joined.
|
| 126 |
+
reenable_gc = False
|
| 127 |
+
try:
|
| 128 |
+
if cls._registry:
|
| 129 |
+
import gc
|
| 130 |
+
|
| 131 |
+
if gc.isenabled():
|
| 132 |
+
reenable_gc = True
|
| 133 |
+
gc.disable()
|
| 134 |
+
pending = None
|
| 135 |
+
while True:
|
| 136 |
+
if pending is None or weakref_finalize._dirty:
|
| 137 |
+
pending = cls._select_for_exit()
|
| 138 |
+
weakref_finalize._dirty = False
|
| 139 |
+
if not pending:
|
| 140 |
+
break
|
| 141 |
+
f = pending.pop()
|
| 142 |
+
try:
|
| 143 |
+
# gc is disabled, so (assuming no daemonic
|
| 144 |
+
# threads) the following is the only line in
|
| 145 |
+
# this function which might trigger creation
|
| 146 |
+
# of a new finalizer
|
| 147 |
+
f()
|
| 148 |
+
except Exception:
|
| 149 |
+
sys.excepthook(*sys.exc_info())
|
| 150 |
+
assert f not in cls._registry
|
| 151 |
+
finally:
|
| 152 |
+
# prevent any more finalizers from executing during shutdown
|
| 153 |
+
weakref_finalize._shutdown = True
|
| 154 |
+
if reenable_gc:
|
| 155 |
+
gc.enable()
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/packages/six.py
ADDED
|
@@ -0,0 +1,1076 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# Copyright (c) 2010-2020 Benjamin Peterson
|
| 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.
|
| 20 |
+
|
| 21 |
+
"""Utilities for writing code that runs on Python 2 and 3"""
|
| 22 |
+
|
| 23 |
+
from __future__ import absolute_import
|
| 24 |
+
|
| 25 |
+
import functools
|
| 26 |
+
import itertools
|
| 27 |
+
import operator
|
| 28 |
+
import sys
|
| 29 |
+
import types
|
| 30 |
+
|
| 31 |
+
__author__ = "Benjamin Peterson <benjamin@python.org>"
|
| 32 |
+
__version__ = "1.16.0"
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
# Useful for very coarse version differentiation.
|
| 36 |
+
PY2 = sys.version_info[0] == 2
|
| 37 |
+
PY3 = sys.version_info[0] == 3
|
| 38 |
+
PY34 = sys.version_info[0:2] >= (3, 4)
|
| 39 |
+
|
| 40 |
+
if PY3:
|
| 41 |
+
string_types = (str,)
|
| 42 |
+
integer_types = (int,)
|
| 43 |
+
class_types = (type,)
|
| 44 |
+
text_type = str
|
| 45 |
+
binary_type = bytes
|
| 46 |
+
|
| 47 |
+
MAXSIZE = sys.maxsize
|
| 48 |
+
else:
|
| 49 |
+
string_types = (basestring,)
|
| 50 |
+
integer_types = (int, long)
|
| 51 |
+
class_types = (type, types.ClassType)
|
| 52 |
+
text_type = unicode
|
| 53 |
+
binary_type = str
|
| 54 |
+
|
| 55 |
+
if sys.platform.startswith("java"):
|
| 56 |
+
# Jython always uses 32 bits.
|
| 57 |
+
MAXSIZE = int((1 << 31) - 1)
|
| 58 |
+
else:
|
| 59 |
+
# It's possible to have sizeof(long) != sizeof(Py_ssize_t).
|
| 60 |
+
class X(object):
|
| 61 |
+
def __len__(self):
|
| 62 |
+
return 1 << 31
|
| 63 |
+
|
| 64 |
+
try:
|
| 65 |
+
len(X())
|
| 66 |
+
except OverflowError:
|
| 67 |
+
# 32-bit
|
| 68 |
+
MAXSIZE = int((1 << 31) - 1)
|
| 69 |
+
else:
|
| 70 |
+
# 64-bit
|
| 71 |
+
MAXSIZE = int((1 << 63) - 1)
|
| 72 |
+
del X
|
| 73 |
+
|
| 74 |
+
if PY34:
|
| 75 |
+
from importlib.util import spec_from_loader
|
| 76 |
+
else:
|
| 77 |
+
spec_from_loader = None
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
def _add_doc(func, doc):
|
| 81 |
+
"""Add documentation to a function."""
|
| 82 |
+
func.__doc__ = doc
|
| 83 |
+
|
| 84 |
+
|
| 85 |
+
def _import_module(name):
|
| 86 |
+
"""Import module, returning the module after the last dot."""
|
| 87 |
+
__import__(name)
|
| 88 |
+
return sys.modules[name]
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
class _LazyDescr(object):
|
| 92 |
+
def __init__(self, name):
|
| 93 |
+
self.name = name
|
| 94 |
+
|
| 95 |
+
def __get__(self, obj, tp):
|
| 96 |
+
result = self._resolve()
|
| 97 |
+
setattr(obj, self.name, result) # Invokes __set__.
|
| 98 |
+
try:
|
| 99 |
+
# This is a bit ugly, but it avoids running this again by
|
| 100 |
+
# removing this descriptor.
|
| 101 |
+
delattr(obj.__class__, self.name)
|
| 102 |
+
except AttributeError:
|
| 103 |
+
pass
|
| 104 |
+
return result
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
class MovedModule(_LazyDescr):
|
| 108 |
+
def __init__(self, name, old, new=None):
|
| 109 |
+
super(MovedModule, self).__init__(name)
|
| 110 |
+
if PY3:
|
| 111 |
+
if new is None:
|
| 112 |
+
new = name
|
| 113 |
+
self.mod = new
|
| 114 |
+
else:
|
| 115 |
+
self.mod = old
|
| 116 |
+
|
| 117 |
+
def _resolve(self):
|
| 118 |
+
return _import_module(self.mod)
|
| 119 |
+
|
| 120 |
+
def __getattr__(self, attr):
|
| 121 |
+
_module = self._resolve()
|
| 122 |
+
value = getattr(_module, attr)
|
| 123 |
+
setattr(self, attr, value)
|
| 124 |
+
return value
|
| 125 |
+
|
| 126 |
+
|
| 127 |
+
class _LazyModule(types.ModuleType):
|
| 128 |
+
def __init__(self, name):
|
| 129 |
+
super(_LazyModule, self).__init__(name)
|
| 130 |
+
self.__doc__ = self.__class__.__doc__
|
| 131 |
+
|
| 132 |
+
def __dir__(self):
|
| 133 |
+
attrs = ["__doc__", "__name__"]
|
| 134 |
+
attrs += [attr.name for attr in self._moved_attributes]
|
| 135 |
+
return attrs
|
| 136 |
+
|
| 137 |
+
# Subclasses should override this
|
| 138 |
+
_moved_attributes = []
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
class MovedAttribute(_LazyDescr):
|
| 142 |
+
def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None):
|
| 143 |
+
super(MovedAttribute, self).__init__(name)
|
| 144 |
+
if PY3:
|
| 145 |
+
if new_mod is None:
|
| 146 |
+
new_mod = name
|
| 147 |
+
self.mod = new_mod
|
| 148 |
+
if new_attr is None:
|
| 149 |
+
if old_attr is None:
|
| 150 |
+
new_attr = name
|
| 151 |
+
else:
|
| 152 |
+
new_attr = old_attr
|
| 153 |
+
self.attr = new_attr
|
| 154 |
+
else:
|
| 155 |
+
self.mod = old_mod
|
| 156 |
+
if old_attr is None:
|
| 157 |
+
old_attr = name
|
| 158 |
+
self.attr = old_attr
|
| 159 |
+
|
| 160 |
+
def _resolve(self):
|
| 161 |
+
module = _import_module(self.mod)
|
| 162 |
+
return getattr(module, self.attr)
|
| 163 |
+
|
| 164 |
+
|
| 165 |
+
class _SixMetaPathImporter(object):
|
| 166 |
+
|
| 167 |
+
"""
|
| 168 |
+
A meta path importer to import six.moves and its submodules.
|
| 169 |
+
|
| 170 |
+
This class implements a PEP302 finder and loader. It should be compatible
|
| 171 |
+
with Python 2.5 and all existing versions of Python3
|
| 172 |
+
"""
|
| 173 |
+
|
| 174 |
+
def __init__(self, six_module_name):
|
| 175 |
+
self.name = six_module_name
|
| 176 |
+
self.known_modules = {}
|
| 177 |
+
|
| 178 |
+
def _add_module(self, mod, *fullnames):
|
| 179 |
+
for fullname in fullnames:
|
| 180 |
+
self.known_modules[self.name + "." + fullname] = mod
|
| 181 |
+
|
| 182 |
+
def _get_module(self, fullname):
|
| 183 |
+
return self.known_modules[self.name + "." + fullname]
|
| 184 |
+
|
| 185 |
+
def find_module(self, fullname, path=None):
|
| 186 |
+
if fullname in self.known_modules:
|
| 187 |
+
return self
|
| 188 |
+
return None
|
| 189 |
+
|
| 190 |
+
def find_spec(self, fullname, path, target=None):
|
| 191 |
+
if fullname in self.known_modules:
|
| 192 |
+
return spec_from_loader(fullname, self)
|
| 193 |
+
return None
|
| 194 |
+
|
| 195 |
+
def __get_module(self, fullname):
|
| 196 |
+
try:
|
| 197 |
+
return self.known_modules[fullname]
|
| 198 |
+
except KeyError:
|
| 199 |
+
raise ImportError("This loader does not know module " + fullname)
|
| 200 |
+
|
| 201 |
+
def load_module(self, fullname):
|
| 202 |
+
try:
|
| 203 |
+
# in case of a reload
|
| 204 |
+
return sys.modules[fullname]
|
| 205 |
+
except KeyError:
|
| 206 |
+
pass
|
| 207 |
+
mod = self.__get_module(fullname)
|
| 208 |
+
if isinstance(mod, MovedModule):
|
| 209 |
+
mod = mod._resolve()
|
| 210 |
+
else:
|
| 211 |
+
mod.__loader__ = self
|
| 212 |
+
sys.modules[fullname] = mod
|
| 213 |
+
return mod
|
| 214 |
+
|
| 215 |
+
def is_package(self, fullname):
|
| 216 |
+
"""
|
| 217 |
+
Return true, if the named module is a package.
|
| 218 |
+
|
| 219 |
+
We need this method to get correct spec objects with
|
| 220 |
+
Python 3.4 (see PEP451)
|
| 221 |
+
"""
|
| 222 |
+
return hasattr(self.__get_module(fullname), "__path__")
|
| 223 |
+
|
| 224 |
+
def get_code(self, fullname):
|
| 225 |
+
"""Return None
|
| 226 |
+
|
| 227 |
+
Required, if is_package is implemented"""
|
| 228 |
+
self.__get_module(fullname) # eventually raises ImportError
|
| 229 |
+
return None
|
| 230 |
+
|
| 231 |
+
get_source = get_code # same as get_code
|
| 232 |
+
|
| 233 |
+
def create_module(self, spec):
|
| 234 |
+
return self.load_module(spec.name)
|
| 235 |
+
|
| 236 |
+
def exec_module(self, module):
|
| 237 |
+
pass
|
| 238 |
+
|
| 239 |
+
|
| 240 |
+
_importer = _SixMetaPathImporter(__name__)
|
| 241 |
+
|
| 242 |
+
|
| 243 |
+
class _MovedItems(_LazyModule):
|
| 244 |
+
|
| 245 |
+
"""Lazy loading of moved objects"""
|
| 246 |
+
|
| 247 |
+
__path__ = [] # mark as package
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
_moved_attributes = [
|
| 251 |
+
MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"),
|
| 252 |
+
MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"),
|
| 253 |
+
MovedAttribute(
|
| 254 |
+
"filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"
|
| 255 |
+
),
|
| 256 |
+
MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"),
|
| 257 |
+
MovedAttribute("intern", "__builtin__", "sys"),
|
| 258 |
+
MovedAttribute("map", "itertools", "builtins", "imap", "map"),
|
| 259 |
+
MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"),
|
| 260 |
+
MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"),
|
| 261 |
+
MovedAttribute("getoutput", "commands", "subprocess"),
|
| 262 |
+
MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"),
|
| 263 |
+
MovedAttribute(
|
| 264 |
+
"reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"
|
| 265 |
+
),
|
| 266 |
+
MovedAttribute("reduce", "__builtin__", "functools"),
|
| 267 |
+
MovedAttribute("shlex_quote", "pipes", "shlex", "quote"),
|
| 268 |
+
MovedAttribute("StringIO", "StringIO", "io"),
|
| 269 |
+
MovedAttribute("UserDict", "UserDict", "collections"),
|
| 270 |
+
MovedAttribute("UserList", "UserList", "collections"),
|
| 271 |
+
MovedAttribute("UserString", "UserString", "collections"),
|
| 272 |
+
MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"),
|
| 273 |
+
MovedAttribute("zip", "itertools", "builtins", "izip", "zip"),
|
| 274 |
+
MovedAttribute(
|
| 275 |
+
"zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"
|
| 276 |
+
),
|
| 277 |
+
MovedModule("builtins", "__builtin__"),
|
| 278 |
+
MovedModule("configparser", "ConfigParser"),
|
| 279 |
+
MovedModule(
|
| 280 |
+
"collections_abc",
|
| 281 |
+
"collections",
|
| 282 |
+
"collections.abc" if sys.version_info >= (3, 3) else "collections",
|
| 283 |
+
),
|
| 284 |
+
MovedModule("copyreg", "copy_reg"),
|
| 285 |
+
MovedModule("dbm_gnu", "gdbm", "dbm.gnu"),
|
| 286 |
+
MovedModule("dbm_ndbm", "dbm", "dbm.ndbm"),
|
| 287 |
+
MovedModule(
|
| 288 |
+
"_dummy_thread",
|
| 289 |
+
"dummy_thread",
|
| 290 |
+
"_dummy_thread" if sys.version_info < (3, 9) else "_thread",
|
| 291 |
+
),
|
| 292 |
+
MovedModule("http_cookiejar", "cookielib", "http.cookiejar"),
|
| 293 |
+
MovedModule("http_cookies", "Cookie", "http.cookies"),
|
| 294 |
+
MovedModule("html_entities", "htmlentitydefs", "html.entities"),
|
| 295 |
+
MovedModule("html_parser", "HTMLParser", "html.parser"),
|
| 296 |
+
MovedModule("http_client", "httplib", "http.client"),
|
| 297 |
+
MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"),
|
| 298 |
+
MovedModule("email_mime_image", "email.MIMEImage", "email.mime.image"),
|
| 299 |
+
MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"),
|
| 300 |
+
MovedModule(
|
| 301 |
+
"email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"
|
| 302 |
+
),
|
| 303 |
+
MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"),
|
| 304 |
+
MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"),
|
| 305 |
+
MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"),
|
| 306 |
+
MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"),
|
| 307 |
+
MovedModule("cPickle", "cPickle", "pickle"),
|
| 308 |
+
MovedModule("queue", "Queue"),
|
| 309 |
+
MovedModule("reprlib", "repr"),
|
| 310 |
+
MovedModule("socketserver", "SocketServer"),
|
| 311 |
+
MovedModule("_thread", "thread", "_thread"),
|
| 312 |
+
MovedModule("tkinter", "Tkinter"),
|
| 313 |
+
MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"),
|
| 314 |
+
MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"),
|
| 315 |
+
MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"),
|
| 316 |
+
MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"),
|
| 317 |
+
MovedModule("tkinter_tix", "Tix", "tkinter.tix"),
|
| 318 |
+
MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"),
|
| 319 |
+
MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"),
|
| 320 |
+
MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"),
|
| 321 |
+
MovedModule("tkinter_colorchooser", "tkColorChooser", "tkinter.colorchooser"),
|
| 322 |
+
MovedModule("tkinter_commondialog", "tkCommonDialog", "tkinter.commondialog"),
|
| 323 |
+
MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"),
|
| 324 |
+
MovedModule("tkinter_font", "tkFont", "tkinter.font"),
|
| 325 |
+
MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"),
|
| 326 |
+
MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", "tkinter.simpledialog"),
|
| 327 |
+
MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"),
|
| 328 |
+
MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"),
|
| 329 |
+
MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"),
|
| 330 |
+
MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"),
|
| 331 |
+
MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"),
|
| 332 |
+
MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"),
|
| 333 |
+
]
|
| 334 |
+
# Add windows specific modules.
|
| 335 |
+
if sys.platform == "win32":
|
| 336 |
+
_moved_attributes += [
|
| 337 |
+
MovedModule("winreg", "_winreg"),
|
| 338 |
+
]
|
| 339 |
+
|
| 340 |
+
for attr in _moved_attributes:
|
| 341 |
+
setattr(_MovedItems, attr.name, attr)
|
| 342 |
+
if isinstance(attr, MovedModule):
|
| 343 |
+
_importer._add_module(attr, "moves." + attr.name)
|
| 344 |
+
del attr
|
| 345 |
+
|
| 346 |
+
_MovedItems._moved_attributes = _moved_attributes
|
| 347 |
+
|
| 348 |
+
moves = _MovedItems(__name__ + ".moves")
|
| 349 |
+
_importer._add_module(moves, "moves")
|
| 350 |
+
|
| 351 |
+
|
| 352 |
+
class Module_six_moves_urllib_parse(_LazyModule):
|
| 353 |
+
|
| 354 |
+
"""Lazy loading of moved objects in six.moves.urllib_parse"""
|
| 355 |
+
|
| 356 |
+
|
| 357 |
+
_urllib_parse_moved_attributes = [
|
| 358 |
+
MovedAttribute("ParseResult", "urlparse", "urllib.parse"),
|
| 359 |
+
MovedAttribute("SplitResult", "urlparse", "urllib.parse"),
|
| 360 |
+
MovedAttribute("parse_qs", "urlparse", "urllib.parse"),
|
| 361 |
+
MovedAttribute("parse_qsl", "urlparse", "urllib.parse"),
|
| 362 |
+
MovedAttribute("urldefrag", "urlparse", "urllib.parse"),
|
| 363 |
+
MovedAttribute("urljoin", "urlparse", "urllib.parse"),
|
| 364 |
+
MovedAttribute("urlparse", "urlparse", "urllib.parse"),
|
| 365 |
+
MovedAttribute("urlsplit", "urlparse", "urllib.parse"),
|
| 366 |
+
MovedAttribute("urlunparse", "urlparse", "urllib.parse"),
|
| 367 |
+
MovedAttribute("urlunsplit", "urlparse", "urllib.parse"),
|
| 368 |
+
MovedAttribute("quote", "urllib", "urllib.parse"),
|
| 369 |
+
MovedAttribute("quote_plus", "urllib", "urllib.parse"),
|
| 370 |
+
MovedAttribute("unquote", "urllib", "urllib.parse"),
|
| 371 |
+
MovedAttribute("unquote_plus", "urllib", "urllib.parse"),
|
| 372 |
+
MovedAttribute(
|
| 373 |
+
"unquote_to_bytes", "urllib", "urllib.parse", "unquote", "unquote_to_bytes"
|
| 374 |
+
),
|
| 375 |
+
MovedAttribute("urlencode", "urllib", "urllib.parse"),
|
| 376 |
+
MovedAttribute("splitquery", "urllib", "urllib.parse"),
|
| 377 |
+
MovedAttribute("splittag", "urllib", "urllib.parse"),
|
| 378 |
+
MovedAttribute("splituser", "urllib", "urllib.parse"),
|
| 379 |
+
MovedAttribute("splitvalue", "urllib", "urllib.parse"),
|
| 380 |
+
MovedAttribute("uses_fragment", "urlparse", "urllib.parse"),
|
| 381 |
+
MovedAttribute("uses_netloc", "urlparse", "urllib.parse"),
|
| 382 |
+
MovedAttribute("uses_params", "urlparse", "urllib.parse"),
|
| 383 |
+
MovedAttribute("uses_query", "urlparse", "urllib.parse"),
|
| 384 |
+
MovedAttribute("uses_relative", "urlparse", "urllib.parse"),
|
| 385 |
+
]
|
| 386 |
+
for attr in _urllib_parse_moved_attributes:
|
| 387 |
+
setattr(Module_six_moves_urllib_parse, attr.name, attr)
|
| 388 |
+
del attr
|
| 389 |
+
|
| 390 |
+
Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes
|
| 391 |
+
|
| 392 |
+
_importer._add_module(
|
| 393 |
+
Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"),
|
| 394 |
+
"moves.urllib_parse",
|
| 395 |
+
"moves.urllib.parse",
|
| 396 |
+
)
|
| 397 |
+
|
| 398 |
+
|
| 399 |
+
class Module_six_moves_urllib_error(_LazyModule):
|
| 400 |
+
|
| 401 |
+
"""Lazy loading of moved objects in six.moves.urllib_error"""
|
| 402 |
+
|
| 403 |
+
|
| 404 |
+
_urllib_error_moved_attributes = [
|
| 405 |
+
MovedAttribute("URLError", "urllib2", "urllib.error"),
|
| 406 |
+
MovedAttribute("HTTPError", "urllib2", "urllib.error"),
|
| 407 |
+
MovedAttribute("ContentTooShortError", "urllib", "urllib.error"),
|
| 408 |
+
]
|
| 409 |
+
for attr in _urllib_error_moved_attributes:
|
| 410 |
+
setattr(Module_six_moves_urllib_error, attr.name, attr)
|
| 411 |
+
del attr
|
| 412 |
+
|
| 413 |
+
Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes
|
| 414 |
+
|
| 415 |
+
_importer._add_module(
|
| 416 |
+
Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"),
|
| 417 |
+
"moves.urllib_error",
|
| 418 |
+
"moves.urllib.error",
|
| 419 |
+
)
|
| 420 |
+
|
| 421 |
+
|
| 422 |
+
class Module_six_moves_urllib_request(_LazyModule):
|
| 423 |
+
|
| 424 |
+
"""Lazy loading of moved objects in six.moves.urllib_request"""
|
| 425 |
+
|
| 426 |
+
|
| 427 |
+
_urllib_request_moved_attributes = [
|
| 428 |
+
MovedAttribute("urlopen", "urllib2", "urllib.request"),
|
| 429 |
+
MovedAttribute("install_opener", "urllib2", "urllib.request"),
|
| 430 |
+
MovedAttribute("build_opener", "urllib2", "urllib.request"),
|
| 431 |
+
MovedAttribute("pathname2url", "urllib", "urllib.request"),
|
| 432 |
+
MovedAttribute("url2pathname", "urllib", "urllib.request"),
|
| 433 |
+
MovedAttribute("getproxies", "urllib", "urllib.request"),
|
| 434 |
+
MovedAttribute("Request", "urllib2", "urllib.request"),
|
| 435 |
+
MovedAttribute("OpenerDirector", "urllib2", "urllib.request"),
|
| 436 |
+
MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"),
|
| 437 |
+
MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"),
|
| 438 |
+
MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"),
|
| 439 |
+
MovedAttribute("ProxyHandler", "urllib2", "urllib.request"),
|
| 440 |
+
MovedAttribute("BaseHandler", "urllib2", "urllib.request"),
|
| 441 |
+
MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"),
|
| 442 |
+
MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"),
|
| 443 |
+
MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"),
|
| 444 |
+
MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"),
|
| 445 |
+
MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"),
|
| 446 |
+
MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"),
|
| 447 |
+
MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"),
|
| 448 |
+
MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"),
|
| 449 |
+
MovedAttribute("HTTPHandler", "urllib2", "urllib.request"),
|
| 450 |
+
MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"),
|
| 451 |
+
MovedAttribute("FileHandler", "urllib2", "urllib.request"),
|
| 452 |
+
MovedAttribute("FTPHandler", "urllib2", "urllib.request"),
|
| 453 |
+
MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"),
|
| 454 |
+
MovedAttribute("UnknownHandler", "urllib2", "urllib.request"),
|
| 455 |
+
MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"),
|
| 456 |
+
MovedAttribute("urlretrieve", "urllib", "urllib.request"),
|
| 457 |
+
MovedAttribute("urlcleanup", "urllib", "urllib.request"),
|
| 458 |
+
MovedAttribute("URLopener", "urllib", "urllib.request"),
|
| 459 |
+
MovedAttribute("FancyURLopener", "urllib", "urllib.request"),
|
| 460 |
+
MovedAttribute("proxy_bypass", "urllib", "urllib.request"),
|
| 461 |
+
MovedAttribute("parse_http_list", "urllib2", "urllib.request"),
|
| 462 |
+
MovedAttribute("parse_keqv_list", "urllib2", "urllib.request"),
|
| 463 |
+
]
|
| 464 |
+
for attr in _urllib_request_moved_attributes:
|
| 465 |
+
setattr(Module_six_moves_urllib_request, attr.name, attr)
|
| 466 |
+
del attr
|
| 467 |
+
|
| 468 |
+
Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes
|
| 469 |
+
|
| 470 |
+
_importer._add_module(
|
| 471 |
+
Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"),
|
| 472 |
+
"moves.urllib_request",
|
| 473 |
+
"moves.urllib.request",
|
| 474 |
+
)
|
| 475 |
+
|
| 476 |
+
|
| 477 |
+
class Module_six_moves_urllib_response(_LazyModule):
|
| 478 |
+
|
| 479 |
+
"""Lazy loading of moved objects in six.moves.urllib_response"""
|
| 480 |
+
|
| 481 |
+
|
| 482 |
+
_urllib_response_moved_attributes = [
|
| 483 |
+
MovedAttribute("addbase", "urllib", "urllib.response"),
|
| 484 |
+
MovedAttribute("addclosehook", "urllib", "urllib.response"),
|
| 485 |
+
MovedAttribute("addinfo", "urllib", "urllib.response"),
|
| 486 |
+
MovedAttribute("addinfourl", "urllib", "urllib.response"),
|
| 487 |
+
]
|
| 488 |
+
for attr in _urllib_response_moved_attributes:
|
| 489 |
+
setattr(Module_six_moves_urllib_response, attr.name, attr)
|
| 490 |
+
del attr
|
| 491 |
+
|
| 492 |
+
Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes
|
| 493 |
+
|
| 494 |
+
_importer._add_module(
|
| 495 |
+
Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"),
|
| 496 |
+
"moves.urllib_response",
|
| 497 |
+
"moves.urllib.response",
|
| 498 |
+
)
|
| 499 |
+
|
| 500 |
+
|
| 501 |
+
class Module_six_moves_urllib_robotparser(_LazyModule):
|
| 502 |
+
|
| 503 |
+
"""Lazy loading of moved objects in six.moves.urllib_robotparser"""
|
| 504 |
+
|
| 505 |
+
|
| 506 |
+
_urllib_robotparser_moved_attributes = [
|
| 507 |
+
MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"),
|
| 508 |
+
]
|
| 509 |
+
for attr in _urllib_robotparser_moved_attributes:
|
| 510 |
+
setattr(Module_six_moves_urllib_robotparser, attr.name, attr)
|
| 511 |
+
del attr
|
| 512 |
+
|
| 513 |
+
Module_six_moves_urllib_robotparser._moved_attributes = (
|
| 514 |
+
_urllib_robotparser_moved_attributes
|
| 515 |
+
)
|
| 516 |
+
|
| 517 |
+
_importer._add_module(
|
| 518 |
+
Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"),
|
| 519 |
+
"moves.urllib_robotparser",
|
| 520 |
+
"moves.urllib.robotparser",
|
| 521 |
+
)
|
| 522 |
+
|
| 523 |
+
|
| 524 |
+
class Module_six_moves_urllib(types.ModuleType):
|
| 525 |
+
|
| 526 |
+
"""Create a six.moves.urllib namespace that resembles the Python 3 namespace"""
|
| 527 |
+
|
| 528 |
+
__path__ = [] # mark as package
|
| 529 |
+
parse = _importer._get_module("moves.urllib_parse")
|
| 530 |
+
error = _importer._get_module("moves.urllib_error")
|
| 531 |
+
request = _importer._get_module("moves.urllib_request")
|
| 532 |
+
response = _importer._get_module("moves.urllib_response")
|
| 533 |
+
robotparser = _importer._get_module("moves.urllib_robotparser")
|
| 534 |
+
|
| 535 |
+
def __dir__(self):
|
| 536 |
+
return ["parse", "error", "request", "response", "robotparser"]
|
| 537 |
+
|
| 538 |
+
|
| 539 |
+
_importer._add_module(
|
| 540 |
+
Module_six_moves_urllib(__name__ + ".moves.urllib"), "moves.urllib"
|
| 541 |
+
)
|
| 542 |
+
|
| 543 |
+
|
| 544 |
+
def add_move(move):
|
| 545 |
+
"""Add an item to six.moves."""
|
| 546 |
+
setattr(_MovedItems, move.name, move)
|
| 547 |
+
|
| 548 |
+
|
| 549 |
+
def remove_move(name):
|
| 550 |
+
"""Remove item from six.moves."""
|
| 551 |
+
try:
|
| 552 |
+
delattr(_MovedItems, name)
|
| 553 |
+
except AttributeError:
|
| 554 |
+
try:
|
| 555 |
+
del moves.__dict__[name]
|
| 556 |
+
except KeyError:
|
| 557 |
+
raise AttributeError("no such move, %r" % (name,))
|
| 558 |
+
|
| 559 |
+
|
| 560 |
+
if PY3:
|
| 561 |
+
_meth_func = "__func__"
|
| 562 |
+
_meth_self = "__self__"
|
| 563 |
+
|
| 564 |
+
_func_closure = "__closure__"
|
| 565 |
+
_func_code = "__code__"
|
| 566 |
+
_func_defaults = "__defaults__"
|
| 567 |
+
_func_globals = "__globals__"
|
| 568 |
+
else:
|
| 569 |
+
_meth_func = "im_func"
|
| 570 |
+
_meth_self = "im_self"
|
| 571 |
+
|
| 572 |
+
_func_closure = "func_closure"
|
| 573 |
+
_func_code = "func_code"
|
| 574 |
+
_func_defaults = "func_defaults"
|
| 575 |
+
_func_globals = "func_globals"
|
| 576 |
+
|
| 577 |
+
|
| 578 |
+
try:
|
| 579 |
+
advance_iterator = next
|
| 580 |
+
except NameError:
|
| 581 |
+
|
| 582 |
+
def advance_iterator(it):
|
| 583 |
+
return it.next()
|
| 584 |
+
|
| 585 |
+
|
| 586 |
+
next = advance_iterator
|
| 587 |
+
|
| 588 |
+
|
| 589 |
+
try:
|
| 590 |
+
callable = callable
|
| 591 |
+
except NameError:
|
| 592 |
+
|
| 593 |
+
def callable(obj):
|
| 594 |
+
return any("__call__" in klass.__dict__ for klass in type(obj).__mro__)
|
| 595 |
+
|
| 596 |
+
|
| 597 |
+
if PY3:
|
| 598 |
+
|
| 599 |
+
def get_unbound_function(unbound):
|
| 600 |
+
return unbound
|
| 601 |
+
|
| 602 |
+
create_bound_method = types.MethodType
|
| 603 |
+
|
| 604 |
+
def create_unbound_method(func, cls):
|
| 605 |
+
return func
|
| 606 |
+
|
| 607 |
+
Iterator = object
|
| 608 |
+
else:
|
| 609 |
+
|
| 610 |
+
def get_unbound_function(unbound):
|
| 611 |
+
return unbound.im_func
|
| 612 |
+
|
| 613 |
+
def create_bound_method(func, obj):
|
| 614 |
+
return types.MethodType(func, obj, obj.__class__)
|
| 615 |
+
|
| 616 |
+
def create_unbound_method(func, cls):
|
| 617 |
+
return types.MethodType(func, None, cls)
|
| 618 |
+
|
| 619 |
+
class Iterator(object):
|
| 620 |
+
def next(self):
|
| 621 |
+
return type(self).__next__(self)
|
| 622 |
+
|
| 623 |
+
callable = callable
|
| 624 |
+
_add_doc(
|
| 625 |
+
get_unbound_function, """Get the function out of a possibly unbound function"""
|
| 626 |
+
)
|
| 627 |
+
|
| 628 |
+
|
| 629 |
+
get_method_function = operator.attrgetter(_meth_func)
|
| 630 |
+
get_method_self = operator.attrgetter(_meth_self)
|
| 631 |
+
get_function_closure = operator.attrgetter(_func_closure)
|
| 632 |
+
get_function_code = operator.attrgetter(_func_code)
|
| 633 |
+
get_function_defaults = operator.attrgetter(_func_defaults)
|
| 634 |
+
get_function_globals = operator.attrgetter(_func_globals)
|
| 635 |
+
|
| 636 |
+
|
| 637 |
+
if PY3:
|
| 638 |
+
|
| 639 |
+
def iterkeys(d, **kw):
|
| 640 |
+
return iter(d.keys(**kw))
|
| 641 |
+
|
| 642 |
+
def itervalues(d, **kw):
|
| 643 |
+
return iter(d.values(**kw))
|
| 644 |
+
|
| 645 |
+
def iteritems(d, **kw):
|
| 646 |
+
return iter(d.items(**kw))
|
| 647 |
+
|
| 648 |
+
def iterlists(d, **kw):
|
| 649 |
+
return iter(d.lists(**kw))
|
| 650 |
+
|
| 651 |
+
viewkeys = operator.methodcaller("keys")
|
| 652 |
+
|
| 653 |
+
viewvalues = operator.methodcaller("values")
|
| 654 |
+
|
| 655 |
+
viewitems = operator.methodcaller("items")
|
| 656 |
+
else:
|
| 657 |
+
|
| 658 |
+
def iterkeys(d, **kw):
|
| 659 |
+
return d.iterkeys(**kw)
|
| 660 |
+
|
| 661 |
+
def itervalues(d, **kw):
|
| 662 |
+
return d.itervalues(**kw)
|
| 663 |
+
|
| 664 |
+
def iteritems(d, **kw):
|
| 665 |
+
return d.iteritems(**kw)
|
| 666 |
+
|
| 667 |
+
def iterlists(d, **kw):
|
| 668 |
+
return d.iterlists(**kw)
|
| 669 |
+
|
| 670 |
+
viewkeys = operator.methodcaller("viewkeys")
|
| 671 |
+
|
| 672 |
+
viewvalues = operator.methodcaller("viewvalues")
|
| 673 |
+
|
| 674 |
+
viewitems = operator.methodcaller("viewitems")
|
| 675 |
+
|
| 676 |
+
_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.")
|
| 677 |
+
_add_doc(itervalues, "Return an iterator over the values of a dictionary.")
|
| 678 |
+
_add_doc(iteritems, "Return an iterator over the (key, value) pairs of a dictionary.")
|
| 679 |
+
_add_doc(
|
| 680 |
+
iterlists, "Return an iterator over the (key, [values]) pairs of a dictionary."
|
| 681 |
+
)
|
| 682 |
+
|
| 683 |
+
|
| 684 |
+
if PY3:
|
| 685 |
+
|
| 686 |
+
def b(s):
|
| 687 |
+
return s.encode("latin-1")
|
| 688 |
+
|
| 689 |
+
def u(s):
|
| 690 |
+
return s
|
| 691 |
+
|
| 692 |
+
unichr = chr
|
| 693 |
+
import struct
|
| 694 |
+
|
| 695 |
+
int2byte = struct.Struct(">B").pack
|
| 696 |
+
del struct
|
| 697 |
+
byte2int = operator.itemgetter(0)
|
| 698 |
+
indexbytes = operator.getitem
|
| 699 |
+
iterbytes = iter
|
| 700 |
+
import io
|
| 701 |
+
|
| 702 |
+
StringIO = io.StringIO
|
| 703 |
+
BytesIO = io.BytesIO
|
| 704 |
+
del io
|
| 705 |
+
_assertCountEqual = "assertCountEqual"
|
| 706 |
+
if sys.version_info[1] <= 1:
|
| 707 |
+
_assertRaisesRegex = "assertRaisesRegexp"
|
| 708 |
+
_assertRegex = "assertRegexpMatches"
|
| 709 |
+
_assertNotRegex = "assertNotRegexpMatches"
|
| 710 |
+
else:
|
| 711 |
+
_assertRaisesRegex = "assertRaisesRegex"
|
| 712 |
+
_assertRegex = "assertRegex"
|
| 713 |
+
_assertNotRegex = "assertNotRegex"
|
| 714 |
+
else:
|
| 715 |
+
|
| 716 |
+
def b(s):
|
| 717 |
+
return s
|
| 718 |
+
|
| 719 |
+
# Workaround for standalone backslash
|
| 720 |
+
|
| 721 |
+
def u(s):
|
| 722 |
+
return unicode(s.replace(r"\\", r"\\\\"), "unicode_escape")
|
| 723 |
+
|
| 724 |
+
unichr = unichr
|
| 725 |
+
int2byte = chr
|
| 726 |
+
|
| 727 |
+
def byte2int(bs):
|
| 728 |
+
return ord(bs[0])
|
| 729 |
+
|
| 730 |
+
def indexbytes(buf, i):
|
| 731 |
+
return ord(buf[i])
|
| 732 |
+
|
| 733 |
+
iterbytes = functools.partial(itertools.imap, ord)
|
| 734 |
+
import StringIO
|
| 735 |
+
|
| 736 |
+
StringIO = BytesIO = StringIO.StringIO
|
| 737 |
+
_assertCountEqual = "assertItemsEqual"
|
| 738 |
+
_assertRaisesRegex = "assertRaisesRegexp"
|
| 739 |
+
_assertRegex = "assertRegexpMatches"
|
| 740 |
+
_assertNotRegex = "assertNotRegexpMatches"
|
| 741 |
+
_add_doc(b, """Byte literal""")
|
| 742 |
+
_add_doc(u, """Text literal""")
|
| 743 |
+
|
| 744 |
+
|
| 745 |
+
def assertCountEqual(self, *args, **kwargs):
|
| 746 |
+
return getattr(self, _assertCountEqual)(*args, **kwargs)
|
| 747 |
+
|
| 748 |
+
|
| 749 |
+
def assertRaisesRegex(self, *args, **kwargs):
|
| 750 |
+
return getattr(self, _assertRaisesRegex)(*args, **kwargs)
|
| 751 |
+
|
| 752 |
+
|
| 753 |
+
def assertRegex(self, *args, **kwargs):
|
| 754 |
+
return getattr(self, _assertRegex)(*args, **kwargs)
|
| 755 |
+
|
| 756 |
+
|
| 757 |
+
def assertNotRegex(self, *args, **kwargs):
|
| 758 |
+
return getattr(self, _assertNotRegex)(*args, **kwargs)
|
| 759 |
+
|
| 760 |
+
|
| 761 |
+
if PY3:
|
| 762 |
+
exec_ = getattr(moves.builtins, "exec")
|
| 763 |
+
|
| 764 |
+
def reraise(tp, value, tb=None):
|
| 765 |
+
try:
|
| 766 |
+
if value is None:
|
| 767 |
+
value = tp()
|
| 768 |
+
if value.__traceback__ is not tb:
|
| 769 |
+
raise value.with_traceback(tb)
|
| 770 |
+
raise value
|
| 771 |
+
finally:
|
| 772 |
+
value = None
|
| 773 |
+
tb = None
|
| 774 |
+
|
| 775 |
+
else:
|
| 776 |
+
|
| 777 |
+
def exec_(_code_, _globs_=None, _locs_=None):
|
| 778 |
+
"""Execute code in a namespace."""
|
| 779 |
+
if _globs_ is None:
|
| 780 |
+
frame = sys._getframe(1)
|
| 781 |
+
_globs_ = frame.f_globals
|
| 782 |
+
if _locs_ is None:
|
| 783 |
+
_locs_ = frame.f_locals
|
| 784 |
+
del frame
|
| 785 |
+
elif _locs_ is None:
|
| 786 |
+
_locs_ = _globs_
|
| 787 |
+
exec ("""exec _code_ in _globs_, _locs_""")
|
| 788 |
+
|
| 789 |
+
exec_(
|
| 790 |
+
"""def reraise(tp, value, tb=None):
|
| 791 |
+
try:
|
| 792 |
+
raise tp, value, tb
|
| 793 |
+
finally:
|
| 794 |
+
tb = None
|
| 795 |
+
"""
|
| 796 |
+
)
|
| 797 |
+
|
| 798 |
+
|
| 799 |
+
if sys.version_info[:2] > (3,):
|
| 800 |
+
exec_(
|
| 801 |
+
"""def raise_from(value, from_value):
|
| 802 |
+
try:
|
| 803 |
+
raise value from from_value
|
| 804 |
+
finally:
|
| 805 |
+
value = None
|
| 806 |
+
"""
|
| 807 |
+
)
|
| 808 |
+
else:
|
| 809 |
+
|
| 810 |
+
def raise_from(value, from_value):
|
| 811 |
+
raise value
|
| 812 |
+
|
| 813 |
+
|
| 814 |
+
print_ = getattr(moves.builtins, "print", None)
|
| 815 |
+
if print_ is None:
|
| 816 |
+
|
| 817 |
+
def print_(*args, **kwargs):
|
| 818 |
+
"""The new-style print function for Python 2.4 and 2.5."""
|
| 819 |
+
fp = kwargs.pop("file", sys.stdout)
|
| 820 |
+
if fp is None:
|
| 821 |
+
return
|
| 822 |
+
|
| 823 |
+
def write(data):
|
| 824 |
+
if not isinstance(data, basestring):
|
| 825 |
+
data = str(data)
|
| 826 |
+
# If the file has an encoding, encode unicode with it.
|
| 827 |
+
if (
|
| 828 |
+
isinstance(fp, file)
|
| 829 |
+
and isinstance(data, unicode)
|
| 830 |
+
and fp.encoding is not None
|
| 831 |
+
):
|
| 832 |
+
errors = getattr(fp, "errors", None)
|
| 833 |
+
if errors is None:
|
| 834 |
+
errors = "strict"
|
| 835 |
+
data = data.encode(fp.encoding, errors)
|
| 836 |
+
fp.write(data)
|
| 837 |
+
|
| 838 |
+
want_unicode = False
|
| 839 |
+
sep = kwargs.pop("sep", None)
|
| 840 |
+
if sep is not None:
|
| 841 |
+
if isinstance(sep, unicode):
|
| 842 |
+
want_unicode = True
|
| 843 |
+
elif not isinstance(sep, str):
|
| 844 |
+
raise TypeError("sep must be None or a string")
|
| 845 |
+
end = kwargs.pop("end", None)
|
| 846 |
+
if end is not None:
|
| 847 |
+
if isinstance(end, unicode):
|
| 848 |
+
want_unicode = True
|
| 849 |
+
elif not isinstance(end, str):
|
| 850 |
+
raise TypeError("end must be None or a string")
|
| 851 |
+
if kwargs:
|
| 852 |
+
raise TypeError("invalid keyword arguments to print()")
|
| 853 |
+
if not want_unicode:
|
| 854 |
+
for arg in args:
|
| 855 |
+
if isinstance(arg, unicode):
|
| 856 |
+
want_unicode = True
|
| 857 |
+
break
|
| 858 |
+
if want_unicode:
|
| 859 |
+
newline = unicode("\n")
|
| 860 |
+
space = unicode(" ")
|
| 861 |
+
else:
|
| 862 |
+
newline = "\n"
|
| 863 |
+
space = " "
|
| 864 |
+
if sep is None:
|
| 865 |
+
sep = space
|
| 866 |
+
if end is None:
|
| 867 |
+
end = newline
|
| 868 |
+
for i, arg in enumerate(args):
|
| 869 |
+
if i:
|
| 870 |
+
write(sep)
|
| 871 |
+
write(arg)
|
| 872 |
+
write(end)
|
| 873 |
+
|
| 874 |
+
|
| 875 |
+
if sys.version_info[:2] < (3, 3):
|
| 876 |
+
_print = print_
|
| 877 |
+
|
| 878 |
+
def print_(*args, **kwargs):
|
| 879 |
+
fp = kwargs.get("file", sys.stdout)
|
| 880 |
+
flush = kwargs.pop("flush", False)
|
| 881 |
+
_print(*args, **kwargs)
|
| 882 |
+
if flush and fp is not None:
|
| 883 |
+
fp.flush()
|
| 884 |
+
|
| 885 |
+
|
| 886 |
+
_add_doc(reraise, """Reraise an exception.""")
|
| 887 |
+
|
| 888 |
+
if sys.version_info[0:2] < (3, 4):
|
| 889 |
+
# This does exactly the same what the :func:`py3:functools.update_wrapper`
|
| 890 |
+
# function does on Python versions after 3.2. It sets the ``__wrapped__``
|
| 891 |
+
# attribute on ``wrapper`` object and it doesn't raise an error if any of
|
| 892 |
+
# the attributes mentioned in ``assigned`` and ``updated`` are missing on
|
| 893 |
+
# ``wrapped`` object.
|
| 894 |
+
def _update_wrapper(
|
| 895 |
+
wrapper,
|
| 896 |
+
wrapped,
|
| 897 |
+
assigned=functools.WRAPPER_ASSIGNMENTS,
|
| 898 |
+
updated=functools.WRAPPER_UPDATES,
|
| 899 |
+
):
|
| 900 |
+
for attr in assigned:
|
| 901 |
+
try:
|
| 902 |
+
value = getattr(wrapped, attr)
|
| 903 |
+
except AttributeError:
|
| 904 |
+
continue
|
| 905 |
+
else:
|
| 906 |
+
setattr(wrapper, attr, value)
|
| 907 |
+
for attr in updated:
|
| 908 |
+
getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
|
| 909 |
+
wrapper.__wrapped__ = wrapped
|
| 910 |
+
return wrapper
|
| 911 |
+
|
| 912 |
+
_update_wrapper.__doc__ = functools.update_wrapper.__doc__
|
| 913 |
+
|
| 914 |
+
def wraps(
|
| 915 |
+
wrapped,
|
| 916 |
+
assigned=functools.WRAPPER_ASSIGNMENTS,
|
| 917 |
+
updated=functools.WRAPPER_UPDATES,
|
| 918 |
+
):
|
| 919 |
+
return functools.partial(
|
| 920 |
+
_update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated
|
| 921 |
+
)
|
| 922 |
+
|
| 923 |
+
wraps.__doc__ = functools.wraps.__doc__
|
| 924 |
+
|
| 925 |
+
else:
|
| 926 |
+
wraps = functools.wraps
|
| 927 |
+
|
| 928 |
+
|
| 929 |
+
def with_metaclass(meta, *bases):
|
| 930 |
+
"""Create a base class with a metaclass."""
|
| 931 |
+
# This requires a bit of explanation: the basic idea is to make a dummy
|
| 932 |
+
# metaclass for one level of class instantiation that replaces itself with
|
| 933 |
+
# the actual metaclass.
|
| 934 |
+
class metaclass(type):
|
| 935 |
+
def __new__(cls, name, this_bases, d):
|
| 936 |
+
if sys.version_info[:2] >= (3, 7):
|
| 937 |
+
# This version introduced PEP 560 that requires a bit
|
| 938 |
+
# of extra care (we mimic what is done by __build_class__).
|
| 939 |
+
resolved_bases = types.resolve_bases(bases)
|
| 940 |
+
if resolved_bases is not bases:
|
| 941 |
+
d["__orig_bases__"] = bases
|
| 942 |
+
else:
|
| 943 |
+
resolved_bases = bases
|
| 944 |
+
return meta(name, resolved_bases, d)
|
| 945 |
+
|
| 946 |
+
@classmethod
|
| 947 |
+
def __prepare__(cls, name, this_bases):
|
| 948 |
+
return meta.__prepare__(name, bases)
|
| 949 |
+
|
| 950 |
+
return type.__new__(metaclass, "temporary_class", (), {})
|
| 951 |
+
|
| 952 |
+
|
| 953 |
+
def add_metaclass(metaclass):
|
| 954 |
+
"""Class decorator for creating a class with a metaclass."""
|
| 955 |
+
|
| 956 |
+
def wrapper(cls):
|
| 957 |
+
orig_vars = cls.__dict__.copy()
|
| 958 |
+
slots = orig_vars.get("__slots__")
|
| 959 |
+
if slots is not None:
|
| 960 |
+
if isinstance(slots, str):
|
| 961 |
+
slots = [slots]
|
| 962 |
+
for slots_var in slots:
|
| 963 |
+
orig_vars.pop(slots_var)
|
| 964 |
+
orig_vars.pop("__dict__", None)
|
| 965 |
+
orig_vars.pop("__weakref__", None)
|
| 966 |
+
if hasattr(cls, "__qualname__"):
|
| 967 |
+
orig_vars["__qualname__"] = cls.__qualname__
|
| 968 |
+
return metaclass(cls.__name__, cls.__bases__, orig_vars)
|
| 969 |
+
|
| 970 |
+
return wrapper
|
| 971 |
+
|
| 972 |
+
|
| 973 |
+
def ensure_binary(s, encoding="utf-8", errors="strict"):
|
| 974 |
+
"""Coerce **s** to six.binary_type.
|
| 975 |
+
|
| 976 |
+
For Python 2:
|
| 977 |
+
- `unicode` -> encoded to `str`
|
| 978 |
+
- `str` -> `str`
|
| 979 |
+
|
| 980 |
+
For Python 3:
|
| 981 |
+
- `str` -> encoded to `bytes`
|
| 982 |
+
- `bytes` -> `bytes`
|
| 983 |
+
"""
|
| 984 |
+
if isinstance(s, binary_type):
|
| 985 |
+
return s
|
| 986 |
+
if isinstance(s, text_type):
|
| 987 |
+
return s.encode(encoding, errors)
|
| 988 |
+
raise TypeError("not expecting type '%s'" % type(s))
|
| 989 |
+
|
| 990 |
+
|
| 991 |
+
def ensure_str(s, encoding="utf-8", errors="strict"):
|
| 992 |
+
"""Coerce *s* to `str`.
|
| 993 |
+
|
| 994 |
+
For Python 2:
|
| 995 |
+
- `unicode` -> encoded to `str`
|
| 996 |
+
- `str` -> `str`
|
| 997 |
+
|
| 998 |
+
For Python 3:
|
| 999 |
+
- `str` -> `str`
|
| 1000 |
+
- `bytes` -> decoded to `str`
|
| 1001 |
+
"""
|
| 1002 |
+
# Optimization: Fast return for the common case.
|
| 1003 |
+
if type(s) is str:
|
| 1004 |
+
return s
|
| 1005 |
+
if PY2 and isinstance(s, text_type):
|
| 1006 |
+
return s.encode(encoding, errors)
|
| 1007 |
+
elif PY3 and isinstance(s, binary_type):
|
| 1008 |
+
return s.decode(encoding, errors)
|
| 1009 |
+
elif not isinstance(s, (text_type, binary_type)):
|
| 1010 |
+
raise TypeError("not expecting type '%s'" % type(s))
|
| 1011 |
+
return s
|
| 1012 |
+
|
| 1013 |
+
|
| 1014 |
+
def ensure_text(s, encoding="utf-8", errors="strict"):
|
| 1015 |
+
"""Coerce *s* to six.text_type.
|
| 1016 |
+
|
| 1017 |
+
For Python 2:
|
| 1018 |
+
- `unicode` -> `unicode`
|
| 1019 |
+
- `str` -> `unicode`
|
| 1020 |
+
|
| 1021 |
+
For Python 3:
|
| 1022 |
+
- `str` -> `str`
|
| 1023 |
+
- `bytes` -> decoded to `str`
|
| 1024 |
+
"""
|
| 1025 |
+
if isinstance(s, binary_type):
|
| 1026 |
+
return s.decode(encoding, errors)
|
| 1027 |
+
elif isinstance(s, text_type):
|
| 1028 |
+
return s
|
| 1029 |
+
else:
|
| 1030 |
+
raise TypeError("not expecting type '%s'" % type(s))
|
| 1031 |
+
|
| 1032 |
+
|
| 1033 |
+
def python_2_unicode_compatible(klass):
|
| 1034 |
+
"""
|
| 1035 |
+
A class decorator that defines __unicode__ and __str__ methods under Python 2.
|
| 1036 |
+
Under Python 3 it does nothing.
|
| 1037 |
+
|
| 1038 |
+
To support Python 2 and 3 with a single code base, define a __str__ method
|
| 1039 |
+
returning text and apply this decorator to the class.
|
| 1040 |
+
"""
|
| 1041 |
+
if PY2:
|
| 1042 |
+
if "__str__" not in klass.__dict__:
|
| 1043 |
+
raise ValueError(
|
| 1044 |
+
"@python_2_unicode_compatible cannot be applied "
|
| 1045 |
+
"to %s because it doesn't define __str__()." % klass.__name__
|
| 1046 |
+
)
|
| 1047 |
+
klass.__unicode__ = klass.__str__
|
| 1048 |
+
klass.__str__ = lambda self: self.__unicode__().encode("utf-8")
|
| 1049 |
+
return klass
|
| 1050 |
+
|
| 1051 |
+
|
| 1052 |
+
# Complete the moves implementation.
|
| 1053 |
+
# This code is at the end of this module to speed up module loading.
|
| 1054 |
+
# Turn this module into a package.
|
| 1055 |
+
__path__ = [] # required for PEP 302 and PEP 451
|
| 1056 |
+
__package__ = __name__ # see PEP 366 @ReservedAssignment
|
| 1057 |
+
if globals().get("__spec__") is not None:
|
| 1058 |
+
__spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable
|
| 1059 |
+
# Remove other six meta path importers, since they cause problems. This can
|
| 1060 |
+
# happen if six is removed from sys.modules and then reloaded. (Setuptools does
|
| 1061 |
+
# this for some reason.)
|
| 1062 |
+
if sys.meta_path:
|
| 1063 |
+
for i, importer in enumerate(sys.meta_path):
|
| 1064 |
+
# Here's some real nastiness: Another "instance" of the six module might
|
| 1065 |
+
# be floating around. Therefore, we can't use isinstance() to check for
|
| 1066 |
+
# the six meta path importer, since the other six instance will have
|
| 1067 |
+
# inserted an importer with different class.
|
| 1068 |
+
if (
|
| 1069 |
+
type(importer).__name__ == "_SixMetaPathImporter"
|
| 1070 |
+
and importer.name == __name__
|
| 1071 |
+
):
|
| 1072 |
+
del sys.meta_path[i]
|
| 1073 |
+
break
|
| 1074 |
+
del i, importer
|
| 1075 |
+
# Finally, add the importer to the meta path import hook.
|
| 1076 |
+
sys.meta_path.append(_importer)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/poolmanager.py
ADDED
|
@@ -0,0 +1,556 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import collections
|
| 4 |
+
import functools
|
| 5 |
+
import logging
|
| 6 |
+
|
| 7 |
+
from ._collections import HTTPHeaderDict, RecentlyUsedContainer
|
| 8 |
+
from .connectionpool import HTTPConnectionPool, HTTPSConnectionPool, port_by_scheme
|
| 9 |
+
from .exceptions import (
|
| 10 |
+
LocationValueError,
|
| 11 |
+
MaxRetryError,
|
| 12 |
+
ProxySchemeUnknown,
|
| 13 |
+
ProxySchemeUnsupported,
|
| 14 |
+
URLSchemeUnknown,
|
| 15 |
+
)
|
| 16 |
+
from .packages import six
|
| 17 |
+
from .packages.six.moves.urllib.parse import urljoin
|
| 18 |
+
from .request import RequestMethods
|
| 19 |
+
from .util.proxy import connection_requires_http_tunnel
|
| 20 |
+
from .util.retry import Retry
|
| 21 |
+
from .util.url import parse_url
|
| 22 |
+
|
| 23 |
+
__all__ = ["PoolManager", "ProxyManager", "proxy_from_url"]
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
log = logging.getLogger(__name__)
|
| 27 |
+
|
| 28 |
+
SSL_KEYWORDS = (
|
| 29 |
+
"key_file",
|
| 30 |
+
"cert_file",
|
| 31 |
+
"cert_reqs",
|
| 32 |
+
"ca_certs",
|
| 33 |
+
"ssl_version",
|
| 34 |
+
"ca_cert_dir",
|
| 35 |
+
"ssl_context",
|
| 36 |
+
"key_password",
|
| 37 |
+
"server_hostname",
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
# All known keyword arguments that could be provided to the pool manager, its
|
| 41 |
+
# pools, or the underlying connections. This is used to construct a pool key.
|
| 42 |
+
_key_fields = (
|
| 43 |
+
"key_scheme", # str
|
| 44 |
+
"key_host", # str
|
| 45 |
+
"key_port", # int
|
| 46 |
+
"key_timeout", # int or float or Timeout
|
| 47 |
+
"key_retries", # int or Retry
|
| 48 |
+
"key_strict", # bool
|
| 49 |
+
"key_block", # bool
|
| 50 |
+
"key_source_address", # str
|
| 51 |
+
"key_key_file", # str
|
| 52 |
+
"key_key_password", # str
|
| 53 |
+
"key_cert_file", # str
|
| 54 |
+
"key_cert_reqs", # str
|
| 55 |
+
"key_ca_certs", # str
|
| 56 |
+
"key_ssl_version", # str
|
| 57 |
+
"key_ca_cert_dir", # str
|
| 58 |
+
"key_ssl_context", # instance of ssl.SSLContext or urllib3.util.ssl_.SSLContext
|
| 59 |
+
"key_maxsize", # int
|
| 60 |
+
"key_headers", # dict
|
| 61 |
+
"key__proxy", # parsed proxy url
|
| 62 |
+
"key__proxy_headers", # dict
|
| 63 |
+
"key__proxy_config", # class
|
| 64 |
+
"key_socket_options", # list of (level (int), optname (int), value (int or str)) tuples
|
| 65 |
+
"key__socks_options", # dict
|
| 66 |
+
"key_assert_hostname", # bool or string
|
| 67 |
+
"key_assert_fingerprint", # str
|
| 68 |
+
"key_server_hostname", # str
|
| 69 |
+
)
|
| 70 |
+
|
| 71 |
+
#: The namedtuple class used to construct keys for the connection pool.
|
| 72 |
+
#: All custom key schemes should include the fields in this key at a minimum.
|
| 73 |
+
PoolKey = collections.namedtuple("PoolKey", _key_fields)
|
| 74 |
+
|
| 75 |
+
_proxy_config_fields = ("ssl_context", "use_forwarding_for_https")
|
| 76 |
+
ProxyConfig = collections.namedtuple("ProxyConfig", _proxy_config_fields)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def _default_key_normalizer(key_class, request_context):
|
| 80 |
+
"""
|
| 81 |
+
Create a pool key out of a request context dictionary.
|
| 82 |
+
|
| 83 |
+
According to RFC 3986, both the scheme and host are case-insensitive.
|
| 84 |
+
Therefore, this function normalizes both before constructing the pool
|
| 85 |
+
key for an HTTPS request. If you wish to change this behaviour, provide
|
| 86 |
+
alternate callables to ``key_fn_by_scheme``.
|
| 87 |
+
|
| 88 |
+
:param key_class:
|
| 89 |
+
The class to use when constructing the key. This should be a namedtuple
|
| 90 |
+
with the ``scheme`` and ``host`` keys at a minimum.
|
| 91 |
+
:type key_class: namedtuple
|
| 92 |
+
:param request_context:
|
| 93 |
+
A dictionary-like object that contain the context for a request.
|
| 94 |
+
:type request_context: dict
|
| 95 |
+
|
| 96 |
+
:return: A namedtuple that can be used as a connection pool key.
|
| 97 |
+
:rtype: PoolKey
|
| 98 |
+
"""
|
| 99 |
+
# Since we mutate the dictionary, make a copy first
|
| 100 |
+
context = request_context.copy()
|
| 101 |
+
context["scheme"] = context["scheme"].lower()
|
| 102 |
+
context["host"] = context["host"].lower()
|
| 103 |
+
|
| 104 |
+
# These are both dictionaries and need to be transformed into frozensets
|
| 105 |
+
for key in ("headers", "_proxy_headers", "_socks_options"):
|
| 106 |
+
if key in context and context[key] is not None:
|
| 107 |
+
context[key] = frozenset(context[key].items())
|
| 108 |
+
|
| 109 |
+
# The socket_options key may be a list and needs to be transformed into a
|
| 110 |
+
# tuple.
|
| 111 |
+
socket_opts = context.get("socket_options")
|
| 112 |
+
if socket_opts is not None:
|
| 113 |
+
context["socket_options"] = tuple(socket_opts)
|
| 114 |
+
|
| 115 |
+
# Map the kwargs to the names in the namedtuple - this is necessary since
|
| 116 |
+
# namedtuples can't have fields starting with '_'.
|
| 117 |
+
for key in list(context.keys()):
|
| 118 |
+
context["key_" + key] = context.pop(key)
|
| 119 |
+
|
| 120 |
+
# Default to ``None`` for keys missing from the context
|
| 121 |
+
for field in key_class._fields:
|
| 122 |
+
if field not in context:
|
| 123 |
+
context[field] = None
|
| 124 |
+
|
| 125 |
+
return key_class(**context)
|
| 126 |
+
|
| 127 |
+
|
| 128 |
+
#: A dictionary that maps a scheme to a callable that creates a pool key.
|
| 129 |
+
#: This can be used to alter the way pool keys are constructed, if desired.
|
| 130 |
+
#: Each PoolManager makes a copy of this dictionary so they can be configured
|
| 131 |
+
#: globally here, or individually on the instance.
|
| 132 |
+
key_fn_by_scheme = {
|
| 133 |
+
"http": functools.partial(_default_key_normalizer, PoolKey),
|
| 134 |
+
"https": functools.partial(_default_key_normalizer, PoolKey),
|
| 135 |
+
}
|
| 136 |
+
|
| 137 |
+
pool_classes_by_scheme = {"http": HTTPConnectionPool, "https": HTTPSConnectionPool}
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
class PoolManager(RequestMethods):
|
| 141 |
+
"""
|
| 142 |
+
Allows for arbitrary requests while transparently keeping track of
|
| 143 |
+
necessary connection pools for you.
|
| 144 |
+
|
| 145 |
+
:param num_pools:
|
| 146 |
+
Number of connection pools to cache before discarding the least
|
| 147 |
+
recently used pool.
|
| 148 |
+
|
| 149 |
+
:param headers:
|
| 150 |
+
Headers to include with all requests, unless other headers are given
|
| 151 |
+
explicitly.
|
| 152 |
+
|
| 153 |
+
:param \\**connection_pool_kw:
|
| 154 |
+
Additional parameters are used to create fresh
|
| 155 |
+
:class:`urllib3.connectionpool.ConnectionPool` instances.
|
| 156 |
+
|
| 157 |
+
Example::
|
| 158 |
+
|
| 159 |
+
>>> manager = PoolManager(num_pools=2)
|
| 160 |
+
>>> r = manager.request('GET', 'http://google.com/')
|
| 161 |
+
>>> r = manager.request('GET', 'http://google.com/mail')
|
| 162 |
+
>>> r = manager.request('GET', 'http://yahoo.com/')
|
| 163 |
+
>>> len(manager.pools)
|
| 164 |
+
2
|
| 165 |
+
|
| 166 |
+
"""
|
| 167 |
+
|
| 168 |
+
proxy = None
|
| 169 |
+
proxy_config = None
|
| 170 |
+
|
| 171 |
+
def __init__(self, num_pools=10, headers=None, **connection_pool_kw):
|
| 172 |
+
RequestMethods.__init__(self, headers)
|
| 173 |
+
if "retries" in connection_pool_kw:
|
| 174 |
+
retries = connection_pool_kw["retries"]
|
| 175 |
+
if not isinstance(retries, Retry):
|
| 176 |
+
# When Retry is initialized, raise_on_redirect is based
|
| 177 |
+
# on a redirect boolean value.
|
| 178 |
+
# But requests made via a pool manager always set
|
| 179 |
+
# redirect to False, and raise_on_redirect always ends
|
| 180 |
+
# up being False consequently.
|
| 181 |
+
# Here we fix the issue by setting raise_on_redirect to
|
| 182 |
+
# a value needed by the pool manager without considering
|
| 183 |
+
# the redirect boolean.
|
| 184 |
+
raise_on_redirect = retries is not False
|
| 185 |
+
retries = Retry.from_int(retries, redirect=False)
|
| 186 |
+
retries.raise_on_redirect = raise_on_redirect
|
| 187 |
+
connection_pool_kw = connection_pool_kw.copy()
|
| 188 |
+
connection_pool_kw["retries"] = retries
|
| 189 |
+
self.connection_pool_kw = connection_pool_kw
|
| 190 |
+
self.pools = RecentlyUsedContainer(num_pools)
|
| 191 |
+
|
| 192 |
+
# Locally set the pool classes and keys so other PoolManagers can
|
| 193 |
+
# override them.
|
| 194 |
+
self.pool_classes_by_scheme = pool_classes_by_scheme
|
| 195 |
+
self.key_fn_by_scheme = key_fn_by_scheme.copy()
|
| 196 |
+
|
| 197 |
+
def __enter__(self):
|
| 198 |
+
return self
|
| 199 |
+
|
| 200 |
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
| 201 |
+
self.clear()
|
| 202 |
+
# Return False to re-raise any potential exceptions
|
| 203 |
+
return False
|
| 204 |
+
|
| 205 |
+
def _new_pool(self, scheme, host, port, request_context=None):
|
| 206 |
+
"""
|
| 207 |
+
Create a new :class:`urllib3.connectionpool.ConnectionPool` based on host, port, scheme, and
|
| 208 |
+
any additional pool keyword arguments.
|
| 209 |
+
|
| 210 |
+
If ``request_context`` is provided, it is provided as keyword arguments
|
| 211 |
+
to the pool class used. This method is used to actually create the
|
| 212 |
+
connection pools handed out by :meth:`connection_from_url` and
|
| 213 |
+
companion methods. It is intended to be overridden for customization.
|
| 214 |
+
"""
|
| 215 |
+
pool_cls = self.pool_classes_by_scheme[scheme]
|
| 216 |
+
if request_context is None:
|
| 217 |
+
request_context = self.connection_pool_kw.copy()
|
| 218 |
+
|
| 219 |
+
# Although the context has everything necessary to create the pool,
|
| 220 |
+
# this function has historically only used the scheme, host, and port
|
| 221 |
+
# in the positional args. When an API change is acceptable these can
|
| 222 |
+
# be removed.
|
| 223 |
+
for key in ("scheme", "host", "port"):
|
| 224 |
+
request_context.pop(key, None)
|
| 225 |
+
|
| 226 |
+
if scheme == "http":
|
| 227 |
+
for kw in SSL_KEYWORDS:
|
| 228 |
+
request_context.pop(kw, None)
|
| 229 |
+
|
| 230 |
+
return pool_cls(host, port, **request_context)
|
| 231 |
+
|
| 232 |
+
def clear(self):
|
| 233 |
+
"""
|
| 234 |
+
Empty our store of pools and direct them all to close.
|
| 235 |
+
|
| 236 |
+
This will not affect in-flight connections, but they will not be
|
| 237 |
+
re-used after completion.
|
| 238 |
+
"""
|
| 239 |
+
self.pools.clear()
|
| 240 |
+
|
| 241 |
+
def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None):
|
| 242 |
+
"""
|
| 243 |
+
Get a :class:`urllib3.connectionpool.ConnectionPool` based on the host, port, and scheme.
|
| 244 |
+
|
| 245 |
+
If ``port`` isn't given, it will be derived from the ``scheme`` using
|
| 246 |
+
``urllib3.connectionpool.port_by_scheme``. If ``pool_kwargs`` is
|
| 247 |
+
provided, it is merged with the instance's ``connection_pool_kw``
|
| 248 |
+
variable and used to create the new connection pool, if one is
|
| 249 |
+
needed.
|
| 250 |
+
"""
|
| 251 |
+
|
| 252 |
+
if not host:
|
| 253 |
+
raise LocationValueError("No host specified.")
|
| 254 |
+
|
| 255 |
+
request_context = self._merge_pool_kwargs(pool_kwargs)
|
| 256 |
+
request_context["scheme"] = scheme or "http"
|
| 257 |
+
if not port:
|
| 258 |
+
port = port_by_scheme.get(request_context["scheme"].lower(), 80)
|
| 259 |
+
request_context["port"] = port
|
| 260 |
+
request_context["host"] = host
|
| 261 |
+
|
| 262 |
+
return self.connection_from_context(request_context)
|
| 263 |
+
|
| 264 |
+
def connection_from_context(self, request_context):
|
| 265 |
+
"""
|
| 266 |
+
Get a :class:`urllib3.connectionpool.ConnectionPool` based on the request context.
|
| 267 |
+
|
| 268 |
+
``request_context`` must at least contain the ``scheme`` key and its
|
| 269 |
+
value must be a key in ``key_fn_by_scheme`` instance variable.
|
| 270 |
+
"""
|
| 271 |
+
scheme = request_context["scheme"].lower()
|
| 272 |
+
pool_key_constructor = self.key_fn_by_scheme.get(scheme)
|
| 273 |
+
if not pool_key_constructor:
|
| 274 |
+
raise URLSchemeUnknown(scheme)
|
| 275 |
+
pool_key = pool_key_constructor(request_context)
|
| 276 |
+
|
| 277 |
+
return self.connection_from_pool_key(pool_key, request_context=request_context)
|
| 278 |
+
|
| 279 |
+
def connection_from_pool_key(self, pool_key, request_context=None):
|
| 280 |
+
"""
|
| 281 |
+
Get a :class:`urllib3.connectionpool.ConnectionPool` based on the provided pool key.
|
| 282 |
+
|
| 283 |
+
``pool_key`` should be a namedtuple that only contains immutable
|
| 284 |
+
objects. At a minimum it must have the ``scheme``, ``host``, and
|
| 285 |
+
``port`` fields.
|
| 286 |
+
"""
|
| 287 |
+
with self.pools.lock:
|
| 288 |
+
# If the scheme, host, or port doesn't match existing open
|
| 289 |
+
# connections, open a new ConnectionPool.
|
| 290 |
+
pool = self.pools.get(pool_key)
|
| 291 |
+
if pool:
|
| 292 |
+
return pool
|
| 293 |
+
|
| 294 |
+
# Make a fresh ConnectionPool of the desired type
|
| 295 |
+
scheme = request_context["scheme"]
|
| 296 |
+
host = request_context["host"]
|
| 297 |
+
port = request_context["port"]
|
| 298 |
+
pool = self._new_pool(scheme, host, port, request_context=request_context)
|
| 299 |
+
self.pools[pool_key] = pool
|
| 300 |
+
|
| 301 |
+
return pool
|
| 302 |
+
|
| 303 |
+
def connection_from_url(self, url, pool_kwargs=None):
|
| 304 |
+
"""
|
| 305 |
+
Similar to :func:`urllib3.connectionpool.connection_from_url`.
|
| 306 |
+
|
| 307 |
+
If ``pool_kwargs`` is not provided and a new pool needs to be
|
| 308 |
+
constructed, ``self.connection_pool_kw`` is used to initialize
|
| 309 |
+
the :class:`urllib3.connectionpool.ConnectionPool`. If ``pool_kwargs``
|
| 310 |
+
is provided, it is used instead. Note that if a new pool does not
|
| 311 |
+
need to be created for the request, the provided ``pool_kwargs`` are
|
| 312 |
+
not used.
|
| 313 |
+
"""
|
| 314 |
+
u = parse_url(url)
|
| 315 |
+
return self.connection_from_host(
|
| 316 |
+
u.host, port=u.port, scheme=u.scheme, pool_kwargs=pool_kwargs
|
| 317 |
+
)
|
| 318 |
+
|
| 319 |
+
def _merge_pool_kwargs(self, override):
|
| 320 |
+
"""
|
| 321 |
+
Merge a dictionary of override values for self.connection_pool_kw.
|
| 322 |
+
|
| 323 |
+
This does not modify self.connection_pool_kw and returns a new dict.
|
| 324 |
+
Any keys in the override dictionary with a value of ``None`` are
|
| 325 |
+
removed from the merged dictionary.
|
| 326 |
+
"""
|
| 327 |
+
base_pool_kwargs = self.connection_pool_kw.copy()
|
| 328 |
+
if override:
|
| 329 |
+
for key, value in override.items():
|
| 330 |
+
if value is None:
|
| 331 |
+
try:
|
| 332 |
+
del base_pool_kwargs[key]
|
| 333 |
+
except KeyError:
|
| 334 |
+
pass
|
| 335 |
+
else:
|
| 336 |
+
base_pool_kwargs[key] = value
|
| 337 |
+
return base_pool_kwargs
|
| 338 |
+
|
| 339 |
+
def _proxy_requires_url_absolute_form(self, parsed_url):
|
| 340 |
+
"""
|
| 341 |
+
Indicates if the proxy requires the complete destination URL in the
|
| 342 |
+
request. Normally this is only needed when not using an HTTP CONNECT
|
| 343 |
+
tunnel.
|
| 344 |
+
"""
|
| 345 |
+
if self.proxy is None:
|
| 346 |
+
return False
|
| 347 |
+
|
| 348 |
+
return not connection_requires_http_tunnel(
|
| 349 |
+
self.proxy, self.proxy_config, parsed_url.scheme
|
| 350 |
+
)
|
| 351 |
+
|
| 352 |
+
def _validate_proxy_scheme_url_selection(self, url_scheme):
|
| 353 |
+
"""
|
| 354 |
+
Validates that were not attempting to do TLS in TLS connections on
|
| 355 |
+
Python2 or with unsupported SSL implementations.
|
| 356 |
+
"""
|
| 357 |
+
if self.proxy is None or url_scheme != "https":
|
| 358 |
+
return
|
| 359 |
+
|
| 360 |
+
if self.proxy.scheme != "https":
|
| 361 |
+
return
|
| 362 |
+
|
| 363 |
+
if six.PY2 and not self.proxy_config.use_forwarding_for_https:
|
| 364 |
+
raise ProxySchemeUnsupported(
|
| 365 |
+
"Contacting HTTPS destinations through HTTPS proxies "
|
| 366 |
+
"'via CONNECT tunnels' is not supported in Python 2"
|
| 367 |
+
)
|
| 368 |
+
|
| 369 |
+
def urlopen(self, method, url, redirect=True, **kw):
|
| 370 |
+
"""
|
| 371 |
+
Same as :meth:`urllib3.HTTPConnectionPool.urlopen`
|
| 372 |
+
with custom cross-host redirect logic and only sends the request-uri
|
| 373 |
+
portion of the ``url``.
|
| 374 |
+
|
| 375 |
+
The given ``url`` parameter must be absolute, such that an appropriate
|
| 376 |
+
:class:`urllib3.connectionpool.ConnectionPool` can be chosen for it.
|
| 377 |
+
"""
|
| 378 |
+
u = parse_url(url)
|
| 379 |
+
self._validate_proxy_scheme_url_selection(u.scheme)
|
| 380 |
+
|
| 381 |
+
conn = self.connection_from_host(u.host, port=u.port, scheme=u.scheme)
|
| 382 |
+
|
| 383 |
+
kw["assert_same_host"] = False
|
| 384 |
+
kw["redirect"] = False
|
| 385 |
+
|
| 386 |
+
if "headers" not in kw:
|
| 387 |
+
kw["headers"] = self.headers.copy()
|
| 388 |
+
|
| 389 |
+
if self._proxy_requires_url_absolute_form(u):
|
| 390 |
+
response = conn.urlopen(method, url, **kw)
|
| 391 |
+
else:
|
| 392 |
+
response = conn.urlopen(method, u.request_uri, **kw)
|
| 393 |
+
|
| 394 |
+
redirect_location = redirect and response.get_redirect_location()
|
| 395 |
+
if not redirect_location:
|
| 396 |
+
return response
|
| 397 |
+
|
| 398 |
+
# Support relative URLs for redirecting.
|
| 399 |
+
redirect_location = urljoin(url, redirect_location)
|
| 400 |
+
|
| 401 |
+
if response.status == 303:
|
| 402 |
+
# Change the method according to RFC 9110, Section 15.4.4.
|
| 403 |
+
method = "GET"
|
| 404 |
+
# And lose the body not to transfer anything sensitive.
|
| 405 |
+
kw["body"] = None
|
| 406 |
+
kw["headers"] = HTTPHeaderDict(kw["headers"])._prepare_for_method_change()
|
| 407 |
+
|
| 408 |
+
retries = kw.get("retries", response.retries)
|
| 409 |
+
if not isinstance(retries, Retry):
|
| 410 |
+
retries = Retry.from_int(retries, redirect=redirect)
|
| 411 |
+
|
| 412 |
+
# Strip headers marked as unsafe to forward to the redirected location.
|
| 413 |
+
# Check remove_headers_on_redirect to avoid a potential network call within
|
| 414 |
+
# conn.is_same_host() which may use socket.gethostbyname() in the future.
|
| 415 |
+
if retries.remove_headers_on_redirect and not conn.is_same_host(
|
| 416 |
+
redirect_location
|
| 417 |
+
):
|
| 418 |
+
headers = list(six.iterkeys(kw["headers"]))
|
| 419 |
+
for header in headers:
|
| 420 |
+
if header.lower() in retries.remove_headers_on_redirect:
|
| 421 |
+
kw["headers"].pop(header, None)
|
| 422 |
+
|
| 423 |
+
try:
|
| 424 |
+
retries = retries.increment(method, url, response=response, _pool=conn)
|
| 425 |
+
except MaxRetryError:
|
| 426 |
+
if retries.raise_on_redirect:
|
| 427 |
+
response.drain_conn()
|
| 428 |
+
raise
|
| 429 |
+
return response
|
| 430 |
+
|
| 431 |
+
kw["retries"] = retries
|
| 432 |
+
kw["redirect"] = redirect
|
| 433 |
+
|
| 434 |
+
log.info("Redirecting %s -> %s", url, redirect_location)
|
| 435 |
+
|
| 436 |
+
response.drain_conn()
|
| 437 |
+
return self.urlopen(method, redirect_location, **kw)
|
| 438 |
+
|
| 439 |
+
|
| 440 |
+
class ProxyManager(PoolManager):
|
| 441 |
+
"""
|
| 442 |
+
Behaves just like :class:`PoolManager`, but sends all requests through
|
| 443 |
+
the defined proxy, using the CONNECT method for HTTPS URLs.
|
| 444 |
+
|
| 445 |
+
:param proxy_url:
|
| 446 |
+
The URL of the proxy to be used.
|
| 447 |
+
|
| 448 |
+
:param proxy_headers:
|
| 449 |
+
A dictionary containing headers that will be sent to the proxy. In case
|
| 450 |
+
of HTTP they are being sent with each request, while in the
|
| 451 |
+
HTTPS/CONNECT case they are sent only once. Could be used for proxy
|
| 452 |
+
authentication.
|
| 453 |
+
|
| 454 |
+
:param proxy_ssl_context:
|
| 455 |
+
The proxy SSL context is used to establish the TLS connection to the
|
| 456 |
+
proxy when using HTTPS proxies.
|
| 457 |
+
|
| 458 |
+
:param use_forwarding_for_https:
|
| 459 |
+
(Defaults to False) If set to True will forward requests to the HTTPS
|
| 460 |
+
proxy to be made on behalf of the client instead of creating a TLS
|
| 461 |
+
tunnel via the CONNECT method. **Enabling this flag means that request
|
| 462 |
+
and response headers and content will be visible from the HTTPS proxy**
|
| 463 |
+
whereas tunneling keeps request and response headers and content
|
| 464 |
+
private. IP address, target hostname, SNI, and port are always visible
|
| 465 |
+
to an HTTPS proxy even when this flag is disabled.
|
| 466 |
+
|
| 467 |
+
Example:
|
| 468 |
+
>>> proxy = urllib3.ProxyManager('http://localhost:3128/')
|
| 469 |
+
>>> r1 = proxy.request('GET', 'http://google.com/')
|
| 470 |
+
>>> r2 = proxy.request('GET', 'http://httpbin.org/')
|
| 471 |
+
>>> len(proxy.pools)
|
| 472 |
+
1
|
| 473 |
+
>>> r3 = proxy.request('GET', 'https://httpbin.org/')
|
| 474 |
+
>>> r4 = proxy.request('GET', 'https://twitter.com/')
|
| 475 |
+
>>> len(proxy.pools)
|
| 476 |
+
3
|
| 477 |
+
|
| 478 |
+
"""
|
| 479 |
+
|
| 480 |
+
def __init__(
|
| 481 |
+
self,
|
| 482 |
+
proxy_url,
|
| 483 |
+
num_pools=10,
|
| 484 |
+
headers=None,
|
| 485 |
+
proxy_headers=None,
|
| 486 |
+
proxy_ssl_context=None,
|
| 487 |
+
use_forwarding_for_https=False,
|
| 488 |
+
**connection_pool_kw
|
| 489 |
+
):
|
| 490 |
+
|
| 491 |
+
if isinstance(proxy_url, HTTPConnectionPool):
|
| 492 |
+
proxy_url = "%s://%s:%i" % (
|
| 493 |
+
proxy_url.scheme,
|
| 494 |
+
proxy_url.host,
|
| 495 |
+
proxy_url.port,
|
| 496 |
+
)
|
| 497 |
+
proxy = parse_url(proxy_url)
|
| 498 |
+
|
| 499 |
+
if proxy.scheme not in ("http", "https"):
|
| 500 |
+
raise ProxySchemeUnknown(proxy.scheme)
|
| 501 |
+
|
| 502 |
+
if not proxy.port:
|
| 503 |
+
port = port_by_scheme.get(proxy.scheme, 80)
|
| 504 |
+
proxy = proxy._replace(port=port)
|
| 505 |
+
|
| 506 |
+
self.proxy = proxy
|
| 507 |
+
self.proxy_headers = proxy_headers or {}
|
| 508 |
+
self.proxy_ssl_context = proxy_ssl_context
|
| 509 |
+
self.proxy_config = ProxyConfig(proxy_ssl_context, use_forwarding_for_https)
|
| 510 |
+
|
| 511 |
+
connection_pool_kw["_proxy"] = self.proxy
|
| 512 |
+
connection_pool_kw["_proxy_headers"] = self.proxy_headers
|
| 513 |
+
connection_pool_kw["_proxy_config"] = self.proxy_config
|
| 514 |
+
|
| 515 |
+
super(ProxyManager, self).__init__(num_pools, headers, **connection_pool_kw)
|
| 516 |
+
|
| 517 |
+
def connection_from_host(self, host, port=None, scheme="http", pool_kwargs=None):
|
| 518 |
+
if scheme == "https":
|
| 519 |
+
return super(ProxyManager, self).connection_from_host(
|
| 520 |
+
host, port, scheme, pool_kwargs=pool_kwargs
|
| 521 |
+
)
|
| 522 |
+
|
| 523 |
+
return super(ProxyManager, self).connection_from_host(
|
| 524 |
+
self.proxy.host, self.proxy.port, self.proxy.scheme, pool_kwargs=pool_kwargs
|
| 525 |
+
)
|
| 526 |
+
|
| 527 |
+
def _set_proxy_headers(self, url, headers=None):
|
| 528 |
+
"""
|
| 529 |
+
Sets headers needed by proxies: specifically, the Accept and Host
|
| 530 |
+
headers. Only sets headers not provided by the user.
|
| 531 |
+
"""
|
| 532 |
+
headers_ = {"Accept": "*/*"}
|
| 533 |
+
|
| 534 |
+
netloc = parse_url(url).netloc
|
| 535 |
+
if netloc:
|
| 536 |
+
headers_["Host"] = netloc
|
| 537 |
+
|
| 538 |
+
if headers:
|
| 539 |
+
headers_.update(headers)
|
| 540 |
+
return headers_
|
| 541 |
+
|
| 542 |
+
def urlopen(self, method, url, redirect=True, **kw):
|
| 543 |
+
"Same as HTTP(S)ConnectionPool.urlopen, ``url`` must be absolute."
|
| 544 |
+
u = parse_url(url)
|
| 545 |
+
if not connection_requires_http_tunnel(self.proxy, self.proxy_config, u.scheme):
|
| 546 |
+
# For connections using HTTP CONNECT, httplib sets the necessary
|
| 547 |
+
# headers on the CONNECT to the proxy. If we're not using CONNECT,
|
| 548 |
+
# we'll definitely need to set 'Host' at the very least.
|
| 549 |
+
headers = kw.get("headers", self.headers)
|
| 550 |
+
kw["headers"] = self._set_proxy_headers(url, headers)
|
| 551 |
+
|
| 552 |
+
return super(ProxyManager, self).urlopen(method, url, redirect=redirect, **kw)
|
| 553 |
+
|
| 554 |
+
|
| 555 |
+
def proxy_from_url(url, **kw):
|
| 556 |
+
return ProxyManager(proxy_url=url, **kw)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/request.py
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import sys
|
| 4 |
+
|
| 5 |
+
from .filepost import encode_multipart_formdata
|
| 6 |
+
from .packages import six
|
| 7 |
+
from .packages.six.moves.urllib.parse import urlencode
|
| 8 |
+
|
| 9 |
+
__all__ = ["RequestMethods"]
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class RequestMethods(object):
|
| 13 |
+
"""
|
| 14 |
+
Convenience mixin for classes who implement a :meth:`urlopen` method, such
|
| 15 |
+
as :class:`urllib3.HTTPConnectionPool` and
|
| 16 |
+
:class:`urllib3.PoolManager`.
|
| 17 |
+
|
| 18 |
+
Provides behavior for making common types of HTTP request methods and
|
| 19 |
+
decides which type of request field encoding to use.
|
| 20 |
+
|
| 21 |
+
Specifically,
|
| 22 |
+
|
| 23 |
+
:meth:`.request_encode_url` is for sending requests whose fields are
|
| 24 |
+
encoded in the URL (such as GET, HEAD, DELETE).
|
| 25 |
+
|
| 26 |
+
:meth:`.request_encode_body` is for sending requests whose fields are
|
| 27 |
+
encoded in the *body* of the request using multipart or www-form-urlencoded
|
| 28 |
+
(such as for POST, PUT, PATCH).
|
| 29 |
+
|
| 30 |
+
:meth:`.request` is for making any kind of request, it will look up the
|
| 31 |
+
appropriate encoding format and use one of the above two methods to make
|
| 32 |
+
the request.
|
| 33 |
+
|
| 34 |
+
Initializer parameters:
|
| 35 |
+
|
| 36 |
+
:param headers:
|
| 37 |
+
Headers to include with all requests, unless other headers are given
|
| 38 |
+
explicitly.
|
| 39 |
+
"""
|
| 40 |
+
|
| 41 |
+
_encode_url_methods = {"DELETE", "GET", "HEAD", "OPTIONS"}
|
| 42 |
+
|
| 43 |
+
def __init__(self, headers=None):
|
| 44 |
+
self.headers = headers or {}
|
| 45 |
+
|
| 46 |
+
def urlopen(
|
| 47 |
+
self,
|
| 48 |
+
method,
|
| 49 |
+
url,
|
| 50 |
+
body=None,
|
| 51 |
+
headers=None,
|
| 52 |
+
encode_multipart=True,
|
| 53 |
+
multipart_boundary=None,
|
| 54 |
+
**kw
|
| 55 |
+
): # Abstract
|
| 56 |
+
raise NotImplementedError(
|
| 57 |
+
"Classes extending RequestMethods must implement "
|
| 58 |
+
"their own ``urlopen`` method."
|
| 59 |
+
)
|
| 60 |
+
|
| 61 |
+
def request(self, method, url, fields=None, headers=None, **urlopen_kw):
|
| 62 |
+
"""
|
| 63 |
+
Make a request using :meth:`urlopen` with the appropriate encoding of
|
| 64 |
+
``fields`` based on the ``method`` used.
|
| 65 |
+
|
| 66 |
+
This is a convenience method that requires the least amount of manual
|
| 67 |
+
effort. It can be used in most situations, while still having the
|
| 68 |
+
option to drop down to more specific methods when necessary, such as
|
| 69 |
+
:meth:`request_encode_url`, :meth:`request_encode_body`,
|
| 70 |
+
or even the lowest level :meth:`urlopen`.
|
| 71 |
+
"""
|
| 72 |
+
method = method.upper()
|
| 73 |
+
|
| 74 |
+
urlopen_kw["request_url"] = url
|
| 75 |
+
|
| 76 |
+
if method in self._encode_url_methods:
|
| 77 |
+
return self.request_encode_url(
|
| 78 |
+
method, url, fields=fields, headers=headers, **urlopen_kw
|
| 79 |
+
)
|
| 80 |
+
else:
|
| 81 |
+
return self.request_encode_body(
|
| 82 |
+
method, url, fields=fields, headers=headers, **urlopen_kw
|
| 83 |
+
)
|
| 84 |
+
|
| 85 |
+
def request_encode_url(self, method, url, fields=None, headers=None, **urlopen_kw):
|
| 86 |
+
"""
|
| 87 |
+
Make a request using :meth:`urlopen` with the ``fields`` encoded in
|
| 88 |
+
the url. This is useful for request methods like GET, HEAD, DELETE, etc.
|
| 89 |
+
"""
|
| 90 |
+
if headers is None:
|
| 91 |
+
headers = self.headers
|
| 92 |
+
|
| 93 |
+
extra_kw = {"headers": headers}
|
| 94 |
+
extra_kw.update(urlopen_kw)
|
| 95 |
+
|
| 96 |
+
if fields:
|
| 97 |
+
url += "?" + urlencode(fields)
|
| 98 |
+
|
| 99 |
+
return self.urlopen(method, url, **extra_kw)
|
| 100 |
+
|
| 101 |
+
def request_encode_body(
|
| 102 |
+
self,
|
| 103 |
+
method,
|
| 104 |
+
url,
|
| 105 |
+
fields=None,
|
| 106 |
+
headers=None,
|
| 107 |
+
encode_multipart=True,
|
| 108 |
+
multipart_boundary=None,
|
| 109 |
+
**urlopen_kw
|
| 110 |
+
):
|
| 111 |
+
"""
|
| 112 |
+
Make a request using :meth:`urlopen` with the ``fields`` encoded in
|
| 113 |
+
the body. This is useful for request methods like POST, PUT, PATCH, etc.
|
| 114 |
+
|
| 115 |
+
When ``encode_multipart=True`` (default), then
|
| 116 |
+
:func:`urllib3.encode_multipart_formdata` is used to encode
|
| 117 |
+
the payload with the appropriate content type. Otherwise
|
| 118 |
+
:func:`urllib.parse.urlencode` is used with the
|
| 119 |
+
'application/x-www-form-urlencoded' content type.
|
| 120 |
+
|
| 121 |
+
Multipart encoding must be used when posting files, and it's reasonably
|
| 122 |
+
safe to use it in other times too. However, it may break request
|
| 123 |
+
signing, such as with OAuth.
|
| 124 |
+
|
| 125 |
+
Supports an optional ``fields`` parameter of key/value strings AND
|
| 126 |
+
key/filetuple. A filetuple is a (filename, data, MIME type) tuple where
|
| 127 |
+
the MIME type is optional. For example::
|
| 128 |
+
|
| 129 |
+
fields = {
|
| 130 |
+
'foo': 'bar',
|
| 131 |
+
'fakefile': ('foofile.txt', 'contents of foofile'),
|
| 132 |
+
'realfile': ('barfile.txt', open('realfile').read()),
|
| 133 |
+
'typedfile': ('bazfile.bin', open('bazfile').read(),
|
| 134 |
+
'image/jpeg'),
|
| 135 |
+
'nonamefile': 'contents of nonamefile field',
|
| 136 |
+
}
|
| 137 |
+
|
| 138 |
+
When uploading a file, providing a filename (the first parameter of the
|
| 139 |
+
tuple) is optional but recommended to best mimic behavior of browsers.
|
| 140 |
+
|
| 141 |
+
Note that if ``headers`` are supplied, the 'Content-Type' header will
|
| 142 |
+
be overwritten because it depends on the dynamic random boundary string
|
| 143 |
+
which is used to compose the body of the request. The random boundary
|
| 144 |
+
string can be explicitly set with the ``multipart_boundary`` parameter.
|
| 145 |
+
"""
|
| 146 |
+
if headers is None:
|
| 147 |
+
headers = self.headers
|
| 148 |
+
|
| 149 |
+
extra_kw = {"headers": {}}
|
| 150 |
+
|
| 151 |
+
if fields:
|
| 152 |
+
if "body" in urlopen_kw:
|
| 153 |
+
raise TypeError(
|
| 154 |
+
"request got values for both 'fields' and 'body', can only specify one."
|
| 155 |
+
)
|
| 156 |
+
|
| 157 |
+
if encode_multipart:
|
| 158 |
+
body, content_type = encode_multipart_formdata(
|
| 159 |
+
fields, boundary=multipart_boundary
|
| 160 |
+
)
|
| 161 |
+
else:
|
| 162 |
+
body, content_type = (
|
| 163 |
+
urlencode(fields),
|
| 164 |
+
"application/x-www-form-urlencoded",
|
| 165 |
+
)
|
| 166 |
+
|
| 167 |
+
extra_kw["body"] = body
|
| 168 |
+
extra_kw["headers"] = {"Content-Type": content_type}
|
| 169 |
+
|
| 170 |
+
extra_kw["headers"].update(headers)
|
| 171 |
+
extra_kw.update(urlopen_kw)
|
| 172 |
+
|
| 173 |
+
return self.urlopen(method, url, **extra_kw)
|
| 174 |
+
|
| 175 |
+
|
| 176 |
+
if not six.PY2:
|
| 177 |
+
|
| 178 |
+
class RequestModule(sys.modules[__name__].__class__):
|
| 179 |
+
def __call__(self, *args, **kwargs):
|
| 180 |
+
"""
|
| 181 |
+
If user tries to call this module directly urllib3 v2.x style raise an error to the user
|
| 182 |
+
suggesting they may need urllib3 v2
|
| 183 |
+
"""
|
| 184 |
+
raise TypeError(
|
| 185 |
+
"'module' object is not callable\n"
|
| 186 |
+
"urllib3.request() method is not supported in this release, "
|
| 187 |
+
"upgrade to urllib3 v2 to use it\n"
|
| 188 |
+
"see https://urllib3.readthedocs.io/en/stable/v2-migration-guide.html"
|
| 189 |
+
)
|
| 190 |
+
|
| 191 |
+
sys.modules[__name__].__class__ = RequestModule
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/response.py
ADDED
|
@@ -0,0 +1,879 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import io
|
| 4 |
+
import logging
|
| 5 |
+
import sys
|
| 6 |
+
import warnings
|
| 7 |
+
import zlib
|
| 8 |
+
from contextlib import contextmanager
|
| 9 |
+
from socket import error as SocketError
|
| 10 |
+
from socket import timeout as SocketTimeout
|
| 11 |
+
|
| 12 |
+
brotli = None
|
| 13 |
+
|
| 14 |
+
from . import util
|
| 15 |
+
from ._collections import HTTPHeaderDict
|
| 16 |
+
from .connection import BaseSSLError, HTTPException
|
| 17 |
+
from .exceptions import (
|
| 18 |
+
BodyNotHttplibCompatible,
|
| 19 |
+
DecodeError,
|
| 20 |
+
HTTPError,
|
| 21 |
+
IncompleteRead,
|
| 22 |
+
InvalidChunkLength,
|
| 23 |
+
InvalidHeader,
|
| 24 |
+
ProtocolError,
|
| 25 |
+
ReadTimeoutError,
|
| 26 |
+
ResponseNotChunked,
|
| 27 |
+
SSLError,
|
| 28 |
+
)
|
| 29 |
+
from .packages import six
|
| 30 |
+
from .util.response import is_fp_closed, is_response_to_head
|
| 31 |
+
|
| 32 |
+
log = logging.getLogger(__name__)
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class DeflateDecoder(object):
|
| 36 |
+
def __init__(self):
|
| 37 |
+
self._first_try = True
|
| 38 |
+
self._data = b""
|
| 39 |
+
self._obj = zlib.decompressobj()
|
| 40 |
+
|
| 41 |
+
def __getattr__(self, name):
|
| 42 |
+
return getattr(self._obj, name)
|
| 43 |
+
|
| 44 |
+
def decompress(self, data):
|
| 45 |
+
if not data:
|
| 46 |
+
return data
|
| 47 |
+
|
| 48 |
+
if not self._first_try:
|
| 49 |
+
return self._obj.decompress(data)
|
| 50 |
+
|
| 51 |
+
self._data += data
|
| 52 |
+
try:
|
| 53 |
+
decompressed = self._obj.decompress(data)
|
| 54 |
+
if decompressed:
|
| 55 |
+
self._first_try = False
|
| 56 |
+
self._data = None
|
| 57 |
+
return decompressed
|
| 58 |
+
except zlib.error:
|
| 59 |
+
self._first_try = False
|
| 60 |
+
self._obj = zlib.decompressobj(-zlib.MAX_WBITS)
|
| 61 |
+
try:
|
| 62 |
+
return self.decompress(self._data)
|
| 63 |
+
finally:
|
| 64 |
+
self._data = None
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
class GzipDecoderState(object):
|
| 68 |
+
|
| 69 |
+
FIRST_MEMBER = 0
|
| 70 |
+
OTHER_MEMBERS = 1
|
| 71 |
+
SWALLOW_DATA = 2
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class GzipDecoder(object):
|
| 75 |
+
def __init__(self):
|
| 76 |
+
self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
| 77 |
+
self._state = GzipDecoderState.FIRST_MEMBER
|
| 78 |
+
|
| 79 |
+
def __getattr__(self, name):
|
| 80 |
+
return getattr(self._obj, name)
|
| 81 |
+
|
| 82 |
+
def decompress(self, data):
|
| 83 |
+
ret = bytearray()
|
| 84 |
+
if self._state == GzipDecoderState.SWALLOW_DATA or not data:
|
| 85 |
+
return bytes(ret)
|
| 86 |
+
while True:
|
| 87 |
+
try:
|
| 88 |
+
ret += self._obj.decompress(data)
|
| 89 |
+
except zlib.error:
|
| 90 |
+
previous_state = self._state
|
| 91 |
+
# Ignore data after the first error
|
| 92 |
+
self._state = GzipDecoderState.SWALLOW_DATA
|
| 93 |
+
if previous_state == GzipDecoderState.OTHER_MEMBERS:
|
| 94 |
+
# Allow trailing garbage acceptable in other gzip clients
|
| 95 |
+
return bytes(ret)
|
| 96 |
+
raise
|
| 97 |
+
data = self._obj.unused_data
|
| 98 |
+
if not data:
|
| 99 |
+
return bytes(ret)
|
| 100 |
+
self._state = GzipDecoderState.OTHER_MEMBERS
|
| 101 |
+
self._obj = zlib.decompressobj(16 + zlib.MAX_WBITS)
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
if brotli is not None:
|
| 105 |
+
|
| 106 |
+
class BrotliDecoder(object):
|
| 107 |
+
# Supports both 'brotlipy' and 'Brotli' packages
|
| 108 |
+
# since they share an import name. The top branches
|
| 109 |
+
# are for 'brotlipy' and bottom branches for 'Brotli'
|
| 110 |
+
def __init__(self):
|
| 111 |
+
self._obj = brotli.Decompressor()
|
| 112 |
+
if hasattr(self._obj, "decompress"):
|
| 113 |
+
self.decompress = self._obj.decompress
|
| 114 |
+
else:
|
| 115 |
+
self.decompress = self._obj.process
|
| 116 |
+
|
| 117 |
+
def flush(self):
|
| 118 |
+
if hasattr(self._obj, "flush"):
|
| 119 |
+
return self._obj.flush()
|
| 120 |
+
return b""
|
| 121 |
+
|
| 122 |
+
|
| 123 |
+
class MultiDecoder(object):
|
| 124 |
+
"""
|
| 125 |
+
From RFC7231:
|
| 126 |
+
If one or more encodings have been applied to a representation, the
|
| 127 |
+
sender that applied the encodings MUST generate a Content-Encoding
|
| 128 |
+
header field that lists the content codings in the order in which
|
| 129 |
+
they were applied.
|
| 130 |
+
"""
|
| 131 |
+
|
| 132 |
+
def __init__(self, modes):
|
| 133 |
+
self._decoders = [_get_decoder(m.strip()) for m in modes.split(",")]
|
| 134 |
+
|
| 135 |
+
def flush(self):
|
| 136 |
+
return self._decoders[0].flush()
|
| 137 |
+
|
| 138 |
+
def decompress(self, data):
|
| 139 |
+
for d in reversed(self._decoders):
|
| 140 |
+
data = d.decompress(data)
|
| 141 |
+
return data
|
| 142 |
+
|
| 143 |
+
|
| 144 |
+
def _get_decoder(mode):
|
| 145 |
+
if "," in mode:
|
| 146 |
+
return MultiDecoder(mode)
|
| 147 |
+
|
| 148 |
+
if mode == "gzip":
|
| 149 |
+
return GzipDecoder()
|
| 150 |
+
|
| 151 |
+
if brotli is not None and mode == "br":
|
| 152 |
+
return BrotliDecoder()
|
| 153 |
+
|
| 154 |
+
return DeflateDecoder()
|
| 155 |
+
|
| 156 |
+
|
| 157 |
+
class HTTPResponse(io.IOBase):
|
| 158 |
+
"""
|
| 159 |
+
HTTP Response container.
|
| 160 |
+
|
| 161 |
+
Backwards-compatible with :class:`http.client.HTTPResponse` but the response ``body`` is
|
| 162 |
+
loaded and decoded on-demand when the ``data`` property is accessed. This
|
| 163 |
+
class is also compatible with the Python standard library's :mod:`io`
|
| 164 |
+
module, and can hence be treated as a readable object in the context of that
|
| 165 |
+
framework.
|
| 166 |
+
|
| 167 |
+
Extra parameters for behaviour not present in :class:`http.client.HTTPResponse`:
|
| 168 |
+
|
| 169 |
+
:param preload_content:
|
| 170 |
+
If True, the response's body will be preloaded during construction.
|
| 171 |
+
|
| 172 |
+
:param decode_content:
|
| 173 |
+
If True, will attempt to decode the body based on the
|
| 174 |
+
'content-encoding' header.
|
| 175 |
+
|
| 176 |
+
:param original_response:
|
| 177 |
+
When this HTTPResponse wrapper is generated from an :class:`http.client.HTTPResponse`
|
| 178 |
+
object, it's convenient to include the original for debug purposes. It's
|
| 179 |
+
otherwise unused.
|
| 180 |
+
|
| 181 |
+
:param retries:
|
| 182 |
+
The retries contains the last :class:`~urllib3.util.retry.Retry` that
|
| 183 |
+
was used during the request.
|
| 184 |
+
|
| 185 |
+
:param enforce_content_length:
|
| 186 |
+
Enforce content length checking. Body returned by server must match
|
| 187 |
+
value of Content-Length header, if present. Otherwise, raise error.
|
| 188 |
+
"""
|
| 189 |
+
|
| 190 |
+
CONTENT_DECODERS = ["gzip", "deflate"]
|
| 191 |
+
if brotli is not None:
|
| 192 |
+
CONTENT_DECODERS += ["br"]
|
| 193 |
+
REDIRECT_STATUSES = [301, 302, 303, 307, 308]
|
| 194 |
+
|
| 195 |
+
def __init__(
|
| 196 |
+
self,
|
| 197 |
+
body="",
|
| 198 |
+
headers=None,
|
| 199 |
+
status=0,
|
| 200 |
+
version=0,
|
| 201 |
+
reason=None,
|
| 202 |
+
strict=0,
|
| 203 |
+
preload_content=True,
|
| 204 |
+
decode_content=True,
|
| 205 |
+
original_response=None,
|
| 206 |
+
pool=None,
|
| 207 |
+
connection=None,
|
| 208 |
+
msg=None,
|
| 209 |
+
retries=None,
|
| 210 |
+
enforce_content_length=False,
|
| 211 |
+
request_method=None,
|
| 212 |
+
request_url=None,
|
| 213 |
+
auto_close=True,
|
| 214 |
+
):
|
| 215 |
+
|
| 216 |
+
if isinstance(headers, HTTPHeaderDict):
|
| 217 |
+
self.headers = headers
|
| 218 |
+
else:
|
| 219 |
+
self.headers = HTTPHeaderDict(headers)
|
| 220 |
+
self.status = status
|
| 221 |
+
self.version = version
|
| 222 |
+
self.reason = reason
|
| 223 |
+
self.strict = strict
|
| 224 |
+
self.decode_content = decode_content
|
| 225 |
+
self.retries = retries
|
| 226 |
+
self.enforce_content_length = enforce_content_length
|
| 227 |
+
self.auto_close = auto_close
|
| 228 |
+
|
| 229 |
+
self._decoder = None
|
| 230 |
+
self._body = None
|
| 231 |
+
self._fp = None
|
| 232 |
+
self._original_response = original_response
|
| 233 |
+
self._fp_bytes_read = 0
|
| 234 |
+
self.msg = msg
|
| 235 |
+
self._request_url = request_url
|
| 236 |
+
|
| 237 |
+
if body and isinstance(body, (six.string_types, bytes)):
|
| 238 |
+
self._body = body
|
| 239 |
+
|
| 240 |
+
self._pool = pool
|
| 241 |
+
self._connection = connection
|
| 242 |
+
|
| 243 |
+
if hasattr(body, "read"):
|
| 244 |
+
self._fp = body
|
| 245 |
+
|
| 246 |
+
# Are we using the chunked-style of transfer encoding?
|
| 247 |
+
self.chunked = False
|
| 248 |
+
self.chunk_left = None
|
| 249 |
+
tr_enc = self.headers.get("transfer-encoding", "").lower()
|
| 250 |
+
# Don't incur the penalty of creating a list and then discarding it
|
| 251 |
+
encodings = (enc.strip() for enc in tr_enc.split(","))
|
| 252 |
+
if "chunked" in encodings:
|
| 253 |
+
self.chunked = True
|
| 254 |
+
|
| 255 |
+
# Determine length of response
|
| 256 |
+
self.length_remaining = self._init_length(request_method)
|
| 257 |
+
|
| 258 |
+
# If requested, preload the body.
|
| 259 |
+
if preload_content and not self._body:
|
| 260 |
+
self._body = self.read(decode_content=decode_content)
|
| 261 |
+
|
| 262 |
+
def get_redirect_location(self):
|
| 263 |
+
"""
|
| 264 |
+
Should we redirect and where to?
|
| 265 |
+
|
| 266 |
+
:returns: Truthy redirect location string if we got a redirect status
|
| 267 |
+
code and valid location. ``None`` if redirect status and no
|
| 268 |
+
location. ``False`` if not a redirect status code.
|
| 269 |
+
"""
|
| 270 |
+
if self.status in self.REDIRECT_STATUSES:
|
| 271 |
+
return self.headers.get("location")
|
| 272 |
+
|
| 273 |
+
return False
|
| 274 |
+
|
| 275 |
+
def release_conn(self):
|
| 276 |
+
if not self._pool or not self._connection:
|
| 277 |
+
return
|
| 278 |
+
|
| 279 |
+
self._pool._put_conn(self._connection)
|
| 280 |
+
self._connection = None
|
| 281 |
+
|
| 282 |
+
def drain_conn(self):
|
| 283 |
+
"""
|
| 284 |
+
Read and discard any remaining HTTP response data in the response connection.
|
| 285 |
+
|
| 286 |
+
Unread data in the HTTPResponse connection blocks the connection from being released back to the pool.
|
| 287 |
+
"""
|
| 288 |
+
try:
|
| 289 |
+
self.read()
|
| 290 |
+
except (HTTPError, SocketError, BaseSSLError, HTTPException):
|
| 291 |
+
pass
|
| 292 |
+
|
| 293 |
+
@property
|
| 294 |
+
def data(self):
|
| 295 |
+
# For backwards-compat with earlier urllib3 0.4 and earlier.
|
| 296 |
+
if self._body:
|
| 297 |
+
return self._body
|
| 298 |
+
|
| 299 |
+
if self._fp:
|
| 300 |
+
return self.read(cache_content=True)
|
| 301 |
+
|
| 302 |
+
@property
|
| 303 |
+
def connection(self):
|
| 304 |
+
return self._connection
|
| 305 |
+
|
| 306 |
+
def isclosed(self):
|
| 307 |
+
return is_fp_closed(self._fp)
|
| 308 |
+
|
| 309 |
+
def tell(self):
|
| 310 |
+
"""
|
| 311 |
+
Obtain the number of bytes pulled over the wire so far. May differ from
|
| 312 |
+
the amount of content returned by :meth:``urllib3.response.HTTPResponse.read``
|
| 313 |
+
if bytes are encoded on the wire (e.g, compressed).
|
| 314 |
+
"""
|
| 315 |
+
return self._fp_bytes_read
|
| 316 |
+
|
| 317 |
+
def _init_length(self, request_method):
|
| 318 |
+
"""
|
| 319 |
+
Set initial length value for Response content if available.
|
| 320 |
+
"""
|
| 321 |
+
length = self.headers.get("content-length")
|
| 322 |
+
|
| 323 |
+
if length is not None:
|
| 324 |
+
if self.chunked:
|
| 325 |
+
# This Response will fail with an IncompleteRead if it can't be
|
| 326 |
+
# received as chunked. This method falls back to attempt reading
|
| 327 |
+
# the response before raising an exception.
|
| 328 |
+
log.warning(
|
| 329 |
+
"Received response with both Content-Length and "
|
| 330 |
+
"Transfer-Encoding set. This is expressly forbidden "
|
| 331 |
+
"by RFC 7230 sec 3.3.2. Ignoring Content-Length and "
|
| 332 |
+
"attempting to process response as Transfer-Encoding: "
|
| 333 |
+
"chunked."
|
| 334 |
+
)
|
| 335 |
+
return None
|
| 336 |
+
|
| 337 |
+
try:
|
| 338 |
+
# RFC 7230 section 3.3.2 specifies multiple content lengths can
|
| 339 |
+
# be sent in a single Content-Length header
|
| 340 |
+
# (e.g. Content-Length: 42, 42). This line ensures the values
|
| 341 |
+
# are all valid ints and that as long as the `set` length is 1,
|
| 342 |
+
# all values are the same. Otherwise, the header is invalid.
|
| 343 |
+
lengths = set([int(val) for val in length.split(",")])
|
| 344 |
+
if len(lengths) > 1:
|
| 345 |
+
raise InvalidHeader(
|
| 346 |
+
"Content-Length contained multiple "
|
| 347 |
+
"unmatching values (%s)" % length
|
| 348 |
+
)
|
| 349 |
+
length = lengths.pop()
|
| 350 |
+
except ValueError:
|
| 351 |
+
length = None
|
| 352 |
+
else:
|
| 353 |
+
if length < 0:
|
| 354 |
+
length = None
|
| 355 |
+
|
| 356 |
+
# Convert status to int for comparison
|
| 357 |
+
# In some cases, httplib returns a status of "_UNKNOWN"
|
| 358 |
+
try:
|
| 359 |
+
status = int(self.status)
|
| 360 |
+
except ValueError:
|
| 361 |
+
status = 0
|
| 362 |
+
|
| 363 |
+
# Check for responses that shouldn't include a body
|
| 364 |
+
if status in (204, 304) or 100 <= status < 200 or request_method == "HEAD":
|
| 365 |
+
length = 0
|
| 366 |
+
|
| 367 |
+
return length
|
| 368 |
+
|
| 369 |
+
def _init_decoder(self):
|
| 370 |
+
"""
|
| 371 |
+
Set-up the _decoder attribute if necessary.
|
| 372 |
+
"""
|
| 373 |
+
# Note: content-encoding value should be case-insensitive, per RFC 7230
|
| 374 |
+
# Section 3.2
|
| 375 |
+
content_encoding = self.headers.get("content-encoding", "").lower()
|
| 376 |
+
if self._decoder is None:
|
| 377 |
+
if content_encoding in self.CONTENT_DECODERS:
|
| 378 |
+
self._decoder = _get_decoder(content_encoding)
|
| 379 |
+
elif "," in content_encoding:
|
| 380 |
+
encodings = [
|
| 381 |
+
e.strip()
|
| 382 |
+
for e in content_encoding.split(",")
|
| 383 |
+
if e.strip() in self.CONTENT_DECODERS
|
| 384 |
+
]
|
| 385 |
+
if len(encodings):
|
| 386 |
+
self._decoder = _get_decoder(content_encoding)
|
| 387 |
+
|
| 388 |
+
DECODER_ERROR_CLASSES = (IOError, zlib.error)
|
| 389 |
+
if brotli is not None:
|
| 390 |
+
DECODER_ERROR_CLASSES += (brotli.error,)
|
| 391 |
+
|
| 392 |
+
def _decode(self, data, decode_content, flush_decoder):
|
| 393 |
+
"""
|
| 394 |
+
Decode the data passed in and potentially flush the decoder.
|
| 395 |
+
"""
|
| 396 |
+
if not decode_content:
|
| 397 |
+
return data
|
| 398 |
+
|
| 399 |
+
try:
|
| 400 |
+
if self._decoder:
|
| 401 |
+
data = self._decoder.decompress(data)
|
| 402 |
+
except self.DECODER_ERROR_CLASSES as e:
|
| 403 |
+
content_encoding = self.headers.get("content-encoding", "").lower()
|
| 404 |
+
raise DecodeError(
|
| 405 |
+
"Received response with content-encoding: %s, but "
|
| 406 |
+
"failed to decode it." % content_encoding,
|
| 407 |
+
e,
|
| 408 |
+
)
|
| 409 |
+
if flush_decoder:
|
| 410 |
+
data += self._flush_decoder()
|
| 411 |
+
|
| 412 |
+
return data
|
| 413 |
+
|
| 414 |
+
def _flush_decoder(self):
|
| 415 |
+
"""
|
| 416 |
+
Flushes the decoder. Should only be called if the decoder is actually
|
| 417 |
+
being used.
|
| 418 |
+
"""
|
| 419 |
+
if self._decoder:
|
| 420 |
+
buf = self._decoder.decompress(b"")
|
| 421 |
+
return buf + self._decoder.flush()
|
| 422 |
+
|
| 423 |
+
return b""
|
| 424 |
+
|
| 425 |
+
@contextmanager
|
| 426 |
+
def _error_catcher(self):
|
| 427 |
+
"""
|
| 428 |
+
Catch low-level python exceptions, instead re-raising urllib3
|
| 429 |
+
variants, so that low-level exceptions are not leaked in the
|
| 430 |
+
high-level api.
|
| 431 |
+
|
| 432 |
+
On exit, release the connection back to the pool.
|
| 433 |
+
"""
|
| 434 |
+
clean_exit = False
|
| 435 |
+
|
| 436 |
+
try:
|
| 437 |
+
try:
|
| 438 |
+
yield
|
| 439 |
+
|
| 440 |
+
except SocketTimeout:
|
| 441 |
+
# FIXME: Ideally we'd like to include the url in the ReadTimeoutError but
|
| 442 |
+
# there is yet no clean way to get at it from this context.
|
| 443 |
+
raise ReadTimeoutError(self._pool, None, "Read timed out.")
|
| 444 |
+
|
| 445 |
+
except BaseSSLError as e:
|
| 446 |
+
# FIXME: Is there a better way to differentiate between SSLErrors?
|
| 447 |
+
if "read operation timed out" not in str(e):
|
| 448 |
+
# SSL errors related to framing/MAC get wrapped and reraised here
|
| 449 |
+
raise SSLError(e)
|
| 450 |
+
|
| 451 |
+
raise ReadTimeoutError(self._pool, None, "Read timed out.")
|
| 452 |
+
|
| 453 |
+
except (HTTPException, SocketError) as e:
|
| 454 |
+
# This includes IncompleteRead.
|
| 455 |
+
raise ProtocolError("Connection broken: %r" % e, e)
|
| 456 |
+
|
| 457 |
+
# If no exception is thrown, we should avoid cleaning up
|
| 458 |
+
# unnecessarily.
|
| 459 |
+
clean_exit = True
|
| 460 |
+
finally:
|
| 461 |
+
# If we didn't terminate cleanly, we need to throw away our
|
| 462 |
+
# connection.
|
| 463 |
+
if not clean_exit:
|
| 464 |
+
# The response may not be closed but we're not going to use it
|
| 465 |
+
# anymore so close it now to ensure that the connection is
|
| 466 |
+
# released back to the pool.
|
| 467 |
+
if self._original_response:
|
| 468 |
+
self._original_response.close()
|
| 469 |
+
|
| 470 |
+
# Closing the response may not actually be sufficient to close
|
| 471 |
+
# everything, so if we have a hold of the connection close that
|
| 472 |
+
# too.
|
| 473 |
+
if self._connection:
|
| 474 |
+
self._connection.close()
|
| 475 |
+
|
| 476 |
+
# If we hold the original response but it's closed now, we should
|
| 477 |
+
# return the connection back to the pool.
|
| 478 |
+
if self._original_response and self._original_response.isclosed():
|
| 479 |
+
self.release_conn()
|
| 480 |
+
|
| 481 |
+
def _fp_read(self, amt):
|
| 482 |
+
"""
|
| 483 |
+
Read a response with the thought that reading the number of bytes
|
| 484 |
+
larger than can fit in a 32-bit int at a time via SSL in some
|
| 485 |
+
known cases leads to an overflow error that has to be prevented
|
| 486 |
+
if `amt` or `self.length_remaining` indicate that a problem may
|
| 487 |
+
happen.
|
| 488 |
+
|
| 489 |
+
The known cases:
|
| 490 |
+
* 3.8 <= CPython < 3.9.7 because of a bug
|
| 491 |
+
https://github.com/urllib3/urllib3/issues/2513#issuecomment-1152559900.
|
| 492 |
+
* urllib3 injected with pyOpenSSL-backed SSL-support.
|
| 493 |
+
* CPython < 3.10 only when `amt` does not fit 32-bit int.
|
| 494 |
+
"""
|
| 495 |
+
assert self._fp
|
| 496 |
+
c_int_max = 2 ** 31 - 1
|
| 497 |
+
if (
|
| 498 |
+
(
|
| 499 |
+
(amt and amt > c_int_max)
|
| 500 |
+
or (self.length_remaining and self.length_remaining > c_int_max)
|
| 501 |
+
)
|
| 502 |
+
and not util.IS_SECURETRANSPORT
|
| 503 |
+
and (util.IS_PYOPENSSL or sys.version_info < (3, 10))
|
| 504 |
+
):
|
| 505 |
+
buffer = io.BytesIO()
|
| 506 |
+
# Besides `max_chunk_amt` being a maximum chunk size, it
|
| 507 |
+
# affects memory overhead of reading a response by this
|
| 508 |
+
# method in CPython.
|
| 509 |
+
# `c_int_max` equal to 2 GiB - 1 byte is the actual maximum
|
| 510 |
+
# chunk size that does not lead to an overflow error, but
|
| 511 |
+
# 256 MiB is a compromise.
|
| 512 |
+
max_chunk_amt = 2 ** 28
|
| 513 |
+
while amt is None or amt != 0:
|
| 514 |
+
if amt is not None:
|
| 515 |
+
chunk_amt = min(amt, max_chunk_amt)
|
| 516 |
+
amt -= chunk_amt
|
| 517 |
+
else:
|
| 518 |
+
chunk_amt = max_chunk_amt
|
| 519 |
+
data = self._fp.read(chunk_amt)
|
| 520 |
+
if not data:
|
| 521 |
+
break
|
| 522 |
+
buffer.write(data)
|
| 523 |
+
del data # to reduce peak memory usage by `max_chunk_amt`.
|
| 524 |
+
return buffer.getvalue()
|
| 525 |
+
else:
|
| 526 |
+
# StringIO doesn't like amt=None
|
| 527 |
+
return self._fp.read(amt) if amt is not None else self._fp.read()
|
| 528 |
+
|
| 529 |
+
def read(self, amt=None, decode_content=None, cache_content=False):
|
| 530 |
+
"""
|
| 531 |
+
Similar to :meth:`http.client.HTTPResponse.read`, but with two additional
|
| 532 |
+
parameters: ``decode_content`` and ``cache_content``.
|
| 533 |
+
|
| 534 |
+
:param amt:
|
| 535 |
+
How much of the content to read. If specified, caching is skipped
|
| 536 |
+
because it doesn't make sense to cache partial content as the full
|
| 537 |
+
response.
|
| 538 |
+
|
| 539 |
+
:param decode_content:
|
| 540 |
+
If True, will attempt to decode the body based on the
|
| 541 |
+
'content-encoding' header.
|
| 542 |
+
|
| 543 |
+
:param cache_content:
|
| 544 |
+
If True, will save the returned data such that the same result is
|
| 545 |
+
returned despite of the state of the underlying file object. This
|
| 546 |
+
is useful if you want the ``.data`` property to continue working
|
| 547 |
+
after having ``.read()`` the file object. (Overridden if ``amt`` is
|
| 548 |
+
set.)
|
| 549 |
+
"""
|
| 550 |
+
self._init_decoder()
|
| 551 |
+
if decode_content is None:
|
| 552 |
+
decode_content = self.decode_content
|
| 553 |
+
|
| 554 |
+
if self._fp is None:
|
| 555 |
+
return
|
| 556 |
+
|
| 557 |
+
flush_decoder = False
|
| 558 |
+
fp_closed = getattr(self._fp, "closed", False)
|
| 559 |
+
|
| 560 |
+
with self._error_catcher():
|
| 561 |
+
data = self._fp_read(amt) if not fp_closed else b""
|
| 562 |
+
if amt is None:
|
| 563 |
+
flush_decoder = True
|
| 564 |
+
else:
|
| 565 |
+
cache_content = False
|
| 566 |
+
if (
|
| 567 |
+
amt != 0 and not data
|
| 568 |
+
): # Platform-specific: Buggy versions of Python.
|
| 569 |
+
# Close the connection when no data is returned
|
| 570 |
+
#
|
| 571 |
+
# This is redundant to what httplib/http.client _should_
|
| 572 |
+
# already do. However, versions of python released before
|
| 573 |
+
# December 15, 2012 (http://bugs.python.org/issue16298) do
|
| 574 |
+
# not properly close the connection in all cases. There is
|
| 575 |
+
# no harm in redundantly calling close.
|
| 576 |
+
self._fp.close()
|
| 577 |
+
flush_decoder = True
|
| 578 |
+
if self.enforce_content_length and self.length_remaining not in (
|
| 579 |
+
0,
|
| 580 |
+
None,
|
| 581 |
+
):
|
| 582 |
+
# This is an edge case that httplib failed to cover due
|
| 583 |
+
# to concerns of backward compatibility. We're
|
| 584 |
+
# addressing it here to make sure IncompleteRead is
|
| 585 |
+
# raised during streaming, so all calls with incorrect
|
| 586 |
+
# Content-Length are caught.
|
| 587 |
+
raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
|
| 588 |
+
|
| 589 |
+
if data:
|
| 590 |
+
self._fp_bytes_read += len(data)
|
| 591 |
+
if self.length_remaining is not None:
|
| 592 |
+
self.length_remaining -= len(data)
|
| 593 |
+
|
| 594 |
+
data = self._decode(data, decode_content, flush_decoder)
|
| 595 |
+
|
| 596 |
+
if cache_content:
|
| 597 |
+
self._body = data
|
| 598 |
+
|
| 599 |
+
return data
|
| 600 |
+
|
| 601 |
+
def stream(self, amt=2 ** 16, decode_content=None):
|
| 602 |
+
"""
|
| 603 |
+
A generator wrapper for the read() method. A call will block until
|
| 604 |
+
``amt`` bytes have been read from the connection or until the
|
| 605 |
+
connection is closed.
|
| 606 |
+
|
| 607 |
+
:param amt:
|
| 608 |
+
How much of the content to read. The generator will return up to
|
| 609 |
+
much data per iteration, but may return less. This is particularly
|
| 610 |
+
likely when using compressed data. However, the empty string will
|
| 611 |
+
never be returned.
|
| 612 |
+
|
| 613 |
+
:param decode_content:
|
| 614 |
+
If True, will attempt to decode the body based on the
|
| 615 |
+
'content-encoding' header.
|
| 616 |
+
"""
|
| 617 |
+
if self.chunked and self.supports_chunked_reads():
|
| 618 |
+
for line in self.read_chunked(amt, decode_content=decode_content):
|
| 619 |
+
yield line
|
| 620 |
+
else:
|
| 621 |
+
while not is_fp_closed(self._fp):
|
| 622 |
+
data = self.read(amt=amt, decode_content=decode_content)
|
| 623 |
+
|
| 624 |
+
if data:
|
| 625 |
+
yield data
|
| 626 |
+
|
| 627 |
+
@classmethod
|
| 628 |
+
def from_httplib(ResponseCls, r, **response_kw):
|
| 629 |
+
"""
|
| 630 |
+
Given an :class:`http.client.HTTPResponse` instance ``r``, return a
|
| 631 |
+
corresponding :class:`urllib3.response.HTTPResponse` object.
|
| 632 |
+
|
| 633 |
+
Remaining parameters are passed to the HTTPResponse constructor, along
|
| 634 |
+
with ``original_response=r``.
|
| 635 |
+
"""
|
| 636 |
+
headers = r.msg
|
| 637 |
+
|
| 638 |
+
if not isinstance(headers, HTTPHeaderDict):
|
| 639 |
+
if six.PY2:
|
| 640 |
+
# Python 2.7
|
| 641 |
+
headers = HTTPHeaderDict.from_httplib(headers)
|
| 642 |
+
else:
|
| 643 |
+
headers = HTTPHeaderDict(headers.items())
|
| 644 |
+
|
| 645 |
+
# HTTPResponse objects in Python 3 don't have a .strict attribute
|
| 646 |
+
strict = getattr(r, "strict", 0)
|
| 647 |
+
resp = ResponseCls(
|
| 648 |
+
body=r,
|
| 649 |
+
headers=headers,
|
| 650 |
+
status=r.status,
|
| 651 |
+
version=r.version,
|
| 652 |
+
reason=r.reason,
|
| 653 |
+
strict=strict,
|
| 654 |
+
original_response=r,
|
| 655 |
+
**response_kw
|
| 656 |
+
)
|
| 657 |
+
return resp
|
| 658 |
+
|
| 659 |
+
# Backwards-compatibility methods for http.client.HTTPResponse
|
| 660 |
+
def getheaders(self):
|
| 661 |
+
warnings.warn(
|
| 662 |
+
"HTTPResponse.getheaders() is deprecated and will be removed "
|
| 663 |
+
"in urllib3 v2.1.0. Instead access HTTPResponse.headers directly.",
|
| 664 |
+
category=DeprecationWarning,
|
| 665 |
+
stacklevel=2,
|
| 666 |
+
)
|
| 667 |
+
return self.headers
|
| 668 |
+
|
| 669 |
+
def getheader(self, name, default=None):
|
| 670 |
+
warnings.warn(
|
| 671 |
+
"HTTPResponse.getheader() is deprecated and will be removed "
|
| 672 |
+
"in urllib3 v2.1.0. Instead use HTTPResponse.headers.get(name, default).",
|
| 673 |
+
category=DeprecationWarning,
|
| 674 |
+
stacklevel=2,
|
| 675 |
+
)
|
| 676 |
+
return self.headers.get(name, default)
|
| 677 |
+
|
| 678 |
+
# Backwards compatibility for http.cookiejar
|
| 679 |
+
def info(self):
|
| 680 |
+
return self.headers
|
| 681 |
+
|
| 682 |
+
# Overrides from io.IOBase
|
| 683 |
+
def close(self):
|
| 684 |
+
if not self.closed:
|
| 685 |
+
self._fp.close()
|
| 686 |
+
|
| 687 |
+
if self._connection:
|
| 688 |
+
self._connection.close()
|
| 689 |
+
|
| 690 |
+
if not self.auto_close:
|
| 691 |
+
io.IOBase.close(self)
|
| 692 |
+
|
| 693 |
+
@property
|
| 694 |
+
def closed(self):
|
| 695 |
+
if not self.auto_close:
|
| 696 |
+
return io.IOBase.closed.__get__(self)
|
| 697 |
+
elif self._fp is None:
|
| 698 |
+
return True
|
| 699 |
+
elif hasattr(self._fp, "isclosed"):
|
| 700 |
+
return self._fp.isclosed()
|
| 701 |
+
elif hasattr(self._fp, "closed"):
|
| 702 |
+
return self._fp.closed
|
| 703 |
+
else:
|
| 704 |
+
return True
|
| 705 |
+
|
| 706 |
+
def fileno(self):
|
| 707 |
+
if self._fp is None:
|
| 708 |
+
raise IOError("HTTPResponse has no file to get a fileno from")
|
| 709 |
+
elif hasattr(self._fp, "fileno"):
|
| 710 |
+
return self._fp.fileno()
|
| 711 |
+
else:
|
| 712 |
+
raise IOError(
|
| 713 |
+
"The file-like object this HTTPResponse is wrapped "
|
| 714 |
+
"around has no file descriptor"
|
| 715 |
+
)
|
| 716 |
+
|
| 717 |
+
def flush(self):
|
| 718 |
+
if (
|
| 719 |
+
self._fp is not None
|
| 720 |
+
and hasattr(self._fp, "flush")
|
| 721 |
+
and not getattr(self._fp, "closed", False)
|
| 722 |
+
):
|
| 723 |
+
return self._fp.flush()
|
| 724 |
+
|
| 725 |
+
def readable(self):
|
| 726 |
+
# This method is required for `io` module compatibility.
|
| 727 |
+
return True
|
| 728 |
+
|
| 729 |
+
def readinto(self, b):
|
| 730 |
+
# This method is required for `io` module compatibility.
|
| 731 |
+
temp = self.read(len(b))
|
| 732 |
+
if len(temp) == 0:
|
| 733 |
+
return 0
|
| 734 |
+
else:
|
| 735 |
+
b[: len(temp)] = temp
|
| 736 |
+
return len(temp)
|
| 737 |
+
|
| 738 |
+
def supports_chunked_reads(self):
|
| 739 |
+
"""
|
| 740 |
+
Checks if the underlying file-like object looks like a
|
| 741 |
+
:class:`http.client.HTTPResponse` object. We do this by testing for
|
| 742 |
+
the fp attribute. If it is present we assume it returns raw chunks as
|
| 743 |
+
processed by read_chunked().
|
| 744 |
+
"""
|
| 745 |
+
return hasattr(self._fp, "fp")
|
| 746 |
+
|
| 747 |
+
def _update_chunk_length(self):
|
| 748 |
+
# First, we'll figure out length of a chunk and then
|
| 749 |
+
# we'll try to read it from socket.
|
| 750 |
+
if self.chunk_left is not None:
|
| 751 |
+
return
|
| 752 |
+
line = self._fp.fp.readline()
|
| 753 |
+
line = line.split(b";", 1)[0]
|
| 754 |
+
try:
|
| 755 |
+
self.chunk_left = int(line, 16)
|
| 756 |
+
except ValueError:
|
| 757 |
+
# Invalid chunked protocol response, abort.
|
| 758 |
+
self.close()
|
| 759 |
+
raise InvalidChunkLength(self, line)
|
| 760 |
+
|
| 761 |
+
def _handle_chunk(self, amt):
|
| 762 |
+
returned_chunk = None
|
| 763 |
+
if amt is None:
|
| 764 |
+
chunk = self._fp._safe_read(self.chunk_left)
|
| 765 |
+
returned_chunk = chunk
|
| 766 |
+
self._fp._safe_read(2) # Toss the CRLF at the end of the chunk.
|
| 767 |
+
self.chunk_left = None
|
| 768 |
+
elif amt < self.chunk_left:
|
| 769 |
+
value = self._fp._safe_read(amt)
|
| 770 |
+
self.chunk_left = self.chunk_left - amt
|
| 771 |
+
returned_chunk = value
|
| 772 |
+
elif amt == self.chunk_left:
|
| 773 |
+
value = self._fp._safe_read(amt)
|
| 774 |
+
self._fp._safe_read(2) # Toss the CRLF at the end of the chunk.
|
| 775 |
+
self.chunk_left = None
|
| 776 |
+
returned_chunk = value
|
| 777 |
+
else: # amt > self.chunk_left
|
| 778 |
+
returned_chunk = self._fp._safe_read(self.chunk_left)
|
| 779 |
+
self._fp._safe_read(2) # Toss the CRLF at the end of the chunk.
|
| 780 |
+
self.chunk_left = None
|
| 781 |
+
return returned_chunk
|
| 782 |
+
|
| 783 |
+
def read_chunked(self, amt=None, decode_content=None):
|
| 784 |
+
"""
|
| 785 |
+
Similar to :meth:`HTTPResponse.read`, but with an additional
|
| 786 |
+
parameter: ``decode_content``.
|
| 787 |
+
|
| 788 |
+
:param amt:
|
| 789 |
+
How much of the content to read. If specified, caching is skipped
|
| 790 |
+
because it doesn't make sense to cache partial content as the full
|
| 791 |
+
response.
|
| 792 |
+
|
| 793 |
+
:param decode_content:
|
| 794 |
+
If True, will attempt to decode the body based on the
|
| 795 |
+
'content-encoding' header.
|
| 796 |
+
"""
|
| 797 |
+
self._init_decoder()
|
| 798 |
+
# FIXME: Rewrite this method and make it a class with a better structured logic.
|
| 799 |
+
if not self.chunked:
|
| 800 |
+
raise ResponseNotChunked(
|
| 801 |
+
"Response is not chunked. "
|
| 802 |
+
"Header 'transfer-encoding: chunked' is missing."
|
| 803 |
+
)
|
| 804 |
+
if not self.supports_chunked_reads():
|
| 805 |
+
raise BodyNotHttplibCompatible(
|
| 806 |
+
"Body should be http.client.HTTPResponse like. "
|
| 807 |
+
"It should have have an fp attribute which returns raw chunks."
|
| 808 |
+
)
|
| 809 |
+
|
| 810 |
+
with self._error_catcher():
|
| 811 |
+
# Don't bother reading the body of a HEAD request.
|
| 812 |
+
if self._original_response and is_response_to_head(self._original_response):
|
| 813 |
+
self._original_response.close()
|
| 814 |
+
return
|
| 815 |
+
|
| 816 |
+
# If a response is already read and closed
|
| 817 |
+
# then return immediately.
|
| 818 |
+
if self._fp.fp is None:
|
| 819 |
+
return
|
| 820 |
+
|
| 821 |
+
while True:
|
| 822 |
+
self._update_chunk_length()
|
| 823 |
+
if self.chunk_left == 0:
|
| 824 |
+
break
|
| 825 |
+
chunk = self._handle_chunk(amt)
|
| 826 |
+
decoded = self._decode(
|
| 827 |
+
chunk, decode_content=decode_content, flush_decoder=False
|
| 828 |
+
)
|
| 829 |
+
if decoded:
|
| 830 |
+
yield decoded
|
| 831 |
+
|
| 832 |
+
if decode_content:
|
| 833 |
+
# On CPython and PyPy, we should never need to flush the
|
| 834 |
+
# decoder. However, on Jython we *might* need to, so
|
| 835 |
+
# lets defensively do it anyway.
|
| 836 |
+
decoded = self._flush_decoder()
|
| 837 |
+
if decoded: # Platform-specific: Jython.
|
| 838 |
+
yield decoded
|
| 839 |
+
|
| 840 |
+
# Chunk content ends with \r\n: discard it.
|
| 841 |
+
while True:
|
| 842 |
+
line = self._fp.fp.readline()
|
| 843 |
+
if not line:
|
| 844 |
+
# Some sites may not end with '\r\n'.
|
| 845 |
+
break
|
| 846 |
+
if line == b"\r\n":
|
| 847 |
+
break
|
| 848 |
+
|
| 849 |
+
# We read everything; close the "file".
|
| 850 |
+
if self._original_response:
|
| 851 |
+
self._original_response.close()
|
| 852 |
+
|
| 853 |
+
def geturl(self):
|
| 854 |
+
"""
|
| 855 |
+
Returns the URL that was the source of this response.
|
| 856 |
+
If the request that generated this response redirected, this method
|
| 857 |
+
will return the final redirect location.
|
| 858 |
+
"""
|
| 859 |
+
if self.retries is not None and len(self.retries.history):
|
| 860 |
+
return self.retries.history[-1].redirect_location
|
| 861 |
+
else:
|
| 862 |
+
return self._request_url
|
| 863 |
+
|
| 864 |
+
def __iter__(self):
|
| 865 |
+
buffer = []
|
| 866 |
+
for chunk in self.stream(decode_content=True):
|
| 867 |
+
if b"\n" in chunk:
|
| 868 |
+
chunk = chunk.split(b"\n")
|
| 869 |
+
yield b"".join(buffer) + chunk[0] + b"\n"
|
| 870 |
+
for x in chunk[1:-1]:
|
| 871 |
+
yield x + b"\n"
|
| 872 |
+
if chunk[-1]:
|
| 873 |
+
buffer = [chunk[-1]]
|
| 874 |
+
else:
|
| 875 |
+
buffer = []
|
| 876 |
+
else:
|
| 877 |
+
buffer.append(chunk)
|
| 878 |
+
if buffer:
|
| 879 |
+
yield b"".join(buffer)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/__init__.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
# For backwards compatibility, provide imports that used to be here.
|
| 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 |
+
HAS_SNI,
|
| 11 |
+
IS_PYOPENSSL,
|
| 12 |
+
IS_SECURETRANSPORT,
|
| 13 |
+
PROTOCOL_TLS,
|
| 14 |
+
SSLContext,
|
| 15 |
+
assert_fingerprint,
|
| 16 |
+
resolve_cert_reqs,
|
| 17 |
+
resolve_ssl_version,
|
| 18 |
+
ssl_wrap_socket,
|
| 19 |
+
)
|
| 20 |
+
from .timeout import Timeout, current_time
|
| 21 |
+
from .url import Url, get_host, parse_url, split_first
|
| 22 |
+
from .wait import wait_for_read, wait_for_write
|
| 23 |
+
|
| 24 |
+
__all__ = (
|
| 25 |
+
"HAS_SNI",
|
| 26 |
+
"IS_PYOPENSSL",
|
| 27 |
+
"IS_SECURETRANSPORT",
|
| 28 |
+
"SSLContext",
|
| 29 |
+
"PROTOCOL_TLS",
|
| 30 |
+
"ALPN_PROTOCOLS",
|
| 31 |
+
"Retry",
|
| 32 |
+
"Timeout",
|
| 33 |
+
"Url",
|
| 34 |
+
"assert_fingerprint",
|
| 35 |
+
"current_time",
|
| 36 |
+
"is_connection_dropped",
|
| 37 |
+
"is_fp_closed",
|
| 38 |
+
"get_host",
|
| 39 |
+
"parse_url",
|
| 40 |
+
"make_headers",
|
| 41 |
+
"resolve_cert_reqs",
|
| 42 |
+
"resolve_ssl_version",
|
| 43 |
+
"split_first",
|
| 44 |
+
"ssl_wrap_socket",
|
| 45 |
+
"wait_for_read",
|
| 46 |
+
"wait_for_write",
|
| 47 |
+
"SKIP_HEADER",
|
| 48 |
+
"SKIPPABLE_HEADERS",
|
| 49 |
+
)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/connection.py
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import socket
|
| 4 |
+
|
| 5 |
+
from ..contrib import _appengine_environ
|
| 6 |
+
from ..exceptions import LocationParseError
|
| 7 |
+
from ..packages import six
|
| 8 |
+
from .wait import NoWayToWaitForSocketError, wait_for_read
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
def is_connection_dropped(conn): # Platform-specific
|
| 12 |
+
"""
|
| 13 |
+
Returns True if the connection is dropped and should be closed.
|
| 14 |
+
|
| 15 |
+
:param conn:
|
| 16 |
+
:class:`http.client.HTTPConnection` object.
|
| 17 |
+
|
| 18 |
+
Note: For platforms like AppEngine, this will always return ``False`` to
|
| 19 |
+
let the platform handle connection recycling transparently for us.
|
| 20 |
+
"""
|
| 21 |
+
sock = getattr(conn, "sock", False)
|
| 22 |
+
if sock is False: # Platform-specific: AppEngine
|
| 23 |
+
return False
|
| 24 |
+
if sock is None: # Connection already closed (such as by httplib).
|
| 25 |
+
return True
|
| 26 |
+
try:
|
| 27 |
+
# Returns True if readable, which here means it's been dropped
|
| 28 |
+
return wait_for_read(sock, timeout=0.0)
|
| 29 |
+
except NoWayToWaitForSocketError: # Platform-specific: AppEngine
|
| 30 |
+
return False
|
| 31 |
+
|
| 32 |
+
|
| 33 |
+
# This function is copied from socket.py in the Python 2.7 standard
|
| 34 |
+
# library test suite. Added to its signature is only `socket_options`.
|
| 35 |
+
# One additional modification is that we avoid binding to IPv6 servers
|
| 36 |
+
# discovered in DNS if the system doesn't have IPv6 functionality.
|
| 37 |
+
def create_connection(
|
| 38 |
+
address,
|
| 39 |
+
timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
|
| 40 |
+
source_address=None,
|
| 41 |
+
socket_options=None,
|
| 42 |
+
):
|
| 43 |
+
"""Connect to *address* and return the socket object.
|
| 44 |
+
|
| 45 |
+
Convenience function. Connect to *address* (a 2-tuple ``(host,
|
| 46 |
+
port)``) and return the socket object. Passing the optional
|
| 47 |
+
*timeout* parameter will set the timeout on the socket instance
|
| 48 |
+
before attempting to connect. If no *timeout* is supplied, the
|
| 49 |
+
global default timeout setting returned by :func:`socket.getdefaulttimeout`
|
| 50 |
+
is used. If *source_address* is set it must be a tuple of (host, port)
|
| 51 |
+
for the socket to bind as a source address before making the connection.
|
| 52 |
+
An host of '' or port 0 tells the OS to use the default.
|
| 53 |
+
"""
|
| 54 |
+
|
| 55 |
+
host, port = address
|
| 56 |
+
if host.startswith("["):
|
| 57 |
+
host = host.strip("[]")
|
| 58 |
+
err = None
|
| 59 |
+
|
| 60 |
+
# Using the value from allowed_gai_family() in the context of getaddrinfo lets
|
| 61 |
+
# us select whether to work with IPv4 DNS records, IPv6 records, or both.
|
| 62 |
+
# The original create_connection function always returns all records.
|
| 63 |
+
family = allowed_gai_family()
|
| 64 |
+
|
| 65 |
+
try:
|
| 66 |
+
host.encode("idna")
|
| 67 |
+
except UnicodeError:
|
| 68 |
+
return six.raise_from(
|
| 69 |
+
LocationParseError(u"'%s', label empty or too long" % host), None
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
|
| 73 |
+
af, socktype, proto, canonname, sa = res
|
| 74 |
+
sock = None
|
| 75 |
+
try:
|
| 76 |
+
sock = socket.socket(af, socktype, proto)
|
| 77 |
+
|
| 78 |
+
# If provided, set socket level options before connecting.
|
| 79 |
+
_set_socket_options(sock, socket_options)
|
| 80 |
+
|
| 81 |
+
if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
|
| 82 |
+
sock.settimeout(timeout)
|
| 83 |
+
if source_address:
|
| 84 |
+
sock.bind(source_address)
|
| 85 |
+
sock.connect(sa)
|
| 86 |
+
return sock
|
| 87 |
+
|
| 88 |
+
except socket.error as e:
|
| 89 |
+
err = e
|
| 90 |
+
if sock is not None:
|
| 91 |
+
sock.close()
|
| 92 |
+
sock = None
|
| 93 |
+
|
| 94 |
+
if err is not None:
|
| 95 |
+
raise err
|
| 96 |
+
|
| 97 |
+
raise socket.error("getaddrinfo returns an empty list")
|
| 98 |
+
|
| 99 |
+
|
| 100 |
+
def _set_socket_options(sock, options):
|
| 101 |
+
if options is None:
|
| 102 |
+
return
|
| 103 |
+
|
| 104 |
+
for opt in options:
|
| 105 |
+
sock.setsockopt(*opt)
|
| 106 |
+
|
| 107 |
+
|
| 108 |
+
def allowed_gai_family():
|
| 109 |
+
"""This function is designed to work in the context of
|
| 110 |
+
getaddrinfo, where family=socket.AF_UNSPEC is the default and
|
| 111 |
+
will perform a DNS search for both IPv6 and IPv4 records."""
|
| 112 |
+
|
| 113 |
+
family = socket.AF_INET
|
| 114 |
+
if HAS_IPV6:
|
| 115 |
+
family = socket.AF_UNSPEC
|
| 116 |
+
return family
|
| 117 |
+
|
| 118 |
+
|
| 119 |
+
def _has_ipv6(host):
|
| 120 |
+
"""Returns True if the system can bind an IPv6 address."""
|
| 121 |
+
sock = None
|
| 122 |
+
has_ipv6 = False
|
| 123 |
+
|
| 124 |
+
# App Engine doesn't support IPV6 sockets and actually has a quota on the
|
| 125 |
+
# number of sockets that can be used, so just early out here instead of
|
| 126 |
+
# creating a socket needlessly.
|
| 127 |
+
# See https://github.com/urllib3/urllib3/issues/1446
|
| 128 |
+
if _appengine_environ.is_appengine_sandbox():
|
| 129 |
+
return False
|
| 130 |
+
|
| 131 |
+
if socket.has_ipv6:
|
| 132 |
+
# has_ipv6 returns true if cPython was compiled with IPv6 support.
|
| 133 |
+
# It does not tell us if the system has IPv6 support enabled. To
|
| 134 |
+
# determine that we must bind to an IPv6 address.
|
| 135 |
+
# https://github.com/urllib3/urllib3/pull/611
|
| 136 |
+
# https://bugs.python.org/issue658327
|
| 137 |
+
try:
|
| 138 |
+
sock = socket.socket(socket.AF_INET6)
|
| 139 |
+
sock.bind((host, 0))
|
| 140 |
+
has_ipv6 = True
|
| 141 |
+
except Exception:
|
| 142 |
+
pass
|
| 143 |
+
|
| 144 |
+
if sock:
|
| 145 |
+
sock.close()
|
| 146 |
+
return has_ipv6
|
| 147 |
+
|
| 148 |
+
|
| 149 |
+
HAS_IPV6 = _has_ipv6("::1")
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/proxy.py
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .ssl_ import create_urllib3_context, resolve_cert_reqs, resolve_ssl_version
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
def connection_requires_http_tunnel(
|
| 5 |
+
proxy_url=None, proxy_config=None, destination_scheme=None
|
| 6 |
+
):
|
| 7 |
+
"""
|
| 8 |
+
Returns True if the connection requires an HTTP CONNECT through the proxy.
|
| 9 |
+
|
| 10 |
+
:param URL proxy_url:
|
| 11 |
+
URL of the proxy.
|
| 12 |
+
:param ProxyConfig proxy_config:
|
| 13 |
+
Proxy configuration from poolmanager.py
|
| 14 |
+
:param str destination_scheme:
|
| 15 |
+
The scheme of the destination. (i.e https, http, etc)
|
| 16 |
+
"""
|
| 17 |
+
# If we're not using a proxy, no way to use a tunnel.
|
| 18 |
+
if proxy_url is None:
|
| 19 |
+
return False
|
| 20 |
+
|
| 21 |
+
# HTTP destinations never require tunneling, we always forward.
|
| 22 |
+
if destination_scheme == "http":
|
| 23 |
+
return False
|
| 24 |
+
|
| 25 |
+
# Support for forwarding with HTTPS proxies and HTTPS destinations.
|
| 26 |
+
if (
|
| 27 |
+
proxy_url.scheme == "https"
|
| 28 |
+
and proxy_config
|
| 29 |
+
and proxy_config.use_forwarding_for_https
|
| 30 |
+
):
|
| 31 |
+
return False
|
| 32 |
+
|
| 33 |
+
# Otherwise always use a tunnel.
|
| 34 |
+
return True
|
| 35 |
+
|
| 36 |
+
|
| 37 |
+
def create_proxy_ssl_context(
|
| 38 |
+
ssl_version, cert_reqs, ca_certs=None, ca_cert_dir=None, ca_cert_data=None
|
| 39 |
+
):
|
| 40 |
+
"""
|
| 41 |
+
Generates a default proxy ssl context if one hasn't been provided by the
|
| 42 |
+
user.
|
| 43 |
+
"""
|
| 44 |
+
ssl_context = create_urllib3_context(
|
| 45 |
+
ssl_version=resolve_ssl_version(ssl_version),
|
| 46 |
+
cert_reqs=resolve_cert_reqs(cert_reqs),
|
| 47 |
+
)
|
| 48 |
+
|
| 49 |
+
if (
|
| 50 |
+
not ca_certs
|
| 51 |
+
and not ca_cert_dir
|
| 52 |
+
and not ca_cert_data
|
| 53 |
+
and hasattr(ssl_context, "load_default_certs")
|
| 54 |
+
):
|
| 55 |
+
ssl_context.load_default_certs()
|
| 56 |
+
|
| 57 |
+
return ssl_context
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/queue.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import collections
|
| 2 |
+
|
| 3 |
+
from ..packages import six
|
| 4 |
+
from ..packages.six.moves import queue
|
| 5 |
+
|
| 6 |
+
if six.PY2:
|
| 7 |
+
# Queue is imported for side effects on MS Windows. See issue #229.
|
| 8 |
+
import Queue as _unused_module_Queue # noqa: F401
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class LifoQueue(queue.Queue):
|
| 12 |
+
def _init(self, _):
|
| 13 |
+
self.queue = collections.deque()
|
| 14 |
+
|
| 15 |
+
def _qsize(self, len=len):
|
| 16 |
+
return len(self.queue)
|
| 17 |
+
|
| 18 |
+
def _put(self, item):
|
| 19 |
+
self.queue.append(item)
|
| 20 |
+
|
| 21 |
+
def _get(self):
|
| 22 |
+
return self.queue.pop()
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/request.py
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
from base64 import b64encode
|
| 4 |
+
|
| 5 |
+
from ..exceptions import UnrewindableBodyError
|
| 6 |
+
from ..packages.six import b, integer_types
|
| 7 |
+
|
| 8 |
+
# Pass as a value within ``headers`` to skip
|
| 9 |
+
# emitting some HTTP headers that are added automatically.
|
| 10 |
+
# The only headers that are supported are ``Accept-Encoding``,
|
| 11 |
+
# ``Host``, and ``User-Agent``.
|
| 12 |
+
SKIP_HEADER = "@@@SKIP_HEADER@@@"
|
| 13 |
+
SKIPPABLE_HEADERS = frozenset(["accept-encoding", "host", "user-agent"])
|
| 14 |
+
|
| 15 |
+
ACCEPT_ENCODING = "gzip,deflate"
|
| 16 |
+
|
| 17 |
+
_FAILEDTELL = object()
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def make_headers(
|
| 21 |
+
keep_alive=None,
|
| 22 |
+
accept_encoding=None,
|
| 23 |
+
user_agent=None,
|
| 24 |
+
basic_auth=None,
|
| 25 |
+
proxy_basic_auth=None,
|
| 26 |
+
disable_cache=None,
|
| 27 |
+
):
|
| 28 |
+
"""
|
| 29 |
+
Shortcuts for generating request headers.
|
| 30 |
+
|
| 31 |
+
:param keep_alive:
|
| 32 |
+
If ``True``, adds 'connection: keep-alive' header.
|
| 33 |
+
|
| 34 |
+
:param accept_encoding:
|
| 35 |
+
Can be a boolean, list, or string.
|
| 36 |
+
``True`` translates to 'gzip,deflate'.
|
| 37 |
+
List will get joined by comma.
|
| 38 |
+
String will be used as provided.
|
| 39 |
+
|
| 40 |
+
:param user_agent:
|
| 41 |
+
String representing the user-agent you want, such as
|
| 42 |
+
"python-urllib3/0.6"
|
| 43 |
+
|
| 44 |
+
:param basic_auth:
|
| 45 |
+
Colon-separated username:password string for 'authorization: basic ...'
|
| 46 |
+
auth header.
|
| 47 |
+
|
| 48 |
+
:param proxy_basic_auth:
|
| 49 |
+
Colon-separated username:password string for 'proxy-authorization: basic ...'
|
| 50 |
+
auth header.
|
| 51 |
+
|
| 52 |
+
:param disable_cache:
|
| 53 |
+
If ``True``, adds 'cache-control: no-cache' header.
|
| 54 |
+
|
| 55 |
+
Example::
|
| 56 |
+
|
| 57 |
+
>>> make_headers(keep_alive=True, user_agent="Batman/1.0")
|
| 58 |
+
{'connection': 'keep-alive', 'user-agent': 'Batman/1.0'}
|
| 59 |
+
>>> make_headers(accept_encoding=True)
|
| 60 |
+
{'accept-encoding': 'gzip,deflate'}
|
| 61 |
+
"""
|
| 62 |
+
headers = {}
|
| 63 |
+
if accept_encoding:
|
| 64 |
+
if isinstance(accept_encoding, str):
|
| 65 |
+
pass
|
| 66 |
+
elif isinstance(accept_encoding, list):
|
| 67 |
+
accept_encoding = ",".join(accept_encoding)
|
| 68 |
+
else:
|
| 69 |
+
accept_encoding = ACCEPT_ENCODING
|
| 70 |
+
headers["accept-encoding"] = accept_encoding
|
| 71 |
+
|
| 72 |
+
if user_agent:
|
| 73 |
+
headers["user-agent"] = user_agent
|
| 74 |
+
|
| 75 |
+
if keep_alive:
|
| 76 |
+
headers["connection"] = "keep-alive"
|
| 77 |
+
|
| 78 |
+
if basic_auth:
|
| 79 |
+
headers["authorization"] = "Basic " + b64encode(b(basic_auth)).decode("utf-8")
|
| 80 |
+
|
| 81 |
+
if proxy_basic_auth:
|
| 82 |
+
headers["proxy-authorization"] = "Basic " + b64encode(
|
| 83 |
+
b(proxy_basic_auth)
|
| 84 |
+
).decode("utf-8")
|
| 85 |
+
|
| 86 |
+
if disable_cache:
|
| 87 |
+
headers["cache-control"] = "no-cache"
|
| 88 |
+
|
| 89 |
+
return headers
|
| 90 |
+
|
| 91 |
+
|
| 92 |
+
def set_file_position(body, pos):
|
| 93 |
+
"""
|
| 94 |
+
If a position is provided, move file to that point.
|
| 95 |
+
Otherwise, we'll attempt to record a position for future use.
|
| 96 |
+
"""
|
| 97 |
+
if pos is not None:
|
| 98 |
+
rewind_body(body, pos)
|
| 99 |
+
elif getattr(body, "tell", None) is not None:
|
| 100 |
+
try:
|
| 101 |
+
pos = body.tell()
|
| 102 |
+
except (IOError, OSError):
|
| 103 |
+
# This differentiates from None, allowing us to catch
|
| 104 |
+
# a failed `tell()` later when trying to rewind the body.
|
| 105 |
+
pos = _FAILEDTELL
|
| 106 |
+
|
| 107 |
+
return pos
|
| 108 |
+
|
| 109 |
+
|
| 110 |
+
def rewind_body(body, body_pos):
|
| 111 |
+
"""
|
| 112 |
+
Attempt to rewind body to a certain position.
|
| 113 |
+
Primarily used for request redirects and retries.
|
| 114 |
+
|
| 115 |
+
:param body:
|
| 116 |
+
File-like object that supports seek.
|
| 117 |
+
|
| 118 |
+
:param int pos:
|
| 119 |
+
Position to seek to in file.
|
| 120 |
+
"""
|
| 121 |
+
body_seek = getattr(body, "seek", None)
|
| 122 |
+
if body_seek is not None and isinstance(body_pos, integer_types):
|
| 123 |
+
try:
|
| 124 |
+
body_seek(body_pos)
|
| 125 |
+
except (IOError, OSError):
|
| 126 |
+
raise UnrewindableBodyError(
|
| 127 |
+
"An error occurred when rewinding request body for redirect/retry."
|
| 128 |
+
)
|
| 129 |
+
elif body_pos is _FAILEDTELL:
|
| 130 |
+
raise UnrewindableBodyError(
|
| 131 |
+
"Unable to record file position for rewinding "
|
| 132 |
+
"request body during a redirect/retry."
|
| 133 |
+
)
|
| 134 |
+
else:
|
| 135 |
+
raise ValueError(
|
| 136 |
+
"body_pos must be of type integer, instead it was %s." % type(body_pos)
|
| 137 |
+
)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/response.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
from email.errors import MultipartInvariantViolationDefect, StartBoundaryNotFoundDefect
|
| 4 |
+
|
| 5 |
+
from ..exceptions import HeaderParsingError
|
| 6 |
+
from ..packages.six.moves import http_client as httplib
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
def is_fp_closed(obj):
|
| 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()
|
| 21 |
+
except AttributeError:
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
try:
|
| 25 |
+
# Check via the official file-like-object way.
|
| 26 |
+
return obj.closed
|
| 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
|
| 34 |
+
except AttributeError:
|
| 35 |
+
pass
|
| 36 |
+
|
| 37 |
+
raise ValueError("Unable to determine whether fp is closed.")
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def assert_header_parsing(headers):
|
| 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("expected httplib.Message, got {0}.".format(type(headers)))
|
| 57 |
+
|
| 58 |
+
defects = getattr(headers, "defects", None)
|
| 59 |
+
get_payload = getattr(headers, "get_payload", None)
|
| 60 |
+
|
| 61 |
+
unparsed_data = None
|
| 62 |
+
if get_payload:
|
| 63 |
+
# get_payload is actually email.message.Message.get_payload;
|
| 64 |
+
# we're only interested in the result if it's not a multipart message
|
| 65 |
+
if not headers.is_multipart():
|
| 66 |
+
payload = get_payload()
|
| 67 |
+
|
| 68 |
+
if isinstance(payload, (bytes, str)):
|
| 69 |
+
unparsed_data = payload
|
| 70 |
+
if defects:
|
| 71 |
+
# httplib is assuming a response body is available
|
| 72 |
+
# when parsing headers even when httplib only sends
|
| 73 |
+
# header data to parse_headers() This results in
|
| 74 |
+
# defects on multipart responses in particular.
|
| 75 |
+
# See: https://github.com/urllib3/urllib3/issues/800
|
| 76 |
+
|
| 77 |
+
# So we ignore the following defects:
|
| 78 |
+
# - StartBoundaryNotFoundDefect:
|
| 79 |
+
# The claimed start boundary was never found.
|
| 80 |
+
# - MultipartInvariantViolationDefect:
|
| 81 |
+
# A message claimed to be a multipart but no subparts were found.
|
| 82 |
+
defects = [
|
| 83 |
+
defect
|
| 84 |
+
for defect in defects
|
| 85 |
+
if not isinstance(
|
| 86 |
+
defect, (StartBoundaryNotFoundDefect, MultipartInvariantViolationDefect)
|
| 87 |
+
)
|
| 88 |
+
]
|
| 89 |
+
|
| 90 |
+
if defects or unparsed_data:
|
| 91 |
+
raise HeaderParsingError(defects=defects, unparsed_data=unparsed_data)
|
| 92 |
+
|
| 93 |
+
|
| 94 |
+
def is_response_to_head(response):
|
| 95 |
+
"""
|
| 96 |
+
Checks whether the request of a response has been a HEAD-request.
|
| 97 |
+
Handles the quirks of AppEngine.
|
| 98 |
+
|
| 99 |
+
:param http.client.HTTPResponse response:
|
| 100 |
+
Response to check if the originating request
|
| 101 |
+
used 'HEAD' as a method.
|
| 102 |
+
"""
|
| 103 |
+
# FIXME: Can we do this somehow without accessing private httplib _method?
|
| 104 |
+
method = response._method
|
| 105 |
+
if isinstance(method, int): # Platform-specific: Appengine
|
| 106 |
+
return method == 3
|
| 107 |
+
return method.upper() == "HEAD"
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/retry.py
ADDED
|
@@ -0,0 +1,622 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import email
|
| 4 |
+
import logging
|
| 5 |
+
import re
|
| 6 |
+
import time
|
| 7 |
+
import warnings
|
| 8 |
+
from collections import namedtuple
|
| 9 |
+
from itertools import takewhile
|
| 10 |
+
|
| 11 |
+
from ..exceptions import (
|
| 12 |
+
ConnectTimeoutError,
|
| 13 |
+
InvalidHeader,
|
| 14 |
+
MaxRetryError,
|
| 15 |
+
ProtocolError,
|
| 16 |
+
ProxyError,
|
| 17 |
+
ReadTimeoutError,
|
| 18 |
+
ResponseError,
|
| 19 |
+
)
|
| 20 |
+
from ..packages import six
|
| 21 |
+
|
| 22 |
+
log = logging.getLogger(__name__)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# Data structure for representing the metadata of requests that result in a retry.
|
| 26 |
+
RequestHistory = namedtuple(
|
| 27 |
+
"RequestHistory", ["method", "url", "error", "status", "redirect_location"]
|
| 28 |
+
)
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
# TODO: In v2 we can remove this sentinel and metaclass with deprecated options.
|
| 32 |
+
_Default = object()
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class _RetryMeta(type):
|
| 36 |
+
@property
|
| 37 |
+
def DEFAULT_METHOD_WHITELIST(cls):
|
| 38 |
+
warnings.warn(
|
| 39 |
+
"Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and "
|
| 40 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_ALLOWED_METHODS' instead",
|
| 41 |
+
DeprecationWarning,
|
| 42 |
+
)
|
| 43 |
+
return cls.DEFAULT_ALLOWED_METHODS
|
| 44 |
+
|
| 45 |
+
@DEFAULT_METHOD_WHITELIST.setter
|
| 46 |
+
def DEFAULT_METHOD_WHITELIST(cls, value):
|
| 47 |
+
warnings.warn(
|
| 48 |
+
"Using 'Retry.DEFAULT_METHOD_WHITELIST' is deprecated and "
|
| 49 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_ALLOWED_METHODS' instead",
|
| 50 |
+
DeprecationWarning,
|
| 51 |
+
)
|
| 52 |
+
cls.DEFAULT_ALLOWED_METHODS = value
|
| 53 |
+
|
| 54 |
+
@property
|
| 55 |
+
def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls):
|
| 56 |
+
warnings.warn(
|
| 57 |
+
"Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and "
|
| 58 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead",
|
| 59 |
+
DeprecationWarning,
|
| 60 |
+
)
|
| 61 |
+
return cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT
|
| 62 |
+
|
| 63 |
+
@DEFAULT_REDIRECT_HEADERS_BLACKLIST.setter
|
| 64 |
+
def DEFAULT_REDIRECT_HEADERS_BLACKLIST(cls, value):
|
| 65 |
+
warnings.warn(
|
| 66 |
+
"Using 'Retry.DEFAULT_REDIRECT_HEADERS_BLACKLIST' is deprecated and "
|
| 67 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_REMOVE_HEADERS_ON_REDIRECT' instead",
|
| 68 |
+
DeprecationWarning,
|
| 69 |
+
)
|
| 70 |
+
cls.DEFAULT_REMOVE_HEADERS_ON_REDIRECT = value
|
| 71 |
+
|
| 72 |
+
@property
|
| 73 |
+
def BACKOFF_MAX(cls):
|
| 74 |
+
warnings.warn(
|
| 75 |
+
"Using 'Retry.BACKOFF_MAX' is deprecated and "
|
| 76 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_BACKOFF_MAX' instead",
|
| 77 |
+
DeprecationWarning,
|
| 78 |
+
)
|
| 79 |
+
return cls.DEFAULT_BACKOFF_MAX
|
| 80 |
+
|
| 81 |
+
@BACKOFF_MAX.setter
|
| 82 |
+
def BACKOFF_MAX(cls, value):
|
| 83 |
+
warnings.warn(
|
| 84 |
+
"Using 'Retry.BACKOFF_MAX' is deprecated and "
|
| 85 |
+
"will be removed in v2.0. Use 'Retry.DEFAULT_BACKOFF_MAX' instead",
|
| 86 |
+
DeprecationWarning,
|
| 87 |
+
)
|
| 88 |
+
cls.DEFAULT_BACKOFF_MAX = value
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
@six.add_metaclass(_RetryMeta)
|
| 92 |
+
class Retry(object):
|
| 93 |
+
"""Retry configuration.
|
| 94 |
+
|
| 95 |
+
Each retry attempt will create a new Retry object with updated values, so
|
| 96 |
+
they can be safely reused.
|
| 97 |
+
|
| 98 |
+
Retries can be defined as a default for a pool::
|
| 99 |
+
|
| 100 |
+
retries = Retry(connect=5, read=2, redirect=5)
|
| 101 |
+
http = PoolManager(retries=retries)
|
| 102 |
+
response = http.request('GET', 'http://example.com/')
|
| 103 |
+
|
| 104 |
+
Or per-request (which overrides the default for the pool)::
|
| 105 |
+
|
| 106 |
+
response = http.request('GET', 'http://example.com/', retries=Retry(10))
|
| 107 |
+
|
| 108 |
+
Retries can be disabled by passing ``False``::
|
| 109 |
+
|
| 110 |
+
response = http.request('GET', 'http://example.com/', retries=False)
|
| 111 |
+
|
| 112 |
+
Errors will be wrapped in :class:`~urllib3.exceptions.MaxRetryError` unless
|
| 113 |
+
retries are disabled, in which case the causing exception will be raised.
|
| 114 |
+
|
| 115 |
+
:param int total:
|
| 116 |
+
Total number of retries to allow. Takes precedence over other counts.
|
| 117 |
+
|
| 118 |
+
Set to ``None`` to remove this constraint and fall back on other
|
| 119 |
+
counts.
|
| 120 |
+
|
| 121 |
+
Set to ``0`` to fail on the first retry.
|
| 122 |
+
|
| 123 |
+
Set to ``False`` to disable and imply ``raise_on_redirect=False``.
|
| 124 |
+
|
| 125 |
+
:param int connect:
|
| 126 |
+
How many connection-related errors to retry on.
|
| 127 |
+
|
| 128 |
+
These are errors raised before the request is sent to the remote server,
|
| 129 |
+
which we assume has not triggered the server to process the request.
|
| 130 |
+
|
| 131 |
+
Set to ``0`` to fail on the first retry of this type.
|
| 132 |
+
|
| 133 |
+
:param int read:
|
| 134 |
+
How many times to retry on read errors.
|
| 135 |
+
|
| 136 |
+
These errors are raised after the request was sent to the server, so the
|
| 137 |
+
request may have side-effects.
|
| 138 |
+
|
| 139 |
+
Set to ``0`` to fail on the first retry of this type.
|
| 140 |
+
|
| 141 |
+
:param int redirect:
|
| 142 |
+
How many redirects to perform. Limit this to avoid infinite redirect
|
| 143 |
+
loops.
|
| 144 |
+
|
| 145 |
+
A redirect is a HTTP response with a status code 301, 302, 303, 307 or
|
| 146 |
+
308.
|
| 147 |
+
|
| 148 |
+
Set to ``0`` to fail on the first retry of this type.
|
| 149 |
+
|
| 150 |
+
Set to ``False`` to disable and imply ``raise_on_redirect=False``.
|
| 151 |
+
|
| 152 |
+
:param int status:
|
| 153 |
+
How many times to retry on bad status codes.
|
| 154 |
+
|
| 155 |
+
These are retries made on responses, where status code matches
|
| 156 |
+
``status_forcelist``.
|
| 157 |
+
|
| 158 |
+
Set to ``0`` to fail on the first retry of this type.
|
| 159 |
+
|
| 160 |
+
:param int other:
|
| 161 |
+
How many times to retry on other errors.
|
| 162 |
+
|
| 163 |
+
Other errors are errors that are not connect, read, redirect or status errors.
|
| 164 |
+
These errors might be raised after the request was sent to the server, so the
|
| 165 |
+
request might have side-effects.
|
| 166 |
+
|
| 167 |
+
Set to ``0`` to fail on the first retry of this type.
|
| 168 |
+
|
| 169 |
+
If ``total`` is not set, it's a good idea to set this to 0 to account
|
| 170 |
+
for unexpected edge cases and avoid infinite retry loops.
|
| 171 |
+
|
| 172 |
+
:param iterable allowed_methods:
|
| 173 |
+
Set of uppercased HTTP method verbs that we should retry on.
|
| 174 |
+
|
| 175 |
+
By default, we only retry on methods which are considered to be
|
| 176 |
+
idempotent (multiple requests with the same parameters end with the
|
| 177 |
+
same state). See :attr:`Retry.DEFAULT_ALLOWED_METHODS`.
|
| 178 |
+
|
| 179 |
+
Set to a ``False`` value to retry on any verb.
|
| 180 |
+
|
| 181 |
+
.. warning::
|
| 182 |
+
|
| 183 |
+
Previously this parameter was named ``method_whitelist``, that
|
| 184 |
+
usage is deprecated in v1.26.0 and will be removed in v2.0.
|
| 185 |
+
|
| 186 |
+
:param iterable status_forcelist:
|
| 187 |
+
A set of integer HTTP status codes that we should force a retry on.
|
| 188 |
+
A retry is initiated if the request method is in ``allowed_methods``
|
| 189 |
+
and the response status code is in ``status_forcelist``.
|
| 190 |
+
|
| 191 |
+
By default, this is disabled with ``None``.
|
| 192 |
+
|
| 193 |
+
:param float backoff_factor:
|
| 194 |
+
A backoff factor to apply between attempts after the second try
|
| 195 |
+
(most errors are resolved immediately by a second try without a
|
| 196 |
+
delay). urllib3 will sleep for::
|
| 197 |
+
|
| 198 |
+
{backoff factor} * (2 ** ({number of total retries} - 1))
|
| 199 |
+
|
| 200 |
+
seconds. If the backoff_factor is 0.1, then :func:`.sleep` will sleep
|
| 201 |
+
for [0.0s, 0.2s, 0.4s, ...] between retries. It will never be longer
|
| 202 |
+
than :attr:`Retry.DEFAULT_BACKOFF_MAX`.
|
| 203 |
+
|
| 204 |
+
By default, backoff is disabled (set to 0).
|
| 205 |
+
|
| 206 |
+
:param bool raise_on_redirect: Whether, if the number of redirects is
|
| 207 |
+
exhausted, to raise a MaxRetryError, or to return a response with a
|
| 208 |
+
response code in the 3xx range.
|
| 209 |
+
|
| 210 |
+
:param bool raise_on_status: Similar meaning to ``raise_on_redirect``:
|
| 211 |
+
whether we should raise an exception, or return a response,
|
| 212 |
+
if status falls in ``status_forcelist`` range and retries have
|
| 213 |
+
been exhausted.
|
| 214 |
+
|
| 215 |
+
:param tuple history: The history of the request encountered during
|
| 216 |
+
each call to :meth:`~Retry.increment`. The list is in the order
|
| 217 |
+
the requests occurred. Each list item is of class :class:`RequestHistory`.
|
| 218 |
+
|
| 219 |
+
:param bool respect_retry_after_header:
|
| 220 |
+
Whether to respect Retry-After header on status codes defined as
|
| 221 |
+
:attr:`Retry.RETRY_AFTER_STATUS_CODES` or not.
|
| 222 |
+
|
| 223 |
+
:param iterable remove_headers_on_redirect:
|
| 224 |
+
Sequence of headers to remove from the request when a response
|
| 225 |
+
indicating a redirect is returned before firing off the redirected
|
| 226 |
+
request.
|
| 227 |
+
"""
|
| 228 |
+
|
| 229 |
+
#: Default methods to be used for ``allowed_methods``
|
| 230 |
+
DEFAULT_ALLOWED_METHODS = frozenset(
|
| 231 |
+
["HEAD", "GET", "PUT", "DELETE", "OPTIONS", "TRACE"]
|
| 232 |
+
)
|
| 233 |
+
|
| 234 |
+
#: Default status codes to be used for ``status_forcelist``
|
| 235 |
+
RETRY_AFTER_STATUS_CODES = frozenset([413, 429, 503])
|
| 236 |
+
|
| 237 |
+
#: Default headers to be used for ``remove_headers_on_redirect``
|
| 238 |
+
DEFAULT_REMOVE_HEADERS_ON_REDIRECT = frozenset(
|
| 239 |
+
["Cookie", "Authorization", "Proxy-Authorization"]
|
| 240 |
+
)
|
| 241 |
+
|
| 242 |
+
#: Maximum backoff time.
|
| 243 |
+
DEFAULT_BACKOFF_MAX = 120
|
| 244 |
+
|
| 245 |
+
def __init__(
|
| 246 |
+
self,
|
| 247 |
+
total=10,
|
| 248 |
+
connect=None,
|
| 249 |
+
read=None,
|
| 250 |
+
redirect=None,
|
| 251 |
+
status=None,
|
| 252 |
+
other=None,
|
| 253 |
+
allowed_methods=_Default,
|
| 254 |
+
status_forcelist=None,
|
| 255 |
+
backoff_factor=0,
|
| 256 |
+
raise_on_redirect=True,
|
| 257 |
+
raise_on_status=True,
|
| 258 |
+
history=None,
|
| 259 |
+
respect_retry_after_header=True,
|
| 260 |
+
remove_headers_on_redirect=_Default,
|
| 261 |
+
# TODO: Deprecated, remove in v2.0
|
| 262 |
+
method_whitelist=_Default,
|
| 263 |
+
):
|
| 264 |
+
|
| 265 |
+
if method_whitelist is not _Default:
|
| 266 |
+
if allowed_methods is not _Default:
|
| 267 |
+
raise ValueError(
|
| 268 |
+
"Using both 'allowed_methods' and "
|
| 269 |
+
"'method_whitelist' together is not allowed. "
|
| 270 |
+
"Instead only use 'allowed_methods'"
|
| 271 |
+
)
|
| 272 |
+
warnings.warn(
|
| 273 |
+
"Using 'method_whitelist' with Retry is deprecated and "
|
| 274 |
+
"will be removed in v2.0. Use 'allowed_methods' instead",
|
| 275 |
+
DeprecationWarning,
|
| 276 |
+
stacklevel=2,
|
| 277 |
+
)
|
| 278 |
+
allowed_methods = method_whitelist
|
| 279 |
+
if allowed_methods is _Default:
|
| 280 |
+
allowed_methods = self.DEFAULT_ALLOWED_METHODS
|
| 281 |
+
if remove_headers_on_redirect is _Default:
|
| 282 |
+
remove_headers_on_redirect = self.DEFAULT_REMOVE_HEADERS_ON_REDIRECT
|
| 283 |
+
|
| 284 |
+
self.total = total
|
| 285 |
+
self.connect = connect
|
| 286 |
+
self.read = read
|
| 287 |
+
self.status = status
|
| 288 |
+
self.other = other
|
| 289 |
+
|
| 290 |
+
if redirect is False or total is False:
|
| 291 |
+
redirect = 0
|
| 292 |
+
raise_on_redirect = False
|
| 293 |
+
|
| 294 |
+
self.redirect = redirect
|
| 295 |
+
self.status_forcelist = status_forcelist or set()
|
| 296 |
+
self.allowed_methods = allowed_methods
|
| 297 |
+
self.backoff_factor = backoff_factor
|
| 298 |
+
self.raise_on_redirect = raise_on_redirect
|
| 299 |
+
self.raise_on_status = raise_on_status
|
| 300 |
+
self.history = history or tuple()
|
| 301 |
+
self.respect_retry_after_header = respect_retry_after_header
|
| 302 |
+
self.remove_headers_on_redirect = frozenset(
|
| 303 |
+
[h.lower() for h in remove_headers_on_redirect]
|
| 304 |
+
)
|
| 305 |
+
|
| 306 |
+
def new(self, **kw):
|
| 307 |
+
params = dict(
|
| 308 |
+
total=self.total,
|
| 309 |
+
connect=self.connect,
|
| 310 |
+
read=self.read,
|
| 311 |
+
redirect=self.redirect,
|
| 312 |
+
status=self.status,
|
| 313 |
+
other=self.other,
|
| 314 |
+
status_forcelist=self.status_forcelist,
|
| 315 |
+
backoff_factor=self.backoff_factor,
|
| 316 |
+
raise_on_redirect=self.raise_on_redirect,
|
| 317 |
+
raise_on_status=self.raise_on_status,
|
| 318 |
+
history=self.history,
|
| 319 |
+
remove_headers_on_redirect=self.remove_headers_on_redirect,
|
| 320 |
+
respect_retry_after_header=self.respect_retry_after_header,
|
| 321 |
+
)
|
| 322 |
+
|
| 323 |
+
# TODO: If already given in **kw we use what's given to us
|
| 324 |
+
# If not given we need to figure out what to pass. We decide
|
| 325 |
+
# based on whether our class has the 'method_whitelist' property
|
| 326 |
+
# and if so we pass the deprecated 'method_whitelist' otherwise
|
| 327 |
+
# we use 'allowed_methods'. Remove in v2.0
|
| 328 |
+
if "method_whitelist" not in kw and "allowed_methods" not in kw:
|
| 329 |
+
if "method_whitelist" in self.__dict__:
|
| 330 |
+
warnings.warn(
|
| 331 |
+
"Using 'method_whitelist' with Retry is deprecated and "
|
| 332 |
+
"will be removed in v2.0. Use 'allowed_methods' instead",
|
| 333 |
+
DeprecationWarning,
|
| 334 |
+
)
|
| 335 |
+
params["method_whitelist"] = self.allowed_methods
|
| 336 |
+
else:
|
| 337 |
+
params["allowed_methods"] = self.allowed_methods
|
| 338 |
+
|
| 339 |
+
params.update(kw)
|
| 340 |
+
return type(self)(**params)
|
| 341 |
+
|
| 342 |
+
@classmethod
|
| 343 |
+
def from_int(cls, retries, redirect=True, default=None):
|
| 344 |
+
"""Backwards-compatibility for the old retries format."""
|
| 345 |
+
if retries is None:
|
| 346 |
+
retries = default if default is not None else cls.DEFAULT
|
| 347 |
+
|
| 348 |
+
if isinstance(retries, Retry):
|
| 349 |
+
return retries
|
| 350 |
+
|
| 351 |
+
redirect = bool(redirect) and None
|
| 352 |
+
new_retries = cls(retries, redirect=redirect)
|
| 353 |
+
log.debug("Converted retries value: %r -> %r", retries, new_retries)
|
| 354 |
+
return new_retries
|
| 355 |
+
|
| 356 |
+
def get_backoff_time(self):
|
| 357 |
+
"""Formula for computing the current backoff
|
| 358 |
+
|
| 359 |
+
:rtype: float
|
| 360 |
+
"""
|
| 361 |
+
# We want to consider only the last consecutive errors sequence (Ignore redirects).
|
| 362 |
+
consecutive_errors_len = len(
|
| 363 |
+
list(
|
| 364 |
+
takewhile(lambda x: x.redirect_location is None, reversed(self.history))
|
| 365 |
+
)
|
| 366 |
+
)
|
| 367 |
+
if consecutive_errors_len <= 1:
|
| 368 |
+
return 0
|
| 369 |
+
|
| 370 |
+
backoff_value = self.backoff_factor * (2 ** (consecutive_errors_len - 1))
|
| 371 |
+
return min(self.DEFAULT_BACKOFF_MAX, backoff_value)
|
| 372 |
+
|
| 373 |
+
def parse_retry_after(self, retry_after):
|
| 374 |
+
# Whitespace: https://tools.ietf.org/html/rfc7230#section-3.2.4
|
| 375 |
+
if re.match(r"^\s*[0-9]+\s*$", retry_after):
|
| 376 |
+
seconds = int(retry_after)
|
| 377 |
+
else:
|
| 378 |
+
retry_date_tuple = email.utils.parsedate_tz(retry_after)
|
| 379 |
+
if retry_date_tuple is None:
|
| 380 |
+
raise InvalidHeader("Invalid Retry-After header: %s" % retry_after)
|
| 381 |
+
if retry_date_tuple[9] is None: # Python 2
|
| 382 |
+
# Assume UTC if no timezone was specified
|
| 383 |
+
# On Python2.7, parsedate_tz returns None for a timezone offset
|
| 384 |
+
# instead of 0 if no timezone is given, where mktime_tz treats
|
| 385 |
+
# a None timezone offset as local time.
|
| 386 |
+
retry_date_tuple = retry_date_tuple[:9] + (0,) + retry_date_tuple[10:]
|
| 387 |
+
|
| 388 |
+
retry_date = email.utils.mktime_tz(retry_date_tuple)
|
| 389 |
+
seconds = retry_date - time.time()
|
| 390 |
+
|
| 391 |
+
if seconds < 0:
|
| 392 |
+
seconds = 0
|
| 393 |
+
|
| 394 |
+
return seconds
|
| 395 |
+
|
| 396 |
+
def get_retry_after(self, response):
|
| 397 |
+
"""Get the value of Retry-After in seconds."""
|
| 398 |
+
|
| 399 |
+
retry_after = response.headers.get("Retry-After")
|
| 400 |
+
|
| 401 |
+
if retry_after is None:
|
| 402 |
+
return None
|
| 403 |
+
|
| 404 |
+
return self.parse_retry_after(retry_after)
|
| 405 |
+
|
| 406 |
+
def sleep_for_retry(self, response=None):
|
| 407 |
+
retry_after = self.get_retry_after(response)
|
| 408 |
+
if retry_after:
|
| 409 |
+
time.sleep(retry_after)
|
| 410 |
+
return True
|
| 411 |
+
|
| 412 |
+
return False
|
| 413 |
+
|
| 414 |
+
def _sleep_backoff(self):
|
| 415 |
+
backoff = self.get_backoff_time()
|
| 416 |
+
if backoff <= 0:
|
| 417 |
+
return
|
| 418 |
+
time.sleep(backoff)
|
| 419 |
+
|
| 420 |
+
def sleep(self, response=None):
|
| 421 |
+
"""Sleep between retry attempts.
|
| 422 |
+
|
| 423 |
+
This method will respect a server's ``Retry-After`` response header
|
| 424 |
+
and sleep the duration of the time requested. If that is not present, it
|
| 425 |
+
will use an exponential backoff. By default, the backoff factor is 0 and
|
| 426 |
+
this method will return immediately.
|
| 427 |
+
"""
|
| 428 |
+
|
| 429 |
+
if self.respect_retry_after_header and response:
|
| 430 |
+
slept = self.sleep_for_retry(response)
|
| 431 |
+
if slept:
|
| 432 |
+
return
|
| 433 |
+
|
| 434 |
+
self._sleep_backoff()
|
| 435 |
+
|
| 436 |
+
def _is_connection_error(self, err):
|
| 437 |
+
"""Errors when we're fairly sure that the server did not receive the
|
| 438 |
+
request, so it should be safe to retry.
|
| 439 |
+
"""
|
| 440 |
+
if isinstance(err, ProxyError):
|
| 441 |
+
err = err.original_error
|
| 442 |
+
return isinstance(err, ConnectTimeoutError)
|
| 443 |
+
|
| 444 |
+
def _is_read_error(self, err):
|
| 445 |
+
"""Errors that occur after the request has been started, so we should
|
| 446 |
+
assume that the server began processing it.
|
| 447 |
+
"""
|
| 448 |
+
return isinstance(err, (ReadTimeoutError, ProtocolError))
|
| 449 |
+
|
| 450 |
+
def _is_method_retryable(self, method):
|
| 451 |
+
"""Checks if a given HTTP method should be retried upon, depending if
|
| 452 |
+
it is included in the allowed_methods
|
| 453 |
+
"""
|
| 454 |
+
# TODO: For now favor if the Retry implementation sets its own method_whitelist
|
| 455 |
+
# property outside of our constructor to avoid breaking custom implementations.
|
| 456 |
+
if "method_whitelist" in self.__dict__:
|
| 457 |
+
warnings.warn(
|
| 458 |
+
"Using 'method_whitelist' with Retry is deprecated and "
|
| 459 |
+
"will be removed in v2.0. Use 'allowed_methods' instead",
|
| 460 |
+
DeprecationWarning,
|
| 461 |
+
)
|
| 462 |
+
allowed_methods = self.method_whitelist
|
| 463 |
+
else:
|
| 464 |
+
allowed_methods = self.allowed_methods
|
| 465 |
+
|
| 466 |
+
if allowed_methods and method.upper() not in allowed_methods:
|
| 467 |
+
return False
|
| 468 |
+
return True
|
| 469 |
+
|
| 470 |
+
def is_retry(self, method, status_code, has_retry_after=False):
|
| 471 |
+
"""Is this method/status code retryable? (Based on allowlists and control
|
| 472 |
+
variables such as the number of total retries to allow, whether to
|
| 473 |
+
respect the Retry-After header, whether this header is present, and
|
| 474 |
+
whether the returned status code is on the list of status codes to
|
| 475 |
+
be retried upon on the presence of the aforementioned header)
|
| 476 |
+
"""
|
| 477 |
+
if not self._is_method_retryable(method):
|
| 478 |
+
return False
|
| 479 |
+
|
| 480 |
+
if self.status_forcelist and status_code in self.status_forcelist:
|
| 481 |
+
return True
|
| 482 |
+
|
| 483 |
+
return (
|
| 484 |
+
self.total
|
| 485 |
+
and self.respect_retry_after_header
|
| 486 |
+
and has_retry_after
|
| 487 |
+
and (status_code in self.RETRY_AFTER_STATUS_CODES)
|
| 488 |
+
)
|
| 489 |
+
|
| 490 |
+
def is_exhausted(self):
|
| 491 |
+
"""Are we out of retries?"""
|
| 492 |
+
retry_counts = (
|
| 493 |
+
self.total,
|
| 494 |
+
self.connect,
|
| 495 |
+
self.read,
|
| 496 |
+
self.redirect,
|
| 497 |
+
self.status,
|
| 498 |
+
self.other,
|
| 499 |
+
)
|
| 500 |
+
retry_counts = list(filter(None, retry_counts))
|
| 501 |
+
if not retry_counts:
|
| 502 |
+
return False
|
| 503 |
+
|
| 504 |
+
return min(retry_counts) < 0
|
| 505 |
+
|
| 506 |
+
def increment(
|
| 507 |
+
self,
|
| 508 |
+
method=None,
|
| 509 |
+
url=None,
|
| 510 |
+
response=None,
|
| 511 |
+
error=None,
|
| 512 |
+
_pool=None,
|
| 513 |
+
_stacktrace=None,
|
| 514 |
+
):
|
| 515 |
+
"""Return a new Retry object with incremented retry counters.
|
| 516 |
+
|
| 517 |
+
:param response: A response object, or None, if the server did not
|
| 518 |
+
return a response.
|
| 519 |
+
:type response: :class:`~urllib3.response.HTTPResponse`
|
| 520 |
+
:param Exception error: An error encountered during the request, or
|
| 521 |
+
None if the response was received successfully.
|
| 522 |
+
|
| 523 |
+
:return: A new ``Retry`` object.
|
| 524 |
+
"""
|
| 525 |
+
if self.total is False and error:
|
| 526 |
+
# Disabled, indicate to re-raise the error.
|
| 527 |
+
raise six.reraise(type(error), error, _stacktrace)
|
| 528 |
+
|
| 529 |
+
total = self.total
|
| 530 |
+
if total is not None:
|
| 531 |
+
total -= 1
|
| 532 |
+
|
| 533 |
+
connect = self.connect
|
| 534 |
+
read = self.read
|
| 535 |
+
redirect = self.redirect
|
| 536 |
+
status_count = self.status
|
| 537 |
+
other = self.other
|
| 538 |
+
cause = "unknown"
|
| 539 |
+
status = None
|
| 540 |
+
redirect_location = None
|
| 541 |
+
|
| 542 |
+
if error and self._is_connection_error(error):
|
| 543 |
+
# Connect retry?
|
| 544 |
+
if connect is False:
|
| 545 |
+
raise six.reraise(type(error), error, _stacktrace)
|
| 546 |
+
elif connect is not None:
|
| 547 |
+
connect -= 1
|
| 548 |
+
|
| 549 |
+
elif error and self._is_read_error(error):
|
| 550 |
+
# Read retry?
|
| 551 |
+
if read is False or not self._is_method_retryable(method):
|
| 552 |
+
raise six.reraise(type(error), error, _stacktrace)
|
| 553 |
+
elif read is not None:
|
| 554 |
+
read -= 1
|
| 555 |
+
|
| 556 |
+
elif error:
|
| 557 |
+
# Other retry?
|
| 558 |
+
if other is not None:
|
| 559 |
+
other -= 1
|
| 560 |
+
|
| 561 |
+
elif response and response.get_redirect_location():
|
| 562 |
+
# Redirect retry?
|
| 563 |
+
if redirect is not None:
|
| 564 |
+
redirect -= 1
|
| 565 |
+
cause = "too many redirects"
|
| 566 |
+
redirect_location = response.get_redirect_location()
|
| 567 |
+
status = response.status
|
| 568 |
+
|
| 569 |
+
else:
|
| 570 |
+
# Incrementing because of a server error like a 500 in
|
| 571 |
+
# status_forcelist and the given method is in the allowed_methods
|
| 572 |
+
cause = ResponseError.GENERIC_ERROR
|
| 573 |
+
if response and response.status:
|
| 574 |
+
if status_count is not None:
|
| 575 |
+
status_count -= 1
|
| 576 |
+
cause = ResponseError.SPECIFIC_ERROR.format(status_code=response.status)
|
| 577 |
+
status = response.status
|
| 578 |
+
|
| 579 |
+
history = self.history + (
|
| 580 |
+
RequestHistory(method, url, error, status, redirect_location),
|
| 581 |
+
)
|
| 582 |
+
|
| 583 |
+
new_retry = self.new(
|
| 584 |
+
total=total,
|
| 585 |
+
connect=connect,
|
| 586 |
+
read=read,
|
| 587 |
+
redirect=redirect,
|
| 588 |
+
status=status_count,
|
| 589 |
+
other=other,
|
| 590 |
+
history=history,
|
| 591 |
+
)
|
| 592 |
+
|
| 593 |
+
if new_retry.is_exhausted():
|
| 594 |
+
raise MaxRetryError(_pool, url, error or ResponseError(cause))
|
| 595 |
+
|
| 596 |
+
log.debug("Incremented Retry for (url='%s'): %r", url, new_retry)
|
| 597 |
+
|
| 598 |
+
return new_retry
|
| 599 |
+
|
| 600 |
+
def __repr__(self):
|
| 601 |
+
return (
|
| 602 |
+
"{cls.__name__}(total={self.total}, connect={self.connect}, "
|
| 603 |
+
"read={self.read}, redirect={self.redirect}, status={self.status})"
|
| 604 |
+
).format(cls=type(self), self=self)
|
| 605 |
+
|
| 606 |
+
def __getattr__(self, item):
|
| 607 |
+
if item == "method_whitelist":
|
| 608 |
+
# TODO: Remove this deprecated alias in v2.0
|
| 609 |
+
warnings.warn(
|
| 610 |
+
"Using 'method_whitelist' with Retry is deprecated and "
|
| 611 |
+
"will be removed in v2.0. Use 'allowed_methods' instead",
|
| 612 |
+
DeprecationWarning,
|
| 613 |
+
)
|
| 614 |
+
return self.allowed_methods
|
| 615 |
+
try:
|
| 616 |
+
return getattr(super(Retry, self), item)
|
| 617 |
+
except AttributeError:
|
| 618 |
+
return getattr(Retry, item)
|
| 619 |
+
|
| 620 |
+
|
| 621 |
+
# For backwards compatibility (equivalent to pre-v1.9):
|
| 622 |
+
Retry.DEFAULT = Retry(3)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_.py
ADDED
|
@@ -0,0 +1,495 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import hmac
|
| 4 |
+
import os
|
| 5 |
+
import sys
|
| 6 |
+
import warnings
|
| 7 |
+
from binascii import hexlify, unhexlify
|
| 8 |
+
from hashlib import md5, sha1, sha256
|
| 9 |
+
|
| 10 |
+
from ..exceptions import (
|
| 11 |
+
InsecurePlatformWarning,
|
| 12 |
+
ProxySchemeUnsupported,
|
| 13 |
+
SNIMissingWarning,
|
| 14 |
+
SSLError,
|
| 15 |
+
)
|
| 16 |
+
from ..packages import six
|
| 17 |
+
from .url import BRACELESS_IPV6_ADDRZ_RE, IPV4_RE
|
| 18 |
+
|
| 19 |
+
SSLContext = None
|
| 20 |
+
SSLTransport = None
|
| 21 |
+
HAS_SNI = False
|
| 22 |
+
IS_PYOPENSSL = False
|
| 23 |
+
IS_SECURETRANSPORT = False
|
| 24 |
+
ALPN_PROTOCOLS = ["http/1.1"]
|
| 25 |
+
|
| 26 |
+
# Maps the length of a digest to a possible hash function producing this digest
|
| 27 |
+
HASHFUNC_MAP = {32: md5, 40: sha1, 64: sha256}
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
def _const_compare_digest_backport(a, b):
|
| 31 |
+
"""
|
| 32 |
+
Compare two digests of equal length in constant time.
|
| 33 |
+
|
| 34 |
+
The digests must be of type str/bytes.
|
| 35 |
+
Returns True if the digests match, and False otherwise.
|
| 36 |
+
"""
|
| 37 |
+
result = abs(len(a) - len(b))
|
| 38 |
+
for left, right in zip(bytearray(a), bytearray(b)):
|
| 39 |
+
result |= left ^ right
|
| 40 |
+
return result == 0
|
| 41 |
+
|
| 42 |
+
|
| 43 |
+
_const_compare_digest = getattr(hmac, "compare_digest", _const_compare_digest_backport)
|
| 44 |
+
|
| 45 |
+
try: # Test for SSL features
|
| 46 |
+
import ssl
|
| 47 |
+
from ssl import CERT_REQUIRED, wrap_socket
|
| 48 |
+
except ImportError:
|
| 49 |
+
pass
|
| 50 |
+
|
| 51 |
+
try:
|
| 52 |
+
from ssl import HAS_SNI # Has SNI?
|
| 53 |
+
except ImportError:
|
| 54 |
+
pass
|
| 55 |
+
|
| 56 |
+
try:
|
| 57 |
+
from .ssltransport import SSLTransport
|
| 58 |
+
except ImportError:
|
| 59 |
+
pass
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
try: # Platform-specific: Python 3.6
|
| 63 |
+
from ssl import PROTOCOL_TLS
|
| 64 |
+
|
| 65 |
+
PROTOCOL_SSLv23 = PROTOCOL_TLS
|
| 66 |
+
except ImportError:
|
| 67 |
+
try:
|
| 68 |
+
from ssl import PROTOCOL_SSLv23 as PROTOCOL_TLS
|
| 69 |
+
|
| 70 |
+
PROTOCOL_SSLv23 = PROTOCOL_TLS
|
| 71 |
+
except ImportError:
|
| 72 |
+
PROTOCOL_SSLv23 = PROTOCOL_TLS = 2
|
| 73 |
+
|
| 74 |
+
try:
|
| 75 |
+
from ssl import PROTOCOL_TLS_CLIENT
|
| 76 |
+
except ImportError:
|
| 77 |
+
PROTOCOL_TLS_CLIENT = PROTOCOL_TLS
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
try:
|
| 81 |
+
from ssl import OP_NO_COMPRESSION, OP_NO_SSLv2, OP_NO_SSLv3
|
| 82 |
+
except ImportError:
|
| 83 |
+
OP_NO_SSLv2, OP_NO_SSLv3 = 0x1000000, 0x2000000
|
| 84 |
+
OP_NO_COMPRESSION = 0x20000
|
| 85 |
+
|
| 86 |
+
|
| 87 |
+
try: # OP_NO_TICKET was added in Python 3.6
|
| 88 |
+
from ssl import OP_NO_TICKET
|
| 89 |
+
except ImportError:
|
| 90 |
+
OP_NO_TICKET = 0x4000
|
| 91 |
+
|
| 92 |
+
|
| 93 |
+
# A secure default.
|
| 94 |
+
# Sources for more information on TLS ciphers:
|
| 95 |
+
#
|
| 96 |
+
# - https://wiki.mozilla.org/Security/Server_Side_TLS
|
| 97 |
+
# - https://www.ssllabs.com/projects/best-practices/index.html
|
| 98 |
+
# - https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
|
| 99 |
+
#
|
| 100 |
+
# The general intent is:
|
| 101 |
+
# - prefer cipher suites that offer perfect forward secrecy (DHE/ECDHE),
|
| 102 |
+
# - prefer ECDHE over DHE for better performance,
|
| 103 |
+
# - prefer any AES-GCM and ChaCha20 over any AES-CBC for better performance and
|
| 104 |
+
# security,
|
| 105 |
+
# - prefer AES-GCM over ChaCha20 because hardware-accelerated AES is common,
|
| 106 |
+
# - disable NULL authentication, MD5 MACs, DSS, and other
|
| 107 |
+
# insecure ciphers for security reasons.
|
| 108 |
+
# - NOTE: TLS 1.3 cipher suites are managed through a different interface
|
| 109 |
+
# not exposed by CPython (yet!) and are enabled by default if they're available.
|
| 110 |
+
DEFAULT_CIPHERS = ":".join(
|
| 111 |
+
[
|
| 112 |
+
"ECDHE+AESGCM",
|
| 113 |
+
"ECDHE+CHACHA20",
|
| 114 |
+
"DHE+AESGCM",
|
| 115 |
+
"DHE+CHACHA20",
|
| 116 |
+
"ECDH+AESGCM",
|
| 117 |
+
"DH+AESGCM",
|
| 118 |
+
"ECDH+AES",
|
| 119 |
+
"DH+AES",
|
| 120 |
+
"RSA+AESGCM",
|
| 121 |
+
"RSA+AES",
|
| 122 |
+
"!aNULL",
|
| 123 |
+
"!eNULL",
|
| 124 |
+
"!MD5",
|
| 125 |
+
"!DSS",
|
| 126 |
+
]
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
try:
|
| 130 |
+
from ssl import SSLContext # Modern SSL?
|
| 131 |
+
except ImportError:
|
| 132 |
+
|
| 133 |
+
class SSLContext(object): # Platform-specific: Python 2
|
| 134 |
+
def __init__(self, protocol_version):
|
| 135 |
+
self.protocol = protocol_version
|
| 136 |
+
# Use default values from a real SSLContext
|
| 137 |
+
self.check_hostname = False
|
| 138 |
+
self.verify_mode = ssl.CERT_NONE
|
| 139 |
+
self.ca_certs = None
|
| 140 |
+
self.options = 0
|
| 141 |
+
self.certfile = None
|
| 142 |
+
self.keyfile = None
|
| 143 |
+
self.ciphers = None
|
| 144 |
+
|
| 145 |
+
def load_cert_chain(self, certfile, keyfile):
|
| 146 |
+
self.certfile = certfile
|
| 147 |
+
self.keyfile = keyfile
|
| 148 |
+
|
| 149 |
+
def load_verify_locations(self, cafile=None, capath=None, cadata=None):
|
| 150 |
+
self.ca_certs = cafile
|
| 151 |
+
|
| 152 |
+
if capath is not None:
|
| 153 |
+
raise SSLError("CA directories not supported in older Pythons")
|
| 154 |
+
|
| 155 |
+
if cadata is not None:
|
| 156 |
+
raise SSLError("CA data not supported in older Pythons")
|
| 157 |
+
|
| 158 |
+
def set_ciphers(self, cipher_suite):
|
| 159 |
+
self.ciphers = cipher_suite
|
| 160 |
+
|
| 161 |
+
def wrap_socket(self, socket, server_hostname=None, server_side=False):
|
| 162 |
+
warnings.warn(
|
| 163 |
+
"A true SSLContext object is not available. This prevents "
|
| 164 |
+
"urllib3 from configuring SSL appropriately and may cause "
|
| 165 |
+
"certain SSL connections to fail. You can upgrade to a newer "
|
| 166 |
+
"version of Python to solve this. For more information, see "
|
| 167 |
+
"https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html"
|
| 168 |
+
"#ssl-warnings",
|
| 169 |
+
InsecurePlatformWarning,
|
| 170 |
+
)
|
| 171 |
+
kwargs = {
|
| 172 |
+
"keyfile": self.keyfile,
|
| 173 |
+
"certfile": self.certfile,
|
| 174 |
+
"ca_certs": self.ca_certs,
|
| 175 |
+
"cert_reqs": self.verify_mode,
|
| 176 |
+
"ssl_version": self.protocol,
|
| 177 |
+
"server_side": server_side,
|
| 178 |
+
}
|
| 179 |
+
return wrap_socket(socket, ciphers=self.ciphers, **kwargs)
|
| 180 |
+
|
| 181 |
+
|
| 182 |
+
def assert_fingerprint(cert, fingerprint):
|
| 183 |
+
"""
|
| 184 |
+
Checks if given fingerprint matches the supplied certificate.
|
| 185 |
+
|
| 186 |
+
:param cert:
|
| 187 |
+
Certificate as bytes object.
|
| 188 |
+
:param fingerprint:
|
| 189 |
+
Fingerprint as string of hexdigits, can be interspersed by colons.
|
| 190 |
+
"""
|
| 191 |
+
|
| 192 |
+
fingerprint = fingerprint.replace(":", "").lower()
|
| 193 |
+
digest_length = len(fingerprint)
|
| 194 |
+
hashfunc = HASHFUNC_MAP.get(digest_length)
|
| 195 |
+
if not hashfunc:
|
| 196 |
+
raise SSLError("Fingerprint of invalid length: {0}".format(fingerprint))
|
| 197 |
+
|
| 198 |
+
# We need encode() here for py32; works on py2 and p33.
|
| 199 |
+
fingerprint_bytes = unhexlify(fingerprint.encode())
|
| 200 |
+
|
| 201 |
+
cert_digest = hashfunc(cert).digest()
|
| 202 |
+
|
| 203 |
+
if not _const_compare_digest(cert_digest, fingerprint_bytes):
|
| 204 |
+
raise SSLError(
|
| 205 |
+
'Fingerprints did not match. Expected "{0}", got "{1}".'.format(
|
| 206 |
+
fingerprint, hexlify(cert_digest)
|
| 207 |
+
)
|
| 208 |
+
)
|
| 209 |
+
|
| 210 |
+
|
| 211 |
+
def resolve_cert_reqs(candidate):
|
| 212 |
+
"""
|
| 213 |
+
Resolves the argument to a numeric constant, which can be passed to
|
| 214 |
+
the wrap_socket function/method from the ssl module.
|
| 215 |
+
Defaults to :data:`ssl.CERT_REQUIRED`.
|
| 216 |
+
If given a string it is assumed to be the name of the constant in the
|
| 217 |
+
:mod:`ssl` module or its abbreviation.
|
| 218 |
+
(So you can specify `REQUIRED` instead of `CERT_REQUIRED`.
|
| 219 |
+
If it's neither `None` nor a string we assume it is already the numeric
|
| 220 |
+
constant which can directly be passed to wrap_socket.
|
| 221 |
+
"""
|
| 222 |
+
if candidate is None:
|
| 223 |
+
return CERT_REQUIRED
|
| 224 |
+
|
| 225 |
+
if isinstance(candidate, str):
|
| 226 |
+
res = getattr(ssl, candidate, None)
|
| 227 |
+
if res is None:
|
| 228 |
+
res = getattr(ssl, "CERT_" + candidate)
|
| 229 |
+
return res
|
| 230 |
+
|
| 231 |
+
return candidate
|
| 232 |
+
|
| 233 |
+
|
| 234 |
+
def resolve_ssl_version(candidate):
|
| 235 |
+
"""
|
| 236 |
+
like resolve_cert_reqs
|
| 237 |
+
"""
|
| 238 |
+
if candidate is None:
|
| 239 |
+
return PROTOCOL_TLS
|
| 240 |
+
|
| 241 |
+
if isinstance(candidate, str):
|
| 242 |
+
res = getattr(ssl, candidate, None)
|
| 243 |
+
if res is None:
|
| 244 |
+
res = getattr(ssl, "PROTOCOL_" + candidate)
|
| 245 |
+
return res
|
| 246 |
+
|
| 247 |
+
return candidate
|
| 248 |
+
|
| 249 |
+
|
| 250 |
+
def create_urllib3_context(
|
| 251 |
+
ssl_version=None, cert_reqs=None, options=None, ciphers=None
|
| 252 |
+
):
|
| 253 |
+
"""All arguments have the same meaning as ``ssl_wrap_socket``.
|
| 254 |
+
|
| 255 |
+
By default, this function does a lot of the same work that
|
| 256 |
+
``ssl.create_default_context`` does on Python 3.4+. It:
|
| 257 |
+
|
| 258 |
+
- Disables SSLv2, SSLv3, and compression
|
| 259 |
+
- Sets a restricted set of server ciphers
|
| 260 |
+
|
| 261 |
+
If you wish to enable SSLv3, you can do::
|
| 262 |
+
|
| 263 |
+
from pip._vendor.urllib3.util import ssl_
|
| 264 |
+
context = ssl_.create_urllib3_context()
|
| 265 |
+
context.options &= ~ssl_.OP_NO_SSLv3
|
| 266 |
+
|
| 267 |
+
You can do the same to enable compression (substituting ``COMPRESSION``
|
| 268 |
+
for ``SSLv3`` in the last line above).
|
| 269 |
+
|
| 270 |
+
:param ssl_version:
|
| 271 |
+
The desired protocol version to use. This will default to
|
| 272 |
+
PROTOCOL_SSLv23 which will negotiate the highest protocol that both
|
| 273 |
+
the server and your installation of OpenSSL support.
|
| 274 |
+
:param cert_reqs:
|
| 275 |
+
Whether to require the certificate verification. This defaults to
|
| 276 |
+
``ssl.CERT_REQUIRED``.
|
| 277 |
+
:param options:
|
| 278 |
+
Specific OpenSSL options. These default to ``ssl.OP_NO_SSLv2``,
|
| 279 |
+
``ssl.OP_NO_SSLv3``, ``ssl.OP_NO_COMPRESSION``, and ``ssl.OP_NO_TICKET``.
|
| 280 |
+
:param ciphers:
|
| 281 |
+
Which cipher suites to allow the server to select.
|
| 282 |
+
:returns:
|
| 283 |
+
Constructed SSLContext object with specified options
|
| 284 |
+
:rtype: SSLContext
|
| 285 |
+
"""
|
| 286 |
+
# PROTOCOL_TLS is deprecated in Python 3.10
|
| 287 |
+
if not ssl_version or ssl_version == PROTOCOL_TLS:
|
| 288 |
+
ssl_version = PROTOCOL_TLS_CLIENT
|
| 289 |
+
|
| 290 |
+
context = SSLContext(ssl_version)
|
| 291 |
+
|
| 292 |
+
context.set_ciphers(ciphers or DEFAULT_CIPHERS)
|
| 293 |
+
|
| 294 |
+
# Setting the default here, as we may have no ssl module on import
|
| 295 |
+
cert_reqs = ssl.CERT_REQUIRED if cert_reqs is None else cert_reqs
|
| 296 |
+
|
| 297 |
+
if options is None:
|
| 298 |
+
options = 0
|
| 299 |
+
# SSLv2 is easily broken and is considered harmful and dangerous
|
| 300 |
+
options |= OP_NO_SSLv2
|
| 301 |
+
# SSLv3 has several problems and is now dangerous
|
| 302 |
+
options |= OP_NO_SSLv3
|
| 303 |
+
# Disable compression to prevent CRIME attacks for OpenSSL 1.0+
|
| 304 |
+
# (issue #309)
|
| 305 |
+
options |= OP_NO_COMPRESSION
|
| 306 |
+
# TLSv1.2 only. Unless set explicitly, do not request tickets.
|
| 307 |
+
# This may save some bandwidth on wire, and although the ticket is encrypted,
|
| 308 |
+
# there is a risk associated with it being on wire,
|
| 309 |
+
# if the server is not rotating its ticketing keys properly.
|
| 310 |
+
options |= OP_NO_TICKET
|
| 311 |
+
|
| 312 |
+
context.options |= options
|
| 313 |
+
|
| 314 |
+
# Enable post-handshake authentication for TLS 1.3, see GH #1634. PHA is
|
| 315 |
+
# necessary for conditional client cert authentication with TLS 1.3.
|
| 316 |
+
# The attribute is None for OpenSSL <= 1.1.0 or does not exist in older
|
| 317 |
+
# versions of Python. We only enable on Python 3.7.4+ or if certificate
|
| 318 |
+
# verification is enabled to work around Python issue #37428
|
| 319 |
+
# See: https://bugs.python.org/issue37428
|
| 320 |
+
if (cert_reqs == ssl.CERT_REQUIRED or sys.version_info >= (3, 7, 4)) and getattr(
|
| 321 |
+
context, "post_handshake_auth", None
|
| 322 |
+
) is not None:
|
| 323 |
+
context.post_handshake_auth = True
|
| 324 |
+
|
| 325 |
+
def disable_check_hostname():
|
| 326 |
+
if (
|
| 327 |
+
getattr(context, "check_hostname", None) is not None
|
| 328 |
+
): # Platform-specific: Python 3.2
|
| 329 |
+
# We do our own verification, including fingerprints and alternative
|
| 330 |
+
# hostnames. So disable it here
|
| 331 |
+
context.check_hostname = False
|
| 332 |
+
|
| 333 |
+
# The order of the below lines setting verify_mode and check_hostname
|
| 334 |
+
# matter due to safe-guards SSLContext has to prevent an SSLContext with
|
| 335 |
+
# check_hostname=True, verify_mode=NONE/OPTIONAL. This is made even more
|
| 336 |
+
# complex because we don't know whether PROTOCOL_TLS_CLIENT will be used
|
| 337 |
+
# or not so we don't know the initial state of the freshly created SSLContext.
|
| 338 |
+
if cert_reqs == ssl.CERT_REQUIRED:
|
| 339 |
+
context.verify_mode = cert_reqs
|
| 340 |
+
disable_check_hostname()
|
| 341 |
+
else:
|
| 342 |
+
disable_check_hostname()
|
| 343 |
+
context.verify_mode = cert_reqs
|
| 344 |
+
|
| 345 |
+
# Enable logging of TLS session keys via defacto standard environment variable
|
| 346 |
+
# 'SSLKEYLOGFILE', if the feature is available (Python 3.8+). Skip empty values.
|
| 347 |
+
if hasattr(context, "keylog_filename"):
|
| 348 |
+
sslkeylogfile = os.environ.get("SSLKEYLOGFILE")
|
| 349 |
+
if sslkeylogfile:
|
| 350 |
+
context.keylog_filename = sslkeylogfile
|
| 351 |
+
|
| 352 |
+
return context
|
| 353 |
+
|
| 354 |
+
|
| 355 |
+
def ssl_wrap_socket(
|
| 356 |
+
sock,
|
| 357 |
+
keyfile=None,
|
| 358 |
+
certfile=None,
|
| 359 |
+
cert_reqs=None,
|
| 360 |
+
ca_certs=None,
|
| 361 |
+
server_hostname=None,
|
| 362 |
+
ssl_version=None,
|
| 363 |
+
ciphers=None,
|
| 364 |
+
ssl_context=None,
|
| 365 |
+
ca_cert_dir=None,
|
| 366 |
+
key_password=None,
|
| 367 |
+
ca_cert_data=None,
|
| 368 |
+
tls_in_tls=False,
|
| 369 |
+
):
|
| 370 |
+
"""
|
| 371 |
+
All arguments except for server_hostname, ssl_context, and ca_cert_dir have
|
| 372 |
+
the same meaning as they do when using :func:`ssl.wrap_socket`.
|
| 373 |
+
|
| 374 |
+
:param server_hostname:
|
| 375 |
+
When SNI is supported, the expected hostname of the certificate
|
| 376 |
+
:param ssl_context:
|
| 377 |
+
A pre-made :class:`SSLContext` object. If none is provided, one will
|
| 378 |
+
be created using :func:`create_urllib3_context`.
|
| 379 |
+
:param ciphers:
|
| 380 |
+
A string of ciphers we wish the client to support.
|
| 381 |
+
:param ca_cert_dir:
|
| 382 |
+
A directory containing CA certificates in multiple separate files, as
|
| 383 |
+
supported by OpenSSL's -CApath flag or the capath argument to
|
| 384 |
+
SSLContext.load_verify_locations().
|
| 385 |
+
:param key_password:
|
| 386 |
+
Optional password if the keyfile is encrypted.
|
| 387 |
+
:param ca_cert_data:
|
| 388 |
+
Optional string containing CA certificates in PEM format suitable for
|
| 389 |
+
passing as the cadata parameter to SSLContext.load_verify_locations()
|
| 390 |
+
:param tls_in_tls:
|
| 391 |
+
Use SSLTransport to wrap the existing socket.
|
| 392 |
+
"""
|
| 393 |
+
context = ssl_context
|
| 394 |
+
if context is None:
|
| 395 |
+
# Note: This branch of code and all the variables in it are no longer
|
| 396 |
+
# used by urllib3 itself. We should consider deprecating and removing
|
| 397 |
+
# this code.
|
| 398 |
+
context = create_urllib3_context(ssl_version, cert_reqs, ciphers=ciphers)
|
| 399 |
+
|
| 400 |
+
if ca_certs or ca_cert_dir or ca_cert_data:
|
| 401 |
+
try:
|
| 402 |
+
context.load_verify_locations(ca_certs, ca_cert_dir, ca_cert_data)
|
| 403 |
+
except (IOError, OSError) as e:
|
| 404 |
+
raise SSLError(e)
|
| 405 |
+
|
| 406 |
+
elif ssl_context is None and hasattr(context, "load_default_certs"):
|
| 407 |
+
# try to load OS default certs; works well on Windows (require Python3.4+)
|
| 408 |
+
context.load_default_certs()
|
| 409 |
+
|
| 410 |
+
# Attempt to detect if we get the goofy behavior of the
|
| 411 |
+
# keyfile being encrypted and OpenSSL asking for the
|
| 412 |
+
# passphrase via the terminal and instead error out.
|
| 413 |
+
if keyfile and key_password is None and _is_key_file_encrypted(keyfile):
|
| 414 |
+
raise SSLError("Client private key is encrypted, password is required")
|
| 415 |
+
|
| 416 |
+
if certfile:
|
| 417 |
+
if key_password is None:
|
| 418 |
+
context.load_cert_chain(certfile, keyfile)
|
| 419 |
+
else:
|
| 420 |
+
context.load_cert_chain(certfile, keyfile, key_password)
|
| 421 |
+
|
| 422 |
+
try:
|
| 423 |
+
if hasattr(context, "set_alpn_protocols"):
|
| 424 |
+
context.set_alpn_protocols(ALPN_PROTOCOLS)
|
| 425 |
+
except NotImplementedError: # Defensive: in CI, we always have set_alpn_protocols
|
| 426 |
+
pass
|
| 427 |
+
|
| 428 |
+
# If we detect server_hostname is an IP address then the SNI
|
| 429 |
+
# extension should not be used according to RFC3546 Section 3.1
|
| 430 |
+
use_sni_hostname = server_hostname and not is_ipaddress(server_hostname)
|
| 431 |
+
# SecureTransport uses server_hostname in certificate verification.
|
| 432 |
+
send_sni = (use_sni_hostname and HAS_SNI) or (
|
| 433 |
+
IS_SECURETRANSPORT and server_hostname
|
| 434 |
+
)
|
| 435 |
+
# Do not warn the user if server_hostname is an invalid SNI hostname.
|
| 436 |
+
if not HAS_SNI and use_sni_hostname:
|
| 437 |
+
warnings.warn(
|
| 438 |
+
"An HTTPS request has been made, but the SNI (Server Name "
|
| 439 |
+
"Indication) extension to TLS is not available on this platform. "
|
| 440 |
+
"This may cause the server to present an incorrect TLS "
|
| 441 |
+
"certificate, which can cause validation failures. You can upgrade to "
|
| 442 |
+
"a newer version of Python to solve this. For more information, see "
|
| 443 |
+
"https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html"
|
| 444 |
+
"#ssl-warnings",
|
| 445 |
+
SNIMissingWarning,
|
| 446 |
+
)
|
| 447 |
+
|
| 448 |
+
if send_sni:
|
| 449 |
+
ssl_sock = _ssl_wrap_socket_impl(
|
| 450 |
+
sock, context, tls_in_tls, server_hostname=server_hostname
|
| 451 |
+
)
|
| 452 |
+
else:
|
| 453 |
+
ssl_sock = _ssl_wrap_socket_impl(sock, context, tls_in_tls)
|
| 454 |
+
return ssl_sock
|
| 455 |
+
|
| 456 |
+
|
| 457 |
+
def is_ipaddress(hostname):
|
| 458 |
+
"""Detects whether the hostname given is an IPv4 or IPv6 address.
|
| 459 |
+
Also detects IPv6 addresses with Zone IDs.
|
| 460 |
+
|
| 461 |
+
:param str hostname: Hostname to examine.
|
| 462 |
+
:return: True if the hostname is an IP address, False otherwise.
|
| 463 |
+
"""
|
| 464 |
+
if not six.PY2 and isinstance(hostname, bytes):
|
| 465 |
+
# IDN A-label bytes are ASCII compatible.
|
| 466 |
+
hostname = hostname.decode("ascii")
|
| 467 |
+
return bool(IPV4_RE.match(hostname) or BRACELESS_IPV6_ADDRZ_RE.match(hostname))
|
| 468 |
+
|
| 469 |
+
|
| 470 |
+
def _is_key_file_encrypted(key_file):
|
| 471 |
+
"""Detects if a key file is encrypted or not."""
|
| 472 |
+
with open(key_file, "r") as f:
|
| 473 |
+
for line in f:
|
| 474 |
+
# Look for Proc-Type: 4,ENCRYPTED
|
| 475 |
+
if "ENCRYPTED" in line:
|
| 476 |
+
return True
|
| 477 |
+
|
| 478 |
+
return False
|
| 479 |
+
|
| 480 |
+
|
| 481 |
+
def _ssl_wrap_socket_impl(sock, ssl_context, tls_in_tls, server_hostname=None):
|
| 482 |
+
if tls_in_tls:
|
| 483 |
+
if not SSLTransport:
|
| 484 |
+
# Import error, ssl is not available.
|
| 485 |
+
raise ProxySchemeUnsupported(
|
| 486 |
+
"TLS in TLS requires support for the 'ssl' module"
|
| 487 |
+
)
|
| 488 |
+
|
| 489 |
+
SSLTransport._validate_ssl_context_for_tls_in_tls(ssl_context)
|
| 490 |
+
return SSLTransport(sock, ssl_context, server_hostname)
|
| 491 |
+
|
| 492 |
+
if server_hostname:
|
| 493 |
+
return ssl_context.wrap_socket(sock, server_hostname=server_hostname)
|
| 494 |
+
else:
|
| 495 |
+
return ssl_context.wrap_socket(sock)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssl_match_hostname.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""The match_hostname() function from Python 3.3.3, essential when using SSL."""
|
| 2 |
+
|
| 3 |
+
# Note: This file is under the PSF license as the code comes from the python
|
| 4 |
+
# stdlib. http://docs.python.org/3/license.html
|
| 5 |
+
|
| 6 |
+
import re
|
| 7 |
+
import sys
|
| 8 |
+
|
| 9 |
+
# ipaddress has been backported to 2.6+ in pypi. If it is installed on the
|
| 10 |
+
# system, use it to handle IPAddress ServerAltnames (this was added in
|
| 11 |
+
# python-3.5) otherwise only do DNS matching. This allows
|
| 12 |
+
# util.ssl_match_hostname to continue to be used in Python 2.7.
|
| 13 |
+
try:
|
| 14 |
+
import ipaddress
|
| 15 |
+
except ImportError:
|
| 16 |
+
ipaddress = None
|
| 17 |
+
|
| 18 |
+
__version__ = "3.5.0.1"
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
class CertificateError(ValueError):
|
| 22 |
+
pass
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def _dnsname_match(dn, hostname, max_wildcards=1):
|
| 26 |
+
"""Matching according to RFC 6125, section 6.4.3
|
| 27 |
+
|
| 28 |
+
http://tools.ietf.org/html/rfc6125#section-6.4.3
|
| 29 |
+
"""
|
| 30 |
+
pats = []
|
| 31 |
+
if not dn:
|
| 32 |
+
return False
|
| 33 |
+
|
| 34 |
+
# Ported from python3-syntax:
|
| 35 |
+
# leftmost, *remainder = dn.split(r'.')
|
| 36 |
+
parts = dn.split(r".")
|
| 37 |
+
leftmost = parts[0]
|
| 38 |
+
remainder = parts[1:]
|
| 39 |
+
|
| 40 |
+
wildcards = leftmost.count("*")
|
| 41 |
+
if wildcards > max_wildcards:
|
| 42 |
+
# Issue #17980: avoid denials of service by refusing more
|
| 43 |
+
# than one wildcard per fragment. A survey of established
|
| 44 |
+
# policy among SSL implementations showed it to be a
|
| 45 |
+
# reasonable choice.
|
| 46 |
+
raise CertificateError(
|
| 47 |
+
"too many wildcards in certificate DNS name: " + repr(dn)
|
| 48 |
+
)
|
| 49 |
+
|
| 50 |
+
# speed up common case w/o wildcards
|
| 51 |
+
if not wildcards:
|
| 52 |
+
return dn.lower() == hostname.lower()
|
| 53 |
+
|
| 54 |
+
# RFC 6125, section 6.4.3, subitem 1.
|
| 55 |
+
# The client SHOULD NOT attempt to match a presented identifier in which
|
| 56 |
+
# the wildcard character comprises a label other than the left-most label.
|
| 57 |
+
if leftmost == "*":
|
| 58 |
+
# When '*' is a fragment by itself, it matches a non-empty dotless
|
| 59 |
+
# fragment.
|
| 60 |
+
pats.append("[^.]+")
|
| 61 |
+
elif leftmost.startswith("xn--") or hostname.startswith("xn--"):
|
| 62 |
+
# RFC 6125, section 6.4.3, subitem 3.
|
| 63 |
+
# The client SHOULD NOT attempt to match a presented identifier
|
| 64 |
+
# where the wildcard character is embedded within an A-label or
|
| 65 |
+
# U-label of an internationalized domain name.
|
| 66 |
+
pats.append(re.escape(leftmost))
|
| 67 |
+
else:
|
| 68 |
+
# Otherwise, '*' matches any dotless string, e.g. www*
|
| 69 |
+
pats.append(re.escape(leftmost).replace(r"\*", "[^.]*"))
|
| 70 |
+
|
| 71 |
+
# add the remaining fragments, ignore any wildcards
|
| 72 |
+
for frag in remainder:
|
| 73 |
+
pats.append(re.escape(frag))
|
| 74 |
+
|
| 75 |
+
pat = re.compile(r"\A" + r"\.".join(pats) + r"\Z", re.IGNORECASE)
|
| 76 |
+
return pat.match(hostname)
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def _to_unicode(obj):
|
| 80 |
+
if isinstance(obj, str) and sys.version_info < (3,):
|
| 81 |
+
# ignored flake8 # F821 to support python 2.7 function
|
| 82 |
+
obj = unicode(obj, encoding="ascii", errors="strict") # noqa: F821
|
| 83 |
+
return obj
|
| 84 |
+
|
| 85 |
+
|
| 86 |
+
def _ipaddress_match(ipname, host_ip):
|
| 87 |
+
"""Exact matching of IP addresses.
|
| 88 |
+
|
| 89 |
+
RFC 6125 explicitly doesn't define an algorithm for this
|
| 90 |
+
(section 1.7.2 - "Out of Scope").
|
| 91 |
+
"""
|
| 92 |
+
# OpenSSL may add a trailing newline to a subjectAltName's IP address
|
| 93 |
+
# Divergence from upstream: ipaddress can't handle byte str
|
| 94 |
+
ip = ipaddress.ip_address(_to_unicode(ipname).rstrip())
|
| 95 |
+
return ip == host_ip
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def match_hostname(cert, hostname):
|
| 99 |
+
"""Verify that *cert* (in decoded format as returned by
|
| 100 |
+
SSLSocket.getpeercert()) matches the *hostname*. RFC 2818 and RFC 6125
|
| 101 |
+
rules are followed, but IP addresses are not accepted for *hostname*.
|
| 102 |
+
|
| 103 |
+
CertificateError is raised on failure. On success, the function
|
| 104 |
+
returns nothing.
|
| 105 |
+
"""
|
| 106 |
+
if not cert:
|
| 107 |
+
raise ValueError(
|
| 108 |
+
"empty or no certificate, match_hostname needs a "
|
| 109 |
+
"SSL socket or SSL context with either "
|
| 110 |
+
"CERT_OPTIONAL or CERT_REQUIRED"
|
| 111 |
+
)
|
| 112 |
+
try:
|
| 113 |
+
# Divergence from upstream: ipaddress can't handle byte str
|
| 114 |
+
host_ip = ipaddress.ip_address(_to_unicode(hostname))
|
| 115 |
+
except (UnicodeError, ValueError):
|
| 116 |
+
# ValueError: Not an IP address (common case)
|
| 117 |
+
# UnicodeError: Divergence from upstream: Have to deal with ipaddress not taking
|
| 118 |
+
# byte strings. addresses should be all ascii, so we consider it not
|
| 119 |
+
# an ipaddress in this case
|
| 120 |
+
host_ip = None
|
| 121 |
+
except AttributeError:
|
| 122 |
+
# Divergence from upstream: Make ipaddress library optional
|
| 123 |
+
if ipaddress is None:
|
| 124 |
+
host_ip = None
|
| 125 |
+
else: # Defensive
|
| 126 |
+
raise
|
| 127 |
+
dnsnames = []
|
| 128 |
+
san = cert.get("subjectAltName", ())
|
| 129 |
+
for key, value in san:
|
| 130 |
+
if key == "DNS":
|
| 131 |
+
if host_ip is None and _dnsname_match(value, hostname):
|
| 132 |
+
return
|
| 133 |
+
dnsnames.append(value)
|
| 134 |
+
elif key == "IP Address":
|
| 135 |
+
if host_ip is not None and _ipaddress_match(value, host_ip):
|
| 136 |
+
return
|
| 137 |
+
dnsnames.append(value)
|
| 138 |
+
if not dnsnames:
|
| 139 |
+
# The subject is only checked when there is no dNSName entry
|
| 140 |
+
# in subjectAltName
|
| 141 |
+
for sub in cert.get("subject", ()):
|
| 142 |
+
for key, value in sub:
|
| 143 |
+
# XXX according to RFC 2818, the most specific Common Name
|
| 144 |
+
# must be used.
|
| 145 |
+
if key == "commonName":
|
| 146 |
+
if _dnsname_match(value, hostname):
|
| 147 |
+
return
|
| 148 |
+
dnsnames.append(value)
|
| 149 |
+
if len(dnsnames) > 1:
|
| 150 |
+
raise CertificateError(
|
| 151 |
+
"hostname %r "
|
| 152 |
+
"doesn't match either of %s" % (hostname, ", ".join(map(repr, dnsnames)))
|
| 153 |
+
)
|
| 154 |
+
elif len(dnsnames) == 1:
|
| 155 |
+
raise CertificateError("hostname %r doesn't match %r" % (hostname, dnsnames[0]))
|
| 156 |
+
else:
|
| 157 |
+
raise CertificateError(
|
| 158 |
+
"no appropriate commonName or subjectAltName fields were found"
|
| 159 |
+
)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/ssltransport.py
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import io
|
| 2 |
+
import socket
|
| 3 |
+
import ssl
|
| 4 |
+
|
| 5 |
+
from ..exceptions import ProxySchemeUnsupported
|
| 6 |
+
from ..packages import six
|
| 7 |
+
|
| 8 |
+
SSL_BLOCKSIZE = 16384
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class SSLTransport:
|
| 12 |
+
"""
|
| 13 |
+
The SSLTransport wraps an existing socket and establishes an SSL connection.
|
| 14 |
+
|
| 15 |
+
Contrary to Python's implementation of SSLSocket, it allows you to chain
|
| 16 |
+
multiple TLS connections together. It's particularly useful if you need to
|
| 17 |
+
implement TLS within TLS.
|
| 18 |
+
|
| 19 |
+
The class supports most of the socket API operations.
|
| 20 |
+
"""
|
| 21 |
+
|
| 22 |
+
@staticmethod
|
| 23 |
+
def _validate_ssl_context_for_tls_in_tls(ssl_context):
|
| 24 |
+
"""
|
| 25 |
+
Raises a ProxySchemeUnsupported if the provided ssl_context can't be used
|
| 26 |
+
for TLS in TLS.
|
| 27 |
+
|
| 28 |
+
The only requirement is that the ssl_context provides the 'wrap_bio'
|
| 29 |
+
methods.
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
if not hasattr(ssl_context, "wrap_bio"):
|
| 33 |
+
if six.PY2:
|
| 34 |
+
raise ProxySchemeUnsupported(
|
| 35 |
+
"TLS in TLS requires SSLContext.wrap_bio() which isn't "
|
| 36 |
+
"supported on Python 2"
|
| 37 |
+
)
|
| 38 |
+
else:
|
| 39 |
+
raise ProxySchemeUnsupported(
|
| 40 |
+
"TLS in TLS requires SSLContext.wrap_bio() which isn't "
|
| 41 |
+
"available on non-native SSLContext"
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
def __init__(
|
| 45 |
+
self, socket, ssl_context, server_hostname=None, suppress_ragged_eofs=True
|
| 46 |
+
):
|
| 47 |
+
"""
|
| 48 |
+
Create an SSLTransport around socket using the provided ssl_context.
|
| 49 |
+
"""
|
| 50 |
+
self.incoming = ssl.MemoryBIO()
|
| 51 |
+
self.outgoing = ssl.MemoryBIO()
|
| 52 |
+
|
| 53 |
+
self.suppress_ragged_eofs = suppress_ragged_eofs
|
| 54 |
+
self.socket = socket
|
| 55 |
+
|
| 56 |
+
self.sslobj = ssl_context.wrap_bio(
|
| 57 |
+
self.incoming, self.outgoing, server_hostname=server_hostname
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
# Perform initial handshake.
|
| 61 |
+
self._ssl_io_loop(self.sslobj.do_handshake)
|
| 62 |
+
|
| 63 |
+
def __enter__(self):
|
| 64 |
+
return self
|
| 65 |
+
|
| 66 |
+
def __exit__(self, *_):
|
| 67 |
+
self.close()
|
| 68 |
+
|
| 69 |
+
def fileno(self):
|
| 70 |
+
return self.socket.fileno()
|
| 71 |
+
|
| 72 |
+
def read(self, len=1024, buffer=None):
|
| 73 |
+
return self._wrap_ssl_read(len, buffer)
|
| 74 |
+
|
| 75 |
+
def recv(self, len=1024, flags=0):
|
| 76 |
+
if flags != 0:
|
| 77 |
+
raise ValueError("non-zero flags not allowed in calls to recv")
|
| 78 |
+
return self._wrap_ssl_read(len)
|
| 79 |
+
|
| 80 |
+
def recv_into(self, buffer, nbytes=None, flags=0):
|
| 81 |
+
if flags != 0:
|
| 82 |
+
raise ValueError("non-zero flags not allowed in calls to recv_into")
|
| 83 |
+
if buffer and (nbytes is None):
|
| 84 |
+
nbytes = len(buffer)
|
| 85 |
+
elif nbytes is None:
|
| 86 |
+
nbytes = 1024
|
| 87 |
+
return self.read(nbytes, buffer)
|
| 88 |
+
|
| 89 |
+
def sendall(self, data, flags=0):
|
| 90 |
+
if flags != 0:
|
| 91 |
+
raise ValueError("non-zero flags not allowed in calls to sendall")
|
| 92 |
+
count = 0
|
| 93 |
+
with memoryview(data) as view, view.cast("B") as byte_view:
|
| 94 |
+
amount = len(byte_view)
|
| 95 |
+
while count < amount:
|
| 96 |
+
v = self.send(byte_view[count:])
|
| 97 |
+
count += v
|
| 98 |
+
|
| 99 |
+
def send(self, data, flags=0):
|
| 100 |
+
if flags != 0:
|
| 101 |
+
raise ValueError("non-zero flags not allowed in calls to send")
|
| 102 |
+
response = self._ssl_io_loop(self.sslobj.write, data)
|
| 103 |
+
return response
|
| 104 |
+
|
| 105 |
+
def makefile(
|
| 106 |
+
self, mode="r", buffering=None, encoding=None, errors=None, newline=None
|
| 107 |
+
):
|
| 108 |
+
"""
|
| 109 |
+
Python's httpclient uses makefile and buffered io when reading HTTP
|
| 110 |
+
messages and we need to support it.
|
| 111 |
+
|
| 112 |
+
This is unfortunately a copy and paste of socket.py makefile with small
|
| 113 |
+
changes to point to the socket directly.
|
| 114 |
+
"""
|
| 115 |
+
if not set(mode) <= {"r", "w", "b"}:
|
| 116 |
+
raise ValueError("invalid mode %r (only r, w, b allowed)" % (mode,))
|
| 117 |
+
|
| 118 |
+
writing = "w" in mode
|
| 119 |
+
reading = "r" in mode or not writing
|
| 120 |
+
assert reading or writing
|
| 121 |
+
binary = "b" in mode
|
| 122 |
+
rawmode = ""
|
| 123 |
+
if reading:
|
| 124 |
+
rawmode += "r"
|
| 125 |
+
if writing:
|
| 126 |
+
rawmode += "w"
|
| 127 |
+
raw = socket.SocketIO(self, rawmode)
|
| 128 |
+
self.socket._io_refs += 1
|
| 129 |
+
if buffering is None:
|
| 130 |
+
buffering = -1
|
| 131 |
+
if buffering < 0:
|
| 132 |
+
buffering = io.DEFAULT_BUFFER_SIZE
|
| 133 |
+
if buffering == 0:
|
| 134 |
+
if not binary:
|
| 135 |
+
raise ValueError("unbuffered streams must be binary")
|
| 136 |
+
return raw
|
| 137 |
+
if reading and writing:
|
| 138 |
+
buffer = io.BufferedRWPair(raw, raw, buffering)
|
| 139 |
+
elif reading:
|
| 140 |
+
buffer = io.BufferedReader(raw, buffering)
|
| 141 |
+
else:
|
| 142 |
+
assert writing
|
| 143 |
+
buffer = io.BufferedWriter(raw, buffering)
|
| 144 |
+
if binary:
|
| 145 |
+
return buffer
|
| 146 |
+
text = io.TextIOWrapper(buffer, encoding, errors, newline)
|
| 147 |
+
text.mode = mode
|
| 148 |
+
return text
|
| 149 |
+
|
| 150 |
+
def unwrap(self):
|
| 151 |
+
self._ssl_io_loop(self.sslobj.unwrap)
|
| 152 |
+
|
| 153 |
+
def close(self):
|
| 154 |
+
self.socket.close()
|
| 155 |
+
|
| 156 |
+
def getpeercert(self, binary_form=False):
|
| 157 |
+
return self.sslobj.getpeercert(binary_form)
|
| 158 |
+
|
| 159 |
+
def version(self):
|
| 160 |
+
return self.sslobj.version()
|
| 161 |
+
|
| 162 |
+
def cipher(self):
|
| 163 |
+
return self.sslobj.cipher()
|
| 164 |
+
|
| 165 |
+
def selected_alpn_protocol(self):
|
| 166 |
+
return self.sslobj.selected_alpn_protocol()
|
| 167 |
+
|
| 168 |
+
def selected_npn_protocol(self):
|
| 169 |
+
return self.sslobj.selected_npn_protocol()
|
| 170 |
+
|
| 171 |
+
def shared_ciphers(self):
|
| 172 |
+
return self.sslobj.shared_ciphers()
|
| 173 |
+
|
| 174 |
+
def compression(self):
|
| 175 |
+
return self.sslobj.compression()
|
| 176 |
+
|
| 177 |
+
def settimeout(self, value):
|
| 178 |
+
self.socket.settimeout(value)
|
| 179 |
+
|
| 180 |
+
def gettimeout(self):
|
| 181 |
+
return self.socket.gettimeout()
|
| 182 |
+
|
| 183 |
+
def _decref_socketios(self):
|
| 184 |
+
self.socket._decref_socketios()
|
| 185 |
+
|
| 186 |
+
def _wrap_ssl_read(self, len, buffer=None):
|
| 187 |
+
try:
|
| 188 |
+
return self._ssl_io_loop(self.sslobj.read, len, buffer)
|
| 189 |
+
except ssl.SSLError as e:
|
| 190 |
+
if e.errno == ssl.SSL_ERROR_EOF and self.suppress_ragged_eofs:
|
| 191 |
+
return 0 # eof, return 0.
|
| 192 |
+
else:
|
| 193 |
+
raise
|
| 194 |
+
|
| 195 |
+
def _ssl_io_loop(self, func, *args):
|
| 196 |
+
"""Performs an I/O loop between incoming/outgoing and the socket."""
|
| 197 |
+
should_loop = True
|
| 198 |
+
ret = None
|
| 199 |
+
|
| 200 |
+
while should_loop:
|
| 201 |
+
errno = None
|
| 202 |
+
try:
|
| 203 |
+
ret = func(*args)
|
| 204 |
+
except ssl.SSLError as e:
|
| 205 |
+
if e.errno not in (ssl.SSL_ERROR_WANT_READ, ssl.SSL_ERROR_WANT_WRITE):
|
| 206 |
+
# WANT_READ, and WANT_WRITE are expected, others are not.
|
| 207 |
+
raise e
|
| 208 |
+
errno = e.errno
|
| 209 |
+
|
| 210 |
+
buf = self.outgoing.read()
|
| 211 |
+
self.socket.sendall(buf)
|
| 212 |
+
|
| 213 |
+
if errno is None:
|
| 214 |
+
should_loop = False
|
| 215 |
+
elif errno == ssl.SSL_ERROR_WANT_READ:
|
| 216 |
+
buf = self.socket.recv(SSL_BLOCKSIZE)
|
| 217 |
+
if buf:
|
| 218 |
+
self.incoming.write(buf)
|
| 219 |
+
else:
|
| 220 |
+
self.incoming.write_eof()
|
| 221 |
+
return ret
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/timeout.py
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import time
|
| 4 |
+
|
| 5 |
+
# The default socket timeout, used by httplib to indicate that no timeout was; specified by the user
|
| 6 |
+
from socket import _GLOBAL_DEFAULT_TIMEOUT, getdefaulttimeout
|
| 7 |
+
|
| 8 |
+
from ..exceptions import TimeoutStateError
|
| 9 |
+
|
| 10 |
+
# A sentinel value to indicate that no timeout was specified by the user in
|
| 11 |
+
# urllib3
|
| 12 |
+
_Default = object()
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# Use time.monotonic if available.
|
| 16 |
+
current_time = getattr(time, "monotonic", time.time)
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
class Timeout(object):
|
| 20 |
+
"""Timeout configuration.
|
| 21 |
+
|
| 22 |
+
Timeouts can be defined as a default for a pool:
|
| 23 |
+
|
| 24 |
+
.. code-block:: python
|
| 25 |
+
|
| 26 |
+
timeout = Timeout(connect=2.0, read=7.0)
|
| 27 |
+
http = PoolManager(timeout=timeout)
|
| 28 |
+
response = http.request('GET', 'http://example.com/')
|
| 29 |
+
|
| 30 |
+
Or per-request (which overrides the default for the pool):
|
| 31 |
+
|
| 32 |
+
.. code-block:: python
|
| 33 |
+
|
| 34 |
+
response = http.request('GET', 'http://example.com/', timeout=Timeout(10))
|
| 35 |
+
|
| 36 |
+
Timeouts can be disabled by setting all the parameters to ``None``:
|
| 37 |
+
|
| 38 |
+
.. code-block:: python
|
| 39 |
+
|
| 40 |
+
no_timeout = Timeout(connect=None, read=None)
|
| 41 |
+
response = http.request('GET', 'http://example.com/, timeout=no_timeout)
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
:param total:
|
| 45 |
+
This combines the connect and read timeouts into one; the read timeout
|
| 46 |
+
will be set to the time leftover from the connect attempt. In the
|
| 47 |
+
event that both a connect timeout and a total are specified, or a read
|
| 48 |
+
timeout and a total are specified, the shorter timeout will be applied.
|
| 49 |
+
|
| 50 |
+
Defaults to None.
|
| 51 |
+
|
| 52 |
+
:type total: int, float, or None
|
| 53 |
+
|
| 54 |
+
:param connect:
|
| 55 |
+
The maximum amount of time (in seconds) to wait for a connection
|
| 56 |
+
attempt to a server to succeed. Omitting the parameter will default the
|
| 57 |
+
connect timeout to the system default, probably `the global default
|
| 58 |
+
timeout in socket.py
|
| 59 |
+
<http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.
|
| 60 |
+
None will set an infinite timeout for connection attempts.
|
| 61 |
+
|
| 62 |
+
:type connect: int, float, or None
|
| 63 |
+
|
| 64 |
+
:param read:
|
| 65 |
+
The maximum amount of time (in seconds) to wait between consecutive
|
| 66 |
+
read operations for a response from the server. Omitting the parameter
|
| 67 |
+
will default the read timeout to the system default, probably `the
|
| 68 |
+
global default timeout in socket.py
|
| 69 |
+
<http://hg.python.org/cpython/file/603b4d593758/Lib/socket.py#l535>`_.
|
| 70 |
+
None will set an infinite timeout.
|
| 71 |
+
|
| 72 |
+
:type read: int, float, or None
|
| 73 |
+
|
| 74 |
+
.. note::
|
| 75 |
+
|
| 76 |
+
Many factors can affect the total amount of time for urllib3 to return
|
| 77 |
+
an HTTP response.
|
| 78 |
+
|
| 79 |
+
For example, Python's DNS resolver does not obey the timeout specified
|
| 80 |
+
on the socket. Other factors that can affect total request time include
|
| 81 |
+
high CPU load, high swap, the program running at a low priority level,
|
| 82 |
+
or other behaviors.
|
| 83 |
+
|
| 84 |
+
In addition, the read and total timeouts only measure the time between
|
| 85 |
+
read operations on the socket connecting the client and the server,
|
| 86 |
+
not the total amount of time for the request to return a complete
|
| 87 |
+
response. For most requests, the timeout is raised because the server
|
| 88 |
+
has not sent the first byte in the specified time. This is not always
|
| 89 |
+
the case; if a server streams one byte every fifteen seconds, a timeout
|
| 90 |
+
of 20 seconds will not trigger, even though the request will take
|
| 91 |
+
several minutes to complete.
|
| 92 |
+
|
| 93 |
+
If your goal is to cut off any request after a set amount of wall clock
|
| 94 |
+
time, consider having a second "watcher" thread to cut off a slow
|
| 95 |
+
request.
|
| 96 |
+
"""
|
| 97 |
+
|
| 98 |
+
#: A sentinel object representing the default timeout value
|
| 99 |
+
DEFAULT_TIMEOUT = _GLOBAL_DEFAULT_TIMEOUT
|
| 100 |
+
|
| 101 |
+
def __init__(self, total=None, connect=_Default, read=_Default):
|
| 102 |
+
self._connect = self._validate_timeout(connect, "connect")
|
| 103 |
+
self._read = self._validate_timeout(read, "read")
|
| 104 |
+
self.total = self._validate_timeout(total, "total")
|
| 105 |
+
self._start_connect = None
|
| 106 |
+
|
| 107 |
+
def __repr__(self):
|
| 108 |
+
return "%s(connect=%r, read=%r, total=%r)" % (
|
| 109 |
+
type(self).__name__,
|
| 110 |
+
self._connect,
|
| 111 |
+
self._read,
|
| 112 |
+
self.total,
|
| 113 |
+
)
|
| 114 |
+
|
| 115 |
+
# __str__ provided for backwards compatibility
|
| 116 |
+
__str__ = __repr__
|
| 117 |
+
|
| 118 |
+
@classmethod
|
| 119 |
+
def resolve_default_timeout(cls, timeout):
|
| 120 |
+
return getdefaulttimeout() if timeout is cls.DEFAULT_TIMEOUT else timeout
|
| 121 |
+
|
| 122 |
+
@classmethod
|
| 123 |
+
def _validate_timeout(cls, value, name):
|
| 124 |
+
"""Check that a timeout attribute is valid.
|
| 125 |
+
|
| 126 |
+
:param value: The timeout value to validate
|
| 127 |
+
:param name: The name of the timeout attribute to validate. This is
|
| 128 |
+
used to specify in error messages.
|
| 129 |
+
:return: The validated and casted version of the given value.
|
| 130 |
+
:raises ValueError: If it is a numeric value less than or equal to
|
| 131 |
+
zero, or the type is not an integer, float, or None.
|
| 132 |
+
"""
|
| 133 |
+
if value is _Default:
|
| 134 |
+
return cls.DEFAULT_TIMEOUT
|
| 135 |
+
|
| 136 |
+
if value is None or value is cls.DEFAULT_TIMEOUT:
|
| 137 |
+
return value
|
| 138 |
+
|
| 139 |
+
if isinstance(value, bool):
|
| 140 |
+
raise ValueError(
|
| 141 |
+
"Timeout cannot be a boolean value. It must "
|
| 142 |
+
"be an int, float or None."
|
| 143 |
+
)
|
| 144 |
+
try:
|
| 145 |
+
float(value)
|
| 146 |
+
except (TypeError, ValueError):
|
| 147 |
+
raise ValueError(
|
| 148 |
+
"Timeout value %s was %s, but it must be an "
|
| 149 |
+
"int, float or None." % (name, value)
|
| 150 |
+
)
|
| 151 |
+
|
| 152 |
+
try:
|
| 153 |
+
if value <= 0:
|
| 154 |
+
raise ValueError(
|
| 155 |
+
"Attempted to set %s timeout to %s, but the "
|
| 156 |
+
"timeout cannot be set to a value less "
|
| 157 |
+
"than or equal to 0." % (name, value)
|
| 158 |
+
)
|
| 159 |
+
except TypeError:
|
| 160 |
+
# Python 3
|
| 161 |
+
raise ValueError(
|
| 162 |
+
"Timeout value %s was %s, but it must be an "
|
| 163 |
+
"int, float or None." % (name, value)
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
return value
|
| 167 |
+
|
| 168 |
+
@classmethod
|
| 169 |
+
def from_float(cls, timeout):
|
| 170 |
+
"""Create a new Timeout from a legacy timeout value.
|
| 171 |
+
|
| 172 |
+
The timeout value used by httplib.py sets the same timeout on the
|
| 173 |
+
connect(), and recv() socket requests. This creates a :class:`Timeout`
|
| 174 |
+
object that sets the individual timeouts to the ``timeout`` value
|
| 175 |
+
passed to this function.
|
| 176 |
+
|
| 177 |
+
:param timeout: The legacy timeout value.
|
| 178 |
+
:type timeout: integer, float, sentinel default object, or None
|
| 179 |
+
:return: Timeout object
|
| 180 |
+
:rtype: :class:`Timeout`
|
| 181 |
+
"""
|
| 182 |
+
return Timeout(read=timeout, connect=timeout)
|
| 183 |
+
|
| 184 |
+
def clone(self):
|
| 185 |
+
"""Create a copy of the timeout object
|
| 186 |
+
|
| 187 |
+
Timeout properties are stored per-pool but each request needs a fresh
|
| 188 |
+
Timeout object to ensure each one has its own start/stop configured.
|
| 189 |
+
|
| 190 |
+
:return: a copy of the timeout object
|
| 191 |
+
:rtype: :class:`Timeout`
|
| 192 |
+
"""
|
| 193 |
+
# We can't use copy.deepcopy because that will also create a new object
|
| 194 |
+
# for _GLOBAL_DEFAULT_TIMEOUT, which socket.py uses as a sentinel to
|
| 195 |
+
# detect the user default.
|
| 196 |
+
return Timeout(connect=self._connect, read=self._read, total=self.total)
|
| 197 |
+
|
| 198 |
+
def start_connect(self):
|
| 199 |
+
"""Start the timeout clock, used during a connect() attempt
|
| 200 |
+
|
| 201 |
+
:raises urllib3.exceptions.TimeoutStateError: if you attempt
|
| 202 |
+
to start a timer that has been started already.
|
| 203 |
+
"""
|
| 204 |
+
if self._start_connect is not None:
|
| 205 |
+
raise TimeoutStateError("Timeout timer has already been started.")
|
| 206 |
+
self._start_connect = current_time()
|
| 207 |
+
return self._start_connect
|
| 208 |
+
|
| 209 |
+
def get_connect_duration(self):
|
| 210 |
+
"""Gets the time elapsed since the call to :meth:`start_connect`.
|
| 211 |
+
|
| 212 |
+
:return: Elapsed time in seconds.
|
| 213 |
+
:rtype: float
|
| 214 |
+
:raises urllib3.exceptions.TimeoutStateError: if you attempt
|
| 215 |
+
to get duration for a timer that hasn't been started.
|
| 216 |
+
"""
|
| 217 |
+
if self._start_connect is None:
|
| 218 |
+
raise TimeoutStateError(
|
| 219 |
+
"Can't get connect duration for timer that has not started."
|
| 220 |
+
)
|
| 221 |
+
return current_time() - self._start_connect
|
| 222 |
+
|
| 223 |
+
@property
|
| 224 |
+
def connect_timeout(self):
|
| 225 |
+
"""Get the value to use when setting a connection timeout.
|
| 226 |
+
|
| 227 |
+
This will be a positive float or integer, the value None
|
| 228 |
+
(never timeout), or the default system timeout.
|
| 229 |
+
|
| 230 |
+
:return: Connect timeout.
|
| 231 |
+
:rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None
|
| 232 |
+
"""
|
| 233 |
+
if self.total is None:
|
| 234 |
+
return self._connect
|
| 235 |
+
|
| 236 |
+
if self._connect is None or self._connect is self.DEFAULT_TIMEOUT:
|
| 237 |
+
return self.total
|
| 238 |
+
|
| 239 |
+
return min(self._connect, self.total)
|
| 240 |
+
|
| 241 |
+
@property
|
| 242 |
+
def read_timeout(self):
|
| 243 |
+
"""Get the value for the read timeout.
|
| 244 |
+
|
| 245 |
+
This assumes some time has elapsed in the connection timeout and
|
| 246 |
+
computes the read timeout appropriately.
|
| 247 |
+
|
| 248 |
+
If self.total is set, the read timeout is dependent on the amount of
|
| 249 |
+
time taken by the connect timeout. If the connection time has not been
|
| 250 |
+
established, a :exc:`~urllib3.exceptions.TimeoutStateError` will be
|
| 251 |
+
raised.
|
| 252 |
+
|
| 253 |
+
:return: Value to use for the read timeout.
|
| 254 |
+
:rtype: int, float, :attr:`Timeout.DEFAULT_TIMEOUT` or None
|
| 255 |
+
:raises urllib3.exceptions.TimeoutStateError: If :meth:`start_connect`
|
| 256 |
+
has not yet been called on this object.
|
| 257 |
+
"""
|
| 258 |
+
if (
|
| 259 |
+
self.total is not None
|
| 260 |
+
and self.total is not self.DEFAULT_TIMEOUT
|
| 261 |
+
and self._read is not None
|
| 262 |
+
and self._read is not self.DEFAULT_TIMEOUT
|
| 263 |
+
):
|
| 264 |
+
# In case the connect timeout has not yet been established.
|
| 265 |
+
if self._start_connect is None:
|
| 266 |
+
return self._read
|
| 267 |
+
return max(0, min(self.total - self.get_connect_duration(), self._read))
|
| 268 |
+
elif self.total is not None and self.total is not self.DEFAULT_TIMEOUT:
|
| 269 |
+
return max(0, self.total - self.get_connect_duration())
|
| 270 |
+
else:
|
| 271 |
+
return self._read
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/url.py
ADDED
|
@@ -0,0 +1,435 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import absolute_import
|
| 2 |
+
|
| 3 |
+
import re
|
| 4 |
+
from collections import namedtuple
|
| 5 |
+
|
| 6 |
+
from ..exceptions import LocationParseError
|
| 7 |
+
from ..packages import six
|
| 8 |
+
|
| 9 |
+
url_attrs = ["scheme", "auth", "host", "port", "path", "query", "fragment"]
|
| 10 |
+
|
| 11 |
+
# We only want to normalize urls with an HTTP(S) scheme.
|
| 12 |
+
# urllib3 infers URLs without a scheme (None) to be http.
|
| 13 |
+
NORMALIZABLE_SCHEMES = ("http", "https", None)
|
| 14 |
+
|
| 15 |
+
# Almost all of these patterns were derived from the
|
| 16 |
+
# 'rfc3986' module: https://github.com/python-hyper/rfc3986
|
| 17 |
+
PERCENT_RE = re.compile(r"%[a-fA-F0-9]{2}")
|
| 18 |
+
SCHEME_RE = re.compile(r"^(?:[a-zA-Z][a-zA-Z0-9+-]*:|/)")
|
| 19 |
+
URI_RE = re.compile(
|
| 20 |
+
r"^(?:([a-zA-Z][a-zA-Z0-9+.-]*):)?"
|
| 21 |
+
r"(?://([^\\/?#]*))?"
|
| 22 |
+
r"([^?#]*)"
|
| 23 |
+
r"(?:\?([^#]*))?"
|
| 24 |
+
r"(?:#(.*))?$",
|
| 25 |
+
re.UNICODE | re.DOTALL,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
IPV4_PAT = r"(?:[0-9]{1,3}\.){3}[0-9]{1,3}"
|
| 29 |
+
HEX_PAT = "[0-9A-Fa-f]{1,4}"
|
| 30 |
+
LS32_PAT = "(?:{hex}:{hex}|{ipv4})".format(hex=HEX_PAT, ipv4=IPV4_PAT)
|
| 31 |
+
_subs = {"hex": HEX_PAT, "ls32": LS32_PAT}
|
| 32 |
+
_variations = [
|
| 33 |
+
# 6( h16 ":" ) ls32
|
| 34 |
+
"(?:%(hex)s:){6}%(ls32)s",
|
| 35 |
+
# "::" 5( h16 ":" ) ls32
|
| 36 |
+
"::(?:%(hex)s:){5}%(ls32)s",
|
| 37 |
+
# [ h16 ] "::" 4( h16 ":" ) ls32
|
| 38 |
+
"(?:%(hex)s)?::(?:%(hex)s:){4}%(ls32)s",
|
| 39 |
+
# [ *1( h16 ":" ) h16 ] "::" 3( h16 ":" ) ls32
|
| 40 |
+
"(?:(?:%(hex)s:)?%(hex)s)?::(?:%(hex)s:){3}%(ls32)s",
|
| 41 |
+
# [ *2( h16 ":" ) h16 ] "::" 2( h16 ":" ) ls32
|
| 42 |
+
"(?:(?:%(hex)s:){0,2}%(hex)s)?::(?:%(hex)s:){2}%(ls32)s",
|
| 43 |
+
# [ *3( h16 ":" ) h16 ] "::" h16 ":" ls32
|
| 44 |
+
"(?:(?:%(hex)s:){0,3}%(hex)s)?::%(hex)s:%(ls32)s",
|
| 45 |
+
# [ *4( h16 ":" ) h16 ] "::" ls32
|
| 46 |
+
"(?:(?:%(hex)s:){0,4}%(hex)s)?::%(ls32)s",
|
| 47 |
+
# [ *5( h16 ":" ) h16 ] "::" h16
|
| 48 |
+
"(?:(?:%(hex)s:){0,5}%(hex)s)?::%(hex)s",
|
| 49 |
+
# [ *6( h16 ":" ) h16 ] "::"
|
| 50 |
+
"(?:(?:%(hex)s:){0,6}%(hex)s)?::",
|
| 51 |
+
]
|
| 52 |
+
|
| 53 |
+
UNRESERVED_PAT = r"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._\-~"
|
| 54 |
+
IPV6_PAT = "(?:" + "|".join([x % _subs for x in _variations]) + ")"
|
| 55 |
+
ZONE_ID_PAT = "(?:%25|%)(?:[" + UNRESERVED_PAT + "]|%[a-fA-F0-9]{2})+"
|
| 56 |
+
IPV6_ADDRZ_PAT = r"\[" + IPV6_PAT + r"(?:" + ZONE_ID_PAT + r")?\]"
|
| 57 |
+
REG_NAME_PAT = r"(?:[^\[\]%:/?#]|%[a-fA-F0-9]{2})*"
|
| 58 |
+
TARGET_RE = re.compile(r"^(/[^?#]*)(?:\?([^#]*))?(?:#.*)?$")
|
| 59 |
+
|
| 60 |
+
IPV4_RE = re.compile("^" + IPV4_PAT + "$")
|
| 61 |
+
IPV6_RE = re.compile("^" + IPV6_PAT + "$")
|
| 62 |
+
IPV6_ADDRZ_RE = re.compile("^" + IPV6_ADDRZ_PAT + "$")
|
| 63 |
+
BRACELESS_IPV6_ADDRZ_RE = re.compile("^" + IPV6_ADDRZ_PAT[2:-2] + "$")
|
| 64 |
+
ZONE_ID_RE = re.compile("(" + ZONE_ID_PAT + r")\]$")
|
| 65 |
+
|
| 66 |
+
_HOST_PORT_PAT = ("^(%s|%s|%s)(?::0*?(|0|[1-9][0-9]{0,4}))?$") % (
|
| 67 |
+
REG_NAME_PAT,
|
| 68 |
+
IPV4_PAT,
|
| 69 |
+
IPV6_ADDRZ_PAT,
|
| 70 |
+
)
|
| 71 |
+
_HOST_PORT_RE = re.compile(_HOST_PORT_PAT, re.UNICODE | re.DOTALL)
|
| 72 |
+
|
| 73 |
+
UNRESERVED_CHARS = set(
|
| 74 |
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._-~"
|
| 75 |
+
)
|
| 76 |
+
SUB_DELIM_CHARS = set("!$&'()*+,;=")
|
| 77 |
+
USERINFO_CHARS = UNRESERVED_CHARS | SUB_DELIM_CHARS | {":"}
|
| 78 |
+
PATH_CHARS = USERINFO_CHARS | {"@", "/"}
|
| 79 |
+
QUERY_CHARS = FRAGMENT_CHARS = PATH_CHARS | {"?"}
|
| 80 |
+
|
| 81 |
+
|
| 82 |
+
class Url(namedtuple("Url", url_attrs)):
|
| 83 |
+
"""
|
| 84 |
+
Data structure for representing an HTTP URL. Used as a return value for
|
| 85 |
+
:func:`parse_url`. Both the scheme and host are normalized as they are
|
| 86 |
+
both case-insensitive according to RFC 3986.
|
| 87 |
+
"""
|
| 88 |
+
|
| 89 |
+
__slots__ = ()
|
| 90 |
+
|
| 91 |
+
def __new__(
|
| 92 |
+
cls,
|
| 93 |
+
scheme=None,
|
| 94 |
+
auth=None,
|
| 95 |
+
host=None,
|
| 96 |
+
port=None,
|
| 97 |
+
path=None,
|
| 98 |
+
query=None,
|
| 99 |
+
fragment=None,
|
| 100 |
+
):
|
| 101 |
+
if path and not path.startswith("/"):
|
| 102 |
+
path = "/" + path
|
| 103 |
+
if scheme is not None:
|
| 104 |
+
scheme = scheme.lower()
|
| 105 |
+
return super(Url, cls).__new__(
|
| 106 |
+
cls, scheme, auth, host, port, path, query, fragment
|
| 107 |
+
)
|
| 108 |
+
|
| 109 |
+
@property
|
| 110 |
+
def hostname(self):
|
| 111 |
+
"""For backwards-compatibility with urlparse. We're nice like that."""
|
| 112 |
+
return self.host
|
| 113 |
+
|
| 114 |
+
@property
|
| 115 |
+
def request_uri(self):
|
| 116 |
+
"""Absolute path including the query string."""
|
| 117 |
+
uri = self.path or "/"
|
| 118 |
+
|
| 119 |
+
if self.query is not None:
|
| 120 |
+
uri += "?" + self.query
|
| 121 |
+
|
| 122 |
+
return uri
|
| 123 |
+
|
| 124 |
+
@property
|
| 125 |
+
def netloc(self):
|
| 126 |
+
"""Network location including host and port"""
|
| 127 |
+
if self.port:
|
| 128 |
+
return "%s:%d" % (self.host, self.port)
|
| 129 |
+
return self.host
|
| 130 |
+
|
| 131 |
+
@property
|
| 132 |
+
def url(self):
|
| 133 |
+
"""
|
| 134 |
+
Convert self into a url
|
| 135 |
+
|
| 136 |
+
This function should more or less round-trip with :func:`.parse_url`. The
|
| 137 |
+
returned url may not be exactly the same as the url inputted to
|
| 138 |
+
:func:`.parse_url`, but it should be equivalent by the RFC (e.g., urls
|
| 139 |
+
with a blank port will have : removed).
|
| 140 |
+
|
| 141 |
+
Example: ::
|
| 142 |
+
|
| 143 |
+
>>> U = parse_url('http://google.com/mail/')
|
| 144 |
+
>>> U.url
|
| 145 |
+
'http://google.com/mail/'
|
| 146 |
+
>>> Url('http', 'username:password', 'host.com', 80,
|
| 147 |
+
... '/path', 'query', 'fragment').url
|
| 148 |
+
'http://username:password@host.com:80/path?query#fragment'
|
| 149 |
+
"""
|
| 150 |
+
scheme, auth, host, port, path, query, fragment = self
|
| 151 |
+
url = u""
|
| 152 |
+
|
| 153 |
+
# We use "is not None" we want things to happen with empty strings (or 0 port)
|
| 154 |
+
if scheme is not None:
|
| 155 |
+
url += scheme + u"://"
|
| 156 |
+
if auth is not None:
|
| 157 |
+
url += auth + u"@"
|
| 158 |
+
if host is not None:
|
| 159 |
+
url += host
|
| 160 |
+
if port is not None:
|
| 161 |
+
url += u":" + str(port)
|
| 162 |
+
if path is not None:
|
| 163 |
+
url += path
|
| 164 |
+
if query is not None:
|
| 165 |
+
url += u"?" + query
|
| 166 |
+
if fragment is not None:
|
| 167 |
+
url += u"#" + fragment
|
| 168 |
+
|
| 169 |
+
return url
|
| 170 |
+
|
| 171 |
+
def __str__(self):
|
| 172 |
+
return self.url
|
| 173 |
+
|
| 174 |
+
|
| 175 |
+
def split_first(s, delims):
|
| 176 |
+
"""
|
| 177 |
+
.. deprecated:: 1.25
|
| 178 |
+
|
| 179 |
+
Given a string and an iterable of delimiters, split on the first found
|
| 180 |
+
delimiter. Return two split parts and the matched delimiter.
|
| 181 |
+
|
| 182 |
+
If not found, then the first part is the full input string.
|
| 183 |
+
|
| 184 |
+
Example::
|
| 185 |
+
|
| 186 |
+
>>> split_first('foo/bar?baz', '?/=')
|
| 187 |
+
('foo', 'bar?baz', '/')
|
| 188 |
+
>>> split_first('foo/bar?baz', '123')
|
| 189 |
+
('foo/bar?baz', '', None)
|
| 190 |
+
|
| 191 |
+
Scales linearly with number of delims. Not ideal for large number of delims.
|
| 192 |
+
"""
|
| 193 |
+
min_idx = None
|
| 194 |
+
min_delim = None
|
| 195 |
+
for d in delims:
|
| 196 |
+
idx = s.find(d)
|
| 197 |
+
if idx < 0:
|
| 198 |
+
continue
|
| 199 |
+
|
| 200 |
+
if min_idx is None or idx < min_idx:
|
| 201 |
+
min_idx = idx
|
| 202 |
+
min_delim = d
|
| 203 |
+
|
| 204 |
+
if min_idx is None or min_idx < 0:
|
| 205 |
+
return s, "", None
|
| 206 |
+
|
| 207 |
+
return s[:min_idx], s[min_idx + 1 :], min_delim
|
| 208 |
+
|
| 209 |
+
|
| 210 |
+
def _encode_invalid_chars(component, allowed_chars, encoding="utf-8"):
|
| 211 |
+
"""Percent-encodes a URI component without reapplying
|
| 212 |
+
onto an already percent-encoded component.
|
| 213 |
+
"""
|
| 214 |
+
if component is None:
|
| 215 |
+
return component
|
| 216 |
+
|
| 217 |
+
component = six.ensure_text(component)
|
| 218 |
+
|
| 219 |
+
# Normalize existing percent-encoded bytes.
|
| 220 |
+
# Try to see if the component we're encoding is already percent-encoded
|
| 221 |
+
# so we can skip all '%' characters but still encode all others.
|
| 222 |
+
component, percent_encodings = PERCENT_RE.subn(
|
| 223 |
+
lambda match: match.group(0).upper(), component
|
| 224 |
+
)
|
| 225 |
+
|
| 226 |
+
uri_bytes = component.encode("utf-8", "surrogatepass")
|
| 227 |
+
is_percent_encoded = percent_encodings == uri_bytes.count(b"%")
|
| 228 |
+
encoded_component = bytearray()
|
| 229 |
+
|
| 230 |
+
for i in range(0, len(uri_bytes)):
|
| 231 |
+
# Will return a single character bytestring on both Python 2 & 3
|
| 232 |
+
byte = uri_bytes[i : i + 1]
|
| 233 |
+
byte_ord = ord(byte)
|
| 234 |
+
if (is_percent_encoded and byte == b"%") or (
|
| 235 |
+
byte_ord < 128 and byte.decode() in allowed_chars
|
| 236 |
+
):
|
| 237 |
+
encoded_component += byte
|
| 238 |
+
continue
|
| 239 |
+
encoded_component.extend(b"%" + (hex(byte_ord)[2:].encode().zfill(2).upper()))
|
| 240 |
+
|
| 241 |
+
return encoded_component.decode(encoding)
|
| 242 |
+
|
| 243 |
+
|
| 244 |
+
def _remove_path_dot_segments(path):
|
| 245 |
+
# See http://tools.ietf.org/html/rfc3986#section-5.2.4 for pseudo-code
|
| 246 |
+
segments = path.split("/") # Turn the path into a list of segments
|
| 247 |
+
output = [] # Initialize the variable to use to store output
|
| 248 |
+
|
| 249 |
+
for segment in segments:
|
| 250 |
+
# '.' is the current directory, so ignore it, it is superfluous
|
| 251 |
+
if segment == ".":
|
| 252 |
+
continue
|
| 253 |
+
# Anything other than '..', should be appended to the output
|
| 254 |
+
elif segment != "..":
|
| 255 |
+
output.append(segment)
|
| 256 |
+
# In this case segment == '..', if we can, we should pop the last
|
| 257 |
+
# element
|
| 258 |
+
elif output:
|
| 259 |
+
output.pop()
|
| 260 |
+
|
| 261 |
+
# If the path starts with '/' and the output is empty or the first string
|
| 262 |
+
# is non-empty
|
| 263 |
+
if path.startswith("/") and (not output or output[0]):
|
| 264 |
+
output.insert(0, "")
|
| 265 |
+
|
| 266 |
+
# If the path starts with '/.' or '/..' ensure we add one more empty
|
| 267 |
+
# string to add a trailing '/'
|
| 268 |
+
if path.endswith(("/.", "/..")):
|
| 269 |
+
output.append("")
|
| 270 |
+
|
| 271 |
+
return "/".join(output)
|
| 272 |
+
|
| 273 |
+
|
| 274 |
+
def _normalize_host(host, scheme):
|
| 275 |
+
if host:
|
| 276 |
+
if isinstance(host, six.binary_type):
|
| 277 |
+
host = six.ensure_str(host)
|
| 278 |
+
|
| 279 |
+
if scheme in NORMALIZABLE_SCHEMES:
|
| 280 |
+
is_ipv6 = IPV6_ADDRZ_RE.match(host)
|
| 281 |
+
if is_ipv6:
|
| 282 |
+
# IPv6 hosts of the form 'a::b%zone' are encoded in a URL as
|
| 283 |
+
# such per RFC 6874: 'a::b%25zone'. Unquote the ZoneID
|
| 284 |
+
# separator as necessary to return a valid RFC 4007 scoped IP.
|
| 285 |
+
match = ZONE_ID_RE.search(host)
|
| 286 |
+
if match:
|
| 287 |
+
start, end = match.span(1)
|
| 288 |
+
zone_id = host[start:end]
|
| 289 |
+
|
| 290 |
+
if zone_id.startswith("%25") and zone_id != "%25":
|
| 291 |
+
zone_id = zone_id[3:]
|
| 292 |
+
else:
|
| 293 |
+
zone_id = zone_id[1:]
|
| 294 |
+
zone_id = "%" + _encode_invalid_chars(zone_id, UNRESERVED_CHARS)
|
| 295 |
+
return host[:start].lower() + zone_id + host[end:]
|
| 296 |
+
else:
|
| 297 |
+
return host.lower()
|
| 298 |
+
elif not IPV4_RE.match(host):
|
| 299 |
+
return six.ensure_str(
|
| 300 |
+
b".".join([_idna_encode(label) for label in host.split(".")])
|
| 301 |
+
)
|
| 302 |
+
return host
|
| 303 |
+
|
| 304 |
+
|
| 305 |
+
def _idna_encode(name):
|
| 306 |
+
if name and any(ord(x) >= 128 for x in name):
|
| 307 |
+
try:
|
| 308 |
+
from pip._vendor import idna
|
| 309 |
+
except ImportError:
|
| 310 |
+
six.raise_from(
|
| 311 |
+
LocationParseError("Unable to parse URL without the 'idna' module"),
|
| 312 |
+
None,
|
| 313 |
+
)
|
| 314 |
+
try:
|
| 315 |
+
return idna.encode(name.lower(), strict=True, std3_rules=True)
|
| 316 |
+
except idna.IDNAError:
|
| 317 |
+
six.raise_from(
|
| 318 |
+
LocationParseError(u"Name '%s' is not a valid IDNA label" % name), None
|
| 319 |
+
)
|
| 320 |
+
return name.lower().encode("ascii")
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
def _encode_target(target):
|
| 324 |
+
"""Percent-encodes a request target so that there are no invalid characters"""
|
| 325 |
+
path, query = TARGET_RE.match(target).groups()
|
| 326 |
+
target = _encode_invalid_chars(path, PATH_CHARS)
|
| 327 |
+
query = _encode_invalid_chars(query, QUERY_CHARS)
|
| 328 |
+
if query is not None:
|
| 329 |
+
target += "?" + query
|
| 330 |
+
return target
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
def parse_url(url):
|
| 334 |
+
"""
|
| 335 |
+
Given a url, return a parsed :class:`.Url` namedtuple. Best-effort is
|
| 336 |
+
performed to parse incomplete urls. Fields not provided will be None.
|
| 337 |
+
This parser is RFC 3986 and RFC 6874 compliant.
|
| 338 |
+
|
| 339 |
+
The parser logic and helper functions are based heavily on
|
| 340 |
+
work done in the ``rfc3986`` module.
|
| 341 |
+
|
| 342 |
+
:param str url: URL to parse into a :class:`.Url` namedtuple.
|
| 343 |
+
|
| 344 |
+
Partly backwards-compatible with :mod:`urlparse`.
|
| 345 |
+
|
| 346 |
+
Example::
|
| 347 |
+
|
| 348 |
+
>>> parse_url('http://google.com/mail/')
|
| 349 |
+
Url(scheme='http', host='google.com', port=None, path='/mail/', ...)
|
| 350 |
+
>>> parse_url('google.com:80')
|
| 351 |
+
Url(scheme=None, host='google.com', port=80, path=None, ...)
|
| 352 |
+
>>> parse_url('/foo?bar')
|
| 353 |
+
Url(scheme=None, host=None, port=None, path='/foo', query='bar', ...)
|
| 354 |
+
"""
|
| 355 |
+
if not url:
|
| 356 |
+
# Empty
|
| 357 |
+
return Url()
|
| 358 |
+
|
| 359 |
+
source_url = url
|
| 360 |
+
if not SCHEME_RE.search(url):
|
| 361 |
+
url = "//" + url
|
| 362 |
+
|
| 363 |
+
try:
|
| 364 |
+
scheme, authority, path, query, fragment = URI_RE.match(url).groups()
|
| 365 |
+
normalize_uri = scheme is None or scheme.lower() in NORMALIZABLE_SCHEMES
|
| 366 |
+
|
| 367 |
+
if scheme:
|
| 368 |
+
scheme = scheme.lower()
|
| 369 |
+
|
| 370 |
+
if authority:
|
| 371 |
+
auth, _, host_port = authority.rpartition("@")
|
| 372 |
+
auth = auth or None
|
| 373 |
+
host, port = _HOST_PORT_RE.match(host_port).groups()
|
| 374 |
+
if auth and normalize_uri:
|
| 375 |
+
auth = _encode_invalid_chars(auth, USERINFO_CHARS)
|
| 376 |
+
if port == "":
|
| 377 |
+
port = None
|
| 378 |
+
else:
|
| 379 |
+
auth, host, port = None, None, None
|
| 380 |
+
|
| 381 |
+
if port is not None:
|
| 382 |
+
port = int(port)
|
| 383 |
+
if not (0 <= port <= 65535):
|
| 384 |
+
raise LocationParseError(url)
|
| 385 |
+
|
| 386 |
+
host = _normalize_host(host, scheme)
|
| 387 |
+
|
| 388 |
+
if normalize_uri and path:
|
| 389 |
+
path = _remove_path_dot_segments(path)
|
| 390 |
+
path = _encode_invalid_chars(path, PATH_CHARS)
|
| 391 |
+
if normalize_uri and query:
|
| 392 |
+
query = _encode_invalid_chars(query, QUERY_CHARS)
|
| 393 |
+
if normalize_uri and fragment:
|
| 394 |
+
fragment = _encode_invalid_chars(fragment, FRAGMENT_CHARS)
|
| 395 |
+
|
| 396 |
+
except (ValueError, AttributeError):
|
| 397 |
+
return six.raise_from(LocationParseError(source_url), None)
|
| 398 |
+
|
| 399 |
+
# For the sake of backwards compatibility we put empty
|
| 400 |
+
# string values for path if there are any defined values
|
| 401 |
+
# beyond the path in the URL.
|
| 402 |
+
# TODO: Remove this when we break backwards compatibility.
|
| 403 |
+
if not path:
|
| 404 |
+
if query is not None or fragment is not None:
|
| 405 |
+
path = ""
|
| 406 |
+
else:
|
| 407 |
+
path = None
|
| 408 |
+
|
| 409 |
+
# Ensure that each part of the URL is a `str` for
|
| 410 |
+
# backwards compatibility.
|
| 411 |
+
if isinstance(url, six.text_type):
|
| 412 |
+
ensure_func = six.ensure_text
|
| 413 |
+
else:
|
| 414 |
+
ensure_func = six.ensure_str
|
| 415 |
+
|
| 416 |
+
def ensure_type(x):
|
| 417 |
+
return x if x is None else ensure_func(x)
|
| 418 |
+
|
| 419 |
+
return Url(
|
| 420 |
+
scheme=ensure_type(scheme),
|
| 421 |
+
auth=ensure_type(auth),
|
| 422 |
+
host=ensure_type(host),
|
| 423 |
+
port=port,
|
| 424 |
+
path=ensure_type(path),
|
| 425 |
+
query=ensure_type(query),
|
| 426 |
+
fragment=ensure_type(fragment),
|
| 427 |
+
)
|
| 428 |
+
|
| 429 |
+
|
| 430 |
+
def get_host(url):
|
| 431 |
+
"""
|
| 432 |
+
Deprecated. Use :func:`parse_url` instead.
|
| 433 |
+
"""
|
| 434 |
+
p = parse_url(url)
|
| 435 |
+
return p.scheme or "http", p.hostname, p.port
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/urllib3/util/wait.py
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import errno
|
| 2 |
+
import select
|
| 3 |
+
import sys
|
| 4 |
+
from functools import partial
|
| 5 |
+
|
| 6 |
+
try:
|
| 7 |
+
from time import monotonic
|
| 8 |
+
except ImportError:
|
| 9 |
+
from time import time as monotonic
|
| 10 |
+
|
| 11 |
+
__all__ = ["NoWayToWaitForSocketError", "wait_for_read", "wait_for_write"]
|
| 12 |
+
|
| 13 |
+
|
| 14 |
+
class NoWayToWaitForSocketError(Exception):
|
| 15 |
+
pass
|
| 16 |
+
|
| 17 |
+
|
| 18 |
+
# How should we wait on sockets?
|
| 19 |
+
#
|
| 20 |
+
# There are two types of APIs you can use for waiting on sockets: the fancy
|
| 21 |
+
# modern stateful APIs like epoll/kqueue, and the older stateless APIs like
|
| 22 |
+
# select/poll. The stateful APIs are more efficient when you have a lots of
|
| 23 |
+
# sockets to keep track of, because you can set them up once and then use them
|
| 24 |
+
# lots of times. But we only ever want to wait on a single socket at a time
|
| 25 |
+
# and don't want to keep track of state, so the stateless APIs are actually
|
| 26 |
+
# more efficient. So we want to use select() or poll().
|
| 27 |
+
#
|
| 28 |
+
# Now, how do we choose between select() and poll()? On traditional Unixes,
|
| 29 |
+
# select() has a strange calling convention that makes it slow, or fail
|
| 30 |
+
# altogether, for high-numbered file descriptors. The point of poll() is to fix
|
| 31 |
+
# that, so on Unixes, we prefer poll().
|
| 32 |
+
#
|
| 33 |
+
# On Windows, there is no poll() (or at least Python doesn't provide a wrapper
|
| 34 |
+
# for it), but that's OK, because on Windows, select() doesn't have this
|
| 35 |
+
# strange calling convention; plain select() works fine.
|
| 36 |
+
#
|
| 37 |
+
# So: on Windows we use select(), and everywhere else we use poll(). We also
|
| 38 |
+
# fall back to select() in case poll() is somehow broken or missing.
|
| 39 |
+
|
| 40 |
+
if sys.version_info >= (3, 5):
|
| 41 |
+
# Modern Python, that retries syscalls by default
|
| 42 |
+
def _retry_on_intr(fn, timeout):
|
| 43 |
+
return fn(timeout)
|
| 44 |
+
|
| 45 |
+
else:
|
| 46 |
+
# Old and broken Pythons.
|
| 47 |
+
def _retry_on_intr(fn, timeout):
|
| 48 |
+
if timeout is None:
|
| 49 |
+
deadline = float("inf")
|
| 50 |
+
else:
|
| 51 |
+
deadline = monotonic() + timeout
|
| 52 |
+
|
| 53 |
+
while True:
|
| 54 |
+
try:
|
| 55 |
+
return fn(timeout)
|
| 56 |
+
# OSError for 3 <= pyver < 3.5, select.error for pyver <= 2.7
|
| 57 |
+
except (OSError, select.error) as e:
|
| 58 |
+
# 'e.args[0]' incantation works for both OSError and select.error
|
| 59 |
+
if e.args[0] != errno.EINTR:
|
| 60 |
+
raise
|
| 61 |
+
else:
|
| 62 |
+
timeout = deadline - monotonic()
|
| 63 |
+
if timeout < 0:
|
| 64 |
+
timeout = 0
|
| 65 |
+
if timeout == float("inf"):
|
| 66 |
+
timeout = None
|
| 67 |
+
continue
|
| 68 |
+
|
| 69 |
+
|
| 70 |
+
def select_wait_for_socket(sock, read=False, write=False, timeout=None):
|
| 71 |
+
if not read and not write:
|
| 72 |
+
raise RuntimeError("must specify at least one of read=True, write=True")
|
| 73 |
+
rcheck = []
|
| 74 |
+
wcheck = []
|
| 75 |
+
if read:
|
| 76 |
+
rcheck.append(sock)
|
| 77 |
+
if write:
|
| 78 |
+
wcheck.append(sock)
|
| 79 |
+
# When doing a non-blocking connect, most systems signal success by
|
| 80 |
+
# marking the socket writable. Windows, though, signals success by marked
|
| 81 |
+
# it as "exceptional". We paper over the difference by checking the write
|
| 82 |
+
# sockets for both conditions. (The stdlib selectors module does the same
|
| 83 |
+
# thing.)
|
| 84 |
+
fn = partial(select.select, rcheck, wcheck, wcheck)
|
| 85 |
+
rready, wready, xready = _retry_on_intr(fn, timeout)
|
| 86 |
+
return bool(rready or wready or xready)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
def poll_wait_for_socket(sock, read=False, write=False, timeout=None):
|
| 90 |
+
if not read and not write:
|
| 91 |
+
raise RuntimeError("must specify at least one of read=True, write=True")
|
| 92 |
+
mask = 0
|
| 93 |
+
if read:
|
| 94 |
+
mask |= select.POLLIN
|
| 95 |
+
if write:
|
| 96 |
+
mask |= select.POLLOUT
|
| 97 |
+
poll_obj = select.poll()
|
| 98 |
+
poll_obj.register(sock, mask)
|
| 99 |
+
|
| 100 |
+
# For some reason, poll() takes timeout in milliseconds
|
| 101 |
+
def do_poll(t):
|
| 102 |
+
if t is not None:
|
| 103 |
+
t *= 1000
|
| 104 |
+
return poll_obj.poll(t)
|
| 105 |
+
|
| 106 |
+
return bool(_retry_on_intr(do_poll, timeout))
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
def null_wait_for_socket(*args, **kwargs):
|
| 110 |
+
raise NoWayToWaitForSocketError("no select-equivalent available")
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
def _have_working_poll():
|
| 114 |
+
# Apparently some systems have a select.poll that fails as soon as you try
|
| 115 |
+
# to use it, either due to strange configuration or broken monkeypatching
|
| 116 |
+
# from libraries like eventlet/greenlet.
|
| 117 |
+
try:
|
| 118 |
+
poll_obj = select.poll()
|
| 119 |
+
_retry_on_intr(poll_obj.poll, 0)
|
| 120 |
+
except (AttributeError, OSError):
|
| 121 |
+
return False
|
| 122 |
+
else:
|
| 123 |
+
return True
|
| 124 |
+
|
| 125 |
+
|
| 126 |
+
def wait_for_socket(*args, **kwargs):
|
| 127 |
+
# We delay choosing which implementation to use until the first time we're
|
| 128 |
+
# called. We could do it at import time, but then we might make the wrong
|
| 129 |
+
# decision if someone goes wild with monkeypatching select.poll after
|
| 130 |
+
# we're imported.
|
| 131 |
+
global wait_for_socket
|
| 132 |
+
if _have_working_poll():
|
| 133 |
+
wait_for_socket = poll_wait_for_socket
|
| 134 |
+
elif hasattr(select, "select"):
|
| 135 |
+
wait_for_socket = select_wait_for_socket
|
| 136 |
+
else: # Platform-specific: Appengine.
|
| 137 |
+
wait_for_socket = null_wait_for_socket
|
| 138 |
+
return wait_for_socket(*args, **kwargs)
|
| 139 |
+
|
| 140 |
+
|
| 141 |
+
def wait_for_read(sock, timeout=None):
|
| 142 |
+
"""Waits for reading to be available on a given socket.
|
| 143 |
+
Returns True if the socket is readable, or False if the timeout expired.
|
| 144 |
+
"""
|
| 145 |
+
return wait_for_socket(sock, read=True, timeout=timeout)
|
| 146 |
+
|
| 147 |
+
|
| 148 |
+
def wait_for_write(sock, timeout=None):
|
| 149 |
+
"""Waits for writing to be available on a given socket.
|
| 150 |
+
Returns True if the socket is readable, or False if the timeout expired.
|
| 151 |
+
"""
|
| 152 |
+
return wait_for_socket(sock, write=True, timeout=timeout)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/vendor.txt
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
CacheControl==0.13.1 # Make sure to update the license in pyproject.toml for this.
|
| 2 |
+
colorama==0.4.6
|
| 3 |
+
distlib==0.3.8
|
| 4 |
+
distro==1.8.0
|
| 5 |
+
msgpack==1.0.5
|
| 6 |
+
packaging==21.3
|
| 7 |
+
platformdirs==3.8.1
|
| 8 |
+
pyparsing==3.1.0
|
| 9 |
+
pyproject-hooks==1.0.0
|
| 10 |
+
requests==2.31.0
|
| 11 |
+
certifi==2023.7.22
|
| 12 |
+
chardet==5.1.0
|
| 13 |
+
idna==3.4
|
| 14 |
+
urllib3==1.26.17
|
| 15 |
+
rich==13.4.2
|
| 16 |
+
pygments==2.15.1
|
| 17 |
+
typing_extensions==4.7.1
|
| 18 |
+
resolvelib==1.0.1
|
| 19 |
+
setuptools==68.0.0
|
| 20 |
+
six==1.16.0
|
| 21 |
+
tenacity==8.2.2
|
| 22 |
+
tomli==2.0.1
|
| 23 |
+
truststore==0.8.0
|
| 24 |
+
webencodings==0.5.1
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/__init__.py
ADDED
|
@@ -0,0 +1,342 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
"""
|
| 3 |
+
|
| 4 |
+
webencodings
|
| 5 |
+
~~~~~~~~~~~~
|
| 6 |
+
|
| 7 |
+
This is a Python implementation of the `WHATWG Encoding standard
|
| 8 |
+
<http://encoding.spec.whatwg.org/>`. See README for details.
|
| 9 |
+
|
| 10 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 11 |
+
:license: BSD, see LICENSE for details.
|
| 12 |
+
|
| 13 |
+
"""
|
| 14 |
+
|
| 15 |
+
from __future__ import unicode_literals
|
| 16 |
+
|
| 17 |
+
import codecs
|
| 18 |
+
|
| 19 |
+
from .labels import LABELS
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
VERSION = '0.5.1'
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# Some names in Encoding are not valid Python aliases. Remap these.
|
| 26 |
+
PYTHON_NAMES = {
|
| 27 |
+
'iso-8859-8-i': 'iso-8859-8',
|
| 28 |
+
'x-mac-cyrillic': 'mac-cyrillic',
|
| 29 |
+
'macintosh': 'mac-roman',
|
| 30 |
+
'windows-874': 'cp874'}
|
| 31 |
+
|
| 32 |
+
CACHE = {}
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
def ascii_lower(string):
|
| 36 |
+
r"""Transform (only) ASCII letters to lower case: A-Z is mapped to a-z.
|
| 37 |
+
|
| 38 |
+
:param string: An Unicode string.
|
| 39 |
+
:returns: A new Unicode string.
|
| 40 |
+
|
| 41 |
+
This is used for `ASCII case-insensitive
|
| 42 |
+
<http://encoding.spec.whatwg.org/#ascii-case-insensitive>`_
|
| 43 |
+
matching of encoding labels.
|
| 44 |
+
The same matching is also used, among other things,
|
| 45 |
+
for `CSS keywords <http://dev.w3.org/csswg/css-values/#keywords>`_.
|
| 46 |
+
|
| 47 |
+
This is different from the :meth:`~py:str.lower` method of Unicode strings
|
| 48 |
+
which also affect non-ASCII characters,
|
| 49 |
+
sometimes mapping them into the ASCII range:
|
| 50 |
+
|
| 51 |
+
>>> keyword = u'Bac\N{KELVIN SIGN}ground'
|
| 52 |
+
>>> assert keyword.lower() == u'background'
|
| 53 |
+
>>> assert ascii_lower(keyword) != keyword.lower()
|
| 54 |
+
>>> assert ascii_lower(keyword) == u'bac\N{KELVIN SIGN}ground'
|
| 55 |
+
|
| 56 |
+
"""
|
| 57 |
+
# This turns out to be faster than unicode.translate()
|
| 58 |
+
return string.encode('utf8').lower().decode('utf8')
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
def lookup(label):
|
| 62 |
+
"""
|
| 63 |
+
Look for an encoding by its label.
|
| 64 |
+
This is the spec’s `get an encoding
|
| 65 |
+
<http://encoding.spec.whatwg.org/#concept-encoding-get>`_ algorithm.
|
| 66 |
+
Supported labels are listed there.
|
| 67 |
+
|
| 68 |
+
:param label: A string.
|
| 69 |
+
:returns:
|
| 70 |
+
An :class:`Encoding` object, or :obj:`None` for an unknown label.
|
| 71 |
+
|
| 72 |
+
"""
|
| 73 |
+
# Only strip ASCII whitespace: U+0009, U+000A, U+000C, U+000D, and U+0020.
|
| 74 |
+
label = ascii_lower(label.strip('\t\n\f\r '))
|
| 75 |
+
name = LABELS.get(label)
|
| 76 |
+
if name is None:
|
| 77 |
+
return None
|
| 78 |
+
encoding = CACHE.get(name)
|
| 79 |
+
if encoding is None:
|
| 80 |
+
if name == 'x-user-defined':
|
| 81 |
+
from .x_user_defined import codec_info
|
| 82 |
+
else:
|
| 83 |
+
python_name = PYTHON_NAMES.get(name, name)
|
| 84 |
+
# Any python_name value that gets to here should be valid.
|
| 85 |
+
codec_info = codecs.lookup(python_name)
|
| 86 |
+
encoding = Encoding(name, codec_info)
|
| 87 |
+
CACHE[name] = encoding
|
| 88 |
+
return encoding
|
| 89 |
+
|
| 90 |
+
|
| 91 |
+
def _get_encoding(encoding_or_label):
|
| 92 |
+
"""
|
| 93 |
+
Accept either an encoding object or label.
|
| 94 |
+
|
| 95 |
+
:param encoding: An :class:`Encoding` object or a label string.
|
| 96 |
+
:returns: An :class:`Encoding` object.
|
| 97 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown label.
|
| 98 |
+
|
| 99 |
+
"""
|
| 100 |
+
if hasattr(encoding_or_label, 'codec_info'):
|
| 101 |
+
return encoding_or_label
|
| 102 |
+
|
| 103 |
+
encoding = lookup(encoding_or_label)
|
| 104 |
+
if encoding is None:
|
| 105 |
+
raise LookupError('Unknown encoding label: %r' % encoding_or_label)
|
| 106 |
+
return encoding
|
| 107 |
+
|
| 108 |
+
|
| 109 |
+
class Encoding(object):
|
| 110 |
+
"""Reresents a character encoding such as UTF-8,
|
| 111 |
+
that can be used for decoding or encoding.
|
| 112 |
+
|
| 113 |
+
.. attribute:: name
|
| 114 |
+
|
| 115 |
+
Canonical name of the encoding
|
| 116 |
+
|
| 117 |
+
.. attribute:: codec_info
|
| 118 |
+
|
| 119 |
+
The actual implementation of the encoding,
|
| 120 |
+
a stdlib :class:`~codecs.CodecInfo` object.
|
| 121 |
+
See :func:`codecs.register`.
|
| 122 |
+
|
| 123 |
+
"""
|
| 124 |
+
def __init__(self, name, codec_info):
|
| 125 |
+
self.name = name
|
| 126 |
+
self.codec_info = codec_info
|
| 127 |
+
|
| 128 |
+
def __repr__(self):
|
| 129 |
+
return '<Encoding %s>' % self.name
|
| 130 |
+
|
| 131 |
+
|
| 132 |
+
#: The UTF-8 encoding. Should be used for new content and formats.
|
| 133 |
+
UTF8 = lookup('utf-8')
|
| 134 |
+
|
| 135 |
+
_UTF16LE = lookup('utf-16le')
|
| 136 |
+
_UTF16BE = lookup('utf-16be')
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
def decode(input, fallback_encoding, errors='replace'):
|
| 140 |
+
"""
|
| 141 |
+
Decode a single string.
|
| 142 |
+
|
| 143 |
+
:param input: A byte string
|
| 144 |
+
:param fallback_encoding:
|
| 145 |
+
An :class:`Encoding` object or a label string.
|
| 146 |
+
The encoding to use if :obj:`input` does note have a BOM.
|
| 147 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 148 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 149 |
+
:return:
|
| 150 |
+
A ``(output, encoding)`` tuple of an Unicode string
|
| 151 |
+
and an :obj:`Encoding`.
|
| 152 |
+
|
| 153 |
+
"""
|
| 154 |
+
# Fail early if `encoding` is an invalid label.
|
| 155 |
+
fallback_encoding = _get_encoding(fallback_encoding)
|
| 156 |
+
bom_encoding, input = _detect_bom(input)
|
| 157 |
+
encoding = bom_encoding or fallback_encoding
|
| 158 |
+
return encoding.codec_info.decode(input, errors)[0], encoding
|
| 159 |
+
|
| 160 |
+
|
| 161 |
+
def _detect_bom(input):
|
| 162 |
+
"""Return (bom_encoding, input), with any BOM removed from the input."""
|
| 163 |
+
if input.startswith(b'\xFF\xFE'):
|
| 164 |
+
return _UTF16LE, input[2:]
|
| 165 |
+
if input.startswith(b'\xFE\xFF'):
|
| 166 |
+
return _UTF16BE, input[2:]
|
| 167 |
+
if input.startswith(b'\xEF\xBB\xBF'):
|
| 168 |
+
return UTF8, input[3:]
|
| 169 |
+
return None, input
|
| 170 |
+
|
| 171 |
+
|
| 172 |
+
def encode(input, encoding=UTF8, errors='strict'):
|
| 173 |
+
"""
|
| 174 |
+
Encode a single string.
|
| 175 |
+
|
| 176 |
+
:param input: An Unicode string.
|
| 177 |
+
:param encoding: An :class:`Encoding` object or a label string.
|
| 178 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 179 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 180 |
+
:return: A byte string.
|
| 181 |
+
|
| 182 |
+
"""
|
| 183 |
+
return _get_encoding(encoding).codec_info.encode(input, errors)[0]
|
| 184 |
+
|
| 185 |
+
|
| 186 |
+
def iter_decode(input, fallback_encoding, errors='replace'):
|
| 187 |
+
"""
|
| 188 |
+
"Pull"-based decoder.
|
| 189 |
+
|
| 190 |
+
:param input:
|
| 191 |
+
An iterable of byte strings.
|
| 192 |
+
|
| 193 |
+
The input is first consumed just enough to determine the encoding
|
| 194 |
+
based on the precense of a BOM,
|
| 195 |
+
then consumed on demand when the return value is.
|
| 196 |
+
:param fallback_encoding:
|
| 197 |
+
An :class:`Encoding` object or a label string.
|
| 198 |
+
The encoding to use if :obj:`input` does note have a BOM.
|
| 199 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 200 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 201 |
+
:returns:
|
| 202 |
+
An ``(output, encoding)`` tuple.
|
| 203 |
+
:obj:`output` is an iterable of Unicode strings,
|
| 204 |
+
:obj:`encoding` is the :obj:`Encoding` that is being used.
|
| 205 |
+
|
| 206 |
+
"""
|
| 207 |
+
|
| 208 |
+
decoder = IncrementalDecoder(fallback_encoding, errors)
|
| 209 |
+
generator = _iter_decode_generator(input, decoder)
|
| 210 |
+
encoding = next(generator)
|
| 211 |
+
return generator, encoding
|
| 212 |
+
|
| 213 |
+
|
| 214 |
+
def _iter_decode_generator(input, decoder):
|
| 215 |
+
"""Return a generator that first yields the :obj:`Encoding`,
|
| 216 |
+
then yields output chukns as Unicode strings.
|
| 217 |
+
|
| 218 |
+
"""
|
| 219 |
+
decode = decoder.decode
|
| 220 |
+
input = iter(input)
|
| 221 |
+
for chunck in input:
|
| 222 |
+
output = decode(chunck)
|
| 223 |
+
if output:
|
| 224 |
+
assert decoder.encoding is not None
|
| 225 |
+
yield decoder.encoding
|
| 226 |
+
yield output
|
| 227 |
+
break
|
| 228 |
+
else:
|
| 229 |
+
# Input exhausted without determining the encoding
|
| 230 |
+
output = decode(b'', final=True)
|
| 231 |
+
assert decoder.encoding is not None
|
| 232 |
+
yield decoder.encoding
|
| 233 |
+
if output:
|
| 234 |
+
yield output
|
| 235 |
+
return
|
| 236 |
+
|
| 237 |
+
for chunck in input:
|
| 238 |
+
output = decode(chunck)
|
| 239 |
+
if output:
|
| 240 |
+
yield output
|
| 241 |
+
output = decode(b'', final=True)
|
| 242 |
+
if output:
|
| 243 |
+
yield output
|
| 244 |
+
|
| 245 |
+
|
| 246 |
+
def iter_encode(input, encoding=UTF8, errors='strict'):
|
| 247 |
+
"""
|
| 248 |
+
“Pull”-based encoder.
|
| 249 |
+
|
| 250 |
+
:param input: An iterable of Unicode strings.
|
| 251 |
+
:param encoding: An :class:`Encoding` object or a label string.
|
| 252 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 253 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 254 |
+
:returns: An iterable of byte strings.
|
| 255 |
+
|
| 256 |
+
"""
|
| 257 |
+
# Fail early if `encoding` is an invalid label.
|
| 258 |
+
encode = IncrementalEncoder(encoding, errors).encode
|
| 259 |
+
return _iter_encode_generator(input, encode)
|
| 260 |
+
|
| 261 |
+
|
| 262 |
+
def _iter_encode_generator(input, encode):
|
| 263 |
+
for chunck in input:
|
| 264 |
+
output = encode(chunck)
|
| 265 |
+
if output:
|
| 266 |
+
yield output
|
| 267 |
+
output = encode('', final=True)
|
| 268 |
+
if output:
|
| 269 |
+
yield output
|
| 270 |
+
|
| 271 |
+
|
| 272 |
+
class IncrementalDecoder(object):
|
| 273 |
+
"""
|
| 274 |
+
“Push”-based decoder.
|
| 275 |
+
|
| 276 |
+
:param fallback_encoding:
|
| 277 |
+
An :class:`Encoding` object or a label string.
|
| 278 |
+
The encoding to use if :obj:`input` does note have a BOM.
|
| 279 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 280 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 281 |
+
|
| 282 |
+
"""
|
| 283 |
+
def __init__(self, fallback_encoding, errors='replace'):
|
| 284 |
+
# Fail early if `encoding` is an invalid label.
|
| 285 |
+
self._fallback_encoding = _get_encoding(fallback_encoding)
|
| 286 |
+
self._errors = errors
|
| 287 |
+
self._buffer = b''
|
| 288 |
+
self._decoder = None
|
| 289 |
+
#: The actual :class:`Encoding` that is being used,
|
| 290 |
+
#: or :obj:`None` if that is not determined yet.
|
| 291 |
+
#: (Ie. if there is not enough input yet to determine
|
| 292 |
+
#: if there is a BOM.)
|
| 293 |
+
self.encoding = None # Not known yet.
|
| 294 |
+
|
| 295 |
+
def decode(self, input, final=False):
|
| 296 |
+
"""Decode one chunk of the input.
|
| 297 |
+
|
| 298 |
+
:param input: A byte string.
|
| 299 |
+
:param final:
|
| 300 |
+
Indicate that no more input is available.
|
| 301 |
+
Must be :obj:`True` if this is the last call.
|
| 302 |
+
:returns: An Unicode string.
|
| 303 |
+
|
| 304 |
+
"""
|
| 305 |
+
decoder = self._decoder
|
| 306 |
+
if decoder is not None:
|
| 307 |
+
return decoder(input, final)
|
| 308 |
+
|
| 309 |
+
input = self._buffer + input
|
| 310 |
+
encoding, input = _detect_bom(input)
|
| 311 |
+
if encoding is None:
|
| 312 |
+
if len(input) < 3 and not final: # Not enough data yet.
|
| 313 |
+
self._buffer = input
|
| 314 |
+
return ''
|
| 315 |
+
else: # No BOM
|
| 316 |
+
encoding = self._fallback_encoding
|
| 317 |
+
decoder = encoding.codec_info.incrementaldecoder(self._errors).decode
|
| 318 |
+
self._decoder = decoder
|
| 319 |
+
self.encoding = encoding
|
| 320 |
+
return decoder(input, final)
|
| 321 |
+
|
| 322 |
+
|
| 323 |
+
class IncrementalEncoder(object):
|
| 324 |
+
"""
|
| 325 |
+
“Push”-based encoder.
|
| 326 |
+
|
| 327 |
+
:param encoding: An :class:`Encoding` object or a label string.
|
| 328 |
+
:param errors: Type of error handling. See :func:`codecs.register`.
|
| 329 |
+
:raises: :exc:`~exceptions.LookupError` for an unknown encoding label.
|
| 330 |
+
|
| 331 |
+
.. method:: encode(input, final=False)
|
| 332 |
+
|
| 333 |
+
:param input: An Unicode string.
|
| 334 |
+
:param final:
|
| 335 |
+
Indicate that no more input is available.
|
| 336 |
+
Must be :obj:`True` if this is the last call.
|
| 337 |
+
:returns: A byte string.
|
| 338 |
+
|
| 339 |
+
"""
|
| 340 |
+
def __init__(self, encoding=UTF8, errors='strict'):
|
| 341 |
+
encoding = _get_encoding(encoding)
|
| 342 |
+
self.encode = encoding.codec_info.incrementalencoder(errors).encode
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/labels.py
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
|
| 3 |
+
webencodings.labels
|
| 4 |
+
~~~~~~~~~~~~~~~~~~~
|
| 5 |
+
|
| 6 |
+
Map encoding labels to their name.
|
| 7 |
+
|
| 8 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 9 |
+
:license: BSD, see LICENSE for details.
|
| 10 |
+
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
# XXX Do not edit!
|
| 14 |
+
# This file is automatically generated by mklabels.py
|
| 15 |
+
|
| 16 |
+
LABELS = {
|
| 17 |
+
'unicode-1-1-utf-8': 'utf-8',
|
| 18 |
+
'utf-8': 'utf-8',
|
| 19 |
+
'utf8': 'utf-8',
|
| 20 |
+
'866': 'ibm866',
|
| 21 |
+
'cp866': 'ibm866',
|
| 22 |
+
'csibm866': 'ibm866',
|
| 23 |
+
'ibm866': 'ibm866',
|
| 24 |
+
'csisolatin2': 'iso-8859-2',
|
| 25 |
+
'iso-8859-2': 'iso-8859-2',
|
| 26 |
+
'iso-ir-101': 'iso-8859-2',
|
| 27 |
+
'iso8859-2': 'iso-8859-2',
|
| 28 |
+
'iso88592': 'iso-8859-2',
|
| 29 |
+
'iso_8859-2': 'iso-8859-2',
|
| 30 |
+
'iso_8859-2:1987': 'iso-8859-2',
|
| 31 |
+
'l2': 'iso-8859-2',
|
| 32 |
+
'latin2': 'iso-8859-2',
|
| 33 |
+
'csisolatin3': 'iso-8859-3',
|
| 34 |
+
'iso-8859-3': 'iso-8859-3',
|
| 35 |
+
'iso-ir-109': 'iso-8859-3',
|
| 36 |
+
'iso8859-3': 'iso-8859-3',
|
| 37 |
+
'iso88593': 'iso-8859-3',
|
| 38 |
+
'iso_8859-3': 'iso-8859-3',
|
| 39 |
+
'iso_8859-3:1988': 'iso-8859-3',
|
| 40 |
+
'l3': 'iso-8859-3',
|
| 41 |
+
'latin3': 'iso-8859-3',
|
| 42 |
+
'csisolatin4': 'iso-8859-4',
|
| 43 |
+
'iso-8859-4': 'iso-8859-4',
|
| 44 |
+
'iso-ir-110': 'iso-8859-4',
|
| 45 |
+
'iso8859-4': 'iso-8859-4',
|
| 46 |
+
'iso88594': 'iso-8859-4',
|
| 47 |
+
'iso_8859-4': 'iso-8859-4',
|
| 48 |
+
'iso_8859-4:1988': 'iso-8859-4',
|
| 49 |
+
'l4': 'iso-8859-4',
|
| 50 |
+
'latin4': 'iso-8859-4',
|
| 51 |
+
'csisolatincyrillic': 'iso-8859-5',
|
| 52 |
+
'cyrillic': 'iso-8859-5',
|
| 53 |
+
'iso-8859-5': 'iso-8859-5',
|
| 54 |
+
'iso-ir-144': 'iso-8859-5',
|
| 55 |
+
'iso8859-5': 'iso-8859-5',
|
| 56 |
+
'iso88595': 'iso-8859-5',
|
| 57 |
+
'iso_8859-5': 'iso-8859-5',
|
| 58 |
+
'iso_8859-5:1988': 'iso-8859-5',
|
| 59 |
+
'arabic': 'iso-8859-6',
|
| 60 |
+
'asmo-708': 'iso-8859-6',
|
| 61 |
+
'csiso88596e': 'iso-8859-6',
|
| 62 |
+
'csiso88596i': 'iso-8859-6',
|
| 63 |
+
'csisolatinarabic': 'iso-8859-6',
|
| 64 |
+
'ecma-114': 'iso-8859-6',
|
| 65 |
+
'iso-8859-6': 'iso-8859-6',
|
| 66 |
+
'iso-8859-6-e': 'iso-8859-6',
|
| 67 |
+
'iso-8859-6-i': 'iso-8859-6',
|
| 68 |
+
'iso-ir-127': 'iso-8859-6',
|
| 69 |
+
'iso8859-6': 'iso-8859-6',
|
| 70 |
+
'iso88596': 'iso-8859-6',
|
| 71 |
+
'iso_8859-6': 'iso-8859-6',
|
| 72 |
+
'iso_8859-6:1987': 'iso-8859-6',
|
| 73 |
+
'csisolatingreek': 'iso-8859-7',
|
| 74 |
+
'ecma-118': 'iso-8859-7',
|
| 75 |
+
'elot_928': 'iso-8859-7',
|
| 76 |
+
'greek': 'iso-8859-7',
|
| 77 |
+
'greek8': 'iso-8859-7',
|
| 78 |
+
'iso-8859-7': 'iso-8859-7',
|
| 79 |
+
'iso-ir-126': 'iso-8859-7',
|
| 80 |
+
'iso8859-7': 'iso-8859-7',
|
| 81 |
+
'iso88597': 'iso-8859-7',
|
| 82 |
+
'iso_8859-7': 'iso-8859-7',
|
| 83 |
+
'iso_8859-7:1987': 'iso-8859-7',
|
| 84 |
+
'sun_eu_greek': 'iso-8859-7',
|
| 85 |
+
'csiso88598e': 'iso-8859-8',
|
| 86 |
+
'csisolatinhebrew': 'iso-8859-8',
|
| 87 |
+
'hebrew': 'iso-8859-8',
|
| 88 |
+
'iso-8859-8': 'iso-8859-8',
|
| 89 |
+
'iso-8859-8-e': 'iso-8859-8',
|
| 90 |
+
'iso-ir-138': 'iso-8859-8',
|
| 91 |
+
'iso8859-8': 'iso-8859-8',
|
| 92 |
+
'iso88598': 'iso-8859-8',
|
| 93 |
+
'iso_8859-8': 'iso-8859-8',
|
| 94 |
+
'iso_8859-8:1988': 'iso-8859-8',
|
| 95 |
+
'visual': 'iso-8859-8',
|
| 96 |
+
'csiso88598i': 'iso-8859-8-i',
|
| 97 |
+
'iso-8859-8-i': 'iso-8859-8-i',
|
| 98 |
+
'logical': 'iso-8859-8-i',
|
| 99 |
+
'csisolatin6': 'iso-8859-10',
|
| 100 |
+
'iso-8859-10': 'iso-8859-10',
|
| 101 |
+
'iso-ir-157': 'iso-8859-10',
|
| 102 |
+
'iso8859-10': 'iso-8859-10',
|
| 103 |
+
'iso885910': 'iso-8859-10',
|
| 104 |
+
'l6': 'iso-8859-10',
|
| 105 |
+
'latin6': 'iso-8859-10',
|
| 106 |
+
'iso-8859-13': 'iso-8859-13',
|
| 107 |
+
'iso8859-13': 'iso-8859-13',
|
| 108 |
+
'iso885913': 'iso-8859-13',
|
| 109 |
+
'iso-8859-14': 'iso-8859-14',
|
| 110 |
+
'iso8859-14': 'iso-8859-14',
|
| 111 |
+
'iso885914': 'iso-8859-14',
|
| 112 |
+
'csisolatin9': 'iso-8859-15',
|
| 113 |
+
'iso-8859-15': 'iso-8859-15',
|
| 114 |
+
'iso8859-15': 'iso-8859-15',
|
| 115 |
+
'iso885915': 'iso-8859-15',
|
| 116 |
+
'iso_8859-15': 'iso-8859-15',
|
| 117 |
+
'l9': 'iso-8859-15',
|
| 118 |
+
'iso-8859-16': 'iso-8859-16',
|
| 119 |
+
'cskoi8r': 'koi8-r',
|
| 120 |
+
'koi': 'koi8-r',
|
| 121 |
+
'koi8': 'koi8-r',
|
| 122 |
+
'koi8-r': 'koi8-r',
|
| 123 |
+
'koi8_r': 'koi8-r',
|
| 124 |
+
'koi8-u': 'koi8-u',
|
| 125 |
+
'csmacintosh': 'macintosh',
|
| 126 |
+
'mac': 'macintosh',
|
| 127 |
+
'macintosh': 'macintosh',
|
| 128 |
+
'x-mac-roman': 'macintosh',
|
| 129 |
+
'dos-874': 'windows-874',
|
| 130 |
+
'iso-8859-11': 'windows-874',
|
| 131 |
+
'iso8859-11': 'windows-874',
|
| 132 |
+
'iso885911': 'windows-874',
|
| 133 |
+
'tis-620': 'windows-874',
|
| 134 |
+
'windows-874': 'windows-874',
|
| 135 |
+
'cp1250': 'windows-1250',
|
| 136 |
+
'windows-1250': 'windows-1250',
|
| 137 |
+
'x-cp1250': 'windows-1250',
|
| 138 |
+
'cp1251': 'windows-1251',
|
| 139 |
+
'windows-1251': 'windows-1251',
|
| 140 |
+
'x-cp1251': 'windows-1251',
|
| 141 |
+
'ansi_x3.4-1968': 'windows-1252',
|
| 142 |
+
'ascii': 'windows-1252',
|
| 143 |
+
'cp1252': 'windows-1252',
|
| 144 |
+
'cp819': 'windows-1252',
|
| 145 |
+
'csisolatin1': 'windows-1252',
|
| 146 |
+
'ibm819': 'windows-1252',
|
| 147 |
+
'iso-8859-1': 'windows-1252',
|
| 148 |
+
'iso-ir-100': 'windows-1252',
|
| 149 |
+
'iso8859-1': 'windows-1252',
|
| 150 |
+
'iso88591': 'windows-1252',
|
| 151 |
+
'iso_8859-1': 'windows-1252',
|
| 152 |
+
'iso_8859-1:1987': 'windows-1252',
|
| 153 |
+
'l1': 'windows-1252',
|
| 154 |
+
'latin1': 'windows-1252',
|
| 155 |
+
'us-ascii': 'windows-1252',
|
| 156 |
+
'windows-1252': 'windows-1252',
|
| 157 |
+
'x-cp1252': 'windows-1252',
|
| 158 |
+
'cp1253': 'windows-1253',
|
| 159 |
+
'windows-1253': 'windows-1253',
|
| 160 |
+
'x-cp1253': 'windows-1253',
|
| 161 |
+
'cp1254': 'windows-1254',
|
| 162 |
+
'csisolatin5': 'windows-1254',
|
| 163 |
+
'iso-8859-9': 'windows-1254',
|
| 164 |
+
'iso-ir-148': 'windows-1254',
|
| 165 |
+
'iso8859-9': 'windows-1254',
|
| 166 |
+
'iso88599': 'windows-1254',
|
| 167 |
+
'iso_8859-9': 'windows-1254',
|
| 168 |
+
'iso_8859-9:1989': 'windows-1254',
|
| 169 |
+
'l5': 'windows-1254',
|
| 170 |
+
'latin5': 'windows-1254',
|
| 171 |
+
'windows-1254': 'windows-1254',
|
| 172 |
+
'x-cp1254': 'windows-1254',
|
| 173 |
+
'cp1255': 'windows-1255',
|
| 174 |
+
'windows-1255': 'windows-1255',
|
| 175 |
+
'x-cp1255': 'windows-1255',
|
| 176 |
+
'cp1256': 'windows-1256',
|
| 177 |
+
'windows-1256': 'windows-1256',
|
| 178 |
+
'x-cp1256': 'windows-1256',
|
| 179 |
+
'cp1257': 'windows-1257',
|
| 180 |
+
'windows-1257': 'windows-1257',
|
| 181 |
+
'x-cp1257': 'windows-1257',
|
| 182 |
+
'cp1258': 'windows-1258',
|
| 183 |
+
'windows-1258': 'windows-1258',
|
| 184 |
+
'x-cp1258': 'windows-1258',
|
| 185 |
+
'x-mac-cyrillic': 'x-mac-cyrillic',
|
| 186 |
+
'x-mac-ukrainian': 'x-mac-cyrillic',
|
| 187 |
+
'chinese': 'gbk',
|
| 188 |
+
'csgb2312': 'gbk',
|
| 189 |
+
'csiso58gb231280': 'gbk',
|
| 190 |
+
'gb2312': 'gbk',
|
| 191 |
+
'gb_2312': 'gbk',
|
| 192 |
+
'gb_2312-80': 'gbk',
|
| 193 |
+
'gbk': 'gbk',
|
| 194 |
+
'iso-ir-58': 'gbk',
|
| 195 |
+
'x-gbk': 'gbk',
|
| 196 |
+
'gb18030': 'gb18030',
|
| 197 |
+
'hz-gb-2312': 'hz-gb-2312',
|
| 198 |
+
'big5': 'big5',
|
| 199 |
+
'big5-hkscs': 'big5',
|
| 200 |
+
'cn-big5': 'big5',
|
| 201 |
+
'csbig5': 'big5',
|
| 202 |
+
'x-x-big5': 'big5',
|
| 203 |
+
'cseucpkdfmtjapanese': 'euc-jp',
|
| 204 |
+
'euc-jp': 'euc-jp',
|
| 205 |
+
'x-euc-jp': 'euc-jp',
|
| 206 |
+
'csiso2022jp': 'iso-2022-jp',
|
| 207 |
+
'iso-2022-jp': 'iso-2022-jp',
|
| 208 |
+
'csshiftjis': 'shift_jis',
|
| 209 |
+
'ms_kanji': 'shift_jis',
|
| 210 |
+
'shift-jis': 'shift_jis',
|
| 211 |
+
'shift_jis': 'shift_jis',
|
| 212 |
+
'sjis': 'shift_jis',
|
| 213 |
+
'windows-31j': 'shift_jis',
|
| 214 |
+
'x-sjis': 'shift_jis',
|
| 215 |
+
'cseuckr': 'euc-kr',
|
| 216 |
+
'csksc56011987': 'euc-kr',
|
| 217 |
+
'euc-kr': 'euc-kr',
|
| 218 |
+
'iso-ir-149': 'euc-kr',
|
| 219 |
+
'korean': 'euc-kr',
|
| 220 |
+
'ks_c_5601-1987': 'euc-kr',
|
| 221 |
+
'ks_c_5601-1989': 'euc-kr',
|
| 222 |
+
'ksc5601': 'euc-kr',
|
| 223 |
+
'ksc_5601': 'euc-kr',
|
| 224 |
+
'windows-949': 'euc-kr',
|
| 225 |
+
'csiso2022kr': 'iso-2022-kr',
|
| 226 |
+
'iso-2022-kr': 'iso-2022-kr',
|
| 227 |
+
'utf-16be': 'utf-16be',
|
| 228 |
+
'utf-16': 'utf-16le',
|
| 229 |
+
'utf-16le': 'utf-16le',
|
| 230 |
+
'x-user-defined': 'x-user-defined',
|
| 231 |
+
}
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/mklabels.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
|
| 3 |
+
webencodings.mklabels
|
| 4 |
+
~~~~~~~~~~~~~~~~~~~~~
|
| 5 |
+
|
| 6 |
+
Regenarate the webencodings.labels module.
|
| 7 |
+
|
| 8 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 9 |
+
:license: BSD, see LICENSE for details.
|
| 10 |
+
|
| 11 |
+
"""
|
| 12 |
+
|
| 13 |
+
import json
|
| 14 |
+
try:
|
| 15 |
+
from urllib import urlopen
|
| 16 |
+
except ImportError:
|
| 17 |
+
from urllib.request import urlopen
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def assert_lower(string):
|
| 21 |
+
assert string == string.lower()
|
| 22 |
+
return string
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def generate(url):
|
| 26 |
+
parts = ['''\
|
| 27 |
+
"""
|
| 28 |
+
|
| 29 |
+
webencodings.labels
|
| 30 |
+
~~~~~~~~~~~~~~~~~~~
|
| 31 |
+
|
| 32 |
+
Map encoding labels to their name.
|
| 33 |
+
|
| 34 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 35 |
+
:license: BSD, see LICENSE for details.
|
| 36 |
+
|
| 37 |
+
"""
|
| 38 |
+
|
| 39 |
+
# XXX Do not edit!
|
| 40 |
+
# This file is automatically generated by mklabels.py
|
| 41 |
+
|
| 42 |
+
LABELS = {
|
| 43 |
+
''']
|
| 44 |
+
labels = [
|
| 45 |
+
(repr(assert_lower(label)).lstrip('u'),
|
| 46 |
+
repr(encoding['name']).lstrip('u'))
|
| 47 |
+
for category in json.loads(urlopen(url).read().decode('ascii'))
|
| 48 |
+
for encoding in category['encodings']
|
| 49 |
+
for label in encoding['labels']]
|
| 50 |
+
max_len = max(len(label) for label, name in labels)
|
| 51 |
+
parts.extend(
|
| 52 |
+
' %s:%s %s,\n' % (label, ' ' * (max_len - len(label)), name)
|
| 53 |
+
for label, name in labels)
|
| 54 |
+
parts.append('}')
|
| 55 |
+
return ''.join(parts)
|
| 56 |
+
|
| 57 |
+
|
| 58 |
+
if __name__ == '__main__':
|
| 59 |
+
print(generate('http://encoding.spec.whatwg.org/encodings.json'))
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/tests.py
ADDED
|
@@ -0,0 +1,153 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
"""
|
| 3 |
+
|
| 4 |
+
webencodings.tests
|
| 5 |
+
~~~~~~~~~~~~~~~~~~
|
| 6 |
+
|
| 7 |
+
A basic test suite for Encoding.
|
| 8 |
+
|
| 9 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 10 |
+
:license: BSD, see LICENSE for details.
|
| 11 |
+
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import unicode_literals
|
| 15 |
+
|
| 16 |
+
from . import (lookup, LABELS, decode, encode, iter_decode, iter_encode,
|
| 17 |
+
IncrementalDecoder, IncrementalEncoder, UTF8)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def assert_raises(exception, function, *args, **kwargs):
|
| 21 |
+
try:
|
| 22 |
+
function(*args, **kwargs)
|
| 23 |
+
except exception:
|
| 24 |
+
return
|
| 25 |
+
else: # pragma: no cover
|
| 26 |
+
raise AssertionError('Did not raise %s.' % exception)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
def test_labels():
|
| 30 |
+
assert lookup('utf-8').name == 'utf-8'
|
| 31 |
+
assert lookup('Utf-8').name == 'utf-8'
|
| 32 |
+
assert lookup('UTF-8').name == 'utf-8'
|
| 33 |
+
assert lookup('utf8').name == 'utf-8'
|
| 34 |
+
assert lookup('utf8').name == 'utf-8'
|
| 35 |
+
assert lookup('utf8 ').name == 'utf-8'
|
| 36 |
+
assert lookup(' \r\nutf8\t').name == 'utf-8'
|
| 37 |
+
assert lookup('u8') is None # Python label.
|
| 38 |
+
assert lookup('utf-8 ') is None # Non-ASCII white space.
|
| 39 |
+
|
| 40 |
+
assert lookup('US-ASCII').name == 'windows-1252'
|
| 41 |
+
assert lookup('iso-8859-1').name == 'windows-1252'
|
| 42 |
+
assert lookup('latin1').name == 'windows-1252'
|
| 43 |
+
assert lookup('LATIN1').name == 'windows-1252'
|
| 44 |
+
assert lookup('latin-1') is None
|
| 45 |
+
assert lookup('LATİN1') is None # ASCII-only case insensitivity.
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
def test_all_labels():
|
| 49 |
+
for label in LABELS:
|
| 50 |
+
assert decode(b'', label) == ('', lookup(label))
|
| 51 |
+
assert encode('', label) == b''
|
| 52 |
+
for repeat in [0, 1, 12]:
|
| 53 |
+
output, _ = iter_decode([b''] * repeat, label)
|
| 54 |
+
assert list(output) == []
|
| 55 |
+
assert list(iter_encode([''] * repeat, label)) == []
|
| 56 |
+
decoder = IncrementalDecoder(label)
|
| 57 |
+
assert decoder.decode(b'') == ''
|
| 58 |
+
assert decoder.decode(b'', final=True) == ''
|
| 59 |
+
encoder = IncrementalEncoder(label)
|
| 60 |
+
assert encoder.encode('') == b''
|
| 61 |
+
assert encoder.encode('', final=True) == b''
|
| 62 |
+
# All encoding names are valid labels too:
|
| 63 |
+
for name in set(LABELS.values()):
|
| 64 |
+
assert lookup(name).name == name
|
| 65 |
+
|
| 66 |
+
|
| 67 |
+
def test_invalid_label():
|
| 68 |
+
assert_raises(LookupError, decode, b'\xEF\xBB\xBF\xc3\xa9', 'invalid')
|
| 69 |
+
assert_raises(LookupError, encode, 'é', 'invalid')
|
| 70 |
+
assert_raises(LookupError, iter_decode, [], 'invalid')
|
| 71 |
+
assert_raises(LookupError, iter_encode, [], 'invalid')
|
| 72 |
+
assert_raises(LookupError, IncrementalDecoder, 'invalid')
|
| 73 |
+
assert_raises(LookupError, IncrementalEncoder, 'invalid')
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def test_decode():
|
| 77 |
+
assert decode(b'\x80', 'latin1') == ('€', lookup('latin1'))
|
| 78 |
+
assert decode(b'\x80', lookup('latin1')) == ('€', lookup('latin1'))
|
| 79 |
+
assert decode(b'\xc3\xa9', 'utf8') == ('é', lookup('utf8'))
|
| 80 |
+
assert decode(b'\xc3\xa9', UTF8) == ('é', lookup('utf8'))
|
| 81 |
+
assert decode(b'\xc3\xa9', 'ascii') == ('é', lookup('ascii'))
|
| 82 |
+
assert decode(b'\xEF\xBB\xBF\xc3\xa9', 'ascii') == ('é', lookup('utf8')) # UTF-8 with BOM
|
| 83 |
+
|
| 84 |
+
assert decode(b'\xFE\xFF\x00\xe9', 'ascii') == ('é', lookup('utf-16be')) # UTF-16-BE with BOM
|
| 85 |
+
assert decode(b'\xFF\xFE\xe9\x00', 'ascii') == ('é', lookup('utf-16le')) # UTF-16-LE with BOM
|
| 86 |
+
assert decode(b'\xFE\xFF\xe9\x00', 'ascii') == ('\ue900', lookup('utf-16be'))
|
| 87 |
+
assert decode(b'\xFF\xFE\x00\xe9', 'ascii') == ('\ue900', lookup('utf-16le'))
|
| 88 |
+
|
| 89 |
+
assert decode(b'\x00\xe9', 'UTF-16BE') == ('é', lookup('utf-16be'))
|
| 90 |
+
assert decode(b'\xe9\x00', 'UTF-16LE') == ('é', lookup('utf-16le'))
|
| 91 |
+
assert decode(b'\xe9\x00', 'UTF-16') == ('é', lookup('utf-16le'))
|
| 92 |
+
|
| 93 |
+
assert decode(b'\xe9\x00', 'UTF-16BE') == ('\ue900', lookup('utf-16be'))
|
| 94 |
+
assert decode(b'\x00\xe9', 'UTF-16LE') == ('\ue900', lookup('utf-16le'))
|
| 95 |
+
assert decode(b'\x00\xe9', 'UTF-16') == ('\ue900', lookup('utf-16le'))
|
| 96 |
+
|
| 97 |
+
|
| 98 |
+
def test_encode():
|
| 99 |
+
assert encode('é', 'latin1') == b'\xe9'
|
| 100 |
+
assert encode('é', 'utf8') == b'\xc3\xa9'
|
| 101 |
+
assert encode('é', 'utf8') == b'\xc3\xa9'
|
| 102 |
+
assert encode('é', 'utf-16') == b'\xe9\x00'
|
| 103 |
+
assert encode('é', 'utf-16le') == b'\xe9\x00'
|
| 104 |
+
assert encode('é', 'utf-16be') == b'\x00\xe9'
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def test_iter_decode():
|
| 108 |
+
def iter_decode_to_string(input, fallback_encoding):
|
| 109 |
+
output, _encoding = iter_decode(input, fallback_encoding)
|
| 110 |
+
return ''.join(output)
|
| 111 |
+
assert iter_decode_to_string([], 'latin1') == ''
|
| 112 |
+
assert iter_decode_to_string([b''], 'latin1') == ''
|
| 113 |
+
assert iter_decode_to_string([b'\xe9'], 'latin1') == 'é'
|
| 114 |
+
assert iter_decode_to_string([b'hello'], 'latin1') == 'hello'
|
| 115 |
+
assert iter_decode_to_string([b'he', b'llo'], 'latin1') == 'hello'
|
| 116 |
+
assert iter_decode_to_string([b'hell', b'o'], 'latin1') == 'hello'
|
| 117 |
+
assert iter_decode_to_string([b'\xc3\xa9'], 'latin1') == 'é'
|
| 118 |
+
assert iter_decode_to_string([b'\xEF\xBB\xBF\xc3\xa9'], 'latin1') == 'é'
|
| 119 |
+
assert iter_decode_to_string([
|
| 120 |
+
b'\xEF\xBB\xBF', b'\xc3', b'\xa9'], 'latin1') == 'é'
|
| 121 |
+
assert iter_decode_to_string([
|
| 122 |
+
b'\xEF\xBB\xBF', b'a', b'\xc3'], 'latin1') == 'a\uFFFD'
|
| 123 |
+
assert iter_decode_to_string([
|
| 124 |
+
b'', b'\xEF', b'', b'', b'\xBB\xBF\xc3', b'\xa9'], 'latin1') == 'é'
|
| 125 |
+
assert iter_decode_to_string([b'\xEF\xBB\xBF'], 'latin1') == ''
|
| 126 |
+
assert iter_decode_to_string([b'\xEF\xBB'], 'latin1') == 'ï»'
|
| 127 |
+
assert iter_decode_to_string([b'\xFE\xFF\x00\xe9'], 'latin1') == 'é'
|
| 128 |
+
assert iter_decode_to_string([b'\xFF\xFE\xe9\x00'], 'latin1') == 'é'
|
| 129 |
+
assert iter_decode_to_string([
|
| 130 |
+
b'', b'\xFF', b'', b'', b'\xFE\xe9', b'\x00'], 'latin1') == 'é'
|
| 131 |
+
assert iter_decode_to_string([
|
| 132 |
+
b'', b'h\xe9', b'llo'], 'x-user-defined') == 'h\uF7E9llo'
|
| 133 |
+
|
| 134 |
+
|
| 135 |
+
def test_iter_encode():
|
| 136 |
+
assert b''.join(iter_encode([], 'latin1')) == b''
|
| 137 |
+
assert b''.join(iter_encode([''], 'latin1')) == b''
|
| 138 |
+
assert b''.join(iter_encode(['é'], 'latin1')) == b'\xe9'
|
| 139 |
+
assert b''.join(iter_encode(['', 'é', '', ''], 'latin1')) == b'\xe9'
|
| 140 |
+
assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16')) == b'\xe9\x00'
|
| 141 |
+
assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16le')) == b'\xe9\x00'
|
| 142 |
+
assert b''.join(iter_encode(['', 'é', '', ''], 'utf-16be')) == b'\x00\xe9'
|
| 143 |
+
assert b''.join(iter_encode([
|
| 144 |
+
'', 'h\uF7E9', '', 'llo'], 'x-user-defined')) == b'h\xe9llo'
|
| 145 |
+
|
| 146 |
+
|
| 147 |
+
def test_x_user_defined():
|
| 148 |
+
encoded = b'2,\x0c\x0b\x1aO\xd9#\xcb\x0f\xc9\xbbt\xcf\xa8\xca'
|
| 149 |
+
decoded = '2,\x0c\x0b\x1aO\uf7d9#\uf7cb\x0f\uf7c9\uf7bbt\uf7cf\uf7a8\uf7ca'
|
| 150 |
+
encoded = b'aa'
|
| 151 |
+
decoded = 'aa'
|
| 152 |
+
assert decode(encoded, 'x-user-defined') == (decoded, lookup('x-user-defined'))
|
| 153 |
+
assert encode(decoded, 'x-user-defined') == encoded
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/_vendor/webencodings/x_user_defined.py
ADDED
|
@@ -0,0 +1,325 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# coding: utf-8
|
| 2 |
+
"""
|
| 3 |
+
|
| 4 |
+
webencodings.x_user_defined
|
| 5 |
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
| 6 |
+
|
| 7 |
+
An implementation of the x-user-defined encoding.
|
| 8 |
+
|
| 9 |
+
:copyright: Copyright 2012 by Simon Sapin
|
| 10 |
+
:license: BSD, see LICENSE for details.
|
| 11 |
+
|
| 12 |
+
"""
|
| 13 |
+
|
| 14 |
+
from __future__ import unicode_literals
|
| 15 |
+
|
| 16 |
+
import codecs
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
### Codec APIs
|
| 20 |
+
|
| 21 |
+
class Codec(codecs.Codec):
|
| 22 |
+
|
| 23 |
+
def encode(self, input, errors='strict'):
|
| 24 |
+
return codecs.charmap_encode(input, errors, encoding_table)
|
| 25 |
+
|
| 26 |
+
def decode(self, input, errors='strict'):
|
| 27 |
+
return codecs.charmap_decode(input, errors, decoding_table)
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
class IncrementalEncoder(codecs.IncrementalEncoder):
|
| 31 |
+
def encode(self, input, final=False):
|
| 32 |
+
return codecs.charmap_encode(input, self.errors, encoding_table)[0]
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
class IncrementalDecoder(codecs.IncrementalDecoder):
|
| 36 |
+
def decode(self, input, final=False):
|
| 37 |
+
return codecs.charmap_decode(input, self.errors, decoding_table)[0]
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class StreamWriter(Codec, codecs.StreamWriter):
|
| 41 |
+
pass
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
class StreamReader(Codec, codecs.StreamReader):
|
| 45 |
+
pass
|
| 46 |
+
|
| 47 |
+
|
| 48 |
+
### encodings module API
|
| 49 |
+
|
| 50 |
+
codec_info = codecs.CodecInfo(
|
| 51 |
+
name='x-user-defined',
|
| 52 |
+
encode=Codec().encode,
|
| 53 |
+
decode=Codec().decode,
|
| 54 |
+
incrementalencoder=IncrementalEncoder,
|
| 55 |
+
incrementaldecoder=IncrementalDecoder,
|
| 56 |
+
streamreader=StreamReader,
|
| 57 |
+
streamwriter=StreamWriter,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
### Decoding Table
|
| 62 |
+
|
| 63 |
+
# Python 3:
|
| 64 |
+
# for c in range(256): print(' %r' % chr(c if c < 128 else c + 0xF700))
|
| 65 |
+
decoding_table = (
|
| 66 |
+
'\x00'
|
| 67 |
+
'\x01'
|
| 68 |
+
'\x02'
|
| 69 |
+
'\x03'
|
| 70 |
+
'\x04'
|
| 71 |
+
'\x05'
|
| 72 |
+
'\x06'
|
| 73 |
+
'\x07'
|
| 74 |
+
'\x08'
|
| 75 |
+
'\t'
|
| 76 |
+
'\n'
|
| 77 |
+
'\x0b'
|
| 78 |
+
'\x0c'
|
| 79 |
+
'\r'
|
| 80 |
+
'\x0e'
|
| 81 |
+
'\x0f'
|
| 82 |
+
'\x10'
|
| 83 |
+
'\x11'
|
| 84 |
+
'\x12'
|
| 85 |
+
'\x13'
|
| 86 |
+
'\x14'
|
| 87 |
+
'\x15'
|
| 88 |
+
'\x16'
|
| 89 |
+
'\x17'
|
| 90 |
+
'\x18'
|
| 91 |
+
'\x19'
|
| 92 |
+
'\x1a'
|
| 93 |
+
'\x1b'
|
| 94 |
+
'\x1c'
|
| 95 |
+
'\x1d'
|
| 96 |
+
'\x1e'
|
| 97 |
+
'\x1f'
|
| 98 |
+
' '
|
| 99 |
+
'!'
|
| 100 |
+
'"'
|
| 101 |
+
'#'
|
| 102 |
+
'$'
|
| 103 |
+
'%'
|
| 104 |
+
'&'
|
| 105 |
+
"'"
|
| 106 |
+
'('
|
| 107 |
+
')'
|
| 108 |
+
'*'
|
| 109 |
+
'+'
|
| 110 |
+
','
|
| 111 |
+
'-'
|
| 112 |
+
'.'
|
| 113 |
+
'/'
|
| 114 |
+
'0'
|
| 115 |
+
'1'
|
| 116 |
+
'2'
|
| 117 |
+
'3'
|
| 118 |
+
'4'
|
| 119 |
+
'5'
|
| 120 |
+
'6'
|
| 121 |
+
'7'
|
| 122 |
+
'8'
|
| 123 |
+
'9'
|
| 124 |
+
':'
|
| 125 |
+
';'
|
| 126 |
+
'<'
|
| 127 |
+
'='
|
| 128 |
+
'>'
|
| 129 |
+
'?'
|
| 130 |
+
'@'
|
| 131 |
+
'A'
|
| 132 |
+
'B'
|
| 133 |
+
'C'
|
| 134 |
+
'D'
|
| 135 |
+
'E'
|
| 136 |
+
'F'
|
| 137 |
+
'G'
|
| 138 |
+
'H'
|
| 139 |
+
'I'
|
| 140 |
+
'J'
|
| 141 |
+
'K'
|
| 142 |
+
'L'
|
| 143 |
+
'M'
|
| 144 |
+
'N'
|
| 145 |
+
'O'
|
| 146 |
+
'P'
|
| 147 |
+
'Q'
|
| 148 |
+
'R'
|
| 149 |
+
'S'
|
| 150 |
+
'T'
|
| 151 |
+
'U'
|
| 152 |
+
'V'
|
| 153 |
+
'W'
|
| 154 |
+
'X'
|
| 155 |
+
'Y'
|
| 156 |
+
'Z'
|
| 157 |
+
'['
|
| 158 |
+
'\\'
|
| 159 |
+
']'
|
| 160 |
+
'^'
|
| 161 |
+
'_'
|
| 162 |
+
'`'
|
| 163 |
+
'a'
|
| 164 |
+
'b'
|
| 165 |
+
'c'
|
| 166 |
+
'd'
|
| 167 |
+
'e'
|
| 168 |
+
'f'
|
| 169 |
+
'g'
|
| 170 |
+
'h'
|
| 171 |
+
'i'
|
| 172 |
+
'j'
|
| 173 |
+
'k'
|
| 174 |
+
'l'
|
| 175 |
+
'm'
|
| 176 |
+
'n'
|
| 177 |
+
'o'
|
| 178 |
+
'p'
|
| 179 |
+
'q'
|
| 180 |
+
'r'
|
| 181 |
+
's'
|
| 182 |
+
't'
|
| 183 |
+
'u'
|
| 184 |
+
'v'
|
| 185 |
+
'w'
|
| 186 |
+
'x'
|
| 187 |
+
'y'
|
| 188 |
+
'z'
|
| 189 |
+
'{'
|
| 190 |
+
'|'
|
| 191 |
+
'}'
|
| 192 |
+
'~'
|
| 193 |
+
'\x7f'
|
| 194 |
+
'\uf780'
|
| 195 |
+
'\uf781'
|
| 196 |
+
'\uf782'
|
| 197 |
+
'\uf783'
|
| 198 |
+
'\uf784'
|
| 199 |
+
'\uf785'
|
| 200 |
+
'\uf786'
|
| 201 |
+
'\uf787'
|
| 202 |
+
'\uf788'
|
| 203 |
+
'\uf789'
|
| 204 |
+
'\uf78a'
|
| 205 |
+
'\uf78b'
|
| 206 |
+
'\uf78c'
|
| 207 |
+
'\uf78d'
|
| 208 |
+
'\uf78e'
|
| 209 |
+
'\uf78f'
|
| 210 |
+
'\uf790'
|
| 211 |
+
'\uf791'
|
| 212 |
+
'\uf792'
|
| 213 |
+
'\uf793'
|
| 214 |
+
'\uf794'
|
| 215 |
+
'\uf795'
|
| 216 |
+
'\uf796'
|
| 217 |
+
'\uf797'
|
| 218 |
+
'\uf798'
|
| 219 |
+
'\uf799'
|
| 220 |
+
'\uf79a'
|
| 221 |
+
'\uf79b'
|
| 222 |
+
'\uf79c'
|
| 223 |
+
'\uf79d'
|
| 224 |
+
'\uf79e'
|
| 225 |
+
'\uf79f'
|
| 226 |
+
'\uf7a0'
|
| 227 |
+
'\uf7a1'
|
| 228 |
+
'\uf7a2'
|
| 229 |
+
'\uf7a3'
|
| 230 |
+
'\uf7a4'
|
| 231 |
+
'\uf7a5'
|
| 232 |
+
'\uf7a6'
|
| 233 |
+
'\uf7a7'
|
| 234 |
+
'\uf7a8'
|
| 235 |
+
'\uf7a9'
|
| 236 |
+
'\uf7aa'
|
| 237 |
+
'\uf7ab'
|
| 238 |
+
'\uf7ac'
|
| 239 |
+
'\uf7ad'
|
| 240 |
+
'\uf7ae'
|
| 241 |
+
'\uf7af'
|
| 242 |
+
'\uf7b0'
|
| 243 |
+
'\uf7b1'
|
| 244 |
+
'\uf7b2'
|
| 245 |
+
'\uf7b3'
|
| 246 |
+
'\uf7b4'
|
| 247 |
+
'\uf7b5'
|
| 248 |
+
'\uf7b6'
|
| 249 |
+
'\uf7b7'
|
| 250 |
+
'\uf7b8'
|
| 251 |
+
'\uf7b9'
|
| 252 |
+
'\uf7ba'
|
| 253 |
+
'\uf7bb'
|
| 254 |
+
'\uf7bc'
|
| 255 |
+
'\uf7bd'
|
| 256 |
+
'\uf7be'
|
| 257 |
+
'\uf7bf'
|
| 258 |
+
'\uf7c0'
|
| 259 |
+
'\uf7c1'
|
| 260 |
+
'\uf7c2'
|
| 261 |
+
'\uf7c3'
|
| 262 |
+
'\uf7c4'
|
| 263 |
+
'\uf7c5'
|
| 264 |
+
'\uf7c6'
|
| 265 |
+
'\uf7c7'
|
| 266 |
+
'\uf7c8'
|
| 267 |
+
'\uf7c9'
|
| 268 |
+
'\uf7ca'
|
| 269 |
+
'\uf7cb'
|
| 270 |
+
'\uf7cc'
|
| 271 |
+
'\uf7cd'
|
| 272 |
+
'\uf7ce'
|
| 273 |
+
'\uf7cf'
|
| 274 |
+
'\uf7d0'
|
| 275 |
+
'\uf7d1'
|
| 276 |
+
'\uf7d2'
|
| 277 |
+
'\uf7d3'
|
| 278 |
+
'\uf7d4'
|
| 279 |
+
'\uf7d5'
|
| 280 |
+
'\uf7d6'
|
| 281 |
+
'\uf7d7'
|
| 282 |
+
'\uf7d8'
|
| 283 |
+
'\uf7d9'
|
| 284 |
+
'\uf7da'
|
| 285 |
+
'\uf7db'
|
| 286 |
+
'\uf7dc'
|
| 287 |
+
'\uf7dd'
|
| 288 |
+
'\uf7de'
|
| 289 |
+
'\uf7df'
|
| 290 |
+
'\uf7e0'
|
| 291 |
+
'\uf7e1'
|
| 292 |
+
'\uf7e2'
|
| 293 |
+
'\uf7e3'
|
| 294 |
+
'\uf7e4'
|
| 295 |
+
'\uf7e5'
|
| 296 |
+
'\uf7e6'
|
| 297 |
+
'\uf7e7'
|
| 298 |
+
'\uf7e8'
|
| 299 |
+
'\uf7e9'
|
| 300 |
+
'\uf7ea'
|
| 301 |
+
'\uf7eb'
|
| 302 |
+
'\uf7ec'
|
| 303 |
+
'\uf7ed'
|
| 304 |
+
'\uf7ee'
|
| 305 |
+
'\uf7ef'
|
| 306 |
+
'\uf7f0'
|
| 307 |
+
'\uf7f1'
|
| 308 |
+
'\uf7f2'
|
| 309 |
+
'\uf7f3'
|
| 310 |
+
'\uf7f4'
|
| 311 |
+
'\uf7f5'
|
| 312 |
+
'\uf7f6'
|
| 313 |
+
'\uf7f7'
|
| 314 |
+
'\uf7f8'
|
| 315 |
+
'\uf7f9'
|
| 316 |
+
'\uf7fa'
|
| 317 |
+
'\uf7fb'
|
| 318 |
+
'\uf7fc'
|
| 319 |
+
'\uf7fd'
|
| 320 |
+
'\uf7fe'
|
| 321 |
+
'\uf7ff'
|
| 322 |
+
)
|
| 323 |
+
|
| 324 |
+
### Encoding table
|
| 325 |
+
encoding_table = codecs.charmap_build(decoding_table)
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pip/py.typed
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pip is a command line program. While it is implemented in Python, and so is
|
| 2 |
+
available for import, you must not use pip's internal APIs in this way. Typing
|
| 3 |
+
information is provided as a convenience only and is not a guarantee. Expect
|
| 4 |
+
unannounced changes to the API and types in releases.
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/INSTALLER
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pip
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/METADATA
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Metadata-Version: 2.4
|
| 2 |
+
Name: pluggy
|
| 3 |
+
Version: 1.6.0
|
| 4 |
+
Summary: plugin and hook calling mechanisms for python
|
| 5 |
+
Author-email: Holger Krekel <holger@merlinux.eu>
|
| 6 |
+
License: MIT
|
| 7 |
+
Classifier: Development Status :: 6 - Mature
|
| 8 |
+
Classifier: Intended Audience :: Developers
|
| 9 |
+
Classifier: License :: OSI Approved :: MIT License
|
| 10 |
+
Classifier: Operating System :: POSIX
|
| 11 |
+
Classifier: Operating System :: Microsoft :: Windows
|
| 12 |
+
Classifier: Operating System :: MacOS :: MacOS X
|
| 13 |
+
Classifier: Topic :: Software Development :: Testing
|
| 14 |
+
Classifier: Topic :: Software Development :: Libraries
|
| 15 |
+
Classifier: Topic :: Utilities
|
| 16 |
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
| 17 |
+
Classifier: Programming Language :: Python :: Implementation :: PyPy
|
| 18 |
+
Classifier: Programming Language :: Python :: 3
|
| 19 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
| 20 |
+
Classifier: Programming Language :: Python :: 3.9
|
| 21 |
+
Classifier: Programming Language :: Python :: 3.10
|
| 22 |
+
Classifier: Programming Language :: Python :: 3.11
|
| 23 |
+
Classifier: Programming Language :: Python :: 3.12
|
| 24 |
+
Classifier: Programming Language :: Python :: 3.13
|
| 25 |
+
Requires-Python: >=3.9
|
| 26 |
+
Description-Content-Type: text/x-rst
|
| 27 |
+
License-File: LICENSE
|
| 28 |
+
Provides-Extra: dev
|
| 29 |
+
Requires-Dist: pre-commit; extra == "dev"
|
| 30 |
+
Requires-Dist: tox; extra == "dev"
|
| 31 |
+
Provides-Extra: testing
|
| 32 |
+
Requires-Dist: pytest; extra == "testing"
|
| 33 |
+
Requires-Dist: pytest-benchmark; extra == "testing"
|
| 34 |
+
Requires-Dist: coverage; extra == "testing"
|
| 35 |
+
Dynamic: license-file
|
| 36 |
+
|
| 37 |
+
====================================================
|
| 38 |
+
pluggy - A minimalist production ready plugin system
|
| 39 |
+
====================================================
|
| 40 |
+
|
| 41 |
+
|pypi| |conda-forge| |versions| |github-actions| |gitter| |black| |codecov|
|
| 42 |
+
|
| 43 |
+
This is the core framework used by the `pytest`_, `tox`_, and `devpi`_ projects.
|
| 44 |
+
|
| 45 |
+
Please `read the docs`_ to learn more!
|
| 46 |
+
|
| 47 |
+
A definitive example
|
| 48 |
+
====================
|
| 49 |
+
.. code-block:: python
|
| 50 |
+
|
| 51 |
+
import pluggy
|
| 52 |
+
|
| 53 |
+
hookspec = pluggy.HookspecMarker("myproject")
|
| 54 |
+
hookimpl = pluggy.HookimplMarker("myproject")
|
| 55 |
+
|
| 56 |
+
|
| 57 |
+
class MySpec:
|
| 58 |
+
"""A hook specification namespace."""
|
| 59 |
+
|
| 60 |
+
@hookspec
|
| 61 |
+
def myhook(self, arg1, arg2):
|
| 62 |
+
"""My special little hook that you can customize."""
|
| 63 |
+
|
| 64 |
+
|
| 65 |
+
class Plugin_1:
|
| 66 |
+
"""A hook implementation namespace."""
|
| 67 |
+
|
| 68 |
+
@hookimpl
|
| 69 |
+
def myhook(self, arg1, arg2):
|
| 70 |
+
print("inside Plugin_1.myhook()")
|
| 71 |
+
return arg1 + arg2
|
| 72 |
+
|
| 73 |
+
|
| 74 |
+
class Plugin_2:
|
| 75 |
+
"""A 2nd hook implementation namespace."""
|
| 76 |
+
|
| 77 |
+
@hookimpl
|
| 78 |
+
def myhook(self, arg1, arg2):
|
| 79 |
+
print("inside Plugin_2.myhook()")
|
| 80 |
+
return arg1 - arg2
|
| 81 |
+
|
| 82 |
+
|
| 83 |
+
# create a manager and add the spec
|
| 84 |
+
pm = pluggy.PluginManager("myproject")
|
| 85 |
+
pm.add_hookspecs(MySpec)
|
| 86 |
+
|
| 87 |
+
# register plugins
|
| 88 |
+
pm.register(Plugin_1())
|
| 89 |
+
pm.register(Plugin_2())
|
| 90 |
+
|
| 91 |
+
# call our ``myhook`` hook
|
| 92 |
+
results = pm.hook.myhook(arg1=1, arg2=2)
|
| 93 |
+
print(results)
|
| 94 |
+
|
| 95 |
+
|
| 96 |
+
Running this directly gets us::
|
| 97 |
+
|
| 98 |
+
$ python docs/examples/toy-example.py
|
| 99 |
+
inside Plugin_2.myhook()
|
| 100 |
+
inside Plugin_1.myhook()
|
| 101 |
+
[-1, 3]
|
| 102 |
+
|
| 103 |
+
|
| 104 |
+
.. badges
|
| 105 |
+
|
| 106 |
+
.. |pypi| image:: https://img.shields.io/pypi/v/pluggy.svg
|
| 107 |
+
:target: https://pypi.org/pypi/pluggy
|
| 108 |
+
|
| 109 |
+
.. |versions| image:: https://img.shields.io/pypi/pyversions/pluggy.svg
|
| 110 |
+
:target: https://pypi.org/pypi/pluggy
|
| 111 |
+
|
| 112 |
+
.. |github-actions| image:: https://github.com/pytest-dev/pluggy/workflows/main/badge.svg
|
| 113 |
+
:target: https://github.com/pytest-dev/pluggy/actions
|
| 114 |
+
|
| 115 |
+
.. |conda-forge| image:: https://img.shields.io/conda/vn/conda-forge/pluggy.svg
|
| 116 |
+
:target: https://anaconda.org/conda-forge/pytest
|
| 117 |
+
|
| 118 |
+
.. |gitter| image:: https://badges.gitter.im/pytest-dev/pluggy.svg
|
| 119 |
+
:alt: Join the chat at https://gitter.im/pytest-dev/pluggy
|
| 120 |
+
:target: https://gitter.im/pytest-dev/pluggy?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
| 121 |
+
|
| 122 |
+
.. |black| image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
| 123 |
+
:target: https://github.com/ambv/black
|
| 124 |
+
|
| 125 |
+
.. |codecov| image:: https://codecov.io/gh/pytest-dev/pluggy/branch/master/graph/badge.svg
|
| 126 |
+
:target: https://codecov.io/gh/pytest-dev/pluggy
|
| 127 |
+
:alt: Code coverage Status
|
| 128 |
+
|
| 129 |
+
.. links
|
| 130 |
+
.. _pytest:
|
| 131 |
+
http://pytest.org
|
| 132 |
+
.. _tox:
|
| 133 |
+
https://tox.readthedocs.org
|
| 134 |
+
.. _devpi:
|
| 135 |
+
http://doc.devpi.net
|
| 136 |
+
.. _read the docs:
|
| 137 |
+
https://pluggy.readthedocs.io/en/latest/
|
| 138 |
+
|
| 139 |
+
|
| 140 |
+
Support pluggy
|
| 141 |
+
--------------
|
| 142 |
+
|
| 143 |
+
`Open Collective`_ is an online funding platform for open and transparent communities.
|
| 144 |
+
It provides tools to raise money and share your finances in full transparency.
|
| 145 |
+
|
| 146 |
+
It is the platform of choice for individuals and companies that want to make one-time or
|
| 147 |
+
monthly donations directly to the project.
|
| 148 |
+
|
| 149 |
+
``pluggy`` is part of the ``pytest-dev`` project, see more details in the `pytest collective`_.
|
| 150 |
+
|
| 151 |
+
.. _Open Collective: https://opencollective.com
|
| 152 |
+
.. _pytest collective: https://opencollective.com/pytest
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/RECORD
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
pluggy-1.6.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
| 2 |
+
pluggy-1.6.0.dist-info/METADATA,sha256=dDjDXuJaCV63QW-EtGHC10Qlxec0rVTDkSRTxlJE4Bw,4811
|
| 3 |
+
pluggy-1.6.0.dist-info/RECORD,,
|
| 4 |
+
pluggy-1.6.0.dist-info/WHEEL,sha256=Nw36Djuh_5VDukK0H78QzOX-_FQEo6V37m3nkm96gtU,91
|
| 5 |
+
pluggy-1.6.0.dist-info/licenses/LICENSE,sha256=1rZebCE6XQtXeRHTTW5ZSbn1nXbCOMUHGi8_wWz7JgY,1110
|
| 6 |
+
pluggy-1.6.0.dist-info/top_level.txt,sha256=xKSCRhai-v9MckvMuWqNz16c1tbsmOggoMSwTgcpYHE,7
|
| 7 |
+
pluggy/__init__.py,sha256=D6dp1gmEDjtDp8hAwQc-qrgaulnL4iltrqkLDd-g9tg,811
|
| 8 |
+
pluggy/__pycache__/__init__.cpython-312.pyc,,
|
| 9 |
+
pluggy/__pycache__/_callers.cpython-312.pyc,,
|
| 10 |
+
pluggy/__pycache__/_hooks.cpython-312.pyc,,
|
| 11 |
+
pluggy/__pycache__/_manager.cpython-312.pyc,,
|
| 12 |
+
pluggy/__pycache__/_result.cpython-312.pyc,,
|
| 13 |
+
pluggy/__pycache__/_tracing.cpython-312.pyc,,
|
| 14 |
+
pluggy/__pycache__/_version.cpython-312.pyc,,
|
| 15 |
+
pluggy/__pycache__/_warnings.cpython-312.pyc,,
|
| 16 |
+
pluggy/_callers.py,sha256=gEZllGaSYVssZ2UmpNfmYC0bdVgh2jYbAFeYKvuRMjY,5991
|
| 17 |
+
pluggy/_hooks.py,sha256=E6f3nYcI6dbEuO0Gmy61ozgGU_59_e69kC08a06EBuo,25218
|
| 18 |
+
pluggy/_manager.py,sha256=K4Ip_pkEjvT2oOIfQPp8CwAWoXVnENgQRcy9tlGii0o,20219
|
| 19 |
+
pluggy/_result.py,sha256=3Xfy7DrjXbYb7puRquyY2VbidIWNq6Pp7QnuElMdj8Q,3098
|
| 20 |
+
pluggy/_tracing.py,sha256=nXd2BCmDgf8jJxV-HO3PqxR-WV53eWnF8B4AF1nJGgo,2073
|
| 21 |
+
pluggy/_version.py,sha256=5FGJNp9Lkk9uOxeCjXpoCGBF79Ar6LGPOR7-atBqb_4,511
|
| 22 |
+
pluggy/_warnings.py,sha256=td0AvZBpfamriCC3OqsLwxMh-SzAMjfjmc58T5vP3lw,828
|
| 23 |
+
pluggy/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/WHEEL
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
Wheel-Version: 1.0
|
| 2 |
+
Generator: setuptools (80.7.1)
|
| 3 |
+
Root-Is-Purelib: true
|
| 4 |
+
Tag: py3-none-any
|
| 5 |
+
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/licenses/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
The MIT License (MIT)
|
| 2 |
+
|
| 3 |
+
Copyright (c) 2015 holger krekel (rather uses bitbucket/hpk42)
|
| 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.
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy-1.6.0.dist-info/top_level.txt
ADDED
|
@@ -0,0 +1 @@
|
|
|
|
|
|
|
| 1 |
+
pluggy
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/__init__.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
__all__ = [
|
| 2 |
+
"__version__",
|
| 3 |
+
"PluginManager",
|
| 4 |
+
"PluginValidationError",
|
| 5 |
+
"HookCaller",
|
| 6 |
+
"HookCallError",
|
| 7 |
+
"HookspecOpts",
|
| 8 |
+
"HookimplOpts",
|
| 9 |
+
"HookImpl",
|
| 10 |
+
"HookRelay",
|
| 11 |
+
"HookspecMarker",
|
| 12 |
+
"HookimplMarker",
|
| 13 |
+
"Result",
|
| 14 |
+
"PluggyWarning",
|
| 15 |
+
"PluggyTeardownRaisedWarning",
|
| 16 |
+
]
|
| 17 |
+
from ._hooks import HookCaller
|
| 18 |
+
from ._hooks import HookImpl
|
| 19 |
+
from ._hooks import HookimplMarker
|
| 20 |
+
from ._hooks import HookimplOpts
|
| 21 |
+
from ._hooks import HookRelay
|
| 22 |
+
from ._hooks import HookspecMarker
|
| 23 |
+
from ._hooks import HookspecOpts
|
| 24 |
+
from ._manager import PluginManager
|
| 25 |
+
from ._manager import PluginValidationError
|
| 26 |
+
from ._result import HookCallError
|
| 27 |
+
from ._result import Result
|
| 28 |
+
from ._version import version as __version__
|
| 29 |
+
from ._warnings import PluggyTeardownRaisedWarning
|
| 30 |
+
from ._warnings import PluggyWarning
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_callers.py
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Call loop machinery
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
from collections.abc import Generator
|
| 8 |
+
from collections.abc import Mapping
|
| 9 |
+
from collections.abc import Sequence
|
| 10 |
+
from typing import cast
|
| 11 |
+
from typing import NoReturn
|
| 12 |
+
import warnings
|
| 13 |
+
|
| 14 |
+
from ._hooks import HookImpl
|
| 15 |
+
from ._result import HookCallError
|
| 16 |
+
from ._result import Result
|
| 17 |
+
from ._warnings import PluggyTeardownRaisedWarning
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
# Need to distinguish between old- and new-style hook wrappers.
|
| 21 |
+
# Wrapping with a tuple is the fastest type-safe way I found to do it.
|
| 22 |
+
Teardown = Generator[None, object, object]
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
def run_old_style_hookwrapper(
|
| 26 |
+
hook_impl: HookImpl, hook_name: str, args: Sequence[object]
|
| 27 |
+
) -> Teardown:
|
| 28 |
+
"""
|
| 29 |
+
backward compatibility wrapper to run a old style hookwrapper as a wrapper
|
| 30 |
+
"""
|
| 31 |
+
|
| 32 |
+
teardown: Teardown = cast(Teardown, hook_impl.function(*args))
|
| 33 |
+
try:
|
| 34 |
+
next(teardown)
|
| 35 |
+
except StopIteration:
|
| 36 |
+
_raise_wrapfail(teardown, "did not yield")
|
| 37 |
+
try:
|
| 38 |
+
res = yield
|
| 39 |
+
result = Result(res, None)
|
| 40 |
+
except BaseException as exc:
|
| 41 |
+
result = Result(None, exc)
|
| 42 |
+
try:
|
| 43 |
+
teardown.send(result)
|
| 44 |
+
except StopIteration:
|
| 45 |
+
pass
|
| 46 |
+
except BaseException as e:
|
| 47 |
+
_warn_teardown_exception(hook_name, hook_impl, e)
|
| 48 |
+
raise
|
| 49 |
+
else:
|
| 50 |
+
_raise_wrapfail(teardown, "has second yield")
|
| 51 |
+
finally:
|
| 52 |
+
teardown.close()
|
| 53 |
+
return result.get_result()
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
def _raise_wrapfail(
|
| 57 |
+
wrap_controller: Generator[None, object, object],
|
| 58 |
+
msg: str,
|
| 59 |
+
) -> NoReturn:
|
| 60 |
+
co = wrap_controller.gi_code # type: ignore[attr-defined]
|
| 61 |
+
raise RuntimeError(
|
| 62 |
+
f"wrap_controller at {co.co_name!r} {co.co_filename}:{co.co_firstlineno} {msg}"
|
| 63 |
+
)
|
| 64 |
+
|
| 65 |
+
|
| 66 |
+
def _warn_teardown_exception(
|
| 67 |
+
hook_name: str, hook_impl: HookImpl, e: BaseException
|
| 68 |
+
) -> None:
|
| 69 |
+
msg = "A plugin raised an exception during an old-style hookwrapper teardown.\n"
|
| 70 |
+
msg += f"Plugin: {hook_impl.plugin_name}, Hook: {hook_name}\n"
|
| 71 |
+
msg += f"{type(e).__name__}: {e}\n"
|
| 72 |
+
msg += "For more information see https://pluggy.readthedocs.io/en/stable/api_reference.html#pluggy.PluggyTeardownRaisedWarning" # noqa: E501
|
| 73 |
+
warnings.warn(PluggyTeardownRaisedWarning(msg), stacklevel=6)
|
| 74 |
+
|
| 75 |
+
|
| 76 |
+
def _multicall(
|
| 77 |
+
hook_name: str,
|
| 78 |
+
hook_impls: Sequence[HookImpl],
|
| 79 |
+
caller_kwargs: Mapping[str, object],
|
| 80 |
+
firstresult: bool,
|
| 81 |
+
) -> object | list[object]:
|
| 82 |
+
"""Execute a call into multiple python functions/methods and return the
|
| 83 |
+
result(s).
|
| 84 |
+
|
| 85 |
+
``caller_kwargs`` comes from HookCaller.__call__().
|
| 86 |
+
"""
|
| 87 |
+
__tracebackhide__ = True
|
| 88 |
+
results: list[object] = []
|
| 89 |
+
exception = None
|
| 90 |
+
try: # run impl and wrapper setup functions in a loop
|
| 91 |
+
teardowns: list[Teardown] = []
|
| 92 |
+
try:
|
| 93 |
+
for hook_impl in reversed(hook_impls):
|
| 94 |
+
try:
|
| 95 |
+
args = [caller_kwargs[argname] for argname in hook_impl.argnames]
|
| 96 |
+
except KeyError as e:
|
| 97 |
+
# coverage bug - this is tested
|
| 98 |
+
for argname in hook_impl.argnames: # pragma: no cover
|
| 99 |
+
if argname not in caller_kwargs:
|
| 100 |
+
raise HookCallError(
|
| 101 |
+
f"hook call must provide argument {argname!r}"
|
| 102 |
+
) from e
|
| 103 |
+
|
| 104 |
+
if hook_impl.hookwrapper:
|
| 105 |
+
function_gen = run_old_style_hookwrapper(hook_impl, hook_name, args)
|
| 106 |
+
|
| 107 |
+
next(function_gen) # first yield
|
| 108 |
+
teardowns.append(function_gen)
|
| 109 |
+
|
| 110 |
+
elif hook_impl.wrapper:
|
| 111 |
+
try:
|
| 112 |
+
# If this cast is not valid, a type error is raised below,
|
| 113 |
+
# which is the desired response.
|
| 114 |
+
res = hook_impl.function(*args)
|
| 115 |
+
function_gen = cast(Generator[None, object, object], res)
|
| 116 |
+
next(function_gen) # first yield
|
| 117 |
+
teardowns.append(function_gen)
|
| 118 |
+
except StopIteration:
|
| 119 |
+
_raise_wrapfail(function_gen, "did not yield")
|
| 120 |
+
else:
|
| 121 |
+
res = hook_impl.function(*args)
|
| 122 |
+
if res is not None:
|
| 123 |
+
results.append(res)
|
| 124 |
+
if firstresult: # halt further impl calls
|
| 125 |
+
break
|
| 126 |
+
except BaseException as exc:
|
| 127 |
+
exception = exc
|
| 128 |
+
finally:
|
| 129 |
+
if firstresult: # first result hooks return a single value
|
| 130 |
+
result = results[0] if results else None
|
| 131 |
+
else:
|
| 132 |
+
result = results
|
| 133 |
+
|
| 134 |
+
# run all wrapper post-yield blocks
|
| 135 |
+
for teardown in reversed(teardowns):
|
| 136 |
+
try:
|
| 137 |
+
if exception is not None:
|
| 138 |
+
try:
|
| 139 |
+
teardown.throw(exception)
|
| 140 |
+
except RuntimeError as re:
|
| 141 |
+
# StopIteration from generator causes RuntimeError
|
| 142 |
+
# even for coroutine usage - see #544
|
| 143 |
+
if (
|
| 144 |
+
isinstance(exception, StopIteration)
|
| 145 |
+
and re.__cause__ is exception
|
| 146 |
+
):
|
| 147 |
+
teardown.close()
|
| 148 |
+
continue
|
| 149 |
+
else:
|
| 150 |
+
raise
|
| 151 |
+
else:
|
| 152 |
+
teardown.send(result)
|
| 153 |
+
# Following is unreachable for a well behaved hook wrapper.
|
| 154 |
+
# Try to force finalizers otherwise postponed till GC action.
|
| 155 |
+
# Note: close() may raise if generator handles GeneratorExit.
|
| 156 |
+
teardown.close()
|
| 157 |
+
except StopIteration as si:
|
| 158 |
+
result = si.value
|
| 159 |
+
exception = None
|
| 160 |
+
continue
|
| 161 |
+
except BaseException as e:
|
| 162 |
+
exception = e
|
| 163 |
+
continue
|
| 164 |
+
_raise_wrapfail(teardown, "has second yield")
|
| 165 |
+
|
| 166 |
+
if exception is not None:
|
| 167 |
+
raise exception
|
| 168 |
+
else:
|
| 169 |
+
return result
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_hooks.py
ADDED
|
@@ -0,0 +1,714 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Internal hook annotation, representation and calling machinery.
|
| 3 |
+
"""
|
| 4 |
+
|
| 5 |
+
from __future__ import annotations
|
| 6 |
+
|
| 7 |
+
from collections.abc import Generator
|
| 8 |
+
from collections.abc import Mapping
|
| 9 |
+
from collections.abc import Sequence
|
| 10 |
+
from collections.abc import Set
|
| 11 |
+
import inspect
|
| 12 |
+
import sys
|
| 13 |
+
from types import ModuleType
|
| 14 |
+
from typing import Any
|
| 15 |
+
from typing import Callable
|
| 16 |
+
from typing import Final
|
| 17 |
+
from typing import final
|
| 18 |
+
from typing import Optional
|
| 19 |
+
from typing import overload
|
| 20 |
+
from typing import TYPE_CHECKING
|
| 21 |
+
from typing import TypedDict
|
| 22 |
+
from typing import TypeVar
|
| 23 |
+
from typing import Union
|
| 24 |
+
import warnings
|
| 25 |
+
|
| 26 |
+
from ._result import Result
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
_T = TypeVar("_T")
|
| 30 |
+
_F = TypeVar("_F", bound=Callable[..., object])
|
| 31 |
+
_Namespace = Union[ModuleType, type]
|
| 32 |
+
_Plugin = object
|
| 33 |
+
_HookExec = Callable[
|
| 34 |
+
[str, Sequence["HookImpl"], Mapping[str, object], bool],
|
| 35 |
+
Union[object, list[object]],
|
| 36 |
+
]
|
| 37 |
+
_HookImplFunction = Callable[..., Union[_T, Generator[None, Result[_T], None]]]
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
class HookspecOpts(TypedDict):
|
| 41 |
+
"""Options for a hook specification."""
|
| 42 |
+
|
| 43 |
+
#: Whether the hook is :ref:`first result only <firstresult>`.
|
| 44 |
+
firstresult: bool
|
| 45 |
+
#: Whether the hook is :ref:`historic <historic>`.
|
| 46 |
+
historic: bool
|
| 47 |
+
#: Whether the hook :ref:`warns when implemented <warn_on_impl>`.
|
| 48 |
+
warn_on_impl: Warning | None
|
| 49 |
+
#: Whether the hook warns when :ref:`certain arguments are requested
|
| 50 |
+
#: <warn_on_impl>`.
|
| 51 |
+
#:
|
| 52 |
+
#: .. versionadded:: 1.5
|
| 53 |
+
warn_on_impl_args: Mapping[str, Warning] | None
|
| 54 |
+
|
| 55 |
+
|
| 56 |
+
class HookimplOpts(TypedDict):
|
| 57 |
+
"""Options for a hook implementation."""
|
| 58 |
+
|
| 59 |
+
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
|
| 60 |
+
wrapper: bool
|
| 61 |
+
#: Whether the hook implementation is an :ref:`old-style wrapper
|
| 62 |
+
#: <old_style_hookwrappers>`.
|
| 63 |
+
hookwrapper: bool
|
| 64 |
+
#: Whether validation against a hook specification is :ref:`optional
|
| 65 |
+
#: <optionalhook>`.
|
| 66 |
+
optionalhook: bool
|
| 67 |
+
#: Whether to try to order this hook implementation :ref:`first
|
| 68 |
+
#: <callorder>`.
|
| 69 |
+
tryfirst: bool
|
| 70 |
+
#: Whether to try to order this hook implementation :ref:`last
|
| 71 |
+
#: <callorder>`.
|
| 72 |
+
trylast: bool
|
| 73 |
+
#: The name of the hook specification to match, see :ref:`specname`.
|
| 74 |
+
specname: str | None
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
@final
|
| 78 |
+
class HookspecMarker:
|
| 79 |
+
"""Decorator for marking functions as hook specifications.
|
| 80 |
+
|
| 81 |
+
Instantiate it with a project_name to get a decorator.
|
| 82 |
+
Calling :meth:`PluginManager.add_hookspecs` later will discover all marked
|
| 83 |
+
functions if the :class:`PluginManager` uses the same project name.
|
| 84 |
+
"""
|
| 85 |
+
|
| 86 |
+
__slots__ = ("project_name",)
|
| 87 |
+
|
| 88 |
+
def __init__(self, project_name: str) -> None:
|
| 89 |
+
self.project_name: Final = project_name
|
| 90 |
+
|
| 91 |
+
@overload
|
| 92 |
+
def __call__(
|
| 93 |
+
self,
|
| 94 |
+
function: _F,
|
| 95 |
+
firstresult: bool = False,
|
| 96 |
+
historic: bool = False,
|
| 97 |
+
warn_on_impl: Warning | None = None,
|
| 98 |
+
warn_on_impl_args: Mapping[str, Warning] | None = None,
|
| 99 |
+
) -> _F: ...
|
| 100 |
+
|
| 101 |
+
@overload # noqa: F811
|
| 102 |
+
def __call__( # noqa: F811
|
| 103 |
+
self,
|
| 104 |
+
function: None = ...,
|
| 105 |
+
firstresult: bool = ...,
|
| 106 |
+
historic: bool = ...,
|
| 107 |
+
warn_on_impl: Warning | None = ...,
|
| 108 |
+
warn_on_impl_args: Mapping[str, Warning] | None = ...,
|
| 109 |
+
) -> Callable[[_F], _F]: ...
|
| 110 |
+
|
| 111 |
+
def __call__( # noqa: F811
|
| 112 |
+
self,
|
| 113 |
+
function: _F | None = None,
|
| 114 |
+
firstresult: bool = False,
|
| 115 |
+
historic: bool = False,
|
| 116 |
+
warn_on_impl: Warning | None = None,
|
| 117 |
+
warn_on_impl_args: Mapping[str, Warning] | None = None,
|
| 118 |
+
) -> _F | Callable[[_F], _F]:
|
| 119 |
+
"""If passed a function, directly sets attributes on the function
|
| 120 |
+
which will make it discoverable to :meth:`PluginManager.add_hookspecs`.
|
| 121 |
+
|
| 122 |
+
If passed no function, returns a decorator which can be applied to a
|
| 123 |
+
function later using the attributes supplied.
|
| 124 |
+
|
| 125 |
+
:param firstresult:
|
| 126 |
+
If ``True``, the 1:N hook call (N being the number of registered
|
| 127 |
+
hook implementation functions) will stop at I<=N when the I'th
|
| 128 |
+
function returns a non-``None`` result. See :ref:`firstresult`.
|
| 129 |
+
|
| 130 |
+
:param historic:
|
| 131 |
+
If ``True``, every call to the hook will be memorized and replayed
|
| 132 |
+
on plugins registered after the call was made. See :ref:`historic`.
|
| 133 |
+
|
| 134 |
+
:param warn_on_impl:
|
| 135 |
+
If given, every implementation of this hook will trigger the given
|
| 136 |
+
warning. See :ref:`warn_on_impl`.
|
| 137 |
+
|
| 138 |
+
:param warn_on_impl_args:
|
| 139 |
+
If given, every implementation of this hook which requests one of
|
| 140 |
+
the arguments in the dict will trigger the corresponding warning.
|
| 141 |
+
See :ref:`warn_on_impl`.
|
| 142 |
+
|
| 143 |
+
.. versionadded:: 1.5
|
| 144 |
+
"""
|
| 145 |
+
|
| 146 |
+
def setattr_hookspec_opts(func: _F) -> _F:
|
| 147 |
+
if historic and firstresult:
|
| 148 |
+
raise ValueError("cannot have a historic firstresult hook")
|
| 149 |
+
opts: HookspecOpts = {
|
| 150 |
+
"firstresult": firstresult,
|
| 151 |
+
"historic": historic,
|
| 152 |
+
"warn_on_impl": warn_on_impl,
|
| 153 |
+
"warn_on_impl_args": warn_on_impl_args,
|
| 154 |
+
}
|
| 155 |
+
setattr(func, self.project_name + "_spec", opts)
|
| 156 |
+
return func
|
| 157 |
+
|
| 158 |
+
if function is not None:
|
| 159 |
+
return setattr_hookspec_opts(function)
|
| 160 |
+
else:
|
| 161 |
+
return setattr_hookspec_opts
|
| 162 |
+
|
| 163 |
+
|
| 164 |
+
@final
|
| 165 |
+
class HookimplMarker:
|
| 166 |
+
"""Decorator for marking functions as hook implementations.
|
| 167 |
+
|
| 168 |
+
Instantiate it with a ``project_name`` to get a decorator.
|
| 169 |
+
Calling :meth:`PluginManager.register` later will discover all marked
|
| 170 |
+
functions if the :class:`PluginManager` uses the same project name.
|
| 171 |
+
"""
|
| 172 |
+
|
| 173 |
+
__slots__ = ("project_name",)
|
| 174 |
+
|
| 175 |
+
def __init__(self, project_name: str) -> None:
|
| 176 |
+
self.project_name: Final = project_name
|
| 177 |
+
|
| 178 |
+
@overload
|
| 179 |
+
def __call__(
|
| 180 |
+
self,
|
| 181 |
+
function: _F,
|
| 182 |
+
hookwrapper: bool = ...,
|
| 183 |
+
optionalhook: bool = ...,
|
| 184 |
+
tryfirst: bool = ...,
|
| 185 |
+
trylast: bool = ...,
|
| 186 |
+
specname: str | None = ...,
|
| 187 |
+
wrapper: bool = ...,
|
| 188 |
+
) -> _F: ...
|
| 189 |
+
|
| 190 |
+
@overload # noqa: F811
|
| 191 |
+
def __call__( # noqa: F811
|
| 192 |
+
self,
|
| 193 |
+
function: None = ...,
|
| 194 |
+
hookwrapper: bool = ...,
|
| 195 |
+
optionalhook: bool = ...,
|
| 196 |
+
tryfirst: bool = ...,
|
| 197 |
+
trylast: bool = ...,
|
| 198 |
+
specname: str | None = ...,
|
| 199 |
+
wrapper: bool = ...,
|
| 200 |
+
) -> Callable[[_F], _F]: ...
|
| 201 |
+
|
| 202 |
+
def __call__( # noqa: F811
|
| 203 |
+
self,
|
| 204 |
+
function: _F | None = None,
|
| 205 |
+
hookwrapper: bool = False,
|
| 206 |
+
optionalhook: bool = False,
|
| 207 |
+
tryfirst: bool = False,
|
| 208 |
+
trylast: bool = False,
|
| 209 |
+
specname: str | None = None,
|
| 210 |
+
wrapper: bool = False,
|
| 211 |
+
) -> _F | Callable[[_F], _F]:
|
| 212 |
+
"""If passed a function, directly sets attributes on the function
|
| 213 |
+
which will make it discoverable to :meth:`PluginManager.register`.
|
| 214 |
+
|
| 215 |
+
If passed no function, returns a decorator which can be applied to a
|
| 216 |
+
function later using the attributes supplied.
|
| 217 |
+
|
| 218 |
+
:param optionalhook:
|
| 219 |
+
If ``True``, a missing matching hook specification will not result
|
| 220 |
+
in an error (by default it is an error if no matching spec is
|
| 221 |
+
found). See :ref:`optionalhook`.
|
| 222 |
+
|
| 223 |
+
:param tryfirst:
|
| 224 |
+
If ``True``, this hook implementation will run as early as possible
|
| 225 |
+
in the chain of N hook implementations for a specification. See
|
| 226 |
+
:ref:`callorder`.
|
| 227 |
+
|
| 228 |
+
:param trylast:
|
| 229 |
+
If ``True``, this hook implementation will run as late as possible
|
| 230 |
+
in the chain of N hook implementations for a specification. See
|
| 231 |
+
:ref:`callorder`.
|
| 232 |
+
|
| 233 |
+
:param wrapper:
|
| 234 |
+
If ``True`` ("new-style hook wrapper"), the hook implementation
|
| 235 |
+
needs to execute exactly one ``yield``. The code before the
|
| 236 |
+
``yield`` is run early before any non-hook-wrapper function is run.
|
| 237 |
+
The code after the ``yield`` is run after all non-hook-wrapper
|
| 238 |
+
functions have run. The ``yield`` receives the result value of the
|
| 239 |
+
inner calls, or raises the exception of inner calls (including
|
| 240 |
+
earlier hook wrapper calls). The return value of the function
|
| 241 |
+
becomes the return value of the hook, and a raised exception becomes
|
| 242 |
+
the exception of the hook. See :ref:`hookwrapper`.
|
| 243 |
+
|
| 244 |
+
:param hookwrapper:
|
| 245 |
+
If ``True`` ("old-style hook wrapper"), the hook implementation
|
| 246 |
+
needs to execute exactly one ``yield``. The code before the
|
| 247 |
+
``yield`` is run early before any non-hook-wrapper function is run.
|
| 248 |
+
The code after the ``yield`` is run after all non-hook-wrapper
|
| 249 |
+
function have run The ``yield`` receives a :class:`Result` object
|
| 250 |
+
representing the exception or result outcome of the inner calls
|
| 251 |
+
(including earlier hook wrapper calls). This option is mutually
|
| 252 |
+
exclusive with ``wrapper``. See :ref:`old_style_hookwrapper`.
|
| 253 |
+
|
| 254 |
+
:param specname:
|
| 255 |
+
If provided, the given name will be used instead of the function
|
| 256 |
+
name when matching this hook implementation to a hook specification
|
| 257 |
+
during registration. See :ref:`specname`.
|
| 258 |
+
|
| 259 |
+
.. versionadded:: 1.2.0
|
| 260 |
+
The ``wrapper`` parameter.
|
| 261 |
+
"""
|
| 262 |
+
|
| 263 |
+
def setattr_hookimpl_opts(func: _F) -> _F:
|
| 264 |
+
opts: HookimplOpts = {
|
| 265 |
+
"wrapper": wrapper,
|
| 266 |
+
"hookwrapper": hookwrapper,
|
| 267 |
+
"optionalhook": optionalhook,
|
| 268 |
+
"tryfirst": tryfirst,
|
| 269 |
+
"trylast": trylast,
|
| 270 |
+
"specname": specname,
|
| 271 |
+
}
|
| 272 |
+
setattr(func, self.project_name + "_impl", opts)
|
| 273 |
+
return func
|
| 274 |
+
|
| 275 |
+
if function is None:
|
| 276 |
+
return setattr_hookimpl_opts
|
| 277 |
+
else:
|
| 278 |
+
return setattr_hookimpl_opts(function)
|
| 279 |
+
|
| 280 |
+
|
| 281 |
+
def normalize_hookimpl_opts(opts: HookimplOpts) -> None:
|
| 282 |
+
opts.setdefault("tryfirst", False)
|
| 283 |
+
opts.setdefault("trylast", False)
|
| 284 |
+
opts.setdefault("wrapper", False)
|
| 285 |
+
opts.setdefault("hookwrapper", False)
|
| 286 |
+
opts.setdefault("optionalhook", False)
|
| 287 |
+
opts.setdefault("specname", None)
|
| 288 |
+
|
| 289 |
+
|
| 290 |
+
_PYPY = hasattr(sys, "pypy_version_info")
|
| 291 |
+
|
| 292 |
+
|
| 293 |
+
def varnames(func: object) -> tuple[tuple[str, ...], tuple[str, ...]]:
|
| 294 |
+
"""Return tuple of positional and keywrord argument names for a function,
|
| 295 |
+
method, class or callable.
|
| 296 |
+
|
| 297 |
+
In case of a class, its ``__init__`` method is considered.
|
| 298 |
+
For methods the ``self`` parameter is not included.
|
| 299 |
+
"""
|
| 300 |
+
if inspect.isclass(func):
|
| 301 |
+
try:
|
| 302 |
+
func = func.__init__
|
| 303 |
+
except AttributeError: # pragma: no cover - pypy special case
|
| 304 |
+
return (), ()
|
| 305 |
+
elif not inspect.isroutine(func): # callable object?
|
| 306 |
+
try:
|
| 307 |
+
func = getattr(func, "__call__", func)
|
| 308 |
+
except Exception: # pragma: no cover - pypy special case
|
| 309 |
+
return (), ()
|
| 310 |
+
|
| 311 |
+
try:
|
| 312 |
+
# func MUST be a function or method here or we won't parse any args.
|
| 313 |
+
sig = inspect.signature(
|
| 314 |
+
func.__func__ if inspect.ismethod(func) else func # type:ignore[arg-type]
|
| 315 |
+
)
|
| 316 |
+
except TypeError: # pragma: no cover
|
| 317 |
+
return (), ()
|
| 318 |
+
|
| 319 |
+
_valid_param_kinds = (
|
| 320 |
+
inspect.Parameter.POSITIONAL_ONLY,
|
| 321 |
+
inspect.Parameter.POSITIONAL_OR_KEYWORD,
|
| 322 |
+
)
|
| 323 |
+
_valid_params = {
|
| 324 |
+
name: param
|
| 325 |
+
for name, param in sig.parameters.items()
|
| 326 |
+
if param.kind in _valid_param_kinds
|
| 327 |
+
}
|
| 328 |
+
args = tuple(_valid_params)
|
| 329 |
+
defaults = (
|
| 330 |
+
tuple(
|
| 331 |
+
param.default
|
| 332 |
+
for param in _valid_params.values()
|
| 333 |
+
if param.default is not param.empty
|
| 334 |
+
)
|
| 335 |
+
or None
|
| 336 |
+
)
|
| 337 |
+
|
| 338 |
+
if defaults:
|
| 339 |
+
index = -len(defaults)
|
| 340 |
+
args, kwargs = args[:index], tuple(args[index:])
|
| 341 |
+
else:
|
| 342 |
+
kwargs = ()
|
| 343 |
+
|
| 344 |
+
# strip any implicit instance arg
|
| 345 |
+
# pypy3 uses "obj" instead of "self" for default dunder methods
|
| 346 |
+
if not _PYPY:
|
| 347 |
+
implicit_names: tuple[str, ...] = ("self",)
|
| 348 |
+
else: # pragma: no cover
|
| 349 |
+
implicit_names = ("self", "obj")
|
| 350 |
+
if args:
|
| 351 |
+
qualname: str = getattr(func, "__qualname__", "")
|
| 352 |
+
if inspect.ismethod(func) or ("." in qualname and args[0] in implicit_names):
|
| 353 |
+
args = args[1:]
|
| 354 |
+
|
| 355 |
+
return args, kwargs
|
| 356 |
+
|
| 357 |
+
|
| 358 |
+
@final
|
| 359 |
+
class HookRelay:
|
| 360 |
+
"""Hook holder object for performing 1:N hook calls where N is the number
|
| 361 |
+
of registered plugins."""
|
| 362 |
+
|
| 363 |
+
__slots__ = ("__dict__",)
|
| 364 |
+
|
| 365 |
+
def __init__(self) -> None:
|
| 366 |
+
""":meta private:"""
|
| 367 |
+
|
| 368 |
+
if TYPE_CHECKING:
|
| 369 |
+
|
| 370 |
+
def __getattr__(self, name: str) -> HookCaller: ...
|
| 371 |
+
|
| 372 |
+
|
| 373 |
+
# Historical name (pluggy<=1.2), kept for backward compatibility.
|
| 374 |
+
_HookRelay = HookRelay
|
| 375 |
+
|
| 376 |
+
|
| 377 |
+
_CallHistory = list[tuple[Mapping[str, object], Optional[Callable[[Any], None]]]]
|
| 378 |
+
|
| 379 |
+
|
| 380 |
+
class HookCaller:
|
| 381 |
+
"""A caller of all registered implementations of a hook specification."""
|
| 382 |
+
|
| 383 |
+
__slots__ = (
|
| 384 |
+
"name",
|
| 385 |
+
"spec",
|
| 386 |
+
"_hookexec",
|
| 387 |
+
"_hookimpls",
|
| 388 |
+
"_call_history",
|
| 389 |
+
)
|
| 390 |
+
|
| 391 |
+
def __init__(
|
| 392 |
+
self,
|
| 393 |
+
name: str,
|
| 394 |
+
hook_execute: _HookExec,
|
| 395 |
+
specmodule_or_class: _Namespace | None = None,
|
| 396 |
+
spec_opts: HookspecOpts | None = None,
|
| 397 |
+
) -> None:
|
| 398 |
+
""":meta private:"""
|
| 399 |
+
#: Name of the hook getting called.
|
| 400 |
+
self.name: Final = name
|
| 401 |
+
self._hookexec: Final = hook_execute
|
| 402 |
+
# The hookimpls list. The caller iterates it *in reverse*. Format:
|
| 403 |
+
# 1. trylast nonwrappers
|
| 404 |
+
# 2. nonwrappers
|
| 405 |
+
# 3. tryfirst nonwrappers
|
| 406 |
+
# 4. trylast wrappers
|
| 407 |
+
# 5. wrappers
|
| 408 |
+
# 6. tryfirst wrappers
|
| 409 |
+
self._hookimpls: Final[list[HookImpl]] = []
|
| 410 |
+
self._call_history: _CallHistory | None = None
|
| 411 |
+
# TODO: Document, or make private.
|
| 412 |
+
self.spec: HookSpec | None = None
|
| 413 |
+
if specmodule_or_class is not None:
|
| 414 |
+
assert spec_opts is not None
|
| 415 |
+
self.set_specification(specmodule_or_class, spec_opts)
|
| 416 |
+
|
| 417 |
+
# TODO: Document, or make private.
|
| 418 |
+
def has_spec(self) -> bool:
|
| 419 |
+
return self.spec is not None
|
| 420 |
+
|
| 421 |
+
# TODO: Document, or make private.
|
| 422 |
+
def set_specification(
|
| 423 |
+
self,
|
| 424 |
+
specmodule_or_class: _Namespace,
|
| 425 |
+
spec_opts: HookspecOpts,
|
| 426 |
+
) -> None:
|
| 427 |
+
if self.spec is not None:
|
| 428 |
+
raise ValueError(
|
| 429 |
+
f"Hook {self.spec.name!r} is already registered "
|
| 430 |
+
f"within namespace {self.spec.namespace}"
|
| 431 |
+
)
|
| 432 |
+
self.spec = HookSpec(specmodule_or_class, self.name, spec_opts)
|
| 433 |
+
if spec_opts.get("historic"):
|
| 434 |
+
self._call_history = []
|
| 435 |
+
|
| 436 |
+
def is_historic(self) -> bool:
|
| 437 |
+
"""Whether this caller is :ref:`historic <historic>`."""
|
| 438 |
+
return self._call_history is not None
|
| 439 |
+
|
| 440 |
+
def _remove_plugin(self, plugin: _Plugin) -> None:
|
| 441 |
+
for i, method in enumerate(self._hookimpls):
|
| 442 |
+
if method.plugin == plugin:
|
| 443 |
+
del self._hookimpls[i]
|
| 444 |
+
return
|
| 445 |
+
raise ValueError(f"plugin {plugin!r} not found")
|
| 446 |
+
|
| 447 |
+
def get_hookimpls(self) -> list[HookImpl]:
|
| 448 |
+
"""Get all registered hook implementations for this hook."""
|
| 449 |
+
return self._hookimpls.copy()
|
| 450 |
+
|
| 451 |
+
def _add_hookimpl(self, hookimpl: HookImpl) -> None:
|
| 452 |
+
"""Add an implementation to the callback chain."""
|
| 453 |
+
for i, method in enumerate(self._hookimpls):
|
| 454 |
+
if method.hookwrapper or method.wrapper:
|
| 455 |
+
splitpoint = i
|
| 456 |
+
break
|
| 457 |
+
else:
|
| 458 |
+
splitpoint = len(self._hookimpls)
|
| 459 |
+
if hookimpl.hookwrapper or hookimpl.wrapper:
|
| 460 |
+
start, end = splitpoint, len(self._hookimpls)
|
| 461 |
+
else:
|
| 462 |
+
start, end = 0, splitpoint
|
| 463 |
+
|
| 464 |
+
if hookimpl.trylast:
|
| 465 |
+
self._hookimpls.insert(start, hookimpl)
|
| 466 |
+
elif hookimpl.tryfirst:
|
| 467 |
+
self._hookimpls.insert(end, hookimpl)
|
| 468 |
+
else:
|
| 469 |
+
# find last non-tryfirst method
|
| 470 |
+
i = end - 1
|
| 471 |
+
while i >= start and self._hookimpls[i].tryfirst:
|
| 472 |
+
i -= 1
|
| 473 |
+
self._hookimpls.insert(i + 1, hookimpl)
|
| 474 |
+
|
| 475 |
+
def __repr__(self) -> str:
|
| 476 |
+
return f"<HookCaller {self.name!r}>"
|
| 477 |
+
|
| 478 |
+
def _verify_all_args_are_provided(self, kwargs: Mapping[str, object]) -> None:
|
| 479 |
+
# This is written to avoid expensive operations when not needed.
|
| 480 |
+
if self.spec:
|
| 481 |
+
for argname in self.spec.argnames:
|
| 482 |
+
if argname not in kwargs:
|
| 483 |
+
notincall = ", ".join(
|
| 484 |
+
repr(argname)
|
| 485 |
+
for argname in self.spec.argnames
|
| 486 |
+
# Avoid self.spec.argnames - kwargs.keys()
|
| 487 |
+
# it doesn't preserve order.
|
| 488 |
+
if argname not in kwargs.keys()
|
| 489 |
+
)
|
| 490 |
+
warnings.warn(
|
| 491 |
+
f"Argument(s) {notincall} which are declared in the hookspec "
|
| 492 |
+
"cannot be found in this hook call",
|
| 493 |
+
stacklevel=2,
|
| 494 |
+
)
|
| 495 |
+
break
|
| 496 |
+
|
| 497 |
+
def __call__(self, **kwargs: object) -> Any:
|
| 498 |
+
"""Call the hook.
|
| 499 |
+
|
| 500 |
+
Only accepts keyword arguments, which should match the hook
|
| 501 |
+
specification.
|
| 502 |
+
|
| 503 |
+
Returns the result(s) of calling all registered plugins, see
|
| 504 |
+
:ref:`calling`.
|
| 505 |
+
"""
|
| 506 |
+
assert not self.is_historic(), (
|
| 507 |
+
"Cannot directly call a historic hook - use call_historic instead."
|
| 508 |
+
)
|
| 509 |
+
self._verify_all_args_are_provided(kwargs)
|
| 510 |
+
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
|
| 511 |
+
# Copy because plugins may register other plugins during iteration (#438).
|
| 512 |
+
return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
|
| 513 |
+
|
| 514 |
+
def call_historic(
|
| 515 |
+
self,
|
| 516 |
+
result_callback: Callable[[Any], None] | None = None,
|
| 517 |
+
kwargs: Mapping[str, object] | None = None,
|
| 518 |
+
) -> None:
|
| 519 |
+
"""Call the hook with given ``kwargs`` for all registered plugins and
|
| 520 |
+
for all plugins which will be registered afterwards, see
|
| 521 |
+
:ref:`historic`.
|
| 522 |
+
|
| 523 |
+
:param result_callback:
|
| 524 |
+
If provided, will be called for each non-``None`` result obtained
|
| 525 |
+
from a hook implementation.
|
| 526 |
+
"""
|
| 527 |
+
assert self._call_history is not None
|
| 528 |
+
kwargs = kwargs or {}
|
| 529 |
+
self._verify_all_args_are_provided(kwargs)
|
| 530 |
+
self._call_history.append((kwargs, result_callback))
|
| 531 |
+
# Historizing hooks don't return results.
|
| 532 |
+
# Remember firstresult isn't compatible with historic.
|
| 533 |
+
# Copy because plugins may register other plugins during iteration (#438).
|
| 534 |
+
res = self._hookexec(self.name, self._hookimpls.copy(), kwargs, False)
|
| 535 |
+
if result_callback is None:
|
| 536 |
+
return
|
| 537 |
+
if isinstance(res, list):
|
| 538 |
+
for x in res:
|
| 539 |
+
result_callback(x)
|
| 540 |
+
|
| 541 |
+
def call_extra(
|
| 542 |
+
self, methods: Sequence[Callable[..., object]], kwargs: Mapping[str, object]
|
| 543 |
+
) -> Any:
|
| 544 |
+
"""Call the hook with some additional temporarily participating
|
| 545 |
+
methods using the specified ``kwargs`` as call parameters, see
|
| 546 |
+
:ref:`call_extra`."""
|
| 547 |
+
assert not self.is_historic(), (
|
| 548 |
+
"Cannot directly call a historic hook - use call_historic instead."
|
| 549 |
+
)
|
| 550 |
+
self._verify_all_args_are_provided(kwargs)
|
| 551 |
+
opts: HookimplOpts = {
|
| 552 |
+
"wrapper": False,
|
| 553 |
+
"hookwrapper": False,
|
| 554 |
+
"optionalhook": False,
|
| 555 |
+
"trylast": False,
|
| 556 |
+
"tryfirst": False,
|
| 557 |
+
"specname": None,
|
| 558 |
+
}
|
| 559 |
+
hookimpls = self._hookimpls.copy()
|
| 560 |
+
for method in methods:
|
| 561 |
+
hookimpl = HookImpl(None, "<temp>", method, opts)
|
| 562 |
+
# Find last non-tryfirst nonwrapper method.
|
| 563 |
+
i = len(hookimpls) - 1
|
| 564 |
+
while i >= 0 and (
|
| 565 |
+
# Skip wrappers.
|
| 566 |
+
(hookimpls[i].hookwrapper or hookimpls[i].wrapper)
|
| 567 |
+
# Skip tryfirst nonwrappers.
|
| 568 |
+
or hookimpls[i].tryfirst
|
| 569 |
+
):
|
| 570 |
+
i -= 1
|
| 571 |
+
hookimpls.insert(i + 1, hookimpl)
|
| 572 |
+
firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
|
| 573 |
+
return self._hookexec(self.name, hookimpls, kwargs, firstresult)
|
| 574 |
+
|
| 575 |
+
def _maybe_apply_history(self, method: HookImpl) -> None:
|
| 576 |
+
"""Apply call history to a new hookimpl if it is marked as historic."""
|
| 577 |
+
if self.is_historic():
|
| 578 |
+
assert self._call_history is not None
|
| 579 |
+
for kwargs, result_callback in self._call_history:
|
| 580 |
+
res = self._hookexec(self.name, [method], kwargs, False)
|
| 581 |
+
if res and result_callback is not None:
|
| 582 |
+
# XXX: remember firstresult isn't compat with historic
|
| 583 |
+
assert isinstance(res, list)
|
| 584 |
+
result_callback(res[0])
|
| 585 |
+
|
| 586 |
+
|
| 587 |
+
# Historical name (pluggy<=1.2), kept for backward compatibility.
|
| 588 |
+
_HookCaller = HookCaller
|
| 589 |
+
|
| 590 |
+
|
| 591 |
+
class _SubsetHookCaller(HookCaller):
|
| 592 |
+
"""A proxy to another HookCaller which manages calls to all registered
|
| 593 |
+
plugins except the ones from remove_plugins."""
|
| 594 |
+
|
| 595 |
+
# This class is unusual: in inhertits from `HookCaller` so all of
|
| 596 |
+
# the *code* runs in the class, but it delegates all underlying *data*
|
| 597 |
+
# to the original HookCaller.
|
| 598 |
+
# `subset_hook_caller` used to be implemented by creating a full-fledged
|
| 599 |
+
# HookCaller, copying all hookimpls from the original. This had problems
|
| 600 |
+
# with memory leaks (#346) and historic calls (#347), which make a proxy
|
| 601 |
+
# approach better.
|
| 602 |
+
# An alternative implementation is to use a `_getattr__`/`__getattribute__`
|
| 603 |
+
# proxy, however that adds more overhead and is more tricky to implement.
|
| 604 |
+
|
| 605 |
+
__slots__ = (
|
| 606 |
+
"_orig",
|
| 607 |
+
"_remove_plugins",
|
| 608 |
+
)
|
| 609 |
+
|
| 610 |
+
def __init__(self, orig: HookCaller, remove_plugins: Set[_Plugin]) -> None:
|
| 611 |
+
self._orig = orig
|
| 612 |
+
self._remove_plugins = remove_plugins
|
| 613 |
+
self.name = orig.name # type: ignore[misc]
|
| 614 |
+
self._hookexec = orig._hookexec # type: ignore[misc]
|
| 615 |
+
|
| 616 |
+
@property # type: ignore[misc]
|
| 617 |
+
def _hookimpls(self) -> list[HookImpl]:
|
| 618 |
+
return [
|
| 619 |
+
impl
|
| 620 |
+
for impl in self._orig._hookimpls
|
| 621 |
+
if impl.plugin not in self._remove_plugins
|
| 622 |
+
]
|
| 623 |
+
|
| 624 |
+
@property
|
| 625 |
+
def spec(self) -> HookSpec | None: # type: ignore[override]
|
| 626 |
+
return self._orig.spec
|
| 627 |
+
|
| 628 |
+
@property
|
| 629 |
+
def _call_history(self) -> _CallHistory | None: # type: ignore[override]
|
| 630 |
+
return self._orig._call_history
|
| 631 |
+
|
| 632 |
+
def __repr__(self) -> str:
|
| 633 |
+
return f"<_SubsetHookCaller {self.name!r}>"
|
| 634 |
+
|
| 635 |
+
|
| 636 |
+
@final
|
| 637 |
+
class HookImpl:
|
| 638 |
+
"""A hook implementation in a :class:`HookCaller`."""
|
| 639 |
+
|
| 640 |
+
__slots__ = (
|
| 641 |
+
"function",
|
| 642 |
+
"argnames",
|
| 643 |
+
"kwargnames",
|
| 644 |
+
"plugin",
|
| 645 |
+
"opts",
|
| 646 |
+
"plugin_name",
|
| 647 |
+
"wrapper",
|
| 648 |
+
"hookwrapper",
|
| 649 |
+
"optionalhook",
|
| 650 |
+
"tryfirst",
|
| 651 |
+
"trylast",
|
| 652 |
+
)
|
| 653 |
+
|
| 654 |
+
def __init__(
|
| 655 |
+
self,
|
| 656 |
+
plugin: _Plugin,
|
| 657 |
+
plugin_name: str,
|
| 658 |
+
function: _HookImplFunction[object],
|
| 659 |
+
hook_impl_opts: HookimplOpts,
|
| 660 |
+
) -> None:
|
| 661 |
+
""":meta private:"""
|
| 662 |
+
#: The hook implementation function.
|
| 663 |
+
self.function: Final = function
|
| 664 |
+
argnames, kwargnames = varnames(self.function)
|
| 665 |
+
#: The positional parameter names of ``function```.
|
| 666 |
+
self.argnames: Final = argnames
|
| 667 |
+
#: The keyword parameter names of ``function```.
|
| 668 |
+
self.kwargnames: Final = kwargnames
|
| 669 |
+
#: The plugin which defined this hook implementation.
|
| 670 |
+
self.plugin: Final = plugin
|
| 671 |
+
#: The :class:`HookimplOpts` used to configure this hook implementation.
|
| 672 |
+
self.opts: Final = hook_impl_opts
|
| 673 |
+
#: The name of the plugin which defined this hook implementation.
|
| 674 |
+
self.plugin_name: Final = plugin_name
|
| 675 |
+
#: Whether the hook implementation is a :ref:`wrapper <hookwrapper>`.
|
| 676 |
+
self.wrapper: Final = hook_impl_opts["wrapper"]
|
| 677 |
+
#: Whether the hook implementation is an :ref:`old-style wrapper
|
| 678 |
+
#: <old_style_hookwrappers>`.
|
| 679 |
+
self.hookwrapper: Final = hook_impl_opts["hookwrapper"]
|
| 680 |
+
#: Whether validation against a hook specification is :ref:`optional
|
| 681 |
+
#: <optionalhook>`.
|
| 682 |
+
self.optionalhook: Final = hook_impl_opts["optionalhook"]
|
| 683 |
+
#: Whether to try to order this hook implementation :ref:`first
|
| 684 |
+
#: <callorder>`.
|
| 685 |
+
self.tryfirst: Final = hook_impl_opts["tryfirst"]
|
| 686 |
+
#: Whether to try to order this hook implementation :ref:`last
|
| 687 |
+
#: <callorder>`.
|
| 688 |
+
self.trylast: Final = hook_impl_opts["trylast"]
|
| 689 |
+
|
| 690 |
+
def __repr__(self) -> str:
|
| 691 |
+
return f"<HookImpl plugin_name={self.plugin_name!r}, plugin={self.plugin!r}>"
|
| 692 |
+
|
| 693 |
+
|
| 694 |
+
@final
|
| 695 |
+
class HookSpec:
|
| 696 |
+
__slots__ = (
|
| 697 |
+
"namespace",
|
| 698 |
+
"function",
|
| 699 |
+
"name",
|
| 700 |
+
"argnames",
|
| 701 |
+
"kwargnames",
|
| 702 |
+
"opts",
|
| 703 |
+
"warn_on_impl",
|
| 704 |
+
"warn_on_impl_args",
|
| 705 |
+
)
|
| 706 |
+
|
| 707 |
+
def __init__(self, namespace: _Namespace, name: str, opts: HookspecOpts) -> None:
|
| 708 |
+
self.namespace = namespace
|
| 709 |
+
self.function: Callable[..., object] = getattr(namespace, name)
|
| 710 |
+
self.name = name
|
| 711 |
+
self.argnames, self.kwargnames = varnames(self.function)
|
| 712 |
+
self.opts = opts
|
| 713 |
+
self.warn_on_impl = opts.get("warn_on_impl")
|
| 714 |
+
self.warn_on_impl_args = opts.get("warn_on_impl_args")
|
Sidecar-Courser/.venv/lib/python3.12/site-packages/pluggy/_manager.py
ADDED
|
@@ -0,0 +1,523 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from __future__ import annotations
|
| 2 |
+
|
| 3 |
+
from collections.abc import Iterable
|
| 4 |
+
from collections.abc import Mapping
|
| 5 |
+
from collections.abc import Sequence
|
| 6 |
+
import inspect
|
| 7 |
+
import types
|
| 8 |
+
from typing import Any
|
| 9 |
+
from typing import Callable
|
| 10 |
+
from typing import cast
|
| 11 |
+
from typing import Final
|
| 12 |
+
from typing import TYPE_CHECKING
|
| 13 |
+
import warnings
|
| 14 |
+
|
| 15 |
+
from . import _tracing
|
| 16 |
+
from ._callers import _multicall
|
| 17 |
+
from ._hooks import _HookImplFunction
|
| 18 |
+
from ._hooks import _Namespace
|
| 19 |
+
from ._hooks import _Plugin
|
| 20 |
+
from ._hooks import _SubsetHookCaller
|
| 21 |
+
from ._hooks import HookCaller
|
| 22 |
+
from ._hooks import HookImpl
|
| 23 |
+
from ._hooks import HookimplOpts
|
| 24 |
+
from ._hooks import HookRelay
|
| 25 |
+
from ._hooks import HookspecOpts
|
| 26 |
+
from ._hooks import normalize_hookimpl_opts
|
| 27 |
+
from ._result import Result
|
| 28 |
+
|
| 29 |
+
|
| 30 |
+
if TYPE_CHECKING:
|
| 31 |
+
# importtlib.metadata import is slow, defer it.
|
| 32 |
+
import importlib.metadata
|
| 33 |
+
|
| 34 |
+
|
| 35 |
+
_BeforeTrace = Callable[[str, Sequence[HookImpl], Mapping[str, Any]], None]
|
| 36 |
+
_AfterTrace = Callable[[Result[Any], str, Sequence[HookImpl], Mapping[str, Any]], None]
|
| 37 |
+
|
| 38 |
+
|
| 39 |
+
def _warn_for_function(warning: Warning, function: Callable[..., object]) -> None:
|
| 40 |
+
func = cast(types.FunctionType, function)
|
| 41 |
+
warnings.warn_explicit(
|
| 42 |
+
warning,
|
| 43 |
+
type(warning),
|
| 44 |
+
lineno=func.__code__.co_firstlineno,
|
| 45 |
+
filename=func.__code__.co_filename,
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
|
| 49 |
+
class PluginValidationError(Exception):
|
| 50 |
+
"""Plugin failed validation.
|
| 51 |
+
|
| 52 |
+
:param plugin: The plugin which failed validation.
|
| 53 |
+
:param message: Error message.
|
| 54 |
+
"""
|
| 55 |
+
|
| 56 |
+
def __init__(self, plugin: _Plugin, message: str) -> None:
|
| 57 |
+
super().__init__(message)
|
| 58 |
+
#: The plugin which failed validation.
|
| 59 |
+
self.plugin = plugin
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
class DistFacade:
|
| 63 |
+
"""Emulate a pkg_resources Distribution"""
|
| 64 |
+
|
| 65 |
+
def __init__(self, dist: importlib.metadata.Distribution) -> None:
|
| 66 |
+
self._dist = dist
|
| 67 |
+
|
| 68 |
+
@property
|
| 69 |
+
def project_name(self) -> str:
|
| 70 |
+
name: str = self.metadata["name"]
|
| 71 |
+
return name
|
| 72 |
+
|
| 73 |
+
def __getattr__(self, attr: str, default: Any | None = None) -> Any:
|
| 74 |
+
return getattr(self._dist, attr, default)
|
| 75 |
+
|
| 76 |
+
def __dir__(self) -> list[str]:
|
| 77 |
+
return sorted(dir(self._dist) + ["_dist", "project_name"])
|
| 78 |
+
|
| 79 |
+
|
| 80 |
+
class PluginManager:
|
| 81 |
+
"""Core class which manages registration of plugin objects and 1:N hook
|
| 82 |
+
calling.
|
| 83 |
+
|
| 84 |
+
You can register new hooks by calling :meth:`add_hookspecs(module_or_class)
|
| 85 |
+
<PluginManager.add_hookspecs>`.
|
| 86 |
+
|
| 87 |
+
You can register plugin objects (which contain hook implementations) by
|
| 88 |
+
calling :meth:`register(plugin) <PluginManager.register>`.
|
| 89 |
+
|
| 90 |
+
For debugging purposes you can call :meth:`PluginManager.enable_tracing`
|
| 91 |
+
which will subsequently send debug information to the trace helper.
|
| 92 |
+
|
| 93 |
+
:param project_name:
|
| 94 |
+
The short project name. Prefer snake case. Make sure it's unique!
|
| 95 |
+
"""
|
| 96 |
+
|
| 97 |
+
def __init__(self, project_name: str) -> None:
|
| 98 |
+
#: The project name.
|
| 99 |
+
self.project_name: Final = project_name
|
| 100 |
+
self._name2plugin: Final[dict[str, _Plugin]] = {}
|
| 101 |
+
self._plugin_distinfo: Final[list[tuple[_Plugin, DistFacade]]] = []
|
| 102 |
+
#: The "hook relay", used to call a hook on all registered plugins.
|
| 103 |
+
#: See :ref:`calling`.
|
| 104 |
+
self.hook: Final = HookRelay()
|
| 105 |
+
#: The tracing entry point. See :ref:`tracing`.
|
| 106 |
+
self.trace: Final[_tracing.TagTracerSub] = _tracing.TagTracer().get(
|
| 107 |
+
"pluginmanage"
|
| 108 |
+
)
|
| 109 |
+
self._inner_hookexec = _multicall
|
| 110 |
+
|
| 111 |
+
def _hookexec(
|
| 112 |
+
self,
|
| 113 |
+
hook_name: str,
|
| 114 |
+
methods: Sequence[HookImpl],
|
| 115 |
+
kwargs: Mapping[str, object],
|
| 116 |
+
firstresult: bool,
|
| 117 |
+
) -> object | list[object]:
|
| 118 |
+
# called from all hookcaller instances.
|
| 119 |
+
# enable_tracing will set its own wrapping function at self._inner_hookexec
|
| 120 |
+
return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
|
| 121 |
+
|
| 122 |
+
def register(self, plugin: _Plugin, name: str | None = None) -> str | None:
|
| 123 |
+
"""Register a plugin and return its name.
|
| 124 |
+
|
| 125 |
+
:param name:
|
| 126 |
+
The name under which to register the plugin. If not specified, a
|
| 127 |
+
name is generated using :func:`get_canonical_name`.
|
| 128 |
+
|
| 129 |
+
:returns:
|
| 130 |
+
The plugin name. If the name is blocked from registering, returns
|
| 131 |
+
``None``.
|
| 132 |
+
|
| 133 |
+
If the plugin is already registered, raises a :exc:`ValueError`.
|
| 134 |
+
"""
|
| 135 |
+
plugin_name = name or self.get_canonical_name(plugin)
|
| 136 |
+
|
| 137 |
+
if plugin_name in self._name2plugin:
|
| 138 |
+
if self._name2plugin.get(plugin_name, -1) is None:
|
| 139 |
+
return None # blocked plugin, return None to indicate no registration
|
| 140 |
+
raise ValueError(
|
| 141 |
+
"Plugin name already registered: "
|
| 142 |
+
f"{plugin_name}={plugin}\n{self._name2plugin}"
|
| 143 |
+
)
|
| 144 |
+
|
| 145 |
+
if plugin in self._name2plugin.values():
|
| 146 |
+
raise ValueError(
|
| 147 |
+
"Plugin already registered under a different name: "
|
| 148 |
+
f"{plugin_name}={plugin}\n{self._name2plugin}"
|
| 149 |
+
)
|
| 150 |
+
|
| 151 |
+
# XXX if an error happens we should make sure no state has been
|
| 152 |
+
# changed at point of return
|
| 153 |
+
self._name2plugin[plugin_name] = plugin
|
| 154 |
+
|
| 155 |
+
# register matching hook implementations of the plugin
|
| 156 |
+
for name in dir(plugin):
|
| 157 |
+
hookimpl_opts = self.parse_hookimpl_opts(plugin, name)
|
| 158 |
+
if hookimpl_opts is not None:
|
| 159 |
+
normalize_hookimpl_opts(hookimpl_opts)
|
| 160 |
+
method: _HookImplFunction[object] = getattr(plugin, name)
|
| 161 |
+
hookimpl = HookImpl(plugin, plugin_name, method, hookimpl_opts)
|
| 162 |
+
name = hookimpl_opts.get("specname") or name
|
| 163 |
+
hook: HookCaller | None = getattr(self.hook, name, None)
|
| 164 |
+
if hook is None:
|
| 165 |
+
hook = HookCaller(name, self._hookexec)
|
| 166 |
+
setattr(self.hook, name, hook)
|
| 167 |
+
elif hook.has_spec():
|
| 168 |
+
self._verify_hook(hook, hookimpl)
|
| 169 |
+
hook._maybe_apply_history(hookimpl)
|
| 170 |
+
hook._add_hookimpl(hookimpl)
|
| 171 |
+
return plugin_name
|
| 172 |
+
|
| 173 |
+
def parse_hookimpl_opts(self, plugin: _Plugin, name: str) -> HookimplOpts | None:
|
| 174 |
+
"""Try to obtain a hook implementation from an item with the given name
|
| 175 |
+
in the given plugin which is being searched for hook impls.
|
| 176 |
+
|
| 177 |
+
:returns:
|
| 178 |
+
The parsed hookimpl options, or None to skip the given item.
|
| 179 |
+
|
| 180 |
+
This method can be overridden by ``PluginManager`` subclasses to
|
| 181 |
+
customize how hook implementation are picked up. By default, returns the
|
| 182 |
+
options for items decorated with :class:`HookimplMarker`.
|
| 183 |
+
"""
|
| 184 |
+
method: object = getattr(plugin, name)
|
| 185 |
+
if not inspect.isroutine(method):
|
| 186 |
+
return None
|
| 187 |
+
try:
|
| 188 |
+
res: HookimplOpts | None = getattr(
|
| 189 |
+
method, self.project_name + "_impl", None
|
| 190 |
+
)
|
| 191 |
+
except Exception: # pragma: no cover
|
| 192 |
+
res = {} # type: ignore[assignment] #pragma: no cover
|
| 193 |
+
if res is not None and not isinstance(res, dict):
|
| 194 |
+
# false positive
|
| 195 |
+
res = None # type:ignore[unreachable] #pragma: no cover
|
| 196 |
+
return res
|
| 197 |
+
|
| 198 |
+
def unregister(
|
| 199 |
+
self, plugin: _Plugin | None = None, name: str | None = None
|
| 200 |
+
) -> Any | None:
|
| 201 |
+
"""Unregister a plugin and all of its hook implementations.
|
| 202 |
+
|
| 203 |
+
The plugin can be specified either by the plugin object or the plugin
|
| 204 |
+
name. If both are specified, they must agree.
|
| 205 |
+
|
| 206 |
+
Returns the unregistered plugin, or ``None`` if not found.
|
| 207 |
+
"""
|
| 208 |
+
if name is None:
|
| 209 |
+
assert plugin is not None, "one of name or plugin needs to be specified"
|
| 210 |
+
name = self.get_name(plugin)
|
| 211 |
+
assert name is not None, "plugin is not registered"
|
| 212 |
+
|
| 213 |
+
if plugin is None:
|
| 214 |
+
plugin = self.get_plugin(name)
|
| 215 |
+
if plugin is None:
|
| 216 |
+
return None
|
| 217 |
+
|
| 218 |
+
hookcallers = self.get_hookcallers(plugin)
|
| 219 |
+
if hookcallers:
|
| 220 |
+
for hookcaller in hookcallers:
|
| 221 |
+
hookcaller._remove_plugin(plugin)
|
| 222 |
+
|
| 223 |
+
# if self._name2plugin[name] == None registration was blocked: ignore
|
| 224 |
+
if self._name2plugin.get(name):
|
| 225 |
+
assert name is not None
|
| 226 |
+
del self._name2plugin[name]
|
| 227 |
+
|
| 228 |
+
return plugin
|
| 229 |
+
|
| 230 |
+
def set_blocked(self, name: str) -> None:
|
| 231 |
+
"""Block registrations of the given name, unregister if already registered."""
|
| 232 |
+
self.unregister(name=name)
|
| 233 |
+
self._name2plugin[name] = None
|
| 234 |
+
|
| 235 |
+
def is_blocked(self, name: str) -> bool:
|
| 236 |
+
"""Return whether the given plugin name is blocked."""
|
| 237 |
+
return name in self._name2plugin and self._name2plugin[name] is None
|
| 238 |
+
|
| 239 |
+
def unblock(self, name: str) -> bool:
|
| 240 |
+
"""Unblocks a name.
|
| 241 |
+
|
| 242 |
+
Returns whether the name was actually blocked.
|
| 243 |
+
"""
|
| 244 |
+
if self._name2plugin.get(name, -1) is None:
|
| 245 |
+
del self._name2plugin[name]
|
| 246 |
+
return True
|
| 247 |
+
return False
|
| 248 |
+
|
| 249 |
+
def add_hookspecs(self, module_or_class: _Namespace) -> None:
|
| 250 |
+
"""Add new hook specifications defined in the given ``module_or_class``.
|
| 251 |
+
|
| 252 |
+
Functions are recognized as hook specifications if they have been
|
| 253 |
+
decorated with a matching :class:`HookspecMarker`.
|
| 254 |
+
"""
|
| 255 |
+
names = []
|
| 256 |
+
for name in dir(module_or_class):
|
| 257 |
+
spec_opts = self.parse_hookspec_opts(module_or_class, name)
|
| 258 |
+
if spec_opts is not None:
|
| 259 |
+
hc: HookCaller | None = getattr(self.hook, name, None)
|
| 260 |
+
if hc is None:
|
| 261 |
+
hc = HookCaller(name, self._hookexec, module_or_class, spec_opts)
|
| 262 |
+
setattr(self.hook, name, hc)
|
| 263 |
+
else:
|
| 264 |
+
# Plugins registered this hook without knowing the spec.
|
| 265 |
+
hc.set_specification(module_or_class, spec_opts)
|
| 266 |
+
for hookfunction in hc.get_hookimpls():
|
| 267 |
+
self._verify_hook(hc, hookfunction)
|
| 268 |
+
names.append(name)
|
| 269 |
+
|
| 270 |
+
if not names:
|
| 271 |
+
raise ValueError(
|
| 272 |
+
f"did not find any {self.project_name!r} hooks in {module_or_class!r}"
|
| 273 |
+
)
|
| 274 |
+
|
| 275 |
+
def parse_hookspec_opts(
|
| 276 |
+
self, module_or_class: _Namespace, name: str
|
| 277 |
+
) -> HookspecOpts | None:
|
| 278 |
+
"""Try to obtain a hook specification from an item with the given name
|
| 279 |
+
in the given module or class which is being searched for hook specs.
|
| 280 |
+
|
| 281 |
+
:returns:
|
| 282 |
+
The parsed hookspec options for defining a hook, or None to skip the
|
| 283 |
+
given item.
|
| 284 |
+
|
| 285 |
+
This method can be overridden by ``PluginManager`` subclasses to
|
| 286 |
+
customize how hook specifications are picked up. By default, returns the
|
| 287 |
+
options for items decorated with :class:`HookspecMarker`.
|
| 288 |
+
"""
|
| 289 |
+
method = getattr(module_or_class, name)
|
| 290 |
+
opts: HookspecOpts | None = getattr(method, self.project_name + "_spec", None)
|
| 291 |
+
return opts
|
| 292 |
+
|
| 293 |
+
def get_plugins(self) -> set[Any]:
|
| 294 |
+
"""Return a set of all registered plugin objects."""
|
| 295 |
+
return {x for x in self._name2plugin.values() if x is not None}
|
| 296 |
+
|
| 297 |
+
def is_registered(self, plugin: _Plugin) -> bool:
|
| 298 |
+
"""Return whether the plugin is already registered."""
|
| 299 |
+
return any(plugin == val for val in self._name2plugin.values())
|
| 300 |
+
|
| 301 |
+
def get_canonical_name(self, plugin: _Plugin) -> str:
|
| 302 |
+
"""Return a canonical name for a plugin object.
|
| 303 |
+
|
| 304 |
+
Note that a plugin may be registered under a different name
|
| 305 |
+
specified by the caller of :meth:`register(plugin, name) <register>`.
|
| 306 |
+
To obtain the name of a registered plugin use :meth:`get_name(plugin)
|
| 307 |
+
<get_name>` instead.
|
| 308 |
+
"""
|
| 309 |
+
name: str | None = getattr(plugin, "__name__", None)
|
| 310 |
+
return name or str(id(plugin))
|
| 311 |
+
|
| 312 |
+
def get_plugin(self, name: str) -> Any | None:
|
| 313 |
+
"""Return the plugin registered under the given name, if any."""
|
| 314 |
+
return self._name2plugin.get(name)
|
| 315 |
+
|
| 316 |
+
def has_plugin(self, name: str) -> bool:
|
| 317 |
+
"""Return whether a plugin with the given name is registered."""
|
| 318 |
+
return self.get_plugin(name) is not None
|
| 319 |
+
|
| 320 |
+
def get_name(self, plugin: _Plugin) -> str | None:
|
| 321 |
+
"""Return the name the plugin is registered under, or ``None`` if
|
| 322 |
+
is isn't."""
|
| 323 |
+
for name, val in self._name2plugin.items():
|
| 324 |
+
if plugin == val:
|
| 325 |
+
return name
|
| 326 |
+
return None
|
| 327 |
+
|
| 328 |
+
def _verify_hook(self, hook: HookCaller, hookimpl: HookImpl) -> None:
|
| 329 |
+
if hook.is_historic() and (hookimpl.hookwrapper or hookimpl.wrapper):
|
| 330 |
+
raise PluginValidationError(
|
| 331 |
+
hookimpl.plugin,
|
| 332 |
+
f"Plugin {hookimpl.plugin_name!r}\nhook {hook.name!r}\n"
|
| 333 |
+
"historic incompatible with yield/wrapper/hookwrapper",
|
| 334 |
+
)
|
| 335 |
+
|
| 336 |
+
assert hook.spec is not None
|
| 337 |
+
if hook.spec.warn_on_impl:
|
| 338 |
+
_warn_for_function(hook.spec.warn_on_impl, hookimpl.function)
|
| 339 |
+
|
| 340 |
+
# positional arg checking
|
| 341 |
+
notinspec = set(hookimpl.argnames) - set(hook.spec.argnames)
|
| 342 |
+
if notinspec:
|
| 343 |
+
raise PluginValidationError(
|
| 344 |
+
hookimpl.plugin,
|
| 345 |
+
f"Plugin {hookimpl.plugin_name!r} for hook {hook.name!r}\n"
|
| 346 |
+
f"hookimpl definition: {_formatdef(hookimpl.function)}\n"
|
| 347 |
+
f"Argument(s) {notinspec} are declared in the hookimpl but "
|
| 348 |
+
"can not be found in the hookspec",
|
| 349 |
+
)
|
| 350 |
+
|
| 351 |
+
if hook.spec.warn_on_impl_args:
|
| 352 |
+
for hookimpl_argname in hookimpl.argnames:
|
| 353 |
+
argname_warning = hook.spec.warn_on_impl_args.get(hookimpl_argname)
|
| 354 |
+
if argname_warning is not None:
|
| 355 |
+
_warn_for_function(argname_warning, hookimpl.function)
|
| 356 |
+
|
| 357 |
+
if (
|
| 358 |
+
hookimpl.wrapper or hookimpl.hookwrapper
|
| 359 |
+
) and not inspect.isgeneratorfunction(hookimpl.function):
|
| 360 |
+
raise PluginValidationError(
|
| 361 |
+
hookimpl.plugin,
|
| 362 |
+
f"Plugin {hookimpl.plugin_name!r} for hook {hook.name!r}\n"
|
| 363 |
+
f"hookimpl definition: {_formatdef(hookimpl.function)}\n"
|
| 364 |
+
"Declared as wrapper=True or hookwrapper=True "
|
| 365 |
+
"but function is not a generator function",
|
| 366 |
+
)
|
| 367 |
+
|
| 368 |
+
if hookimpl.wrapper and hookimpl.hookwrapper:
|
| 369 |
+
raise PluginValidationError(
|
| 370 |
+
hookimpl.plugin,
|
| 371 |
+
f"Plugin {hookimpl.plugin_name!r} for hook {hook.name!r}\n"
|
| 372 |
+
f"hookimpl definition: {_formatdef(hookimpl.function)}\n"
|
| 373 |
+
"The wrapper=True and hookwrapper=True options are mutually exclusive",
|
| 374 |
+
)
|
| 375 |
+
|
| 376 |
+
def check_pending(self) -> None:
|
| 377 |
+
"""Verify that all hooks which have not been verified against a
|
| 378 |
+
hook specification are optional, otherwise raise
|
| 379 |
+
:exc:`PluginValidationError`."""
|
| 380 |
+
for name in self.hook.__dict__:
|
| 381 |
+
if name[0] == "_":
|
| 382 |
+
continue
|
| 383 |
+
hook: HookCaller = getattr(self.hook, name)
|
| 384 |
+
if not hook.has_spec():
|
| 385 |
+
for hookimpl in hook.get_hookimpls():
|
| 386 |
+
if not hookimpl.optionalhook:
|
| 387 |
+
raise PluginValidationError(
|
| 388 |
+
hookimpl.plugin,
|
| 389 |
+
f"unknown hook {name!r} in plugin {hookimpl.plugin!r}",
|
| 390 |
+
)
|
| 391 |
+
|
| 392 |
+
def load_setuptools_entrypoints(self, group: str, name: str | None = None) -> int:
|
| 393 |
+
"""Load modules from querying the specified setuptools ``group``.
|
| 394 |
+
|
| 395 |
+
:param group:
|
| 396 |
+
Entry point group to load plugins.
|
| 397 |
+
:param name:
|
| 398 |
+
If given, loads only plugins with the given ``name``.
|
| 399 |
+
|
| 400 |
+
:return:
|
| 401 |
+
The number of plugins loaded by this call.
|
| 402 |
+
"""
|
| 403 |
+
import importlib.metadata
|
| 404 |
+
|
| 405 |
+
count = 0
|
| 406 |
+
for dist in list(importlib.metadata.distributions()):
|
| 407 |
+
for ep in dist.entry_points:
|
| 408 |
+
if (
|
| 409 |
+
ep.group != group
|
| 410 |
+
or (name is not None and ep.name != name)
|
| 411 |
+
# already registered
|
| 412 |
+
or self.get_plugin(ep.name)
|
| 413 |
+
or self.is_blocked(ep.name)
|
| 414 |
+
):
|
| 415 |
+
continue
|
| 416 |
+
plugin = ep.load()
|
| 417 |
+
self.register(plugin, name=ep.name)
|
| 418 |
+
self._plugin_distinfo.append((plugin, DistFacade(dist)))
|
| 419 |
+
count += 1
|
| 420 |
+
return count
|
| 421 |
+
|
| 422 |
+
def list_plugin_distinfo(self) -> list[tuple[_Plugin, DistFacade]]:
|
| 423 |
+
"""Return a list of (plugin, distinfo) pairs for all
|
| 424 |
+
setuptools-registered plugins."""
|
| 425 |
+
return list(self._plugin_distinfo)
|
| 426 |
+
|
| 427 |
+
def list_name_plugin(self) -> list[tuple[str, _Plugin]]:
|
| 428 |
+
"""Return a list of (name, plugin) pairs for all registered plugins."""
|
| 429 |
+
return list(self._name2plugin.items())
|
| 430 |
+
|
| 431 |
+
def get_hookcallers(self, plugin: _Plugin) -> list[HookCaller] | None:
|
| 432 |
+
"""Get all hook callers for the specified plugin.
|
| 433 |
+
|
| 434 |
+
:returns:
|
| 435 |
+
The hook callers, or ``None`` if ``plugin`` is not registered in
|
| 436 |
+
this plugin manager.
|
| 437 |
+
"""
|
| 438 |
+
if self.get_name(plugin) is None:
|
| 439 |
+
return None
|
| 440 |
+
hookcallers = []
|
| 441 |
+
for hookcaller in self.hook.__dict__.values():
|
| 442 |
+
for hookimpl in hookcaller.get_hookimpls():
|
| 443 |
+
if hookimpl.plugin is plugin:
|
| 444 |
+
hookcallers.append(hookcaller)
|
| 445 |
+
return hookcallers
|
| 446 |
+
|
| 447 |
+
def add_hookcall_monitoring(
|
| 448 |
+
self, before: _BeforeTrace, after: _AfterTrace
|
| 449 |
+
) -> Callable[[], None]:
|
| 450 |
+
"""Add before/after tracing functions for all hooks.
|
| 451 |
+
|
| 452 |
+
Returns an undo function which, when called, removes the added tracers.
|
| 453 |
+
|
| 454 |
+
``before(hook_name, hook_impls, kwargs)`` will be called ahead
|
| 455 |
+
of all hook calls and receive a hookcaller instance, a list
|
| 456 |
+
of HookImpl instances and the keyword arguments for the hook call.
|
| 457 |
+
|
| 458 |
+
``after(outcome, hook_name, hook_impls, kwargs)`` receives the
|
| 459 |
+
same arguments as ``before`` but also a :class:`~pluggy.Result` object
|
| 460 |
+
which represents the result of the overall hook call.
|
| 461 |
+
"""
|
| 462 |
+
oldcall = self._inner_hookexec
|
| 463 |
+
|
| 464 |
+
def traced_hookexec(
|
| 465 |
+
hook_name: str,
|
| 466 |
+
hook_impls: Sequence[HookImpl],
|
| 467 |
+
caller_kwargs: Mapping[str, object],
|
| 468 |
+
firstresult: bool,
|
| 469 |
+
) -> object | list[object]:
|
| 470 |
+
before(hook_name, hook_impls, caller_kwargs)
|
| 471 |
+
outcome = Result.from_call(
|
| 472 |
+
lambda: oldcall(hook_name, hook_impls, caller_kwargs, firstresult)
|
| 473 |
+
)
|
| 474 |
+
after(outcome, hook_name, hook_impls, caller_kwargs)
|
| 475 |
+
return outcome.get_result()
|
| 476 |
+
|
| 477 |
+
self._inner_hookexec = traced_hookexec
|
| 478 |
+
|
| 479 |
+
def undo() -> None:
|
| 480 |
+
self._inner_hookexec = oldcall
|
| 481 |
+
|
| 482 |
+
return undo
|
| 483 |
+
|
| 484 |
+
def enable_tracing(self) -> Callable[[], None]:
|
| 485 |
+
"""Enable tracing of hook calls.
|
| 486 |
+
|
| 487 |
+
Returns an undo function which, when called, removes the added tracing.
|
| 488 |
+
"""
|
| 489 |
+
hooktrace = self.trace.root.get("hook")
|
| 490 |
+
|
| 491 |
+
def before(
|
| 492 |
+
hook_name: str, methods: Sequence[HookImpl], kwargs: Mapping[str, object]
|
| 493 |
+
) -> None:
|
| 494 |
+
hooktrace.root.indent += 1
|
| 495 |
+
hooktrace(hook_name, kwargs)
|
| 496 |
+
|
| 497 |
+
def after(
|
| 498 |
+
outcome: Result[object],
|
| 499 |
+
hook_name: str,
|
| 500 |
+
methods: Sequence[HookImpl],
|
| 501 |
+
kwargs: Mapping[str, object],
|
| 502 |
+
) -> None:
|
| 503 |
+
if outcome.exception is None:
|
| 504 |
+
hooktrace("finish", hook_name, "-->", outcome.get_result())
|
| 505 |
+
hooktrace.root.indent -= 1
|
| 506 |
+
|
| 507 |
+
return self.add_hookcall_monitoring(before, after)
|
| 508 |
+
|
| 509 |
+
def subset_hook_caller(
|
| 510 |
+
self, name: str, remove_plugins: Iterable[_Plugin]
|
| 511 |
+
) -> HookCaller:
|
| 512 |
+
"""Return a proxy :class:`~pluggy.HookCaller` instance for the named
|
| 513 |
+
method which manages calls to all registered plugins except the ones
|
| 514 |
+
from remove_plugins."""
|
| 515 |
+
orig: HookCaller = getattr(self.hook, name)
|
| 516 |
+
plugins_to_remove = {plug for plug in remove_plugins if hasattr(plug, name)}
|
| 517 |
+
if plugins_to_remove:
|
| 518 |
+
return _SubsetHookCaller(orig, plugins_to_remove)
|
| 519 |
+
return orig
|
| 520 |
+
|
| 521 |
+
|
| 522 |
+
def _formatdef(func: Callable[..., object]) -> str:
|
| 523 |
+
return f"{func.__name__}{inspect.signature(func)}"
|