Spaces:
Running
Running
Improved UI
Browse filesThis view is limited to 50 files because it contains too many changes.
See raw diff
- .idx/dev.nix +60 -0
- __pycache__/config.cpython-311.pyc +0 -0
- venv/bin/Activate.ps1 +247 -0
- venv/bin/activate +63 -0
- venv/bin/activate.csh +26 -0
- venv/bin/activate.fish +69 -0
- venv/bin/flask +8 -0
- venv/bin/normalizer +8 -0
- venv/bin/pip +8 -0
- venv/bin/pip3 +8 -0
- venv/bin/pip3.11 +8 -0
- venv/bin/python +1 -0
- venv/bin/python3 +1 -0
- venv/bin/python3.11 +1 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER +1 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt +28 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/METADATA +92 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/RECORD +14 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL +6 -0
- venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt +1 -0
- venv/lib/python3.11/site-packages/_distutils_hack/__init__.py +222 -0
- venv/lib/python3.11/site-packages/_distutils_hack/__pycache__/__init__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/_distutils_hack/__pycache__/override.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/_distutils_hack/override.py +1 -0
- venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/INSTALLER +1 -0
- venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/LICENSE.txt +20 -0
- venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/METADATA +60 -0
- venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/RECORD +12 -0
- venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/WHEEL +4 -0
- venv/lib/python3.11/site-packages/blinker/__init__.py +17 -0
- venv/lib/python3.11/site-packages/blinker/__pycache__/__init__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/blinker/__pycache__/_utilities.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/blinker/__pycache__/base.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/blinker/_utilities.py +64 -0
- venv/lib/python3.11/site-packages/blinker/base.py +512 -0
- venv/lib/python3.11/site-packages/blinker/py.typed +0 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/INSTALLER +1 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/LICENSE +20 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/METADATA +68 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/RECORD +14 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/WHEEL +5 -0
- venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/top_level.txt +1 -0
- venv/lib/python3.11/site-packages/certifi/__init__.py +4 -0
- venv/lib/python3.11/site-packages/certifi/__main__.py +12 -0
- venv/lib/python3.11/site-packages/certifi/__pycache__/__init__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/certifi/__pycache__/__main__.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/certifi/__pycache__/core.cpython-311.pyc +0 -0
- venv/lib/python3.11/site-packages/certifi/cacert.pem +0 -0
- venv/lib/python3.11/site-packages/certifi/core.py +114 -0
- venv/lib/python3.11/site-packages/certifi/py.typed +0 -0
.idx/dev.nix
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{ pkgs, ... }: {
|
2 |
+
# Which nixpkgs channel to use.
|
3 |
+
channel = "stable-24.05"; # or "unstable"
|
4 |
+
|
5 |
+
# Use https://search.nixos.org/packages to find packages
|
6 |
+
packages = [
|
7 |
+
pkgs.python311
|
8 |
+
pkgs.python311Packages.pip
|
9 |
+
pkgs.python311Packages.virtualenv
|
10 |
+
pkgs.python311Packages.black # Optional: Add a popular Python code formatter
|
11 |
+
pkgs.python311Packages.isort # Optional: Add a Python code sorter
|
12 |
+
pkgs.python311Packages.flake8 # Optional: Add a Python linter
|
13 |
+
];
|
14 |
+
|
15 |
+
# Sets environment variables in the workspace
|
16 |
+
env = {
|
17 |
+
PYTHONPATH = "$HOME/.local/lib/python3.11/site-packages";
|
18 |
+
};
|
19 |
+
|
20 |
+
idx = {
|
21 |
+
# Search for the extensions you want on https://open-vsx.org/ and use "publisher.id"
|
22 |
+
extensions = [
|
23 |
+
# "vscodevim.vim" # Uncomment if you want the Vim extension for VSCode
|
24 |
+
];
|
25 |
+
|
26 |
+
# Enable previews
|
27 |
+
previews = {
|
28 |
+
enable = true;
|
29 |
+
previews = {
|
30 |
+
# Example for running a Python script in a web preview:
|
31 |
+
# web = {
|
32 |
+
# command = ["python" "app.py"];
|
33 |
+
# manager = "web";
|
34 |
+
# env = {
|
35 |
+
# # Set environment variables like PORT if needed
|
36 |
+
# PORT = "$PORT";
|
37 |
+
# };
|
38 |
+
# };
|
39 |
+
};
|
40 |
+
};
|
41 |
+
|
42 |
+
# Workspace lifecycle hooks
|
43 |
+
workspace = {
|
44 |
+
# Runs when a workspace is first created
|
45 |
+
onCreate = {
|
46 |
+
# Example: Set up a virtual environment and install dependencies
|
47 |
+
install_dependencies = ''
|
48 |
+
python3 -m venv .venv
|
49 |
+
. .venv/bin/activate
|
50 |
+
pip install -r requirements.txt # Assuming a requirements.txt file exists
|
51 |
+
'';
|
52 |
+
};
|
53 |
+
# Runs when the workspace is (re)started
|
54 |
+
onStart = {
|
55 |
+
# Example: Run a background task like starting a Python server
|
56 |
+
# start-server = "python3 -m http.server";
|
57 |
+
};
|
58 |
+
};
|
59 |
+
};
|
60 |
+
}
|
__pycache__/config.cpython-311.pyc
ADDED
Binary file (813 Bytes). View file
|
|
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,63 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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 |
+
VIRTUAL_ENV="/home/user/AI-Chat-UI/venv"
|
39 |
+
export VIRTUAL_ENV
|
40 |
+
|
41 |
+
_OLD_VIRTUAL_PATH="$PATH"
|
42 |
+
PATH="$VIRTUAL_ENV/bin:$PATH"
|
43 |
+
export PATH
|
44 |
+
|
45 |
+
# unset PYTHONHOME if set
|
46 |
+
# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
|
47 |
+
# could use `if (set -u; : $PYTHONHOME) ;` in bash
|
48 |
+
if [ -n "${PYTHONHOME:-}" ] ; then
|
49 |
+
_OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
|
50 |
+
unset PYTHONHOME
|
51 |
+
fi
|
52 |
+
|
53 |
+
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
|
54 |
+
_OLD_VIRTUAL_PS1="${PS1:-}"
|
55 |
+
PS1="(venv) ${PS1:-}"
|
56 |
+
export PS1
|
57 |
+
VIRTUAL_ENV_PROMPT="(venv) "
|
58 |
+
export VIRTUAL_ENV_PROMPT
|
59 |
+
fi
|
60 |
+
|
61 |
+
# Call hash to forget past commands. Without forgetting
|
62 |
+
# past commands the $PATH changes we made may not be respected
|
63 |
+
hash -r 2> /dev/null
|
venv/bin/activate.csh
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# This file must be used with "source bin/activate.csh" *from csh*.
|
2 |
+
# You cannot run it directly.
|
3 |
+
# Created by Davide Di Blasi <[email protected]>.
|
4 |
+
# Ported to Python 3.3 venv by Andrew Svetlov <[email protected]>
|
5 |
+
|
6 |
+
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'
|
7 |
+
|
8 |
+
# Unset irrelevant variables.
|
9 |
+
deactivate nondestructive
|
10 |
+
|
11 |
+
setenv VIRTUAL_ENV "/home/user/AI-Chat-UI/venv"
|
12 |
+
|
13 |
+
set _OLD_VIRTUAL_PATH="$PATH"
|
14 |
+
setenv PATH "$VIRTUAL_ENV/bin:$PATH"
|
15 |
+
|
16 |
+
|
17 |
+
set _OLD_VIRTUAL_PROMPT="$prompt"
|
18 |
+
|
19 |
+
if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
|
20 |
+
set prompt = "(venv) $prompt"
|
21 |
+
setenv VIRTUAL_ENV_PROMPT "(venv) "
|
22 |
+
endif
|
23 |
+
|
24 |
+
alias pydoc python -m pydoc
|
25 |
+
|
26 |
+
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/user/AI-Chat-UI/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/flask
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/home/user/AI-Chat-UI/venv/bin/python
|
2 |
+
# -*- coding: utf-8 -*-
|
3 |
+
import re
|
4 |
+
import sys
|
5 |
+
from flask.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/user/AI-Chat-UI/venv/bin/python
|
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/user/AI-Chat-UI/venv/bin/python
|
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/user/AI-Chat-UI/venv/bin/python
|
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.11
ADDED
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/home/user/AI-Chat-UI/venv/bin/python
|
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/python
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
/usr/bin/python
|
venv/bin/python3
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
python
|
venv/bin/python3.11
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
python
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/LICENSE.txt
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright 2010 Pallets
|
2 |
+
|
3 |
+
Redistribution and use in source and binary forms, with or without
|
4 |
+
modification, are permitted provided that the following conditions are
|
5 |
+
met:
|
6 |
+
|
7 |
+
1. Redistributions of source code must retain the above copyright
|
8 |
+
notice, this list of conditions and the following disclaimer.
|
9 |
+
|
10 |
+
2. Redistributions in binary form must reproduce the above copyright
|
11 |
+
notice, this list of conditions and the following disclaimer in the
|
12 |
+
documentation and/or other materials provided with the distribution.
|
13 |
+
|
14 |
+
3. Neither the name of the copyright holder nor the names of its
|
15 |
+
contributors may be used to endorse or promote products derived from
|
16 |
+
this software without specific prior written permission.
|
17 |
+
|
18 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
19 |
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
20 |
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
21 |
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
22 |
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
23 |
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
24 |
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
25 |
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
26 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
27 |
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
28 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/METADATA
ADDED
@@ -0,0 +1,92 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: MarkupSafe
|
3 |
+
Version: 3.0.2
|
4 |
+
Summary: Safely add untrusted strings to HTML/XML markup.
|
5 |
+
Maintainer-email: Pallets <[email protected]>
|
6 |
+
License: Copyright 2010 Pallets
|
7 |
+
|
8 |
+
Redistribution and use in source and binary forms, with or without
|
9 |
+
modification, are permitted provided that the following conditions are
|
10 |
+
met:
|
11 |
+
|
12 |
+
1. Redistributions of source code must retain the above copyright
|
13 |
+
notice, this list of conditions and the following disclaimer.
|
14 |
+
|
15 |
+
2. Redistributions in binary form must reproduce the above copyright
|
16 |
+
notice, this list of conditions and the following disclaimer in the
|
17 |
+
documentation and/or other materials provided with the distribution.
|
18 |
+
|
19 |
+
3. Neither the name of the copyright holder nor the names of its
|
20 |
+
contributors may be used to endorse or promote products derived from
|
21 |
+
this software without specific prior written permission.
|
22 |
+
|
23 |
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
24 |
+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
25 |
+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
26 |
+
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
27 |
+
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
28 |
+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
|
29 |
+
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
30 |
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
31 |
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
32 |
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
33 |
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
34 |
+
|
35 |
+
Project-URL: Donate, https://palletsprojects.com/donate
|
36 |
+
Project-URL: Documentation, https://markupsafe.palletsprojects.com/
|
37 |
+
Project-URL: Changes, https://markupsafe.palletsprojects.com/changes/
|
38 |
+
Project-URL: Source, https://github.com/pallets/markupsafe/
|
39 |
+
Project-URL: Chat, https://discord.gg/pallets
|
40 |
+
Classifier: Development Status :: 5 - Production/Stable
|
41 |
+
Classifier: Environment :: Web Environment
|
42 |
+
Classifier: Intended Audience :: Developers
|
43 |
+
Classifier: License :: OSI Approved :: BSD License
|
44 |
+
Classifier: Operating System :: OS Independent
|
45 |
+
Classifier: Programming Language :: Python
|
46 |
+
Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
|
47 |
+
Classifier: Topic :: Text Processing :: Markup :: HTML
|
48 |
+
Classifier: Typing :: Typed
|
49 |
+
Requires-Python: >=3.9
|
50 |
+
Description-Content-Type: text/markdown
|
51 |
+
License-File: LICENSE.txt
|
52 |
+
|
53 |
+
# MarkupSafe
|
54 |
+
|
55 |
+
MarkupSafe implements a text object that escapes characters so it is
|
56 |
+
safe to use in HTML and XML. Characters that have special meanings are
|
57 |
+
replaced so that they display as the actual characters. This mitigates
|
58 |
+
injection attacks, meaning untrusted user input can safely be displayed
|
59 |
+
on a page.
|
60 |
+
|
61 |
+
|
62 |
+
## Examples
|
63 |
+
|
64 |
+
```pycon
|
65 |
+
>>> from markupsafe import Markup, escape
|
66 |
+
|
67 |
+
>>> # escape replaces special characters and wraps in Markup
|
68 |
+
>>> escape("<script>alert(document.cookie);</script>")
|
69 |
+
Markup('<script>alert(document.cookie);</script>')
|
70 |
+
|
71 |
+
>>> # wrap in Markup to mark text "safe" and prevent escaping
|
72 |
+
>>> Markup("<strong>Hello</strong>")
|
73 |
+
Markup('<strong>hello</strong>')
|
74 |
+
|
75 |
+
>>> escape(Markup("<strong>Hello</strong>"))
|
76 |
+
Markup('<strong>hello</strong>')
|
77 |
+
|
78 |
+
>>> # Markup is a str subclass
|
79 |
+
>>> # methods and operators escape their arguments
|
80 |
+
>>> template = Markup("Hello <em>{name}</em>")
|
81 |
+
>>> template.format(name='"World"')
|
82 |
+
Markup('Hello <em>"World"</em>')
|
83 |
+
```
|
84 |
+
|
85 |
+
## Donate
|
86 |
+
|
87 |
+
The Pallets organization develops and supports MarkupSafe and other
|
88 |
+
popular packages. In order to grow the community of contributors and
|
89 |
+
users, and allow the maintainers to devote more time to the projects,
|
90 |
+
[please donate today][].
|
91 |
+
|
92 |
+
[please donate today]: https://palletsprojects.com/donate
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/RECORD
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
MarkupSafe-3.0.2.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
2 |
+
MarkupSafe-3.0.2.dist-info/LICENSE.txt,sha256=SJqOEQhQntmKN7uYPhHg9-HTHwvY-Zp5yESOf_N9B-o,1475
|
3 |
+
MarkupSafe-3.0.2.dist-info/METADATA,sha256=aAwbZhSmXdfFuMM-rEHpeiHRkBOGESyVLJIuwzHP-nw,3975
|
4 |
+
MarkupSafe-3.0.2.dist-info/RECORD,,
|
5 |
+
MarkupSafe-3.0.2.dist-info/WHEEL,sha256=OhaudQk1f3YCu0uQO5v6u-i01XPoX70c0R3T_XY-jOo,151
|
6 |
+
MarkupSafe-3.0.2.dist-info/top_level.txt,sha256=qy0Plje5IJuvsCBjejJyhDCjEAdcDLK_2agVcex8Z6U,11
|
7 |
+
markupsafe/__init__.py,sha256=sr-U6_27DfaSrj5jnHYxWN-pvhM27sjlDplMDPZKm7k,13214
|
8 |
+
markupsafe/__pycache__/__init__.cpython-311.pyc,,
|
9 |
+
markupsafe/__pycache__/_native.cpython-311.pyc,,
|
10 |
+
markupsafe/_native.py,sha256=hSLs8Jmz5aqayuengJJ3kdT5PwNpBWpKrmQSdipndC8,210
|
11 |
+
markupsafe/_speedups.c,sha256=O7XulmTo-epI6n2FtMVOrJXl8EAaIwD2iNYmBI5SEoQ,4149
|
12 |
+
markupsafe/_speedups.cpython-311-x86_64-linux-gnu.so,sha256=6IDH6Z1ajjClhfGerTB8WLb81uXUpLD8e-e1WzCirVY,43456
|
13 |
+
markupsafe/_speedups.pyi,sha256=ENd1bYe7gbBUf2ywyYWOGUpnXOHNJ-cgTNqetlW8h5k,41
|
14 |
+
markupsafe/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/WHEEL
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (75.2.0)
|
3 |
+
Root-Is-Purelib: false
|
4 |
+
Tag: cp311-cp311-manylinux_2_17_x86_64
|
5 |
+
Tag: cp311-cp311-manylinux2014_x86_64
|
6 |
+
|
venv/lib/python3.11/site-packages/MarkupSafe-3.0.2.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
markupsafe
|
venv/lib/python3.11/site-packages/_distutils_hack/__init__.py
ADDED
@@ -0,0 +1,222 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# don't import any costly modules
|
2 |
+
import sys
|
3 |
+
import os
|
4 |
+
|
5 |
+
|
6 |
+
is_pypy = '__pypy__' in sys.builtin_module_names
|
7 |
+
|
8 |
+
|
9 |
+
def warn_distutils_present():
|
10 |
+
if 'distutils' not in sys.modules:
|
11 |
+
return
|
12 |
+
if is_pypy and sys.version_info < (3, 7):
|
13 |
+
# PyPy for 3.6 unconditionally imports distutils, so bypass the warning
|
14 |
+
# https://foss.heptapod.net/pypy/pypy/-/blob/be829135bc0d758997b3566062999ee8b23872b4/lib-python/3/site.py#L250
|
15 |
+
return
|
16 |
+
import warnings
|
17 |
+
|
18 |
+
warnings.warn(
|
19 |
+
"Distutils was imported before Setuptools, but importing Setuptools "
|
20 |
+
"also replaces the `distutils` module in `sys.modules`. This may lead "
|
21 |
+
"to undesirable behaviors or errors. To avoid these issues, avoid "
|
22 |
+
"using distutils directly, ensure that setuptools is installed in the "
|
23 |
+
"traditional way (e.g. not an editable install), and/or make sure "
|
24 |
+
"that setuptools is always imported before distutils."
|
25 |
+
)
|
26 |
+
|
27 |
+
|
28 |
+
def clear_distutils():
|
29 |
+
if 'distutils' not in sys.modules:
|
30 |
+
return
|
31 |
+
import warnings
|
32 |
+
|
33 |
+
warnings.warn("Setuptools is replacing distutils.")
|
34 |
+
mods = [
|
35 |
+
name
|
36 |
+
for name in sys.modules
|
37 |
+
if name == "distutils" or name.startswith("distutils.")
|
38 |
+
]
|
39 |
+
for name in mods:
|
40 |
+
del sys.modules[name]
|
41 |
+
|
42 |
+
|
43 |
+
def enabled():
|
44 |
+
"""
|
45 |
+
Allow selection of distutils by environment variable.
|
46 |
+
"""
|
47 |
+
which = os.environ.get('SETUPTOOLS_USE_DISTUTILS', 'local')
|
48 |
+
return which == 'local'
|
49 |
+
|
50 |
+
|
51 |
+
def ensure_local_distutils():
|
52 |
+
import importlib
|
53 |
+
|
54 |
+
clear_distutils()
|
55 |
+
|
56 |
+
# With the DistutilsMetaFinder in place,
|
57 |
+
# perform an import to cause distutils to be
|
58 |
+
# loaded from setuptools._distutils. Ref #2906.
|
59 |
+
with shim():
|
60 |
+
importlib.import_module('distutils')
|
61 |
+
|
62 |
+
# check that submodules load as expected
|
63 |
+
core = importlib.import_module('distutils.core')
|
64 |
+
assert '_distutils' in core.__file__, core.__file__
|
65 |
+
assert 'setuptools._distutils.log' not in sys.modules
|
66 |
+
|
67 |
+
|
68 |
+
def do_override():
|
69 |
+
"""
|
70 |
+
Ensure that the local copy of distutils is preferred over stdlib.
|
71 |
+
|
72 |
+
See https://github.com/pypa/setuptools/issues/417#issuecomment-392298401
|
73 |
+
for more motivation.
|
74 |
+
"""
|
75 |
+
if enabled():
|
76 |
+
warn_distutils_present()
|
77 |
+
ensure_local_distutils()
|
78 |
+
|
79 |
+
|
80 |
+
class _TrivialRe:
|
81 |
+
def __init__(self, *patterns):
|
82 |
+
self._patterns = patterns
|
83 |
+
|
84 |
+
def match(self, string):
|
85 |
+
return all(pat in string for pat in self._patterns)
|
86 |
+
|
87 |
+
|
88 |
+
class DistutilsMetaFinder:
|
89 |
+
def find_spec(self, fullname, path, target=None):
|
90 |
+
# optimization: only consider top level modules and those
|
91 |
+
# found in the CPython test suite.
|
92 |
+
if path is not None and not fullname.startswith('test.'):
|
93 |
+
return
|
94 |
+
|
95 |
+
method_name = 'spec_for_{fullname}'.format(**locals())
|
96 |
+
method = getattr(self, method_name, lambda: None)
|
97 |
+
return method()
|
98 |
+
|
99 |
+
def spec_for_distutils(self):
|
100 |
+
if self.is_cpython():
|
101 |
+
return
|
102 |
+
|
103 |
+
import importlib
|
104 |
+
import importlib.abc
|
105 |
+
import importlib.util
|
106 |
+
|
107 |
+
try:
|
108 |
+
mod = importlib.import_module('setuptools._distutils')
|
109 |
+
except Exception:
|
110 |
+
# There are a couple of cases where setuptools._distutils
|
111 |
+
# may not be present:
|
112 |
+
# - An older Setuptools without a local distutils is
|
113 |
+
# taking precedence. Ref #2957.
|
114 |
+
# - Path manipulation during sitecustomize removes
|
115 |
+
# setuptools from the path but only after the hook
|
116 |
+
# has been loaded. Ref #2980.
|
117 |
+
# In either case, fall back to stdlib behavior.
|
118 |
+
return
|
119 |
+
|
120 |
+
class DistutilsLoader(importlib.abc.Loader):
|
121 |
+
def create_module(self, spec):
|
122 |
+
mod.__name__ = 'distutils'
|
123 |
+
return mod
|
124 |
+
|
125 |
+
def exec_module(self, module):
|
126 |
+
pass
|
127 |
+
|
128 |
+
return importlib.util.spec_from_loader(
|
129 |
+
'distutils', DistutilsLoader(), origin=mod.__file__
|
130 |
+
)
|
131 |
+
|
132 |
+
@staticmethod
|
133 |
+
def is_cpython():
|
134 |
+
"""
|
135 |
+
Suppress supplying distutils for CPython (build and tests).
|
136 |
+
Ref #2965 and #3007.
|
137 |
+
"""
|
138 |
+
return os.path.isfile('pybuilddir.txt')
|
139 |
+
|
140 |
+
def spec_for_pip(self):
|
141 |
+
"""
|
142 |
+
Ensure stdlib distutils when running under pip.
|
143 |
+
See pypa/pip#8761 for rationale.
|
144 |
+
"""
|
145 |
+
if self.pip_imported_during_build():
|
146 |
+
return
|
147 |
+
clear_distutils()
|
148 |
+
self.spec_for_distutils = lambda: None
|
149 |
+
|
150 |
+
@classmethod
|
151 |
+
def pip_imported_during_build(cls):
|
152 |
+
"""
|
153 |
+
Detect if pip is being imported in a build script. Ref #2355.
|
154 |
+
"""
|
155 |
+
import traceback
|
156 |
+
|
157 |
+
return any(
|
158 |
+
cls.frame_file_is_setup(frame) for frame, line in traceback.walk_stack(None)
|
159 |
+
)
|
160 |
+
|
161 |
+
@staticmethod
|
162 |
+
def frame_file_is_setup(frame):
|
163 |
+
"""
|
164 |
+
Return True if the indicated frame suggests a setup.py file.
|
165 |
+
"""
|
166 |
+
# some frames may not have __file__ (#2940)
|
167 |
+
return frame.f_globals.get('__file__', '').endswith('setup.py')
|
168 |
+
|
169 |
+
def spec_for_sensitive_tests(self):
|
170 |
+
"""
|
171 |
+
Ensure stdlib distutils when running select tests under CPython.
|
172 |
+
|
173 |
+
python/cpython#91169
|
174 |
+
"""
|
175 |
+
clear_distutils()
|
176 |
+
self.spec_for_distutils = lambda: None
|
177 |
+
|
178 |
+
sensitive_tests = (
|
179 |
+
[
|
180 |
+
'test.test_distutils',
|
181 |
+
'test.test_peg_generator',
|
182 |
+
'test.test_importlib',
|
183 |
+
]
|
184 |
+
if sys.version_info < (3, 10)
|
185 |
+
else [
|
186 |
+
'test.test_distutils',
|
187 |
+
]
|
188 |
+
)
|
189 |
+
|
190 |
+
|
191 |
+
for name in DistutilsMetaFinder.sensitive_tests:
|
192 |
+
setattr(
|
193 |
+
DistutilsMetaFinder,
|
194 |
+
f'spec_for_{name}',
|
195 |
+
DistutilsMetaFinder.spec_for_sensitive_tests,
|
196 |
+
)
|
197 |
+
|
198 |
+
|
199 |
+
DISTUTILS_FINDER = DistutilsMetaFinder()
|
200 |
+
|
201 |
+
|
202 |
+
def add_shim():
|
203 |
+
DISTUTILS_FINDER in sys.meta_path or insert_shim()
|
204 |
+
|
205 |
+
|
206 |
+
class shim:
|
207 |
+
def __enter__(self):
|
208 |
+
insert_shim()
|
209 |
+
|
210 |
+
def __exit__(self, exc, value, tb):
|
211 |
+
remove_shim()
|
212 |
+
|
213 |
+
|
214 |
+
def insert_shim():
|
215 |
+
sys.meta_path.insert(0, DISTUTILS_FINDER)
|
216 |
+
|
217 |
+
|
218 |
+
def remove_shim():
|
219 |
+
try:
|
220 |
+
sys.meta_path.remove(DISTUTILS_FINDER)
|
221 |
+
except ValueError:
|
222 |
+
pass
|
venv/lib/python3.11/site-packages/_distutils_hack/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (11.2 kB). View file
|
|
venv/lib/python3.11/site-packages/_distutils_hack/__pycache__/override.cpython-311.pyc
ADDED
Binary file (314 Bytes). View file
|
|
venv/lib/python3.11/site-packages/_distutils_hack/override.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
__import__('_distutils_hack').do_override()
|
venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Copyright 2010 Jason Kirtland
|
2 |
+
|
3 |
+
Permission is hereby granted, free of charge, to any person obtaining a
|
4 |
+
copy of this software and associated documentation files (the
|
5 |
+
"Software"), to deal in the Software without restriction, including
|
6 |
+
without limitation the rights to use, copy, modify, merge, publish,
|
7 |
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8 |
+
permit persons to whom the Software is furnished to do so, subject to
|
9 |
+
the following conditions:
|
10 |
+
|
11 |
+
The above copyright notice and this permission notice shall be included
|
12 |
+
in all copies or substantial portions of the Software.
|
13 |
+
|
14 |
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
15 |
+
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16 |
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
17 |
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
18 |
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
19 |
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
20 |
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/METADATA
ADDED
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.3
|
2 |
+
Name: blinker
|
3 |
+
Version: 1.9.0
|
4 |
+
Summary: Fast, simple object-to-object and broadcast signaling
|
5 |
+
Author: Jason Kirtland
|
6 |
+
Maintainer-email: Pallets Ecosystem <[email protected]>
|
7 |
+
Requires-Python: >=3.9
|
8 |
+
Description-Content-Type: text/markdown
|
9 |
+
Classifier: Development Status :: 5 - Production/Stable
|
10 |
+
Classifier: License :: OSI Approved :: MIT License
|
11 |
+
Classifier: Programming Language :: Python
|
12 |
+
Classifier: Typing :: Typed
|
13 |
+
Project-URL: Chat, https://discord.gg/pallets
|
14 |
+
Project-URL: Documentation, https://blinker.readthedocs.io
|
15 |
+
Project-URL: Source, https://github.com/pallets-eco/blinker/
|
16 |
+
|
17 |
+
# Blinker
|
18 |
+
|
19 |
+
Blinker provides a fast dispatching system that allows any number of
|
20 |
+
interested parties to subscribe to events, or "signals".
|
21 |
+
|
22 |
+
|
23 |
+
## Pallets Community Ecosystem
|
24 |
+
|
25 |
+
> [!IMPORTANT]\
|
26 |
+
> This project is part of the Pallets Community Ecosystem. Pallets is the open
|
27 |
+
> source organization that maintains Flask; Pallets-Eco enables community
|
28 |
+
> maintenance of related projects. If you are interested in helping maintain
|
29 |
+
> this project, please reach out on [the Pallets Discord server][discord].
|
30 |
+
>
|
31 |
+
> [discord]: https://discord.gg/pallets
|
32 |
+
|
33 |
+
|
34 |
+
## Example
|
35 |
+
|
36 |
+
Signal receivers can subscribe to specific senders or receive signals
|
37 |
+
sent by any sender.
|
38 |
+
|
39 |
+
```pycon
|
40 |
+
>>> from blinker import signal
|
41 |
+
>>> started = signal('round-started')
|
42 |
+
>>> def each(round):
|
43 |
+
... print(f"Round {round}")
|
44 |
+
...
|
45 |
+
>>> started.connect(each)
|
46 |
+
|
47 |
+
>>> def round_two(round):
|
48 |
+
... print("This is round two.")
|
49 |
+
...
|
50 |
+
>>> started.connect(round_two, sender=2)
|
51 |
+
|
52 |
+
>>> for round in range(1, 4):
|
53 |
+
... started.send(round)
|
54 |
+
...
|
55 |
+
Round 1!
|
56 |
+
Round 2!
|
57 |
+
This is round two.
|
58 |
+
Round 3!
|
59 |
+
```
|
60 |
+
|
venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/RECORD
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
blinker-1.9.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
2 |
+
blinker-1.9.0.dist-info/LICENSE.txt,sha256=nrc6HzhZekqhcCXSrhvjg5Ykx5XphdTw6Xac4p-spGc,1054
|
3 |
+
blinker-1.9.0.dist-info/METADATA,sha256=uIRiM8wjjbHkCtbCyTvctU37IAZk0kEe5kxAld1dvzA,1633
|
4 |
+
blinker-1.9.0.dist-info/RECORD,,
|
5 |
+
blinker-1.9.0.dist-info/WHEEL,sha256=CpUCUxeHQbRN5UGRQHYRJorO5Af-Qy_fHMctcQ8DSGI,82
|
6 |
+
blinker/__init__.py,sha256=I2EdZqpy4LyjX17Hn1yzJGWCjeLaVaPzsMgHkLfj_cQ,317
|
7 |
+
blinker/__pycache__/__init__.cpython-311.pyc,,
|
8 |
+
blinker/__pycache__/_utilities.cpython-311.pyc,,
|
9 |
+
blinker/__pycache__/base.cpython-311.pyc,,
|
10 |
+
blinker/_utilities.py,sha256=0J7eeXXTUx0Ivf8asfpx0ycVkp0Eqfqnj117x2mYX9E,1675
|
11 |
+
blinker/base.py,sha256=QpDuvXXcwJF49lUBcH5BiST46Rz9wSG7VW_p7N_027M,19132
|
12 |
+
blinker/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
venv/lib/python3.11/site-packages/blinker-1.9.0.dist-info/WHEEL
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: flit 3.10.1
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
venv/lib/python3.11/site-packages/blinker/__init__.py
ADDED
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
|
3 |
+
from .base import ANY
|
4 |
+
from .base import default_namespace
|
5 |
+
from .base import NamedSignal
|
6 |
+
from .base import Namespace
|
7 |
+
from .base import Signal
|
8 |
+
from .base import signal
|
9 |
+
|
10 |
+
__all__ = [
|
11 |
+
"ANY",
|
12 |
+
"default_namespace",
|
13 |
+
"NamedSignal",
|
14 |
+
"Namespace",
|
15 |
+
"Signal",
|
16 |
+
"signal",
|
17 |
+
]
|
venv/lib/python3.11/site-packages/blinker/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (605 Bytes). View file
|
|
venv/lib/python3.11/site-packages/blinker/__pycache__/_utilities.cpython-311.pyc
ADDED
Binary file (3.09 kB). View file
|
|
venv/lib/python3.11/site-packages/blinker/__pycache__/base.cpython-311.pyc
ADDED
Binary file (23.6 kB). View file
|
|
venv/lib/python3.11/site-packages/blinker/_utilities.py
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
|
3 |
+
import collections.abc as c
|
4 |
+
import inspect
|
5 |
+
import typing as t
|
6 |
+
from weakref import ref
|
7 |
+
from weakref import WeakMethod
|
8 |
+
|
9 |
+
T = t.TypeVar("T")
|
10 |
+
|
11 |
+
|
12 |
+
class Symbol:
|
13 |
+
"""A constant symbol, nicer than ``object()``. Repeated calls return the
|
14 |
+
same instance.
|
15 |
+
|
16 |
+
>>> Symbol('foo') is Symbol('foo')
|
17 |
+
True
|
18 |
+
>>> Symbol('foo')
|
19 |
+
foo
|
20 |
+
"""
|
21 |
+
|
22 |
+
symbols: t.ClassVar[dict[str, Symbol]] = {}
|
23 |
+
|
24 |
+
def __new__(cls, name: str) -> Symbol:
|
25 |
+
if name in cls.symbols:
|
26 |
+
return cls.symbols[name]
|
27 |
+
|
28 |
+
obj = super().__new__(cls)
|
29 |
+
cls.symbols[name] = obj
|
30 |
+
return obj
|
31 |
+
|
32 |
+
def __init__(self, name: str) -> None:
|
33 |
+
self.name = name
|
34 |
+
|
35 |
+
def __repr__(self) -> str:
|
36 |
+
return self.name
|
37 |
+
|
38 |
+
def __getnewargs__(self) -> tuple[t.Any, ...]:
|
39 |
+
return (self.name,)
|
40 |
+
|
41 |
+
|
42 |
+
def make_id(obj: object) -> c.Hashable:
|
43 |
+
"""Get a stable identifier for a receiver or sender, to be used as a dict
|
44 |
+
key or in a set.
|
45 |
+
"""
|
46 |
+
if inspect.ismethod(obj):
|
47 |
+
# The id of a bound method is not stable, but the id of the unbound
|
48 |
+
# function and instance are.
|
49 |
+
return id(obj.__func__), id(obj.__self__)
|
50 |
+
|
51 |
+
if isinstance(obj, (str, int)):
|
52 |
+
# Instances with the same value always compare equal and have the same
|
53 |
+
# hash, even if the id may change.
|
54 |
+
return obj
|
55 |
+
|
56 |
+
# Assume other types are not hashable but will always be the same instance.
|
57 |
+
return id(obj)
|
58 |
+
|
59 |
+
|
60 |
+
def make_ref(obj: T, callback: c.Callable[[ref[T]], None] | None = None) -> ref[T]:
|
61 |
+
if inspect.ismethod(obj):
|
62 |
+
return WeakMethod(obj, callback) # type: ignore[arg-type, return-value]
|
63 |
+
|
64 |
+
return ref(obj, callback)
|
venv/lib/python3.11/site-packages/blinker/base.py
ADDED
@@ -0,0 +1,512 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from __future__ import annotations
|
2 |
+
|
3 |
+
import collections.abc as c
|
4 |
+
import sys
|
5 |
+
import typing as t
|
6 |
+
import weakref
|
7 |
+
from collections import defaultdict
|
8 |
+
from contextlib import contextmanager
|
9 |
+
from functools import cached_property
|
10 |
+
from inspect import iscoroutinefunction
|
11 |
+
|
12 |
+
from ._utilities import make_id
|
13 |
+
from ._utilities import make_ref
|
14 |
+
from ._utilities import Symbol
|
15 |
+
|
16 |
+
F = t.TypeVar("F", bound=c.Callable[..., t.Any])
|
17 |
+
|
18 |
+
ANY = Symbol("ANY")
|
19 |
+
"""Symbol for "any sender"."""
|
20 |
+
|
21 |
+
ANY_ID = 0
|
22 |
+
|
23 |
+
|
24 |
+
class Signal:
|
25 |
+
"""A notification emitter.
|
26 |
+
|
27 |
+
:param doc: The docstring for the signal.
|
28 |
+
"""
|
29 |
+
|
30 |
+
ANY = ANY
|
31 |
+
"""An alias for the :data:`~blinker.ANY` sender symbol."""
|
32 |
+
|
33 |
+
set_class: type[set[t.Any]] = set
|
34 |
+
"""The set class to use for tracking connected receivers and senders.
|
35 |
+
Python's ``set`` is unordered. If receivers must be dispatched in the order
|
36 |
+
they were connected, an ordered set implementation can be used.
|
37 |
+
|
38 |
+
.. versionadded:: 1.7
|
39 |
+
"""
|
40 |
+
|
41 |
+
@cached_property
|
42 |
+
def receiver_connected(self) -> Signal:
|
43 |
+
"""Emitted at the end of each :meth:`connect` call.
|
44 |
+
|
45 |
+
The signal sender is the signal instance, and the :meth:`connect`
|
46 |
+
arguments are passed through: ``receiver``, ``sender``, and ``weak``.
|
47 |
+
|
48 |
+
.. versionadded:: 1.2
|
49 |
+
"""
|
50 |
+
return Signal(doc="Emitted after a receiver connects.")
|
51 |
+
|
52 |
+
@cached_property
|
53 |
+
def receiver_disconnected(self) -> Signal:
|
54 |
+
"""Emitted at the end of each :meth:`disconnect` call.
|
55 |
+
|
56 |
+
The sender is the signal instance, and the :meth:`disconnect` arguments
|
57 |
+
are passed through: ``receiver`` and ``sender``.
|
58 |
+
|
59 |
+
This signal is emitted **only** when :meth:`disconnect` is called
|
60 |
+
explicitly. This signal cannot be emitted by an automatic disconnect
|
61 |
+
when a weakly referenced receiver or sender goes out of scope, as the
|
62 |
+
instance is no longer be available to be used as the sender for this
|
63 |
+
signal.
|
64 |
+
|
65 |
+
An alternative approach is available by subscribing to
|
66 |
+
:attr:`receiver_connected` and setting up a custom weakref cleanup
|
67 |
+
callback on weak receivers and senders.
|
68 |
+
|
69 |
+
.. versionadded:: 1.2
|
70 |
+
"""
|
71 |
+
return Signal(doc="Emitted after a receiver disconnects.")
|
72 |
+
|
73 |
+
def __init__(self, doc: str | None = None) -> None:
|
74 |
+
if doc:
|
75 |
+
self.__doc__ = doc
|
76 |
+
|
77 |
+
self.receivers: dict[
|
78 |
+
t.Any, weakref.ref[c.Callable[..., t.Any]] | c.Callable[..., t.Any]
|
79 |
+
] = {}
|
80 |
+
"""The map of connected receivers. Useful to quickly check if any
|
81 |
+
receivers are connected to the signal: ``if s.receivers:``. The
|
82 |
+
structure and data is not part of the public API, but checking its
|
83 |
+
boolean value is.
|
84 |
+
"""
|
85 |
+
|
86 |
+
self.is_muted: bool = False
|
87 |
+
self._by_receiver: dict[t.Any, set[t.Any]] = defaultdict(self.set_class)
|
88 |
+
self._by_sender: dict[t.Any, set[t.Any]] = defaultdict(self.set_class)
|
89 |
+
self._weak_senders: dict[t.Any, weakref.ref[t.Any]] = {}
|
90 |
+
|
91 |
+
def connect(self, receiver: F, sender: t.Any = ANY, weak: bool = True) -> F:
|
92 |
+
"""Connect ``receiver`` to be called when the signal is sent by
|
93 |
+
``sender``.
|
94 |
+
|
95 |
+
:param receiver: The callable to call when :meth:`send` is called with
|
96 |
+
the given ``sender``, passing ``sender`` as a positional argument
|
97 |
+
along with any extra keyword arguments.
|
98 |
+
:param sender: Any object or :data:`ANY`. ``receiver`` will only be
|
99 |
+
called when :meth:`send` is called with this sender. If ``ANY``, the
|
100 |
+
receiver will be called for any sender. A receiver may be connected
|
101 |
+
to multiple senders by calling :meth:`connect` multiple times.
|
102 |
+
:param weak: Track the receiver with a :mod:`weakref`. The receiver will
|
103 |
+
be automatically disconnected when it is garbage collected. When
|
104 |
+
connecting a receiver defined within a function, set to ``False``,
|
105 |
+
otherwise it will be disconnected when the function scope ends.
|
106 |
+
"""
|
107 |
+
receiver_id = make_id(receiver)
|
108 |
+
sender_id = ANY_ID if sender is ANY else make_id(sender)
|
109 |
+
|
110 |
+
if weak:
|
111 |
+
self.receivers[receiver_id] = make_ref(
|
112 |
+
receiver, self._make_cleanup_receiver(receiver_id)
|
113 |
+
)
|
114 |
+
else:
|
115 |
+
self.receivers[receiver_id] = receiver
|
116 |
+
|
117 |
+
self._by_sender[sender_id].add(receiver_id)
|
118 |
+
self._by_receiver[receiver_id].add(sender_id)
|
119 |
+
|
120 |
+
if sender is not ANY and sender_id not in self._weak_senders:
|
121 |
+
# store a cleanup for weakref-able senders
|
122 |
+
try:
|
123 |
+
self._weak_senders[sender_id] = make_ref(
|
124 |
+
sender, self._make_cleanup_sender(sender_id)
|
125 |
+
)
|
126 |
+
except TypeError:
|
127 |
+
pass
|
128 |
+
|
129 |
+
if "receiver_connected" in self.__dict__ and self.receiver_connected.receivers:
|
130 |
+
try:
|
131 |
+
self.receiver_connected.send(
|
132 |
+
self, receiver=receiver, sender=sender, weak=weak
|
133 |
+
)
|
134 |
+
except TypeError:
|
135 |
+
# TODO no explanation or test for this
|
136 |
+
self.disconnect(receiver, sender)
|
137 |
+
raise
|
138 |
+
|
139 |
+
return receiver
|
140 |
+
|
141 |
+
def connect_via(self, sender: t.Any, weak: bool = False) -> c.Callable[[F], F]:
|
142 |
+
"""Connect the decorated function to be called when the signal is sent
|
143 |
+
by ``sender``.
|
144 |
+
|
145 |
+
The decorated function will be called when :meth:`send` is called with
|
146 |
+
the given ``sender``, passing ``sender`` as a positional argument along
|
147 |
+
with any extra keyword arguments.
|
148 |
+
|
149 |
+
:param sender: Any object or :data:`ANY`. ``receiver`` will only be
|
150 |
+
called when :meth:`send` is called with this sender. If ``ANY``, the
|
151 |
+
receiver will be called for any sender. A receiver may be connected
|
152 |
+
to multiple senders by calling :meth:`connect` multiple times.
|
153 |
+
:param weak: Track the receiver with a :mod:`weakref`. The receiver will
|
154 |
+
be automatically disconnected when it is garbage collected. When
|
155 |
+
connecting a receiver defined within a function, set to ``False``,
|
156 |
+
otherwise it will be disconnected when the function scope ends.=
|
157 |
+
|
158 |
+
.. versionadded:: 1.1
|
159 |
+
"""
|
160 |
+
|
161 |
+
def decorator(fn: F) -> F:
|
162 |
+
self.connect(fn, sender, weak)
|
163 |
+
return fn
|
164 |
+
|
165 |
+
return decorator
|
166 |
+
|
167 |
+
@contextmanager
|
168 |
+
def connected_to(
|
169 |
+
self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY
|
170 |
+
) -> c.Generator[None, None, None]:
|
171 |
+
"""A context manager that temporarily connects ``receiver`` to the
|
172 |
+
signal while a ``with`` block executes. When the block exits, the
|
173 |
+
receiver is disconnected. Useful for tests.
|
174 |
+
|
175 |
+
:param receiver: The callable to call when :meth:`send` is called with
|
176 |
+
the given ``sender``, passing ``sender`` as a positional argument
|
177 |
+
along with any extra keyword arguments.
|
178 |
+
:param sender: Any object or :data:`ANY`. ``receiver`` will only be
|
179 |
+
called when :meth:`send` is called with this sender. If ``ANY``, the
|
180 |
+
receiver will be called for any sender.
|
181 |
+
|
182 |
+
.. versionadded:: 1.1
|
183 |
+
"""
|
184 |
+
self.connect(receiver, sender=sender, weak=False)
|
185 |
+
|
186 |
+
try:
|
187 |
+
yield None
|
188 |
+
finally:
|
189 |
+
self.disconnect(receiver)
|
190 |
+
|
191 |
+
@contextmanager
|
192 |
+
def muted(self) -> c.Generator[None, None, None]:
|
193 |
+
"""A context manager that temporarily disables the signal. No receivers
|
194 |
+
will be called if the signal is sent, until the ``with`` block exits.
|
195 |
+
Useful for tests.
|
196 |
+
"""
|
197 |
+
self.is_muted = True
|
198 |
+
|
199 |
+
try:
|
200 |
+
yield None
|
201 |
+
finally:
|
202 |
+
self.is_muted = False
|
203 |
+
|
204 |
+
def send(
|
205 |
+
self,
|
206 |
+
sender: t.Any | None = None,
|
207 |
+
/,
|
208 |
+
*,
|
209 |
+
_async_wrapper: c.Callable[
|
210 |
+
[c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]], c.Callable[..., t.Any]
|
211 |
+
]
|
212 |
+
| None = None,
|
213 |
+
**kwargs: t.Any,
|
214 |
+
) -> list[tuple[c.Callable[..., t.Any], t.Any]]:
|
215 |
+
"""Call all receivers that are connected to the given ``sender``
|
216 |
+
or :data:`ANY`. Each receiver is called with ``sender`` as a positional
|
217 |
+
argument along with any extra keyword arguments. Return a list of
|
218 |
+
``(receiver, return value)`` tuples.
|
219 |
+
|
220 |
+
The order receivers are called is undefined, but can be influenced by
|
221 |
+
setting :attr:`set_class`.
|
222 |
+
|
223 |
+
If a receiver raises an exception, that exception will propagate up.
|
224 |
+
This makes debugging straightforward, with an assumption that correctly
|
225 |
+
implemented receivers will not raise.
|
226 |
+
|
227 |
+
:param sender: Call receivers connected to this sender, in addition to
|
228 |
+
those connected to :data:`ANY`.
|
229 |
+
:param _async_wrapper: Will be called on any receivers that are async
|
230 |
+
coroutines to turn them into sync callables. For example, could run
|
231 |
+
the receiver with an event loop.
|
232 |
+
:param kwargs: Extra keyword arguments to pass to each receiver.
|
233 |
+
|
234 |
+
.. versionchanged:: 1.7
|
235 |
+
Added the ``_async_wrapper`` argument.
|
236 |
+
"""
|
237 |
+
if self.is_muted:
|
238 |
+
return []
|
239 |
+
|
240 |
+
results = []
|
241 |
+
|
242 |
+
for receiver in self.receivers_for(sender):
|
243 |
+
if iscoroutinefunction(receiver):
|
244 |
+
if _async_wrapper is None:
|
245 |
+
raise RuntimeError("Cannot send to a coroutine function.")
|
246 |
+
|
247 |
+
result = _async_wrapper(receiver)(sender, **kwargs)
|
248 |
+
else:
|
249 |
+
result = receiver(sender, **kwargs)
|
250 |
+
|
251 |
+
results.append((receiver, result))
|
252 |
+
|
253 |
+
return results
|
254 |
+
|
255 |
+
async def send_async(
|
256 |
+
self,
|
257 |
+
sender: t.Any | None = None,
|
258 |
+
/,
|
259 |
+
*,
|
260 |
+
_sync_wrapper: c.Callable[
|
261 |
+
[c.Callable[..., t.Any]], c.Callable[..., c.Coroutine[t.Any, t.Any, t.Any]]
|
262 |
+
]
|
263 |
+
| None = None,
|
264 |
+
**kwargs: t.Any,
|
265 |
+
) -> list[tuple[c.Callable[..., t.Any], t.Any]]:
|
266 |
+
"""Await all receivers that are connected to the given ``sender``
|
267 |
+
or :data:`ANY`. Each receiver is called with ``sender`` as a positional
|
268 |
+
argument along with any extra keyword arguments. Return a list of
|
269 |
+
``(receiver, return value)`` tuples.
|
270 |
+
|
271 |
+
The order receivers are called is undefined, but can be influenced by
|
272 |
+
setting :attr:`set_class`.
|
273 |
+
|
274 |
+
If a receiver raises an exception, that exception will propagate up.
|
275 |
+
This makes debugging straightforward, with an assumption that correctly
|
276 |
+
implemented receivers will not raise.
|
277 |
+
|
278 |
+
:param sender: Call receivers connected to this sender, in addition to
|
279 |
+
those connected to :data:`ANY`.
|
280 |
+
:param _sync_wrapper: Will be called on any receivers that are sync
|
281 |
+
callables to turn them into async coroutines. For example,
|
282 |
+
could call the receiver in a thread.
|
283 |
+
:param kwargs: Extra keyword arguments to pass to each receiver.
|
284 |
+
|
285 |
+
.. versionadded:: 1.7
|
286 |
+
"""
|
287 |
+
if self.is_muted:
|
288 |
+
return []
|
289 |
+
|
290 |
+
results = []
|
291 |
+
|
292 |
+
for receiver in self.receivers_for(sender):
|
293 |
+
if not iscoroutinefunction(receiver):
|
294 |
+
if _sync_wrapper is None:
|
295 |
+
raise RuntimeError("Cannot send to a non-coroutine function.")
|
296 |
+
|
297 |
+
result = await _sync_wrapper(receiver)(sender, **kwargs)
|
298 |
+
else:
|
299 |
+
result = await receiver(sender, **kwargs)
|
300 |
+
|
301 |
+
results.append((receiver, result))
|
302 |
+
|
303 |
+
return results
|
304 |
+
|
305 |
+
def has_receivers_for(self, sender: t.Any) -> bool:
|
306 |
+
"""Check if there is at least one receiver that will be called with the
|
307 |
+
given ``sender``. A receiver connected to :data:`ANY` will always be
|
308 |
+
called, regardless of sender. Does not check if weakly referenced
|
309 |
+
receivers are still live. See :meth:`receivers_for` for a stronger
|
310 |
+
search.
|
311 |
+
|
312 |
+
:param sender: Check for receivers connected to this sender, in addition
|
313 |
+
to those connected to :data:`ANY`.
|
314 |
+
"""
|
315 |
+
if not self.receivers:
|
316 |
+
return False
|
317 |
+
|
318 |
+
if self._by_sender[ANY_ID]:
|
319 |
+
return True
|
320 |
+
|
321 |
+
if sender is ANY:
|
322 |
+
return False
|
323 |
+
|
324 |
+
return make_id(sender) in self._by_sender
|
325 |
+
|
326 |
+
def receivers_for(
|
327 |
+
self, sender: t.Any
|
328 |
+
) -> c.Generator[c.Callable[..., t.Any], None, None]:
|
329 |
+
"""Yield each receiver to be called for ``sender``, in addition to those
|
330 |
+
to be called for :data:`ANY`. Weakly referenced receivers that are not
|
331 |
+
live will be disconnected and skipped.
|
332 |
+
|
333 |
+
:param sender: Yield receivers connected to this sender, in addition
|
334 |
+
to those connected to :data:`ANY`.
|
335 |
+
"""
|
336 |
+
# TODO: test receivers_for(ANY)
|
337 |
+
if not self.receivers:
|
338 |
+
return
|
339 |
+
|
340 |
+
sender_id = make_id(sender)
|
341 |
+
|
342 |
+
if sender_id in self._by_sender:
|
343 |
+
ids = self._by_sender[ANY_ID] | self._by_sender[sender_id]
|
344 |
+
else:
|
345 |
+
ids = self._by_sender[ANY_ID].copy()
|
346 |
+
|
347 |
+
for receiver_id in ids:
|
348 |
+
receiver = self.receivers.get(receiver_id)
|
349 |
+
|
350 |
+
if receiver is None:
|
351 |
+
continue
|
352 |
+
|
353 |
+
if isinstance(receiver, weakref.ref):
|
354 |
+
strong = receiver()
|
355 |
+
|
356 |
+
if strong is None:
|
357 |
+
self._disconnect(receiver_id, ANY_ID)
|
358 |
+
continue
|
359 |
+
|
360 |
+
yield strong
|
361 |
+
else:
|
362 |
+
yield receiver
|
363 |
+
|
364 |
+
def disconnect(self, receiver: c.Callable[..., t.Any], sender: t.Any = ANY) -> None:
|
365 |
+
"""Disconnect ``receiver`` from being called when the signal is sent by
|
366 |
+
``sender``.
|
367 |
+
|
368 |
+
:param receiver: A connected receiver callable.
|
369 |
+
:param sender: Disconnect from only this sender. By default, disconnect
|
370 |
+
from all senders.
|
371 |
+
"""
|
372 |
+
sender_id: c.Hashable
|
373 |
+
|
374 |
+
if sender is ANY:
|
375 |
+
sender_id = ANY_ID
|
376 |
+
else:
|
377 |
+
sender_id = make_id(sender)
|
378 |
+
|
379 |
+
receiver_id = make_id(receiver)
|
380 |
+
self._disconnect(receiver_id, sender_id)
|
381 |
+
|
382 |
+
if (
|
383 |
+
"receiver_disconnected" in self.__dict__
|
384 |
+
and self.receiver_disconnected.receivers
|
385 |
+
):
|
386 |
+
self.receiver_disconnected.send(self, receiver=receiver, sender=sender)
|
387 |
+
|
388 |
+
def _disconnect(self, receiver_id: c.Hashable, sender_id: c.Hashable) -> None:
|
389 |
+
if sender_id == ANY_ID:
|
390 |
+
if self._by_receiver.pop(receiver_id, None) is not None:
|
391 |
+
for bucket in self._by_sender.values():
|
392 |
+
bucket.discard(receiver_id)
|
393 |
+
|
394 |
+
self.receivers.pop(receiver_id, None)
|
395 |
+
else:
|
396 |
+
self._by_sender[sender_id].discard(receiver_id)
|
397 |
+
self._by_receiver[receiver_id].discard(sender_id)
|
398 |
+
|
399 |
+
def _make_cleanup_receiver(
|
400 |
+
self, receiver_id: c.Hashable
|
401 |
+
) -> c.Callable[[weakref.ref[c.Callable[..., t.Any]]], None]:
|
402 |
+
"""Create a callback function to disconnect a weakly referenced
|
403 |
+
receiver when it is garbage collected.
|
404 |
+
"""
|
405 |
+
|
406 |
+
def cleanup(ref: weakref.ref[c.Callable[..., t.Any]]) -> None:
|
407 |
+
# If the interpreter is shutting down, disconnecting can result in a
|
408 |
+
# weird ignored exception. Don't call it in that case.
|
409 |
+
if not sys.is_finalizing():
|
410 |
+
self._disconnect(receiver_id, ANY_ID)
|
411 |
+
|
412 |
+
return cleanup
|
413 |
+
|
414 |
+
def _make_cleanup_sender(
|
415 |
+
self, sender_id: c.Hashable
|
416 |
+
) -> c.Callable[[weakref.ref[t.Any]], None]:
|
417 |
+
"""Create a callback function to disconnect all receivers for a weakly
|
418 |
+
referenced sender when it is garbage collected.
|
419 |
+
"""
|
420 |
+
assert sender_id != ANY_ID
|
421 |
+
|
422 |
+
def cleanup(ref: weakref.ref[t.Any]) -> None:
|
423 |
+
self._weak_senders.pop(sender_id, None)
|
424 |
+
|
425 |
+
for receiver_id in self._by_sender.pop(sender_id, ()):
|
426 |
+
self._by_receiver[receiver_id].discard(sender_id)
|
427 |
+
|
428 |
+
return cleanup
|
429 |
+
|
430 |
+
def _cleanup_bookkeeping(self) -> None:
|
431 |
+
"""Prune unused sender/receiver bookkeeping. Not threadsafe.
|
432 |
+
|
433 |
+
Connecting & disconnecting leaves behind a small amount of bookkeeping
|
434 |
+
data. Typical workloads using Blinker, for example in most web apps,
|
435 |
+
Flask, CLI scripts, etc., are not adversely affected by this
|
436 |
+
bookkeeping.
|
437 |
+
|
438 |
+
With a long-running process performing dynamic signal routing with high
|
439 |
+
volume, e.g. connecting to function closures, senders are all unique
|
440 |
+
object instances. Doing all of this over and over may cause memory usage
|
441 |
+
to grow due to extraneous bookkeeping. (An empty ``set`` for each stale
|
442 |
+
sender/receiver pair.)
|
443 |
+
|
444 |
+
This method will prune that bookkeeping away, with the caveat that such
|
445 |
+
pruning is not threadsafe. The risk is that cleanup of a fully
|
446 |
+
disconnected receiver/sender pair occurs while another thread is
|
447 |
+
connecting that same pair. If you are in the highly dynamic, unique
|
448 |
+
receiver/sender situation that has lead you to this method, that failure
|
449 |
+
mode is perhaps not a big deal for you.
|
450 |
+
"""
|
451 |
+
for mapping in (self._by_sender, self._by_receiver):
|
452 |
+
for ident, bucket in list(mapping.items()):
|
453 |
+
if not bucket:
|
454 |
+
mapping.pop(ident, None)
|
455 |
+
|
456 |
+
def _clear_state(self) -> None:
|
457 |
+
"""Disconnect all receivers and senders. Useful for tests."""
|
458 |
+
self._weak_senders.clear()
|
459 |
+
self.receivers.clear()
|
460 |
+
self._by_sender.clear()
|
461 |
+
self._by_receiver.clear()
|
462 |
+
|
463 |
+
|
464 |
+
class NamedSignal(Signal):
|
465 |
+
"""A named generic notification emitter. The name is not used by the signal
|
466 |
+
itself, but matches the key in the :class:`Namespace` that it belongs to.
|
467 |
+
|
468 |
+
:param name: The name of the signal within the namespace.
|
469 |
+
:param doc: The docstring for the signal.
|
470 |
+
"""
|
471 |
+
|
472 |
+
def __init__(self, name: str, doc: str | None = None) -> None:
|
473 |
+
super().__init__(doc)
|
474 |
+
|
475 |
+
#: The name of this signal.
|
476 |
+
self.name: str = name
|
477 |
+
|
478 |
+
def __repr__(self) -> str:
|
479 |
+
base = super().__repr__()
|
480 |
+
return f"{base[:-1]}; {self.name!r}>" # noqa: E702
|
481 |
+
|
482 |
+
|
483 |
+
class Namespace(dict[str, NamedSignal]):
|
484 |
+
"""A dict mapping names to signals."""
|
485 |
+
|
486 |
+
def signal(self, name: str, doc: str | None = None) -> NamedSignal:
|
487 |
+
"""Return the :class:`NamedSignal` for the given ``name``, creating it
|
488 |
+
if required. Repeated calls with the same name return the same signal.
|
489 |
+
|
490 |
+
:param name: The name of the signal.
|
491 |
+
:param doc: The docstring of the signal.
|
492 |
+
"""
|
493 |
+
if name not in self:
|
494 |
+
self[name] = NamedSignal(name, doc)
|
495 |
+
|
496 |
+
return self[name]
|
497 |
+
|
498 |
+
|
499 |
+
class _PNamespaceSignal(t.Protocol):
|
500 |
+
def __call__(self, name: str, doc: str | None = None) -> NamedSignal: ...
|
501 |
+
|
502 |
+
|
503 |
+
default_namespace: Namespace = Namespace()
|
504 |
+
"""A default :class:`Namespace` for creating named signals. :func:`signal`
|
505 |
+
creates a :class:`NamedSignal` in this namespace.
|
506 |
+
"""
|
507 |
+
|
508 |
+
signal: _PNamespaceSignal = default_namespace.signal
|
509 |
+
"""Return a :class:`NamedSignal` in :data:`default_namespace` with the given
|
510 |
+
``name``, creating it if required. Repeated calls with the same name return the
|
511 |
+
same signal.
|
512 |
+
"""
|
venv/lib/python3.11/site-packages/blinker/py.typed
ADDED
File without changes
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/INSTALLER
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
pip
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
This package contains a modified version of ca-bundle.crt:
|
2 |
+
|
3 |
+
ca-bundle.crt -- Bundle of CA Root Certificates
|
4 |
+
|
5 |
+
This is a bundle of X.509 certificates of public Certificate Authorities
|
6 |
+
(CA). These were automatically extracted from Mozilla's root certificates
|
7 |
+
file (certdata.txt). This file can be found in the mozilla source tree:
|
8 |
+
https://hg.mozilla.org/mozilla-central/file/tip/security/nss/lib/ckfw/builtins/certdata.txt
|
9 |
+
It contains the certificates in PEM format and therefore
|
10 |
+
can be directly used with curl / libcurl / php_curl, or with
|
11 |
+
an Apache+mod_ssl webserver for SSL client authentication.
|
12 |
+
Just configure this file as the SSLCACertificateFile.#
|
13 |
+
|
14 |
+
***** BEGIN LICENSE BLOCK *****
|
15 |
+
This Source Code Form is subject to the terms of the Mozilla Public License,
|
16 |
+
v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain
|
17 |
+
one at http://mozilla.org/MPL/2.0/.
|
18 |
+
|
19 |
+
***** END LICENSE BLOCK *****
|
20 |
+
@(#) $RCSfile: certdata.txt,v $ $Revision: 1.80 $ $Date: 2011/11/03 15:11:58 $
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/METADATA
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Metadata-Version: 2.1
|
2 |
+
Name: certifi
|
3 |
+
Version: 2024.12.14
|
4 |
+
Summary: Python package for providing Mozilla's CA Bundle.
|
5 |
+
Home-page: https://github.com/certifi/python-certifi
|
6 |
+
Author: Kenneth Reitz
|
7 |
+
Author-email: [email protected]
|
8 |
+
License: MPL-2.0
|
9 |
+
Project-URL: Source, https://github.com/certifi/python-certifi
|
10 |
+
Classifier: Development Status :: 5 - Production/Stable
|
11 |
+
Classifier: Intended Audience :: Developers
|
12 |
+
Classifier: License :: OSI Approved :: Mozilla Public License 2.0 (MPL 2.0)
|
13 |
+
Classifier: Natural Language :: English
|
14 |
+
Classifier: Programming Language :: Python
|
15 |
+
Classifier: Programming Language :: Python :: 3
|
16 |
+
Classifier: Programming Language :: Python :: 3 :: Only
|
17 |
+
Classifier: Programming Language :: Python :: 3.6
|
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 :: 3.13
|
25 |
+
Requires-Python: >=3.6
|
26 |
+
License-File: LICENSE
|
27 |
+
|
28 |
+
Certifi: Python SSL Certificates
|
29 |
+
================================
|
30 |
+
|
31 |
+
Certifi provides Mozilla's carefully curated collection of Root Certificates for
|
32 |
+
validating the trustworthiness of SSL certificates while verifying the identity
|
33 |
+
of TLS hosts. It has been extracted from the `Requests`_ project.
|
34 |
+
|
35 |
+
Installation
|
36 |
+
------------
|
37 |
+
|
38 |
+
``certifi`` is available on PyPI. Simply install it with ``pip``::
|
39 |
+
|
40 |
+
$ pip install certifi
|
41 |
+
|
42 |
+
Usage
|
43 |
+
-----
|
44 |
+
|
45 |
+
To reference the installed certificate authority (CA) bundle, you can use the
|
46 |
+
built-in function::
|
47 |
+
|
48 |
+
>>> import certifi
|
49 |
+
|
50 |
+
>>> certifi.where()
|
51 |
+
'/usr/local/lib/python3.7/site-packages/certifi/cacert.pem'
|
52 |
+
|
53 |
+
Or from the command line::
|
54 |
+
|
55 |
+
$ python -m certifi
|
56 |
+
/usr/local/lib/python3.7/site-packages/certifi/cacert.pem
|
57 |
+
|
58 |
+
Enjoy!
|
59 |
+
|
60 |
+
.. _`Requests`: https://requests.readthedocs.io/en/master/
|
61 |
+
|
62 |
+
Addition/Removal of Certificates
|
63 |
+
--------------------------------
|
64 |
+
|
65 |
+
Certifi does not support any addition/removal or other modification of the
|
66 |
+
CA trust store content. This project is intended to provide a reliable and
|
67 |
+
highly portable root of trust to python deployments. Look to upstream projects
|
68 |
+
for methods to use alternate trust.
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/RECORD
ADDED
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
certifi-2024.12.14.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
2 |
+
certifi-2024.12.14.dist-info/LICENSE,sha256=6TcW2mucDVpKHfYP5pWzcPBpVgPSH2-D8FPkLPwQyvc,989
|
3 |
+
certifi-2024.12.14.dist-info/METADATA,sha256=z71eRGTFszr4qsHenZ_vG2Fd5bV9PBWmJgShthc8IkY,2274
|
4 |
+
certifi-2024.12.14.dist-info/RECORD,,
|
5 |
+
certifi-2024.12.14.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
6 |
+
certifi-2024.12.14.dist-info/top_level.txt,sha256=KMu4vUCfsjLrkPbSNdgdekS-pVJzBAJFO__nI8NF6-U,8
|
7 |
+
certifi/__init__.py,sha256=LqjNcwt1sYSS3uhPXrf6jJzVCuHtNVpuirg5rb7mVm8,94
|
8 |
+
certifi/__main__.py,sha256=xBBoj905TUWBLRGANOcf7oi6e-3dMP4cEoG9OyMs11g,243
|
9 |
+
certifi/__pycache__/__init__.cpython-311.pyc,,
|
10 |
+
certifi/__pycache__/__main__.cpython-311.pyc,,
|
11 |
+
certifi/__pycache__/core.cpython-311.pyc,,
|
12 |
+
certifi/cacert.pem,sha256=gHiXJU84Oif0XkT0llbzeKurIUHt5DpK08JCCll90j8,294769
|
13 |
+
certifi/core.py,sha256=qRDDFyXVJwTB_EmoGppaXU_R9qCZvhl-EzxPMuV3nTA,4426
|
14 |
+
certifi/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/WHEEL
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Wheel-Version: 1.0
|
2 |
+
Generator: setuptools (75.6.0)
|
3 |
+
Root-Is-Purelib: true
|
4 |
+
Tag: py3-none-any
|
5 |
+
|
venv/lib/python3.11/site-packages/certifi-2024.12.14.dist-info/top_level.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
certifi
|
venv/lib/python3.11/site-packages/certifi/__init__.py
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from .core import contents, where
|
2 |
+
|
3 |
+
__all__ = ["contents", "where"]
|
4 |
+
__version__ = "2024.12.14"
|
venv/lib/python3.11/site-packages/certifi/__main__.py
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import argparse
|
2 |
+
|
3 |
+
from certifi import contents, where
|
4 |
+
|
5 |
+
parser = argparse.ArgumentParser()
|
6 |
+
parser.add_argument("-c", "--contents", action="store_true")
|
7 |
+
args = parser.parse_args()
|
8 |
+
|
9 |
+
if args.contents:
|
10 |
+
print(contents())
|
11 |
+
else:
|
12 |
+
print(where())
|
venv/lib/python3.11/site-packages/certifi/__pycache__/__init__.cpython-311.pyc
ADDED
Binary file (326 Bytes). View file
|
|
venv/lib/python3.11/site-packages/certifi/__pycache__/__main__.cpython-311.pyc
ADDED
Binary file (715 Bytes). View file
|
|
venv/lib/python3.11/site-packages/certifi/__pycache__/core.cpython-311.pyc
ADDED
Binary file (3.76 kB). View file
|
|
venv/lib/python3.11/site-packages/certifi/cacert.pem
ADDED
The diff for this file is too large to render.
See raw diff
|
|
venv/lib/python3.11/site-packages/certifi/core.py
ADDED
@@ -0,0 +1,114 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
"""
|
2 |
+
certifi.py
|
3 |
+
~~~~~~~~~~
|
4 |
+
|
5 |
+
This module returns the installation location of cacert.pem or its contents.
|
6 |
+
"""
|
7 |
+
import sys
|
8 |
+
import atexit
|
9 |
+
|
10 |
+
def exit_cacert_ctx() -> None:
|
11 |
+
_CACERT_CTX.__exit__(None, None, None) # type: ignore[union-attr]
|
12 |
+
|
13 |
+
|
14 |
+
if sys.version_info >= (3, 11):
|
15 |
+
|
16 |
+
from importlib.resources import as_file, files
|
17 |
+
|
18 |
+
_CACERT_CTX = None
|
19 |
+
_CACERT_PATH = None
|
20 |
+
|
21 |
+
def where() -> str:
|
22 |
+
# This is slightly terrible, but we want to delay extracting the file
|
23 |
+
# in cases where we're inside of a zipimport situation until someone
|
24 |
+
# actually calls where(), but we don't want to re-extract the file
|
25 |
+
# on every call of where(), so we'll do it once then store it in a
|
26 |
+
# global variable.
|
27 |
+
global _CACERT_CTX
|
28 |
+
global _CACERT_PATH
|
29 |
+
if _CACERT_PATH is None:
|
30 |
+
# This is slightly janky, the importlib.resources API wants you to
|
31 |
+
# manage the cleanup of this file, so it doesn't actually return a
|
32 |
+
# path, it returns a context manager that will give you the path
|
33 |
+
# when you enter it and will do any cleanup when you leave it. In
|
34 |
+
# the common case of not needing a temporary file, it will just
|
35 |
+
# return the file system location and the __exit__() is a no-op.
|
36 |
+
#
|
37 |
+
# We also have to hold onto the actual context manager, because
|
38 |
+
# it will do the cleanup whenever it gets garbage collected, so
|
39 |
+
# we will also store that at the global level as well.
|
40 |
+
_CACERT_CTX = as_file(files("certifi").joinpath("cacert.pem"))
|
41 |
+
_CACERT_PATH = str(_CACERT_CTX.__enter__())
|
42 |
+
atexit.register(exit_cacert_ctx)
|
43 |
+
|
44 |
+
return _CACERT_PATH
|
45 |
+
|
46 |
+
def contents() -> str:
|
47 |
+
return files("certifi").joinpath("cacert.pem").read_text(encoding="ascii")
|
48 |
+
|
49 |
+
elif sys.version_info >= (3, 7):
|
50 |
+
|
51 |
+
from importlib.resources import path as get_path, read_text
|
52 |
+
|
53 |
+
_CACERT_CTX = None
|
54 |
+
_CACERT_PATH = None
|
55 |
+
|
56 |
+
def where() -> str:
|
57 |
+
# This is slightly terrible, but we want to delay extracting the
|
58 |
+
# file in cases where we're inside of a zipimport situation until
|
59 |
+
# someone actually calls where(), but we don't want to re-extract
|
60 |
+
# the file on every call of where(), so we'll do it once then store
|
61 |
+
# it in a global variable.
|
62 |
+
global _CACERT_CTX
|
63 |
+
global _CACERT_PATH
|
64 |
+
if _CACERT_PATH is None:
|
65 |
+
# This is slightly janky, the importlib.resources API wants you
|
66 |
+
# to manage the cleanup of this file, so it doesn't actually
|
67 |
+
# return a path, it returns a context manager that will give
|
68 |
+
# you the path when you enter it and will do any cleanup when
|
69 |
+
# you leave it. In the common case of not needing a temporary
|
70 |
+
# file, it will just return the file system location and the
|
71 |
+
# __exit__() is a no-op.
|
72 |
+
#
|
73 |
+
# We also have to hold onto the actual context manager, because
|
74 |
+
# it will do the cleanup whenever it gets garbage collected, so
|
75 |
+
# we will also store that at the global level as well.
|
76 |
+
_CACERT_CTX = get_path("certifi", "cacert.pem")
|
77 |
+
_CACERT_PATH = str(_CACERT_CTX.__enter__())
|
78 |
+
atexit.register(exit_cacert_ctx)
|
79 |
+
|
80 |
+
return _CACERT_PATH
|
81 |
+
|
82 |
+
def contents() -> str:
|
83 |
+
return read_text("certifi", "cacert.pem", encoding="ascii")
|
84 |
+
|
85 |
+
else:
|
86 |
+
import os
|
87 |
+
import types
|
88 |
+
from typing import Union
|
89 |
+
|
90 |
+
Package = Union[types.ModuleType, str]
|
91 |
+
Resource = Union[str, "os.PathLike"]
|
92 |
+
|
93 |
+
# This fallback will work for Python versions prior to 3.7 that lack the
|
94 |
+
# importlib.resources module but relies on the existing `where` function
|
95 |
+
# so won't address issues with environments like PyOxidizer that don't set
|
96 |
+
# __file__ on modules.
|
97 |
+
def read_text(
|
98 |
+
package: Package,
|
99 |
+
resource: Resource,
|
100 |
+
encoding: str = 'utf-8',
|
101 |
+
errors: str = 'strict'
|
102 |
+
) -> str:
|
103 |
+
with open(where(), encoding=encoding) as data:
|
104 |
+
return data.read()
|
105 |
+
|
106 |
+
# If we don't have importlib.resources, then we will just do the old logic
|
107 |
+
# of assuming we're on the filesystem and munge the path directly.
|
108 |
+
def where() -> str:
|
109 |
+
f = os.path.dirname(__file__)
|
110 |
+
|
111 |
+
return os.path.join(f, "cacert.pem")
|
112 |
+
|
113 |
+
def contents() -> str:
|
114 |
+
return read_text("certifi", "cacert.pem", encoding="ascii")
|
venv/lib/python3.11/site-packages/certifi/py.typed
ADDED
File without changes
|