FranklinWillemen commited on
Commit
59cd50e
1 Parent(s): 6d7aca3

intial commit

Browse files
.gitignore ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ config.py
2
+
3
+ # Byte-compiled / optimized / DLL files
4
+ __pycache__/
5
+ *.py[cod]
6
+ *$py.class
7
+
8
+ # C extensions
9
+ *.so
10
+
11
+ # Distribution / packaging
12
+ .Python
13
+ build/
14
+ develop-eggs/
15
+ dist/
16
+ downloads/
17
+ eggs/
18
+ .eggs/
19
+ lib/
20
+ lib64/
21
+ parts/
22
+ sdist/
23
+ var/
24
+ wheels/
25
+ pip-wheel-metadata/
26
+ share/python-wheels/
27
+ *.egg-info/
28
+ .installed.cfg
29
+ *.egg
30
+ MANIFEST
31
+
32
+ # PyInstaller
33
+ # Usually these files are written by a python script from a template
34
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
35
+ *.manifest
36
+ *.spec
37
+
38
+ # Installer logs
39
+ pip-log.txt
40
+ pip-delete-this-directory.txt
41
+
42
+ # Unit test / coverage reports
43
+ htmlcov/
44
+ .tox/
45
+ .nox/
46
+ .coverage
47
+ .coverage.*
48
+ .cache
49
+ nosetests.xml
50
+ coverage.xml
51
+ *.cover
52
+ *.py,cover
53
+ .hypothesis/
54
+ .pytest_cache/
55
+
56
+ # Translations
57
+ *.mo
58
+ *.pot
59
+
60
+ # Django stuff:
61
+ *.log
62
+ local_settings.py
63
+ db.sqlite3
64
+ db.sqlite3-journal
65
+
66
+ # Flask stuff:
67
+ instance/
68
+ .webassets-cache
69
+
70
+ # Scrapy stuff:
71
+ .scrapy
72
+
73
+ # Sphinx documentation
74
+ docs/_build/
75
+
76
+ # PyBuilder
77
+ target/
78
+
79
+ # Jupyter Notebook
80
+ .ipynb_checkpoints
81
+
82
+ # IPython
83
+ profile_default/
84
+ ipython_config.py
85
+
86
+ # pyenv
87
+ .python-version
88
+
89
+ # pipenv
90
+ # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
91
+ # However, in case of collaboration, if having platform-specific dependencies or dependencies
92
+ # having no cross-platform support, pipenv may install dependencies that don't work, or not
93
+ # install all needed dependencies.
94
+ #Pipfile.lock
95
+
96
+ # PEP 582; used by e.g. github.com/David-OConnor/pyflow
97
+ __pypackages__/
98
+
99
+ # Celery stuff
100
+ celerybeat-schedule
101
+ celerybeat.pid
102
+
103
+ # SageMath parsed files
104
+ *.sage.py
105
+
106
+ # Environments
107
+ .env
108
+ .venv
109
+ env/
110
+ venv/
111
+ ENV/
112
+ env.bak/
113
+ venv.bak/
114
+
115
+ # Spyder project settings
116
+ .spyderproject
117
+ .spyproject
118
+
119
+ # Rope project settings
120
+ .ropeproject
121
+
122
+ # mkdocs documentation
123
+ /site
124
+
125
+ # mypy
126
+ .mypy_cache/
127
+ .dmypy.json
128
+ dmypy.json
129
+
130
+ # Pyre type checker
131
+ .pyre/
README.md CHANGED
@@ -1 +1,6 @@
1
- # TARS-AI
 
 
 
 
 
 
1
+ # TARS Discourse
2
+ Playground for a discourse bot based on SOTA (State Of The Art) AIAAS (AI As A Service).
3
+
4
+ Starting point is a fork of the "chatgpt api and whisper api tutorial - voice conversation with therapist".
5
+
6
+ ## Setup
TARS-discourse.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import openai
3
+ import config
4
+ import os
5
+ import pyttsx3
6
+ openai.api_key = config.OPENAI_API_KEY
7
+
8
+ messages = [{"role": "system", "content": 'You are a therapist. Respond to all input in 25 words or less.'}]
9
+
10
+ def transcribe(audio: str):
11
+ global messages
12
+
13
+ audio_filename_with_extension = audio + '.wav'
14
+ os.rename(audio, audio_filename_with_extension)
15
+
16
+ audio_file = open(audio_filename_with_extension, "rb")
17
+ transcript = openai.Audio.transcribe("whisper-1", audio_file)
18
+
19
+ messages.append({"role": "user", "content": transcript["text"]})
20
+
21
+ response = openai.ChatCompletion.create(model="gpt-3.5-turbo", messages=messages)
22
+
23
+ system_message = response["choices"][0]["message"]
24
+ messages.append(system_message)
25
+
26
+ # subprocess.call(["say", system_message['content']])
27
+ engine = pyttsx3.init()
28
+ engine.say(system_message['content'])
29
+ engine.runAndWait()
30
+
31
+ chat_transcript = ""
32
+ for message in messages:
33
+ if message['role'] != 'system':
34
+ chat_transcript += message['role'] + ": " + message['content'] + "\n\n"
35
+
36
+ return chat_transcript
37
+
38
+ ui = gr.Interface(fn=transcribe, inputs=gr.Audio(source="microphone", type="filepath"), outputs="text").launch()
requirements.txt ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ openai
2
+ gradio
tars-env/Scripts/Activate.ps1 ADDED
@@ -0,0 +1,502 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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"
248
+
249
+ # SIG # Begin signature block
250
+ # MIIvIQYJKoZIhvcNAQcCoIIvEjCCLw4CAQExDzANBglghkgBZQMEAgEFADB5Bgor
251
+ # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
252
+ # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk
253
+ # dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCE8MwggWQMIIDeKADAgECAhAFmxtXno4h
254
+ # MuI5B72nd3VcMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
255
+ # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
256
+ # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0xMzA4MDExMjAwMDBaFw0z
257
+ # ODAxMTUxMjAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
258
+ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
259
+ # IFRydXN0ZWQgUm9vdCBHNDCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
260
+ # AL/mkHNo3rvkXUo8MCIwaTPswqclLskhPfKK2FnC4SmnPVirdprNrnsbhA3EMB/z
261
+ # G6Q4FutWxpdtHauyefLKEdLkX9YFPFIPUh/GnhWlfr6fqVcWWVVyr2iTcMKyunWZ
262
+ # anMylNEQRBAu34LzB4TmdDttceItDBvuINXJIB1jKS3O7F5OyJP4IWGbNOsFxl7s
263
+ # Wxq868nPzaw0QF+xembud8hIqGZXV59UWI4MK7dPpzDZVu7Ke13jrclPXuU15zHL
264
+ # 2pNe3I6PgNq2kZhAkHnDeMe2scS1ahg4AxCN2NQ3pC4FfYj1gj4QkXCrVYJBMtfb
265
+ # BHMqbpEBfCFM1LyuGwN1XXhm2ToxRJozQL8I11pJpMLmqaBn3aQnvKFPObURWBf3
266
+ # JFxGj2T3wWmIdph2PVldQnaHiZdpekjw4KISG2aadMreSx7nDmOu5tTvkpI6nj3c
267
+ # AORFJYm2mkQZK37AlLTSYW3rM9nF30sEAMx9HJXDj/chsrIRt7t/8tWMcCxBYKqx
268
+ # YxhElRp2Yn72gLD76GSmM9GJB+G9t+ZDpBi4pncB4Q+UDCEdslQpJYls5Q5SUUd0
269
+ # viastkF13nqsX40/ybzTQRESW+UQUOsxxcpyFiIJ33xMdT9j7CFfxCBRa2+xq4aL
270
+ # T8LWRV+dIPyhHsXAj6KxfgommfXkaS+YHS312amyHeUbAgMBAAGjQjBAMA8GA1Ud
271
+ # EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBTs1+OC0nFdZEzf
272
+ # Lmc/57qYrhwPTzANBgkqhkiG9w0BAQwFAAOCAgEAu2HZfalsvhfEkRvDoaIAjeNk
273
+ # aA9Wz3eucPn9mkqZucl4XAwMX+TmFClWCzZJXURj4K2clhhmGyMNPXnpbWvWVPjS
274
+ # PMFDQK4dUPVS/JA7u5iZaWvHwaeoaKQn3J35J64whbn2Z006Po9ZOSJTROvIXQPK
275
+ # 7VB6fWIhCoDIc2bRoAVgX+iltKevqPdtNZx8WorWojiZ83iL9E3SIAveBO6Mm0eB
276
+ # cg3AFDLvMFkuruBx8lbkapdvklBtlo1oepqyNhR6BvIkuQkRUNcIsbiJeoQjYUIp
277
+ # 5aPNoiBB19GcZNnqJqGLFNdMGbJQQXE9P01wI4YMStyB0swylIQNCAmXHE/A7msg
278
+ # dDDS4Dk0EIUhFQEI6FUy3nFJ2SgXUE3mvk3RdazQyvtBuEOlqtPDBURPLDab4vri
279
+ # RbgjU2wGb2dVf0a1TD9uKFp5JtKkqGKX0h7i7UqLvBv9R0oN32dmfrJbQdA75PQ7
280
+ # 9ARj6e/CVABRoIoqyc54zNXqhwQYs86vSYiv85KZtrPmYQ/ShQDnUBrkG5WdGaG5
281
+ # nLGbsQAe79APT0JsyQq87kP6OnGlyE0mpTX9iV28hWIdMtKgK1TtmlfB2/oQzxm3
282
+ # i0objwG2J5VT6LaJbVu8aNQj6ItRolb58KaAoNYes7wPD1N1KarqE3fk3oyBIa0H
283
+ # EEcRrYc9B9F1vM/zZn4wggawMIIEmKADAgECAhAIrUCyYNKcTJ9ezam9k67ZMA0G
284
+ # CSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ
285
+ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lDZXJ0
286
+ # IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0zNjA0MjgyMzU5NTla
287
+ # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
288
+ # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
289
+ # ODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVtC9C
290
+ # 0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0JAfhS0/TeEP0F9ce
291
+ # 2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJrQ5qZ8sU7H/Lvy0da
292
+ # E6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhFLqGfLOEYwhrMxe6T
293
+ # SXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+FLEikVoQ11vkunKoA
294
+ # FdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh3K3kGKDYwSNHR7Oh
295
+ # D26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJwZPt4bRc4G/rJvmM
296
+ # 1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQayg9Rc9hUZTO1i4F4z
297
+ # 8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbIYViY9XwCFjyDKK05
298
+ # huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchApQfDVxW0mdmgRQRNY
299
+ # mtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRroOBl8ZhzNeDhFMJlP
300
+ # /2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IBWTCCAVUwEgYDVR0T
301
+ # AQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+YXsIiGX0TkIwHwYD
302
+ # VR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0PAQH/BAQDAgGGMBMG
303
+ # A1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAkBggrBgEFBQcwAYYY
304
+ # aHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAChjVodHRwOi8vY2Fj
305
+ # ZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNydDBDBgNV
306
+ # HR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRU
307
+ # cnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAEDMAgGBmeBDAEEATAN
308
+ # BgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql+Eg08yy25nRm95Ry
309
+ # sQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFFUP2cvbaF4HZ+N3HL
310
+ # IvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1hmYFW9snjdufE5Btf
311
+ # Q/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3RywYFzzDaju4ImhvTnh
312
+ # OE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5UbdldAhQfQDN8A+KVssIh
313
+ # dXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw8MzK7/0pNVwfiThV
314
+ # 9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnPLqR0kq3bPKSchh/j
315
+ # wVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatEQOON8BUozu3xGFYH
316
+ # Ki8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bnKD+sEq6lLyJsQfmC
317
+ # XBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQjiWQ1tygVQK+pKHJ6l
318
+ # /aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbqyK+p/pQd52MbOoZW
319
+ # eE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0GCSqGSIb3DQEBCwUA
320
+ # MGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjFBMD8GA1UE
321
+ # AxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcgUlNBNDA5NiBTSEEz
322
+ # ODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1MjM1OTU5WjB8MQsw
323
+ # CQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQHEwlCZWF2ZXJ0b24x
324
+ # IzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9uMSMwIQYDVQQDExpQ
325
+ # eXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
326
+ # ADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiSYgDFfwhjQy89koM7
327
+ # uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi0GGAZUegEAeRlSXx
328
+ # xhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN16yS8skFa3IHyvWdb
329
+ # D9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGuppxcia6a7xCyKoOA
330
+ # GjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu352diDY+iCMpk9Zanm
331
+ # SjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0ZFYKeb6BLA66d2GA
332
+ # LwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oERzTzEiV6nCO1M3U1
333
+ # HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZI7IWe7JKhHohqKuc
334
+ # eQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16xot2KVPdfyPAWd81w
335
+ # tZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapPUnwo8ygflJJ74J+B
336
+ # Yxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3ZIly+qIqDAgMBAAGj
337
+ # ggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiIZfROQjAdBgNVHQ4E
338
+ # FgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQM
339
+ # MAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0dHA6Ly9jcmwzLmRp
340
+ # Z2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNI
341
+ # QTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5kaWdpY2VydC5jb20v
342
+ # RGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZTSEEzODQyMDIxQ0Ex
343
+ # LmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUFBwIBFhtodHRwOi8v
344
+ # d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGHMIGEMCQGCCsGAQUF
345
+ # BzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYBBQUHMAKGUGh0dHA6
346
+ # Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu
347
+ # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZI
348
+ # hvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcWTiNc2rskrNLrfH1N
349
+ # s0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+VVzxC88pOEvz68nA
350
+ # 82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfLIJQsAHBla0i7QRF2
351
+ # de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izWOXM95BSkFSKdE45O
352
+ # q3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86WmjRUqbrnvdyR2yd
353
+ # I5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+W1scCpnA8YTs2d50
354
+ # jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM58WEDkbeoriDk3hxU
355
+ # 8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMfZOm5cuclMnUHs2uq
356
+ # rRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw/TKqVL4Oaz3bkMSs
357
+ # M46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3r7bjyHTxOgqxRCVa
358
+ # 18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VHxaZg2unjHY3rMYIa
359
+ # tDCCGrACAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu
360
+ # Yy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29kZSBTaWduaW5nIFJT
361
+ # QTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM0NHdMA0GCWCGSAFl
362
+ # AwQCAQUAoIHIMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcC
363
+ # AQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBnAZ6P7YvTwq0fbF62
364
+ # o7E75R0LxsW5OtyYiFESQckLhjBcBgorBgEEAYI3AgEMMU4wTKBGgEQAQgB1AGkA
365
+ # bAB0ADoAIABSAGUAbABlAGEAcwBlAF8AdgAzAC4AMQAxAC4AMwBfADIAMAAyADMA
366
+ # MAA0ADAANAAuADAAMaECgAAwDQYJKoZIhvcNAQEBBQAEggIAbmsoeVnvqR4l7EsR
367
+ # nUNDQhIoOsioPo5dRYtGRoY3gWX6NnIWzyYo3nlX//xY6JbfZ8oyaqLZULFMkLWm
368
+ # +c70FKdQS5yI9auu/DOqmZ0AcPsLXEc7rJZagpBDgi6xCvAyvpAHj1FUcGGzWsE+
369
+ # Qp8LkKU5AApLcHpBci3eZYUpiwoTNvDCQLYIv5j5mh8Fb8j2D/sUt2coONsqLllY
370
+ # BB1Cpko4g9CEfJKtXKb8g0U8+giDAxt/0r6AMdeqlx9ysFB0Nil+tneagBTQ4vQl
371
+ # pl5mztf7JVkzasgDNvNcFMo04crUW5g5oErl3e/bO63v1duN7ZuJBJvKs9aDrogI
372
+ # KOLwYbTYa1Y5wHCsz8HCgd3pfRxQgwWL0+zx7+MKpqlvo20JmFG5H8wj3tcdc1FW
373
+ # QeOVYzVijkeGqRb21HTNHKuTfV4Gw3cLdT4oOENY3JdkJ+oqnAiSwC1p/Fm3pizG
374
+ # wkc3D+JjNYg6UT+9PdWqLtsjaBODM1lB22Bpx/nnPCnUG8WEx9cwi39zJdV+atcZ
375
+ # eTKc+Ahpyxot3az6yv9w83+7wIdnSWBWQwAHonjwx1jjMiiDpLyHblqxt/jgejkV
376
+ # VQEam7XX3KOKI3CHDC8k3M4V6QTnCTIX/WLslIO57hwUGtOAGmww6/q2NOqKeqpH
377
+ # 1B6f/CLtXwSh0d4raerISKVQjYChghc9MIIXOQYKKwYBBAGCNwMDATGCFykwghcl
378
+ # BgkqhkiG9w0BBwKgghcWMIIXEgIBAzEPMA0GCWCGSAFlAwQCAQUAMHcGCyqGSIb3
379
+ # DQEJEAEEoGgEZjBkAgEBBglghkgBhv1sBwEwMTANBglghkgBZQMEAgEFAAQgkIZK
380
+ # LoYk5fC9ubz0LiZd/QHnskSNa7ucOHGD7CWySe4CEHn5OnRbrbmQtyWnJjmOhREY
381
+ # DzIwMjMwNDA1MDAwMjQ1WqCCEwcwggbAMIIEqKADAgECAhAMTWlyS5T6PCpKPSkH
382
+ # gD1aMA0GCSqGSIb3DQEBCwUAMGMxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdp
383
+ # Q2VydCwgSW5jLjE7MDkGA1UEAxMyRGlnaUNlcnQgVHJ1c3RlZCBHNCBSU0E0MDk2
384
+ # IFNIQTI1NiBUaW1lU3RhbXBpbmcgQ0EwHhcNMjIwOTIxMDAwMDAwWhcNMzMxMTIx
385
+ # MjM1OTU5WjBGMQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxJDAiBgNV
386
+ # BAMTG0RpZ2lDZXJ0IFRpbWVzdGFtcCAyMDIyIC0gMjCCAiIwDQYJKoZIhvcNAQEB
387
+ # BQADggIPADCCAgoCggIBAM/spSY6xqnya7uNwQ2a26HoFIV0MxomrNAcVR4eNm28
388
+ # klUMYfSdCXc9FZYIL2tkpP0GgxbXkZI4HDEClvtysZc6Va8z7GGK6aYo25BjXL2J
389
+ # U+A6LYyHQq4mpOS7eHi5ehbhVsbAumRTuyoW51BIu4hpDIjG8b7gL307scpTjUCD
390
+ # HufLckkoHkyAHoVW54Xt8mG8qjoHffarbuVm3eJc9S/tjdRNlYRo44DLannR0hCR
391
+ # RinrPibytIzNTLlmyLuqUDgN5YyUXRlav/V7QG5vFqianJVHhoV5PgxeZowaCiS+
392
+ # nKrSnLb3T254xCg/oxwPUAY3ugjZNaa1Htp4WB056PhMkRCWfk3h3cKtpX74LRsf
393
+ # 7CtGGKMZ9jn39cFPcS6JAxGiS7uYv/pP5Hs27wZE5FX/NurlfDHn88JSxOYWe1p+
394
+ # pSVz28BqmSEtY+VZ9U0vkB8nt9KrFOU4ZodRCGv7U0M50GT6Vs/g9ArmFG1keLuY
395
+ # /ZTDcyHzL8IuINeBrNPxB9ThvdldS24xlCmL5kGkZZTAWOXlLimQprdhZPrZIGwY
396
+ # UWC6poEPCSVT8b876asHDmoHOWIZydaFfxPZjXnPYsXs4Xu5zGcTB5rBeO3GiMiw
397
+ # bjJ5xwtZg43G7vUsfHuOy2SJ8bHEuOdTXl9V0n0ZKVkDTvpd6kVzHIR+187i1Dp3
398
+ # AgMBAAGjggGLMIIBhzAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNV
399
+ # HSUBAf8EDDAKBggrBgEFBQcDCDAgBgNVHSAEGTAXMAgGBmeBDAEEAjALBglghkgB
400
+ # hv1sBwEwHwYDVR0jBBgwFoAUuhbZbU2FL3MpdpovdYxqII+eyG8wHQYDVR0OBBYE
401
+ # FGKK3tBh/I8xFO2XC809KpQU31KcMFoGA1UdHwRTMFEwT6BNoEuGSWh0dHA6Ly9j
402
+ # cmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEyNTZU
403
+ # aW1lU3RhbXBpbmdDQS5jcmwwgZAGCCsGAQUFBwEBBIGDMIGAMCQGCCsGAQUFBzAB
404
+ # hhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wWAYIKwYBBQUHMAKGTGh0dHA6Ly9j
405
+ # YWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNFJTQTQwOTZTSEEy
406
+ # NTZUaW1lU3RhbXBpbmdDQS5jcnQwDQYJKoZIhvcNAQELBQADggIBAFWqKhrzRvN4
407
+ # Vzcw/HXjT9aFI/H8+ZU5myXm93KKmMN31GT8Ffs2wklRLHiIY1UJRjkA/GnUypsp
408
+ # +6M/wMkAmxMdsJiJ3HjyzXyFzVOdr2LiYWajFCpFh0qYQitQ/Bu1nggwCfrkLdcJ
409
+ # iXn5CeaIzn0buGqim8FTYAnoo7id160fHLjsmEHw9g6A++T/350Qp+sAul9Kjxo6
410
+ # UrTqvwlJFTU2WZoPVNKyG39+XgmtdlSKdG3K0gVnK3br/5iyJpU4GYhEFOUKWaJr
411
+ # 5yI+RCHSPxzAm+18SLLYkgyRTzxmlK9dAlPrnuKe5NMfhgFknADC6Vp0dQ094XmI
412
+ # vxwBl8kZI4DXNlpflhaxYwzGRkA7zl011Fk+Q5oYrsPJy8P7mxNfarXH4PMFw1nf
413
+ # J2Ir3kHJU7n/NBBn9iYymHv+XEKUgZSCnawKi8ZLFUrTmJBFYDOA4CPe+AOk9kVH
414
+ # 5c64A0JH6EE2cXet/aLol3ROLtoeHYxayB6a1cLwxiKoT5u92ByaUcQvmvZfpyeX
415
+ # upYuhVfAYOd4Vn9q78KVmksRAsiCnMkaBXy6cbVOepls9Oie1FqYyJ+/jbsYXEP1
416
+ # 0Cro4mLueATbvdH7WwqocH7wl4R44wgDXUcsY6glOJcB0j862uXl9uab3H4szP8X
417
+ # TE0AotjWAQ64i+7m4HJViSwnGWH2dwGMMIIGrjCCBJagAwIBAgIQBzY3tyRUfNhH
418
+ # rP0oZipeWzANBgkqhkiG9w0BAQsFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM
419
+ # RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQD
420
+ # ExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwHhcNMjIwMzIzMDAwMDAwWhcNMzcw
421
+ # MzIyMjM1OTU5WjBjMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORGlnaUNlcnQsIElu
422
+ # Yy4xOzA5BgNVBAMTMkRpZ2lDZXJ0IFRydXN0ZWQgRzQgUlNBNDA5NiBTSEEyNTYg
423
+ # VGltZVN0YW1waW5nIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA
424
+ # xoY1BkmzwT1ySVFVxyUDxPKRN6mXUaHW0oPRnkyibaCwzIP5WvYRoUQVQl+kiPNo
425
+ # +n3znIkLf50fng8zH1ATCyZzlm34V6gCff1DtITaEfFzsbPuK4CEiiIY3+vaPcQX
426
+ # f6sZKz5C3GeO6lE98NZW1OcoLevTsbV15x8GZY2UKdPZ7Gnf2ZCHRgB720RBidx8
427
+ # ald68Dd5n12sy+iEZLRS8nZH92GDGd1ftFQLIWhuNyG7QKxfst5Kfc71ORJn7w6l
428
+ # Y2zkpsUdzTYNXNXmG6jBZHRAp8ByxbpOH7G1WE15/tePc5OsLDnipUjW8LAxE6lX
429
+ # KZYnLvWHpo9OdhVVJnCYJn+gGkcgQ+NDY4B7dW4nJZCYOjgRs/b2nuY7W+yB3iIU
430
+ # 2YIqx5K/oN7jPqJz+ucfWmyU8lKVEStYdEAoq3NDzt9KoRxrOMUp88qqlnNCaJ+2
431
+ # RrOdOqPVA+C/8KI8ykLcGEh/FDTP0kyr75s9/g64ZCr6dSgkQe1CvwWcZklSUPRR
432
+ # 8zZJTYsg0ixXNXkrqPNFYLwjjVj33GHek/45wPmyMKVM1+mYSlg+0wOI/rOP015L
433
+ # dhJRk8mMDDtbiiKowSYI+RQQEgN9XyO7ZONj4KbhPvbCdLI/Hgl27KtdRnXiYKNY
434
+ # CQEoAA6EVO7O6V3IXjASvUaetdN2udIOa5kM0jO0zbECAwEAAaOCAV0wggFZMBIG
435
+ # A1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYEFLoW2W1NhS9zKXaaL3WMaiCPnshv
436
+ # MB8GA1UdIwQYMBaAFOzX44LScV1kTN8uZz/nupiuHA9PMA4GA1UdDwEB/wQEAwIB
437
+ # hjATBgNVHSUEDDAKBggrBgEFBQcDCDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUH
438
+ # MAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDov
439
+ # L2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0VHJ1c3RlZFJvb3RHNC5jcnQw
440
+ # QwYDVR0fBDwwOjA4oDagNIYyaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0RpZ2lD
441
+ # ZXJ0VHJ1c3RlZFJvb3RHNC5jcmwwIAYDVR0gBBkwFzAIBgZngQwBBAIwCwYJYIZI
442
+ # AYb9bAcBMA0GCSqGSIb3DQEBCwUAA4ICAQB9WY7Ak7ZvmKlEIgF+ZtbYIULhsBgu
443
+ # EE0TzzBTzr8Y+8dQXeJLKftwig2qKWn8acHPHQfpPmDI2AvlXFvXbYf6hCAlNDFn
444
+ # zbYSlm/EUExiHQwIgqgWvalWzxVzjQEiJc6VaT9Hd/tydBTX/6tPiix6q4XNQ1/t
445
+ # YLaqT5Fmniye4Iqs5f2MvGQmh2ySvZ180HAKfO+ovHVPulr3qRCyXen/KFSJ8NWK
446
+ # cXZl2szwcqMj+sAngkSumScbqyQeJsG33irr9p6xeZmBo1aGqwpFyd/EjaDnmPv7
447
+ # pp1yr8THwcFqcdnGE4AJxLafzYeHJLtPo0m5d2aR8XKc6UsCUqc3fpNTrDsdCEkP
448
+ # lM05et3/JWOZJyw9P2un8WbDQc1PtkCbISFA0LcTJM3cHXg65J6t5TRxktcma+Q4
449
+ # c6umAU+9Pzt4rUyt+8SVe+0KXzM5h0F4ejjpnOHdI/0dKNPH+ejxmF/7K9h+8kad
450
+ # dSweJywm228Vex4Ziza4k9Tm8heZWcpw8De/mADfIBZPJ/tgZxahZrrdVcA6KYaw
451
+ # mKAr7ZVBtzrVFZgxtGIJDwq9gdkT/r+k0fNX2bwE+oLeMt8EifAAzV3C+dAjfwAL
452
+ # 5HYCJtnwZXZCpimHCUcr5n8apIUP/JiW9lVUKx+A+sDyDivl1vupL0QVSucTDh3b
453
+ # NzgaoSv27dZ8/DCCBY0wggR1oAMCAQICEA6bGI750C3n79tQ4ghAGFowDQYJKoZI
454
+ # hvcNAQEMBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
455
+ # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGlnaUNlcnQgQXNz
456
+ # dXJlZCBJRCBSb290IENBMB4XDTIyMDgwMTAwMDAwMFoXDTMxMTEwOTIzNTk1OVow
457
+ # YjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQ
458
+ # d3d3LmRpZ2ljZXJ0LmNvbTEhMB8GA1UEAxMYRGlnaUNlcnQgVHJ1c3RlZCBSb290
459
+ # IEc0MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAv+aQc2jeu+RdSjww
460
+ # IjBpM+zCpyUuySE98orYWcLhKac9WKt2ms2uexuEDcQwH/MbpDgW61bGl20dq7J5
461
+ # 8soR0uRf1gU8Ug9SH8aeFaV+vp+pVxZZVXKvaJNwwrK6dZlqczKU0RBEEC7fgvMH
462
+ # hOZ0O21x4i0MG+4g1ckgHWMpLc7sXk7Ik/ghYZs06wXGXuxbGrzryc/NrDRAX7F6
463
+ # Zu53yEioZldXn1RYjgwrt0+nMNlW7sp7XeOtyU9e5TXnMcvak17cjo+A2raRmECQ
464
+ # ecN4x7axxLVqGDgDEI3Y1DekLgV9iPWCPhCRcKtVgkEy19sEcypukQF8IUzUvK4b
465
+ # A3VdeGbZOjFEmjNAvwjXWkmkwuapoGfdpCe8oU85tRFYF/ckXEaPZPfBaYh2mHY9
466
+ # WV1CdoeJl2l6SPDgohIbZpp0yt5LHucOY67m1O+SkjqePdwA5EUlibaaRBkrfsCU
467
+ # tNJhbesz2cXfSwQAzH0clcOP9yGyshG3u3/y1YxwLEFgqrFjGESVGnZifvaAsPvo
468
+ # ZKYz0YkH4b235kOkGLimdwHhD5QMIR2yVCkliWzlDlJRR3S+Jqy2QXXeeqxfjT/J
469
+ # vNNBERJb5RBQ6zHFynIWIgnffEx1P2PsIV/EIFFrb7GrhotPwtZFX50g/KEexcCP
470
+ # orF+CiaZ9eRpL5gdLfXZqbId5RsCAwEAAaOCATowggE2MA8GA1UdEwEB/wQFMAMB
471
+ # Af8wHQYDVR0OBBYEFOzX44LScV1kTN8uZz/nupiuHA9PMB8GA1UdIwQYMBaAFEXr
472
+ # oq/0ksuCMS1Ri6enIZ3zbcgPMA4GA1UdDwEB/wQEAwIBhjB5BggrBgEFBQcBAQRt
473
+ # MGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEF
474
+ # BQcwAoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl
475
+ # ZElEUm9vdENBLmNydDBFBgNVHR8EPjA8MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdp
476
+ # Y2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMBEGA1UdIAQKMAgw
477
+ # BgYEVR0gADANBgkqhkiG9w0BAQwFAAOCAQEAcKC/Q1xV5zhfoKN0Gz22Ftf3v1cH
478
+ # vZqsoYcs7IVeqRq7IviHGmlUIu2kiHdtvRoU9BNKei8ttzjv9P+Aufih9/Jy3iS8
479
+ # UgPITtAq3votVs/59PesMHqai7Je1M/RQ0SbQyHrlnKhSLSZy51PpwYDE3cnRNTn
480
+ # f+hZqPC/Lwum6fI0POz3A8eHqNJMQBk1RmppVLC4oVaO7KTVPeix3P0c2PR3WlxU
481
+ # jG/voVA9/HYJaISfb8rbII01YBwCA8sgsKxYoA5AY8WYIsGyWfVVa88nq2x2zm8j
482
+ # LfR+cWojayL/ErhULSd+2DrZ8LaHlv1b0VysGMNNn3O3AamfV6peKOK5lDGCA3Yw
483
+ # ggNyAgEBMHcwYzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu
484
+ # MTswOQYDVQQDEzJEaWdpQ2VydCBUcnVzdGVkIEc0IFJTQTQwOTYgU0hBMjU2IFRp
485
+ # bWVTdGFtcGluZyBDQQIQDE1pckuU+jwqSj0pB4A9WjANBglghkgBZQMEAgEFAKCB
486
+ # 0TAaBgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIz
487
+ # MDQwNTAwMDI0NVowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU84ciTYYzgpI1qZS8
488
+ # vY+W6f4cfHMwLwYJKoZIhvcNAQkEMSIEIJBlriw3QJw5qq5ADo60uCRAA2a3vjKn
489
+ # zaGl8ppJqVo5MDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEIMf04b4yKIkgq+ImOr4a
490
+ # xPxP5ngcLWTQTIB1V6Ajtbb6MA0GCSqGSIb3DQEBAQUABIICADC4cqKeH7lb0Ll+
491
+ # iZIDw+mU6vcA3C8vUPR4KdqQmVlEkjfKdHBpHOI1eRkXwesD+BkrXpRX/NMNKm5w
492
+ # eKlymuuS70/NOX03BgnP4A9p4TqSZJcLvrP5VUc7VlMaVwkNj47vft4OF9A7PFs4
493
+ # 3e8BJmhhkXDh1j+MdQ5URPGsla8uYm74Cn/T2WPNZ5FFQ8nkoVz93x1c5wUYEruB
494
+ # uIyFKwZshDnsYsHetZoBMpWDspcXj0kKAplBW0hUw6kgX7qBKX7doTcZPXP00VM8
495
+ # vYnpQkJPGrTZ4S/cN0D5k0ZTXTCTDtOpFaZLbG29OgSFxD/TslfXkf1t8GiuzXvk
496
+ # u6xLEPxBW9N4yrun+jUjXr0921HEg7BKRr77bGS9v9b4mfzThomjtdcL3bweU5RE
497
+ # 3Bg4qVrgNF9Io8L/n39U7Zd5LG4Nacd+Uv+B1x6sfyQP+vGvY0UEiJUhkGy0ymzm
498
+ # RBtsPmJanvIovpkYebSccueoeC08/AUf2LxZ6lfGxkJp95vNj4pWToYRXY2dj5JE
499
+ # 6nX7mLYn3mWMbXniPhtpnYJeDahE2cuB3pqbhZSlGpOtF7fEPSCBq9P3YMnuyRun
500
+ # thsRTf8xc30muj6bRejnUJj0bNQaByZKAhEENnqH0TXBF7yasT1H3/PyC1pgyzx8
501
+ # swIsvJFXCqG2u9lftpHuQYmHPDoq
502
+ # SIG # End signature block
tars-env/Scripts/activate ADDED
@@ -0,0 +1,69 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
+ # This should detect bash and zsh, which have a hash command that must
18
+ # be called to get it to forget past commands. Without forgetting
19
+ # past commands the $PATH changes we made may not be respected
20
+ if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
21
+ hash -r 2> /dev/null
22
+ fi
23
+
24
+ if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
25
+ PS1="${_OLD_VIRTUAL_PS1:-}"
26
+ export PS1
27
+ unset _OLD_VIRTUAL_PS1
28
+ fi
29
+
30
+ unset VIRTUAL_ENV
31
+ unset VIRTUAL_ENV_PROMPT
32
+ if [ ! "${1:-}" = "nondestructive" ] ; then
33
+ # Self destruct!
34
+ unset -f deactivate
35
+ fi
36
+ }
37
+
38
+ # unset irrelevant variables
39
+ deactivate nondestructive
40
+
41
+ VIRTUAL_ENV="C:\Users\Frank\TARS\tars-env"
42
+ export VIRTUAL_ENV
43
+
44
+ _OLD_VIRTUAL_PATH="$PATH"
45
+ PATH="$VIRTUAL_ENV/Scripts:$PATH"
46
+ export PATH
47
+
48
+ # unset PYTHONHOME if set
49
+ # this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
50
+ # could use `if (set -u; : $PYTHONHOME) ;` in bash
51
+ if [ -n "${PYTHONHOME:-}" ] ; then
52
+ _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
53
+ unset PYTHONHOME
54
+ fi
55
+
56
+ if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
57
+ _OLD_VIRTUAL_PS1="${PS1:-}"
58
+ PS1="(tars-env) ${PS1:-}"
59
+ export PS1
60
+ VIRTUAL_ENV_PROMPT="(tars-env) "
61
+ export VIRTUAL_ENV_PROMPT
62
+ fi
63
+
64
+ # This should detect bash and zsh, which have a hash command that must
65
+ # be called to get it to forget past commands. Without forgetting
66
+ # past commands the $PATH changes we made may not be respected
67
+ if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
68
+ hash -r 2> /dev/null
69
+ fi
tars-env/Scripts/activate.bat ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+
3
+ rem This file is UTF-8 encoded, so we need to update the current code page while executing it
4
+ for /f "tokens=2 delims=:." %%a in ('"%SystemRoot%\System32\chcp.com"') do (
5
+ set _OLD_CODEPAGE=%%a
6
+ )
7
+ if defined _OLD_CODEPAGE (
8
+ "%SystemRoot%\System32\chcp.com" 65001 > nul
9
+ )
10
+
11
+ set VIRTUAL_ENV=C:\Users\Frank\TARS\tars-env
12
+
13
+ if not defined PROMPT set PROMPT=$P$G
14
+
15
+ if defined _OLD_VIRTUAL_PROMPT set PROMPT=%_OLD_VIRTUAL_PROMPT%
16
+ if defined _OLD_VIRTUAL_PYTHONHOME set PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%
17
+
18
+ set _OLD_VIRTUAL_PROMPT=%PROMPT%
19
+ set PROMPT=(tars-env) %PROMPT%
20
+
21
+ if defined PYTHONHOME set _OLD_VIRTUAL_PYTHONHOME=%PYTHONHOME%
22
+ set PYTHONHOME=
23
+
24
+ if defined _OLD_VIRTUAL_PATH set PATH=%_OLD_VIRTUAL_PATH%
25
+ if not defined _OLD_VIRTUAL_PATH set _OLD_VIRTUAL_PATH=%PATH%
26
+
27
+ set PATH=%VIRTUAL_ENV%\Scripts;%PATH%
28
+ set VIRTUAL_ENV_PROMPT=(tars-env)
29
+
30
+ :END
31
+ if defined _OLD_CODEPAGE (
32
+ "%SystemRoot%\System32\chcp.com" %_OLD_CODEPAGE% > nul
33
+ set _OLD_CODEPAGE=
34
+ )
tars-env/Scripts/clear_comtypes_cache.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import sys
3
+ import shutil
4
+
5
+ def get_next_cache_dir():
6
+ work_dir = os.getcwd()
7
+ try:
8
+ # change working directory to avoid import from local folder
9
+ # during installation process
10
+ os.chdir(os.path.dirname(sys.executable))
11
+ import comtypes.client
12
+ return comtypes.client._code_cache._find_gen_dir()
13
+ except ImportError:
14
+ return None
15
+ finally:
16
+ os.chdir(work_dir)
17
+
18
+
19
+ def _remove(directory):
20
+ shutil.rmtree(directory)
21
+ print('Removed directory "%s"' % directory)
22
+
23
+
24
+ def remove_directory(directory, silent):
25
+ if directory:
26
+ if silent:
27
+ _remove(directory)
28
+ else:
29
+ try:
30
+ confirm = raw_input('Remove comtypes cache directories? (y/n): ')
31
+ except NameError:
32
+ confirm = input('Remove comtypes cache directories? (y/n): ')
33
+ if confirm.lower() == 'y':
34
+ _remove(directory)
35
+ else:
36
+ print('Directory "%s" NOT removed' % directory)
37
+ return False
38
+ return True
39
+
40
+
41
+ if len(sys.argv) > 1 and "-y" in sys.argv[1:]:
42
+ silent = True
43
+ else:
44
+ silent = False
45
+
46
+
47
+ # First iteration may get folder with restricted rights.
48
+ # Second iteration always gets temp cache folder (writable for all).
49
+ directory = get_next_cache_dir()
50
+ removed = remove_directory(directory, silent)
51
+
52
+ if removed:
53
+ directory = get_next_cache_dir()
54
+
55
+ # do not request the second confirmation
56
+ # if the first folder was already removed
57
+ remove_directory(directory, silent=removed)
tars-env/Scripts/deactivate.bat ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ @echo off
2
+
3
+ if defined _OLD_VIRTUAL_PROMPT (
4
+ set "PROMPT=%_OLD_VIRTUAL_PROMPT%"
5
+ )
6
+ set _OLD_VIRTUAL_PROMPT=
7
+
8
+ if defined _OLD_VIRTUAL_PYTHONHOME (
9
+ set "PYTHONHOME=%_OLD_VIRTUAL_PYTHONHOME%"
10
+ set _OLD_VIRTUAL_PYTHONHOME=
11
+ )
12
+
13
+ if defined _OLD_VIRTUAL_PATH (
14
+ set "PATH=%_OLD_VIRTUAL_PATH%"
15
+ )
16
+
17
+ set _OLD_VIRTUAL_PATH=
18
+
19
+ set VIRTUAL_ENV=
20
+ set VIRTUAL_ENV_PROMPT=
21
+
22
+ :END
tars-env/Scripts/f2py.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/fonttools.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/gradio.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/httpx.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/huggingface-cli.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/jsonschema.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/markdown-it.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/normalizer.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/openai.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/pip.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/pip3.11.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/pip3.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/pyftmerge.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/pyftsubset.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/python.exe ADDED
Binary file (271 kB). View file
 
tars-env/Scripts/pythonw.exe ADDED
Binary file (259 kB). View file
 
tars-env/Scripts/pywin32_postinstall.py ADDED
@@ -0,0 +1,783 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # postinstall script for pywin32
2
+ #
3
+ # copies PyWinTypesxx.dll and PythonCOMxx.dll into the system directory,
4
+ # and creates a pth file
5
+ import glob
6
+ import os
7
+ import shutil
8
+ import sys
9
+ import sysconfig
10
+
11
+ try:
12
+ import winreg as winreg
13
+ except:
14
+ import winreg
15
+
16
+ # Send output somewhere so it can be found if necessary...
17
+ import tempfile
18
+
19
+ tee_f = open(os.path.join(tempfile.gettempdir(), "pywin32_postinstall.log"), "w")
20
+
21
+
22
+ class Tee:
23
+ def __init__(self, file):
24
+ self.f = file
25
+
26
+ def write(self, what):
27
+ if self.f is not None:
28
+ try:
29
+ self.f.write(what.replace("\n", "\r\n"))
30
+ except IOError:
31
+ pass
32
+ tee_f.write(what)
33
+
34
+ def flush(self):
35
+ if self.f is not None:
36
+ try:
37
+ self.f.flush()
38
+ except IOError:
39
+ pass
40
+ tee_f.flush()
41
+
42
+
43
+ # For some unknown reason, when running under bdist_wininst we will start up
44
+ # with sys.stdout as None but stderr is hooked up. This work-around allows
45
+ # bdist_wininst to see the output we write and display it at the end of
46
+ # the install.
47
+ if sys.stdout is None:
48
+ sys.stdout = sys.stderr
49
+
50
+ sys.stderr = Tee(sys.stderr)
51
+ sys.stdout = Tee(sys.stdout)
52
+
53
+ com_modules = [
54
+ # module_name, class_names
55
+ ("win32com.servers.interp", "Interpreter"),
56
+ ("win32com.servers.dictionary", "DictionaryPolicy"),
57
+ ("win32com.axscript.client.pyscript", "PyScript"),
58
+ ]
59
+
60
+ # Is this a 'silent' install - ie, avoid all dialogs.
61
+ # Different than 'verbose'
62
+ silent = 0
63
+
64
+ # Verbosity of output messages.
65
+ verbose = 1
66
+
67
+ root_key_name = "Software\\Python\\PythonCore\\" + sys.winver
68
+
69
+ try:
70
+ # When this script is run from inside the bdist_wininst installer,
71
+ # file_created() and directory_created() are additional builtin
72
+ # functions which write lines to Python23\pywin32-install.log. This is
73
+ # a list of actions for the uninstaller, the format is inspired by what
74
+ # the Wise installer also creates.
75
+ file_created
76
+ is_bdist_wininst = True
77
+ except NameError:
78
+ is_bdist_wininst = False # we know what it is not - but not what it is :)
79
+
80
+ def file_created(file):
81
+ pass
82
+
83
+ def directory_created(directory):
84
+ pass
85
+
86
+ def get_root_hkey():
87
+ try:
88
+ winreg.OpenKey(
89
+ winreg.HKEY_LOCAL_MACHINE, root_key_name, 0, winreg.KEY_CREATE_SUB_KEY
90
+ )
91
+ return winreg.HKEY_LOCAL_MACHINE
92
+ except OSError:
93
+ # Either not exist, or no permissions to create subkey means
94
+ # must be HKCU
95
+ return winreg.HKEY_CURRENT_USER
96
+
97
+
98
+ try:
99
+ create_shortcut
100
+ except NameError:
101
+ # Create a function with the same signature as create_shortcut provided
102
+ # by bdist_wininst
103
+ def create_shortcut(
104
+ path, description, filename, arguments="", workdir="", iconpath="", iconindex=0
105
+ ):
106
+ import pythoncom
107
+ from win32com.shell import shell
108
+
109
+ ilink = pythoncom.CoCreateInstance(
110
+ shell.CLSID_ShellLink,
111
+ None,
112
+ pythoncom.CLSCTX_INPROC_SERVER,
113
+ shell.IID_IShellLink,
114
+ )
115
+ ilink.SetPath(path)
116
+ ilink.SetDescription(description)
117
+ if arguments:
118
+ ilink.SetArguments(arguments)
119
+ if workdir:
120
+ ilink.SetWorkingDirectory(workdir)
121
+ if iconpath or iconindex:
122
+ ilink.SetIconLocation(iconpath, iconindex)
123
+ # now save it.
124
+ ipf = ilink.QueryInterface(pythoncom.IID_IPersistFile)
125
+ ipf.Save(filename, 0)
126
+
127
+ # Support the same list of "path names" as bdist_wininst.
128
+ def get_special_folder_path(path_name):
129
+ from win32com.shell import shell, shellcon
130
+
131
+ for maybe in """
132
+ CSIDL_COMMON_STARTMENU CSIDL_STARTMENU CSIDL_COMMON_APPDATA
133
+ CSIDL_LOCAL_APPDATA CSIDL_APPDATA CSIDL_COMMON_DESKTOPDIRECTORY
134
+ CSIDL_DESKTOPDIRECTORY CSIDL_COMMON_STARTUP CSIDL_STARTUP
135
+ CSIDL_COMMON_PROGRAMS CSIDL_PROGRAMS CSIDL_PROGRAM_FILES_COMMON
136
+ CSIDL_PROGRAM_FILES CSIDL_FONTS""".split():
137
+ if maybe == path_name:
138
+ csidl = getattr(shellcon, maybe)
139
+ return shell.SHGetSpecialFolderPath(0, csidl, False)
140
+ raise ValueError("%s is an unknown path ID" % (path_name,))
141
+
142
+
143
+ def CopyTo(desc, src, dest):
144
+ import win32api
145
+ import win32con
146
+
147
+ while 1:
148
+ try:
149
+ win32api.CopyFile(src, dest, 0)
150
+ return
151
+ except win32api.error as details:
152
+ if details.winerror == 5: # access denied - user not admin.
153
+ raise
154
+ if silent:
155
+ # Running silent mode - just re-raise the error.
156
+ raise
157
+ full_desc = (
158
+ "Error %s\n\n"
159
+ "If you have any Python applications running, "
160
+ "please close them now\nand select 'Retry'\n\n%s"
161
+ % (desc, details.strerror)
162
+ )
163
+ rc = win32api.MessageBox(
164
+ 0, full_desc, "Installation Error", win32con.MB_ABORTRETRYIGNORE
165
+ )
166
+ if rc == win32con.IDABORT:
167
+ raise
168
+ elif rc == win32con.IDIGNORE:
169
+ return
170
+ # else retry - around we go again.
171
+
172
+
173
+ # We need to import win32api to determine the Windows system directory,
174
+ # so we can copy our system files there - but importing win32api will
175
+ # load the pywintypes.dll already in the system directory preventing us
176
+ # from updating them!
177
+ # So, we pull the same trick pywintypes.py does, but it loads from
178
+ # our pywintypes_system32 directory.
179
+ def LoadSystemModule(lib_dir, modname):
180
+ # See if this is a debug build.
181
+ import importlib.machinery
182
+ import importlib.util
183
+
184
+ suffix = "_d" if "_d.pyd" in importlib.machinery.EXTENSION_SUFFIXES else ""
185
+ filename = "%s%d%d%s.dll" % (
186
+ modname,
187
+ sys.version_info[0],
188
+ sys.version_info[1],
189
+ suffix,
190
+ )
191
+ filename = os.path.join(lib_dir, "pywin32_system32", filename)
192
+ loader = importlib.machinery.ExtensionFileLoader(modname, filename)
193
+ spec = importlib.machinery.ModuleSpec(name=modname, loader=loader, origin=filename)
194
+ mod = importlib.util.module_from_spec(spec)
195
+ spec.loader.exec_module(mod)
196
+
197
+
198
+ def SetPyKeyVal(key_name, value_name, value):
199
+ root_hkey = get_root_hkey()
200
+ root_key = winreg.OpenKey(root_hkey, root_key_name)
201
+ try:
202
+ my_key = winreg.CreateKey(root_key, key_name)
203
+ try:
204
+ winreg.SetValueEx(my_key, value_name, 0, winreg.REG_SZ, value)
205
+ if verbose:
206
+ print("-> %s\\%s[%s]=%r" % (root_key_name, key_name, value_name, value))
207
+ finally:
208
+ my_key.Close()
209
+ finally:
210
+ root_key.Close()
211
+
212
+
213
+ def UnsetPyKeyVal(key_name, value_name, delete_key=False):
214
+ root_hkey = get_root_hkey()
215
+ root_key = winreg.OpenKey(root_hkey, root_key_name)
216
+ try:
217
+ my_key = winreg.OpenKey(root_key, key_name, 0, winreg.KEY_SET_VALUE)
218
+ try:
219
+ winreg.DeleteValue(my_key, value_name)
220
+ if verbose:
221
+ print("-> DELETE %s\\%s[%s]" % (root_key_name, key_name, value_name))
222
+ finally:
223
+ my_key.Close()
224
+ if delete_key:
225
+ winreg.DeleteKey(root_key, key_name)
226
+ if verbose:
227
+ print("-> DELETE %s\\%s" % (root_key_name, key_name))
228
+ except OSError as why:
229
+ winerror = getattr(why, "winerror", why.errno)
230
+ if winerror != 2: # file not found
231
+ raise
232
+ finally:
233
+ root_key.Close()
234
+
235
+
236
+ def RegisterCOMObjects(register=True):
237
+ import win32com.server.register
238
+
239
+ if register:
240
+ func = win32com.server.register.RegisterClasses
241
+ else:
242
+ func = win32com.server.register.UnregisterClasses
243
+ flags = {}
244
+ if not verbose:
245
+ flags["quiet"] = 1
246
+ for module, klass_name in com_modules:
247
+ __import__(module)
248
+ mod = sys.modules[module]
249
+ flags["finalize_register"] = getattr(mod, "DllRegisterServer", None)
250
+ flags["finalize_unregister"] = getattr(mod, "DllUnregisterServer", None)
251
+ klass = getattr(mod, klass_name)
252
+ func(klass, **flags)
253
+
254
+
255
+ def RegisterHelpFile(register=True, lib_dir=None):
256
+ if lib_dir is None:
257
+ lib_dir = sysconfig.get_paths()["platlib"]
258
+ if register:
259
+ # Register the .chm help file.
260
+ chm_file = os.path.join(lib_dir, "PyWin32.chm")
261
+ if os.path.isfile(chm_file):
262
+ # This isn't recursive, so if 'Help' doesn't exist, we croak
263
+ SetPyKeyVal("Help", None, None)
264
+ SetPyKeyVal("Help\\Pythonwin Reference", None, chm_file)
265
+ return chm_file
266
+ else:
267
+ print("NOTE: PyWin32.chm can not be located, so has not " "been registered")
268
+ else:
269
+ UnsetPyKeyVal("Help\\Pythonwin Reference", None, delete_key=True)
270
+ return None
271
+
272
+
273
+ def RegisterPythonwin(register=True, lib_dir=None):
274
+ """Add (or remove) Pythonwin to context menu for python scripts.
275
+ ??? Should probably also add Edit command for pys files also.
276
+ Also need to remove these keys on uninstall, but there's no function
277
+ like file_created to add registry entries to uninstall log ???
278
+ """
279
+ import os
280
+
281
+ if lib_dir is None:
282
+ lib_dir = sysconfig.get_paths()["platlib"]
283
+ classes_root = get_root_hkey()
284
+ ## Installer executable doesn't seem to pass anything to postinstall script indicating if it's a debug build,
285
+ pythonwin_exe = os.path.join(lib_dir, "Pythonwin", "Pythonwin.exe")
286
+ pythonwin_edit_command = pythonwin_exe + ' -edit "%1"'
287
+
288
+ keys_vals = [
289
+ (
290
+ "Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\Pythonwin.exe",
291
+ "",
292
+ pythonwin_exe,
293
+ ),
294
+ (
295
+ "Software\\Classes\\Python.File\\shell\\Edit with Pythonwin",
296
+ "command",
297
+ pythonwin_edit_command,
298
+ ),
299
+ (
300
+ "Software\\Classes\\Python.NoConFile\\shell\\Edit with Pythonwin",
301
+ "command",
302
+ pythonwin_edit_command,
303
+ ),
304
+ ]
305
+
306
+ try:
307
+ if register:
308
+ for key, sub_key, val in keys_vals:
309
+ ## Since winreg only uses the character Api functions, this can fail if Python
310
+ ## is installed to a path containing non-ascii characters
311
+ hkey = winreg.CreateKey(classes_root, key)
312
+ if sub_key:
313
+ hkey = winreg.CreateKey(hkey, sub_key)
314
+ winreg.SetValueEx(hkey, None, 0, winreg.REG_SZ, val)
315
+ hkey.Close()
316
+ else:
317
+ for key, sub_key, val in keys_vals:
318
+ try:
319
+ if sub_key:
320
+ hkey = winreg.OpenKey(classes_root, key)
321
+ winreg.DeleteKey(hkey, sub_key)
322
+ hkey.Close()
323
+ winreg.DeleteKey(classes_root, key)
324
+ except OSError as why:
325
+ winerror = getattr(why, "winerror", why.errno)
326
+ if winerror != 2: # file not found
327
+ raise
328
+ finally:
329
+ # tell windows about the change
330
+ from win32com.shell import shell, shellcon
331
+
332
+ shell.SHChangeNotify(
333
+ shellcon.SHCNE_ASSOCCHANGED, shellcon.SHCNF_IDLIST, None, None
334
+ )
335
+
336
+
337
+ def get_shortcuts_folder():
338
+ if get_root_hkey() == winreg.HKEY_LOCAL_MACHINE:
339
+ try:
340
+ fldr = get_special_folder_path("CSIDL_COMMON_PROGRAMS")
341
+ except OSError:
342
+ # No CSIDL_COMMON_PROGRAMS on this platform
343
+ fldr = get_special_folder_path("CSIDL_PROGRAMS")
344
+ else:
345
+ # non-admin install - always goes in this user's start menu.
346
+ fldr = get_special_folder_path("CSIDL_PROGRAMS")
347
+
348
+ try:
349
+ install_group = winreg.QueryValue(
350
+ get_root_hkey(), root_key_name + "\\InstallPath\\InstallGroup"
351
+ )
352
+ except OSError:
353
+ vi = sys.version_info
354
+ install_group = "Python %d.%d" % (vi[0], vi[1])
355
+ return os.path.join(fldr, install_group)
356
+
357
+
358
+ # Get the system directory, which may be the Wow64 directory if we are a 32bit
359
+ # python on a 64bit OS.
360
+ def get_system_dir():
361
+ import win32api # we assume this exists.
362
+
363
+ try:
364
+ import pythoncom
365
+ import win32process
366
+ from win32com.shell import shell, shellcon
367
+
368
+ try:
369
+ if win32process.IsWow64Process():
370
+ return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEMX86)
371
+ return shell.SHGetSpecialFolderPath(0, shellcon.CSIDL_SYSTEM)
372
+ except (pythoncom.com_error, win32process.error):
373
+ return win32api.GetSystemDirectory()
374
+ except ImportError:
375
+ return win32api.GetSystemDirectory()
376
+
377
+
378
+ def fixup_dbi():
379
+ # We used to have a dbi.pyd with our .pyd files, but now have a .py file.
380
+ # If the user didn't uninstall, they will find the .pyd which will cause
381
+ # problems - so handle that.
382
+ import win32api
383
+ import win32con
384
+
385
+ pyd_name = os.path.join(os.path.dirname(win32api.__file__), "dbi.pyd")
386
+ pyd_d_name = os.path.join(os.path.dirname(win32api.__file__), "dbi_d.pyd")
387
+ py_name = os.path.join(os.path.dirname(win32con.__file__), "dbi.py")
388
+ for this_pyd in (pyd_name, pyd_d_name):
389
+ this_dest = this_pyd + ".old"
390
+ if os.path.isfile(this_pyd) and os.path.isfile(py_name):
391
+ try:
392
+ if os.path.isfile(this_dest):
393
+ print(
394
+ "Old dbi '%s' already exists - deleting '%s'"
395
+ % (this_dest, this_pyd)
396
+ )
397
+ os.remove(this_pyd)
398
+ else:
399
+ os.rename(this_pyd, this_dest)
400
+ print("renamed '%s'->'%s.old'" % (this_pyd, this_pyd))
401
+ file_created(this_pyd + ".old")
402
+ except os.error as exc:
403
+ print("FAILED to rename '%s': %s" % (this_pyd, exc))
404
+
405
+
406
+ def install(lib_dir):
407
+ import traceback
408
+
409
+ # The .pth file is now installed as a regular file.
410
+ # Create the .pth file in the site-packages dir, and use only relative paths
411
+ # We used to write a .pth directly to sys.prefix - clobber it.
412
+ if os.path.isfile(os.path.join(sys.prefix, "pywin32.pth")):
413
+ os.unlink(os.path.join(sys.prefix, "pywin32.pth"))
414
+ # The .pth may be new and therefore not loaded in this session.
415
+ # Setup the paths just in case.
416
+ for name in "win32 win32\\lib Pythonwin".split():
417
+ sys.path.append(os.path.join(lib_dir, name))
418
+ # It is possible people with old versions installed with still have
419
+ # pywintypes and pythoncom registered. We no longer need this, and stale
420
+ # entries hurt us.
421
+ for name in "pythoncom pywintypes".split():
422
+ keyname = "Software\\Python\\PythonCore\\" + sys.winver + "\\Modules\\" + name
423
+ for root in winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER:
424
+ try:
425
+ winreg.DeleteKey(root, keyname + "\\Debug")
426
+ except WindowsError:
427
+ pass
428
+ try:
429
+ winreg.DeleteKey(root, keyname)
430
+ except WindowsError:
431
+ pass
432
+ LoadSystemModule(lib_dir, "pywintypes")
433
+ LoadSystemModule(lib_dir, "pythoncom")
434
+ import win32api
435
+
436
+ # and now we can get the system directory:
437
+ files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
438
+ if not files:
439
+ raise RuntimeError("No system files to copy!!")
440
+ # Try the system32 directory first - if that fails due to "access denied",
441
+ # it implies a non-admin user, and we use sys.prefix
442
+ for dest_dir in [get_system_dir(), sys.prefix]:
443
+ # and copy some files over there
444
+ worked = 0
445
+ try:
446
+ for fname in files:
447
+ base = os.path.basename(fname)
448
+ dst = os.path.join(dest_dir, base)
449
+ CopyTo("installing %s" % base, fname, dst)
450
+ if verbose:
451
+ print("Copied %s to %s" % (base, dst))
452
+ # Register the files with the uninstaller
453
+ file_created(dst)
454
+ worked = 1
455
+ # Nuke any other versions that may exist - having
456
+ # duplicates causes major headaches.
457
+ bad_dest_dirs = [
458
+ os.path.join(sys.prefix, "Library\\bin"),
459
+ os.path.join(sys.prefix, "Lib\\site-packages\\win32"),
460
+ ]
461
+ if dest_dir != sys.prefix:
462
+ bad_dest_dirs.append(sys.prefix)
463
+ for bad_dest_dir in bad_dest_dirs:
464
+ bad_fname = os.path.join(bad_dest_dir, base)
465
+ if os.path.exists(bad_fname):
466
+ # let exceptions go here - delete must succeed
467
+ os.unlink(bad_fname)
468
+ if worked:
469
+ break
470
+ except win32api.error as details:
471
+ if details.winerror == 5:
472
+ # access denied - user not admin - try sys.prefix dir,
473
+ # but first check that a version doesn't already exist
474
+ # in that place - otherwise that one will still get used!
475
+ if os.path.exists(dst):
476
+ msg = (
477
+ "The file '%s' exists, but can not be replaced "
478
+ "due to insufficient permissions. You must "
479
+ "reinstall this software as an Administrator" % dst
480
+ )
481
+ print(msg)
482
+ raise RuntimeError(msg)
483
+ continue
484
+ raise
485
+ else:
486
+ raise RuntimeError(
487
+ "You don't have enough permissions to install the system files"
488
+ )
489
+
490
+ # Pythonwin 'compiles' config files - record them for uninstall.
491
+ pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin")
492
+ for fname in glob.glob(os.path.join(pywin_dir, "*.cfg")):
493
+ file_created(fname[:-1] + "c") # .cfg->.cfc
494
+
495
+ # Register our demo COM objects.
496
+ try:
497
+ try:
498
+ RegisterCOMObjects()
499
+ except win32api.error as details:
500
+ if details.winerror != 5: # ERROR_ACCESS_DENIED
501
+ raise
502
+ print("You do not have the permissions to install COM objects.")
503
+ print("The sample COM objects were not registered.")
504
+ except Exception:
505
+ print("FAILED to register the Python COM objects")
506
+ traceback.print_exc()
507
+
508
+ # There may be no main Python key in HKCU if, eg, an admin installed
509
+ # python itself.
510
+ winreg.CreateKey(get_root_hkey(), root_key_name)
511
+
512
+ chm_file = None
513
+ try:
514
+ chm_file = RegisterHelpFile(True, lib_dir)
515
+ except Exception:
516
+ print("Failed to register help file")
517
+ traceback.print_exc()
518
+ else:
519
+ if verbose:
520
+ print("Registered help file")
521
+
522
+ # misc other fixups.
523
+ fixup_dbi()
524
+
525
+ # Register Pythonwin in context menu
526
+ try:
527
+ RegisterPythonwin(True, lib_dir)
528
+ except Exception:
529
+ print("Failed to register pythonwin as editor")
530
+ traceback.print_exc()
531
+ else:
532
+ if verbose:
533
+ print("Pythonwin has been registered in context menu")
534
+
535
+ # Create the win32com\gen_py directory.
536
+ make_dir = os.path.join(lib_dir, "win32com", "gen_py")
537
+ if not os.path.isdir(make_dir):
538
+ if verbose:
539
+ print("Creating directory %s" % (make_dir,))
540
+ directory_created(make_dir)
541
+ os.mkdir(make_dir)
542
+
543
+ try:
544
+ # create shortcuts
545
+ # CSIDL_COMMON_PROGRAMS only available works on NT/2000/XP, and
546
+ # will fail there if the user has no admin rights.
547
+ fldr = get_shortcuts_folder()
548
+ # If the group doesn't exist, then we don't make shortcuts - its
549
+ # possible that this isn't a "normal" install.
550
+ if os.path.isdir(fldr):
551
+ dst = os.path.join(fldr, "PythonWin.lnk")
552
+ create_shortcut(
553
+ os.path.join(lib_dir, "Pythonwin\\Pythonwin.exe"),
554
+ "The Pythonwin IDE",
555
+ dst,
556
+ "",
557
+ sys.prefix,
558
+ )
559
+ file_created(dst)
560
+ if verbose:
561
+ print("Shortcut for Pythonwin created")
562
+ # And the docs.
563
+ if chm_file:
564
+ dst = os.path.join(fldr, "Python for Windows Documentation.lnk")
565
+ doc = "Documentation for the PyWin32 extensions"
566
+ create_shortcut(chm_file, doc, dst)
567
+ file_created(dst)
568
+ if verbose:
569
+ print("Shortcut to documentation created")
570
+ else:
571
+ if verbose:
572
+ print("Can't install shortcuts - %r is not a folder" % (fldr,))
573
+ except Exception as details:
574
+ print(details)
575
+
576
+ # importing win32com.client ensures the gen_py dir created - not strictly
577
+ # necessary to do now, but this makes the installation "complete"
578
+ try:
579
+ import win32com.client # noqa
580
+ except ImportError:
581
+ # Don't let this error sound fatal
582
+ pass
583
+ print("The pywin32 extensions were successfully installed.")
584
+
585
+ if is_bdist_wininst:
586
+ # Open a web page with info about the .exe installers being deprecated.
587
+ import webbrowser
588
+
589
+ try:
590
+ webbrowser.open("https://mhammond.github.io/pywin32_installers.html")
591
+ except webbrowser.Error:
592
+ print("Please visit https://mhammond.github.io/pywin32_installers.html")
593
+
594
+
595
+ def uninstall(lib_dir):
596
+ # First ensure our system modules are loaded from pywin32_system, so
597
+ # we can remove the ones we copied...
598
+ LoadSystemModule(lib_dir, "pywintypes")
599
+ LoadSystemModule(lib_dir, "pythoncom")
600
+
601
+ try:
602
+ RegisterCOMObjects(False)
603
+ except Exception as why:
604
+ print("Failed to unregister COM objects: %s" % (why,))
605
+
606
+ try:
607
+ RegisterHelpFile(False, lib_dir)
608
+ except Exception as why:
609
+ print("Failed to unregister help file: %s" % (why,))
610
+ else:
611
+ if verbose:
612
+ print("Unregistered help file")
613
+
614
+ try:
615
+ RegisterPythonwin(False, lib_dir)
616
+ except Exception as why:
617
+ print("Failed to unregister Pythonwin: %s" % (why,))
618
+ else:
619
+ if verbose:
620
+ print("Unregistered Pythonwin")
621
+
622
+ try:
623
+ # remove gen_py directory.
624
+ gen_dir = os.path.join(lib_dir, "win32com", "gen_py")
625
+ if os.path.isdir(gen_dir):
626
+ shutil.rmtree(gen_dir)
627
+ if verbose:
628
+ print("Removed directory %s" % (gen_dir,))
629
+
630
+ # Remove pythonwin compiled "config" files.
631
+ pywin_dir = os.path.join(lib_dir, "Pythonwin", "pywin")
632
+ for fname in glob.glob(os.path.join(pywin_dir, "*.cfc")):
633
+ os.remove(fname)
634
+
635
+ # The dbi.pyd.old files we may have created.
636
+ try:
637
+ os.remove(os.path.join(lib_dir, "win32", "dbi.pyd.old"))
638
+ except os.error:
639
+ pass
640
+ try:
641
+ os.remove(os.path.join(lib_dir, "win32", "dbi_d.pyd.old"))
642
+ except os.error:
643
+ pass
644
+
645
+ except Exception as why:
646
+ print("Failed to remove misc files: %s" % (why,))
647
+
648
+ try:
649
+ fldr = get_shortcuts_folder()
650
+ for link in ("PythonWin.lnk", "Python for Windows Documentation.lnk"):
651
+ fqlink = os.path.join(fldr, link)
652
+ if os.path.isfile(fqlink):
653
+ os.remove(fqlink)
654
+ if verbose:
655
+ print("Removed %s" % (link,))
656
+ except Exception as why:
657
+ print("Failed to remove shortcuts: %s" % (why,))
658
+ # Now remove the system32 files.
659
+ files = glob.glob(os.path.join(lib_dir, "pywin32_system32\\*.*"))
660
+ # Try the system32 directory first - if that fails due to "access denied",
661
+ # it implies a non-admin user, and we use sys.prefix
662
+ try:
663
+ for dest_dir in [get_system_dir(), sys.prefix]:
664
+ # and copy some files over there
665
+ worked = 0
666
+ for fname in files:
667
+ base = os.path.basename(fname)
668
+ dst = os.path.join(dest_dir, base)
669
+ if os.path.isfile(dst):
670
+ try:
671
+ os.remove(dst)
672
+ worked = 1
673
+ if verbose:
674
+ print("Removed file %s" % (dst))
675
+ except Exception:
676
+ print("FAILED to remove %s" % (dst,))
677
+ if worked:
678
+ break
679
+ except Exception as why:
680
+ print("FAILED to remove system files: %s" % (why,))
681
+
682
+
683
+ # NOTE: If this script is run from inside the bdist_wininst created
684
+ # binary installer or uninstaller, the command line args are either
685
+ # '-install' or '-remove'.
686
+
687
+ # Important: From inside the binary installer this script MUST NOT
688
+ # call sys.exit() or raise SystemExit, otherwise not only this script
689
+ # but also the installer will terminate! (Is there a way to prevent
690
+ # this from the bdist_wininst C code?)
691
+
692
+
693
+ def verify_destination(location):
694
+ if not os.path.isdir(location):
695
+ raise argparse.ArgumentTypeError('Path "{}" does not exist!'.format(location))
696
+ return location
697
+
698
+
699
+ def main():
700
+ import argparse
701
+
702
+ parser = argparse.ArgumentParser(
703
+ formatter_class=argparse.RawDescriptionHelpFormatter,
704
+ description="""A post-install script for the pywin32 extensions.
705
+
706
+ * Typical usage:
707
+
708
+ > python pywin32_postinstall.py -install
709
+
710
+ If you installed pywin32 via a .exe installer, this should be run
711
+ automatically after installation, but if it fails you can run it again.
712
+
713
+ If you installed pywin32 via PIP, you almost certainly need to run this to
714
+ setup the environment correctly.
715
+
716
+ Execute with script with a '-install' parameter, to ensure the environment
717
+ is setup correctly.
718
+ """,
719
+ )
720
+ parser.add_argument(
721
+ "-install",
722
+ default=False,
723
+ action="store_true",
724
+ help="Configure the Python environment correctly for pywin32.",
725
+ )
726
+ parser.add_argument(
727
+ "-remove",
728
+ default=False,
729
+ action="store_true",
730
+ help="Try and remove everything that was installed or copied.",
731
+ )
732
+ parser.add_argument(
733
+ "-wait",
734
+ type=int,
735
+ help="Wait for the specified process to terminate before starting.",
736
+ )
737
+ parser.add_argument(
738
+ "-silent",
739
+ default=False,
740
+ action="store_true",
741
+ help='Don\'t display the "Abort/Retry/Ignore" dialog for files in use.',
742
+ )
743
+ parser.add_argument(
744
+ "-quiet",
745
+ default=False,
746
+ action="store_true",
747
+ help="Don't display progress messages.",
748
+ )
749
+ parser.add_argument(
750
+ "-destination",
751
+ default=sysconfig.get_paths()["platlib"],
752
+ type=verify_destination,
753
+ help="Location of the PyWin32 installation",
754
+ )
755
+
756
+ args = parser.parse_args()
757
+
758
+ if not args.quiet:
759
+ print("Parsed arguments are: {}".format(args))
760
+
761
+ if not args.install ^ args.remove:
762
+ parser.error("You need to either choose to -install or -remove!")
763
+
764
+ if args.wait is not None:
765
+ try:
766
+ os.waitpid(args.wait, 0)
767
+ except os.error:
768
+ # child already dead
769
+ pass
770
+
771
+ silent = args.silent
772
+ verbose = not args.quiet
773
+
774
+ if args.install:
775
+ install(args.destination)
776
+
777
+ if args.remove:
778
+ if not is_bdist_wininst:
779
+ uninstall(args.destination)
780
+
781
+
782
+ if __name__ == "__main__":
783
+ main()
tars-env/Scripts/pywin32_testall.py ADDED
@@ -0,0 +1,124 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """A test runner for pywin32"""
2
+ import os
3
+ import site
4
+ import subprocess
5
+ import sys
6
+
7
+ # locate the dirs based on where this script is - it may be either in the
8
+ # source tree, or in an installed Python 'Scripts' tree.
9
+ this_dir = os.path.dirname(__file__)
10
+ site_packages = [
11
+ site.getusersitepackages(),
12
+ ] + site.getsitepackages()
13
+
14
+ failures = []
15
+
16
+
17
+ # Run a test using subprocess and wait for the result.
18
+ # If we get an returncode != 0, we know that there was an error, but we don't
19
+ # abort immediately - we run as many tests as we can.
20
+ def run_test(script, cmdline_extras):
21
+ dirname, scriptname = os.path.split(script)
22
+ # some tests prefer to be run from their directory.
23
+ cmd = [sys.executable, "-u", scriptname] + cmdline_extras
24
+ print("--- Running '%s' ---" % script)
25
+ sys.stdout.flush()
26
+ result = subprocess.run(cmd, check=False, cwd=dirname)
27
+ print("*** Test script '%s' exited with %s" % (script, result.returncode))
28
+ sys.stdout.flush()
29
+ if result.returncode:
30
+ failures.append(script)
31
+
32
+
33
+ def find_and_run(possible_locations, extras):
34
+ for maybe in possible_locations:
35
+ if os.path.isfile(maybe):
36
+ run_test(maybe, extras)
37
+ break
38
+ else:
39
+ raise RuntimeError(
40
+ "Failed to locate a test script in one of %s" % possible_locations
41
+ )
42
+
43
+
44
+ def main():
45
+ import argparse
46
+
47
+ code_directories = [this_dir] + site_packages
48
+
49
+ parser = argparse.ArgumentParser(
50
+ description="A script to trigger tests in all subprojects of PyWin32."
51
+ )
52
+ parser.add_argument(
53
+ "-no-user-interaction",
54
+ default=False,
55
+ action="store_true",
56
+ help="(This is now the default - use `-user-interaction` to include them)",
57
+ )
58
+
59
+ parser.add_argument(
60
+ "-user-interaction",
61
+ action="store_true",
62
+ help="Include tests which require user interaction",
63
+ )
64
+
65
+ parser.add_argument(
66
+ "-skip-adodbapi",
67
+ default=False,
68
+ action="store_true",
69
+ help="Skip the adodbapi tests; useful for CI where there's no provider",
70
+ )
71
+
72
+ args, remains = parser.parse_known_args()
73
+
74
+ # win32, win32ui / Pythonwin
75
+
76
+ extras = []
77
+ if args.user_interaction:
78
+ extras += ["-user-interaction"]
79
+ extras.extend(remains)
80
+ scripts = [
81
+ "win32/test/testall.py",
82
+ "Pythonwin/pywin/test/all.py",
83
+ ]
84
+ for script in scripts:
85
+ maybes = [os.path.join(directory, script) for directory in code_directories]
86
+ find_and_run(maybes, extras)
87
+
88
+ # win32com
89
+ maybes = [
90
+ os.path.join(directory, "win32com", "test", "testall.py")
91
+ for directory in [
92
+ os.path.join(this_dir, "com"),
93
+ ]
94
+ + site_packages
95
+ ]
96
+ extras = remains + ["1"] # only run "level 1" tests in CI
97
+ find_and_run(maybes, extras)
98
+
99
+ # adodbapi
100
+ if not args.skip_adodbapi:
101
+ maybes = [
102
+ os.path.join(directory, "adodbapi", "test", "adodbapitest.py")
103
+ for directory in code_directories
104
+ ]
105
+ find_and_run(maybes, remains)
106
+ # This script has a hard-coded sql server name in it, (and markh typically
107
+ # doesn't have a different server to test on) but there is now supposed to be a server out there on the Internet
108
+ # just to run these tests, so try it...
109
+ maybes = [
110
+ os.path.join(directory, "adodbapi", "test", "test_adodbapi_dbapi20.py")
111
+ for directory in code_directories
112
+ ]
113
+ find_and_run(maybes, remains)
114
+
115
+ if failures:
116
+ print("The following scripts failed")
117
+ for failure in failures:
118
+ print(">", failure)
119
+ sys.exit(1)
120
+ print("All tests passed \\o/")
121
+
122
+
123
+ if __name__ == "__main__":
124
+ main()
tars-env/Scripts/tqdm.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/ttx.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/upload_theme.exe ADDED
Binary file (108 kB). View file
 
tars-env/Scripts/uvicorn.exe ADDED
Binary file (108 kB). View file
 
tars-env/pyvenv.cfg ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ home = C:\Users\Frank\AppData\Local\Programs\Python\Python311
2
+ include-system-site-packages = false
3
+ version = 3.11.3
4
+ executable = C:\Users\Frank\AppData\Local\Programs\Python\Python311\python.exe
5
+ command = C:\Users\Frank\AppData\Local\Programs\Python\Python311\python.exe -m venv C:\Users\Frank\TARS\tars-env
tars-env/share/man/man1/ttx.1 ADDED
@@ -0,0 +1,225 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .Dd May 18, 2004
2
+ .\" ttx is not specific to any OS, but contrary to what groff_mdoc(7)
3
+ .\" seems to imply, entirely omitting the .Os macro causes 'BSD' to
4
+ .\" be used, so I give a zero-width space as its argument.
5
+ .Os \&
6
+ .\" The "FontTools Manual" argument apparently has no effect in
7
+ .\" groff 1.18.1. I think it is a bug in the -mdoc groff package.
8
+ .Dt TTX 1 "FontTools Manual"
9
+ .Sh NAME
10
+ .Nm ttx
11
+ .Nd tool for manipulating TrueType and OpenType fonts
12
+ .Sh SYNOPSIS
13
+ .Nm
14
+ .Bk
15
+ .Op Ar option ...
16
+ .Ek
17
+ .Bk
18
+ .Ar file ...
19
+ .Ek
20
+ .Sh DESCRIPTION
21
+ .Nm
22
+ is a tool for manipulating TrueType and OpenType fonts. It can convert
23
+ TrueType and OpenType fonts to and from an
24
+ .Tn XML Ns -based format called
25
+ .Tn TTX .
26
+ .Tn TTX
27
+ files have a
28
+ .Ql .ttx
29
+ extension.
30
+ .Pp
31
+ For each
32
+ .Ar file
33
+ argument it is given,
34
+ .Nm
35
+ detects whether it is a
36
+ .Ql .ttf ,
37
+ .Ql .otf
38
+ or
39
+ .Ql .ttx
40
+ file and acts accordingly: if it is a
41
+ .Ql .ttf
42
+ or
43
+ .Ql .otf
44
+ file, it generates a
45
+ .Ql .ttx
46
+ file; if it is a
47
+ .Ql .ttx
48
+ file, it generates a
49
+ .Ql .ttf
50
+ or
51
+ .Ql .otf
52
+ file.
53
+ .Pp
54
+ By default, every output file is created in the same directory as the
55
+ corresponding input file and with the same name except for the
56
+ extension, which is substituted appropriately.
57
+ .Nm
58
+ never overwrites existing files; if necessary, it appends a suffix to
59
+ the output file name before the extension, as in
60
+ .Pa Arial#1.ttf .
61
+ .Ss "General options"
62
+ .Bl -tag -width ".Fl t Ar table"
63
+ .It Fl h
64
+ Display usage information.
65
+ .It Fl d Ar dir
66
+ Write the output files to directory
67
+ .Ar dir
68
+ instead of writing every output file to the same directory as the
69
+ corresponding input file.
70
+ .It Fl o Ar file
71
+ Write the output to
72
+ .Ar file
73
+ instead of writing it to the same directory as the
74
+ corresponding input file.
75
+ .It Fl v
76
+ Be verbose. Write more messages to the standard output describing what
77
+ is being done.
78
+ .It Fl a
79
+ Allow virtual glyphs ID's on compile or decompile.
80
+ .El
81
+ .Ss "Dump options"
82
+ The following options control the process of dumping font files
83
+ (TrueType or OpenType) to
84
+ .Tn TTX
85
+ files.
86
+ .Bl -tag -width ".Fl t Ar table"
87
+ .It Fl l
88
+ List table information. Instead of dumping the font to a
89
+ .Tn TTX
90
+ file, display minimal information about each table.
91
+ .It Fl t Ar table
92
+ Dump table
93
+ .Ar table .
94
+ This option may be given multiple times to dump several tables at
95
+ once. When not specified, all tables are dumped.
96
+ .It Fl x Ar table
97
+ Exclude table
98
+ .Ar table
99
+ from the list of tables to dump. This option may be given multiple
100
+ times to exclude several tables from the dump. The
101
+ .Fl t
102
+ and
103
+ .Fl x
104
+ options are mutually exclusive.
105
+ .It Fl s
106
+ Split tables. Dump each table to a separate
107
+ .Tn TTX
108
+ file and write (under the name that would have been used for the output
109
+ file if the
110
+ .Fl s
111
+ option had not been given) one small
112
+ .Tn TTX
113
+ file containing references to the individual table dump files. This
114
+ file can be used as input to
115
+ .Nm
116
+ as long as the referenced files can be found in the same directory.
117
+ .It Fl i
118
+ .\" XXX: I suppose OpenType programs (exist and) are also affected.
119
+ Don't disassemble TrueType instructions. When this option is specified,
120
+ all TrueType programs (glyph programs, the font program and the
121
+ pre-program) are written to the
122
+ .Tn TTX
123
+ file as hexadecimal data instead of
124
+ assembly. This saves some time and results in smaller
125
+ .Tn TTX
126
+ files.
127
+ .It Fl y Ar n
128
+ When decompiling a TrueType Collection (TTC) file,
129
+ decompile font number
130
+ .Ar n ,
131
+ starting from 0.
132
+ .El
133
+ .Ss "Compilation options"
134
+ The following options control the process of compiling
135
+ .Tn TTX
136
+ files into font files (TrueType or OpenType):
137
+ .Bl -tag -width ".Fl t Ar table"
138
+ .It Fl m Ar fontfile
139
+ Merge the input
140
+ .Tn TTX
141
+ file
142
+ .Ar file
143
+ with
144
+ .Ar fontfile .
145
+ No more than one
146
+ .Ar file
147
+ argument can be specified when this option is used.
148
+ .It Fl b
149
+ Don't recalculate glyph bounding boxes. Use the values in the
150
+ .Tn TTX
151
+ file as is.
152
+ .El
153
+ .Sh "THE TTX FILE FORMAT"
154
+ You can find some information about the
155
+ .Tn TTX
156
+ file format in
157
+ .Pa documentation.html .
158
+ In particular, you will find in that file the list of tables understood by
159
+ .Nm
160
+ and the relations between TrueType GlyphIDs and the glyph names used in
161
+ .Tn TTX
162
+ files.
163
+ .Sh EXAMPLES
164
+ In the following examples, all files are read from and written to the
165
+ current directory. Additionally, the name given for the output file
166
+ assumes in every case that it did not exist before
167
+ .Nm
168
+ was invoked.
169
+ .Pp
170
+ Dump the TrueType font contained in
171
+ .Pa FreeSans.ttf
172
+ to
173
+ .Pa FreeSans.ttx :
174
+ .Pp
175
+ .Dl ttx FreeSans.ttf
176
+ .Pp
177
+ Compile
178
+ .Pa MyFont.ttx
179
+ into a TrueType or OpenType font file:
180
+ .Pp
181
+ .Dl ttx MyFont.ttx
182
+ .Pp
183
+ List the tables in
184
+ .Pa FreeSans.ttf
185
+ along with some information:
186
+ .Pp
187
+ .Dl ttx -l FreeSans.ttf
188
+ .Pp
189
+ Dump the
190
+ .Sq cmap
191
+ table from
192
+ .Pa FreeSans.ttf
193
+ to
194
+ .Pa FreeSans.ttx :
195
+ .Pp
196
+ .Dl ttx -t cmap FreeSans.ttf
197
+ .Sh NOTES
198
+ On MS\-Windows and MacOS,
199
+ .Nm
200
+ is available as a graphical application to which files can be dropped.
201
+ .Sh SEE ALSO
202
+ .Pa documentation.html
203
+ .Pp
204
+ .Xr fontforge 1 ,
205
+ .Xr ftinfo 1 ,
206
+ .Xr gfontview 1 ,
207
+ .Xr xmbdfed 1 ,
208
+ .Xr Font::TTF 3pm
209
+ .Sh AUTHORS
210
+ .Nm
211
+ was written by
212
+ .An -nosplit
213
+ .An "Just van Rossum" Aq just@letterror.com .
214
+ .Pp
215
+ This manual page was written by
216
+ .An "Florent Rougon" Aq f.rougon@free.fr
217
+ for the Debian GNU/Linux system based on the existing FontTools
218
+ documentation. It may be freely used, modified and distributed without
219
+ restrictions.
220
+ .\" For Emacs:
221
+ .\" Local Variables:
222
+ .\" fill-column: 72
223
+ .\" sentence-end: "[.?!][]\"')}]*\\($\\| $\\| \\| \\)[ \n]*"
224
+ .\" sentence-end-double-space: t
225
+ .\" End: