Akash6776 commited on
Commit
f92bb5a
·
verified ·
1 Parent(s): 0b05d07

Add files using upload-large-folder tool

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +11 -0
  2. 17.Clips4Sale.MHBHJ.Kenzie and Evelin.mp4 +3 -0
  3. 17.DigitalPlayground.Slippery Salesgirl.mp4 +3 -0
  4. 17.GirlsWay.My Amazon Step-Mom.mp4 +3 -0
  5. 17.Nubiles-Porn.Christmas Family Sex.mp4 +3 -0
  6. 18.Cospimps.Sailor Moon gets Creampied.mp4 +3 -0
  7. 18.GirlsWay.Don't Share With Anyone.mp4 +3 -0
  8. 18.Nubiles-Porn.Step Sister In Love.mp4 +3 -0
  9. 18.SpyFam.Stepdaughter Fucks Stepdad To Hide Lesbian Makeout.mp4 +3 -0
  10. 18.Tushy.My Second Anal Confession.100667.mp4 +3 -0
  11. 19.AdultTime.JaysPOVSex Crazed Step Daughter POV Kenzie Reeves.mp4 +3 -0
  12. 19.EvilAngel.Teen Kenzie - Gaping Anal & Cum Facial.mp4 +3 -0
  13. venv/bin/Activate.ps1 +247 -0
  14. venv/bin/activate +70 -0
  15. venv/bin/activate.csh +27 -0
  16. venv/bin/activate.fish +69 -0
  17. venv/bin/huggingface-cli +8 -0
  18. venv/bin/normalizer +8 -0
  19. venv/bin/pip +8 -0
  20. venv/bin/pip3 +8 -0
  21. venv/bin/pip3.12 +8 -0
  22. venv/bin/tiny-agents +8 -0
  23. venv/bin/tqdm +8 -0
  24. venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/INSTALLER +1 -0
  25. venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/METADATA +58 -0
  26. venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/RECORD +24 -0
  27. venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/WHEEL +4 -0
  28. venv/lib/python3.12/site-packages/hf_xet/__init__.py +5 -0
  29. venv/lib/python3.12/site-packages/packaging/__init__.py +15 -0
  30. venv/lib/python3.12/site-packages/packaging/_elffile.py +109 -0
  31. venv/lib/python3.12/site-packages/packaging/_manylinux.py +262 -0
  32. venv/lib/python3.12/site-packages/packaging/_musllinux.py +85 -0
  33. venv/lib/python3.12/site-packages/packaging/_parser.py +353 -0
  34. venv/lib/python3.12/site-packages/packaging/_structures.py +61 -0
  35. venv/lib/python3.12/site-packages/packaging/_tokenizer.py +195 -0
  36. venv/lib/python3.12/site-packages/packaging/markers.py +362 -0
  37. venv/lib/python3.12/site-packages/packaging/metadata.py +862 -0
  38. venv/lib/python3.12/site-packages/packaging/py.typed +0 -0
  39. venv/lib/python3.12/site-packages/packaging/requirements.py +91 -0
  40. venv/lib/python3.12/site-packages/packaging/specifiers.py +1019 -0
  41. venv/lib/python3.12/site-packages/packaging/tags.py +656 -0
  42. venv/lib/python3.12/site-packages/packaging/utils.py +163 -0
  43. venv/lib/python3.12/site-packages/packaging/version.py +582 -0
  44. venv/lib/python3.12/site-packages/pip-24.0.dist-info/AUTHORS.txt +760 -0
  45. venv/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER +1 -0
  46. venv/lib/python3.12/site-packages/pip-24.0.dist-info/METADATA +88 -0
  47. venv/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD +1005 -0
  48. venv/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED +0 -0
  49. venv/lib/python3.12/site-packages/pip-24.0.dist-info/entry_points.txt +4 -0
  50. venv/lib/python3.12/site-packages/typing_extensions.py +0 -0
.gitattributes CHANGED
@@ -83,3 +83,14 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
83
  18.Nubiles-Porn.Spring[[:space:]]Break[[:space:]]Lake[[:space:]]Powell[[:space:]]3.mp4 filter=lfs diff=lfs merge=lfs -text
84
  19.AdultTime.Vivid.Downton[[:space:]]Bratty.mp4 filter=lfs diff=lfs merge=lfs -text
85
  17.Clips4Sale.FamilyManipulation.Won't[[:space:]]Mom[[:space:]]Hear[[:space:]]Us.mp4 filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
83
  18.Nubiles-Porn.Spring[[:space:]]Break[[:space:]]Lake[[:space:]]Powell[[:space:]]3.mp4 filter=lfs diff=lfs merge=lfs -text
84
  19.AdultTime.Vivid.Downton[[:space:]]Bratty.mp4 filter=lfs diff=lfs merge=lfs -text
85
  17.Clips4Sale.FamilyManipulation.Won't[[:space:]]Mom[[:space:]]Hear[[:space:]]Us.mp4 filter=lfs diff=lfs merge=lfs -text
86
+ 18.Cospimps.Sailor[[:space:]]Moon[[:space:]]gets[[:space:]]Creampied.mp4 filter=lfs diff=lfs merge=lfs -text
87
+ 17.Nubiles-Porn.Christmas[[:space:]]Family[[:space:]]Sex.mp4 filter=lfs diff=lfs merge=lfs -text
88
+ 18.Tushy.My[[:space:]]Second[[:space:]]Anal[[:space:]]Confession.100667.mp4 filter=lfs diff=lfs merge=lfs -text
89
+ 18.GirlsWay.Don't[[:space:]]Share[[:space:]]With[[:space:]]Anyone.mp4 filter=lfs diff=lfs merge=lfs -text
90
+ 19.AdultTime.JaysPOVSex[[:space:]]Crazed[[:space:]]Step[[:space:]]Daughter[[:space:]]POV[[:space:]]Kenzie[[:space:]]Reeves.mp4 filter=lfs diff=lfs merge=lfs -text
91
+ 17.DigitalPlayground.Slippery[[:space:]]Salesgirl.mp4 filter=lfs diff=lfs merge=lfs -text
92
+ 17.Clips4Sale.MHBHJ.Kenzie[[:space:]]and[[:space:]]Evelin.mp4 filter=lfs diff=lfs merge=lfs -text
93
+ 18.SpyFam.Stepdaughter[[:space:]]Fucks[[:space:]]Stepdad[[:space:]]To[[:space:]]Hide[[:space:]]Lesbian[[:space:]]Makeout.mp4 filter=lfs diff=lfs merge=lfs -text
94
+ 17.GirlsWay.My[[:space:]]Amazon[[:space:]]Step-Mom.mp4 filter=lfs diff=lfs merge=lfs -text
95
+ 19.EvilAngel.Teen[[:space:]]Kenzie[[:space:]]-[[:space:]]Gaping[[:space:]]Anal[[:space:]]&[[:space:]]Cum[[:space:]]Facial.mp4 filter=lfs diff=lfs merge=lfs -text
96
+ 18.Nubiles-Porn.Step[[:space:]]Sister[[:space:]]In[[:space:]]Love.mp4 filter=lfs diff=lfs merge=lfs -text
17.Clips4Sale.MHBHJ.Kenzie and Evelin.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac6b5af3b82a136debef8899d5ce738fc455eddb865067e162526852a1b3e065
3
+ size 337340616
17.DigitalPlayground.Slippery Salesgirl.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e8db0016fd1a4ed784a71b6f18cda17e6deb1191beae6bd97ecda59e6ac8329
3
+ size 1583948491
17.GirlsWay.My Amazon Step-Mom.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3b5859e5683db1085ac02625ae1ddab0dd63a21b1b67aeae013dd82d08cafef3
3
+ size 1641973375
17.Nubiles-Porn.Christmas Family Sex.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b2e8c02f8f0e6b55df803853d656fe6d16d7802b30297552157d188e4ca32733
3
+ size 3044294703
18.Cospimps.Sailor Moon gets Creampied.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:110431c0b811634ce1933ca0a7c2014dc9a3da23b7cdc0dc7c366e34f462d9f1
3
+ size 762397109
18.GirlsWay.Don't Share With Anyone.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:88b0181a0125d89215097a5a2ec9e71d1fd53ab325392923583bb68406480b67
3
+ size 2763822883
18.Nubiles-Porn.Step Sister In Love.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9a65ba27d7c08d44f3090d75b18aa7ccfd1df391e418f3480e60f826913ac7c2
3
+ size 3243182831
18.SpyFam.Stepdaughter Fucks Stepdad To Hide Lesbian Makeout.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:789af76b63d1aad996df4e0884e9939ab4b9909eb72657e24923a8045b3917bd
3
+ size 1431962948
18.Tushy.My Second Anal Confession.100667.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9db822ff1442173c0d6f29d7dc1ada074980c14926969eea957148c83c4a847c
3
+ size 4294178259
19.AdultTime.JaysPOVSex Crazed Step Daughter POV Kenzie Reeves.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c9ef66d862eeb01904fd8bea847c5af0ba04b3193a2ba2b633139d5a597446c3
3
+ size 1050772638
19.EvilAngel.Teen Kenzie - Gaping Anal & Cum Facial.mp4 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:19bbb5c73384d6305d56164af878f70c6e865b6e132fe89bdcfde0af8270091c
3
+ size 541853874
venv/bin/Activate.ps1 ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <#
2
+ .Synopsis
3
+ Activate a Python virtual environment for the current PowerShell session.
4
+
5
+ .Description
6
+ Pushes the python executable for a virtual environment to the front of the
7
+ $Env:PATH environment variable and sets the prompt to signify that you are
8
+ in a Python virtual environment. Makes use of the command line switches as
9
+ well as the `pyvenv.cfg` file values present in the virtual environment.
10
+
11
+ .Parameter VenvDir
12
+ Path to the directory that contains the virtual environment to activate. The
13
+ default value for this is the parent of the directory that the Activate.ps1
14
+ script is located within.
15
+
16
+ .Parameter Prompt
17
+ The prompt prefix to display when this virtual environment is activated. By
18
+ default, this prompt is the name of the virtual environment folder (VenvDir)
19
+ surrounded by parentheses and followed by a single space (ie. '(.venv) ').
20
+
21
+ .Example
22
+ Activate.ps1
23
+ Activates the Python virtual environment that contains the Activate.ps1 script.
24
+
25
+ .Example
26
+ Activate.ps1 -Verbose
27
+ Activates the Python virtual environment that contains the Activate.ps1 script,
28
+ and shows extra information about the activation as it executes.
29
+
30
+ .Example
31
+ Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
32
+ Activates the Python virtual environment located in the specified location.
33
+
34
+ .Example
35
+ Activate.ps1 -Prompt "MyPython"
36
+ Activates the Python virtual environment that contains the Activate.ps1 script,
37
+ and prefixes the current prompt with the specified string (surrounded in
38
+ parentheses) while the virtual environment is active.
39
+
40
+ .Notes
41
+ On Windows, it may be required to enable this Activate.ps1 script by setting the
42
+ execution policy for the user. You can do this by issuing the following PowerShell
43
+ command:
44
+
45
+ PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
46
+
47
+ For more information on Execution Policies:
48
+ https://go.microsoft.com/fwlink/?LinkID=135170
49
+
50
+ #>
51
+ Param(
52
+ [Parameter(Mandatory = $false)]
53
+ [String]
54
+ $VenvDir,
55
+ [Parameter(Mandatory = $false)]
56
+ [String]
57
+ $Prompt
58
+ )
59
+
60
+ <# Function declarations --------------------------------------------------- #>
61
+
62
+ <#
63
+ .Synopsis
64
+ Remove all shell session elements added by the Activate script, including the
65
+ addition of the virtual environment's Python executable from the beginning of
66
+ the PATH variable.
67
+
68
+ .Parameter NonDestructive
69
+ If present, do not remove this function from the global namespace for the
70
+ session.
71
+
72
+ #>
73
+ function global:deactivate ([switch]$NonDestructive) {
74
+ # Revert to original values
75
+
76
+ # The prior prompt:
77
+ if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
78
+ Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
79
+ Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
80
+ }
81
+
82
+ # The prior PYTHONHOME:
83
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
84
+ Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
85
+ Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
86
+ }
87
+
88
+ # The prior PATH:
89
+ if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
90
+ Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
91
+ Remove-Item -Path Env:_OLD_VIRTUAL_PATH
92
+ }
93
+
94
+ # Just remove the VIRTUAL_ENV altogether:
95
+ if (Test-Path -Path Env:VIRTUAL_ENV) {
96
+ Remove-Item -Path env:VIRTUAL_ENV
97
+ }
98
+
99
+ # Just remove VIRTUAL_ENV_PROMPT altogether.
100
+ if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
101
+ Remove-Item -Path env:VIRTUAL_ENV_PROMPT
102
+ }
103
+
104
+ # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
105
+ if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
106
+ Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
107
+ }
108
+
109
+ # Leave deactivate function in the global namespace if requested:
110
+ if (-not $NonDestructive) {
111
+ Remove-Item -Path function:deactivate
112
+ }
113
+ }
114
+
115
+ <#
116
+ .Description
117
+ Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
118
+ given folder, and returns them in a map.
119
+
120
+ For each line in the pyvenv.cfg file, if that line can be parsed into exactly
121
+ two strings separated by `=` (with any amount of whitespace surrounding the =)
122
+ then it is considered a `key = value` line. The left hand string is the key,
123
+ the right hand is the value.
124
+
125
+ If the value starts with a `'` or a `"` then the first and last character is
126
+ stripped from the value before being captured.
127
+
128
+ .Parameter ConfigDir
129
+ Path to the directory that contains the `pyvenv.cfg` file.
130
+ #>
131
+ function Get-PyVenvConfig(
132
+ [String]
133
+ $ConfigDir
134
+ ) {
135
+ Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
136
+
137
+ # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
138
+ $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
139
+
140
+ # An empty map will be returned if no config file is found.
141
+ $pyvenvConfig = @{ }
142
+
143
+ if ($pyvenvConfigPath) {
144
+
145
+ Write-Verbose "File exists, parse `key = value` lines"
146
+ $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
147
+
148
+ $pyvenvConfigContent | ForEach-Object {
149
+ $keyval = $PSItem -split "\s*=\s*", 2
150
+ if ($keyval[0] -and $keyval[1]) {
151
+ $val = $keyval[1]
152
+
153
+ # Remove extraneous quotations around a string value.
154
+ if ("'""".Contains($val.Substring(0, 1))) {
155
+ $val = $val.Substring(1, $val.Length - 2)
156
+ }
157
+
158
+ $pyvenvConfig[$keyval[0]] = $val
159
+ Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
160
+ }
161
+ }
162
+ }
163
+ return $pyvenvConfig
164
+ }
165
+
166
+
167
+ <# Begin Activate script --------------------------------------------------- #>
168
+
169
+ # Determine the containing directory of this script
170
+ $VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
171
+ $VenvExecDir = Get-Item -Path $VenvExecPath
172
+
173
+ Write-Verbose "Activation script is located in path: '$VenvExecPath'"
174
+ Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
175
+ Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
176
+
177
+ # Set values required in priority: CmdLine, ConfigFile, Default
178
+ # First, get the location of the virtual environment, it might not be
179
+ # VenvExecDir if specified on the command line.
180
+ if ($VenvDir) {
181
+ Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
182
+ }
183
+ else {
184
+ Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
185
+ $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
186
+ Write-Verbose "VenvDir=$VenvDir"
187
+ }
188
+
189
+ # Next, read the `pyvenv.cfg` file to determine any required value such
190
+ # as `prompt`.
191
+ $pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
192
+
193
+ # Next, set the prompt from the command line, or the config file, or
194
+ # just use the name of the virtual environment folder.
195
+ if ($Prompt) {
196
+ Write-Verbose "Prompt specified as argument, using '$Prompt'"
197
+ }
198
+ else {
199
+ Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
200
+ if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
201
+ Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
202
+ $Prompt = $pyvenvCfg['prompt'];
203
+ }
204
+ else {
205
+ Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
206
+ Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
207
+ $Prompt = Split-Path -Path $venvDir -Leaf
208
+ }
209
+ }
210
+
211
+ Write-Verbose "Prompt = '$Prompt'"
212
+ Write-Verbose "VenvDir='$VenvDir'"
213
+
214
+ # Deactivate any currently active virtual environment, but leave the
215
+ # deactivate function in place.
216
+ deactivate -nondestructive
217
+
218
+ # Now set the environment variable VIRTUAL_ENV, used by many tools to determine
219
+ # that there is an activated venv.
220
+ $env:VIRTUAL_ENV = $VenvDir
221
+
222
+ if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
223
+
224
+ Write-Verbose "Setting prompt to '$Prompt'"
225
+
226
+ # Set the prompt to include the env name
227
+ # Make sure _OLD_VIRTUAL_PROMPT is global
228
+ function global:_OLD_VIRTUAL_PROMPT { "" }
229
+ Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
230
+ New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
231
+
232
+ function global:prompt {
233
+ Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
234
+ _OLD_VIRTUAL_PROMPT
235
+ }
236
+ $env:VIRTUAL_ENV_PROMPT = $Prompt
237
+ }
238
+
239
+ # Clear PYTHONHOME
240
+ if (Test-Path -Path Env:PYTHONHOME) {
241
+ Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
242
+ Remove-Item -Path Env:PYTHONHOME
243
+ }
244
+
245
+ # Add the venv to the PATH
246
+ Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
247
+ $Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
venv/bin/activate ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source bin/activate" *from bash*
2
+ # You cannot run it directly
3
+
4
+ deactivate () {
5
+ # reset old environment variables
6
+ if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
7
+ PATH="${_OLD_VIRTUAL_PATH:-}"
8
+ export PATH
9
+ unset _OLD_VIRTUAL_PATH
10
+ fi
11
+ if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
12
+ PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
13
+ export PYTHONHOME
14
+ unset _OLD_VIRTUAL_PYTHONHOME
15
+ fi
16
+
17
+ # Call hash to forget past commands. Without forgetting
18
+ # past commands the $PATH changes we made may not be respected
19
+ hash -r 2> /dev/null
20
+
21
+ if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
22
+ PS1="${_OLD_VIRTUAL_PS1:-}"
23
+ export PS1
24
+ unset _OLD_VIRTUAL_PS1
25
+ fi
26
+
27
+ unset VIRTUAL_ENV
28
+ unset VIRTUAL_ENV_PROMPT
29
+ if [ ! "${1:-}" = "nondestructive" ] ; then
30
+ # Self destruct!
31
+ unset -f deactivate
32
+ fi
33
+ }
34
+
35
+ # unset irrelevant variables
36
+ deactivate nondestructive
37
+
38
+ # on Windows, a path can contain colons and backslashes and has to be converted:
39
+ if [ "${OSTYPE:-}" = "cygwin" ] || [ "${OSTYPE:-}" = "msys" ] ; then
40
+ # transform D:\path\to\venv to /d/path/to/venv on MSYS
41
+ # and to /cygdrive/d/path/to/venv on Cygwin
42
+ export VIRTUAL_ENV=$(cygpath /home/ubuntu/Downloads/ken/venv)
43
+ else
44
+ # use the path as-is
45
+ export VIRTUAL_ENV=/home/ubuntu/Downloads/ken/venv
46
+ fi
47
+
48
+ _OLD_VIRTUAL_PATH="$PATH"
49
+ PATH="$VIRTUAL_ENV/"bin":$PATH"
50
+ export PATH
51
+
52
+ # unset PYTHONHOME if set
53
+ # this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
54
+ # could use `if (set -u; : $PYTHONHOME) ;` in bash
55
+ if [ -n "${PYTHONHOME:-}" ] ; then
56
+ _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
57
+ unset PYTHONHOME
58
+ fi
59
+
60
+ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
61
+ _OLD_VIRTUAL_PS1="${PS1:-}"
62
+ PS1='(venv) '"${PS1:-}"
63
+ export PS1
64
+ VIRTUAL_ENV_PROMPT='(venv) '
65
+ export VIRTUAL_ENV_PROMPT
66
+ fi
67
+
68
+ # Call hash to forget past commands. Without forgetting
69
+ # past commands the $PATH changes we made may not be respected
70
+ hash -r 2> /dev/null
venv/bin/activate.csh ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source bin/activate.csh" *from csh*.
2
+ # You cannot run it directly.
3
+
4
+ # Created by Davide Di Blasi <davidedb@gmail.com>.
5
+ # Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
6
+
7
+ alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; unsetenv VIRTUAL_ENV_PROMPT; test "\!:*" != "nondestructive" && unalias deactivate'
8
+
9
+ # Unset irrelevant variables.
10
+ deactivate nondestructive
11
+
12
+ setenv VIRTUAL_ENV /home/ubuntu/Downloads/ken/venv
13
+
14
+ set _OLD_VIRTUAL_PATH="$PATH"
15
+ setenv PATH "$VIRTUAL_ENV/"bin":$PATH"
16
+
17
+
18
+ set _OLD_VIRTUAL_PROMPT="$prompt"
19
+
20
+ if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
21
+ set prompt = '(venv) '"$prompt"
22
+ setenv VIRTUAL_ENV_PROMPT '(venv) '
23
+ endif
24
+
25
+ alias pydoc python -m pydoc
26
+
27
+ rehash
venv/bin/activate.fish ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file must be used with "source <venv>/bin/activate.fish" *from fish*
2
+ # (https://fishshell.com/). You cannot run it directly.
3
+
4
+ function deactivate -d "Exit virtual environment and return to normal shell environment"
5
+ # reset old environment variables
6
+ if test -n "$_OLD_VIRTUAL_PATH"
7
+ set -gx PATH $_OLD_VIRTUAL_PATH
8
+ set -e _OLD_VIRTUAL_PATH
9
+ end
10
+ if test -n "$_OLD_VIRTUAL_PYTHONHOME"
11
+ set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
12
+ set -e _OLD_VIRTUAL_PYTHONHOME
13
+ end
14
+
15
+ if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
16
+ set -e _OLD_FISH_PROMPT_OVERRIDE
17
+ # prevents error when using nested fish instances (Issue #93858)
18
+ if functions -q _old_fish_prompt
19
+ functions -e fish_prompt
20
+ functions -c _old_fish_prompt fish_prompt
21
+ functions -e _old_fish_prompt
22
+ end
23
+ end
24
+
25
+ set -e VIRTUAL_ENV
26
+ set -e VIRTUAL_ENV_PROMPT
27
+ if test "$argv[1]" != "nondestructive"
28
+ # Self-destruct!
29
+ functions -e deactivate
30
+ end
31
+ end
32
+
33
+ # Unset irrelevant variables.
34
+ deactivate nondestructive
35
+
36
+ set -gx VIRTUAL_ENV /home/ubuntu/Downloads/ken/venv
37
+
38
+ set -gx _OLD_VIRTUAL_PATH $PATH
39
+ set -gx PATH "$VIRTUAL_ENV/"bin $PATH
40
+
41
+ # Unset PYTHONHOME if set.
42
+ if set -q PYTHONHOME
43
+ set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
44
+ set -e PYTHONHOME
45
+ end
46
+
47
+ if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
48
+ # fish uses a function instead of an env var to generate the prompt.
49
+
50
+ # Save the current fish_prompt function as the function _old_fish_prompt.
51
+ functions -c fish_prompt _old_fish_prompt
52
+
53
+ # With the original prompt function renamed, we can override with our own.
54
+ function fish_prompt
55
+ # Save the return status of the last command.
56
+ set -l old_status $status
57
+
58
+ # Output the venv prompt; color taken from the blue of the Python logo.
59
+ printf "%s%s%s" (set_color 4B8BBE) '(venv) ' (set_color normal)
60
+
61
+ # Restore the return status of the previous command.
62
+ echo "exit $old_status" | .
63
+ # Output the original/"old" prompt.
64
+ _old_fish_prompt
65
+ end
66
+
67
+ set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
68
+ set -gx VIRTUAL_ENV_PROMPT '(venv) '
69
+ end
venv/bin/huggingface-cli ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from huggingface_hub.commands.huggingface_cli import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
venv/bin/normalizer ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from charset_normalizer import cli
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(cli.cli_detect())
venv/bin/pip ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
venv/bin/pip3 ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
venv/bin/pip3.12 ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from pip._internal.cli.main import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
venv/bin/tiny-agents ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from huggingface_hub.inference._mcp.cli import app
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(app())
venv/bin/tqdm ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ #!/home/ubuntu/Downloads/ken/venv/bin/python3
2
+ # -*- coding: utf-8 -*-
3
+ import re
4
+ import sys
5
+ from tqdm.cli import main
6
+ if __name__ == '__main__':
7
+ sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
8
+ sys.exit(main())
venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/METADATA ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Metadata-Version: 2.4
2
+ Name: filelock
3
+ Version: 3.18.0
4
+ Summary: A platform independent file lock.
5
+ Project-URL: Documentation, https://py-filelock.readthedocs.io
6
+ Project-URL: Homepage, https://github.com/tox-dev/py-filelock
7
+ Project-URL: Source, https://github.com/tox-dev/py-filelock
8
+ Project-URL: Tracker, https://github.com/tox-dev/py-filelock/issues
9
+ Maintainer-email: Bernát Gábor <gaborjbernat@gmail.com>
10
+ License-Expression: Unlicense
11
+ License-File: LICENSE
12
+ Keywords: application,cache,directory,log,user
13
+ Classifier: Development Status :: 5 - Production/Stable
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: The Unlicense (Unlicense)
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python
18
+ Classifier: Programming Language :: Python :: 3 :: Only
19
+ Classifier: Programming Language :: Python :: 3.9
20
+ Classifier: Programming Language :: Python :: 3.10
21
+ Classifier: Programming Language :: Python :: 3.11
22
+ Classifier: Programming Language :: Python :: 3.12
23
+ Classifier: Programming Language :: Python :: 3.13
24
+ Classifier: Topic :: Internet
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Classifier: Topic :: System
27
+ Requires-Python: >=3.9
28
+ Provides-Extra: docs
29
+ Requires-Dist: furo>=2024.8.6; extra == 'docs'
30
+ Requires-Dist: sphinx-autodoc-typehints>=3; extra == 'docs'
31
+ Requires-Dist: sphinx>=8.1.3; extra == 'docs'
32
+ Provides-Extra: testing
33
+ Requires-Dist: covdefaults>=2.3; extra == 'testing'
34
+ Requires-Dist: coverage>=7.6.10; extra == 'testing'
35
+ Requires-Dist: diff-cover>=9.2.1; extra == 'testing'
36
+ Requires-Dist: pytest-asyncio>=0.25.2; extra == 'testing'
37
+ Requires-Dist: pytest-cov>=6; extra == 'testing'
38
+ Requires-Dist: pytest-mock>=3.14; extra == 'testing'
39
+ Requires-Dist: pytest-timeout>=2.3.1; extra == 'testing'
40
+ Requires-Dist: pytest>=8.3.4; extra == 'testing'
41
+ Requires-Dist: virtualenv>=20.28.1; extra == 'testing'
42
+ Provides-Extra: typing
43
+ Requires-Dist: typing-extensions>=4.12.2; (python_version < '3.11') and extra == 'typing'
44
+ Description-Content-Type: text/markdown
45
+
46
+ # filelock
47
+
48
+ [![PyPI](https://img.shields.io/pypi/v/filelock)](https://pypi.org/project/filelock/)
49
+ [![Supported Python
50
+ versions](https://img.shields.io/pypi/pyversions/filelock.svg)](https://pypi.org/project/filelock/)
51
+ [![Documentation
52
+ status](https://readthedocs.org/projects/py-filelock/badge/?version=latest)](https://py-filelock.readthedocs.io/en/latest/?badge=latest)
53
+ [![Code style:
54
+ black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
55
+ [![Downloads](https://static.pepy.tech/badge/filelock/month)](https://pepy.tech/project/filelock)
56
+ [![check](https://github.com/tox-dev/py-filelock/actions/workflows/check.yaml/badge.svg)](https://github.com/tox-dev/py-filelock/actions/workflows/check.yaml)
57
+
58
+ For more information checkout the [official documentation](https://py-filelock.readthedocs.io/en/latest/index.html).
venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/RECORD ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ filelock-3.18.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
2
+ filelock-3.18.0.dist-info/METADATA,sha256=bMzrZMIFytIbgg_WaLomH79i_7KEx8ahX0IJBxbx1_I,2897
3
+ filelock-3.18.0.dist-info/RECORD,,
4
+ filelock-3.18.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
5
+ filelock-3.18.0.dist-info/licenses/LICENSE,sha256=iNm062BXnBkew5HKBMFhMFctfu3EqG2qWL8oxuFMm80,1210
6
+ filelock/__init__.py,sha256=_t_-OAGXo_qyPa9lNQ1YnzVYEvSW3I0onPqzpomsVVg,1769
7
+ filelock/__pycache__/__init__.cpython-312.pyc,,
8
+ filelock/__pycache__/_api.cpython-312.pyc,,
9
+ filelock/__pycache__/_error.cpython-312.pyc,,
10
+ filelock/__pycache__/_soft.cpython-312.pyc,,
11
+ filelock/__pycache__/_unix.cpython-312.pyc,,
12
+ filelock/__pycache__/_util.cpython-312.pyc,,
13
+ filelock/__pycache__/_windows.cpython-312.pyc,,
14
+ filelock/__pycache__/asyncio.cpython-312.pyc,,
15
+ filelock/__pycache__/version.cpython-312.pyc,,
16
+ filelock/_api.py,sha256=2aATBeJ3-jtMj5OSm7EE539iNaTBsf13KXtcBMoi8oM,14545
17
+ filelock/_error.py,sha256=-5jMcjTu60YAvAO1UbqDD1GIEjVkwr8xCFwDBtMeYDg,787
18
+ filelock/_soft.py,sha256=haqtc_TB_KJbYv2a8iuEAclKuM4fMG1vTcp28sK919c,1711
19
+ filelock/_unix.py,sha256=eGOs4gDgZ-5fGnJUz-OkJDeZkAMzgvYcD8hVD6XH7e4,2351
20
+ filelock/_util.py,sha256=QHBoNFIYfbAThhotH3Q8E2acFc84wpG49-T-uu017ZE,1715
21
+ filelock/_windows.py,sha256=8k4XIBl_zZVfGC2gz0kEr8DZBvpNa8wdU9qeM1YrBb8,2179
22
+ filelock/asyncio.py,sha256=EZdJVkbMnZMuQwzuPN5IvXD0Ugzt__vOtrMP4-siVeU,12451
23
+ filelock/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ filelock/version.py,sha256=D9gAiF9PGH4dQFjbe6VcXhU8kyCLpU7-c7_vfZP--Hc,513
venv/lib/python3.12/site-packages/filelock-3.18.0.dist-info/WHEEL ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
venv/lib/python3.12/site-packages/hf_xet/__init__.py ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ from .hf_xet import *
2
+
3
+ __doc__ = hf_xet.__doc__
4
+ if hasattr(hf_xet, "__all__"):
5
+ __all__ = hf_xet.__all__
venv/lib/python3.12/site-packages/packaging/__init__.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+ __title__ = "packaging"
6
+ __summary__ = "Core utilities for Python packages"
7
+ __uri__ = "https://github.com/pypa/packaging"
8
+
9
+ __version__ = "25.0"
10
+
11
+ __author__ = "Donald Stufft and individual contributors"
12
+ __email__ = "donald@stufft.io"
13
+
14
+ __license__ = "BSD-2-Clause or Apache-2.0"
15
+ __copyright__ = f"2014 {__author__}"
venv/lib/python3.12/site-packages/packaging/_elffile.py ADDED
@@ -0,0 +1,109 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ ELF file parser.
3
+
4
+ This provides a class ``ELFFile`` that parses an ELF executable in a similar
5
+ interface to ``ZipFile``. Only the read interface is implemented.
6
+
7
+ Based on: https://gist.github.com/lyssdod/f51579ae8d93c8657a5564aefc2ffbca
8
+ ELF header: https://refspecs.linuxfoundation.org/elf/gabi4+/ch4.eheader.html
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import enum
14
+ import os
15
+ import struct
16
+ from typing import IO
17
+
18
+
19
+ class ELFInvalid(ValueError):
20
+ pass
21
+
22
+
23
+ class EIClass(enum.IntEnum):
24
+ C32 = 1
25
+ C64 = 2
26
+
27
+
28
+ class EIData(enum.IntEnum):
29
+ Lsb = 1
30
+ Msb = 2
31
+
32
+
33
+ class EMachine(enum.IntEnum):
34
+ I386 = 3
35
+ S390 = 22
36
+ Arm = 40
37
+ X8664 = 62
38
+ AArc64 = 183
39
+
40
+
41
+ class ELFFile:
42
+ """
43
+ Representation of an ELF executable.
44
+ """
45
+
46
+ def __init__(self, f: IO[bytes]) -> None:
47
+ self._f = f
48
+
49
+ try:
50
+ ident = self._read("16B")
51
+ except struct.error as e:
52
+ raise ELFInvalid("unable to parse identification") from e
53
+ magic = bytes(ident[:4])
54
+ if magic != b"\x7fELF":
55
+ raise ELFInvalid(f"invalid magic: {magic!r}")
56
+
57
+ self.capacity = ident[4] # Format for program header (bitness).
58
+ self.encoding = ident[5] # Data structure encoding (endianness).
59
+
60
+ try:
61
+ # e_fmt: Format for program header.
62
+ # p_fmt: Format for section header.
63
+ # p_idx: Indexes to find p_type, p_offset, and p_filesz.
64
+ e_fmt, self._p_fmt, self._p_idx = {
65
+ (1, 1): ("<HHIIIIIHHH", "<IIIIIIII", (0, 1, 4)), # 32-bit LSB.
66
+ (1, 2): (">HHIIIIIHHH", ">IIIIIIII", (0, 1, 4)), # 32-bit MSB.
67
+ (2, 1): ("<HHIQQQIHHH", "<IIQQQQQQ", (0, 2, 5)), # 64-bit LSB.
68
+ (2, 2): (">HHIQQQIHHH", ">IIQQQQQQ", (0, 2, 5)), # 64-bit MSB.
69
+ }[(self.capacity, self.encoding)]
70
+ except KeyError as e:
71
+ raise ELFInvalid(
72
+ f"unrecognized capacity ({self.capacity}) or encoding ({self.encoding})"
73
+ ) from e
74
+
75
+ try:
76
+ (
77
+ _,
78
+ self.machine, # Architecture type.
79
+ _,
80
+ _,
81
+ self._e_phoff, # Offset of program header.
82
+ _,
83
+ self.flags, # Processor-specific flags.
84
+ _,
85
+ self._e_phentsize, # Size of section.
86
+ self._e_phnum, # Number of sections.
87
+ ) = self._read(e_fmt)
88
+ except struct.error as e:
89
+ raise ELFInvalid("unable to parse machine and section information") from e
90
+
91
+ def _read(self, fmt: str) -> tuple[int, ...]:
92
+ return struct.unpack(fmt, self._f.read(struct.calcsize(fmt)))
93
+
94
+ @property
95
+ def interpreter(self) -> str | None:
96
+ """
97
+ The path recorded in the ``PT_INTERP`` section header.
98
+ """
99
+ for index in range(self._e_phnum):
100
+ self._f.seek(self._e_phoff + self._e_phentsize * index)
101
+ try:
102
+ data = self._read(self._p_fmt)
103
+ except struct.error:
104
+ continue
105
+ if data[self._p_idx[0]] != 3: # Not PT_INTERP.
106
+ continue
107
+ self._f.seek(data[self._p_idx[1]])
108
+ return os.fsdecode(self._f.read(data[self._p_idx[2]])).strip("\0")
109
+ return None
venv/lib/python3.12/site-packages/packaging/_manylinux.py ADDED
@@ -0,0 +1,262 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import collections
4
+ import contextlib
5
+ import functools
6
+ import os
7
+ import re
8
+ import sys
9
+ import warnings
10
+ from typing import Generator, Iterator, NamedTuple, Sequence
11
+
12
+ from ._elffile import EIClass, EIData, ELFFile, EMachine
13
+
14
+ EF_ARM_ABIMASK = 0xFF000000
15
+ EF_ARM_ABI_VER5 = 0x05000000
16
+ EF_ARM_ABI_FLOAT_HARD = 0x00000400
17
+
18
+
19
+ # `os.PathLike` not a generic type until Python 3.9, so sticking with `str`
20
+ # as the type for `path` until then.
21
+ @contextlib.contextmanager
22
+ def _parse_elf(path: str) -> Generator[ELFFile | None, None, None]:
23
+ try:
24
+ with open(path, "rb") as f:
25
+ yield ELFFile(f)
26
+ except (OSError, TypeError, ValueError):
27
+ yield None
28
+
29
+
30
+ def _is_linux_armhf(executable: str) -> bool:
31
+ # hard-float ABI can be detected from the ELF header of the running
32
+ # process
33
+ # https://static.docs.arm.com/ihi0044/g/aaelf32.pdf
34
+ with _parse_elf(executable) as f:
35
+ return (
36
+ f is not None
37
+ and f.capacity == EIClass.C32
38
+ and f.encoding == EIData.Lsb
39
+ and f.machine == EMachine.Arm
40
+ and f.flags & EF_ARM_ABIMASK == EF_ARM_ABI_VER5
41
+ and f.flags & EF_ARM_ABI_FLOAT_HARD == EF_ARM_ABI_FLOAT_HARD
42
+ )
43
+
44
+
45
+ def _is_linux_i686(executable: str) -> bool:
46
+ with _parse_elf(executable) as f:
47
+ return (
48
+ f is not None
49
+ and f.capacity == EIClass.C32
50
+ and f.encoding == EIData.Lsb
51
+ and f.machine == EMachine.I386
52
+ )
53
+
54
+
55
+ def _have_compatible_abi(executable: str, archs: Sequence[str]) -> bool:
56
+ if "armv7l" in archs:
57
+ return _is_linux_armhf(executable)
58
+ if "i686" in archs:
59
+ return _is_linux_i686(executable)
60
+ allowed_archs = {
61
+ "x86_64",
62
+ "aarch64",
63
+ "ppc64",
64
+ "ppc64le",
65
+ "s390x",
66
+ "loongarch64",
67
+ "riscv64",
68
+ }
69
+ return any(arch in allowed_archs for arch in archs)
70
+
71
+
72
+ # If glibc ever changes its major version, we need to know what the last
73
+ # minor version was, so we can build the complete list of all versions.
74
+ # For now, guess what the highest minor version might be, assume it will
75
+ # be 50 for testing. Once this actually happens, update the dictionary
76
+ # with the actual value.
77
+ _LAST_GLIBC_MINOR: dict[int, int] = collections.defaultdict(lambda: 50)
78
+
79
+
80
+ class _GLibCVersion(NamedTuple):
81
+ major: int
82
+ minor: int
83
+
84
+
85
+ def _glibc_version_string_confstr() -> str | None:
86
+ """
87
+ Primary implementation of glibc_version_string using os.confstr.
88
+ """
89
+ # os.confstr is quite a bit faster than ctypes.DLL. It's also less likely
90
+ # to be broken or missing. This strategy is used in the standard library
91
+ # platform module.
92
+ # https://github.com/python/cpython/blob/fcf1d003bf4f0100c/Lib/platform.py#L175-L183
93
+ try:
94
+ # Should be a string like "glibc 2.17".
95
+ version_string: str | None = os.confstr("CS_GNU_LIBC_VERSION")
96
+ assert version_string is not None
97
+ _, version = version_string.rsplit()
98
+ except (AssertionError, AttributeError, OSError, ValueError):
99
+ # os.confstr() or CS_GNU_LIBC_VERSION not available (or a bad value)...
100
+ return None
101
+ return version
102
+
103
+
104
+ def _glibc_version_string_ctypes() -> str | None:
105
+ """
106
+ Fallback implementation of glibc_version_string using ctypes.
107
+ """
108
+ try:
109
+ import ctypes
110
+ except ImportError:
111
+ return None
112
+
113
+ # ctypes.CDLL(None) internally calls dlopen(NULL), and as the dlopen
114
+ # manpage says, "If filename is NULL, then the returned handle is for the
115
+ # main program". This way we can let the linker do the work to figure out
116
+ # which libc our process is actually using.
117
+ #
118
+ # We must also handle the special case where the executable is not a
119
+ # dynamically linked executable. This can occur when using musl libc,
120
+ # for example. In this situation, dlopen() will error, leading to an
121
+ # OSError. Interestingly, at least in the case of musl, there is no
122
+ # errno set on the OSError. The single string argument used to construct
123
+ # OSError comes from libc itself and is therefore not portable to
124
+ # hard code here. In any case, failure to call dlopen() means we
125
+ # can proceed, so we bail on our attempt.
126
+ try:
127
+ process_namespace = ctypes.CDLL(None)
128
+ except OSError:
129
+ return None
130
+
131
+ try:
132
+ gnu_get_libc_version = process_namespace.gnu_get_libc_version
133
+ except AttributeError:
134
+ # Symbol doesn't exist -> therefore, we are not linked to
135
+ # glibc.
136
+ return None
137
+
138
+ # Call gnu_get_libc_version, which returns a string like "2.5"
139
+ gnu_get_libc_version.restype = ctypes.c_char_p
140
+ version_str: str = gnu_get_libc_version()
141
+ # py2 / py3 compatibility:
142
+ if not isinstance(version_str, str):
143
+ version_str = version_str.decode("ascii")
144
+
145
+ return version_str
146
+
147
+
148
+ def _glibc_version_string() -> str | None:
149
+ """Returns glibc version string, or None if not using glibc."""
150
+ return _glibc_version_string_confstr() or _glibc_version_string_ctypes()
151
+
152
+
153
+ def _parse_glibc_version(version_str: str) -> tuple[int, int]:
154
+ """Parse glibc version.
155
+
156
+ We use a regexp instead of str.split because we want to discard any
157
+ random junk that might come after the minor version -- this might happen
158
+ in patched/forked versions of glibc (e.g. Linaro's version of glibc
159
+ uses version strings like "2.20-2014.11"). See gh-3588.
160
+ """
161
+ m = re.match(r"(?P<major>[0-9]+)\.(?P<minor>[0-9]+)", version_str)
162
+ if not m:
163
+ warnings.warn(
164
+ f"Expected glibc version with 2 components major.minor, got: {version_str}",
165
+ RuntimeWarning,
166
+ stacklevel=2,
167
+ )
168
+ return -1, -1
169
+ return int(m.group("major")), int(m.group("minor"))
170
+
171
+
172
+ @functools.lru_cache
173
+ def _get_glibc_version() -> tuple[int, int]:
174
+ version_str = _glibc_version_string()
175
+ if version_str is None:
176
+ return (-1, -1)
177
+ return _parse_glibc_version(version_str)
178
+
179
+
180
+ # From PEP 513, PEP 600
181
+ def _is_compatible(arch: str, version: _GLibCVersion) -> bool:
182
+ sys_glibc = _get_glibc_version()
183
+ if sys_glibc < version:
184
+ return False
185
+ # Check for presence of _manylinux module.
186
+ try:
187
+ import _manylinux
188
+ except ImportError:
189
+ return True
190
+ if hasattr(_manylinux, "manylinux_compatible"):
191
+ result = _manylinux.manylinux_compatible(version[0], version[1], arch)
192
+ if result is not None:
193
+ return bool(result)
194
+ return True
195
+ if version == _GLibCVersion(2, 5):
196
+ if hasattr(_manylinux, "manylinux1_compatible"):
197
+ return bool(_manylinux.manylinux1_compatible)
198
+ if version == _GLibCVersion(2, 12):
199
+ if hasattr(_manylinux, "manylinux2010_compatible"):
200
+ return bool(_manylinux.manylinux2010_compatible)
201
+ if version == _GLibCVersion(2, 17):
202
+ if hasattr(_manylinux, "manylinux2014_compatible"):
203
+ return bool(_manylinux.manylinux2014_compatible)
204
+ return True
205
+
206
+
207
+ _LEGACY_MANYLINUX_MAP = {
208
+ # CentOS 7 w/ glibc 2.17 (PEP 599)
209
+ (2, 17): "manylinux2014",
210
+ # CentOS 6 w/ glibc 2.12 (PEP 571)
211
+ (2, 12): "manylinux2010",
212
+ # CentOS 5 w/ glibc 2.5 (PEP 513)
213
+ (2, 5): "manylinux1",
214
+ }
215
+
216
+
217
+ def platform_tags(archs: Sequence[str]) -> Iterator[str]:
218
+ """Generate manylinux tags compatible to the current platform.
219
+
220
+ :param archs: Sequence of compatible architectures.
221
+ The first one shall be the closest to the actual architecture and be the part of
222
+ platform tag after the ``linux_`` prefix, e.g. ``x86_64``.
223
+ The ``linux_`` prefix is assumed as a prerequisite for the current platform to
224
+ be manylinux-compatible.
225
+
226
+ :returns: An iterator of compatible manylinux tags.
227
+ """
228
+ if not _have_compatible_abi(sys.executable, archs):
229
+ return
230
+ # Oldest glibc to be supported regardless of architecture is (2, 17).
231
+ too_old_glibc2 = _GLibCVersion(2, 16)
232
+ if set(archs) & {"x86_64", "i686"}:
233
+ # On x86/i686 also oldest glibc to be supported is (2, 5).
234
+ too_old_glibc2 = _GLibCVersion(2, 4)
235
+ current_glibc = _GLibCVersion(*_get_glibc_version())
236
+ glibc_max_list = [current_glibc]
237
+ # We can assume compatibility across glibc major versions.
238
+ # https://sourceware.org/bugzilla/show_bug.cgi?id=24636
239
+ #
240
+ # Build a list of maximum glibc versions so that we can
241
+ # output the canonical list of all glibc from current_glibc
242
+ # down to too_old_glibc2, including all intermediary versions.
243
+ for glibc_major in range(current_glibc.major - 1, 1, -1):
244
+ glibc_minor = _LAST_GLIBC_MINOR[glibc_major]
245
+ glibc_max_list.append(_GLibCVersion(glibc_major, glibc_minor))
246
+ for arch in archs:
247
+ for glibc_max in glibc_max_list:
248
+ if glibc_max.major == too_old_glibc2.major:
249
+ min_minor = too_old_glibc2.minor
250
+ else:
251
+ # For other glibc major versions oldest supported is (x, 0).
252
+ min_minor = -1
253
+ for glibc_minor in range(glibc_max.minor, min_minor, -1):
254
+ glibc_version = _GLibCVersion(glibc_max.major, glibc_minor)
255
+ tag = "manylinux_{}_{}".format(*glibc_version)
256
+ if _is_compatible(arch, glibc_version):
257
+ yield f"{tag}_{arch}"
258
+ # Handle the legacy manylinux1, manylinux2010, manylinux2014 tags.
259
+ if glibc_version in _LEGACY_MANYLINUX_MAP:
260
+ legacy_tag = _LEGACY_MANYLINUX_MAP[glibc_version]
261
+ if _is_compatible(arch, glibc_version):
262
+ yield f"{legacy_tag}_{arch}"
venv/lib/python3.12/site-packages/packaging/_musllinux.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """PEP 656 support.
2
+
3
+ This module implements logic to detect if the currently running Python is
4
+ linked against musl, and what musl version is used.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import functools
10
+ import re
11
+ import subprocess
12
+ import sys
13
+ from typing import Iterator, NamedTuple, Sequence
14
+
15
+ from ._elffile import ELFFile
16
+
17
+
18
+ class _MuslVersion(NamedTuple):
19
+ major: int
20
+ minor: int
21
+
22
+
23
+ def _parse_musl_version(output: str) -> _MuslVersion | None:
24
+ lines = [n for n in (n.strip() for n in output.splitlines()) if n]
25
+ if len(lines) < 2 or lines[0][:4] != "musl":
26
+ return None
27
+ m = re.match(r"Version (\d+)\.(\d+)", lines[1])
28
+ if not m:
29
+ return None
30
+ return _MuslVersion(major=int(m.group(1)), minor=int(m.group(2)))
31
+
32
+
33
+ @functools.lru_cache
34
+ def _get_musl_version(executable: str) -> _MuslVersion | None:
35
+ """Detect currently-running musl runtime version.
36
+
37
+ This is done by checking the specified executable's dynamic linking
38
+ information, and invoking the loader to parse its output for a version
39
+ string. If the loader is musl, the output would be something like::
40
+
41
+ musl libc (x86_64)
42
+ Version 1.2.2
43
+ Dynamic Program Loader
44
+ """
45
+ try:
46
+ with open(executable, "rb") as f:
47
+ ld = ELFFile(f).interpreter
48
+ except (OSError, TypeError, ValueError):
49
+ return None
50
+ if ld is None or "musl" not in ld:
51
+ return None
52
+ proc = subprocess.run([ld], stderr=subprocess.PIPE, text=True)
53
+ return _parse_musl_version(proc.stderr)
54
+
55
+
56
+ def platform_tags(archs: Sequence[str]) -> Iterator[str]:
57
+ """Generate musllinux tags compatible to the current platform.
58
+
59
+ :param archs: Sequence of compatible architectures.
60
+ The first one shall be the closest to the actual architecture and be the part of
61
+ platform tag after the ``linux_`` prefix, e.g. ``x86_64``.
62
+ The ``linux_`` prefix is assumed as a prerequisite for the current platform to
63
+ be musllinux-compatible.
64
+
65
+ :returns: An iterator of compatible musllinux tags.
66
+ """
67
+ sys_musl = _get_musl_version(sys.executable)
68
+ if sys_musl is None: # Python not dynamically linked against musl.
69
+ return
70
+ for arch in archs:
71
+ for minor in range(sys_musl.minor, -1, -1):
72
+ yield f"musllinux_{sys_musl.major}_{minor}_{arch}"
73
+
74
+
75
+ if __name__ == "__main__": # pragma: no cover
76
+ import sysconfig
77
+
78
+ plat = sysconfig.get_platform()
79
+ assert plat.startswith("linux-"), "not linux"
80
+
81
+ print("plat:", plat)
82
+ print("musl:", _get_musl_version(sys.executable))
83
+ print("tags:", end=" ")
84
+ for t in platform_tags(re.sub(r"[.-]", "_", plat.split("-", 1)[-1])):
85
+ print(t, end="\n ")
venv/lib/python3.12/site-packages/packaging/_parser.py ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Handwritten parser of dependency specifiers.
2
+
3
+ The docstring for each __parse_* function contains EBNF-inspired grammar representing
4
+ the implementation.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import ast
10
+ from typing import NamedTuple, Sequence, Tuple, Union
11
+
12
+ from ._tokenizer import DEFAULT_RULES, Tokenizer
13
+
14
+
15
+ class Node:
16
+ def __init__(self, value: str) -> None:
17
+ self.value = value
18
+
19
+ def __str__(self) -> str:
20
+ return self.value
21
+
22
+ def __repr__(self) -> str:
23
+ return f"<{self.__class__.__name__}('{self}')>"
24
+
25
+ def serialize(self) -> str:
26
+ raise NotImplementedError
27
+
28
+
29
+ class Variable(Node):
30
+ def serialize(self) -> str:
31
+ return str(self)
32
+
33
+
34
+ class Value(Node):
35
+ def serialize(self) -> str:
36
+ return f'"{self}"'
37
+
38
+
39
+ class Op(Node):
40
+ def serialize(self) -> str:
41
+ return str(self)
42
+
43
+
44
+ MarkerVar = Union[Variable, Value]
45
+ MarkerItem = Tuple[MarkerVar, Op, MarkerVar]
46
+ MarkerAtom = Union[MarkerItem, Sequence["MarkerAtom"]]
47
+ MarkerList = Sequence[Union["MarkerList", MarkerAtom, str]]
48
+
49
+
50
+ class ParsedRequirement(NamedTuple):
51
+ name: str
52
+ url: str
53
+ extras: list[str]
54
+ specifier: str
55
+ marker: MarkerList | None
56
+
57
+
58
+ # --------------------------------------------------------------------------------------
59
+ # Recursive descent parser for dependency specifier
60
+ # --------------------------------------------------------------------------------------
61
+ def parse_requirement(source: str) -> ParsedRequirement:
62
+ return _parse_requirement(Tokenizer(source, rules=DEFAULT_RULES))
63
+
64
+
65
+ def _parse_requirement(tokenizer: Tokenizer) -> ParsedRequirement:
66
+ """
67
+ requirement = WS? IDENTIFIER WS? extras WS? requirement_details
68
+ """
69
+ tokenizer.consume("WS")
70
+
71
+ name_token = tokenizer.expect(
72
+ "IDENTIFIER", expected="package name at the start of dependency specifier"
73
+ )
74
+ name = name_token.text
75
+ tokenizer.consume("WS")
76
+
77
+ extras = _parse_extras(tokenizer)
78
+ tokenizer.consume("WS")
79
+
80
+ url, specifier, marker = _parse_requirement_details(tokenizer)
81
+ tokenizer.expect("END", expected="end of dependency specifier")
82
+
83
+ return ParsedRequirement(name, url, extras, specifier, marker)
84
+
85
+
86
+ def _parse_requirement_details(
87
+ tokenizer: Tokenizer,
88
+ ) -> tuple[str, str, MarkerList | None]:
89
+ """
90
+ requirement_details = AT URL (WS requirement_marker?)?
91
+ | specifier WS? (requirement_marker)?
92
+ """
93
+
94
+ specifier = ""
95
+ url = ""
96
+ marker = None
97
+
98
+ if tokenizer.check("AT"):
99
+ tokenizer.read()
100
+ tokenizer.consume("WS")
101
+
102
+ url_start = tokenizer.position
103
+ url = tokenizer.expect("URL", expected="URL after @").text
104
+ if tokenizer.check("END", peek=True):
105
+ return (url, specifier, marker)
106
+
107
+ tokenizer.expect("WS", expected="whitespace after URL")
108
+
109
+ # The input might end after whitespace.
110
+ if tokenizer.check("END", peek=True):
111
+ return (url, specifier, marker)
112
+
113
+ marker = _parse_requirement_marker(
114
+ tokenizer, span_start=url_start, after="URL and whitespace"
115
+ )
116
+ else:
117
+ specifier_start = tokenizer.position
118
+ specifier = _parse_specifier(tokenizer)
119
+ tokenizer.consume("WS")
120
+
121
+ if tokenizer.check("END", peek=True):
122
+ return (url, specifier, marker)
123
+
124
+ marker = _parse_requirement_marker(
125
+ tokenizer,
126
+ span_start=specifier_start,
127
+ after=(
128
+ "version specifier"
129
+ if specifier
130
+ else "name and no valid version specifier"
131
+ ),
132
+ )
133
+
134
+ return (url, specifier, marker)
135
+
136
+
137
+ def _parse_requirement_marker(
138
+ tokenizer: Tokenizer, *, span_start: int, after: str
139
+ ) -> MarkerList:
140
+ """
141
+ requirement_marker = SEMICOLON marker WS?
142
+ """
143
+
144
+ if not tokenizer.check("SEMICOLON"):
145
+ tokenizer.raise_syntax_error(
146
+ f"Expected end or semicolon (after {after})",
147
+ span_start=span_start,
148
+ )
149
+ tokenizer.read()
150
+
151
+ marker = _parse_marker(tokenizer)
152
+ tokenizer.consume("WS")
153
+
154
+ return marker
155
+
156
+
157
+ def _parse_extras(tokenizer: Tokenizer) -> list[str]:
158
+ """
159
+ extras = (LEFT_BRACKET wsp* extras_list? wsp* RIGHT_BRACKET)?
160
+ """
161
+ if not tokenizer.check("LEFT_BRACKET", peek=True):
162
+ return []
163
+
164
+ with tokenizer.enclosing_tokens(
165
+ "LEFT_BRACKET",
166
+ "RIGHT_BRACKET",
167
+ around="extras",
168
+ ):
169
+ tokenizer.consume("WS")
170
+ extras = _parse_extras_list(tokenizer)
171
+ tokenizer.consume("WS")
172
+
173
+ return extras
174
+
175
+
176
+ def _parse_extras_list(tokenizer: Tokenizer) -> list[str]:
177
+ """
178
+ extras_list = identifier (wsp* ',' wsp* identifier)*
179
+ """
180
+ extras: list[str] = []
181
+
182
+ if not tokenizer.check("IDENTIFIER"):
183
+ return extras
184
+
185
+ extras.append(tokenizer.read().text)
186
+
187
+ while True:
188
+ tokenizer.consume("WS")
189
+ if tokenizer.check("IDENTIFIER", peek=True):
190
+ tokenizer.raise_syntax_error("Expected comma between extra names")
191
+ elif not tokenizer.check("COMMA"):
192
+ break
193
+
194
+ tokenizer.read()
195
+ tokenizer.consume("WS")
196
+
197
+ extra_token = tokenizer.expect("IDENTIFIER", expected="extra name after comma")
198
+ extras.append(extra_token.text)
199
+
200
+ return extras
201
+
202
+
203
+ def _parse_specifier(tokenizer: Tokenizer) -> str:
204
+ """
205
+ specifier = LEFT_PARENTHESIS WS? version_many WS? RIGHT_PARENTHESIS
206
+ | WS? version_many WS?
207
+ """
208
+ with tokenizer.enclosing_tokens(
209
+ "LEFT_PARENTHESIS",
210
+ "RIGHT_PARENTHESIS",
211
+ around="version specifier",
212
+ ):
213
+ tokenizer.consume("WS")
214
+ parsed_specifiers = _parse_version_many(tokenizer)
215
+ tokenizer.consume("WS")
216
+
217
+ return parsed_specifiers
218
+
219
+
220
+ def _parse_version_many(tokenizer: Tokenizer) -> str:
221
+ """
222
+ version_many = (SPECIFIER (WS? COMMA WS? SPECIFIER)*)?
223
+ """
224
+ parsed_specifiers = ""
225
+ while tokenizer.check("SPECIFIER"):
226
+ span_start = tokenizer.position
227
+ parsed_specifiers += tokenizer.read().text
228
+ if tokenizer.check("VERSION_PREFIX_TRAIL", peek=True):
229
+ tokenizer.raise_syntax_error(
230
+ ".* suffix can only be used with `==` or `!=` operators",
231
+ span_start=span_start,
232
+ span_end=tokenizer.position + 1,
233
+ )
234
+ if tokenizer.check("VERSION_LOCAL_LABEL_TRAIL", peek=True):
235
+ tokenizer.raise_syntax_error(
236
+ "Local version label can only be used with `==` or `!=` operators",
237
+ span_start=span_start,
238
+ span_end=tokenizer.position,
239
+ )
240
+ tokenizer.consume("WS")
241
+ if not tokenizer.check("COMMA"):
242
+ break
243
+ parsed_specifiers += tokenizer.read().text
244
+ tokenizer.consume("WS")
245
+
246
+ return parsed_specifiers
247
+
248
+
249
+ # --------------------------------------------------------------------------------------
250
+ # Recursive descent parser for marker expression
251
+ # --------------------------------------------------------------------------------------
252
+ def parse_marker(source: str) -> MarkerList:
253
+ return _parse_full_marker(Tokenizer(source, rules=DEFAULT_RULES))
254
+
255
+
256
+ def _parse_full_marker(tokenizer: Tokenizer) -> MarkerList:
257
+ retval = _parse_marker(tokenizer)
258
+ tokenizer.expect("END", expected="end of marker expression")
259
+ return retval
260
+
261
+
262
+ def _parse_marker(tokenizer: Tokenizer) -> MarkerList:
263
+ """
264
+ marker = marker_atom (BOOLOP marker_atom)+
265
+ """
266
+ expression = [_parse_marker_atom(tokenizer)]
267
+ while tokenizer.check("BOOLOP"):
268
+ token = tokenizer.read()
269
+ expr_right = _parse_marker_atom(tokenizer)
270
+ expression.extend((token.text, expr_right))
271
+ return expression
272
+
273
+
274
+ def _parse_marker_atom(tokenizer: Tokenizer) -> MarkerAtom:
275
+ """
276
+ marker_atom = WS? LEFT_PARENTHESIS WS? marker WS? RIGHT_PARENTHESIS WS?
277
+ | WS? marker_item WS?
278
+ """
279
+
280
+ tokenizer.consume("WS")
281
+ if tokenizer.check("LEFT_PARENTHESIS", peek=True):
282
+ with tokenizer.enclosing_tokens(
283
+ "LEFT_PARENTHESIS",
284
+ "RIGHT_PARENTHESIS",
285
+ around="marker expression",
286
+ ):
287
+ tokenizer.consume("WS")
288
+ marker: MarkerAtom = _parse_marker(tokenizer)
289
+ tokenizer.consume("WS")
290
+ else:
291
+ marker = _parse_marker_item(tokenizer)
292
+ tokenizer.consume("WS")
293
+ return marker
294
+
295
+
296
+ def _parse_marker_item(tokenizer: Tokenizer) -> MarkerItem:
297
+ """
298
+ marker_item = WS? marker_var WS? marker_op WS? marker_var WS?
299
+ """
300
+ tokenizer.consume("WS")
301
+ marker_var_left = _parse_marker_var(tokenizer)
302
+ tokenizer.consume("WS")
303
+ marker_op = _parse_marker_op(tokenizer)
304
+ tokenizer.consume("WS")
305
+ marker_var_right = _parse_marker_var(tokenizer)
306
+ tokenizer.consume("WS")
307
+ return (marker_var_left, marker_op, marker_var_right)
308
+
309
+
310
+ def _parse_marker_var(tokenizer: Tokenizer) -> MarkerVar:
311
+ """
312
+ marker_var = VARIABLE | QUOTED_STRING
313
+ """
314
+ if tokenizer.check("VARIABLE"):
315
+ return process_env_var(tokenizer.read().text.replace(".", "_"))
316
+ elif tokenizer.check("QUOTED_STRING"):
317
+ return process_python_str(tokenizer.read().text)
318
+ else:
319
+ tokenizer.raise_syntax_error(
320
+ message="Expected a marker variable or quoted string"
321
+ )
322
+
323
+
324
+ def process_env_var(env_var: str) -> Variable:
325
+ if env_var in ("platform_python_implementation", "python_implementation"):
326
+ return Variable("platform_python_implementation")
327
+ else:
328
+ return Variable(env_var)
329
+
330
+
331
+ def process_python_str(python_str: str) -> Value:
332
+ value = ast.literal_eval(python_str)
333
+ return Value(str(value))
334
+
335
+
336
+ def _parse_marker_op(tokenizer: Tokenizer) -> Op:
337
+ """
338
+ marker_op = IN | NOT IN | OP
339
+ """
340
+ if tokenizer.check("IN"):
341
+ tokenizer.read()
342
+ return Op("in")
343
+ elif tokenizer.check("NOT"):
344
+ tokenizer.read()
345
+ tokenizer.expect("WS", expected="whitespace after 'not'")
346
+ tokenizer.expect("IN", expected="'in' after 'not'")
347
+ return Op("not in")
348
+ elif tokenizer.check("OP"):
349
+ return Op(tokenizer.read().text)
350
+ else:
351
+ return tokenizer.raise_syntax_error(
352
+ "Expected marker operator, one of <=, <, !=, ==, >=, >, ~=, ===, in, not in"
353
+ )
venv/lib/python3.12/site-packages/packaging/_structures.py ADDED
@@ -0,0 +1,61 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+
6
+ class InfinityType:
7
+ def __repr__(self) -> str:
8
+ return "Infinity"
9
+
10
+ def __hash__(self) -> int:
11
+ return hash(repr(self))
12
+
13
+ def __lt__(self, other: object) -> bool:
14
+ return False
15
+
16
+ def __le__(self, other: object) -> bool:
17
+ return False
18
+
19
+ def __eq__(self, other: object) -> bool:
20
+ return isinstance(other, self.__class__)
21
+
22
+ def __gt__(self, other: object) -> bool:
23
+ return True
24
+
25
+ def __ge__(self, other: object) -> bool:
26
+ return True
27
+
28
+ def __neg__(self: object) -> "NegativeInfinityType":
29
+ return NegativeInfinity
30
+
31
+
32
+ Infinity = InfinityType()
33
+
34
+
35
+ class NegativeInfinityType:
36
+ def __repr__(self) -> str:
37
+ return "-Infinity"
38
+
39
+ def __hash__(self) -> int:
40
+ return hash(repr(self))
41
+
42
+ def __lt__(self, other: object) -> bool:
43
+ return True
44
+
45
+ def __le__(self, other: object) -> bool:
46
+ return True
47
+
48
+ def __eq__(self, other: object) -> bool:
49
+ return isinstance(other, self.__class__)
50
+
51
+ def __gt__(self, other: object) -> bool:
52
+ return False
53
+
54
+ def __ge__(self, other: object) -> bool:
55
+ return False
56
+
57
+ def __neg__(self: object) -> InfinityType:
58
+ return Infinity
59
+
60
+
61
+ NegativeInfinity = NegativeInfinityType()
venv/lib/python3.12/site-packages/packaging/_tokenizer.py ADDED
@@ -0,0 +1,195 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import contextlib
4
+ import re
5
+ from dataclasses import dataclass
6
+ from typing import Iterator, NoReturn
7
+
8
+ from .specifiers import Specifier
9
+
10
+
11
+ @dataclass
12
+ class Token:
13
+ name: str
14
+ text: str
15
+ position: int
16
+
17
+
18
+ class ParserSyntaxError(Exception):
19
+ """The provided source text could not be parsed correctly."""
20
+
21
+ def __init__(
22
+ self,
23
+ message: str,
24
+ *,
25
+ source: str,
26
+ span: tuple[int, int],
27
+ ) -> None:
28
+ self.span = span
29
+ self.message = message
30
+ self.source = source
31
+
32
+ super().__init__()
33
+
34
+ def __str__(self) -> str:
35
+ marker = " " * self.span[0] + "~" * (self.span[1] - self.span[0]) + "^"
36
+ return "\n ".join([self.message, self.source, marker])
37
+
38
+
39
+ DEFAULT_RULES: dict[str, str | re.Pattern[str]] = {
40
+ "LEFT_PARENTHESIS": r"\(",
41
+ "RIGHT_PARENTHESIS": r"\)",
42
+ "LEFT_BRACKET": r"\[",
43
+ "RIGHT_BRACKET": r"\]",
44
+ "SEMICOLON": r";",
45
+ "COMMA": r",",
46
+ "QUOTED_STRING": re.compile(
47
+ r"""
48
+ (
49
+ ('[^']*')
50
+ |
51
+ ("[^"]*")
52
+ )
53
+ """,
54
+ re.VERBOSE,
55
+ ),
56
+ "OP": r"(===|==|~=|!=|<=|>=|<|>)",
57
+ "BOOLOP": r"\b(or|and)\b",
58
+ "IN": r"\bin\b",
59
+ "NOT": r"\bnot\b",
60
+ "VARIABLE": re.compile(
61
+ r"""
62
+ \b(
63
+ python_version
64
+ |python_full_version
65
+ |os[._]name
66
+ |sys[._]platform
67
+ |platform_(release|system)
68
+ |platform[._](version|machine|python_implementation)
69
+ |python_implementation
70
+ |implementation_(name|version)
71
+ |extras?
72
+ |dependency_groups
73
+ )\b
74
+ """,
75
+ re.VERBOSE,
76
+ ),
77
+ "SPECIFIER": re.compile(
78
+ Specifier._operator_regex_str + Specifier._version_regex_str,
79
+ re.VERBOSE | re.IGNORECASE,
80
+ ),
81
+ "AT": r"\@",
82
+ "URL": r"[^ \t]+",
83
+ "IDENTIFIER": r"\b[a-zA-Z0-9][a-zA-Z0-9._-]*\b",
84
+ "VERSION_PREFIX_TRAIL": r"\.\*",
85
+ "VERSION_LOCAL_LABEL_TRAIL": r"\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*",
86
+ "WS": r"[ \t]+",
87
+ "END": r"$",
88
+ }
89
+
90
+
91
+ class Tokenizer:
92
+ """Context-sensitive token parsing.
93
+
94
+ Provides methods to examine the input stream to check whether the next token
95
+ matches.
96
+ """
97
+
98
+ def __init__(
99
+ self,
100
+ source: str,
101
+ *,
102
+ rules: dict[str, str | re.Pattern[str]],
103
+ ) -> None:
104
+ self.source = source
105
+ self.rules: dict[str, re.Pattern[str]] = {
106
+ name: re.compile(pattern) for name, pattern in rules.items()
107
+ }
108
+ self.next_token: Token | None = None
109
+ self.position = 0
110
+
111
+ def consume(self, name: str) -> None:
112
+ """Move beyond provided token name, if at current position."""
113
+ if self.check(name):
114
+ self.read()
115
+
116
+ def check(self, name: str, *, peek: bool = False) -> bool:
117
+ """Check whether the next token has the provided name.
118
+
119
+ By default, if the check succeeds, the token *must* be read before
120
+ another check. If `peek` is set to `True`, the token is not loaded and
121
+ would need to be checked again.
122
+ """
123
+ assert self.next_token is None, (
124
+ f"Cannot check for {name!r}, already have {self.next_token!r}"
125
+ )
126
+ assert name in self.rules, f"Unknown token name: {name!r}"
127
+
128
+ expression = self.rules[name]
129
+
130
+ match = expression.match(self.source, self.position)
131
+ if match is None:
132
+ return False
133
+ if not peek:
134
+ self.next_token = Token(name, match[0], self.position)
135
+ return True
136
+
137
+ def expect(self, name: str, *, expected: str) -> Token:
138
+ """Expect a certain token name next, failing with a syntax error otherwise.
139
+
140
+ The token is *not* read.
141
+ """
142
+ if not self.check(name):
143
+ raise self.raise_syntax_error(f"Expected {expected}")
144
+ return self.read()
145
+
146
+ def read(self) -> Token:
147
+ """Consume the next token and return it."""
148
+ token = self.next_token
149
+ assert token is not None
150
+
151
+ self.position += len(token.text)
152
+ self.next_token = None
153
+
154
+ return token
155
+
156
+ def raise_syntax_error(
157
+ self,
158
+ message: str,
159
+ *,
160
+ span_start: int | None = None,
161
+ span_end: int | None = None,
162
+ ) -> NoReturn:
163
+ """Raise ParserSyntaxError at the given position."""
164
+ span = (
165
+ self.position if span_start is None else span_start,
166
+ self.position if span_end is None else span_end,
167
+ )
168
+ raise ParserSyntaxError(
169
+ message,
170
+ source=self.source,
171
+ span=span,
172
+ )
173
+
174
+ @contextlib.contextmanager
175
+ def enclosing_tokens(
176
+ self, open_token: str, close_token: str, *, around: str
177
+ ) -> Iterator[None]:
178
+ if self.check(open_token):
179
+ open_position = self.position
180
+ self.read()
181
+ else:
182
+ open_position = None
183
+
184
+ yield
185
+
186
+ if open_position is None:
187
+ return
188
+
189
+ if not self.check(close_token):
190
+ self.raise_syntax_error(
191
+ f"Expected matching {close_token} for {open_token}, after {around}",
192
+ span_start=open_position,
193
+ )
194
+
195
+ self.read()
venv/lib/python3.12/site-packages/packaging/markers.py ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+ from __future__ import annotations
6
+
7
+ import operator
8
+ import os
9
+ import platform
10
+ import sys
11
+ from typing import AbstractSet, Any, Callable, Literal, TypedDict, Union, cast
12
+
13
+ from ._parser import MarkerAtom, MarkerList, Op, Value, Variable
14
+ from ._parser import parse_marker as _parse_marker
15
+ from ._tokenizer import ParserSyntaxError
16
+ from .specifiers import InvalidSpecifier, Specifier
17
+ from .utils import canonicalize_name
18
+
19
+ __all__ = [
20
+ "EvaluateContext",
21
+ "InvalidMarker",
22
+ "Marker",
23
+ "UndefinedComparison",
24
+ "UndefinedEnvironmentName",
25
+ "default_environment",
26
+ ]
27
+
28
+ Operator = Callable[[str, Union[str, AbstractSet[str]]], bool]
29
+ EvaluateContext = Literal["metadata", "lock_file", "requirement"]
30
+ MARKERS_ALLOWING_SET = {"extras", "dependency_groups"}
31
+
32
+
33
+ class InvalidMarker(ValueError):
34
+ """
35
+ An invalid marker was found, users should refer to PEP 508.
36
+ """
37
+
38
+
39
+ class UndefinedComparison(ValueError):
40
+ """
41
+ An invalid operation was attempted on a value that doesn't support it.
42
+ """
43
+
44
+
45
+ class UndefinedEnvironmentName(ValueError):
46
+ """
47
+ A name was attempted to be used that does not exist inside of the
48
+ environment.
49
+ """
50
+
51
+
52
+ class Environment(TypedDict):
53
+ implementation_name: str
54
+ """The implementation's identifier, e.g. ``'cpython'``."""
55
+
56
+ implementation_version: str
57
+ """
58
+ The implementation's version, e.g. ``'3.13.0a2'`` for CPython 3.13.0a2, or
59
+ ``'7.3.13'`` for PyPy3.10 v7.3.13.
60
+ """
61
+
62
+ os_name: str
63
+ """
64
+ The value of :py:data:`os.name`. The name of the operating system dependent module
65
+ imported, e.g. ``'posix'``.
66
+ """
67
+
68
+ platform_machine: str
69
+ """
70
+ Returns the machine type, e.g. ``'i386'``.
71
+
72
+ An empty string if the value cannot be determined.
73
+ """
74
+
75
+ platform_release: str
76
+ """
77
+ The system's release, e.g. ``'2.2.0'`` or ``'NT'``.
78
+
79
+ An empty string if the value cannot be determined.
80
+ """
81
+
82
+ platform_system: str
83
+ """
84
+ The system/OS name, e.g. ``'Linux'``, ``'Windows'`` or ``'Java'``.
85
+
86
+ An empty string if the value cannot be determined.
87
+ """
88
+
89
+ platform_version: str
90
+ """
91
+ The system's release version, e.g. ``'#3 on degas'``.
92
+
93
+ An empty string if the value cannot be determined.
94
+ """
95
+
96
+ python_full_version: str
97
+ """
98
+ The Python version as string ``'major.minor.patchlevel'``.
99
+
100
+ Note that unlike the Python :py:data:`sys.version`, this value will always include
101
+ the patchlevel (it defaults to 0).
102
+ """
103
+
104
+ platform_python_implementation: str
105
+ """
106
+ A string identifying the Python implementation, e.g. ``'CPython'``.
107
+ """
108
+
109
+ python_version: str
110
+ """The Python version as string ``'major.minor'``."""
111
+
112
+ sys_platform: str
113
+ """
114
+ This string contains a platform identifier that can be used to append
115
+ platform-specific components to :py:data:`sys.path`, for instance.
116
+
117
+ For Unix systems, except on Linux and AIX, this is the lowercased OS name as
118
+ returned by ``uname -s`` with the first part of the version as returned by
119
+ ``uname -r`` appended, e.g. ``'sunos5'`` or ``'freebsd8'``, at the time when Python
120
+ was built.
121
+ """
122
+
123
+
124
+ def _normalize_extra_values(results: Any) -> Any:
125
+ """
126
+ Normalize extra values.
127
+ """
128
+ if isinstance(results[0], tuple):
129
+ lhs, op, rhs = results[0]
130
+ if isinstance(lhs, Variable) and lhs.value == "extra":
131
+ normalized_extra = canonicalize_name(rhs.value)
132
+ rhs = Value(normalized_extra)
133
+ elif isinstance(rhs, Variable) and rhs.value == "extra":
134
+ normalized_extra = canonicalize_name(lhs.value)
135
+ lhs = Value(normalized_extra)
136
+ results[0] = lhs, op, rhs
137
+ return results
138
+
139
+
140
+ def _format_marker(
141
+ marker: list[str] | MarkerAtom | str, first: bool | None = True
142
+ ) -> str:
143
+ assert isinstance(marker, (list, tuple, str))
144
+
145
+ # Sometimes we have a structure like [[...]] which is a single item list
146
+ # where the single item is itself it's own list. In that case we want skip
147
+ # the rest of this function so that we don't get extraneous () on the
148
+ # outside.
149
+ if (
150
+ isinstance(marker, list)
151
+ and len(marker) == 1
152
+ and isinstance(marker[0], (list, tuple))
153
+ ):
154
+ return _format_marker(marker[0])
155
+
156
+ if isinstance(marker, list):
157
+ inner = (_format_marker(m, first=False) for m in marker)
158
+ if first:
159
+ return " ".join(inner)
160
+ else:
161
+ return "(" + " ".join(inner) + ")"
162
+ elif isinstance(marker, tuple):
163
+ return " ".join([m.serialize() for m in marker])
164
+ else:
165
+ return marker
166
+
167
+
168
+ _operators: dict[str, Operator] = {
169
+ "in": lambda lhs, rhs: lhs in rhs,
170
+ "not in": lambda lhs, rhs: lhs not in rhs,
171
+ "<": operator.lt,
172
+ "<=": operator.le,
173
+ "==": operator.eq,
174
+ "!=": operator.ne,
175
+ ">=": operator.ge,
176
+ ">": operator.gt,
177
+ }
178
+
179
+
180
+ def _eval_op(lhs: str, op: Op, rhs: str | AbstractSet[str]) -> bool:
181
+ if isinstance(rhs, str):
182
+ try:
183
+ spec = Specifier("".join([op.serialize(), rhs]))
184
+ except InvalidSpecifier:
185
+ pass
186
+ else:
187
+ return spec.contains(lhs, prereleases=True)
188
+
189
+ oper: Operator | None = _operators.get(op.serialize())
190
+ if oper is None:
191
+ raise UndefinedComparison(f"Undefined {op!r} on {lhs!r} and {rhs!r}.")
192
+
193
+ return oper(lhs, rhs)
194
+
195
+
196
+ def _normalize(
197
+ lhs: str, rhs: str | AbstractSet[str], key: str
198
+ ) -> tuple[str, str | AbstractSet[str]]:
199
+ # PEP 685 – Comparison of extra names for optional distribution dependencies
200
+ # https://peps.python.org/pep-0685/
201
+ # > When comparing extra names, tools MUST normalize the names being
202
+ # > compared using the semantics outlined in PEP 503 for names
203
+ if key == "extra":
204
+ assert isinstance(rhs, str), "extra value must be a string"
205
+ return (canonicalize_name(lhs), canonicalize_name(rhs))
206
+ if key in MARKERS_ALLOWING_SET:
207
+ if isinstance(rhs, str): # pragma: no cover
208
+ return (canonicalize_name(lhs), canonicalize_name(rhs))
209
+ else:
210
+ return (canonicalize_name(lhs), {canonicalize_name(v) for v in rhs})
211
+
212
+ # other environment markers don't have such standards
213
+ return lhs, rhs
214
+
215
+
216
+ def _evaluate_markers(
217
+ markers: MarkerList, environment: dict[str, str | AbstractSet[str]]
218
+ ) -> bool:
219
+ groups: list[list[bool]] = [[]]
220
+
221
+ for marker in markers:
222
+ assert isinstance(marker, (list, tuple, str))
223
+
224
+ if isinstance(marker, list):
225
+ groups[-1].append(_evaluate_markers(marker, environment))
226
+ elif isinstance(marker, tuple):
227
+ lhs, op, rhs = marker
228
+
229
+ if isinstance(lhs, Variable):
230
+ environment_key = lhs.value
231
+ lhs_value = environment[environment_key]
232
+ rhs_value = rhs.value
233
+ else:
234
+ lhs_value = lhs.value
235
+ environment_key = rhs.value
236
+ rhs_value = environment[environment_key]
237
+ assert isinstance(lhs_value, str), "lhs must be a string"
238
+ lhs_value, rhs_value = _normalize(lhs_value, rhs_value, key=environment_key)
239
+ groups[-1].append(_eval_op(lhs_value, op, rhs_value))
240
+ else:
241
+ assert marker in ["and", "or"]
242
+ if marker == "or":
243
+ groups.append([])
244
+
245
+ return any(all(item) for item in groups)
246
+
247
+
248
+ def format_full_version(info: sys._version_info) -> str:
249
+ version = f"{info.major}.{info.minor}.{info.micro}"
250
+ kind = info.releaselevel
251
+ if kind != "final":
252
+ version += kind[0] + str(info.serial)
253
+ return version
254
+
255
+
256
+ def default_environment() -> Environment:
257
+ iver = format_full_version(sys.implementation.version)
258
+ implementation_name = sys.implementation.name
259
+ return {
260
+ "implementation_name": implementation_name,
261
+ "implementation_version": iver,
262
+ "os_name": os.name,
263
+ "platform_machine": platform.machine(),
264
+ "platform_release": platform.release(),
265
+ "platform_system": platform.system(),
266
+ "platform_version": platform.version(),
267
+ "python_full_version": platform.python_version(),
268
+ "platform_python_implementation": platform.python_implementation(),
269
+ "python_version": ".".join(platform.python_version_tuple()[:2]),
270
+ "sys_platform": sys.platform,
271
+ }
272
+
273
+
274
+ class Marker:
275
+ def __init__(self, marker: str) -> None:
276
+ # Note: We create a Marker object without calling this constructor in
277
+ # packaging.requirements.Requirement. If any additional logic is
278
+ # added here, make sure to mirror/adapt Requirement.
279
+ try:
280
+ self._markers = _normalize_extra_values(_parse_marker(marker))
281
+ # The attribute `_markers` can be described in terms of a recursive type:
282
+ # MarkerList = List[Union[Tuple[Node, ...], str, MarkerList]]
283
+ #
284
+ # For example, the following expression:
285
+ # python_version > "3.6" or (python_version == "3.6" and os_name == "unix")
286
+ #
287
+ # is parsed into:
288
+ # [
289
+ # (<Variable('python_version')>, <Op('>')>, <Value('3.6')>),
290
+ # 'and',
291
+ # [
292
+ # (<Variable('python_version')>, <Op('==')>, <Value('3.6')>),
293
+ # 'or',
294
+ # (<Variable('os_name')>, <Op('==')>, <Value('unix')>)
295
+ # ]
296
+ # ]
297
+ except ParserSyntaxError as e:
298
+ raise InvalidMarker(str(e)) from e
299
+
300
+ def __str__(self) -> str:
301
+ return _format_marker(self._markers)
302
+
303
+ def __repr__(self) -> str:
304
+ return f"<Marker('{self}')>"
305
+
306
+ def __hash__(self) -> int:
307
+ return hash((self.__class__.__name__, str(self)))
308
+
309
+ def __eq__(self, other: Any) -> bool:
310
+ if not isinstance(other, Marker):
311
+ return NotImplemented
312
+
313
+ return str(self) == str(other)
314
+
315
+ def evaluate(
316
+ self,
317
+ environment: dict[str, str] | None = None,
318
+ context: EvaluateContext = "metadata",
319
+ ) -> bool:
320
+ """Evaluate a marker.
321
+
322
+ Return the boolean from evaluating the given marker against the
323
+ environment. environment is an optional argument to override all or
324
+ part of the determined environment. The *context* parameter specifies what
325
+ context the markers are being evaluated for, which influences what markers
326
+ are considered valid. Acceptable values are "metadata" (for core metadata;
327
+ default), "lock_file", and "requirement" (i.e. all other situations).
328
+
329
+ The environment is determined from the current Python process.
330
+ """
331
+ current_environment = cast(
332
+ "dict[str, str | AbstractSet[str]]", default_environment()
333
+ )
334
+ if context == "lock_file":
335
+ current_environment.update(
336
+ extras=frozenset(), dependency_groups=frozenset()
337
+ )
338
+ elif context == "metadata":
339
+ current_environment["extra"] = ""
340
+ if environment is not None:
341
+ current_environment.update(environment)
342
+ # The API used to allow setting extra to None. We need to handle this
343
+ # case for backwards compatibility.
344
+ if "extra" in current_environment and current_environment["extra"] is None:
345
+ current_environment["extra"] = ""
346
+
347
+ return _evaluate_markers(
348
+ self._markers, _repair_python_full_version(current_environment)
349
+ )
350
+
351
+
352
+ def _repair_python_full_version(
353
+ env: dict[str, str | AbstractSet[str]],
354
+ ) -> dict[str, str | AbstractSet[str]]:
355
+ """
356
+ Work around platform.python_version() returning something that is not PEP 440
357
+ compliant for non-tagged Python builds.
358
+ """
359
+ python_full_version = cast(str, env["python_full_version"])
360
+ if python_full_version.endswith("+"):
361
+ env["python_full_version"] = f"{python_full_version}local"
362
+ return env
venv/lib/python3.12/site-packages/packaging/metadata.py ADDED
@@ -0,0 +1,862 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import email.feedparser
4
+ import email.header
5
+ import email.message
6
+ import email.parser
7
+ import email.policy
8
+ import pathlib
9
+ import sys
10
+ import typing
11
+ from typing import (
12
+ Any,
13
+ Callable,
14
+ Generic,
15
+ Literal,
16
+ TypedDict,
17
+ cast,
18
+ )
19
+
20
+ from . import licenses, requirements, specifiers, utils
21
+ from . import version as version_module
22
+ from .licenses import NormalizedLicenseExpression
23
+
24
+ T = typing.TypeVar("T")
25
+
26
+
27
+ if sys.version_info >= (3, 11): # pragma: no cover
28
+ ExceptionGroup = ExceptionGroup
29
+ else: # pragma: no cover
30
+
31
+ class ExceptionGroup(Exception):
32
+ """A minimal implementation of :external:exc:`ExceptionGroup` from Python 3.11.
33
+
34
+ If :external:exc:`ExceptionGroup` is already defined by Python itself,
35
+ that version is used instead.
36
+ """
37
+
38
+ message: str
39
+ exceptions: list[Exception]
40
+
41
+ def __init__(self, message: str, exceptions: list[Exception]) -> None:
42
+ self.message = message
43
+ self.exceptions = exceptions
44
+
45
+ def __repr__(self) -> str:
46
+ return f"{self.__class__.__name__}({self.message!r}, {self.exceptions!r})"
47
+
48
+
49
+ class InvalidMetadata(ValueError):
50
+ """A metadata field contains invalid data."""
51
+
52
+ field: str
53
+ """The name of the field that contains invalid data."""
54
+
55
+ def __init__(self, field: str, message: str) -> None:
56
+ self.field = field
57
+ super().__init__(message)
58
+
59
+
60
+ # The RawMetadata class attempts to make as few assumptions about the underlying
61
+ # serialization formats as possible. The idea is that as long as a serialization
62
+ # formats offer some very basic primitives in *some* way then we can support
63
+ # serializing to and from that format.
64
+ class RawMetadata(TypedDict, total=False):
65
+ """A dictionary of raw core metadata.
66
+
67
+ Each field in core metadata maps to a key of this dictionary (when data is
68
+ provided). The key is lower-case and underscores are used instead of dashes
69
+ compared to the equivalent core metadata field. Any core metadata field that
70
+ can be specified multiple times or can hold multiple values in a single
71
+ field have a key with a plural name. See :class:`Metadata` whose attributes
72
+ match the keys of this dictionary.
73
+
74
+ Core metadata fields that can be specified multiple times are stored as a
75
+ list or dict depending on which is appropriate for the field. Any fields
76
+ which hold multiple values in a single field are stored as a list.
77
+
78
+ """
79
+
80
+ # Metadata 1.0 - PEP 241
81
+ metadata_version: str
82
+ name: str
83
+ version: str
84
+ platforms: list[str]
85
+ summary: str
86
+ description: str
87
+ keywords: list[str]
88
+ home_page: str
89
+ author: str
90
+ author_email: str
91
+ license: str
92
+
93
+ # Metadata 1.1 - PEP 314
94
+ supported_platforms: list[str]
95
+ download_url: str
96
+ classifiers: list[str]
97
+ requires: list[str]
98
+ provides: list[str]
99
+ obsoletes: list[str]
100
+
101
+ # Metadata 1.2 - PEP 345
102
+ maintainer: str
103
+ maintainer_email: str
104
+ requires_dist: list[str]
105
+ provides_dist: list[str]
106
+ obsoletes_dist: list[str]
107
+ requires_python: str
108
+ requires_external: list[str]
109
+ project_urls: dict[str, str]
110
+
111
+ # Metadata 2.0
112
+ # PEP 426 attempted to completely revamp the metadata format
113
+ # but got stuck without ever being able to build consensus on
114
+ # it and ultimately ended up withdrawn.
115
+ #
116
+ # However, a number of tools had started emitting METADATA with
117
+ # `2.0` Metadata-Version, so for historical reasons, this version
118
+ # was skipped.
119
+
120
+ # Metadata 2.1 - PEP 566
121
+ description_content_type: str
122
+ provides_extra: list[str]
123
+
124
+ # Metadata 2.2 - PEP 643
125
+ dynamic: list[str]
126
+
127
+ # Metadata 2.3 - PEP 685
128
+ # No new fields were added in PEP 685, just some edge case were
129
+ # tightened up to provide better interoptability.
130
+
131
+ # Metadata 2.4 - PEP 639
132
+ license_expression: str
133
+ license_files: list[str]
134
+
135
+
136
+ _STRING_FIELDS = {
137
+ "author",
138
+ "author_email",
139
+ "description",
140
+ "description_content_type",
141
+ "download_url",
142
+ "home_page",
143
+ "license",
144
+ "license_expression",
145
+ "maintainer",
146
+ "maintainer_email",
147
+ "metadata_version",
148
+ "name",
149
+ "requires_python",
150
+ "summary",
151
+ "version",
152
+ }
153
+
154
+ _LIST_FIELDS = {
155
+ "classifiers",
156
+ "dynamic",
157
+ "license_files",
158
+ "obsoletes",
159
+ "obsoletes_dist",
160
+ "platforms",
161
+ "provides",
162
+ "provides_dist",
163
+ "provides_extra",
164
+ "requires",
165
+ "requires_dist",
166
+ "requires_external",
167
+ "supported_platforms",
168
+ }
169
+
170
+ _DICT_FIELDS = {
171
+ "project_urls",
172
+ }
173
+
174
+
175
+ def _parse_keywords(data: str) -> list[str]:
176
+ """Split a string of comma-separated keywords into a list of keywords."""
177
+ return [k.strip() for k in data.split(",")]
178
+
179
+
180
+ def _parse_project_urls(data: list[str]) -> dict[str, str]:
181
+ """Parse a list of label/URL string pairings separated by a comma."""
182
+ urls = {}
183
+ for pair in data:
184
+ # Our logic is slightly tricky here as we want to try and do
185
+ # *something* reasonable with malformed data.
186
+ #
187
+ # The main thing that we have to worry about, is data that does
188
+ # not have a ',' at all to split the label from the Value. There
189
+ # isn't a singular right answer here, and we will fail validation
190
+ # later on (if the caller is validating) so it doesn't *really*
191
+ # matter, but since the missing value has to be an empty str
192
+ # and our return value is dict[str, str], if we let the key
193
+ # be the missing value, then they'd have multiple '' values that
194
+ # overwrite each other in a accumulating dict.
195
+ #
196
+ # The other potentional issue is that it's possible to have the
197
+ # same label multiple times in the metadata, with no solid "right"
198
+ # answer with what to do in that case. As such, we'll do the only
199
+ # thing we can, which is treat the field as unparseable and add it
200
+ # to our list of unparsed fields.
201
+ parts = [p.strip() for p in pair.split(",", 1)]
202
+ parts.extend([""] * (max(0, 2 - len(parts)))) # Ensure 2 items
203
+
204
+ # TODO: The spec doesn't say anything about if the keys should be
205
+ # considered case sensitive or not... logically they should
206
+ # be case-preserving and case-insensitive, but doing that
207
+ # would open up more cases where we might have duplicate
208
+ # entries.
209
+ label, url = parts
210
+ if label in urls:
211
+ # The label already exists in our set of urls, so this field
212
+ # is unparseable, and we can just add the whole thing to our
213
+ # unparseable data and stop processing it.
214
+ raise KeyError("duplicate labels in project urls")
215
+ urls[label] = url
216
+
217
+ return urls
218
+
219
+
220
+ def _get_payload(msg: email.message.Message, source: bytes | str) -> str:
221
+ """Get the body of the message."""
222
+ # If our source is a str, then our caller has managed encodings for us,
223
+ # and we don't need to deal with it.
224
+ if isinstance(source, str):
225
+ payload = msg.get_payload()
226
+ assert isinstance(payload, str)
227
+ return payload
228
+ # If our source is a bytes, then we're managing the encoding and we need
229
+ # to deal with it.
230
+ else:
231
+ bpayload = msg.get_payload(decode=True)
232
+ assert isinstance(bpayload, bytes)
233
+ try:
234
+ return bpayload.decode("utf8", "strict")
235
+ except UnicodeDecodeError as exc:
236
+ raise ValueError("payload in an invalid encoding") from exc
237
+
238
+
239
+ # The various parse_FORMAT functions here are intended to be as lenient as
240
+ # possible in their parsing, while still returning a correctly typed
241
+ # RawMetadata.
242
+ #
243
+ # To aid in this, we also generally want to do as little touching of the
244
+ # data as possible, except where there are possibly some historic holdovers
245
+ # that make valid data awkward to work with.
246
+ #
247
+ # While this is a lower level, intermediate format than our ``Metadata``
248
+ # class, some light touch ups can make a massive difference in usability.
249
+
250
+ # Map METADATA fields to RawMetadata.
251
+ _EMAIL_TO_RAW_MAPPING = {
252
+ "author": "author",
253
+ "author-email": "author_email",
254
+ "classifier": "classifiers",
255
+ "description": "description",
256
+ "description-content-type": "description_content_type",
257
+ "download-url": "download_url",
258
+ "dynamic": "dynamic",
259
+ "home-page": "home_page",
260
+ "keywords": "keywords",
261
+ "license": "license",
262
+ "license-expression": "license_expression",
263
+ "license-file": "license_files",
264
+ "maintainer": "maintainer",
265
+ "maintainer-email": "maintainer_email",
266
+ "metadata-version": "metadata_version",
267
+ "name": "name",
268
+ "obsoletes": "obsoletes",
269
+ "obsoletes-dist": "obsoletes_dist",
270
+ "platform": "platforms",
271
+ "project-url": "project_urls",
272
+ "provides": "provides",
273
+ "provides-dist": "provides_dist",
274
+ "provides-extra": "provides_extra",
275
+ "requires": "requires",
276
+ "requires-dist": "requires_dist",
277
+ "requires-external": "requires_external",
278
+ "requires-python": "requires_python",
279
+ "summary": "summary",
280
+ "supported-platform": "supported_platforms",
281
+ "version": "version",
282
+ }
283
+ _RAW_TO_EMAIL_MAPPING = {raw: email for email, raw in _EMAIL_TO_RAW_MAPPING.items()}
284
+
285
+
286
+ def parse_email(data: bytes | str) -> tuple[RawMetadata, dict[str, list[str]]]:
287
+ """Parse a distribution's metadata stored as email headers (e.g. from ``METADATA``).
288
+
289
+ This function returns a two-item tuple of dicts. The first dict is of
290
+ recognized fields from the core metadata specification. Fields that can be
291
+ parsed and translated into Python's built-in types are converted
292
+ appropriately. All other fields are left as-is. Fields that are allowed to
293
+ appear multiple times are stored as lists.
294
+
295
+ The second dict contains all other fields from the metadata. This includes
296
+ any unrecognized fields. It also includes any fields which are expected to
297
+ be parsed into a built-in type but were not formatted appropriately. Finally,
298
+ any fields that are expected to appear only once but are repeated are
299
+ included in this dict.
300
+
301
+ """
302
+ raw: dict[str, str | list[str] | dict[str, str]] = {}
303
+ unparsed: dict[str, list[str]] = {}
304
+
305
+ if isinstance(data, str):
306
+ parsed = email.parser.Parser(policy=email.policy.compat32).parsestr(data)
307
+ else:
308
+ parsed = email.parser.BytesParser(policy=email.policy.compat32).parsebytes(data)
309
+
310
+ # We have to wrap parsed.keys() in a set, because in the case of multiple
311
+ # values for a key (a list), the key will appear multiple times in the
312
+ # list of keys, but we're avoiding that by using get_all().
313
+ for name in frozenset(parsed.keys()):
314
+ # Header names in RFC are case insensitive, so we'll normalize to all
315
+ # lower case to make comparisons easier.
316
+ name = name.lower()
317
+
318
+ # We use get_all() here, even for fields that aren't multiple use,
319
+ # because otherwise someone could have e.g. two Name fields, and we
320
+ # would just silently ignore it rather than doing something about it.
321
+ headers = parsed.get_all(name) or []
322
+
323
+ # The way the email module works when parsing bytes is that it
324
+ # unconditionally decodes the bytes as ascii using the surrogateescape
325
+ # handler. When you pull that data back out (such as with get_all() ),
326
+ # it looks to see if the str has any surrogate escapes, and if it does
327
+ # it wraps it in a Header object instead of returning the string.
328
+ #
329
+ # As such, we'll look for those Header objects, and fix up the encoding.
330
+ value = []
331
+ # Flag if we have run into any issues processing the headers, thus
332
+ # signalling that the data belongs in 'unparsed'.
333
+ valid_encoding = True
334
+ for h in headers:
335
+ # It's unclear if this can return more types than just a Header or
336
+ # a str, so we'll just assert here to make sure.
337
+ assert isinstance(h, (email.header.Header, str))
338
+
339
+ # If it's a header object, we need to do our little dance to get
340
+ # the real data out of it. In cases where there is invalid data
341
+ # we're going to end up with mojibake, but there's no obvious, good
342
+ # way around that without reimplementing parts of the Header object
343
+ # ourselves.
344
+ #
345
+ # That should be fine since, if mojibacked happens, this key is
346
+ # going into the unparsed dict anyways.
347
+ if isinstance(h, email.header.Header):
348
+ # The Header object stores it's data as chunks, and each chunk
349
+ # can be independently encoded, so we'll need to check each
350
+ # of them.
351
+ chunks: list[tuple[bytes, str | None]] = []
352
+ for bin, encoding in email.header.decode_header(h):
353
+ try:
354
+ bin.decode("utf8", "strict")
355
+ except UnicodeDecodeError:
356
+ # Enable mojibake.
357
+ encoding = "latin1"
358
+ valid_encoding = False
359
+ else:
360
+ encoding = "utf8"
361
+ chunks.append((bin, encoding))
362
+
363
+ # Turn our chunks back into a Header object, then let that
364
+ # Header object do the right thing to turn them into a
365
+ # string for us.
366
+ value.append(str(email.header.make_header(chunks)))
367
+ # This is already a string, so just add it.
368
+ else:
369
+ value.append(h)
370
+
371
+ # We've processed all of our values to get them into a list of str,
372
+ # but we may have mojibake data, in which case this is an unparsed
373
+ # field.
374
+ if not valid_encoding:
375
+ unparsed[name] = value
376
+ continue
377
+
378
+ raw_name = _EMAIL_TO_RAW_MAPPING.get(name)
379
+ if raw_name is None:
380
+ # This is a bit of a weird situation, we've encountered a key that
381
+ # we don't know what it means, so we don't know whether it's meant
382
+ # to be a list or not.
383
+ #
384
+ # Since we can't really tell one way or another, we'll just leave it
385
+ # as a list, even though it may be a single item list, because that's
386
+ # what makes the most sense for email headers.
387
+ unparsed[name] = value
388
+ continue
389
+
390
+ # If this is one of our string fields, then we'll check to see if our
391
+ # value is a list of a single item. If it is then we'll assume that
392
+ # it was emitted as a single string, and unwrap the str from inside
393
+ # the list.
394
+ #
395
+ # If it's any other kind of data, then we haven't the faintest clue
396
+ # what we should parse it as, and we have to just add it to our list
397
+ # of unparsed stuff.
398
+ if raw_name in _STRING_FIELDS and len(value) == 1:
399
+ raw[raw_name] = value[0]
400
+ # If this is one of our list of string fields, then we can just assign
401
+ # the value, since email *only* has strings, and our get_all() call
402
+ # above ensures that this is a list.
403
+ elif raw_name in _LIST_FIELDS:
404
+ raw[raw_name] = value
405
+ # Special Case: Keywords
406
+ # The keywords field is implemented in the metadata spec as a str,
407
+ # but it conceptually is a list of strings, and is serialized using
408
+ # ", ".join(keywords), so we'll do some light data massaging to turn
409
+ # this into what it logically is.
410
+ elif raw_name == "keywords" and len(value) == 1:
411
+ raw[raw_name] = _parse_keywords(value[0])
412
+ # Special Case: Project-URL
413
+ # The project urls is implemented in the metadata spec as a list of
414
+ # specially-formatted strings that represent a key and a value, which
415
+ # is fundamentally a mapping, however the email format doesn't support
416
+ # mappings in a sane way, so it was crammed into a list of strings
417
+ # instead.
418
+ #
419
+ # We will do a little light data massaging to turn this into a map as
420
+ # it logically should be.
421
+ elif raw_name == "project_urls":
422
+ try:
423
+ raw[raw_name] = _parse_project_urls(value)
424
+ except KeyError:
425
+ unparsed[name] = value
426
+ # Nothing that we've done has managed to parse this, so it'll just
427
+ # throw it in our unparseable data and move on.
428
+ else:
429
+ unparsed[name] = value
430
+
431
+ # We need to support getting the Description from the message payload in
432
+ # addition to getting it from the the headers. This does mean, though, there
433
+ # is the possibility of it being set both ways, in which case we put both
434
+ # in 'unparsed' since we don't know which is right.
435
+ try:
436
+ payload = _get_payload(parsed, data)
437
+ except ValueError:
438
+ unparsed.setdefault("description", []).append(
439
+ parsed.get_payload(decode=isinstance(data, bytes)) # type: ignore[call-overload]
440
+ )
441
+ else:
442
+ if payload:
443
+ # Check to see if we've already got a description, if so then both
444
+ # it, and this body move to unparseable.
445
+ if "description" in raw:
446
+ description_header = cast(str, raw.pop("description"))
447
+ unparsed.setdefault("description", []).extend(
448
+ [description_header, payload]
449
+ )
450
+ elif "description" in unparsed:
451
+ unparsed["description"].append(payload)
452
+ else:
453
+ raw["description"] = payload
454
+
455
+ # We need to cast our `raw` to a metadata, because a TypedDict only support
456
+ # literal key names, but we're computing our key names on purpose, but the
457
+ # way this function is implemented, our `TypedDict` can only have valid key
458
+ # names.
459
+ return cast(RawMetadata, raw), unparsed
460
+
461
+
462
+ _NOT_FOUND = object()
463
+
464
+
465
+ # Keep the two values in sync.
466
+ _VALID_METADATA_VERSIONS = ["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"]
467
+ _MetadataVersion = Literal["1.0", "1.1", "1.2", "2.1", "2.2", "2.3", "2.4"]
468
+
469
+ _REQUIRED_ATTRS = frozenset(["metadata_version", "name", "version"])
470
+
471
+
472
+ class _Validator(Generic[T]):
473
+ """Validate a metadata field.
474
+
475
+ All _process_*() methods correspond to a core metadata field. The method is
476
+ called with the field's raw value. If the raw value is valid it is returned
477
+ in its "enriched" form (e.g. ``version.Version`` for the ``Version`` field).
478
+ If the raw value is invalid, :exc:`InvalidMetadata` is raised (with a cause
479
+ as appropriate).
480
+ """
481
+
482
+ name: str
483
+ raw_name: str
484
+ added: _MetadataVersion
485
+
486
+ def __init__(
487
+ self,
488
+ *,
489
+ added: _MetadataVersion = "1.0",
490
+ ) -> None:
491
+ self.added = added
492
+
493
+ def __set_name__(self, _owner: Metadata, name: str) -> None:
494
+ self.name = name
495
+ self.raw_name = _RAW_TO_EMAIL_MAPPING[name]
496
+
497
+ def __get__(self, instance: Metadata, _owner: type[Metadata]) -> T:
498
+ # With Python 3.8, the caching can be replaced with functools.cached_property().
499
+ # No need to check the cache as attribute lookup will resolve into the
500
+ # instance's __dict__ before __get__ is called.
501
+ cache = instance.__dict__
502
+ value = instance._raw.get(self.name)
503
+
504
+ # To make the _process_* methods easier, we'll check if the value is None
505
+ # and if this field is NOT a required attribute, and if both of those
506
+ # things are true, we'll skip the the converter. This will mean that the
507
+ # converters never have to deal with the None union.
508
+ if self.name in _REQUIRED_ATTRS or value is not None:
509
+ try:
510
+ converter: Callable[[Any], T] = getattr(self, f"_process_{self.name}")
511
+ except AttributeError:
512
+ pass
513
+ else:
514
+ value = converter(value)
515
+
516
+ cache[self.name] = value
517
+ try:
518
+ del instance._raw[self.name] # type: ignore[misc]
519
+ except KeyError:
520
+ pass
521
+
522
+ return cast(T, value)
523
+
524
+ def _invalid_metadata(
525
+ self, msg: str, cause: Exception | None = None
526
+ ) -> InvalidMetadata:
527
+ exc = InvalidMetadata(
528
+ self.raw_name, msg.format_map({"field": repr(self.raw_name)})
529
+ )
530
+ exc.__cause__ = cause
531
+ return exc
532
+
533
+ def _process_metadata_version(self, value: str) -> _MetadataVersion:
534
+ # Implicitly makes Metadata-Version required.
535
+ if value not in _VALID_METADATA_VERSIONS:
536
+ raise self._invalid_metadata(f"{value!r} is not a valid metadata version")
537
+ return cast(_MetadataVersion, value)
538
+
539
+ def _process_name(self, value: str) -> str:
540
+ if not value:
541
+ raise self._invalid_metadata("{field} is a required field")
542
+ # Validate the name as a side-effect.
543
+ try:
544
+ utils.canonicalize_name(value, validate=True)
545
+ except utils.InvalidName as exc:
546
+ raise self._invalid_metadata(
547
+ f"{value!r} is invalid for {{field}}", cause=exc
548
+ ) from exc
549
+ else:
550
+ return value
551
+
552
+ def _process_version(self, value: str) -> version_module.Version:
553
+ if not value:
554
+ raise self._invalid_metadata("{field} is a required field")
555
+ try:
556
+ return version_module.parse(value)
557
+ except version_module.InvalidVersion as exc:
558
+ raise self._invalid_metadata(
559
+ f"{value!r} is invalid for {{field}}", cause=exc
560
+ ) from exc
561
+
562
+ def _process_summary(self, value: str) -> str:
563
+ """Check the field contains no newlines."""
564
+ if "\n" in value:
565
+ raise self._invalid_metadata("{field} must be a single line")
566
+ return value
567
+
568
+ def _process_description_content_type(self, value: str) -> str:
569
+ content_types = {"text/plain", "text/x-rst", "text/markdown"}
570
+ message = email.message.EmailMessage()
571
+ message["content-type"] = value
572
+
573
+ content_type, parameters = (
574
+ # Defaults to `text/plain` if parsing failed.
575
+ message.get_content_type().lower(),
576
+ message["content-type"].params,
577
+ )
578
+ # Check if content-type is valid or defaulted to `text/plain` and thus was
579
+ # not parseable.
580
+ if content_type not in content_types or content_type not in value.lower():
581
+ raise self._invalid_metadata(
582
+ f"{{field}} must be one of {list(content_types)}, not {value!r}"
583
+ )
584
+
585
+ charset = parameters.get("charset", "UTF-8")
586
+ if charset != "UTF-8":
587
+ raise self._invalid_metadata(
588
+ f"{{field}} can only specify the UTF-8 charset, not {list(charset)}"
589
+ )
590
+
591
+ markdown_variants = {"GFM", "CommonMark"}
592
+ variant = parameters.get("variant", "GFM") # Use an acceptable default.
593
+ if content_type == "text/markdown" and variant not in markdown_variants:
594
+ raise self._invalid_metadata(
595
+ f"valid Markdown variants for {{field}} are {list(markdown_variants)}, "
596
+ f"not {variant!r}",
597
+ )
598
+ return value
599
+
600
+ def _process_dynamic(self, value: list[str]) -> list[str]:
601
+ for dynamic_field in map(str.lower, value):
602
+ if dynamic_field in {"name", "version", "metadata-version"}:
603
+ raise self._invalid_metadata(
604
+ f"{dynamic_field!r} is not allowed as a dynamic field"
605
+ )
606
+ elif dynamic_field not in _EMAIL_TO_RAW_MAPPING:
607
+ raise self._invalid_metadata(
608
+ f"{dynamic_field!r} is not a valid dynamic field"
609
+ )
610
+ return list(map(str.lower, value))
611
+
612
+ def _process_provides_extra(
613
+ self,
614
+ value: list[str],
615
+ ) -> list[utils.NormalizedName]:
616
+ normalized_names = []
617
+ try:
618
+ for name in value:
619
+ normalized_names.append(utils.canonicalize_name(name, validate=True))
620
+ except utils.InvalidName as exc:
621
+ raise self._invalid_metadata(
622
+ f"{name!r} is invalid for {{field}}", cause=exc
623
+ ) from exc
624
+ else:
625
+ return normalized_names
626
+
627
+ def _process_requires_python(self, value: str) -> specifiers.SpecifierSet:
628
+ try:
629
+ return specifiers.SpecifierSet(value)
630
+ except specifiers.InvalidSpecifier as exc:
631
+ raise self._invalid_metadata(
632
+ f"{value!r} is invalid for {{field}}", cause=exc
633
+ ) from exc
634
+
635
+ def _process_requires_dist(
636
+ self,
637
+ value: list[str],
638
+ ) -> list[requirements.Requirement]:
639
+ reqs = []
640
+ try:
641
+ for req in value:
642
+ reqs.append(requirements.Requirement(req))
643
+ except requirements.InvalidRequirement as exc:
644
+ raise self._invalid_metadata(
645
+ f"{req!r} is invalid for {{field}}", cause=exc
646
+ ) from exc
647
+ else:
648
+ return reqs
649
+
650
+ def _process_license_expression(
651
+ self, value: str
652
+ ) -> NormalizedLicenseExpression | None:
653
+ try:
654
+ return licenses.canonicalize_license_expression(value)
655
+ except ValueError as exc:
656
+ raise self._invalid_metadata(
657
+ f"{value!r} is invalid for {{field}}", cause=exc
658
+ ) from exc
659
+
660
+ def _process_license_files(self, value: list[str]) -> list[str]:
661
+ paths = []
662
+ for path in value:
663
+ if ".." in path:
664
+ raise self._invalid_metadata(
665
+ f"{path!r} is invalid for {{field}}, "
666
+ "parent directory indicators are not allowed"
667
+ )
668
+ if "*" in path:
669
+ raise self._invalid_metadata(
670
+ f"{path!r} is invalid for {{field}}, paths must be resolved"
671
+ )
672
+ if (
673
+ pathlib.PurePosixPath(path).is_absolute()
674
+ or pathlib.PureWindowsPath(path).is_absolute()
675
+ ):
676
+ raise self._invalid_metadata(
677
+ f"{path!r} is invalid for {{field}}, paths must be relative"
678
+ )
679
+ if pathlib.PureWindowsPath(path).as_posix() != path:
680
+ raise self._invalid_metadata(
681
+ f"{path!r} is invalid for {{field}}, paths must use '/' delimiter"
682
+ )
683
+ paths.append(path)
684
+ return paths
685
+
686
+
687
+ class Metadata:
688
+ """Representation of distribution metadata.
689
+
690
+ Compared to :class:`RawMetadata`, this class provides objects representing
691
+ metadata fields instead of only using built-in types. Any invalid metadata
692
+ will cause :exc:`InvalidMetadata` to be raised (with a
693
+ :py:attr:`~BaseException.__cause__` attribute as appropriate).
694
+ """
695
+
696
+ _raw: RawMetadata
697
+
698
+ @classmethod
699
+ def from_raw(cls, data: RawMetadata, *, validate: bool = True) -> Metadata:
700
+ """Create an instance from :class:`RawMetadata`.
701
+
702
+ If *validate* is true, all metadata will be validated. All exceptions
703
+ related to validation will be gathered and raised as an :class:`ExceptionGroup`.
704
+ """
705
+ ins = cls()
706
+ ins._raw = data.copy() # Mutations occur due to caching enriched values.
707
+
708
+ if validate:
709
+ exceptions: list[Exception] = []
710
+ try:
711
+ metadata_version = ins.metadata_version
712
+ metadata_age = _VALID_METADATA_VERSIONS.index(metadata_version)
713
+ except InvalidMetadata as metadata_version_exc:
714
+ exceptions.append(metadata_version_exc)
715
+ metadata_version = None
716
+
717
+ # Make sure to check for the fields that are present, the required
718
+ # fields (so their absence can be reported).
719
+ fields_to_check = frozenset(ins._raw) | _REQUIRED_ATTRS
720
+ # Remove fields that have already been checked.
721
+ fields_to_check -= {"metadata_version"}
722
+
723
+ for key in fields_to_check:
724
+ try:
725
+ if metadata_version:
726
+ # Can't use getattr() as that triggers descriptor protocol which
727
+ # will fail due to no value for the instance argument.
728
+ try:
729
+ field_metadata_version = cls.__dict__[key].added
730
+ except KeyError:
731
+ exc = InvalidMetadata(key, f"unrecognized field: {key!r}")
732
+ exceptions.append(exc)
733
+ continue
734
+ field_age = _VALID_METADATA_VERSIONS.index(
735
+ field_metadata_version
736
+ )
737
+ if field_age > metadata_age:
738
+ field = _RAW_TO_EMAIL_MAPPING[key]
739
+ exc = InvalidMetadata(
740
+ field,
741
+ f"{field} introduced in metadata version "
742
+ f"{field_metadata_version}, not {metadata_version}",
743
+ )
744
+ exceptions.append(exc)
745
+ continue
746
+ getattr(ins, key)
747
+ except InvalidMetadata as exc:
748
+ exceptions.append(exc)
749
+
750
+ if exceptions:
751
+ raise ExceptionGroup("invalid metadata", exceptions)
752
+
753
+ return ins
754
+
755
+ @classmethod
756
+ def from_email(cls, data: bytes | str, *, validate: bool = True) -> Metadata:
757
+ """Parse metadata from email headers.
758
+
759
+ If *validate* is true, the metadata will be validated. All exceptions
760
+ related to validation will be gathered and raised as an :class:`ExceptionGroup`.
761
+ """
762
+ raw, unparsed = parse_email(data)
763
+
764
+ if validate:
765
+ exceptions: list[Exception] = []
766
+ for unparsed_key in unparsed:
767
+ if unparsed_key in _EMAIL_TO_RAW_MAPPING:
768
+ message = f"{unparsed_key!r} has invalid data"
769
+ else:
770
+ message = f"unrecognized field: {unparsed_key!r}"
771
+ exceptions.append(InvalidMetadata(unparsed_key, message))
772
+
773
+ if exceptions:
774
+ raise ExceptionGroup("unparsed", exceptions)
775
+
776
+ try:
777
+ return cls.from_raw(raw, validate=validate)
778
+ except ExceptionGroup as exc_group:
779
+ raise ExceptionGroup(
780
+ "invalid or unparsed metadata", exc_group.exceptions
781
+ ) from None
782
+
783
+ metadata_version: _Validator[_MetadataVersion] = _Validator()
784
+ """:external:ref:`core-metadata-metadata-version`
785
+ (required; validated to be a valid metadata version)"""
786
+ # `name` is not normalized/typed to NormalizedName so as to provide access to
787
+ # the original/raw name.
788
+ name: _Validator[str] = _Validator()
789
+ """:external:ref:`core-metadata-name`
790
+ (required; validated using :func:`~packaging.utils.canonicalize_name` and its
791
+ *validate* parameter)"""
792
+ version: _Validator[version_module.Version] = _Validator()
793
+ """:external:ref:`core-metadata-version` (required)"""
794
+ dynamic: _Validator[list[str] | None] = _Validator(
795
+ added="2.2",
796
+ )
797
+ """:external:ref:`core-metadata-dynamic`
798
+ (validated against core metadata field names and lowercased)"""
799
+ platforms: _Validator[list[str] | None] = _Validator()
800
+ """:external:ref:`core-metadata-platform`"""
801
+ supported_platforms: _Validator[list[str] | None] = _Validator(added="1.1")
802
+ """:external:ref:`core-metadata-supported-platform`"""
803
+ summary: _Validator[str | None] = _Validator()
804
+ """:external:ref:`core-metadata-summary` (validated to contain no newlines)"""
805
+ description: _Validator[str | None] = _Validator() # TODO 2.1: can be in body
806
+ """:external:ref:`core-metadata-description`"""
807
+ description_content_type: _Validator[str | None] = _Validator(added="2.1")
808
+ """:external:ref:`core-metadata-description-content-type` (validated)"""
809
+ keywords: _Validator[list[str] | None] = _Validator()
810
+ """:external:ref:`core-metadata-keywords`"""
811
+ home_page: _Validator[str | None] = _Validator()
812
+ """:external:ref:`core-metadata-home-page`"""
813
+ download_url: _Validator[str | None] = _Validator(added="1.1")
814
+ """:external:ref:`core-metadata-download-url`"""
815
+ author: _Validator[str | None] = _Validator()
816
+ """:external:ref:`core-metadata-author`"""
817
+ author_email: _Validator[str | None] = _Validator()
818
+ """:external:ref:`core-metadata-author-email`"""
819
+ maintainer: _Validator[str | None] = _Validator(added="1.2")
820
+ """:external:ref:`core-metadata-maintainer`"""
821
+ maintainer_email: _Validator[str | None] = _Validator(added="1.2")
822
+ """:external:ref:`core-metadata-maintainer-email`"""
823
+ license: _Validator[str | None] = _Validator()
824
+ """:external:ref:`core-metadata-license`"""
825
+ license_expression: _Validator[NormalizedLicenseExpression | None] = _Validator(
826
+ added="2.4"
827
+ )
828
+ """:external:ref:`core-metadata-license-expression`"""
829
+ license_files: _Validator[list[str] | None] = _Validator(added="2.4")
830
+ """:external:ref:`core-metadata-license-file`"""
831
+ classifiers: _Validator[list[str] | None] = _Validator(added="1.1")
832
+ """:external:ref:`core-metadata-classifier`"""
833
+ requires_dist: _Validator[list[requirements.Requirement] | None] = _Validator(
834
+ added="1.2"
835
+ )
836
+ """:external:ref:`core-metadata-requires-dist`"""
837
+ requires_python: _Validator[specifiers.SpecifierSet | None] = _Validator(
838
+ added="1.2"
839
+ )
840
+ """:external:ref:`core-metadata-requires-python`"""
841
+ # Because `Requires-External` allows for non-PEP 440 version specifiers, we
842
+ # don't do any processing on the values.
843
+ requires_external: _Validator[list[str] | None] = _Validator(added="1.2")
844
+ """:external:ref:`core-metadata-requires-external`"""
845
+ project_urls: _Validator[dict[str, str] | None] = _Validator(added="1.2")
846
+ """:external:ref:`core-metadata-project-url`"""
847
+ # PEP 685 lets us raise an error if an extra doesn't pass `Name` validation
848
+ # regardless of metadata version.
849
+ provides_extra: _Validator[list[utils.NormalizedName] | None] = _Validator(
850
+ added="2.1",
851
+ )
852
+ """:external:ref:`core-metadata-provides-extra`"""
853
+ provides_dist: _Validator[list[str] | None] = _Validator(added="1.2")
854
+ """:external:ref:`core-metadata-provides-dist`"""
855
+ obsoletes_dist: _Validator[list[str] | None] = _Validator(added="1.2")
856
+ """:external:ref:`core-metadata-obsoletes-dist`"""
857
+ requires: _Validator[list[str] | None] = _Validator(added="1.1")
858
+ """``Requires`` (deprecated)"""
859
+ provides: _Validator[list[str] | None] = _Validator(added="1.1")
860
+ """``Provides`` (deprecated)"""
861
+ obsoletes: _Validator[list[str] | None] = _Validator(added="1.1")
862
+ """``Obsoletes`` (deprecated)"""
venv/lib/python3.12/site-packages/packaging/py.typed ADDED
File without changes
venv/lib/python3.12/site-packages/packaging/requirements.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ from __future__ import annotations
5
+
6
+ from typing import Any, Iterator
7
+
8
+ from ._parser import parse_requirement as _parse_requirement
9
+ from ._tokenizer import ParserSyntaxError
10
+ from .markers import Marker, _normalize_extra_values
11
+ from .specifiers import SpecifierSet
12
+ from .utils import canonicalize_name
13
+
14
+
15
+ class InvalidRequirement(ValueError):
16
+ """
17
+ An invalid requirement was found, users should refer to PEP 508.
18
+ """
19
+
20
+
21
+ class Requirement:
22
+ """Parse a requirement.
23
+
24
+ Parse a given requirement string into its parts, such as name, specifier,
25
+ URL, and extras. Raises InvalidRequirement on a badly-formed requirement
26
+ string.
27
+ """
28
+
29
+ # TODO: Can we test whether something is contained within a requirement?
30
+ # If so how do we do that? Do we need to test against the _name_ of
31
+ # the thing as well as the version? What about the markers?
32
+ # TODO: Can we normalize the name and extra name?
33
+
34
+ def __init__(self, requirement_string: str) -> None:
35
+ try:
36
+ parsed = _parse_requirement(requirement_string)
37
+ except ParserSyntaxError as e:
38
+ raise InvalidRequirement(str(e)) from e
39
+
40
+ self.name: str = parsed.name
41
+ self.url: str | None = parsed.url or None
42
+ self.extras: set[str] = set(parsed.extras or [])
43
+ self.specifier: SpecifierSet = SpecifierSet(parsed.specifier)
44
+ self.marker: Marker | None = None
45
+ if parsed.marker is not None:
46
+ self.marker = Marker.__new__(Marker)
47
+ self.marker._markers = _normalize_extra_values(parsed.marker)
48
+
49
+ def _iter_parts(self, name: str) -> Iterator[str]:
50
+ yield name
51
+
52
+ if self.extras:
53
+ formatted_extras = ",".join(sorted(self.extras))
54
+ yield f"[{formatted_extras}]"
55
+
56
+ if self.specifier:
57
+ yield str(self.specifier)
58
+
59
+ if self.url:
60
+ yield f"@ {self.url}"
61
+ if self.marker:
62
+ yield " "
63
+
64
+ if self.marker:
65
+ yield f"; {self.marker}"
66
+
67
+ def __str__(self) -> str:
68
+ return "".join(self._iter_parts(self.name))
69
+
70
+ def __repr__(self) -> str:
71
+ return f"<Requirement('{self}')>"
72
+
73
+ def __hash__(self) -> int:
74
+ return hash(
75
+ (
76
+ self.__class__.__name__,
77
+ *self._iter_parts(canonicalize_name(self.name)),
78
+ )
79
+ )
80
+
81
+ def __eq__(self, other: Any) -> bool:
82
+ if not isinstance(other, Requirement):
83
+ return NotImplemented
84
+
85
+ return (
86
+ canonicalize_name(self.name) == canonicalize_name(other.name)
87
+ and self.extras == other.extras
88
+ and self.specifier == other.specifier
89
+ and self.url == other.url
90
+ and self.marker == other.marker
91
+ )
venv/lib/python3.12/site-packages/packaging/specifiers.py ADDED
@@ -0,0 +1,1019 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ """
5
+ .. testsetup::
6
+
7
+ from packaging.specifiers import Specifier, SpecifierSet, InvalidSpecifier
8
+ from packaging.version import Version
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import abc
14
+ import itertools
15
+ import re
16
+ from typing import Callable, Iterable, Iterator, TypeVar, Union
17
+
18
+ from .utils import canonicalize_version
19
+ from .version import Version
20
+
21
+ UnparsedVersion = Union[Version, str]
22
+ UnparsedVersionVar = TypeVar("UnparsedVersionVar", bound=UnparsedVersion)
23
+ CallableOperator = Callable[[Version, str], bool]
24
+
25
+
26
+ def _coerce_version(version: UnparsedVersion) -> Version:
27
+ if not isinstance(version, Version):
28
+ version = Version(version)
29
+ return version
30
+
31
+
32
+ class InvalidSpecifier(ValueError):
33
+ """
34
+ Raised when attempting to create a :class:`Specifier` with a specifier
35
+ string that is invalid.
36
+
37
+ >>> Specifier("lolwat")
38
+ Traceback (most recent call last):
39
+ ...
40
+ packaging.specifiers.InvalidSpecifier: Invalid specifier: 'lolwat'
41
+ """
42
+
43
+
44
+ class BaseSpecifier(metaclass=abc.ABCMeta):
45
+ @abc.abstractmethod
46
+ def __str__(self) -> str:
47
+ """
48
+ Returns the str representation of this Specifier-like object. This
49
+ should be representative of the Specifier itself.
50
+ """
51
+
52
+ @abc.abstractmethod
53
+ def __hash__(self) -> int:
54
+ """
55
+ Returns a hash value for this Specifier-like object.
56
+ """
57
+
58
+ @abc.abstractmethod
59
+ def __eq__(self, other: object) -> bool:
60
+ """
61
+ Returns a boolean representing whether or not the two Specifier-like
62
+ objects are equal.
63
+
64
+ :param other: The other object to check against.
65
+ """
66
+
67
+ @property
68
+ @abc.abstractmethod
69
+ def prereleases(self) -> bool | None:
70
+ """Whether or not pre-releases as a whole are allowed.
71
+
72
+ This can be set to either ``True`` or ``False`` to explicitly enable or disable
73
+ prereleases or it can be set to ``None`` (the default) to use default semantics.
74
+ """
75
+
76
+ @prereleases.setter
77
+ def prereleases(self, value: bool) -> None:
78
+ """Setter for :attr:`prereleases`.
79
+
80
+ :param value: The value to set.
81
+ """
82
+
83
+ @abc.abstractmethod
84
+ def contains(self, item: str, prereleases: bool | None = None) -> bool:
85
+ """
86
+ Determines if the given item is contained within this specifier.
87
+ """
88
+
89
+ @abc.abstractmethod
90
+ def filter(
91
+ self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None
92
+ ) -> Iterator[UnparsedVersionVar]:
93
+ """
94
+ Takes an iterable of items and filters them so that only items which
95
+ are contained within this specifier are allowed in it.
96
+ """
97
+
98
+
99
+ class Specifier(BaseSpecifier):
100
+ """This class abstracts handling of version specifiers.
101
+
102
+ .. tip::
103
+
104
+ It is generally not required to instantiate this manually. You should instead
105
+ prefer to work with :class:`SpecifierSet` instead, which can parse
106
+ comma-separated version specifiers (which is what package metadata contains).
107
+ """
108
+
109
+ _operator_regex_str = r"""
110
+ (?P<operator>(~=|==|!=|<=|>=|<|>|===))
111
+ """
112
+ _version_regex_str = r"""
113
+ (?P<version>
114
+ (?:
115
+ # The identity operators allow for an escape hatch that will
116
+ # do an exact string match of the version you wish to install.
117
+ # This will not be parsed by PEP 440 and we cannot determine
118
+ # any semantic meaning from it. This operator is discouraged
119
+ # but included entirely as an escape hatch.
120
+ (?<====) # Only match for the identity operator
121
+ \s*
122
+ [^\s;)]* # The arbitrary version can be just about anything,
123
+ # we match everything except for whitespace, a
124
+ # semi-colon for marker support, and a closing paren
125
+ # since versions can be enclosed in them.
126
+ )
127
+ |
128
+ (?:
129
+ # The (non)equality operators allow for wild card and local
130
+ # versions to be specified so we have to define these two
131
+ # operators separately to enable that.
132
+ (?<===|!=) # Only match for equals and not equals
133
+
134
+ \s*
135
+ v?
136
+ (?:[0-9]+!)? # epoch
137
+ [0-9]+(?:\.[0-9]+)* # release
138
+
139
+ # You cannot use a wild card and a pre-release, post-release, a dev or
140
+ # local version together so group them with a | and make them optional.
141
+ (?:
142
+ \.\* # Wild card syntax of .*
143
+ |
144
+ (?: # pre release
145
+ [-_\.]?
146
+ (alpha|beta|preview|pre|a|b|c|rc)
147
+ [-_\.]?
148
+ [0-9]*
149
+ )?
150
+ (?: # post release
151
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
152
+ )?
153
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
154
+ (?:\+[a-z0-9]+(?:[-_\.][a-z0-9]+)*)? # local
155
+ )?
156
+ )
157
+ |
158
+ (?:
159
+ # The compatible operator requires at least two digits in the
160
+ # release segment.
161
+ (?<=~=) # Only match for the compatible operator
162
+
163
+ \s*
164
+ v?
165
+ (?:[0-9]+!)? # epoch
166
+ [0-9]+(?:\.[0-9]+)+ # release (We have a + instead of a *)
167
+ (?: # pre release
168
+ [-_\.]?
169
+ (alpha|beta|preview|pre|a|b|c|rc)
170
+ [-_\.]?
171
+ [0-9]*
172
+ )?
173
+ (?: # post release
174
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
175
+ )?
176
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
177
+ )
178
+ |
179
+ (?:
180
+ # All other operators only allow a sub set of what the
181
+ # (non)equality operators do. Specifically they do not allow
182
+ # local versions to be specified nor do they allow the prefix
183
+ # matching wild cards.
184
+ (?<!==|!=|~=) # We have special cases for these
185
+ # operators so we want to make sure they
186
+ # don't match here.
187
+
188
+ \s*
189
+ v?
190
+ (?:[0-9]+!)? # epoch
191
+ [0-9]+(?:\.[0-9]+)* # release
192
+ (?: # pre release
193
+ [-_\.]?
194
+ (alpha|beta|preview|pre|a|b|c|rc)
195
+ [-_\.]?
196
+ [0-9]*
197
+ )?
198
+ (?: # post release
199
+ (?:-[0-9]+)|(?:[-_\.]?(post|rev|r)[-_\.]?[0-9]*)
200
+ )?
201
+ (?:[-_\.]?dev[-_\.]?[0-9]*)? # dev release
202
+ )
203
+ )
204
+ """
205
+
206
+ _regex = re.compile(
207
+ r"^\s*" + _operator_regex_str + _version_regex_str + r"\s*$",
208
+ re.VERBOSE | re.IGNORECASE,
209
+ )
210
+
211
+ _operators = {
212
+ "~=": "compatible",
213
+ "==": "equal",
214
+ "!=": "not_equal",
215
+ "<=": "less_than_equal",
216
+ ">=": "greater_than_equal",
217
+ "<": "less_than",
218
+ ">": "greater_than",
219
+ "===": "arbitrary",
220
+ }
221
+
222
+ def __init__(self, spec: str = "", prereleases: bool | None = None) -> None:
223
+ """Initialize a Specifier instance.
224
+
225
+ :param spec:
226
+ The string representation of a specifier which will be parsed and
227
+ normalized before use.
228
+ :param prereleases:
229
+ This tells the specifier if it should accept prerelease versions if
230
+ applicable or not. The default of ``None`` will autodetect it from the
231
+ given specifiers.
232
+ :raises InvalidSpecifier:
233
+ If the given specifier is invalid (i.e. bad syntax).
234
+ """
235
+ match = self._regex.search(spec)
236
+ if not match:
237
+ raise InvalidSpecifier(f"Invalid specifier: {spec!r}")
238
+
239
+ self._spec: tuple[str, str] = (
240
+ match.group("operator").strip(),
241
+ match.group("version").strip(),
242
+ )
243
+
244
+ # Store whether or not this Specifier should accept prereleases
245
+ self._prereleases = prereleases
246
+
247
+ # https://github.com/python/mypy/pull/13475#pullrequestreview-1079784515
248
+ @property # type: ignore[override]
249
+ def prereleases(self) -> bool:
250
+ # If there is an explicit prereleases set for this, then we'll just
251
+ # blindly use that.
252
+ if self._prereleases is not None:
253
+ return self._prereleases
254
+
255
+ # Look at all of our specifiers and determine if they are inclusive
256
+ # operators, and if they are if they are including an explicit
257
+ # prerelease.
258
+ operator, version = self._spec
259
+ if operator in ["==", ">=", "<=", "~=", "===", ">", "<"]:
260
+ # The == specifier can include a trailing .*, if it does we
261
+ # want to remove before parsing.
262
+ if operator == "==" and version.endswith(".*"):
263
+ version = version[:-2]
264
+
265
+ # Parse the version, and if it is a pre-release than this
266
+ # specifier allows pre-releases.
267
+ if Version(version).is_prerelease:
268
+ return True
269
+
270
+ return False
271
+
272
+ @prereleases.setter
273
+ def prereleases(self, value: bool) -> None:
274
+ self._prereleases = value
275
+
276
+ @property
277
+ def operator(self) -> str:
278
+ """The operator of this specifier.
279
+
280
+ >>> Specifier("==1.2.3").operator
281
+ '=='
282
+ """
283
+ return self._spec[0]
284
+
285
+ @property
286
+ def version(self) -> str:
287
+ """The version of this specifier.
288
+
289
+ >>> Specifier("==1.2.3").version
290
+ '1.2.3'
291
+ """
292
+ return self._spec[1]
293
+
294
+ def __repr__(self) -> str:
295
+ """A representation of the Specifier that shows all internal state.
296
+
297
+ >>> Specifier('>=1.0.0')
298
+ <Specifier('>=1.0.0')>
299
+ >>> Specifier('>=1.0.0', prereleases=False)
300
+ <Specifier('>=1.0.0', prereleases=False)>
301
+ >>> Specifier('>=1.0.0', prereleases=True)
302
+ <Specifier('>=1.0.0', prereleases=True)>
303
+ """
304
+ pre = (
305
+ f", prereleases={self.prereleases!r}"
306
+ if self._prereleases is not None
307
+ else ""
308
+ )
309
+
310
+ return f"<{self.__class__.__name__}({str(self)!r}{pre})>"
311
+
312
+ def __str__(self) -> str:
313
+ """A string representation of the Specifier that can be round-tripped.
314
+
315
+ >>> str(Specifier('>=1.0.0'))
316
+ '>=1.0.0'
317
+ >>> str(Specifier('>=1.0.0', prereleases=False))
318
+ '>=1.0.0'
319
+ """
320
+ return "{}{}".format(*self._spec)
321
+
322
+ @property
323
+ def _canonical_spec(self) -> tuple[str, str]:
324
+ canonical_version = canonicalize_version(
325
+ self._spec[1],
326
+ strip_trailing_zero=(self._spec[0] != "~="),
327
+ )
328
+ return self._spec[0], canonical_version
329
+
330
+ def __hash__(self) -> int:
331
+ return hash(self._canonical_spec)
332
+
333
+ def __eq__(self, other: object) -> bool:
334
+ """Whether or not the two Specifier-like objects are equal.
335
+
336
+ :param other: The other object to check against.
337
+
338
+ The value of :attr:`prereleases` is ignored.
339
+
340
+ >>> Specifier("==1.2.3") == Specifier("== 1.2.3.0")
341
+ True
342
+ >>> (Specifier("==1.2.3", prereleases=False) ==
343
+ ... Specifier("==1.2.3", prereleases=True))
344
+ True
345
+ >>> Specifier("==1.2.3") == "==1.2.3"
346
+ True
347
+ >>> Specifier("==1.2.3") == Specifier("==1.2.4")
348
+ False
349
+ >>> Specifier("==1.2.3") == Specifier("~=1.2.3")
350
+ False
351
+ """
352
+ if isinstance(other, str):
353
+ try:
354
+ other = self.__class__(str(other))
355
+ except InvalidSpecifier:
356
+ return NotImplemented
357
+ elif not isinstance(other, self.__class__):
358
+ return NotImplemented
359
+
360
+ return self._canonical_spec == other._canonical_spec
361
+
362
+ def _get_operator(self, op: str) -> CallableOperator:
363
+ operator_callable: CallableOperator = getattr(
364
+ self, f"_compare_{self._operators[op]}"
365
+ )
366
+ return operator_callable
367
+
368
+ def _compare_compatible(self, prospective: Version, spec: str) -> bool:
369
+ # Compatible releases have an equivalent combination of >= and ==. That
370
+ # is that ~=2.2 is equivalent to >=2.2,==2.*. This allows us to
371
+ # implement this in terms of the other specifiers instead of
372
+ # implementing it ourselves. The only thing we need to do is construct
373
+ # the other specifiers.
374
+
375
+ # We want everything but the last item in the version, but we want to
376
+ # ignore suffix segments.
377
+ prefix = _version_join(
378
+ list(itertools.takewhile(_is_not_suffix, _version_split(spec)))[:-1]
379
+ )
380
+
381
+ # Add the prefix notation to the end of our string
382
+ prefix += ".*"
383
+
384
+ return self._get_operator(">=")(prospective, spec) and self._get_operator("==")(
385
+ prospective, prefix
386
+ )
387
+
388
+ def _compare_equal(self, prospective: Version, spec: str) -> bool:
389
+ # We need special logic to handle prefix matching
390
+ if spec.endswith(".*"):
391
+ # In the case of prefix matching we want to ignore local segment.
392
+ normalized_prospective = canonicalize_version(
393
+ prospective.public, strip_trailing_zero=False
394
+ )
395
+ # Get the normalized version string ignoring the trailing .*
396
+ normalized_spec = canonicalize_version(spec[:-2], strip_trailing_zero=False)
397
+ # Split the spec out by bangs and dots, and pretend that there is
398
+ # an implicit dot in between a release segment and a pre-release segment.
399
+ split_spec = _version_split(normalized_spec)
400
+
401
+ # Split the prospective version out by bangs and dots, and pretend
402
+ # that there is an implicit dot in between a release segment and
403
+ # a pre-release segment.
404
+ split_prospective = _version_split(normalized_prospective)
405
+
406
+ # 0-pad the prospective version before shortening it to get the correct
407
+ # shortened version.
408
+ padded_prospective, _ = _pad_version(split_prospective, split_spec)
409
+
410
+ # Shorten the prospective version to be the same length as the spec
411
+ # so that we can determine if the specifier is a prefix of the
412
+ # prospective version or not.
413
+ shortened_prospective = padded_prospective[: len(split_spec)]
414
+
415
+ return shortened_prospective == split_spec
416
+ else:
417
+ # Convert our spec string into a Version
418
+ spec_version = Version(spec)
419
+
420
+ # If the specifier does not have a local segment, then we want to
421
+ # act as if the prospective version also does not have a local
422
+ # segment.
423
+ if not spec_version.local:
424
+ prospective = Version(prospective.public)
425
+
426
+ return prospective == spec_version
427
+
428
+ def _compare_not_equal(self, prospective: Version, spec: str) -> bool:
429
+ return not self._compare_equal(prospective, spec)
430
+
431
+ def _compare_less_than_equal(self, prospective: Version, spec: str) -> bool:
432
+ # NB: Local version identifiers are NOT permitted in the version
433
+ # specifier, so local version labels can be universally removed from
434
+ # the prospective version.
435
+ return Version(prospective.public) <= Version(spec)
436
+
437
+ def _compare_greater_than_equal(self, prospective: Version, spec: str) -> bool:
438
+ # NB: Local version identifiers are NOT permitted in the version
439
+ # specifier, so local version labels can be universally removed from
440
+ # the prospective version.
441
+ return Version(prospective.public) >= Version(spec)
442
+
443
+ def _compare_less_than(self, prospective: Version, spec_str: str) -> bool:
444
+ # Convert our spec to a Version instance, since we'll want to work with
445
+ # it as a version.
446
+ spec = Version(spec_str)
447
+
448
+ # Check to see if the prospective version is less than the spec
449
+ # version. If it's not we can short circuit and just return False now
450
+ # instead of doing extra unneeded work.
451
+ if not prospective < spec:
452
+ return False
453
+
454
+ # This special case is here so that, unless the specifier itself
455
+ # includes is a pre-release version, that we do not accept pre-release
456
+ # versions for the version mentioned in the specifier (e.g. <3.1 should
457
+ # not match 3.1.dev0, but should match 3.0.dev0).
458
+ if not spec.is_prerelease and prospective.is_prerelease:
459
+ if Version(prospective.base_version) == Version(spec.base_version):
460
+ return False
461
+
462
+ # If we've gotten to here, it means that prospective version is both
463
+ # less than the spec version *and* it's not a pre-release of the same
464
+ # version in the spec.
465
+ return True
466
+
467
+ def _compare_greater_than(self, prospective: Version, spec_str: str) -> bool:
468
+ # Convert our spec to a Version instance, since we'll want to work with
469
+ # it as a version.
470
+ spec = Version(spec_str)
471
+
472
+ # Check to see if the prospective version is greater than the spec
473
+ # version. If it's not we can short circuit and just return False now
474
+ # instead of doing extra unneeded work.
475
+ if not prospective > spec:
476
+ return False
477
+
478
+ # This special case is here so that, unless the specifier itself
479
+ # includes is a post-release version, that we do not accept
480
+ # post-release versions for the version mentioned in the specifier
481
+ # (e.g. >3.1 should not match 3.0.post0, but should match 3.2.post0).
482
+ if not spec.is_postrelease and prospective.is_postrelease:
483
+ if Version(prospective.base_version) == Version(spec.base_version):
484
+ return False
485
+
486
+ # Ensure that we do not allow a local version of the version mentioned
487
+ # in the specifier, which is technically greater than, to match.
488
+ if prospective.local is not None:
489
+ if Version(prospective.base_version) == Version(spec.base_version):
490
+ return False
491
+
492
+ # If we've gotten to here, it means that prospective version is both
493
+ # greater than the spec version *and* it's not a pre-release of the
494
+ # same version in the spec.
495
+ return True
496
+
497
+ def _compare_arbitrary(self, prospective: Version, spec: str) -> bool:
498
+ return str(prospective).lower() == str(spec).lower()
499
+
500
+ def __contains__(self, item: str | Version) -> bool:
501
+ """Return whether or not the item is contained in this specifier.
502
+
503
+ :param item: The item to check for.
504
+
505
+ This is used for the ``in`` operator and behaves the same as
506
+ :meth:`contains` with no ``prereleases`` argument passed.
507
+
508
+ >>> "1.2.3" in Specifier(">=1.2.3")
509
+ True
510
+ >>> Version("1.2.3") in Specifier(">=1.2.3")
511
+ True
512
+ >>> "1.0.0" in Specifier(">=1.2.3")
513
+ False
514
+ >>> "1.3.0a1" in Specifier(">=1.2.3")
515
+ False
516
+ >>> "1.3.0a1" in Specifier(">=1.2.3", prereleases=True)
517
+ True
518
+ """
519
+ return self.contains(item)
520
+
521
+ def contains(self, item: UnparsedVersion, prereleases: bool | None = None) -> bool:
522
+ """Return whether or not the item is contained in this specifier.
523
+
524
+ :param item:
525
+ The item to check for, which can be a version string or a
526
+ :class:`Version` instance.
527
+ :param prereleases:
528
+ Whether or not to match prereleases with this Specifier. If set to
529
+ ``None`` (the default), it uses :attr:`prereleases` to determine
530
+ whether or not prereleases are allowed.
531
+
532
+ >>> Specifier(">=1.2.3").contains("1.2.3")
533
+ True
534
+ >>> Specifier(">=1.2.3").contains(Version("1.2.3"))
535
+ True
536
+ >>> Specifier(">=1.2.3").contains("1.0.0")
537
+ False
538
+ >>> Specifier(">=1.2.3").contains("1.3.0a1")
539
+ False
540
+ >>> Specifier(">=1.2.3", prereleases=True).contains("1.3.0a1")
541
+ True
542
+ >>> Specifier(">=1.2.3").contains("1.3.0a1", prereleases=True)
543
+ True
544
+ """
545
+
546
+ # Determine if prereleases are to be allowed or not.
547
+ if prereleases is None:
548
+ prereleases = self.prereleases
549
+
550
+ # Normalize item to a Version, this allows us to have a shortcut for
551
+ # "2.0" in Specifier(">=2")
552
+ normalized_item = _coerce_version(item)
553
+
554
+ # Determine if we should be supporting prereleases in this specifier
555
+ # or not, if we do not support prereleases than we can short circuit
556
+ # logic if this version is a prereleases.
557
+ if normalized_item.is_prerelease and not prereleases:
558
+ return False
559
+
560
+ # Actually do the comparison to determine if this item is contained
561
+ # within this Specifier or not.
562
+ operator_callable: CallableOperator = self._get_operator(self.operator)
563
+ return operator_callable(normalized_item, self.version)
564
+
565
+ def filter(
566
+ self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None
567
+ ) -> Iterator[UnparsedVersionVar]:
568
+ """Filter items in the given iterable, that match the specifier.
569
+
570
+ :param iterable:
571
+ An iterable that can contain version strings and :class:`Version` instances.
572
+ The items in the iterable will be filtered according to the specifier.
573
+ :param prereleases:
574
+ Whether or not to allow prereleases in the returned iterator. If set to
575
+ ``None`` (the default), it will be intelligently decide whether to allow
576
+ prereleases or not (based on the :attr:`prereleases` attribute, and
577
+ whether the only versions matching are prereleases).
578
+
579
+ This method is smarter than just ``filter(Specifier().contains, [...])``
580
+ because it implements the rule from :pep:`440` that a prerelease item
581
+ SHOULD be accepted if no other versions match the given specifier.
582
+
583
+ >>> list(Specifier(">=1.2.3").filter(["1.2", "1.3", "1.5a1"]))
584
+ ['1.3']
585
+ >>> list(Specifier(">=1.2.3").filter(["1.2", "1.2.3", "1.3", Version("1.4")]))
586
+ ['1.2.3', '1.3', <Version('1.4')>]
587
+ >>> list(Specifier(">=1.2.3").filter(["1.2", "1.5a1"]))
588
+ ['1.5a1']
589
+ >>> list(Specifier(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True))
590
+ ['1.3', '1.5a1']
591
+ >>> list(Specifier(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"]))
592
+ ['1.3', '1.5a1']
593
+ """
594
+
595
+ yielded = False
596
+ found_prereleases = []
597
+
598
+ kw = {"prereleases": prereleases if prereleases is not None else True}
599
+
600
+ # Attempt to iterate over all the values in the iterable and if any of
601
+ # them match, yield them.
602
+ for version in iterable:
603
+ parsed_version = _coerce_version(version)
604
+
605
+ if self.contains(parsed_version, **kw):
606
+ # If our version is a prerelease, and we were not set to allow
607
+ # prereleases, then we'll store it for later in case nothing
608
+ # else matches this specifier.
609
+ if parsed_version.is_prerelease and not (
610
+ prereleases or self.prereleases
611
+ ):
612
+ found_prereleases.append(version)
613
+ # Either this is not a prerelease, or we should have been
614
+ # accepting prereleases from the beginning.
615
+ else:
616
+ yielded = True
617
+ yield version
618
+
619
+ # Now that we've iterated over everything, determine if we've yielded
620
+ # any values, and if we have not and we have any prereleases stored up
621
+ # then we will go ahead and yield the prereleases.
622
+ if not yielded and found_prereleases:
623
+ for version in found_prereleases:
624
+ yield version
625
+
626
+
627
+ _prefix_regex = re.compile(r"^([0-9]+)((?:a|b|c|rc)[0-9]+)$")
628
+
629
+
630
+ def _version_split(version: str) -> list[str]:
631
+ """Split version into components.
632
+
633
+ The split components are intended for version comparison. The logic does
634
+ not attempt to retain the original version string, so joining the
635
+ components back with :func:`_version_join` may not produce the original
636
+ version string.
637
+ """
638
+ result: list[str] = []
639
+
640
+ epoch, _, rest = version.rpartition("!")
641
+ result.append(epoch or "0")
642
+
643
+ for item in rest.split("."):
644
+ match = _prefix_regex.search(item)
645
+ if match:
646
+ result.extend(match.groups())
647
+ else:
648
+ result.append(item)
649
+ return result
650
+
651
+
652
+ def _version_join(components: list[str]) -> str:
653
+ """Join split version components into a version string.
654
+
655
+ This function assumes the input came from :func:`_version_split`, where the
656
+ first component must be the epoch (either empty or numeric), and all other
657
+ components numeric.
658
+ """
659
+ epoch, *rest = components
660
+ return f"{epoch}!{'.'.join(rest)}"
661
+
662
+
663
+ def _is_not_suffix(segment: str) -> bool:
664
+ return not any(
665
+ segment.startswith(prefix) for prefix in ("dev", "a", "b", "rc", "post")
666
+ )
667
+
668
+
669
+ def _pad_version(left: list[str], right: list[str]) -> tuple[list[str], list[str]]:
670
+ left_split, right_split = [], []
671
+
672
+ # Get the release segment of our versions
673
+ left_split.append(list(itertools.takewhile(lambda x: x.isdigit(), left)))
674
+ right_split.append(list(itertools.takewhile(lambda x: x.isdigit(), right)))
675
+
676
+ # Get the rest of our versions
677
+ left_split.append(left[len(left_split[0]) :])
678
+ right_split.append(right[len(right_split[0]) :])
679
+
680
+ # Insert our padding
681
+ left_split.insert(1, ["0"] * max(0, len(right_split[0]) - len(left_split[0])))
682
+ right_split.insert(1, ["0"] * max(0, len(left_split[0]) - len(right_split[0])))
683
+
684
+ return (
685
+ list(itertools.chain.from_iterable(left_split)),
686
+ list(itertools.chain.from_iterable(right_split)),
687
+ )
688
+
689
+
690
+ class SpecifierSet(BaseSpecifier):
691
+ """This class abstracts handling of a set of version specifiers.
692
+
693
+ It can be passed a single specifier (``>=3.0``), a comma-separated list of
694
+ specifiers (``>=3.0,!=3.1``), or no specifier at all.
695
+ """
696
+
697
+ def __init__(
698
+ self,
699
+ specifiers: str | Iterable[Specifier] = "",
700
+ prereleases: bool | None = None,
701
+ ) -> None:
702
+ """Initialize a SpecifierSet instance.
703
+
704
+ :param specifiers:
705
+ The string representation of a specifier or a comma-separated list of
706
+ specifiers which will be parsed and normalized before use.
707
+ May also be an iterable of ``Specifier`` instances, which will be used
708
+ as is.
709
+ :param prereleases:
710
+ This tells the SpecifierSet if it should accept prerelease versions if
711
+ applicable or not. The default of ``None`` will autodetect it from the
712
+ given specifiers.
713
+
714
+ :raises InvalidSpecifier:
715
+ If the given ``specifiers`` are not parseable than this exception will be
716
+ raised.
717
+ """
718
+
719
+ if isinstance(specifiers, str):
720
+ # Split on `,` to break each individual specifier into its own item, and
721
+ # strip each item to remove leading/trailing whitespace.
722
+ split_specifiers = [s.strip() for s in specifiers.split(",") if s.strip()]
723
+
724
+ # Make each individual specifier a Specifier and save in a frozen set
725
+ # for later.
726
+ self._specs = frozenset(map(Specifier, split_specifiers))
727
+ else:
728
+ # Save the supplied specifiers in a frozen set.
729
+ self._specs = frozenset(specifiers)
730
+
731
+ # Store our prereleases value so we can use it later to determine if
732
+ # we accept prereleases or not.
733
+ self._prereleases = prereleases
734
+
735
+ @property
736
+ def prereleases(self) -> bool | None:
737
+ # If we have been given an explicit prerelease modifier, then we'll
738
+ # pass that through here.
739
+ if self._prereleases is not None:
740
+ return self._prereleases
741
+
742
+ # If we don't have any specifiers, and we don't have a forced value,
743
+ # then we'll just return None since we don't know if this should have
744
+ # pre-releases or not.
745
+ if not self._specs:
746
+ return None
747
+
748
+ # Otherwise we'll see if any of the given specifiers accept
749
+ # prereleases, if any of them do we'll return True, otherwise False.
750
+ return any(s.prereleases for s in self._specs)
751
+
752
+ @prereleases.setter
753
+ def prereleases(self, value: bool) -> None:
754
+ self._prereleases = value
755
+
756
+ def __repr__(self) -> str:
757
+ """A representation of the specifier set that shows all internal state.
758
+
759
+ Note that the ordering of the individual specifiers within the set may not
760
+ match the input string.
761
+
762
+ >>> SpecifierSet('>=1.0.0,!=2.0.0')
763
+ <SpecifierSet('!=2.0.0,>=1.0.0')>
764
+ >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=False)
765
+ <SpecifierSet('!=2.0.0,>=1.0.0', prereleases=False)>
766
+ >>> SpecifierSet('>=1.0.0,!=2.0.0', prereleases=True)
767
+ <SpecifierSet('!=2.0.0,>=1.0.0', prereleases=True)>
768
+ """
769
+ pre = (
770
+ f", prereleases={self.prereleases!r}"
771
+ if self._prereleases is not None
772
+ else ""
773
+ )
774
+
775
+ return f"<SpecifierSet({str(self)!r}{pre})>"
776
+
777
+ def __str__(self) -> str:
778
+ """A string representation of the specifier set that can be round-tripped.
779
+
780
+ Note that the ordering of the individual specifiers within the set may not
781
+ match the input string.
782
+
783
+ >>> str(SpecifierSet(">=1.0.0,!=1.0.1"))
784
+ '!=1.0.1,>=1.0.0'
785
+ >>> str(SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False))
786
+ '!=1.0.1,>=1.0.0'
787
+ """
788
+ return ",".join(sorted(str(s) for s in self._specs))
789
+
790
+ def __hash__(self) -> int:
791
+ return hash(self._specs)
792
+
793
+ def __and__(self, other: SpecifierSet | str) -> SpecifierSet:
794
+ """Return a SpecifierSet which is a combination of the two sets.
795
+
796
+ :param other: The other object to combine with.
797
+
798
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") & '<=2.0.0,!=2.0.1'
799
+ <SpecifierSet('!=1.0.1,!=2.0.1,<=2.0.0,>=1.0.0')>
800
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") & SpecifierSet('<=2.0.0,!=2.0.1')
801
+ <SpecifierSet('!=1.0.1,!=2.0.1,<=2.0.0,>=1.0.0')>
802
+ """
803
+ if isinstance(other, str):
804
+ other = SpecifierSet(other)
805
+ elif not isinstance(other, SpecifierSet):
806
+ return NotImplemented
807
+
808
+ specifier = SpecifierSet()
809
+ specifier._specs = frozenset(self._specs | other._specs)
810
+
811
+ if self._prereleases is None and other._prereleases is not None:
812
+ specifier._prereleases = other._prereleases
813
+ elif self._prereleases is not None and other._prereleases is None:
814
+ specifier._prereleases = self._prereleases
815
+ elif self._prereleases == other._prereleases:
816
+ specifier._prereleases = self._prereleases
817
+ else:
818
+ raise ValueError(
819
+ "Cannot combine SpecifierSets with True and False prerelease overrides."
820
+ )
821
+
822
+ return specifier
823
+
824
+ def __eq__(self, other: object) -> bool:
825
+ """Whether or not the two SpecifierSet-like objects are equal.
826
+
827
+ :param other: The other object to check against.
828
+
829
+ The value of :attr:`prereleases` is ignored.
830
+
831
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.1")
832
+ True
833
+ >>> (SpecifierSet(">=1.0.0,!=1.0.1", prereleases=False) ==
834
+ ... SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True))
835
+ True
836
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") == ">=1.0.0,!=1.0.1"
837
+ True
838
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0")
839
+ False
840
+ >>> SpecifierSet(">=1.0.0,!=1.0.1") == SpecifierSet(">=1.0.0,!=1.0.2")
841
+ False
842
+ """
843
+ if isinstance(other, (str, Specifier)):
844
+ other = SpecifierSet(str(other))
845
+ elif not isinstance(other, SpecifierSet):
846
+ return NotImplemented
847
+
848
+ return self._specs == other._specs
849
+
850
+ def __len__(self) -> int:
851
+ """Returns the number of specifiers in this specifier set."""
852
+ return len(self._specs)
853
+
854
+ def __iter__(self) -> Iterator[Specifier]:
855
+ """
856
+ Returns an iterator over all the underlying :class:`Specifier` instances
857
+ in this specifier set.
858
+
859
+ >>> sorted(SpecifierSet(">=1.0.0,!=1.0.1"), key=str)
860
+ [<Specifier('!=1.0.1')>, <Specifier('>=1.0.0')>]
861
+ """
862
+ return iter(self._specs)
863
+
864
+ def __contains__(self, item: UnparsedVersion) -> bool:
865
+ """Return whether or not the item is contained in this specifier.
866
+
867
+ :param item: The item to check for.
868
+
869
+ This is used for the ``in`` operator and behaves the same as
870
+ :meth:`contains` with no ``prereleases`` argument passed.
871
+
872
+ >>> "1.2.3" in SpecifierSet(">=1.0.0,!=1.0.1")
873
+ True
874
+ >>> Version("1.2.3") in SpecifierSet(">=1.0.0,!=1.0.1")
875
+ True
876
+ >>> "1.0.1" in SpecifierSet(">=1.0.0,!=1.0.1")
877
+ False
878
+ >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1")
879
+ False
880
+ >>> "1.3.0a1" in SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True)
881
+ True
882
+ """
883
+ return self.contains(item)
884
+
885
+ def contains(
886
+ self,
887
+ item: UnparsedVersion,
888
+ prereleases: bool | None = None,
889
+ installed: bool | None = None,
890
+ ) -> bool:
891
+ """Return whether or not the item is contained in this SpecifierSet.
892
+
893
+ :param item:
894
+ The item to check for, which can be a version string or a
895
+ :class:`Version` instance.
896
+ :param prereleases:
897
+ Whether or not to match prereleases with this SpecifierSet. If set to
898
+ ``None`` (the default), it uses :attr:`prereleases` to determine
899
+ whether or not prereleases are allowed.
900
+
901
+ >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.2.3")
902
+ True
903
+ >>> SpecifierSet(">=1.0.0,!=1.0.1").contains(Version("1.2.3"))
904
+ True
905
+ >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.0.1")
906
+ False
907
+ >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1")
908
+ False
909
+ >>> SpecifierSet(">=1.0.0,!=1.0.1", prereleases=True).contains("1.3.0a1")
910
+ True
911
+ >>> SpecifierSet(">=1.0.0,!=1.0.1").contains("1.3.0a1", prereleases=True)
912
+ True
913
+ """
914
+ # Ensure that our item is a Version instance.
915
+ if not isinstance(item, Version):
916
+ item = Version(item)
917
+
918
+ # Determine if we're forcing a prerelease or not, if we're not forcing
919
+ # one for this particular filter call, then we'll use whatever the
920
+ # SpecifierSet thinks for whether or not we should support prereleases.
921
+ if prereleases is None:
922
+ prereleases = self.prereleases
923
+
924
+ # We can determine if we're going to allow pre-releases by looking to
925
+ # see if any of the underlying items supports them. If none of them do
926
+ # and this item is a pre-release then we do not allow it and we can
927
+ # short circuit that here.
928
+ # Note: This means that 1.0.dev1 would not be contained in something
929
+ # like >=1.0.devabc however it would be in >=1.0.debabc,>0.0.dev0
930
+ if not prereleases and item.is_prerelease:
931
+ return False
932
+
933
+ if installed and item.is_prerelease:
934
+ item = Version(item.base_version)
935
+
936
+ # We simply dispatch to the underlying specs here to make sure that the
937
+ # given version is contained within all of them.
938
+ # Note: This use of all() here means that an empty set of specifiers
939
+ # will always return True, this is an explicit design decision.
940
+ return all(s.contains(item, prereleases=prereleases) for s in self._specs)
941
+
942
+ def filter(
943
+ self, iterable: Iterable[UnparsedVersionVar], prereleases: bool | None = None
944
+ ) -> Iterator[UnparsedVersionVar]:
945
+ """Filter items in the given iterable, that match the specifiers in this set.
946
+
947
+ :param iterable:
948
+ An iterable that can contain version strings and :class:`Version` instances.
949
+ The items in the iterable will be filtered according to the specifier.
950
+ :param prereleases:
951
+ Whether or not to allow prereleases in the returned iterator. If set to
952
+ ``None`` (the default), it will be intelligently decide whether to allow
953
+ prereleases or not (based on the :attr:`prereleases` attribute, and
954
+ whether the only versions matching are prereleases).
955
+
956
+ This method is smarter than just ``filter(SpecifierSet(...).contains, [...])``
957
+ because it implements the rule from :pep:`440` that a prerelease item
958
+ SHOULD be accepted if no other versions match the given specifier.
959
+
960
+ >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", "1.5a1"]))
961
+ ['1.3']
962
+ >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.3", Version("1.4")]))
963
+ ['1.3', <Version('1.4')>]
964
+ >>> list(SpecifierSet(">=1.2.3").filter(["1.2", "1.5a1"]))
965
+ []
966
+ >>> list(SpecifierSet(">=1.2.3").filter(["1.3", "1.5a1"], prereleases=True))
967
+ ['1.3', '1.5a1']
968
+ >>> list(SpecifierSet(">=1.2.3", prereleases=True).filter(["1.3", "1.5a1"]))
969
+ ['1.3', '1.5a1']
970
+
971
+ An "empty" SpecifierSet will filter items based on the presence of prerelease
972
+ versions in the set.
973
+
974
+ >>> list(SpecifierSet("").filter(["1.3", "1.5a1"]))
975
+ ['1.3']
976
+ >>> list(SpecifierSet("").filter(["1.5a1"]))
977
+ ['1.5a1']
978
+ >>> list(SpecifierSet("", prereleases=True).filter(["1.3", "1.5a1"]))
979
+ ['1.3', '1.5a1']
980
+ >>> list(SpecifierSet("").filter(["1.3", "1.5a1"], prereleases=True))
981
+ ['1.3', '1.5a1']
982
+ """
983
+ # Determine if we're forcing a prerelease or not, if we're not forcing
984
+ # one for this particular filter call, then we'll use whatever the
985
+ # SpecifierSet thinks for whether or not we should support prereleases.
986
+ if prereleases is None:
987
+ prereleases = self.prereleases
988
+
989
+ # If we have any specifiers, then we want to wrap our iterable in the
990
+ # filter method for each one, this will act as a logical AND amongst
991
+ # each specifier.
992
+ if self._specs:
993
+ for spec in self._specs:
994
+ iterable = spec.filter(iterable, prereleases=bool(prereleases))
995
+ return iter(iterable)
996
+ # If we do not have any specifiers, then we need to have a rough filter
997
+ # which will filter out any pre-releases, unless there are no final
998
+ # releases.
999
+ else:
1000
+ filtered: list[UnparsedVersionVar] = []
1001
+ found_prereleases: list[UnparsedVersionVar] = []
1002
+
1003
+ for item in iterable:
1004
+ parsed_version = _coerce_version(item)
1005
+
1006
+ # Store any item which is a pre-release for later unless we've
1007
+ # already found a final version or we are accepting prereleases
1008
+ if parsed_version.is_prerelease and not prereleases:
1009
+ if not filtered:
1010
+ found_prereleases.append(item)
1011
+ else:
1012
+ filtered.append(item)
1013
+
1014
+ # If we've found no items except for pre-releases, then we'll go
1015
+ # ahead and use the pre-releases
1016
+ if not filtered and found_prereleases and prereleases is None:
1017
+ return iter(found_prereleases)
1018
+
1019
+ return iter(filtered)
venv/lib/python3.12/site-packages/packaging/tags.py ADDED
@@ -0,0 +1,656 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+ from __future__ import annotations
6
+
7
+ import logging
8
+ import platform
9
+ import re
10
+ import struct
11
+ import subprocess
12
+ import sys
13
+ import sysconfig
14
+ from importlib.machinery import EXTENSION_SUFFIXES
15
+ from typing import (
16
+ Iterable,
17
+ Iterator,
18
+ Sequence,
19
+ Tuple,
20
+ cast,
21
+ )
22
+
23
+ from . import _manylinux, _musllinux
24
+
25
+ logger = logging.getLogger(__name__)
26
+
27
+ PythonVersion = Sequence[int]
28
+ AppleVersion = Tuple[int, int]
29
+
30
+ INTERPRETER_SHORT_NAMES: dict[str, str] = {
31
+ "python": "py", # Generic.
32
+ "cpython": "cp",
33
+ "pypy": "pp",
34
+ "ironpython": "ip",
35
+ "jython": "jy",
36
+ }
37
+
38
+
39
+ _32_BIT_INTERPRETER = struct.calcsize("P") == 4
40
+
41
+
42
+ class Tag:
43
+ """
44
+ A representation of the tag triple for a wheel.
45
+
46
+ Instances are considered immutable and thus are hashable. Equality checking
47
+ is also supported.
48
+ """
49
+
50
+ __slots__ = ["_abi", "_hash", "_interpreter", "_platform"]
51
+
52
+ def __init__(self, interpreter: str, abi: str, platform: str) -> None:
53
+ self._interpreter = interpreter.lower()
54
+ self._abi = abi.lower()
55
+ self._platform = platform.lower()
56
+ # The __hash__ of every single element in a Set[Tag] will be evaluated each time
57
+ # that a set calls its `.disjoint()` method, which may be called hundreds of
58
+ # times when scanning a page of links for packages with tags matching that
59
+ # Set[Tag]. Pre-computing the value here produces significant speedups for
60
+ # downstream consumers.
61
+ self._hash = hash((self._interpreter, self._abi, self._platform))
62
+
63
+ @property
64
+ def interpreter(self) -> str:
65
+ return self._interpreter
66
+
67
+ @property
68
+ def abi(self) -> str:
69
+ return self._abi
70
+
71
+ @property
72
+ def platform(self) -> str:
73
+ return self._platform
74
+
75
+ def __eq__(self, other: object) -> bool:
76
+ if not isinstance(other, Tag):
77
+ return NotImplemented
78
+
79
+ return (
80
+ (self._hash == other._hash) # Short-circuit ASAP for perf reasons.
81
+ and (self._platform == other._platform)
82
+ and (self._abi == other._abi)
83
+ and (self._interpreter == other._interpreter)
84
+ )
85
+
86
+ def __hash__(self) -> int:
87
+ return self._hash
88
+
89
+ def __str__(self) -> str:
90
+ return f"{self._interpreter}-{self._abi}-{self._platform}"
91
+
92
+ def __repr__(self) -> str:
93
+ return f"<{self} @ {id(self)}>"
94
+
95
+
96
+ def parse_tag(tag: str) -> frozenset[Tag]:
97
+ """
98
+ Parses the provided tag (e.g. `py3-none-any`) into a frozenset of Tag instances.
99
+
100
+ Returning a set is required due to the possibility that the tag is a
101
+ compressed tag set.
102
+ """
103
+ tags = set()
104
+ interpreters, abis, platforms = tag.split("-")
105
+ for interpreter in interpreters.split("."):
106
+ for abi in abis.split("."):
107
+ for platform_ in platforms.split("."):
108
+ tags.add(Tag(interpreter, abi, platform_))
109
+ return frozenset(tags)
110
+
111
+
112
+ def _get_config_var(name: str, warn: bool = False) -> int | str | None:
113
+ value: int | str | None = sysconfig.get_config_var(name)
114
+ if value is None and warn:
115
+ logger.debug(
116
+ "Config variable '%s' is unset, Python ABI tag may be incorrect", name
117
+ )
118
+ return value
119
+
120
+
121
+ def _normalize_string(string: str) -> str:
122
+ return string.replace(".", "_").replace("-", "_").replace(" ", "_")
123
+
124
+
125
+ def _is_threaded_cpython(abis: list[str]) -> bool:
126
+ """
127
+ Determine if the ABI corresponds to a threaded (`--disable-gil`) build.
128
+
129
+ The threaded builds are indicated by a "t" in the abiflags.
130
+ """
131
+ if len(abis) == 0:
132
+ return False
133
+ # expect e.g., cp313
134
+ m = re.match(r"cp\d+(.*)", abis[0])
135
+ if not m:
136
+ return False
137
+ abiflags = m.group(1)
138
+ return "t" in abiflags
139
+
140
+
141
+ def _abi3_applies(python_version: PythonVersion, threading: bool) -> bool:
142
+ """
143
+ Determine if the Python version supports abi3.
144
+
145
+ PEP 384 was first implemented in Python 3.2. The threaded (`--disable-gil`)
146
+ builds do not support abi3.
147
+ """
148
+ return len(python_version) > 1 and tuple(python_version) >= (3, 2) and not threading
149
+
150
+
151
+ def _cpython_abis(py_version: PythonVersion, warn: bool = False) -> list[str]:
152
+ py_version = tuple(py_version) # To allow for version comparison.
153
+ abis = []
154
+ version = _version_nodot(py_version[:2])
155
+ threading = debug = pymalloc = ucs4 = ""
156
+ with_debug = _get_config_var("Py_DEBUG", warn)
157
+ has_refcount = hasattr(sys, "gettotalrefcount")
158
+ # Windows doesn't set Py_DEBUG, so checking for support of debug-compiled
159
+ # extension modules is the best option.
160
+ # https://github.com/pypa/pip/issues/3383#issuecomment-173267692
161
+ has_ext = "_d.pyd" in EXTENSION_SUFFIXES
162
+ if with_debug or (with_debug is None and (has_refcount or has_ext)):
163
+ debug = "d"
164
+ if py_version >= (3, 13) and _get_config_var("Py_GIL_DISABLED", warn):
165
+ threading = "t"
166
+ if py_version < (3, 8):
167
+ with_pymalloc = _get_config_var("WITH_PYMALLOC", warn)
168
+ if with_pymalloc or with_pymalloc is None:
169
+ pymalloc = "m"
170
+ if py_version < (3, 3):
171
+ unicode_size = _get_config_var("Py_UNICODE_SIZE", warn)
172
+ if unicode_size == 4 or (
173
+ unicode_size is None and sys.maxunicode == 0x10FFFF
174
+ ):
175
+ ucs4 = "u"
176
+ elif debug:
177
+ # Debug builds can also load "normal" extension modules.
178
+ # We can also assume no UCS-4 or pymalloc requirement.
179
+ abis.append(f"cp{version}{threading}")
180
+ abis.insert(0, f"cp{version}{threading}{debug}{pymalloc}{ucs4}")
181
+ return abis
182
+
183
+
184
+ def cpython_tags(
185
+ python_version: PythonVersion | None = None,
186
+ abis: Iterable[str] | None = None,
187
+ platforms: Iterable[str] | None = None,
188
+ *,
189
+ warn: bool = False,
190
+ ) -> Iterator[Tag]:
191
+ """
192
+ Yields the tags for a CPython interpreter.
193
+
194
+ The tags consist of:
195
+ - cp<python_version>-<abi>-<platform>
196
+ - cp<python_version>-abi3-<platform>
197
+ - cp<python_version>-none-<platform>
198
+ - cp<less than python_version>-abi3-<platform> # Older Python versions down to 3.2.
199
+
200
+ If python_version only specifies a major version then user-provided ABIs and
201
+ the 'none' ABItag will be used.
202
+
203
+ If 'abi3' or 'none' are specified in 'abis' then they will be yielded at
204
+ their normal position and not at the beginning.
205
+ """
206
+ if not python_version:
207
+ python_version = sys.version_info[:2]
208
+
209
+ interpreter = f"cp{_version_nodot(python_version[:2])}"
210
+
211
+ if abis is None:
212
+ if len(python_version) > 1:
213
+ abis = _cpython_abis(python_version, warn)
214
+ else:
215
+ abis = []
216
+ abis = list(abis)
217
+ # 'abi3' and 'none' are explicitly handled later.
218
+ for explicit_abi in ("abi3", "none"):
219
+ try:
220
+ abis.remove(explicit_abi)
221
+ except ValueError:
222
+ pass
223
+
224
+ platforms = list(platforms or platform_tags())
225
+ for abi in abis:
226
+ for platform_ in platforms:
227
+ yield Tag(interpreter, abi, platform_)
228
+
229
+ threading = _is_threaded_cpython(abis)
230
+ use_abi3 = _abi3_applies(python_version, threading)
231
+ if use_abi3:
232
+ yield from (Tag(interpreter, "abi3", platform_) for platform_ in platforms)
233
+ yield from (Tag(interpreter, "none", platform_) for platform_ in platforms)
234
+
235
+ if use_abi3:
236
+ for minor_version in range(python_version[1] - 1, 1, -1):
237
+ for platform_ in platforms:
238
+ version = _version_nodot((python_version[0], minor_version))
239
+ interpreter = f"cp{version}"
240
+ yield Tag(interpreter, "abi3", platform_)
241
+
242
+
243
+ def _generic_abi() -> list[str]:
244
+ """
245
+ Return the ABI tag based on EXT_SUFFIX.
246
+ """
247
+ # The following are examples of `EXT_SUFFIX`.
248
+ # We want to keep the parts which are related to the ABI and remove the
249
+ # parts which are related to the platform:
250
+ # - linux: '.cpython-310-x86_64-linux-gnu.so' => cp310
251
+ # - mac: '.cpython-310-darwin.so' => cp310
252
+ # - win: '.cp310-win_amd64.pyd' => cp310
253
+ # - win: '.pyd' => cp37 (uses _cpython_abis())
254
+ # - pypy: '.pypy38-pp73-x86_64-linux-gnu.so' => pypy38_pp73
255
+ # - graalpy: '.graalpy-38-native-x86_64-darwin.dylib'
256
+ # => graalpy_38_native
257
+
258
+ ext_suffix = _get_config_var("EXT_SUFFIX", warn=True)
259
+ if not isinstance(ext_suffix, str) or ext_suffix[0] != ".":
260
+ raise SystemError("invalid sysconfig.get_config_var('EXT_SUFFIX')")
261
+ parts = ext_suffix.split(".")
262
+ if len(parts) < 3:
263
+ # CPython3.7 and earlier uses ".pyd" on Windows.
264
+ return _cpython_abis(sys.version_info[:2])
265
+ soabi = parts[1]
266
+ if soabi.startswith("cpython"):
267
+ # non-windows
268
+ abi = "cp" + soabi.split("-")[1]
269
+ elif soabi.startswith("cp"):
270
+ # windows
271
+ abi = soabi.split("-")[0]
272
+ elif soabi.startswith("pypy"):
273
+ abi = "-".join(soabi.split("-")[:2])
274
+ elif soabi.startswith("graalpy"):
275
+ abi = "-".join(soabi.split("-")[:3])
276
+ elif soabi:
277
+ # pyston, ironpython, others?
278
+ abi = soabi
279
+ else:
280
+ return []
281
+ return [_normalize_string(abi)]
282
+
283
+
284
+ def generic_tags(
285
+ interpreter: str | None = None,
286
+ abis: Iterable[str] | None = None,
287
+ platforms: Iterable[str] | None = None,
288
+ *,
289
+ warn: bool = False,
290
+ ) -> Iterator[Tag]:
291
+ """
292
+ Yields the tags for a generic interpreter.
293
+
294
+ The tags consist of:
295
+ - <interpreter>-<abi>-<platform>
296
+
297
+ The "none" ABI will be added if it was not explicitly provided.
298
+ """
299
+ if not interpreter:
300
+ interp_name = interpreter_name()
301
+ interp_version = interpreter_version(warn=warn)
302
+ interpreter = "".join([interp_name, interp_version])
303
+ if abis is None:
304
+ abis = _generic_abi()
305
+ else:
306
+ abis = list(abis)
307
+ platforms = list(platforms or platform_tags())
308
+ if "none" not in abis:
309
+ abis.append("none")
310
+ for abi in abis:
311
+ for platform_ in platforms:
312
+ yield Tag(interpreter, abi, platform_)
313
+
314
+
315
+ def _py_interpreter_range(py_version: PythonVersion) -> Iterator[str]:
316
+ """
317
+ Yields Python versions in descending order.
318
+
319
+ After the latest version, the major-only version will be yielded, and then
320
+ all previous versions of that major version.
321
+ """
322
+ if len(py_version) > 1:
323
+ yield f"py{_version_nodot(py_version[:2])}"
324
+ yield f"py{py_version[0]}"
325
+ if len(py_version) > 1:
326
+ for minor in range(py_version[1] - 1, -1, -1):
327
+ yield f"py{_version_nodot((py_version[0], minor))}"
328
+
329
+
330
+ def compatible_tags(
331
+ python_version: PythonVersion | None = None,
332
+ interpreter: str | None = None,
333
+ platforms: Iterable[str] | None = None,
334
+ ) -> Iterator[Tag]:
335
+ """
336
+ Yields the sequence of tags that are compatible with a specific version of Python.
337
+
338
+ The tags consist of:
339
+ - py*-none-<platform>
340
+ - <interpreter>-none-any # ... if `interpreter` is provided.
341
+ - py*-none-any
342
+ """
343
+ if not python_version:
344
+ python_version = sys.version_info[:2]
345
+ platforms = list(platforms or platform_tags())
346
+ for version in _py_interpreter_range(python_version):
347
+ for platform_ in platforms:
348
+ yield Tag(version, "none", platform_)
349
+ if interpreter:
350
+ yield Tag(interpreter, "none", "any")
351
+ for version in _py_interpreter_range(python_version):
352
+ yield Tag(version, "none", "any")
353
+
354
+
355
+ def _mac_arch(arch: str, is_32bit: bool = _32_BIT_INTERPRETER) -> str:
356
+ if not is_32bit:
357
+ return arch
358
+
359
+ if arch.startswith("ppc"):
360
+ return "ppc"
361
+
362
+ return "i386"
363
+
364
+
365
+ def _mac_binary_formats(version: AppleVersion, cpu_arch: str) -> list[str]:
366
+ formats = [cpu_arch]
367
+ if cpu_arch == "x86_64":
368
+ if version < (10, 4):
369
+ return []
370
+ formats.extend(["intel", "fat64", "fat32"])
371
+
372
+ elif cpu_arch == "i386":
373
+ if version < (10, 4):
374
+ return []
375
+ formats.extend(["intel", "fat32", "fat"])
376
+
377
+ elif cpu_arch == "ppc64":
378
+ # TODO: Need to care about 32-bit PPC for ppc64 through 10.2?
379
+ if version > (10, 5) or version < (10, 4):
380
+ return []
381
+ formats.append("fat64")
382
+
383
+ elif cpu_arch == "ppc":
384
+ if version > (10, 6):
385
+ return []
386
+ formats.extend(["fat32", "fat"])
387
+
388
+ if cpu_arch in {"arm64", "x86_64"}:
389
+ formats.append("universal2")
390
+
391
+ if cpu_arch in {"x86_64", "i386", "ppc64", "ppc", "intel"}:
392
+ formats.append("universal")
393
+
394
+ return formats
395
+
396
+
397
+ def mac_platforms(
398
+ version: AppleVersion | None = None, arch: str | None = None
399
+ ) -> Iterator[str]:
400
+ """
401
+ Yields the platform tags for a macOS system.
402
+
403
+ The `version` parameter is a two-item tuple specifying the macOS version to
404
+ generate platform tags for. The `arch` parameter is the CPU architecture to
405
+ generate platform tags for. Both parameters default to the appropriate value
406
+ for the current system.
407
+ """
408
+ version_str, _, cpu_arch = platform.mac_ver()
409
+ if version is None:
410
+ version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
411
+ if version == (10, 16):
412
+ # When built against an older macOS SDK, Python will report macOS 10.16
413
+ # instead of the real version.
414
+ version_str = subprocess.run(
415
+ [
416
+ sys.executable,
417
+ "-sS",
418
+ "-c",
419
+ "import platform; print(platform.mac_ver()[0])",
420
+ ],
421
+ check=True,
422
+ env={"SYSTEM_VERSION_COMPAT": "0"},
423
+ stdout=subprocess.PIPE,
424
+ text=True,
425
+ ).stdout
426
+ version = cast("AppleVersion", tuple(map(int, version_str.split(".")[:2])))
427
+ else:
428
+ version = version
429
+ if arch is None:
430
+ arch = _mac_arch(cpu_arch)
431
+ else:
432
+ arch = arch
433
+
434
+ if (10, 0) <= version and version < (11, 0):
435
+ # Prior to Mac OS 11, each yearly release of Mac OS bumped the
436
+ # "minor" version number. The major version was always 10.
437
+ major_version = 10
438
+ for minor_version in range(version[1], -1, -1):
439
+ compat_version = major_version, minor_version
440
+ binary_formats = _mac_binary_formats(compat_version, arch)
441
+ for binary_format in binary_formats:
442
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
443
+
444
+ if version >= (11, 0):
445
+ # Starting with Mac OS 11, each yearly release bumps the major version
446
+ # number. The minor versions are now the midyear updates.
447
+ minor_version = 0
448
+ for major_version in range(version[0], 10, -1):
449
+ compat_version = major_version, minor_version
450
+ binary_formats = _mac_binary_formats(compat_version, arch)
451
+ for binary_format in binary_formats:
452
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
453
+
454
+ if version >= (11, 0):
455
+ # Mac OS 11 on x86_64 is compatible with binaries from previous releases.
456
+ # Arm64 support was introduced in 11.0, so no Arm binaries from previous
457
+ # releases exist.
458
+ #
459
+ # However, the "universal2" binary format can have a
460
+ # macOS version earlier than 11.0 when the x86_64 part of the binary supports
461
+ # that version of macOS.
462
+ major_version = 10
463
+ if arch == "x86_64":
464
+ for minor_version in range(16, 3, -1):
465
+ compat_version = major_version, minor_version
466
+ binary_formats = _mac_binary_formats(compat_version, arch)
467
+ for binary_format in binary_formats:
468
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
469
+ else:
470
+ for minor_version in range(16, 3, -1):
471
+ compat_version = major_version, minor_version
472
+ binary_format = "universal2"
473
+ yield f"macosx_{major_version}_{minor_version}_{binary_format}"
474
+
475
+
476
+ def ios_platforms(
477
+ version: AppleVersion | None = None, multiarch: str | None = None
478
+ ) -> Iterator[str]:
479
+ """
480
+ Yields the platform tags for an iOS system.
481
+
482
+ :param version: A two-item tuple specifying the iOS version to generate
483
+ platform tags for. Defaults to the current iOS version.
484
+ :param multiarch: The CPU architecture+ABI to generate platform tags for -
485
+ (the value used by `sys.implementation._multiarch` e.g.,
486
+ `arm64_iphoneos` or `x84_64_iphonesimulator`). Defaults to the current
487
+ multiarch value.
488
+ """
489
+ if version is None:
490
+ # if iOS is the current platform, ios_ver *must* be defined. However,
491
+ # it won't exist for CPython versions before 3.13, which causes a mypy
492
+ # error.
493
+ _, release, _, _ = platform.ios_ver() # type: ignore[attr-defined, unused-ignore]
494
+ version = cast("AppleVersion", tuple(map(int, release.split(".")[:2])))
495
+
496
+ if multiarch is None:
497
+ multiarch = sys.implementation._multiarch
498
+ multiarch = multiarch.replace("-", "_")
499
+
500
+ ios_platform_template = "ios_{major}_{minor}_{multiarch}"
501
+
502
+ # Consider any iOS major.minor version from the version requested, down to
503
+ # 12.0. 12.0 is the first iOS version that is known to have enough features
504
+ # to support CPython. Consider every possible minor release up to X.9. There
505
+ # highest the minor has ever gone is 8 (14.8 and 15.8) but having some extra
506
+ # candidates that won't ever match doesn't really hurt, and it saves us from
507
+ # having to keep an explicit list of known iOS versions in the code. Return
508
+ # the results descending order of version number.
509
+
510
+ # If the requested major version is less than 12, there won't be any matches.
511
+ if version[0] < 12:
512
+ return
513
+
514
+ # Consider the actual X.Y version that was requested.
515
+ yield ios_platform_template.format(
516
+ major=version[0], minor=version[1], multiarch=multiarch
517
+ )
518
+
519
+ # Consider every minor version from X.0 to the minor version prior to the
520
+ # version requested by the platform.
521
+ for minor in range(version[1] - 1, -1, -1):
522
+ yield ios_platform_template.format(
523
+ major=version[0], minor=minor, multiarch=multiarch
524
+ )
525
+
526
+ for major in range(version[0] - 1, 11, -1):
527
+ for minor in range(9, -1, -1):
528
+ yield ios_platform_template.format(
529
+ major=major, minor=minor, multiarch=multiarch
530
+ )
531
+
532
+
533
+ def android_platforms(
534
+ api_level: int | None = None, abi: str | None = None
535
+ ) -> Iterator[str]:
536
+ """
537
+ Yields the :attr:`~Tag.platform` tags for Android. If this function is invoked on
538
+ non-Android platforms, the ``api_level`` and ``abi`` arguments are required.
539
+
540
+ :param int api_level: The maximum `API level
541
+ <https://developer.android.com/tools/releases/platforms>`__ to return. Defaults
542
+ to the current system's version, as returned by ``platform.android_ver``.
543
+ :param str abi: The `Android ABI <https://developer.android.com/ndk/guides/abis>`__,
544
+ e.g. ``arm64_v8a``. Defaults to the current system's ABI , as returned by
545
+ ``sysconfig.get_platform``. Hyphens and periods will be replaced with
546
+ underscores.
547
+ """
548
+ if platform.system() != "Android" and (api_level is None or abi is None):
549
+ raise TypeError(
550
+ "on non-Android platforms, the api_level and abi arguments are required"
551
+ )
552
+
553
+ if api_level is None:
554
+ # Python 3.13 was the first version to return platform.system() == "Android",
555
+ # and also the first version to define platform.android_ver().
556
+ api_level = platform.android_ver().api_level # type: ignore[attr-defined]
557
+
558
+ if abi is None:
559
+ abi = sysconfig.get_platform().split("-")[-1]
560
+ abi = _normalize_string(abi)
561
+
562
+ # 16 is the minimum API level known to have enough features to support CPython
563
+ # without major patching. Yield every API level from the maximum down to the
564
+ # minimum, inclusive.
565
+ min_api_level = 16
566
+ for ver in range(api_level, min_api_level - 1, -1):
567
+ yield f"android_{ver}_{abi}"
568
+
569
+
570
+ def _linux_platforms(is_32bit: bool = _32_BIT_INTERPRETER) -> Iterator[str]:
571
+ linux = _normalize_string(sysconfig.get_platform())
572
+ if not linux.startswith("linux_"):
573
+ # we should never be here, just yield the sysconfig one and return
574
+ yield linux
575
+ return
576
+ if is_32bit:
577
+ if linux == "linux_x86_64":
578
+ linux = "linux_i686"
579
+ elif linux == "linux_aarch64":
580
+ linux = "linux_armv8l"
581
+ _, arch = linux.split("_", 1)
582
+ archs = {"armv8l": ["armv8l", "armv7l"]}.get(arch, [arch])
583
+ yield from _manylinux.platform_tags(archs)
584
+ yield from _musllinux.platform_tags(archs)
585
+ for arch in archs:
586
+ yield f"linux_{arch}"
587
+
588
+
589
+ def _generic_platforms() -> Iterator[str]:
590
+ yield _normalize_string(sysconfig.get_platform())
591
+
592
+
593
+ def platform_tags() -> Iterator[str]:
594
+ """
595
+ Provides the platform tags for this installation.
596
+ """
597
+ if platform.system() == "Darwin":
598
+ return mac_platforms()
599
+ elif platform.system() == "iOS":
600
+ return ios_platforms()
601
+ elif platform.system() == "Android":
602
+ return android_platforms()
603
+ elif platform.system() == "Linux":
604
+ return _linux_platforms()
605
+ else:
606
+ return _generic_platforms()
607
+
608
+
609
+ def interpreter_name() -> str:
610
+ """
611
+ Returns the name of the running interpreter.
612
+
613
+ Some implementations have a reserved, two-letter abbreviation which will
614
+ be returned when appropriate.
615
+ """
616
+ name = sys.implementation.name
617
+ return INTERPRETER_SHORT_NAMES.get(name) or name
618
+
619
+
620
+ def interpreter_version(*, warn: bool = False) -> str:
621
+ """
622
+ Returns the version of the running interpreter.
623
+ """
624
+ version = _get_config_var("py_version_nodot", warn=warn)
625
+ if version:
626
+ version = str(version)
627
+ else:
628
+ version = _version_nodot(sys.version_info[:2])
629
+ return version
630
+
631
+
632
+ def _version_nodot(version: PythonVersion) -> str:
633
+ return "".join(map(str, version))
634
+
635
+
636
+ def sys_tags(*, warn: bool = False) -> Iterator[Tag]:
637
+ """
638
+ Returns the sequence of tag triples for the running interpreter.
639
+
640
+ The order of the sequence corresponds to priority order for the
641
+ interpreter, from most to least important.
642
+ """
643
+
644
+ interp_name = interpreter_name()
645
+ if interp_name == "cp":
646
+ yield from cpython_tags(warn=warn)
647
+ else:
648
+ yield from generic_tags()
649
+
650
+ if interp_name == "pp":
651
+ interp = "pp3"
652
+ elif interp_name == "cp":
653
+ interp = "cp" + interpreter_version(warn=warn)
654
+ else:
655
+ interp = None
656
+ yield from compatible_tags(interpreter=interp)
venv/lib/python3.12/site-packages/packaging/utils.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+
5
+ from __future__ import annotations
6
+
7
+ import functools
8
+ import re
9
+ from typing import NewType, Tuple, Union, cast
10
+
11
+ from .tags import Tag, parse_tag
12
+ from .version import InvalidVersion, Version, _TrimmedRelease
13
+
14
+ BuildTag = Union[Tuple[()], Tuple[int, str]]
15
+ NormalizedName = NewType("NormalizedName", str)
16
+
17
+
18
+ class InvalidName(ValueError):
19
+ """
20
+ An invalid distribution name; users should refer to the packaging user guide.
21
+ """
22
+
23
+
24
+ class InvalidWheelFilename(ValueError):
25
+ """
26
+ An invalid wheel filename was found, users should refer to PEP 427.
27
+ """
28
+
29
+
30
+ class InvalidSdistFilename(ValueError):
31
+ """
32
+ An invalid sdist filename was found, users should refer to the packaging user guide.
33
+ """
34
+
35
+
36
+ # Core metadata spec for `Name`
37
+ _validate_regex = re.compile(
38
+ r"^([A-Z0-9]|[A-Z0-9][A-Z0-9._-]*[A-Z0-9])$", re.IGNORECASE
39
+ )
40
+ _canonicalize_regex = re.compile(r"[-_.]+")
41
+ _normalized_regex = re.compile(r"^([a-z0-9]|[a-z0-9]([a-z0-9-](?!--))*[a-z0-9])$")
42
+ # PEP 427: The build number must start with a digit.
43
+ _build_tag_regex = re.compile(r"(\d+)(.*)")
44
+
45
+
46
+ def canonicalize_name(name: str, *, validate: bool = False) -> NormalizedName:
47
+ if validate and not _validate_regex.match(name):
48
+ raise InvalidName(f"name is invalid: {name!r}")
49
+ # This is taken from PEP 503.
50
+ value = _canonicalize_regex.sub("-", name).lower()
51
+ return cast(NormalizedName, value)
52
+
53
+
54
+ def is_normalized_name(name: str) -> bool:
55
+ return _normalized_regex.match(name) is not None
56
+
57
+
58
+ @functools.singledispatch
59
+ def canonicalize_version(
60
+ version: Version | str, *, strip_trailing_zero: bool = True
61
+ ) -> str:
62
+ """
63
+ Return a canonical form of a version as a string.
64
+
65
+ >>> canonicalize_version('1.0.1')
66
+ '1.0.1'
67
+
68
+ Per PEP 625, versions may have multiple canonical forms, differing
69
+ only by trailing zeros.
70
+
71
+ >>> canonicalize_version('1.0.0')
72
+ '1'
73
+ >>> canonicalize_version('1.0.0', strip_trailing_zero=False)
74
+ '1.0.0'
75
+
76
+ Invalid versions are returned unaltered.
77
+
78
+ >>> canonicalize_version('foo bar baz')
79
+ 'foo bar baz'
80
+ """
81
+ return str(_TrimmedRelease(str(version)) if strip_trailing_zero else version)
82
+
83
+
84
+ @canonicalize_version.register
85
+ def _(version: str, *, strip_trailing_zero: bool = True) -> str:
86
+ try:
87
+ parsed = Version(version)
88
+ except InvalidVersion:
89
+ # Legacy versions cannot be normalized
90
+ return version
91
+ return canonicalize_version(parsed, strip_trailing_zero=strip_trailing_zero)
92
+
93
+
94
+ def parse_wheel_filename(
95
+ filename: str,
96
+ ) -> tuple[NormalizedName, Version, BuildTag, frozenset[Tag]]:
97
+ if not filename.endswith(".whl"):
98
+ raise InvalidWheelFilename(
99
+ f"Invalid wheel filename (extension must be '.whl'): {filename!r}"
100
+ )
101
+
102
+ filename = filename[:-4]
103
+ dashes = filename.count("-")
104
+ if dashes not in (4, 5):
105
+ raise InvalidWheelFilename(
106
+ f"Invalid wheel filename (wrong number of parts): {filename!r}"
107
+ )
108
+
109
+ parts = filename.split("-", dashes - 2)
110
+ name_part = parts[0]
111
+ # See PEP 427 for the rules on escaping the project name.
112
+ if "__" in name_part or re.match(r"^[\w\d._]*$", name_part, re.UNICODE) is None:
113
+ raise InvalidWheelFilename(f"Invalid project name: {filename!r}")
114
+ name = canonicalize_name(name_part)
115
+
116
+ try:
117
+ version = Version(parts[1])
118
+ except InvalidVersion as e:
119
+ raise InvalidWheelFilename(
120
+ f"Invalid wheel filename (invalid version): {filename!r}"
121
+ ) from e
122
+
123
+ if dashes == 5:
124
+ build_part = parts[2]
125
+ build_match = _build_tag_regex.match(build_part)
126
+ if build_match is None:
127
+ raise InvalidWheelFilename(
128
+ f"Invalid build number: {build_part} in {filename!r}"
129
+ )
130
+ build = cast(BuildTag, (int(build_match.group(1)), build_match.group(2)))
131
+ else:
132
+ build = ()
133
+ tags = parse_tag(parts[-1])
134
+ return (name, version, build, tags)
135
+
136
+
137
+ def parse_sdist_filename(filename: str) -> tuple[NormalizedName, Version]:
138
+ if filename.endswith(".tar.gz"):
139
+ file_stem = filename[: -len(".tar.gz")]
140
+ elif filename.endswith(".zip"):
141
+ file_stem = filename[: -len(".zip")]
142
+ else:
143
+ raise InvalidSdistFilename(
144
+ f"Invalid sdist filename (extension must be '.tar.gz' or '.zip'):"
145
+ f" {filename!r}"
146
+ )
147
+
148
+ # We are requiring a PEP 440 version, which cannot contain dashes,
149
+ # so we split on the last dash.
150
+ name_part, sep, version_part = file_stem.rpartition("-")
151
+ if not sep:
152
+ raise InvalidSdistFilename(f"Invalid sdist filename: {filename!r}")
153
+
154
+ name = canonicalize_name(name_part)
155
+
156
+ try:
157
+ version = Version(version_part)
158
+ except InvalidVersion as e:
159
+ raise InvalidSdistFilename(
160
+ f"Invalid sdist filename (invalid version): {filename!r}"
161
+ ) from e
162
+
163
+ return (name, version)
venv/lib/python3.12/site-packages/packaging/version.py ADDED
@@ -0,0 +1,582 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # This file is dual licensed under the terms of the Apache License, Version
2
+ # 2.0, and the BSD License. See the LICENSE file in the root of this repository
3
+ # for complete details.
4
+ """
5
+ .. testsetup::
6
+
7
+ from packaging.version import parse, Version
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import itertools
13
+ import re
14
+ from typing import Any, Callable, NamedTuple, SupportsInt, Tuple, Union
15
+
16
+ from ._structures import Infinity, InfinityType, NegativeInfinity, NegativeInfinityType
17
+
18
+ __all__ = ["VERSION_PATTERN", "InvalidVersion", "Version", "parse"]
19
+
20
+ LocalType = Tuple[Union[int, str], ...]
21
+
22
+ CmpPrePostDevType = Union[InfinityType, NegativeInfinityType, Tuple[str, int]]
23
+ CmpLocalType = Union[
24
+ NegativeInfinityType,
25
+ Tuple[Union[Tuple[int, str], Tuple[NegativeInfinityType, Union[int, str]]], ...],
26
+ ]
27
+ CmpKey = Tuple[
28
+ int,
29
+ Tuple[int, ...],
30
+ CmpPrePostDevType,
31
+ CmpPrePostDevType,
32
+ CmpPrePostDevType,
33
+ CmpLocalType,
34
+ ]
35
+ VersionComparisonMethod = Callable[[CmpKey, CmpKey], bool]
36
+
37
+
38
+ class _Version(NamedTuple):
39
+ epoch: int
40
+ release: tuple[int, ...]
41
+ dev: tuple[str, int] | None
42
+ pre: tuple[str, int] | None
43
+ post: tuple[str, int] | None
44
+ local: LocalType | None
45
+
46
+
47
+ def parse(version: str) -> Version:
48
+ """Parse the given version string.
49
+
50
+ >>> parse('1.0.dev1')
51
+ <Version('1.0.dev1')>
52
+
53
+ :param version: The version string to parse.
54
+ :raises InvalidVersion: When the version string is not a valid version.
55
+ """
56
+ return Version(version)
57
+
58
+
59
+ class InvalidVersion(ValueError):
60
+ """Raised when a version string is not a valid version.
61
+
62
+ >>> Version("invalid")
63
+ Traceback (most recent call last):
64
+ ...
65
+ packaging.version.InvalidVersion: Invalid version: 'invalid'
66
+ """
67
+
68
+
69
+ class _BaseVersion:
70
+ _key: tuple[Any, ...]
71
+
72
+ def __hash__(self) -> int:
73
+ return hash(self._key)
74
+
75
+ # Please keep the duplicated `isinstance` check
76
+ # in the six comparisons hereunder
77
+ # unless you find a way to avoid adding overhead function calls.
78
+ def __lt__(self, other: _BaseVersion) -> bool:
79
+ if not isinstance(other, _BaseVersion):
80
+ return NotImplemented
81
+
82
+ return self._key < other._key
83
+
84
+ def __le__(self, other: _BaseVersion) -> bool:
85
+ if not isinstance(other, _BaseVersion):
86
+ return NotImplemented
87
+
88
+ return self._key <= other._key
89
+
90
+ def __eq__(self, other: object) -> bool:
91
+ if not isinstance(other, _BaseVersion):
92
+ return NotImplemented
93
+
94
+ return self._key == other._key
95
+
96
+ def __ge__(self, other: _BaseVersion) -> bool:
97
+ if not isinstance(other, _BaseVersion):
98
+ return NotImplemented
99
+
100
+ return self._key >= other._key
101
+
102
+ def __gt__(self, other: _BaseVersion) -> bool:
103
+ if not isinstance(other, _BaseVersion):
104
+ return NotImplemented
105
+
106
+ return self._key > other._key
107
+
108
+ def __ne__(self, other: object) -> bool:
109
+ if not isinstance(other, _BaseVersion):
110
+ return NotImplemented
111
+
112
+ return self._key != other._key
113
+
114
+
115
+ # Deliberately not anchored to the start and end of the string, to make it
116
+ # easier for 3rd party code to reuse
117
+ _VERSION_PATTERN = r"""
118
+ v?
119
+ (?:
120
+ (?:(?P<epoch>[0-9]+)!)? # epoch
121
+ (?P<release>[0-9]+(?:\.[0-9]+)*) # release segment
122
+ (?P<pre> # pre-release
123
+ [-_\.]?
124
+ (?P<pre_l>alpha|a|beta|b|preview|pre|c|rc)
125
+ [-_\.]?
126
+ (?P<pre_n>[0-9]+)?
127
+ )?
128
+ (?P<post> # post release
129
+ (?:-(?P<post_n1>[0-9]+))
130
+ |
131
+ (?:
132
+ [-_\.]?
133
+ (?P<post_l>post|rev|r)
134
+ [-_\.]?
135
+ (?P<post_n2>[0-9]+)?
136
+ )
137
+ )?
138
+ (?P<dev> # dev release
139
+ [-_\.]?
140
+ (?P<dev_l>dev)
141
+ [-_\.]?
142
+ (?P<dev_n>[0-9]+)?
143
+ )?
144
+ )
145
+ (?:\+(?P<local>[a-z0-9]+(?:[-_\.][a-z0-9]+)*))? # local version
146
+ """
147
+
148
+ VERSION_PATTERN = _VERSION_PATTERN
149
+ """
150
+ A string containing the regular expression used to match a valid version.
151
+
152
+ The pattern is not anchored at either end, and is intended for embedding in larger
153
+ expressions (for example, matching a version number as part of a file name). The
154
+ regular expression should be compiled with the ``re.VERBOSE`` and ``re.IGNORECASE``
155
+ flags set.
156
+
157
+ :meta hide-value:
158
+ """
159
+
160
+
161
+ class Version(_BaseVersion):
162
+ """This class abstracts handling of a project's versions.
163
+
164
+ A :class:`Version` instance is comparison aware and can be compared and
165
+ sorted using the standard Python interfaces.
166
+
167
+ >>> v1 = Version("1.0a5")
168
+ >>> v2 = Version("1.0")
169
+ >>> v1
170
+ <Version('1.0a5')>
171
+ >>> v2
172
+ <Version('1.0')>
173
+ >>> v1 < v2
174
+ True
175
+ >>> v1 == v2
176
+ False
177
+ >>> v1 > v2
178
+ False
179
+ >>> v1 >= v2
180
+ False
181
+ >>> v1 <= v2
182
+ True
183
+ """
184
+
185
+ _regex = re.compile(r"^\s*" + VERSION_PATTERN + r"\s*$", re.VERBOSE | re.IGNORECASE)
186
+ _key: CmpKey
187
+
188
+ def __init__(self, version: str) -> None:
189
+ """Initialize a Version object.
190
+
191
+ :param version:
192
+ The string representation of a version which will be parsed and normalized
193
+ before use.
194
+ :raises InvalidVersion:
195
+ If the ``version`` does not conform to PEP 440 in any way then this
196
+ exception will be raised.
197
+ """
198
+
199
+ # Validate the version and parse it into pieces
200
+ match = self._regex.search(version)
201
+ if not match:
202
+ raise InvalidVersion(f"Invalid version: {version!r}")
203
+
204
+ # Store the parsed out pieces of the version
205
+ self._version = _Version(
206
+ epoch=int(match.group("epoch")) if match.group("epoch") else 0,
207
+ release=tuple(int(i) for i in match.group("release").split(".")),
208
+ pre=_parse_letter_version(match.group("pre_l"), match.group("pre_n")),
209
+ post=_parse_letter_version(
210
+ match.group("post_l"), match.group("post_n1") or match.group("post_n2")
211
+ ),
212
+ dev=_parse_letter_version(match.group("dev_l"), match.group("dev_n")),
213
+ local=_parse_local_version(match.group("local")),
214
+ )
215
+
216
+ # Generate a key which will be used for sorting
217
+ self._key = _cmpkey(
218
+ self._version.epoch,
219
+ self._version.release,
220
+ self._version.pre,
221
+ self._version.post,
222
+ self._version.dev,
223
+ self._version.local,
224
+ )
225
+
226
+ def __repr__(self) -> str:
227
+ """A representation of the Version that shows all internal state.
228
+
229
+ >>> Version('1.0.0')
230
+ <Version('1.0.0')>
231
+ """
232
+ return f"<Version('{self}')>"
233
+
234
+ def __str__(self) -> str:
235
+ """A string representation of the version that can be round-tripped.
236
+
237
+ >>> str(Version("1.0a5"))
238
+ '1.0a5'
239
+ """
240
+ parts = []
241
+
242
+ # Epoch
243
+ if self.epoch != 0:
244
+ parts.append(f"{self.epoch}!")
245
+
246
+ # Release segment
247
+ parts.append(".".join(str(x) for x in self.release))
248
+
249
+ # Pre-release
250
+ if self.pre is not None:
251
+ parts.append("".join(str(x) for x in self.pre))
252
+
253
+ # Post-release
254
+ if self.post is not None:
255
+ parts.append(f".post{self.post}")
256
+
257
+ # Development release
258
+ if self.dev is not None:
259
+ parts.append(f".dev{self.dev}")
260
+
261
+ # Local version segment
262
+ if self.local is not None:
263
+ parts.append(f"+{self.local}")
264
+
265
+ return "".join(parts)
266
+
267
+ @property
268
+ def epoch(self) -> int:
269
+ """The epoch of the version.
270
+
271
+ >>> Version("2.0.0").epoch
272
+ 0
273
+ >>> Version("1!2.0.0").epoch
274
+ 1
275
+ """
276
+ return self._version.epoch
277
+
278
+ @property
279
+ def release(self) -> tuple[int, ...]:
280
+ """The components of the "release" segment of the version.
281
+
282
+ >>> Version("1.2.3").release
283
+ (1, 2, 3)
284
+ >>> Version("2.0.0").release
285
+ (2, 0, 0)
286
+ >>> Version("1!2.0.0.post0").release
287
+ (2, 0, 0)
288
+
289
+ Includes trailing zeroes but not the epoch or any pre-release / development /
290
+ post-release suffixes.
291
+ """
292
+ return self._version.release
293
+
294
+ @property
295
+ def pre(self) -> tuple[str, int] | None:
296
+ """The pre-release segment of the version.
297
+
298
+ >>> print(Version("1.2.3").pre)
299
+ None
300
+ >>> Version("1.2.3a1").pre
301
+ ('a', 1)
302
+ >>> Version("1.2.3b1").pre
303
+ ('b', 1)
304
+ >>> Version("1.2.3rc1").pre
305
+ ('rc', 1)
306
+ """
307
+ return self._version.pre
308
+
309
+ @property
310
+ def post(self) -> int | None:
311
+ """The post-release number of the version.
312
+
313
+ >>> print(Version("1.2.3").post)
314
+ None
315
+ >>> Version("1.2.3.post1").post
316
+ 1
317
+ """
318
+ return self._version.post[1] if self._version.post else None
319
+
320
+ @property
321
+ def dev(self) -> int | None:
322
+ """The development number of the version.
323
+
324
+ >>> print(Version("1.2.3").dev)
325
+ None
326
+ >>> Version("1.2.3.dev1").dev
327
+ 1
328
+ """
329
+ return self._version.dev[1] if self._version.dev else None
330
+
331
+ @property
332
+ def local(self) -> str | None:
333
+ """The local version segment of the version.
334
+
335
+ >>> print(Version("1.2.3").local)
336
+ None
337
+ >>> Version("1.2.3+abc").local
338
+ 'abc'
339
+ """
340
+ if self._version.local:
341
+ return ".".join(str(x) for x in self._version.local)
342
+ else:
343
+ return None
344
+
345
+ @property
346
+ def public(self) -> str:
347
+ """The public portion of the version.
348
+
349
+ >>> Version("1.2.3").public
350
+ '1.2.3'
351
+ >>> Version("1.2.3+abc").public
352
+ '1.2.3'
353
+ >>> Version("1!1.2.3dev1+abc").public
354
+ '1!1.2.3.dev1'
355
+ """
356
+ return str(self).split("+", 1)[0]
357
+
358
+ @property
359
+ def base_version(self) -> str:
360
+ """The "base version" of the version.
361
+
362
+ >>> Version("1.2.3").base_version
363
+ '1.2.3'
364
+ >>> Version("1.2.3+abc").base_version
365
+ '1.2.3'
366
+ >>> Version("1!1.2.3dev1+abc").base_version
367
+ '1!1.2.3'
368
+
369
+ The "base version" is the public version of the project without any pre or post
370
+ release markers.
371
+ """
372
+ parts = []
373
+
374
+ # Epoch
375
+ if self.epoch != 0:
376
+ parts.append(f"{self.epoch}!")
377
+
378
+ # Release segment
379
+ parts.append(".".join(str(x) for x in self.release))
380
+
381
+ return "".join(parts)
382
+
383
+ @property
384
+ def is_prerelease(self) -> bool:
385
+ """Whether this version is a pre-release.
386
+
387
+ >>> Version("1.2.3").is_prerelease
388
+ False
389
+ >>> Version("1.2.3a1").is_prerelease
390
+ True
391
+ >>> Version("1.2.3b1").is_prerelease
392
+ True
393
+ >>> Version("1.2.3rc1").is_prerelease
394
+ True
395
+ >>> Version("1.2.3dev1").is_prerelease
396
+ True
397
+ """
398
+ return self.dev is not None or self.pre is not None
399
+
400
+ @property
401
+ def is_postrelease(self) -> bool:
402
+ """Whether this version is a post-release.
403
+
404
+ >>> Version("1.2.3").is_postrelease
405
+ False
406
+ >>> Version("1.2.3.post1").is_postrelease
407
+ True
408
+ """
409
+ return self.post is not None
410
+
411
+ @property
412
+ def is_devrelease(self) -> bool:
413
+ """Whether this version is a development release.
414
+
415
+ >>> Version("1.2.3").is_devrelease
416
+ False
417
+ >>> Version("1.2.3.dev1").is_devrelease
418
+ True
419
+ """
420
+ return self.dev is not None
421
+
422
+ @property
423
+ def major(self) -> int:
424
+ """The first item of :attr:`release` or ``0`` if unavailable.
425
+
426
+ >>> Version("1.2.3").major
427
+ 1
428
+ """
429
+ return self.release[0] if len(self.release) >= 1 else 0
430
+
431
+ @property
432
+ def minor(self) -> int:
433
+ """The second item of :attr:`release` or ``0`` if unavailable.
434
+
435
+ >>> Version("1.2.3").minor
436
+ 2
437
+ >>> Version("1").minor
438
+ 0
439
+ """
440
+ return self.release[1] if len(self.release) >= 2 else 0
441
+
442
+ @property
443
+ def micro(self) -> int:
444
+ """The third item of :attr:`release` or ``0`` if unavailable.
445
+
446
+ >>> Version("1.2.3").micro
447
+ 3
448
+ >>> Version("1").micro
449
+ 0
450
+ """
451
+ return self.release[2] if len(self.release) >= 3 else 0
452
+
453
+
454
+ class _TrimmedRelease(Version):
455
+ @property
456
+ def release(self) -> tuple[int, ...]:
457
+ """
458
+ Release segment without any trailing zeros.
459
+
460
+ >>> _TrimmedRelease('1.0.0').release
461
+ (1,)
462
+ >>> _TrimmedRelease('0.0').release
463
+ (0,)
464
+ """
465
+ rel = super().release
466
+ nonzeros = (index for index, val in enumerate(rel) if val)
467
+ last_nonzero = max(nonzeros, default=0)
468
+ return rel[: last_nonzero + 1]
469
+
470
+
471
+ def _parse_letter_version(
472
+ letter: str | None, number: str | bytes | SupportsInt | None
473
+ ) -> tuple[str, int] | None:
474
+ if letter:
475
+ # We consider there to be an implicit 0 in a pre-release if there is
476
+ # not a numeral associated with it.
477
+ if number is None:
478
+ number = 0
479
+
480
+ # We normalize any letters to their lower case form
481
+ letter = letter.lower()
482
+
483
+ # We consider some words to be alternate spellings of other words and
484
+ # in those cases we want to normalize the spellings to our preferred
485
+ # spelling.
486
+ if letter == "alpha":
487
+ letter = "a"
488
+ elif letter == "beta":
489
+ letter = "b"
490
+ elif letter in ["c", "pre", "preview"]:
491
+ letter = "rc"
492
+ elif letter in ["rev", "r"]:
493
+ letter = "post"
494
+
495
+ return letter, int(number)
496
+
497
+ assert not letter
498
+ if number:
499
+ # We assume if we are given a number, but we are not given a letter
500
+ # then this is using the implicit post release syntax (e.g. 1.0-1)
501
+ letter = "post"
502
+
503
+ return letter, int(number)
504
+
505
+ return None
506
+
507
+
508
+ _local_version_separators = re.compile(r"[\._-]")
509
+
510
+
511
+ def _parse_local_version(local: str | None) -> LocalType | None:
512
+ """
513
+ Takes a string like abc.1.twelve and turns it into ("abc", 1, "twelve").
514
+ """
515
+ if local is not None:
516
+ return tuple(
517
+ part.lower() if not part.isdigit() else int(part)
518
+ for part in _local_version_separators.split(local)
519
+ )
520
+ return None
521
+
522
+
523
+ def _cmpkey(
524
+ epoch: int,
525
+ release: tuple[int, ...],
526
+ pre: tuple[str, int] | None,
527
+ post: tuple[str, int] | None,
528
+ dev: tuple[str, int] | None,
529
+ local: LocalType | None,
530
+ ) -> CmpKey:
531
+ # When we compare a release version, we want to compare it with all of the
532
+ # trailing zeros removed. So we'll use a reverse the list, drop all the now
533
+ # leading zeros until we come to something non zero, then take the rest
534
+ # re-reverse it back into the correct order and make it a tuple and use
535
+ # that for our sorting key.
536
+ _release = tuple(
537
+ reversed(list(itertools.dropwhile(lambda x: x == 0, reversed(release))))
538
+ )
539
+
540
+ # We need to "trick" the sorting algorithm to put 1.0.dev0 before 1.0a0.
541
+ # We'll do this by abusing the pre segment, but we _only_ want to do this
542
+ # if there is not a pre or a post segment. If we have one of those then
543
+ # the normal sorting rules will handle this case correctly.
544
+ if pre is None and post is None and dev is not None:
545
+ _pre: CmpPrePostDevType = NegativeInfinity
546
+ # Versions without a pre-release (except as noted above) should sort after
547
+ # those with one.
548
+ elif pre is None:
549
+ _pre = Infinity
550
+ else:
551
+ _pre = pre
552
+
553
+ # Versions without a post segment should sort before those with one.
554
+ if post is None:
555
+ _post: CmpPrePostDevType = NegativeInfinity
556
+
557
+ else:
558
+ _post = post
559
+
560
+ # Versions without a development segment should sort after those with one.
561
+ if dev is None:
562
+ _dev: CmpPrePostDevType = Infinity
563
+
564
+ else:
565
+ _dev = dev
566
+
567
+ if local is None:
568
+ # Versions without a local segment should sort before those with one.
569
+ _local: CmpLocalType = NegativeInfinity
570
+ else:
571
+ # Versions with a local segment need that segment parsed to implement
572
+ # the sorting rules in PEP440.
573
+ # - Alpha numeric segments sort before numeric segments
574
+ # - Alpha numeric segments sort lexicographically
575
+ # - Numeric segments sort numerically
576
+ # - Shorter versions sort before longer versions when the prefixes
577
+ # match exactly
578
+ _local = tuple(
579
+ (i, "") if isinstance(i, int) else (NegativeInfinity, i) for i in local
580
+ )
581
+
582
+ return epoch, _release, _pre, _post, _dev, _local
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‮
venv/lib/python3.12/site-packages/pip-24.0.dist-info/INSTALLER ADDED
@@ -0,0 +1 @@
 
 
1
+ pip
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
venv/lib/python3.12/site-packages/pip-24.0.dist-info/RECORD ADDED
@@ -0,0 +1,1005 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ../../../bin/pip,sha256=pGsj1Dkk0eAwh83TWZEEOIhoZiU3auFKr3DbzSuEQbs,248
2
+ ../../../bin/pip3,sha256=pGsj1Dkk0eAwh83TWZEEOIhoZiU3auFKr3DbzSuEQbs,248
3
+ ../../../bin/pip3.12,sha256=pGsj1Dkk0eAwh83TWZEEOIhoZiU3auFKr3DbzSuEQbs,248
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=1JxchwKzkxBSn7R_oCE12oBu3eVux0VzdxolmIad24M,12950
514
+ pip/_vendor/idna/idnadata.py,sha256=xUjqKqiJV8Ho_XzBpAtv5JFoVPSupK-SUXvtjygUHqw,44375
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=kOPn0qYD6xRTzaxbqTdYiSInBZHl6379AJsyIgzYGLY,33460
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=Rp1mVyBgc_UlAcp6M3at1skJBXR5J43NawRTvW2g_XY,10811
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=ItVDasDnPRPP9R8bNxY7tPBlC724nJ9nlxVgXG_SLbI,39990
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=dnQHy25qCcoJZGM8zrcmuW48tHF3UO83bxvkySwtf24,20705
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
venv/lib/python3.12/site-packages/pip-24.0.dist-info/REQUESTED ADDED
File without changes
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
venv/lib/python3.12/site-packages/typing_extensions.py ADDED
The diff for this file is too large to render. See raw diff