You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Activate.ps1 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. <#
  2. .Synopsis
  3. Activate a Python virtual environment for the current Powershell session.
  4. .Description
  5. Pushes the python executable for a virtual environment to the front of the
  6. $Env:PATH environment variable and sets the prompt to signify that you are
  7. in a Python virtual environment. Makes use of the command line switches as
  8. well as the `pyvenv.cfg` file values present in the virtual environment.
  9. .Parameter VenvDir
  10. Path to the directory that contains the virtual environment to activate. The
  11. default value for this is the parent of the directory that the Activate.ps1
  12. script is located within.
  13. .Parameter Prompt
  14. The prompt prefix to display when this virtual environment is activated. By
  15. default, this prompt is the name of the virtual environment folder (VenvDir)
  16. surrounded by parentheses and followed by a single space (ie. '(.venv) ').
  17. .Example
  18. Activate.ps1
  19. Activates the Python virtual environment that contains the Activate.ps1 script.
  20. .Example
  21. Activate.ps1 -Verbose
  22. Activates the Python virtual environment that contains the Activate.ps1 script,
  23. and shows extra information about the activation as it executes.
  24. .Example
  25. Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
  26. Activates the Python virtual environment located in the specified location.
  27. .Example
  28. Activate.ps1 -Prompt "MyPython"
  29. Activates the Python virtual environment that contains the Activate.ps1 script,
  30. and prefixes the current prompt with the specified string (surrounded in
  31. parentheses) while the virtual environment is active.
  32. #>
  33. Param(
  34. [Parameter(Mandatory = $false)]
  35. [String]
  36. $VenvDir,
  37. [Parameter(Mandatory = $false)]
  38. [String]
  39. $Prompt
  40. )
  41. <# Function declarations --------------------------------------------------- #>
  42. <#
  43. .Synopsis
  44. Remove all shell session elements added by the Activate script, including the
  45. addition of the virtual environment's Python executable from the beginning of
  46. the PATH variable.
  47. .Parameter NonDestructive
  48. If present, do not remove this function from the global namespace for the
  49. session.
  50. #>
  51. function global:deactivate ([switch]$NonDestructive) {
  52. # Revert to original values
  53. # The prior prompt:
  54. if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
  55. Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
  56. Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
  57. }
  58. # The prior PYTHONHOME:
  59. if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
  60. Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
  61. Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
  62. }
  63. # The prior PATH:
  64. if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
  65. Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
  66. Remove-Item -Path Env:_OLD_VIRTUAL_PATH
  67. }
  68. # Just remove the VIRTUAL_ENV altogether:
  69. if (Test-Path -Path Env:VIRTUAL_ENV) {
  70. Remove-Item -Path env:VIRTUAL_ENV
  71. }
  72. # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
  73. if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
  74. Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
  75. }
  76. # Leave deactivate function in the global namespace if requested:
  77. if (-not $NonDestructive) {
  78. Remove-Item -Path function:deactivate
  79. }
  80. }
  81. <#
  82. .Description
  83. Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
  84. given folder, and returns them in a map.
  85. For each line in the pyvenv.cfg file, if that line can be parsed into exactly
  86. two strings separated by `=` (with any amount of whitespace surrounding the =)
  87. then it is considered a `key = value` line. The left hand string is the key,
  88. the right hand is the value.
  89. If the value starts with a `'` or a `"` then the first and last character is
  90. stripped from the value before being captured.
  91. .Parameter ConfigDir
  92. Path to the directory that contains the `pyvenv.cfg` file.
  93. #>
  94. function Get-PyVenvConfig(
  95. [String]
  96. $ConfigDir
  97. ) {
  98. Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
  99. # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
  100. $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
  101. # An empty map will be returned if no config file is found.
  102. $pyvenvConfig = @{ }
  103. if ($pyvenvConfigPath) {
  104. Write-Verbose "File exists, parse `key = value` lines"
  105. $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
  106. $pyvenvConfigContent | ForEach-Object {
  107. $keyval = $PSItem -split "\s*=\s*", 2
  108. if ($keyval[0] -and $keyval[1]) {
  109. $val = $keyval[1]
  110. # Remove extraneous quotations around a string value.
  111. if ("'""".Contains($val.Substring(0,1))) {
  112. $val = $val.Substring(1, $val.Length - 2)
  113. }
  114. $pyvenvConfig[$keyval[0]] = $val
  115. Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
  116. }
  117. }
  118. }
  119. return $pyvenvConfig
  120. }
  121. <# Begin Activate script --------------------------------------------------- #>
  122. # Determine the containing directory of this script
  123. $VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
  124. $VenvExecDir = Get-Item -Path $VenvExecPath
  125. Write-Verbose "Activation script is located in path: '$VenvExecPath'"
  126. Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
  127. Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
  128. # Set values required in priority: CmdLine, ConfigFile, Default
  129. # First, get the location of the virtual environment, it might not be
  130. # VenvExecDir if specified on the command line.
  131. if ($VenvDir) {
  132. Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
  133. } else {
  134. Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
  135. $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
  136. $VenvDir = $VenvDir.Insert($VenvDir.Length, "/")
  137. Write-Verbose "VenvDir=$VenvDir"
  138. }
  139. # Next, read the `pyvenv.cfg` file to determine any required value such
  140. # as `prompt`.
  141. $pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
  142. # Next, set the prompt from the command line, or the config file, or
  143. # just use the name of the virtual environment folder.
  144. if ($Prompt) {
  145. Write-Verbose "Prompt specified as argument, using '$Prompt'"
  146. } else {
  147. Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
  148. if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
  149. Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
  150. $Prompt = $pyvenvCfg['prompt'];
  151. }
  152. else {
  153. Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)"
  154. Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
  155. $Prompt = Split-Path -Path $venvDir -Leaf
  156. }
  157. }
  158. Write-Verbose "Prompt = '$Prompt'"
  159. Write-Verbose "VenvDir='$VenvDir'"
  160. # Deactivate any currently active virtual environment, but leave the
  161. # deactivate function in place.
  162. deactivate -nondestructive
  163. # Now set the environment variable VIRTUAL_ENV, used by many tools to determine
  164. # that there is an activated venv.
  165. $env:VIRTUAL_ENV = $VenvDir
  166. if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
  167. Write-Verbose "Setting prompt to '$Prompt'"
  168. # Set the prompt to include the env name
  169. # Make sure _OLD_VIRTUAL_PROMPT is global
  170. function global:_OLD_VIRTUAL_PROMPT { "" }
  171. Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
  172. New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
  173. function global:prompt {
  174. Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
  175. _OLD_VIRTUAL_PROMPT
  176. }
  177. }
  178. # Clear PYTHONHOME
  179. if (Test-Path -Path Env:PYTHONHOME) {
  180. Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
  181. Remove-Item -Path Env:PYTHONHOME
  182. }
  183. # Add the venv to the PATH
  184. Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
  185. $Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
  186. # SIG # Begin signature block
  187. # MIIaVgYJKoZIhvcNAQcCoIIaRzCCGkMCAQExDzANBglghkgBZQMEAgEFADB5Bgor
  188. # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
  189. # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCDq2sTPEIJ8JE5n
  190. # msRhacE7nmlm6ccumO/BwpdDqNYl5KCCFBgwggPuMIIDV6ADAgECAhB+k+v7fMZO
  191. # WepLmnfUBvw7MA0GCSqGSIb3DQEBBQUAMIGLMQswCQYDVQQGEwJaQTEVMBMGA1UE
  192. # CBMMV2VzdGVybiBDYXBlMRQwEgYDVQQHEwtEdXJiYW52aWxsZTEPMA0GA1UEChMG
  193. # VGhhd3RlMR0wGwYDVQQLExRUaGF3dGUgQ2VydGlmaWNhdGlvbjEfMB0GA1UEAxMW
  194. # VGhhd3RlIFRpbWVzdGFtcGluZyBDQTAeFw0xMjEyMjEwMDAwMDBaFw0yMDEyMzAy
  195. # MzU5NTlaMF4xCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRTeW1hbnRlYyBDb3Jwb3Jh
  196. # dGlvbjEwMC4GA1UEAxMnU3ltYW50ZWMgVGltZSBTdGFtcGluZyBTZXJ2aWNlcyBD
  197. # QSAtIEcyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsayzSVRLlxwS
  198. # CtgleZEiVypv3LgmxENza8K/LlBa+xTCdo5DASVDtKHiRfTot3vDdMwi17SUAAL3
  199. # Te2/tLdEJGvNX0U70UTOQxJzF4KLabQry5kerHIbJk1xH7Ex3ftRYQJTpqr1SSwF
  200. # eEWlL4nO55nn/oziVz89xpLcSvh7M+R5CvvwdYhBnP/FA1GZqtdsn5Nph2Upg4XC
  201. # YBTEyMk7FNrAgfAfDXTekiKryvf7dHwn5vdKG3+nw54trorqpuaqJxZ9YfeYcRG8
  202. # 4lChS+Vd+uUOpyyfqmUg09iW6Mh8pU5IRP8Z4kQHkgvXaISAXWp4ZEXNYEZ+VMET
  203. # fMV58cnBcQIDAQABo4H6MIH3MB0GA1UdDgQWBBRfmvVuXMzMdJrU3X3vP9vsTIAu
  204. # 3TAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnRoYXd0
  205. # ZS5jb20wEgYDVR0TAQH/BAgwBgEB/wIBADA/BgNVHR8EODA2MDSgMqAwhi5odHRw
  206. # Oi8vY3JsLnRoYXd0ZS5jb20vVGhhd3RlVGltZXN0YW1waW5nQ0EuY3JsMBMGA1Ud
  207. # JQQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIBBjAoBgNVHREEITAfpB0wGzEZ
  208. # MBcGA1UEAxMQVGltZVN0YW1wLTIwNDgtMTANBgkqhkiG9w0BAQUFAAOBgQADCZuP
  209. # ee9/WTCq72i1+uMJHbtPggZdN1+mUp8WjeockglEbvVt61h8MOj5aY0jcwsSb0ep
  210. # rjkR+Cqxm7Aaw47rWZYArc4MTbLQMaYIXCp6/OJ6HVdMqGUY6XlAYiWWbsfHN2qD
  211. # IQiOQerd2Vc/HXdJhyoWBl6mOGoiEqNRGYN+tjCCBKMwggOLoAMCAQICEA7P9DjI
  212. # /r81bgTYapgbGlAwDQYJKoZIhvcNAQEFBQAwXjELMAkGA1UEBhMCVVMxHTAbBgNV
  213. # BAoTFFN5bWFudGVjIENvcnBvcmF0aW9uMTAwLgYDVQQDEydTeW1hbnRlYyBUaW1l
  214. # IFN0YW1waW5nIFNlcnZpY2VzIENBIC0gRzIwHhcNMTIxMDE4MDAwMDAwWhcNMjAx
  215. # MjI5MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEdMBsGA1UEChMUU3ltYW50ZWMgQ29y
  216. # cG9yYXRpb24xNDAyBgNVBAMTK1N5bWFudGVjIFRpbWUgU3RhbXBpbmcgU2Vydmlj
  217. # ZXMgU2lnbmVyIC0gRzQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCi
  218. # Yws5RLi7I6dESbsO/6HwYQpTk7CY260sD0rFbv+GPFNVDxXOBD8r/amWltm+YXkL
  219. # W8lMhnbl4ENLIpXuwitDwZ/YaLSOQE/uhTi5EcUj8mRY8BUyb05Xoa6IpALXKh7N
  220. # S+HdY9UXiTJbsF6ZWqidKFAOF+6W22E7RVEdzxJWC5JH/Kuu9mY9R6xwcueS51/N
  221. # ELnEg2SUGb0lgOHo0iKl0LoCeqF3k1tlw+4XdLxBhircCEyMkoyRLZ53RB9o1qh0
  222. # d9sOWzKLVoszvdljyEmdOsXF6jML0vGjG/SLvtmzV4s73gSneiKyJK4ux3DFvk6D
  223. # Jgj7C72pT5kI4RAocqrNAgMBAAGjggFXMIIBUzAMBgNVHRMBAf8EAjAAMBYGA1Ud
  224. # JQEB/wQMMAoGCCsGAQUFBwMIMA4GA1UdDwEB/wQEAwIHgDBzBggrBgEFBQcBAQRn
  225. # MGUwKgYIKwYBBQUHMAGGHmh0dHA6Ly90cy1vY3NwLndzLnN5bWFudGVjLmNvbTA3
  226. # BggrBgEFBQcwAoYraHR0cDovL3RzLWFpYS53cy5zeW1hbnRlYy5jb20vdHNzLWNh
  227. # LWcyLmNlcjA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8vdHMtY3JsLndzLnN5bWFu
  228. # dGVjLmNvbS90c3MtY2EtZzIuY3JsMCgGA1UdEQQhMB+kHTAbMRkwFwYDVQQDExBU
  229. # aW1lU3RhbXAtMjA0OC0yMB0GA1UdDgQWBBRGxmmjDkoUHtVM2lJjFz9eNrwN5jAf
  230. # BgNVHSMEGDAWgBRfmvVuXMzMdJrU3X3vP9vsTIAu3TANBgkqhkiG9w0BAQUFAAOC
  231. # AQEAeDu0kSoATPCPYjA3eKOEJwdvGLLeJdyg1JQDqoZOJZ+aQAMc3c7jecshaAba
  232. # tjK0bb/0LCZjM+RJZG0N5sNnDvcFpDVsfIkWxumy37Lp3SDGcQ/NlXTctlzevTcf
  233. # Q3jmeLXNKAQgo6rxS8SIKZEOgNER/N1cdm5PXg5FRkFuDbDqOJqxOtoJcRD8HHm0
  234. # gHusafT9nLYMFivxf1sJPZtb4hbKE4FtAC44DagpjyzhsvRaqQGvFZwsL0kb2yK7
  235. # w/54lFHDhrGCiF3wPbRRoXkzKy57udwgCRNx62oZW8/opTBXLIlJP7nPf8m/PiJo
  236. # Y1OavWl0rMUdPH+S4MO8HNgEdTCCBTAwggQYoAMCAQICEAQJGBtf1btmdVNDtW+V
  237. # UAgwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lD
  238. # ZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEkMCIGA1UEAxMbRGln
  239. # aUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTEzMTAyMjEyMDAwMFoXDTI4MTAy
  240. # MjEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
  241. # MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hB
  242. # MiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
  243. # ggEPADCCAQoCggEBAPjTsxx/DhGvZ3cH0wsxSRnP0PtFmbE620T1f+Wondsy13Hq
  244. # dp0FLreP+pJDwKX5idQ3Gde2qvCchqXYJawOeSg6funRZ9PG+yknx9N7I5TkkSOW
  245. # kHeC+aGEI2YSVDNQdLEoJrskacLCUvIUZ4qJRdQtoaPpiCwgla4cSocI3wz14k1g
  246. # GL6qxLKucDFmM3E+rHCiq85/6XzLkqHlOzEcz+ryCuRXu0q16XTmK/5sy350OTYN
  247. # kO/ktU6kqepqCquE86xnTrXE94zRICUj6whkPlKWwfIPEvTFjg/BougsUfdzvL2F
  248. # sWKDc0GCB+Q4i2pzINAPZHM8np+mM6n9Gd8lk9ECAwEAAaOCAc0wggHJMBIGA1Ud
  249. # EwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUF
  250. # BwMDMHkGCCsGAQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGln
  251. # aWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5j
  252. # b20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2
  253. # hjRodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290
  254. # Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRB
  255. # c3N1cmVkSURSb290Q0EuY3JsME8GA1UdIARIMEYwOAYKYIZIAYb9bAACBDAqMCgG
  256. # CCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAoGCGCGSAGG
  257. # /WwDMB0GA1UdDgQWBBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAfBgNVHSMEGDAWgBRF
  258. # 66Kv9JLLgjEtUYunpyGd823IDzANBgkqhkiG9w0BAQsFAAOCAQEAPuwNWiSz8yLR
  259. # FcgsfCUpdqgdXRwtOhrE7zBh134LYP3DPQ/Er4v97yrfIFU3sOH20ZJ1D1G0bqWO
  260. # WuJeJIFOEKTuP3GOYw4TS63XX0R58zYUBor3nEZOXP+QsRsHDpEV+7qvtVHCjSSu
  261. # JMbHJyqhKSgaOnEoAjwukaPAJRHinBRHoXpoaK+bp1wgXNlxsQyPu6j4xRJon89A
  262. # y0BEpRPw5mQMJQhCMrI2iiQC/i9yfhzXSUWW6Fkd6fp0ZGuy62ZD2rOwjNXpDd32
  263. # ASDOmTFjPQgaGLOBm0/GkxAG/AeB+ova+YJJ92JuoVP6EpQYhS6SkepobEQysmah
  264. # 5xikmmRR7zCCBkcwggUvoAMCAQICEAM+1e2gZdG4yR38+Spsm9gwDQYJKoZIhvcN
  265. # AQELBQAwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcG
  266. # A1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBB
  267. # c3N1cmVkIElEIENvZGUgU2lnbmluZyBDQTAeFw0xODEyMTgwMDAwMDBaFw0yMTEy
  268. # MjIxMjAwMDBaMIGDMQswCQYDVQQGEwJVUzEWMBQGA1UECBMNTmV3IEhhbXBzaGly
  269. # ZTESMBAGA1UEBxMJV29sZmVib3JvMSMwIQYDVQQKExpQeXRob24gU29mdHdhcmUg
  270. # Rm91bmRhdGlvbjEjMCEGA1UEAxMaUHl0aG9uIFNvZnR3YXJlIEZvdW5kYXRpb24w
  271. # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCqvaRLsnW5buglHGWx2sRM
  272. # CMpqt+gflMjw9ZJPphvbE+ig/u8dPiJpVfIvkvN7V/ncnDrtKn67nbh8ld/fSodW
  273. # IRbG6bLZFYbSdyJTZ36YyrOOVoBZJk0XS7hFy/IMmiQRXRFQ6ojkIbnM8jdb25Do
  274. # uJSTccJhbqSkfXvsDlPenD8+jw7woSskafVqdqq0ggKr33JLGsxp3/aE8wFF/o11
  275. # qHt/sc+fWCRJJMCh6PK6oXmH4HSojj4krn5Uu/Prn1VNsBYmxhqSTFnFVZikW/gp
  276. # 5BJLCijQPMy+YRGxPM29UExaG706uIk2D5B8WZ/3rNVO73dxn6vvEyltfJ8g4YqE
  277. # cxpG5nyKG5YjHeAj1YcMVfp8EpHz4eWF2RqIERYixdGjL4RBTIrvNSz4Wo6jaxFi
  278. # 21uzwxMX1gMoVnDI+Of1af6AsZ3k1QRXI28P1BUYES03u/Hztt24lQHwXgPKUSwy
  279. # 1lN+PD9q7oCY6ead4rlRypIm7BHJloY2TvLeqPTq63H4dNOoeCL3vlSnF/KvACqS
  280. # i+hkRYFVKm+S7w9WGQFdwuY17owQeUWJoyiIAMB4qZflEVGQ35WuZgZODjNqPF90
  281. # d4hjxO8t/jy1N+adAl33yB4lC//TU1TL8XG7CoC5ORp7Pk2XUvE/QKlMeGCHM7gV
  282. # EPiK1PbCpOHiOmiPD1BmewIDAQABo4IBxTCCAcEwHwYDVR0jBBgwFoAUWsS5eyoK
  283. # o6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFPwqv37Uvqzzgpykz3siATu4jwfyMA4G
  284. # A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWg
  285. # M6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx
  286. # LmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl
  287. # ZC1jcy1nMS5jcmwwTAYDVR0gBEUwQzA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcC
  288. # ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAIBgZngQwBBAEwgYQGCCsG
  289. # AQUFBwEBBHgwdjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t
  290. # ME4GCCsGAQUFBzAChkJodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl
  291. # cnRTSEEyQXNzdXJlZElEQ29kZVNpZ25pbmdDQS5jcnQwDAYDVR0TAQH/BAIwADAN
  292. # BgkqhkiG9w0BAQsFAAOCAQEAS3WhLbVfRrGJp8+PJj6+ViqNYq5S79gW5hYgSrqJ
  293. # FFoVps0OGP1EEVAX9omITmaytAQ58APr/qBVIf3WVlYGqDo0R4b1P1JduIA+8n0I
  294. # RYWx2RdSuNtaG8Ke5nuSpS5TkEC6YjVBFuliBkvdQD6JleSaNsaHWWfytSFYjFsF
  295. # gvhKDaeqkHjinsJQViQ+P8xvBTaC8FXaleOPlZqyShm2wAIy/mDjYE2hUuhECL56
  296. # /qzTs8634m0dEibzuVPK5zzCHSzBM9TCSwpstTVl2P0Kmq3Nee5UTTDnR7Em9FIr
  297. # dW3iD7S+KCkjeo+YN2mR/37gy/LRcw1yqu2HDbRH4+QiUzGCBZQwggWQAgEBMIGG
  298. # MHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsT
  299. # EHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJl
  300. # ZCBJRCBDb2RlIFNpZ25pbmcgQ0ECEAM+1e2gZdG4yR38+Spsm9gwDQYJYIZIAWUD
  301. # BAIBBQCggdAwGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIB
  302. # CzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIDwkNFE0J7lFqDFWlO8g
  303. # a0Vg8TqicqZe2fbuhTmOCdCDMGQGCisGAQQBgjcCAQwxVjBUoFKAUABCAHUAaQBs
  304. # AHQAOgAgAFIAZQBsAGUAYQBzAGUAXwBtAGEAcwB0AGUAcgBfAHYAMwAuADgALgAw
  305. # AF8AMgAwADEAOQAxADAAMQA0AC4AMAAyMA0GCSqGSIb3DQEBAQUABIICAJVRHHyG
  306. # aSg/QAce2Gk2vae47EiAxljo70Tygvew++CoLy67kRcb03qFNxlfcO033TA7muKF
  307. # IbRaEU2o8gIWArJmPZmMfmSB0vF+YzISbWEWBGJuHOEeNuCQIR2DRziWvmrfdwdo
  308. # dNpoUnD6M/i8pI5asDc6BxyR33WCrH2xNJlXDg8XGuG7df+nymqXucGwydAB6DoB
  309. # +QbIjnRMr1ZCFtWsetCKRX2zS4tKQxFmB7cOjsWKsilC1fgDf7/YGoPlrvaPuVpR
  310. # i1OzhsZksi0M2os3S3NDa0Dsdc+pg8+tZrk3F7az4dskqrbv5++3o7xYv3c63Z33
  311. # dExvW6Jm6YexPE82gZnfGhtnt0shk8ga+JJkaE7/QBxVsUSHZHBZsXgZsLz6p6NO
  312. # YsYgMQJoIb1Z7gxHrOIOto/7fvVYdkcHKTZ7OWcmzd5lvwn47cX0ElfEeiseR/K6
  313. # dVM2y7NMMyz33Aa2arGDIatrudFpCuop/Tk/PxqpiA99MkcUKOMPNs5RXpeR+VyJ
  314. # ncR8Wktx9PtQKzbK9VVAg/iw5l0PDgvn9pIBLNKFxj/nAF+KNYVV4IyyCnseFMMT
  315. # LetKz0LN+NhvUrHsq9NFwxMW3TCUUUqSdPTTOHnzmwVdLynqNsMd+Dx39qKADPBd
  316. # i6Q1XEluhGhdxrRCo9xnF6orI37ozzVMYFSOoYICCzCCAgcGCSqGSIb3DQEJBjGC
  317. # AfgwggH0AgEBMHIwXjELMAkGA1UEBhMCVVMxHTAbBgNVBAoTFFN5bWFudGVjIENv
  318. # cnBvcmF0aW9uMTAwLgYDVQQDEydTeW1hbnRlYyBUaW1lIFN0YW1waW5nIFNlcnZp
  319. # Y2VzIENBIC0gRzICEA7P9DjI/r81bgTYapgbGlAwCQYFKw4DAhoFAKBdMBgGCSqG
  320. # SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE5MTAxNDE5NDEx
  321. # MVowIwYJKoZIhvcNAQkEMRYEFIMEvvUpkO4r3hcHdhB8ezxwvYT3MA0GCSqGSIb3
  322. # DQEBAQUABIIBAG6a8VUP727ARM++rUjHHi5e4yk8drKTw10/4pUNOI0PtNY1vpc8
  323. # XFssjutk/kiVCAzA96cZfoB14N3vTzgMhvg9KlxqWFlJyBR6vVI/1uXypfBWD6rY
  324. # CiTWZjRvNWqGsY4yPmGv5t4hHdcMwz4pSXCgSNCzlPwAK5tZT1DVXZt/MS5tieHF
  325. # PNw2phbMYyvFOrkQrtLF0bjBY0sWd+ABRnw9Ng3cu6IE42kqVqrCl4l/RF90hcTd
  326. # V9TQOc9vYgbsuwDI7VILxI3WruqQhbhIj5KGb3N8qWayeNpAj2A16Pt4TIR9lTj/
  327. # T2hLH+2yqwga3KDkVcxVwxIibAYHjZkdCfE=
  328. # SIG # End signature block