Activate.ps1 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420
  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. .Notes
  33. On Windows, it may be required to enable this Activate.ps1 script by setting the
  34. execution policy for the user. You can do this by issuing the following PowerShell
  35. command:
  36. PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
  37. For more information on Execution Policies:
  38. https://go.microsoft.com/fwlink/?LinkID=135170
  39. #>
  40. Param(
  41. [Parameter(Mandatory = $false)]
  42. [String]
  43. $VenvDir,
  44. [Parameter(Mandatory = $false)]
  45. [String]
  46. $Prompt
  47. )
  48. <# Function declarations --------------------------------------------------- #>
  49. <#
  50. .Synopsis
  51. Remove all shell session elements added by the Activate script, including the
  52. addition of the virtual environment's Python executable from the beginning of
  53. the PATH variable.
  54. .Parameter NonDestructive
  55. If present, do not remove this function from the global namespace for the
  56. session.
  57. #>
  58. function global:deactivate ([switch]$NonDestructive) {
  59. # Revert to original values
  60. # The prior prompt:
  61. if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
  62. Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
  63. Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
  64. }
  65. # The prior PYTHONHOME:
  66. if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
  67. Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
  68. Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
  69. }
  70. # The prior PATH:
  71. if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
  72. Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
  73. Remove-Item -Path Env:_OLD_VIRTUAL_PATH
  74. }
  75. # Just remove the VIRTUAL_ENV altogether:
  76. if (Test-Path -Path Env:VIRTUAL_ENV) {
  77. Remove-Item -Path env:VIRTUAL_ENV
  78. }
  79. # Just remove VIRTUAL_ENV_PROMPT altogether.
  80. if (Test-Path -Path Env:VIRTUAL_ENV_PROMPT) {
  81. Remove-Item -Path env:VIRTUAL_ENV_PROMPT
  82. }
  83. # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
  84. if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
  85. Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
  86. }
  87. # Leave deactivate function in the global namespace if requested:
  88. if (-not $NonDestructive) {
  89. Remove-Item -Path function:deactivate
  90. }
  91. }
  92. <#
  93. .Description
  94. Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
  95. given folder, and returns them in a map.
  96. For each line in the pyvenv.cfg file, if that line can be parsed into exactly
  97. two strings separated by `=` (with any amount of whitespace surrounding the =)
  98. then it is considered a `key = value` line. The left hand string is the key,
  99. the right hand is the value.
  100. If the value starts with a `'` or a `"` then the first and last character is
  101. stripped from the value before being captured.
  102. .Parameter ConfigDir
  103. Path to the directory that contains the `pyvenv.cfg` file.
  104. #>
  105. function Get-PyVenvConfig(
  106. [String]
  107. $ConfigDir
  108. ) {
  109. Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
  110. # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
  111. $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
  112. # An empty map will be returned if no config file is found.
  113. $pyvenvConfig = @{ }
  114. if ($pyvenvConfigPath) {
  115. Write-Verbose "File exists, parse `key = value` lines"
  116. $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
  117. $pyvenvConfigContent | ForEach-Object {
  118. $keyval = $PSItem -split "\s*=\s*", 2
  119. if ($keyval[0] -and $keyval[1]) {
  120. $val = $keyval[1]
  121. # Remove extraneous quotations around a string value.
  122. if ("'""".Contains($val.Substring(0, 1))) {
  123. $val = $val.Substring(1, $val.Length - 2)
  124. }
  125. $pyvenvConfig[$keyval[0]] = $val
  126. Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
  127. }
  128. }
  129. }
  130. return $pyvenvConfig
  131. }
  132. <# Begin Activate script --------------------------------------------------- #>
  133. # Determine the containing directory of this script
  134. $VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
  135. $VenvExecDir = Get-Item -Path $VenvExecPath
  136. Write-Verbose "Activation script is located in path: '$VenvExecPath'"
  137. Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
  138. Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
  139. # Set values required in priority: CmdLine, ConfigFile, Default
  140. # First, get the location of the virtual environment, it might not be
  141. # VenvExecDir if specified on the command line.
  142. if ($VenvDir) {
  143. Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
  144. }
  145. else {
  146. Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
  147. $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
  148. Write-Verbose "VenvDir=$VenvDir"
  149. }
  150. # Next, read the `pyvenv.cfg` file to determine any required value such
  151. # as `prompt`.
  152. $pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
  153. # Next, set the prompt from the command line, or the config file, or
  154. # just use the name of the virtual environment folder.
  155. if ($Prompt) {
  156. Write-Verbose "Prompt specified as argument, using '$Prompt'"
  157. }
  158. else {
  159. Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
  160. if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
  161. Write-Verbose " Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
  162. $Prompt = $pyvenvCfg['prompt'];
  163. }
  164. else {
  165. Write-Verbose " Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virtual environment)"
  166. Write-Verbose " Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
  167. $Prompt = Split-Path -Path $venvDir -Leaf
  168. }
  169. }
  170. Write-Verbose "Prompt = '$Prompt'"
  171. Write-Verbose "VenvDir='$VenvDir'"
  172. # Deactivate any currently active virtual environment, but leave the
  173. # deactivate function in place.
  174. deactivate -nondestructive
  175. # Now set the environment variable VIRTUAL_ENV, used by many tools to determine
  176. # that there is an activated venv.
  177. $env:VIRTUAL_ENV = $VenvDir
  178. if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
  179. Write-Verbose "Setting prompt to '$Prompt'"
  180. # Set the prompt to include the env name
  181. # Make sure _OLD_VIRTUAL_PROMPT is global
  182. function global:_OLD_VIRTUAL_PROMPT { "" }
  183. Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
  184. New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
  185. function global:prompt {
  186. Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
  187. _OLD_VIRTUAL_PROMPT
  188. }
  189. $env:VIRTUAL_ENV_PROMPT = $Prompt
  190. }
  191. # Clear PYTHONHOME
  192. if (Test-Path -Path Env:PYTHONHOME) {
  193. Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
  194. Remove-Item -Path Env:PYTHONHOME
  195. }
  196. # Add the venv to the PATH
  197. Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
  198. $Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"
  199. # SIG # Begin signature block
  200. # MIIf2wYJKoZIhvcNAQcCoIIfzDCCH8gCAQExDzANBglghkgBZQMEAgEFADB5Bgor
  201. # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG
  202. # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCBnL745ElCYk8vk
  203. # dBtMuQhLeWJ3ZGfzKW4DHCYzAn+QB6CCDi8wggawMIIEmKADAgECAhAIrUCyYNKc
  204. # TJ9ezam9k67ZMA0GCSqGSIb3DQEBDAUAMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
  205. # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNV
  206. # BAMTGERpZ2lDZXJ0IFRydXN0ZWQgUm9vdCBHNDAeFw0yMTA0MjkwMDAwMDBaFw0z
  207. # NjA0MjgyMzU5NTlaMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
  208. # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
  209. # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
  210. # ggIKAoICAQDVtC9C0CiteLdd1TlZG7GIQvUzjOs9gZdwxbvEhSYwn6SOaNhc9es0
  211. # JAfhS0/TeEP0F9ce2vnS1WcaUk8OoVf8iJnBkcyBAz5NcCRks43iCH00fUyAVxJr
  212. # Q5qZ8sU7H/Lvy0daE6ZMswEgJfMQ04uy+wjwiuCdCcBlp/qYgEk1hz1RGeiQIXhF
  213. # LqGfLOEYwhrMxe6TSXBCMo/7xuoc82VokaJNTIIRSFJo3hC9FFdd6BgTZcV/sk+F
  214. # LEikVoQ11vkunKoAFdE3/hoGlMJ8yOobMubKwvSnowMOdKWvObarYBLj6Na59zHh
  215. # 3K3kGKDYwSNHR7OhD26jq22YBoMbt2pnLdK9RBqSEIGPsDsJ18ebMlrC/2pgVItJ
  216. # wZPt4bRc4G/rJvmM1bL5OBDm6s6R9b7T+2+TYTRcvJNFKIM2KmYoX7BzzosmJQay
  217. # g9Rc9hUZTO1i4F4z8ujo7AqnsAMrkbI2eb73rQgedaZlzLvjSFDzd5Ea/ttQokbI
  218. # YViY9XwCFjyDKK05huzUtw1T0PhH5nUwjewwk3YUpltLXXRhTT8SkXbev1jLchAp
  219. # QfDVxW0mdmgRQRNYmtwmKwH0iU1Z23jPgUo+QEdfyYFQc4UQIyFZYIpkVMHMIRro
  220. # OBl8ZhzNeDhFMJlP/2NPTLuqDQhTQXxYPUez+rbsjDIJAsxsPAxWEQIDAQABo4IB
  221. # WTCCAVUwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHQ4EFgQUaDfg67Y7+F8Rhvv+
  222. # YXsIiGX0TkIwHwYDVR0jBBgwFoAU7NfjgtJxXWRM3y5nP+e6mK4cD08wDgYDVR0P
  223. # AQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMDMHcGCCsGAQUFBwEBBGswaTAk
  224. # BggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEEGCCsGAQUFBzAC
  225. # hjVodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkUm9v
  226. # dEc0LmNydDBDBgNVHR8EPDA6MDigNqA0hjJodHRwOi8vY3JsMy5kaWdpY2VydC5j
  227. # b20vRGlnaUNlcnRUcnVzdGVkUm9vdEc0LmNybDAcBgNVHSAEFTATMAcGBWeBDAED
  228. # MAgGBmeBDAEEATANBgkqhkiG9w0BAQwFAAOCAgEAOiNEPY0Idu6PvDqZ01bgAhql
  229. # +Eg08yy25nRm95RysQDKr2wwJxMSnpBEn0v9nqN8JtU3vDpdSG2V1T9J9Ce7FoFF
  230. # UP2cvbaF4HZ+N3HLIvdaqpDP9ZNq4+sg0dVQeYiaiorBtr2hSBh+3NiAGhEZGM1h
  231. # mYFW9snjdufE5BtfQ/g+lP92OT2e1JnPSt0o618moZVYSNUa/tcnP/2Q0XaG3Ryw
  232. # YFzzDaju4ImhvTnhOE7abrs2nfvlIVNaw8rpavGiPttDuDPITzgUkpn13c5Ubdld
  233. # AhQfQDN8A+KVssIhdXNSy0bYxDQcoqVLjc1vdjcshT8azibpGL6QB7BDf5WIIIJw
  234. # 8MzK7/0pNVwfiThV9zeKiwmhywvpMRr/LhlcOXHhvpynCgbWJme3kuZOX956rEnP
  235. # LqR0kq3bPKSchh/jwVYbKyP/j7XqiHtwa+aguv06P0WmxOgWkVKLQcBIhEuWTatE
  236. # QOON8BUozu3xGFYHKi8QxAwIZDwzj64ojDzLj4gLDb879M4ee47vtevLt/B3E+bn
  237. # KD+sEq6lLyJsQfmCXBVmzGwOysWGw/YmMwwHS6DTBwJqakAwSEs0qFEgu60bhQji
  238. # WQ1tygVQK+pKHJ6l/aCnHwZ05/LWUpD9r4VIIflXO7ScA+2GRfS0YW6/aOImYIbq
  239. # yK+p/pQd52MbOoZWeE4wggd3MIIFX6ADAgECAhAHHxQbizANJfMU6yMM0NHdMA0G
  240. # CSqGSIb3DQEBCwUAMGkxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwg
  241. # SW5jLjFBMD8GA1UEAxM4RGlnaUNlcnQgVHJ1c3RlZCBHNCBDb2RlIFNpZ25pbmcg
  242. # UlNBNDA5NiBTSEEzODQgMjAyMSBDQTEwHhcNMjIwMTE3MDAwMDAwWhcNMjUwMTE1
  243. # MjM1OTU5WjB8MQswCQYDVQQGEwJVUzEPMA0GA1UECBMGT3JlZ29uMRIwEAYDVQQH
  244. # EwlCZWF2ZXJ0b24xIzAhBgNVBAoTGlB5dGhvbiBTb2Z0d2FyZSBGb3VuZGF0aW9u
  245. # MSMwIQYDVQQDExpQeXRob24gU29mdHdhcmUgRm91bmRhdGlvbjCCAiIwDQYJKoZI
  246. # hvcNAQEBBQADggIPADCCAgoCggIBAKgc0BTT+iKbtK6f2mr9pNMUTcAJxKdsuOiS
  247. # YgDFfwhjQy89koM7uP+QV/gwx8MzEt3c9tLJvDccVWQ8H7mVsk/K+X+IufBLCgUi
  248. # 0GGAZUegEAeRlSXxxhYScr818ma8EvGIZdiSOhqjYc4KnfgfIS4RLtZSrDFG2tN1
  249. # 6yS8skFa3IHyvWdbD9PvZ4iYNAS4pjYDRjT/9uzPZ4Pan+53xZIcDgjiTwOh8VGu
  250. # ppxcia6a7xCyKoOAGjvCyQsj5223v1/Ig7Dp9mGI+nh1E3IwmyTIIuVHyK6Lqu35
  251. # 2diDY+iCMpk9ZanmSjmB+GMVs+H/gOiofjjtf6oz0ki3rb7sQ8fTnonIL9dyGTJ0
  252. # ZFYKeb6BLA66d2GALwxZhLe5WH4Np9HcyXHACkppsE6ynYjTOd7+jN1PRJahN1oE
  253. # RzTzEiV6nCO1M3U1HbPTGyq52IMFSBM2/07WTJSbOeXjvYR7aUxK9/ZkJiacl2iZ
  254. # I7IWe7JKhHohqKuceQNyOzxTakLcRkzynvIrk33R9YVqtB4L6wtFxhUjvDnQg16x
  255. # ot2KVPdfyPAWd81wtZADmrUtsZ9qG79x1hBdyOl4vUtVPECuyhCxaw+faVjumapP
  256. # Unwo8ygflJJ74J+BYxf6UuD7m8yzsfXWkdv52DjL74TxzuFTLHPyARWCSCAbzn3Z
  257. # Ily+qIqDAgMBAAGjggIGMIICAjAfBgNVHSMEGDAWgBRoN+Drtjv4XxGG+/5hewiI
  258. # ZfROQjAdBgNVHQ4EFgQUt/1Teh2XDuUj2WW3siYWJgkZHA8wDgYDVR0PAQH/BAQD
  259. # AgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMDMIG1BgNVHR8Ega0wgaowU6BRoE+GTWh0
  260. # dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0ZWRHNENvZGVTaWdu
  261. # aW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3JsMFOgUaBPhk1odHRwOi8vY3JsNC5k
  262. # aWdpY2VydC5jb20vRGlnaUNlcnRUcnVzdGVkRzRDb2RlU2lnbmluZ1JTQTQwOTZT
  263. # SEEzODQyMDIxQ0ExLmNybDA+BgNVHSAENzA1MDMGBmeBDAEEATApMCcGCCsGAQUF
  264. # BwIBFhtodHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwgZQGCCsGAQUFBwEBBIGH
  265. # MIGEMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wXAYIKwYB
  266. # BQUHMAKGUGh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFRydXN0
  267. # ZWRHNENvZGVTaWduaW5nUlNBNDA5NlNIQTM4NDIwMjFDQTEuY3J0MAwGA1UdEwEB
  268. # /wQCMAAwDQYJKoZIhvcNAQELBQADggIBABxv4AeV/5ltkELHSC63fXAFYS5tadcW
  269. # TiNc2rskrNLrfH1Ns0vgSZFoQxYBFKI159E8oQQ1SKbTEubZ/B9kmHPhprHya08+
  270. # VVzxC88pOEvz68nA82oEM09584aILqYmj8Pj7h/kmZNzuEL7WiwFa/U1hX+XiWfL
  271. # IJQsAHBla0i7QRF2de8/VSF0XXFa2kBQ6aiTsiLyKPNbaNtbcucaUdn6vVUS5izW
  272. # OXM95BSkFSKdE45Oq3FForNJXjBvSCpwcP36WklaHL+aHu1upIhCTUkzTHMh8b86
  273. # WmjRUqbrnvdyR2ydI5l1OqcMBjkpPpIV6wcc+KY/RH2xvVuuoHjlUjwq2bHiNoX+
  274. # W1scCpnA8YTs2d50jDHUgwUo+ciwpffH0Riq132NFmrH3r67VaN3TuBxjI8SIZM5
  275. # 8WEDkbeoriDk3hxU8ZWV7b8AW6oyVBGfM06UgkfMb58h+tJPrFx8VI/WLq1dTqMf
  276. # ZOm5cuclMnUHs2uqrRNtnV8UfidPBL4ZHkTcClQbCoz0UbLhkiDvIS00Dn+BBcxw
  277. # /TKqVL4Oaz3bkMSsM46LciTeucHY9ExRVt3zy7i149sd+F4QozPqn7FrSVHXmem3
  278. # r7bjyHTxOgqxRCVa18Vtx7P/8bYSBeS+WHCKcliFCecspusCDSlnRUjZwyPdP0VH
  279. # xaZg2unjHY3rMYIRAjCCEP4CAQEwfTBpMQswCQYDVQQGEwJVUzEXMBUGA1UEChMO
  280. # RGlnaUNlcnQsIEluYy4xQTA/BgNVBAMTOERpZ2lDZXJ0IFRydXN0ZWQgRzQgQ29k
  281. # ZSBTaWduaW5nIFJTQTQwOTYgU0hBMzg0IDIwMjEgQ0ExAhAHHxQbizANJfMU6yMM
  282. # 0NHdMA0GCWCGSAFlAwQCAQUAoIHWMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEE
  283. # MBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCBn
  284. # AZ6P7YvTwq0fbF62o7E75R0LxsW5OtyYiFESQckLhjBqBgorBgEEAYI3AgEMMVww
  285. # WqBYgFYAQgB1AGkAbAB0ADoAIABSAGUAbABlAGEAcwBlAF8AYgB1AGkAbABkAGYA
  286. # aQB4AF8AdgAzAC4AMQAwAC4ANABfADIAMAAyADIAMAAzADIAMwAuADAAMjANBgkq
  287. # hkiG9w0BAQEFAASCAgAcEvETg2Xhn12WXdKe3tBaVv7GlhnKE3KIyIYicO7HekaL
  288. # xA56c/hiIuIkAGRuhbm++NMB/L7RYueQI8+ze8q4BoHLvH5lxR92twKr1RhKRbo3
  289. # rSj5zGPna6P7s677Nfw3WJ01RlOKF3ygJe+GRj3RpUR8aL2DM4pzydcVM2ihWzFy
  290. # CqsKCj3s/ELGiA3RQ0KVbZ9VO+r2/AsZdndYKCjxYL4PMiCver6+eeqhxkS0r7v0
  291. # Dv6/NJOPaC61Gcwi5lIfZRMOcMKPC18O6VmXbsDmh044BLfz3oE3oQsrq1AkUj4a
  292. # eguQAOZAy44a6um8/YoHOZ73ZJkxfnGWVRZlmHJbvx/KFK/MnXtDI1lW2OerCx4N
  293. # k1tRq9aHimmomsJvo4N10dCGMkDIWUPGJKTBvtvW3K+QWYzukvqADuQuuJPs67yF
  294. # oiKncZ7+51Qruo7qWxJeLJl7q2vzf8dPOwc/7SXiOhCjQqwxYvSB/xkSQ8xkl2Ve
  295. # 8lQlVjSCQG109Q8TvA2GKUXc3wnEC+hmSCz0lGRQ1jwHEk4wY73fxRocK4cmXqib
  296. # szuaj4C/IIue9npABx5K0eAwJ/JjiYc2CtrDJ1cPJz3Ho0UBpHdhND4s25oB9F5r
  297. # IihejiQumFRTIABC+gn8289gCoNK7MADZdigwW76/Jg/M1KWbpvBJuEJsoQim6GC
  298. # DX0wgg15BgorBgEEAYI3AwMBMYINaTCCDWUGCSqGSIb3DQEHAqCCDVYwgg1SAgED
  299. # MQ8wDQYJYIZIAWUDBAIBBQAwdwYLKoZIhvcNAQkQAQSgaARmMGQCAQEGCWCGSAGG
  300. # /WwHATAxMA0GCWCGSAFlAwQCAQUABCC0XTDkLGotxVA3SNZCglpIf43K7cFUZzmD
  301. # j6rKB6I4xgIQWaJlxfK8fWWZr5xb+dKEGhgPMjAyMjAzMjMyMzE5MjhaoIIKNzCC
  302. # BP4wggPmoAMCAQICEA1CSuC+Ooj/YEAhzhQA8N0wDQYJKoZIhvcNAQELBQAwcjEL
  303. # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
  304. # LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElE
  305. # IFRpbWVzdGFtcGluZyBDQTAeFw0yMTAxMDEwMDAwMDBaFw0zMTAxMDYwMDAwMDBa
  306. # MEgxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEgMB4GA1UE
  307. # AxMXRGlnaUNlcnQgVGltZXN0YW1wIDIwMjEwggEiMA0GCSqGSIb3DQEBAQUAA4IB
  308. # DwAwggEKAoIBAQDC5mGEZ8WK9Q0IpEXKY2tR1zoRQr0KdXVNlLQMULUmEP4dyG+R
  309. # awyW5xpcSO9E5b+bYc0VkWJauP9nC5xj/TZqgfop+N0rcIXeAhjzeG28ffnHbQk9
  310. # vmp2h+mKvfiEXR52yeTGdnY6U9HR01o2j8aj4S8bOrdh1nPsTm0zinxdRS1LsVDm
  311. # QTo3VobckyON91Al6GTm3dOPL1e1hyDrDo4s1SPa9E14RuMDgzEpSlwMMYpKjIjF
  312. # 9zBa+RSvFV9sQ0kJ/SYjU/aNY+gaq1uxHTDCm2mCtNv8VlS8H6GHq756WwogL0sJ
  313. # yZWnjbL61mOLTqVyHO6fegFz+BnW/g1JhL0BAgMBAAGjggG4MIIBtDAOBgNVHQ8B
  314. # Af8EBAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDBB
  315. # BgNVHSAEOjA4MDYGCWCGSAGG/WwHATApMCcGCCsGAQUFBwIBFhtodHRwOi8vd3d3
  316. # LmRpZ2ljZXJ0LmNvbS9DUFMwHwYDVR0jBBgwFoAU9LbhIB3+Ka7S5GGlsqIlssgX
  317. # NW4wHQYDVR0OBBYEFDZEho6kurBmvrwoLR1ENt3janq8MHEGA1UdHwRqMGgwMqAw
  318. # oC6GLGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMuY3Js
  319. # MDKgMKAuhixodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLXRz
  320. # LmNybDCBhQYIKwYBBQUHAQEEeTB3MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5k
  321. # aWdpY2VydC5jb20wTwYIKwYBBQUHMAKGQ2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0
  322. # LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURUaW1lc3RhbXBpbmdDQS5jcnQwDQYJ
  323. # KoZIhvcNAQELBQADggEBAEgc3LXpmiO85xrnIA6OZ0b9QnJRdAojR6OrktIlxHBZ
  324. # vhSg5SeBpU0UFRkHefDRBMOG2Tu9/kQCZk3taaQP9rhwz2Lo9VFKeHk2eie38+dS
  325. # n5On7UOee+e03UEiifuHokYDTvz0/rdkd2NfI1Jpg4L6GlPtkMyNoRdzDfTzZTlw
  326. # S/Oc1np72gy8PTLQG8v1Yfx1CAB2vIEO+MDhXM/EEXLnG2RJ2CKadRVC9S0yOIHa
  327. # 9GCiurRS+1zgYSQlT7LfySmoc0NR2r1j1h9bm/cuG08THfdKDXF+l7f0P4TrweOj
  328. # SaH6zqe/Vs+6WXZhiV9+p7SOZ3j5NpjhyyjaW4emii8wggUxMIIEGaADAgECAhAK
  329. # oSXW1jIbfkHkBdo2l8IVMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUw
  330. # EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
  331. # JDAiBgNVBAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xNjAxMDcx
  332. # MjAwMDBaFw0zMTAxMDcxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxE
  333. # aWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMT
  334. # KERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJRCBUaW1lc3RhbXBpbmcgQ0EwggEiMA0G
  335. # CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC90DLuS82Pf92puoKZxTlUKFe2I0rE
  336. # DgdFM1EQfdD5fU1ofue2oPSNs4jkl79jIZCYvxO8V9PD4X4I1moUADj3Lh477sym
  337. # 9jJZ/l9lP+Cb6+NGRwYaVX4LJ37AovWg4N4iPw7/fpX786O6Ij4YrBHk8JkDbTuF
  338. # fAnT7l3ImgtU46gJcWvgzyIQD3XPcXJOCq3fQDpct1HhoXkUxk0kIzBdvOw8YGqs
  339. # LwfM/fDqR9mIUF79Zm5WYScpiYRR5oLnRlD9lCosp+R1PrqYD4R/nzEU1q3V8mTL
  340. # ex4F0IQZchfxFwbvPc3WTe8GQv2iUypPhR3EHTyvz9qsEPXdrKzpVv+TAgMBAAGj
  341. # ggHOMIIByjAdBgNVHQ4EFgQU9LbhIB3+Ka7S5GGlsqIlssgXNW4wHwYDVR0jBBgw
  342. # FoAUReuir/SSy4IxLVGLp6chnfNtyA8wEgYDVR0TAQH/BAgwBgEB/wIBADAOBgNV
  343. # HQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwgweQYIKwYBBQUHAQEEbTBr
  344. # MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYIKwYBBQUH
  345. # MAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ
  346. # RFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2lj
  347. # ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6
  348. # Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmww
  349. # UAYDVR0gBEkwRzA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0dHBzOi8v
  350. # d3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCwYJYIZIAYb9bAcBMA0GCSqGSIb3DQEBCwUA
  351. # A4IBAQBxlRLpUYdWac3v3dp8qmN6s3jPBjdAhO9LhL/KzwMC/cWnww4gQiyvd/Mr
  352. # HwwhWiq3BTQdaq6Z+CeiZr8JqmDfdqQ6kw/4stHYfBli6F6CJR7Euhx7LCHi1lss
  353. # FDVDBGiy23UC4HLHmNY8ZOUfSBAYX4k4YU1iRiSHY4yRUiyvKYnleB/WCxSlgNcS
  354. # R3CzddWThZN+tpJn+1Nhiaj1a5bA9FhpDXzIAbG5KHW3mWOFIoxhynmUfln8jA/j
  355. # b7UBJrZspe6HUSHkWGCbugwtK22ixH67xCUrRwIIfEmuE7bhfEJCKMYYVs9BNLZm
  356. # XbZ0e/VWMyIvIjayS6JKldj1po5SMYIChjCCAoICAQEwgYYwcjELMAkGA1UEBhMC
  357. # VVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0
  358. # LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFt
  359. # cGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEFAKCB0TAaBgkq
  360. # hkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTIyMDMyMzIz
  361. # MTkyOFowKwYLKoZIhvcNAQkQAgwxHDAaMBgwFgQU4deCqOGRvu9ryhaRtaq0lKYk
  362. # m/MwLwYJKoZIhvcNAQkEMSIEIHNTJ07DMb66i/CvfgCQwd6w8vfBx22bam2qmc9M
  363. # uGZaMDcGCyqGSIb3DQEJEAIvMSgwJjAkMCIEILMQkAa8CtmDB5FXKeBEA0Fcg+Mp
  364. # K2FPJpZMjTVx7PWpMA0GCSqGSIb3DQEBAQUABIIBAHon6BMHxuQFoPSgk2hY0LY8
  365. # iYSY/wzH+juGLxHQ8DQP7CHbPiIvftqXgEK9VgVLxjk+e+O2+/6zdUzhg1q0N+1W
  366. # RR0AvTl3Kv6ISCmG8HrcnC33q2OgPKLYhPZy0WBv0bZGfZzVnFMGmWjmBUmovqKG
  367. # mSvf+8yV58oAwASWRNXJE1Ut4bR8qjCLZ31Uh+L/YQRVrYCvmUS09rrufBAAjzbC
  368. # 1Uir2Pea4OE5jneMOvHAg29Nsh2GzUjPeKqHw4Dkv1ED0+3jbxOd5iGBi8ZXn9Us
  369. # mhxC+BxAf/7oN9038H/22cT9ec1QUce7UapZaDZlGO1uhFNzHR/RTpn62Ol4iWM=
  370. # SIG # End signature block