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.

2466 lines
99 KiB

4 years ago
  1. #!/usr/bin/env python
  2. """Create a "virtual" Python installation"""
  3. # fmt: off
  4. import os # isort:skip
  5. import sys # isort:skip
  6. # If we are running in a new interpreter to create a virtualenv,
  7. # we do NOT want paths from our existing location interfering with anything,
  8. # So we remove this file's directory from sys.path - most likely to be
  9. # the previous interpreter's site-packages. Solves #705, #763, #779
  10. if os.environ.get("VIRTUALENV_INTERPRETER_RUNNING"):
  11. for path in sys.path[:]:
  12. if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path):
  13. sys.path.remove(path)
  14. # fmt: on
  15. import base64
  16. import codecs
  17. import distutils.spawn
  18. import distutils.sysconfig
  19. import errno
  20. import glob
  21. import logging
  22. import optparse
  23. import os
  24. import re
  25. import shutil
  26. import struct
  27. import subprocess
  28. import sys
  29. import textwrap
  30. import zlib
  31. from distutils.util import strtobool
  32. from os.path import join
  33. try:
  34. import ConfigParser
  35. except ImportError:
  36. import configparser as ConfigParser
  37. __version__ = "16.1.0"
  38. virtualenv_version = __version__ # legacy
  39. if sys.version_info < (2, 7):
  40. print("ERROR: %s" % sys.exc_info()[1])
  41. print("ERROR: this script requires Python 2.7 or greater.")
  42. sys.exit(101)
  43. try:
  44. basestring
  45. except NameError:
  46. basestring = str
  47. py_version = "python{}.{}".format(sys.version_info[0], sys.version_info[1])
  48. is_jython = sys.platform.startswith("java")
  49. is_pypy = hasattr(sys, "pypy_version_info")
  50. is_win = sys.platform == "win32"
  51. is_cygwin = sys.platform == "cygwin"
  52. is_darwin = sys.platform == "darwin"
  53. abiflags = getattr(sys, "abiflags", "")
  54. user_dir = os.path.expanduser("~")
  55. if is_win:
  56. default_storage_dir = os.path.join(user_dir, "virtualenv")
  57. else:
  58. default_storage_dir = os.path.join(user_dir, ".virtualenv")
  59. default_config_file = os.path.join(default_storage_dir, "virtualenv.ini")
  60. if is_pypy:
  61. expected_exe = "pypy"
  62. elif is_jython:
  63. expected_exe = "jython"
  64. else:
  65. expected_exe = "python"
  66. # Return a mapping of version -> Python executable
  67. # Only provided for Windows, where the information in the registry is used
  68. if not is_win:
  69. def get_installed_pythons():
  70. return {}
  71. else:
  72. try:
  73. import winreg
  74. except ImportError:
  75. import _winreg as winreg
  76. def get_installed_pythons():
  77. exes = dict()
  78. # If both system and current user installations are found for a
  79. # particular Python version, the current user one is used
  80. for key in (winreg.HKEY_LOCAL_MACHINE, winreg.HKEY_CURRENT_USER):
  81. try:
  82. python_core = winreg.CreateKey(key, "Software\\Python\\PythonCore")
  83. except WindowsError:
  84. # No registered Python installations
  85. continue
  86. i = 0
  87. while True:
  88. try:
  89. version = winreg.EnumKey(python_core, i)
  90. i += 1
  91. try:
  92. path = winreg.QueryValue(python_core, "%s\\InstallPath" % version)
  93. except WindowsError:
  94. continue
  95. exes[version] = join(path, "python.exe")
  96. except WindowsError:
  97. break
  98. winreg.CloseKey(python_core)
  99. # For versions that track separate 32-bit (`X.Y-32`) & 64-bit (`X-Y`)
  100. # installation registrations, add a `X.Y-64` version tag and make the
  101. # extensionless `X.Y` version tag represent the 64-bit installation if
  102. # available or 32-bit if it is not
  103. updated = {}
  104. for ver in exes:
  105. if ver < "3.5":
  106. continue
  107. if ver.endswith("-32"):
  108. base_ver = ver[:-3]
  109. if base_ver not in exes:
  110. updated[base_ver] = exes[ver]
  111. else:
  112. updated[ver + "-64"] = exes[ver]
  113. exes.update(updated)
  114. # Add the major versions
  115. # Sort the keys, then repeatedly update the major version entry
  116. # Last executable (i.e., highest version) wins with this approach,
  117. # 64-bit over 32-bit if both are found
  118. for ver in sorted(exes):
  119. exes[ver[0]] = exes[ver]
  120. return exes
  121. REQUIRED_MODULES = [
  122. "os",
  123. "posix",
  124. "posixpath",
  125. "nt",
  126. "ntpath",
  127. "genericpath",
  128. "fnmatch",
  129. "locale",
  130. "encodings",
  131. "codecs",
  132. "stat",
  133. "UserDict",
  134. "readline",
  135. "copy_reg",
  136. "types",
  137. "re",
  138. "sre",
  139. "sre_parse",
  140. "sre_constants",
  141. "sre_compile",
  142. "zlib",
  143. ]
  144. REQUIRED_FILES = ["lib-dynload", "config"]
  145. majver, minver = sys.version_info[:2]
  146. if majver == 2:
  147. if minver >= 6:
  148. REQUIRED_MODULES.extend(["warnings", "linecache", "_abcoll", "abc"])
  149. if minver >= 7:
  150. REQUIRED_MODULES.extend(["_weakrefset"])
  151. elif majver == 3:
  152. # Some extra modules are needed for Python 3, but different ones
  153. # for different versions.
  154. REQUIRED_MODULES.extend(
  155. [
  156. "_abcoll",
  157. "warnings",
  158. "linecache",
  159. "abc",
  160. "io",
  161. "_weakrefset",
  162. "copyreg",
  163. "tempfile",
  164. "random",
  165. "__future__",
  166. "collections",
  167. "keyword",
  168. "tarfile",
  169. "shutil",
  170. "struct",
  171. "copy",
  172. "tokenize",
  173. "token",
  174. "functools",
  175. "heapq",
  176. "bisect",
  177. "weakref",
  178. "reprlib",
  179. ]
  180. )
  181. if minver >= 2:
  182. REQUIRED_FILES[-1] = "config-%s" % majver
  183. if minver >= 3:
  184. import sysconfig
  185. platdir = sysconfig.get_config_var("PLATDIR")
  186. REQUIRED_FILES.append(platdir)
  187. REQUIRED_MODULES.extend(["base64", "_dummy_thread", "hashlib", "hmac", "imp", "importlib", "rlcompleter"])
  188. if minver >= 4:
  189. REQUIRED_MODULES.extend(["operator", "_collections_abc", "_bootlocale"])
  190. if minver >= 6:
  191. REQUIRED_MODULES.extend(["enum"])
  192. if is_pypy:
  193. # these are needed to correctly display the exceptions that may happen
  194. # during the bootstrap
  195. REQUIRED_MODULES.extend(["traceback", "linecache"])
  196. if majver == 3:
  197. # _functools is needed to import locale during stdio initialization and
  198. # needs to be copied on PyPy because it's not built in
  199. REQUIRED_MODULES.append("_functools")
  200. class Logger(object):
  201. """
  202. Logging object for use in command-line script. Allows ranges of
  203. levels, to avoid some redundancy of displayed information.
  204. """
  205. DEBUG = logging.DEBUG
  206. INFO = logging.INFO
  207. NOTIFY = (logging.INFO + logging.WARN) / 2
  208. WARN = WARNING = logging.WARN
  209. ERROR = logging.ERROR
  210. FATAL = logging.FATAL
  211. LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
  212. def __init__(self, consumers):
  213. self.consumers = consumers
  214. self.indent = 0
  215. self.in_progress = None
  216. self.in_progress_hanging = False
  217. def debug(self, msg, *args, **kw):
  218. self.log(self.DEBUG, msg, *args, **kw)
  219. def info(self, msg, *args, **kw):
  220. self.log(self.INFO, msg, *args, **kw)
  221. def notify(self, msg, *args, **kw):
  222. self.log(self.NOTIFY, msg, *args, **kw)
  223. def warn(self, msg, *args, **kw):
  224. self.log(self.WARN, msg, *args, **kw)
  225. def error(self, msg, *args, **kw):
  226. self.log(self.ERROR, msg, *args, **kw)
  227. def fatal(self, msg, *args, **kw):
  228. self.log(self.FATAL, msg, *args, **kw)
  229. def log(self, level, msg, *args, **kw):
  230. if args:
  231. if kw:
  232. raise TypeError("You may give positional or keyword arguments, not both")
  233. args = args or kw
  234. rendered = None
  235. for consumer_level, consumer in self.consumers:
  236. if self.level_matches(level, consumer_level):
  237. if self.in_progress_hanging and consumer in (sys.stdout, sys.stderr):
  238. self.in_progress_hanging = False
  239. print("")
  240. sys.stdout.flush()
  241. if rendered is None:
  242. if args:
  243. rendered = msg % args
  244. else:
  245. rendered = msg
  246. rendered = " " * self.indent + rendered
  247. if hasattr(consumer, "write"):
  248. consumer.write(rendered + "\n")
  249. else:
  250. consumer(rendered)
  251. def start_progress(self, msg):
  252. assert not self.in_progress, "Tried to start_progress({!r}) while in_progress {!r}".format(
  253. msg, self.in_progress
  254. )
  255. if self.level_matches(self.NOTIFY, self._stdout_level()):
  256. print(msg)
  257. sys.stdout.flush()
  258. self.in_progress_hanging = True
  259. else:
  260. self.in_progress_hanging = False
  261. self.in_progress = msg
  262. def end_progress(self, msg="done."):
  263. assert self.in_progress, "Tried to end_progress without start_progress"
  264. if self.stdout_level_matches(self.NOTIFY):
  265. if not self.in_progress_hanging:
  266. # Some message has been printed out since start_progress
  267. print("...{}{}".format(self.in_progress, msg))
  268. sys.stdout.flush()
  269. else:
  270. print(msg)
  271. sys.stdout.flush()
  272. self.in_progress = None
  273. self.in_progress_hanging = False
  274. def show_progress(self):
  275. """If we are in a progress scope, and no log messages have been
  276. shown, write out another '.'"""
  277. if self.in_progress_hanging:
  278. print(".")
  279. sys.stdout.flush()
  280. def stdout_level_matches(self, level):
  281. """Returns true if a message at this level will go to stdout"""
  282. return self.level_matches(level, self._stdout_level())
  283. def _stdout_level(self):
  284. """Returns the level that stdout runs at"""
  285. for level, consumer in self.consumers:
  286. if consumer is sys.stdout:
  287. return level
  288. return self.FATAL
  289. def level_matches(self, level, consumer_level):
  290. """
  291. >>> l = Logger([])
  292. >>> l.level_matches(3, 4)
  293. False
  294. >>> l.level_matches(3, 2)
  295. True
  296. >>> l.level_matches(slice(None, 3), 3)
  297. False
  298. >>> l.level_matches(slice(None, 3), 2)
  299. True
  300. >>> l.level_matches(slice(1, 3), 1)
  301. True
  302. >>> l.level_matches(slice(2, 3), 1)
  303. False
  304. """
  305. if isinstance(level, slice):
  306. start, stop = level.start, level.stop
  307. if start is not None and start > consumer_level:
  308. return False
  309. if stop is not None and stop <= consumer_level:
  310. return False
  311. return True
  312. else:
  313. return level >= consumer_level
  314. @classmethod
  315. def level_for_integer(cls, level):
  316. levels = cls.LEVELS
  317. if level < 0:
  318. return levels[0]
  319. if level >= len(levels):
  320. return levels[-1]
  321. return levels[level]
  322. # create a silent logger just to prevent this from being undefined
  323. # will be overridden with requested verbosity main() is called.
  324. logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
  325. def mkdir(path):
  326. if not os.path.exists(path):
  327. logger.info("Creating %s", path)
  328. os.makedirs(path)
  329. else:
  330. logger.info("Directory %s already exists", path)
  331. def copyfileordir(src, dest, symlink=True):
  332. if os.path.isdir(src):
  333. shutil.copytree(src, dest, symlink)
  334. else:
  335. shutil.copy2(src, dest)
  336. def copyfile(src, dest, symlink=True):
  337. if not os.path.exists(src):
  338. # Some bad symlink in the src
  339. logger.warn("Cannot find file %s (bad symlink)", src)
  340. return
  341. if os.path.exists(dest):
  342. logger.debug("File %s already exists", dest)
  343. return
  344. if not os.path.exists(os.path.dirname(dest)):
  345. logger.info("Creating parent directories for %s", os.path.dirname(dest))
  346. os.makedirs(os.path.dirname(dest))
  347. if not os.path.islink(src):
  348. srcpath = os.path.abspath(src)
  349. else:
  350. srcpath = os.readlink(src)
  351. if symlink and hasattr(os, "symlink") and not is_win:
  352. logger.info("Symlinking %s", dest)
  353. try:
  354. os.symlink(srcpath, dest)
  355. except (OSError, NotImplementedError):
  356. logger.info("Symlinking failed, copying to %s", dest)
  357. copyfileordir(src, dest, symlink)
  358. else:
  359. logger.info("Copying to %s", dest)
  360. copyfileordir(src, dest, symlink)
  361. def writefile(dest, content, overwrite=True):
  362. if not os.path.exists(dest):
  363. logger.info("Writing %s", dest)
  364. with open(dest, "wb") as f:
  365. f.write(content.encode("utf-8"))
  366. return
  367. else:
  368. with open(dest, "rb") as f:
  369. c = f.read()
  370. if c != content.encode("utf-8"):
  371. if not overwrite:
  372. logger.notify("File %s exists with different content; not overwriting", dest)
  373. return
  374. logger.notify("Overwriting %s with new content", dest)
  375. with open(dest, "wb") as f:
  376. f.write(content.encode("utf-8"))
  377. else:
  378. logger.info("Content %s already in place", dest)
  379. def rmtree(dir):
  380. if os.path.exists(dir):
  381. logger.notify("Deleting tree %s", dir)
  382. shutil.rmtree(dir)
  383. else:
  384. logger.info("Do not need to delete %s; already gone", dir)
  385. def make_exe(fn):
  386. if hasattr(os, "chmod"):
  387. oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
  388. newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
  389. os.chmod(fn, newmode)
  390. logger.info("Changed mode of %s to %s", fn, oct(newmode))
  391. def _find_file(filename, dirs):
  392. for dir in reversed(dirs):
  393. files = glob.glob(os.path.join(dir, filename))
  394. if files and os.path.isfile(files[0]):
  395. return True, files[0]
  396. return False, filename
  397. def file_search_dirs():
  398. here = os.path.dirname(os.path.abspath(__file__))
  399. dirs = [here, join(here, "virtualenv_support")]
  400. if os.path.splitext(os.path.dirname(__file__))[0] != "virtualenv":
  401. # Probably some boot script; just in case virtualenv is installed...
  402. try:
  403. import virtualenv
  404. except ImportError:
  405. pass
  406. else:
  407. dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), "virtualenv_support"))
  408. return [d for d in dirs if os.path.isdir(d)]
  409. class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
  410. """
  411. Custom help formatter for use in ConfigOptionParser that updates
  412. the defaults before expanding them, allowing them to show up correctly
  413. in the help listing
  414. """
  415. def expand_default(self, option):
  416. if self.parser is not None:
  417. self.parser.update_defaults(self.parser.defaults)
  418. return optparse.IndentedHelpFormatter.expand_default(self, option)
  419. class ConfigOptionParser(optparse.OptionParser):
  420. """
  421. Custom option parser which updates its defaults by checking the
  422. configuration files and environmental variables
  423. """
  424. def __init__(self, *args, **kwargs):
  425. self.config = ConfigParser.RawConfigParser()
  426. self.files = self.get_config_files()
  427. self.config.read(self.files)
  428. optparse.OptionParser.__init__(self, *args, **kwargs)
  429. def get_config_files(self):
  430. config_file = os.environ.get("VIRTUALENV_CONFIG_FILE", False)
  431. if config_file and os.path.exists(config_file):
  432. return [config_file]
  433. return [default_config_file]
  434. def update_defaults(self, defaults):
  435. """
  436. Updates the given defaults with values from the config files and
  437. the environ. Does a little special handling for certain types of
  438. options (lists).
  439. """
  440. # Then go and look for the other sources of configuration:
  441. config = {}
  442. # 1. config files
  443. config.update(dict(self.get_config_section("virtualenv")))
  444. # 2. environmental variables
  445. config.update(dict(self.get_environ_vars()))
  446. # Then set the options with those values
  447. for key, val in config.items():
  448. key = key.replace("_", "-")
  449. if not key.startswith("--"):
  450. key = "--%s" % key # only prefer long opts
  451. option = self.get_option(key)
  452. if option is not None:
  453. # ignore empty values
  454. if not val:
  455. continue
  456. # handle multiline configs
  457. if option.action == "append":
  458. val = val.split()
  459. else:
  460. option.nargs = 1
  461. if option.action == "store_false":
  462. val = not strtobool(val)
  463. elif option.action in ("store_true", "count"):
  464. val = strtobool(val)
  465. try:
  466. val = option.convert_value(key, val)
  467. except optparse.OptionValueError:
  468. e = sys.exc_info()[1]
  469. print("An error occurred during configuration: %s" % e)
  470. sys.exit(3)
  471. defaults[option.dest] = val
  472. return defaults
  473. def get_config_section(self, name):
  474. """
  475. Get a section of a configuration
  476. """
  477. if self.config.has_section(name):
  478. return self.config.items(name)
  479. return []
  480. def get_environ_vars(self, prefix="VIRTUALENV_"):
  481. """
  482. Returns a generator with all environmental vars with prefix VIRTUALENV
  483. """
  484. for key, val in os.environ.items():
  485. if key.startswith(prefix):
  486. yield (key.replace(prefix, "").lower(), val)
  487. def get_default_values(self):
  488. """
  489. Overridding to make updating the defaults after instantiation of
  490. the option parser possible, update_defaults() does the dirty work.
  491. """
  492. if not self.process_default_values:
  493. # Old, pre-Optik 1.5 behaviour.
  494. return optparse.Values(self.defaults)
  495. defaults = self.update_defaults(self.defaults.copy()) # ours
  496. for option in self._get_all_options():
  497. default = defaults.get(option.dest)
  498. if isinstance(default, basestring):
  499. opt_str = option.get_opt_string()
  500. defaults[option.dest] = option.check_value(opt_str, default)
  501. return optparse.Values(defaults)
  502. def main():
  503. parser = ConfigOptionParser(
  504. version=virtualenv_version, usage="%prog [OPTIONS] DEST_DIR", formatter=UpdatingDefaultsHelpFormatter()
  505. )
  506. parser.add_option("-v", "--verbose", action="count", dest="verbose", default=0, help="Increase verbosity.")
  507. parser.add_option("-q", "--quiet", action="count", dest="quiet", default=0, help="Decrease verbosity.")
  508. parser.add_option(
  509. "-p",
  510. "--python",
  511. dest="python",
  512. metavar="PYTHON_EXE",
  513. help="The Python interpreter to use, e.g., --python=python3.5 will use the python3.5 "
  514. "interpreter to create the new environment. The default is the interpreter that "
  515. "virtualenv was installed with (%s)" % sys.executable,
  516. )
  517. parser.add_option(
  518. "--clear", dest="clear", action="store_true", help="Clear out the non-root install and start from scratch."
  519. )
  520. parser.set_defaults(system_site_packages=False)
  521. parser.add_option(
  522. "--no-site-packages",
  523. dest="system_site_packages",
  524. action="store_false",
  525. help="DEPRECATED. Retained only for backward compatibility. "
  526. "Not having access to global site-packages is now the default behavior.",
  527. )
  528. parser.add_option(
  529. "--system-site-packages",
  530. dest="system_site_packages",
  531. action="store_true",
  532. help="Give the virtual environment access to the global site-packages.",
  533. )
  534. parser.add_option(
  535. "--always-copy",
  536. dest="symlink",
  537. action="store_false",
  538. default=True,
  539. help="Always copy files rather than symlinking.",
  540. )
  541. parser.add_option(
  542. "--relocatable",
  543. dest="relocatable",
  544. action="store_true",
  545. help="Make an EXISTING virtualenv environment relocatable. "
  546. "This fixes up scripts and makes all .pth files relative.",
  547. )
  548. parser.add_option(
  549. "--no-setuptools",
  550. dest="no_setuptools",
  551. action="store_true",
  552. help="Do not install setuptools in the new virtualenv.",
  553. )
  554. parser.add_option("--no-pip", dest="no_pip", action="store_true", help="Do not install pip in the new virtualenv.")
  555. parser.add_option(
  556. "--no-wheel", dest="no_wheel", action="store_true", help="Do not install wheel in the new virtualenv."
  557. )
  558. default_search_dirs = file_search_dirs()
  559. parser.add_option(
  560. "--extra-search-dir",
  561. dest="search_dirs",
  562. action="append",
  563. metavar="DIR",
  564. default=default_search_dirs,
  565. help="Directory to look for setuptools/pip distributions in. " "This option can be used multiple times.",
  566. )
  567. parser.add_option(
  568. "--download",
  569. dest="download",
  570. default=True,
  571. action="store_true",
  572. help="Download preinstalled packages from PyPI.",
  573. )
  574. parser.add_option(
  575. "--no-download",
  576. "--never-download",
  577. dest="download",
  578. action="store_false",
  579. help="Do not download preinstalled packages from PyPI.",
  580. )
  581. parser.add_option("--prompt", dest="prompt", help="Provides an alternative prompt prefix for this environment.")
  582. parser.add_option(
  583. "--setuptools",
  584. dest="setuptools",
  585. action="store_true",
  586. help="DEPRECATED. Retained only for backward compatibility. This option has no effect.",
  587. )
  588. parser.add_option(
  589. "--distribute",
  590. dest="distribute",
  591. action="store_true",
  592. help="DEPRECATED. Retained only for backward compatibility. This option has no effect.",
  593. )
  594. parser.add_option(
  595. "--unzip-setuptools",
  596. action="store_true",
  597. help="DEPRECATED. Retained only for backward compatibility. This option has no effect.",
  598. )
  599. if "extend_parser" in globals():
  600. extend_parser(parser) # noqa: F821
  601. options, args = parser.parse_args()
  602. global logger
  603. if "adjust_options" in globals():
  604. adjust_options(options, args) # noqa: F821
  605. verbosity = options.verbose - options.quiet
  606. logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
  607. if options.python and not os.environ.get("VIRTUALENV_INTERPRETER_RUNNING"):
  608. env = os.environ.copy()
  609. interpreter = resolve_interpreter(options.python)
  610. if interpreter == sys.executable:
  611. logger.warn("Already using interpreter %s" % interpreter)
  612. else:
  613. logger.notify("Running virtualenv with interpreter %s" % interpreter)
  614. env["VIRTUALENV_INTERPRETER_RUNNING"] = "true"
  615. file = __file__
  616. if file.endswith(".pyc"):
  617. file = file[:-1]
  618. popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env)
  619. raise SystemExit(popen.wait())
  620. if not args:
  621. print("You must provide a DEST_DIR")
  622. parser.print_help()
  623. sys.exit(2)
  624. if len(args) > 1:
  625. print("There must be only one argument: DEST_DIR (you gave %s)" % (" ".join(args)))
  626. parser.print_help()
  627. sys.exit(2)
  628. home_dir = args[0]
  629. if os.path.exists(home_dir) and os.path.isfile(home_dir):
  630. logger.fatal("ERROR: File already exists and is not a directory.")
  631. logger.fatal("Please provide a different path or delete the file.")
  632. sys.exit(3)
  633. if os.environ.get("WORKING_ENV"):
  634. logger.fatal("ERROR: you cannot run virtualenv while in a workingenv")
  635. logger.fatal("Please deactivate your workingenv, then re-run this script")
  636. sys.exit(3)
  637. if "PYTHONHOME" in os.environ:
  638. logger.warn("PYTHONHOME is set. You *must* activate the virtualenv before using it")
  639. del os.environ["PYTHONHOME"]
  640. if options.relocatable:
  641. make_environment_relocatable(home_dir)
  642. return
  643. create_environment(
  644. home_dir,
  645. site_packages=options.system_site_packages,
  646. clear=options.clear,
  647. prompt=options.prompt,
  648. search_dirs=options.search_dirs,
  649. download=options.download,
  650. no_setuptools=options.no_setuptools,
  651. no_pip=options.no_pip,
  652. no_wheel=options.no_wheel,
  653. symlink=options.symlink,
  654. )
  655. if "after_install" in globals():
  656. after_install(options, home_dir) # noqa: F821
  657. def call_subprocess(
  658. cmd,
  659. show_stdout=True,
  660. filter_stdout=None,
  661. cwd=None,
  662. raise_on_returncode=True,
  663. extra_env=None,
  664. remove_from_env=None,
  665. stdin=None,
  666. ):
  667. cmd_parts = []
  668. for part in cmd:
  669. if len(part) > 45:
  670. part = part[:20] + "..." + part[-20:]
  671. if " " in part or "\n" in part or '"' in part or "'" in part:
  672. part = '"%s"' % part.replace('"', '\\"')
  673. if hasattr(part, "decode"):
  674. try:
  675. part = part.decode(sys.getdefaultencoding())
  676. except UnicodeDecodeError:
  677. part = part.decode(sys.getfilesystemencoding())
  678. cmd_parts.append(part)
  679. cmd_desc = " ".join(cmd_parts)
  680. if show_stdout:
  681. stdout = None
  682. else:
  683. stdout = subprocess.PIPE
  684. logger.debug("Running command %s" % cmd_desc)
  685. if extra_env or remove_from_env:
  686. env = os.environ.copy()
  687. if extra_env:
  688. env.update(extra_env)
  689. if remove_from_env:
  690. for varname in remove_from_env:
  691. env.pop(varname, None)
  692. else:
  693. env = None
  694. try:
  695. proc = subprocess.Popen(
  696. cmd,
  697. stderr=subprocess.STDOUT,
  698. stdin=None if stdin is None else subprocess.PIPE,
  699. stdout=stdout,
  700. cwd=cwd,
  701. env=env,
  702. )
  703. except Exception:
  704. e = sys.exc_info()[1]
  705. logger.fatal("Error {} while executing command {}".format(e, cmd_desc))
  706. raise
  707. all_output = []
  708. if stdout is not None:
  709. if stdin is not None:
  710. proc.stdin.write(stdin)
  711. proc.stdin.close()
  712. stdout = proc.stdout
  713. encoding = sys.getdefaultencoding()
  714. fs_encoding = sys.getfilesystemencoding()
  715. while 1:
  716. line = stdout.readline()
  717. try:
  718. line = line.decode(encoding)
  719. except UnicodeDecodeError:
  720. line = line.decode(fs_encoding)
  721. if not line:
  722. break
  723. line = line.rstrip()
  724. all_output.append(line)
  725. if filter_stdout:
  726. level = filter_stdout(line)
  727. if isinstance(level, tuple):
  728. level, line = level
  729. logger.log(level, line)
  730. if not logger.stdout_level_matches(level):
  731. logger.show_progress()
  732. else:
  733. logger.info(line)
  734. else:
  735. proc.communicate(stdin)
  736. proc.wait()
  737. if proc.returncode:
  738. if raise_on_returncode:
  739. if all_output:
  740. logger.notify("Complete output from command %s:" % cmd_desc)
  741. logger.notify("\n".join(all_output) + "\n----------------------------------------")
  742. raise OSError("Command {} failed with error code {}".format(cmd_desc, proc.returncode))
  743. else:
  744. logger.warn("Command {} had error code {}".format(cmd_desc, proc.returncode))
  745. def filter_install_output(line):
  746. if line.strip().startswith("running"):
  747. return Logger.INFO
  748. return Logger.DEBUG
  749. def find_wheels(projects, search_dirs):
  750. """Find wheels from which we can import PROJECTS.
  751. Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return
  752. a list of the first wheel found for each PROJECT
  753. """
  754. wheels = []
  755. # Look through SEARCH_DIRS for the first suitable wheel. Don't bother
  756. # about version checking here, as this is simply to get something we can
  757. # then use to install the correct version.
  758. for project in projects:
  759. for dirname in search_dirs:
  760. # This relies on only having "universal" wheels available.
  761. # The pattern could be tightened to require -py2.py3-none-any.whl.
  762. files = glob.glob(os.path.join(dirname, project + "-*.whl"))
  763. if files:
  764. wheels.append(os.path.abspath(files[0]))
  765. break
  766. else:
  767. # We're out of luck, so quit with a suitable error
  768. logger.fatal("Cannot find a wheel for {}".format(project))
  769. return wheels
  770. def install_wheel(project_names, py_executable, search_dirs=None, download=False):
  771. if search_dirs is None:
  772. search_dirs = file_search_dirs()
  773. wheels = find_wheels(["setuptools", "pip"], search_dirs)
  774. python_path = os.pathsep.join(wheels)
  775. # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths
  776. # with spaces in them. Convert any of those to local file:// URL form.
  777. try:
  778. from urlparse import urljoin
  779. from urllib import pathname2url
  780. except ImportError:
  781. from urllib.parse import urljoin
  782. from urllib.request import pathname2url
  783. def space_path2url(p):
  784. if " " not in p:
  785. return p
  786. return urljoin("file:", pathname2url(os.path.abspath(p)))
  787. findlinks = " ".join(space_path2url(d) for d in search_dirs)
  788. SCRIPT = textwrap.dedent(
  789. """
  790. import sys
  791. import pkgutil
  792. import tempfile
  793. import os
  794. try:
  795. from pip._internal import main as _main
  796. cert_data = pkgutil.get_data("pip._vendor.certifi", "cacert.pem")
  797. except ImportError:
  798. from pip import main as _main
  799. cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem")
  800. if cert_data is not None:
  801. cert_file = tempfile.NamedTemporaryFile(delete=False)
  802. cert_file.write(cert_data)
  803. cert_file.close()
  804. else:
  805. cert_file = None
  806. try:
  807. args = ["install", "--ignore-installed"]
  808. if cert_file is not None:
  809. args += ["--cert", cert_file.name{}]
  810. args += sys.argv[1:]
  811. sys.exit(_main(args))
  812. finally:
  813. if cert_file is not None:
  814. os.remove(cert_file.name)
  815. """.format(
  816. ", '--no-cache'" if is_jython else ""
  817. )
  818. ).encode("utf8")
  819. cmd = [py_executable, "-"] + project_names
  820. logger.start_progress("Installing %s..." % (", ".join(project_names)))
  821. logger.indent += 2
  822. env = {
  823. "PYTHONPATH": python_path,
  824. "JYTHONPATH": python_path, # for Jython < 3.x
  825. "PIP_FIND_LINKS": findlinks,
  826. "PIP_USE_WHEEL": "1",
  827. "PIP_ONLY_BINARY": ":all:",
  828. "PIP_USER": "0",
  829. "PIP_NO_INPUT": "1",
  830. }
  831. if not download:
  832. env["PIP_NO_INDEX"] = "1"
  833. try:
  834. call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT)
  835. finally:
  836. logger.indent -= 2
  837. logger.end_progress()
  838. def create_environment(
  839. home_dir,
  840. site_packages=False,
  841. clear=False,
  842. prompt=None,
  843. search_dirs=None,
  844. download=False,
  845. no_setuptools=False,
  846. no_pip=False,
  847. no_wheel=False,
  848. symlink=True,
  849. ):
  850. """
  851. Creates a new environment in ``home_dir``.
  852. If ``site_packages`` is true, then the global ``site-packages/``
  853. directory will be on the path.
  854. If ``clear`` is true (default False) then the environment will
  855. first be cleared.
  856. """
  857. home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
  858. py_executable = os.path.abspath(
  859. install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages=site_packages, clear=clear, symlink=symlink)
  860. )
  861. install_distutils(home_dir)
  862. to_install = []
  863. if not no_setuptools:
  864. to_install.append("setuptools")
  865. if not no_pip:
  866. to_install.append("pip")
  867. if not no_wheel:
  868. to_install.append("wheel")
  869. if to_install:
  870. install_wheel(to_install, py_executable, search_dirs, download=download)
  871. install_activate(home_dir, bin_dir, prompt)
  872. install_python_config(home_dir, bin_dir, prompt)
  873. def is_executable_file(fpath):
  874. return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
  875. def path_locations(home_dir, dry_run=False):
  876. """Return the path locations for the environment (where libraries are,
  877. where scripts go, etc)"""
  878. home_dir = os.path.abspath(home_dir)
  879. # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
  880. # prefix arg is broken: http://bugs.python.org/issue3386
  881. if is_win:
  882. # Windows has lots of problems with executables with spaces in
  883. # the name; this function will remove them (using the ~1
  884. # format):
  885. if not dry_run:
  886. mkdir(home_dir)
  887. if " " in home_dir:
  888. import ctypes
  889. GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
  890. size = max(len(home_dir) + 1, 256)
  891. buf = ctypes.create_unicode_buffer(size)
  892. try:
  893. u = unicode
  894. except NameError:
  895. u = str
  896. ret = GetShortPathName(u(home_dir), buf, size)
  897. if not ret:
  898. print('Error: the path "%s" has a space in it' % home_dir)
  899. print("We could not determine the short pathname for it.")
  900. print("Exiting.")
  901. sys.exit(3)
  902. home_dir = str(buf.value)
  903. lib_dir = join(home_dir, "Lib")
  904. inc_dir = join(home_dir, "Include")
  905. bin_dir = join(home_dir, "Scripts")
  906. if is_jython:
  907. lib_dir = join(home_dir, "Lib")
  908. inc_dir = join(home_dir, "Include")
  909. bin_dir = join(home_dir, "bin")
  910. elif is_pypy:
  911. lib_dir = home_dir
  912. inc_dir = join(home_dir, "include")
  913. bin_dir = join(home_dir, "bin")
  914. elif not is_win:
  915. lib_dir = join(home_dir, "lib", py_version)
  916. inc_dir = join(home_dir, "include", py_version + abiflags)
  917. bin_dir = join(home_dir, "bin")
  918. return home_dir, lib_dir, inc_dir, bin_dir
  919. def change_prefix(filename, dst_prefix):
  920. prefixes = [sys.prefix]
  921. if is_darwin:
  922. prefixes.extend(
  923. (
  924. os.path.join("/Library/Python", sys.version[:3], "site-packages"),
  925. os.path.join(sys.prefix, "Extras", "lib", "python"),
  926. os.path.join("~", "Library", "Python", sys.version[:3], "site-packages"),
  927. # Python 2.6 no-frameworks
  928. os.path.join("~", ".local", "lib", "python", sys.version[:3], "site-packages"),
  929. # System Python 2.7 on OSX Mountain Lion
  930. os.path.join("~", "Library", "Python", sys.version[:3], "lib", "python", "site-packages"),
  931. )
  932. )
  933. if hasattr(sys, "real_prefix"):
  934. prefixes.append(sys.real_prefix)
  935. if hasattr(sys, "base_prefix"):
  936. prefixes.append(sys.base_prefix)
  937. prefixes = list(map(os.path.expanduser, prefixes))
  938. prefixes = list(map(os.path.abspath, prefixes))
  939. # Check longer prefixes first so we don't split in the middle of a filename
  940. prefixes = sorted(prefixes, key=len, reverse=True)
  941. filename = os.path.abspath(filename)
  942. # On Windows, make sure drive letter is uppercase
  943. if is_win and filename[0] in "abcdefghijklmnopqrstuvwxyz":
  944. filename = filename[0].upper() + filename[1:]
  945. for i, prefix in enumerate(prefixes):
  946. if is_win and prefix[0] in "abcdefghijklmnopqrstuvwxyz":
  947. prefixes[i] = prefix[0].upper() + prefix[1:]
  948. for src_prefix in prefixes:
  949. if filename.startswith(src_prefix):
  950. _, relpath = filename.split(src_prefix, 1)
  951. if src_prefix != os.sep: # sys.prefix == "/"
  952. assert relpath[0] == os.sep
  953. relpath = relpath[1:]
  954. return join(dst_prefix, relpath)
  955. assert False, "Filename {} does not start with any of these prefixes: {}".format(filename, prefixes)
  956. def copy_required_modules(dst_prefix, symlink):
  957. import warnings
  958. with warnings.catch_warnings():
  959. # Ignore deprecation of the imp module
  960. # TODO: do not use deprecated imp module
  961. warnings.simplefilter("ignore")
  962. import imp
  963. for modname in REQUIRED_MODULES:
  964. if modname in sys.builtin_module_names:
  965. logger.info("Ignoring built-in bootstrap module: %s" % modname)
  966. continue
  967. try:
  968. f, filename, _ = imp.find_module(modname)
  969. except ImportError:
  970. logger.info("Cannot import bootstrap module: %s" % modname)
  971. else:
  972. if f is not None:
  973. f.close()
  974. # special-case custom readline.so on OS X, but not for pypy:
  975. if (
  976. modname == "readline"
  977. and sys.platform == "darwin"
  978. and not (is_pypy or filename.endswith(join("lib-dynload", "readline.so")))
  979. ):
  980. dst_filename = join(dst_prefix, "lib", "python%s" % sys.version[:3], "readline.so")
  981. elif modname == "readline" and sys.platform == "win32":
  982. # special-case for Windows, where readline is not a
  983. # standard module, though it may have been installed in
  984. # site-packages by a third-party package
  985. pass
  986. else:
  987. dst_filename = change_prefix(filename, dst_prefix)
  988. copyfile(filename, dst_filename, symlink)
  989. if filename.endswith(".pyc"):
  990. pyfile = filename[:-1]
  991. if os.path.exists(pyfile):
  992. copyfile(pyfile, dst_filename[:-1], symlink)
  993. def copy_tcltk(src, dest, symlink):
  994. """ copy tcl/tk libraries on Windows (issue #93) """
  995. for libversion in "8.5", "8.6":
  996. for libname in "tcl", "tk":
  997. srcdir = join(src, "tcl", libname + libversion)
  998. destdir = join(dest, "tcl", libname + libversion)
  999. # Only copy the dirs from the above combinations that exist
  1000. if os.path.exists(srcdir) and not os.path.exists(destdir):
  1001. copyfileordir(srcdir, destdir, symlink)
  1002. def subst_path(prefix_path, prefix, home_dir):
  1003. prefix_path = os.path.normpath(prefix_path)
  1004. prefix = os.path.normpath(prefix)
  1005. home_dir = os.path.normpath(home_dir)
  1006. if not prefix_path.startswith(prefix):
  1007. logger.warn("Path not in prefix %r %r", prefix_path, prefix)
  1008. return
  1009. return prefix_path.replace(prefix, home_dir, 1)
  1010. def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, symlink=True):
  1011. """Install just the base environment, no distutils patches etc"""
  1012. if sys.executable.startswith(bin_dir):
  1013. print("Please use the *system* python to run this script")
  1014. return
  1015. if clear:
  1016. rmtree(lib_dir)
  1017. # FIXME: why not delete it?
  1018. # Maybe it should delete everything with #!/path/to/venv/python in it
  1019. logger.notify("Not deleting %s", bin_dir)
  1020. if hasattr(sys, "real_prefix"):
  1021. logger.notify("Using real prefix %r" % sys.real_prefix)
  1022. prefix = sys.real_prefix
  1023. elif hasattr(sys, "base_prefix"):
  1024. logger.notify("Using base prefix %r" % sys.base_prefix)
  1025. prefix = sys.base_prefix
  1026. else:
  1027. prefix = sys.prefix
  1028. prefix = os.path.abspath(prefix)
  1029. mkdir(lib_dir)
  1030. fix_lib64(lib_dir, symlink)
  1031. stdlib_dirs = [os.path.dirname(os.__file__)]
  1032. if is_win:
  1033. stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), "DLLs"))
  1034. elif is_darwin:
  1035. stdlib_dirs.append(join(stdlib_dirs[0], "site-packages"))
  1036. if hasattr(os, "symlink"):
  1037. logger.info("Symlinking Python bootstrap modules")
  1038. else:
  1039. logger.info("Copying Python bootstrap modules")
  1040. logger.indent += 2
  1041. try:
  1042. # copy required files...
  1043. for stdlib_dir in stdlib_dirs:
  1044. if not os.path.isdir(stdlib_dir):
  1045. continue
  1046. for fn in os.listdir(stdlib_dir):
  1047. bn = os.path.splitext(fn)[0]
  1048. if fn != "site-packages" and bn in REQUIRED_FILES:
  1049. copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink)
  1050. # ...and modules
  1051. copy_required_modules(home_dir, symlink)
  1052. finally:
  1053. logger.indent -= 2
  1054. # ...copy tcl/tk
  1055. if is_win:
  1056. copy_tcltk(prefix, home_dir, symlink)
  1057. mkdir(join(lib_dir, "site-packages"))
  1058. import site
  1059. site_filename = site.__file__
  1060. if site_filename.endswith(".pyc") or site_filename.endswith(".pyo"):
  1061. site_filename = site_filename[:-1]
  1062. elif site_filename.endswith("$py.class"):
  1063. site_filename = site_filename.replace("$py.class", ".py")
  1064. site_filename_dst = change_prefix(site_filename, home_dir)
  1065. site_dir = os.path.dirname(site_filename_dst)
  1066. writefile(site_filename_dst, SITE_PY)
  1067. writefile(join(site_dir, "orig-prefix.txt"), prefix)
  1068. site_packages_filename = join(site_dir, "no-global-site-packages.txt")
  1069. if not site_packages:
  1070. writefile(site_packages_filename, "")
  1071. if is_pypy or is_win:
  1072. stdinc_dir = join(prefix, "include")
  1073. else:
  1074. stdinc_dir = join(prefix, "include", py_version + abiflags)
  1075. if os.path.exists(stdinc_dir):
  1076. copyfile(stdinc_dir, inc_dir, symlink)
  1077. else:
  1078. logger.debug("No include dir %s" % stdinc_dir)
  1079. platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
  1080. if platinc_dir != stdinc_dir:
  1081. platinc_dest = distutils.sysconfig.get_python_inc(plat_specific=1, prefix=home_dir)
  1082. if platinc_dir == platinc_dest:
  1083. # Do platinc_dest manually due to a CPython bug;
  1084. # not http://bugs.python.org/issue3386 but a close cousin
  1085. platinc_dest = subst_path(platinc_dir, prefix, home_dir)
  1086. if platinc_dest:
  1087. # PyPy's stdinc_dir and prefix are relative to the original binary
  1088. # (traversing virtualenvs), whereas the platinc_dir is relative to
  1089. # the inner virtualenv and ignores the prefix argument.
  1090. # This seems more evolved than designed.
  1091. copyfile(platinc_dir, platinc_dest, symlink)
  1092. # pypy never uses exec_prefix, just ignore it
  1093. if sys.exec_prefix != prefix and not is_pypy:
  1094. if is_win:
  1095. exec_dir = join(sys.exec_prefix, "lib")
  1096. elif is_jython:
  1097. exec_dir = join(sys.exec_prefix, "Lib")
  1098. else:
  1099. exec_dir = join(sys.exec_prefix, "lib", py_version)
  1100. if os.path.isdir(exec_dir):
  1101. for fn in os.listdir(exec_dir):
  1102. copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink)
  1103. if is_jython:
  1104. # Jython has either jython-dev.jar and javalib/ dir, or just
  1105. # jython.jar
  1106. for name in "jython-dev.jar", "javalib", "jython.jar":
  1107. src = join(prefix, name)
  1108. if os.path.exists(src):
  1109. copyfile(src, join(home_dir, name), symlink)
  1110. # XXX: registry should always exist after Jython 2.5rc1
  1111. src = join(prefix, "registry")
  1112. if os.path.exists(src):
  1113. copyfile(src, join(home_dir, "registry"), symlink=False)
  1114. copyfile(join(prefix, "cachedir"), join(home_dir, "cachedir"), symlink=False)
  1115. mkdir(bin_dir)
  1116. py_executable = join(bin_dir, os.path.basename(sys.executable))
  1117. if "Python.framework" in prefix:
  1118. # OS X framework builds cause validation to break
  1119. # https://github.com/pypa/virtualenv/issues/322
  1120. if os.environ.get("__PYVENV_LAUNCHER__"):
  1121. del os.environ["__PYVENV_LAUNCHER__"]
  1122. if re.search(r"/Python(?:-32|-64)*$", py_executable):
  1123. # The name of the python executable is not quite what
  1124. # we want, rename it.
  1125. py_executable = os.path.join(os.path.dirname(py_executable), "python")
  1126. logger.notify("New %s executable in %s", expected_exe, py_executable)
  1127. pcbuild_dir = os.path.dirname(sys.executable)
  1128. pyd_pth = os.path.join(lib_dir, "site-packages", "virtualenv_builddir_pyd.pth")
  1129. if is_win and os.path.exists(os.path.join(pcbuild_dir, "build.bat")):
  1130. logger.notify("Detected python running from build directory %s", pcbuild_dir)
  1131. logger.notify("Writing .pth file linking to build directory for *.pyd files")
  1132. writefile(pyd_pth, pcbuild_dir)
  1133. else:
  1134. pcbuild_dir = None
  1135. if os.path.exists(pyd_pth):
  1136. logger.info("Deleting %s (not Windows env or not build directory python)" % pyd_pth)
  1137. os.unlink(pyd_pth)
  1138. if sys.executable != py_executable:
  1139. # FIXME: could I just hard link?
  1140. executable = sys.executable
  1141. shutil.copyfile(executable, py_executable)
  1142. make_exe(py_executable)
  1143. if is_win or is_cygwin:
  1144. pythonw = os.path.join(os.path.dirname(sys.executable), "pythonw.exe")
  1145. if os.path.exists(pythonw):
  1146. logger.info("Also created pythonw.exe")
  1147. shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executable), "pythonw.exe"))
  1148. python_d = os.path.join(os.path.dirname(sys.executable), "python_d.exe")
  1149. python_d_dest = os.path.join(os.path.dirname(py_executable), "python_d.exe")
  1150. if os.path.exists(python_d):
  1151. logger.info("Also created python_d.exe")
  1152. shutil.copyfile(python_d, python_d_dest)
  1153. elif os.path.exists(python_d_dest):
  1154. logger.info("Removed python_d.exe as it is no longer at the source")
  1155. os.unlink(python_d_dest)
  1156. # we need to copy the DLL to enforce that windows will load the correct one.
  1157. # may not exist if we are cygwin.
  1158. if is_pypy:
  1159. py_executable_dlls = [("libpypy-c.dll", "libpypy_d-c.dll")]
  1160. else:
  1161. py_executable_dlls = [
  1162. ("python%s.dll" % (sys.version_info[0]), "python%s_d.dll" % (sys.version_info[0])),
  1163. (
  1164. "python{}{}.dll".format(sys.version_info[0], sys.version_info[1]),
  1165. "python{}{}_d.dll".format(sys.version_info[0], sys.version_info[1]),
  1166. ),
  1167. ]
  1168. for py_executable_dll, py_executable_dll_d in py_executable_dlls:
  1169. pythondll = os.path.join(os.path.dirname(sys.executable), py_executable_dll)
  1170. pythondll_d = os.path.join(os.path.dirname(sys.executable), py_executable_dll_d)
  1171. pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_executable_dll_d)
  1172. if os.path.exists(pythondll):
  1173. logger.info("Also created %s" % py_executable_dll)
  1174. shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_executable), py_executable_dll))
  1175. if os.path.exists(pythondll_d):
  1176. logger.info("Also created %s" % py_executable_dll_d)
  1177. shutil.copyfile(pythondll_d, pythondll_d_dest)
  1178. elif os.path.exists(pythondll_d_dest):
  1179. logger.info("Removed %s as the source does not exist" % pythondll_d_dest)
  1180. os.unlink(pythondll_d_dest)
  1181. if is_pypy:
  1182. # make a symlink python --> pypy-c
  1183. python_executable = os.path.join(os.path.dirname(py_executable), "python")
  1184. if sys.platform in ("win32", "cygwin"):
  1185. python_executable += ".exe"
  1186. logger.info("Also created executable %s" % python_executable)
  1187. copyfile(py_executable, python_executable, symlink)
  1188. if is_win:
  1189. for name in ["libexpat.dll", "libeay32.dll", "ssleay32.dll", "sqlite3.dll", "tcl85.dll", "tk85.dll"]:
  1190. src = join(prefix, name)
  1191. if os.path.exists(src):
  1192. copyfile(src, join(bin_dir, name), symlink)
  1193. for d in sys.path:
  1194. if d.endswith("lib_pypy"):
  1195. break
  1196. else:
  1197. logger.fatal("Could not find lib_pypy in sys.path")
  1198. raise SystemExit(3)
  1199. logger.info("Copying lib_pypy")
  1200. copyfile(d, os.path.join(home_dir, "lib_pypy"), symlink)
  1201. if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
  1202. secondary_exe = os.path.join(os.path.dirname(py_executable), expected_exe)
  1203. py_executable_ext = os.path.splitext(py_executable)[1]
  1204. if py_executable_ext.lower() == ".exe":
  1205. # python2.4 gives an extension of '.4' :P
  1206. secondary_exe += py_executable_ext
  1207. if os.path.exists(secondary_exe):
  1208. logger.warn(
  1209. "Not overwriting existing {} script {} (you must use {})".format(
  1210. expected_exe, secondary_exe, py_executable
  1211. )
  1212. )
  1213. else:
  1214. logger.notify("Also creating executable in %s" % secondary_exe)
  1215. shutil.copyfile(sys.executable, secondary_exe)
  1216. make_exe(secondary_exe)
  1217. if ".framework" in prefix:
  1218. if "Python.framework" in prefix:
  1219. logger.debug("MacOSX Python framework detected")
  1220. # Make sure we use the embedded interpreter inside
  1221. # the framework, even if sys.executable points to
  1222. # the stub executable in ${sys.prefix}/bin
  1223. # See http://groups.google.com/group/python-virtualenv/
  1224. # browse_thread/thread/17cab2f85da75951
  1225. original_python = os.path.join(prefix, "Resources/Python.app/Contents/MacOS/Python")
  1226. if "EPD" in prefix:
  1227. logger.debug("EPD framework detected")
  1228. original_python = os.path.join(prefix, "bin/python")
  1229. shutil.copy(original_python, py_executable)
  1230. # Copy the framework's dylib into the virtual
  1231. # environment
  1232. virtual_lib = os.path.join(home_dir, ".Python")
  1233. if os.path.exists(virtual_lib):
  1234. os.unlink(virtual_lib)
  1235. copyfile(os.path.join(prefix, "Python"), virtual_lib, symlink)
  1236. # And then change the install_name of the copied python executable
  1237. try:
  1238. mach_o_change(py_executable, os.path.join(prefix, "Python"), "@executable_path/../.Python")
  1239. except Exception:
  1240. e = sys.exc_info()[1]
  1241. logger.warn("Could not call mach_o_change: %s. " "Trying to call install_name_tool instead." % e)
  1242. try:
  1243. call_subprocess(
  1244. [
  1245. "install_name_tool",
  1246. "-change",
  1247. os.path.join(prefix, "Python"),
  1248. "@executable_path/../.Python",
  1249. py_executable,
  1250. ]
  1251. )
  1252. except Exception:
  1253. logger.fatal("Could not call install_name_tool -- you must " "have Apple's development tools installed")
  1254. raise
  1255. if not is_win:
  1256. # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
  1257. py_exe_version_major = "python%s" % sys.version_info[0]
  1258. py_exe_version_major_minor = "python{}.{}".format(sys.version_info[0], sys.version_info[1])
  1259. py_exe_no_version = "python"
  1260. required_symlinks = [py_exe_no_version, py_exe_version_major, py_exe_version_major_minor]
  1261. py_executable_base = os.path.basename(py_executable)
  1262. if py_executable_base in required_symlinks:
  1263. # Don't try to symlink to yourself.
  1264. required_symlinks.remove(py_executable_base)
  1265. for pth in required_symlinks:
  1266. full_pth = join(bin_dir, pth)
  1267. if os.path.exists(full_pth):
  1268. os.unlink(full_pth)
  1269. if symlink:
  1270. os.symlink(py_executable_base, full_pth)
  1271. else:
  1272. copyfile(py_executable, full_pth, symlink)
  1273. cmd = [
  1274. py_executable,
  1275. "-c",
  1276. "import sys;out=sys.stdout;" 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))',
  1277. ]
  1278. logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
  1279. try:
  1280. proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
  1281. proc_stdout, proc_stderr = proc.communicate()
  1282. except OSError:
  1283. e = sys.exc_info()[1]
  1284. if e.errno == errno.EACCES:
  1285. logger.fatal("ERROR: The executable {} could not be run: {}".format(py_executable, e))
  1286. sys.exit(100)
  1287. else:
  1288. raise e
  1289. proc_stdout = proc_stdout.strip().decode("utf-8")
  1290. proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
  1291. norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
  1292. if hasattr(norm_home_dir, "decode"):
  1293. norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
  1294. if proc_stdout != norm_home_dir:
  1295. logger.fatal("ERROR: The executable %s is not functioning" % py_executable)
  1296. logger.fatal("ERROR: It thinks sys.prefix is {!r} (should be {!r})".format(proc_stdout, norm_home_dir))
  1297. logger.fatal("ERROR: virtualenv is not compatible with this system or executable")
  1298. if is_win:
  1299. logger.fatal(
  1300. "Note: some Windows users have reported this error when they "
  1301. 'installed Python for "Only this user" or have multiple '
  1302. "versions of Python installed. Copying the appropriate "
  1303. "PythonXX.dll to the virtualenv Scripts/ directory may fix "
  1304. "this problem."
  1305. )
  1306. sys.exit(100)
  1307. else:
  1308. logger.info("Got sys.prefix result: %r" % proc_stdout)
  1309. pydistutils = os.path.expanduser("~/.pydistutils.cfg")
  1310. if os.path.exists(pydistutils):
  1311. logger.notify("Please make sure you remove any previous custom paths from " "your %s file." % pydistutils)
  1312. # FIXME: really this should be calculated earlier
  1313. fix_local_scheme(home_dir, symlink)
  1314. if site_packages:
  1315. if os.path.exists(site_packages_filename):
  1316. logger.info("Deleting %s" % site_packages_filename)
  1317. os.unlink(site_packages_filename)
  1318. return py_executable
  1319. def install_activate(home_dir, bin_dir, prompt=None):
  1320. if is_win or is_jython and os._name == "nt":
  1321. files = {"activate.bat": ACTIVATE_BAT, "deactivate.bat": DEACTIVATE_BAT, "activate.ps1": ACTIVATE_PS}
  1322. # MSYS needs paths of the form /c/path/to/file
  1323. drive, tail = os.path.splitdrive(home_dir.replace(os.sep, "/"))
  1324. home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
  1325. # Run-time conditional enables (basic) Cygwin compatibility
  1326. home_dir_sh = """$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '{}'; else echo '{}'; fi;)""".format(
  1327. home_dir, home_dir_msys
  1328. )
  1329. files["activate"] = ACTIVATE_SH.replace("__VIRTUAL_ENV__", home_dir_sh)
  1330. else:
  1331. files = {"activate": ACTIVATE_SH}
  1332. # suppling activate.fish in addition to, not instead of, the
  1333. # bash script support.
  1334. files["activate.fish"] = ACTIVATE_FISH
  1335. # same for csh/tcsh support...
  1336. files["activate.csh"] = ACTIVATE_CSH
  1337. # same for powershell
  1338. files["activate.ps1"] = ACTIVATE_PS
  1339. files["activate_this.py"] = ACTIVATE_THIS
  1340. install_files(home_dir, bin_dir, prompt, files)
  1341. def install_files(home_dir, bin_dir, prompt, files):
  1342. if hasattr(home_dir, "decode"):
  1343. home_dir = home_dir.decode(sys.getfilesystemencoding())
  1344. vname = os.path.basename(home_dir)
  1345. for name, content in files.items():
  1346. content = content.replace("__VIRTUAL_PROMPT__", prompt or "")
  1347. content = content.replace("__VIRTUAL_WINPROMPT__", prompt or "(%s)" % vname)
  1348. content = content.replace("__VIRTUAL_ENV__", home_dir)
  1349. content = content.replace("__VIRTUAL_NAME__", vname)
  1350. content = content.replace("__BIN_NAME__", os.path.basename(bin_dir))
  1351. content = content.replace("__PATH_SEP__", os.pathsep)
  1352. writefile(os.path.join(bin_dir, name), content)
  1353. def install_python_config(home_dir, bin_dir, prompt=None):
  1354. if sys.platform == "win32" or is_jython and os._name == "nt":
  1355. files = {}
  1356. else:
  1357. files = {"python-config": PYTHON_CONFIG}
  1358. install_files(home_dir, bin_dir, prompt, files)
  1359. for name, _ in files.items():
  1360. make_exe(os.path.join(bin_dir, name))
  1361. def install_distutils(home_dir):
  1362. distutils_path = change_prefix(distutils.__path__[0], home_dir)
  1363. mkdir(distutils_path)
  1364. # FIXME: maybe this prefix setting should only be put in place if
  1365. # there's a local distutils.cfg with a prefix setting?
  1366. home_dir = os.path.abspath(home_dir)
  1367. # FIXME: this is breaking things, removing for now:
  1368. # distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
  1369. writefile(os.path.join(distutils_path, "__init__.py"), DISTUTILS_INIT)
  1370. writefile(os.path.join(distutils_path, "distutils.cfg"), DISTUTILS_CFG, overwrite=False)
  1371. def fix_local_scheme(home_dir, symlink=True):
  1372. """
  1373. Platforms that use the "posix_local" install scheme (like Ubuntu with
  1374. Python 2.7) need to be given an additional "local" location, sigh.
  1375. """
  1376. try:
  1377. import sysconfig
  1378. except ImportError:
  1379. pass
  1380. else:
  1381. if sysconfig._get_default_scheme() == "posix_local":
  1382. local_path = os.path.join(home_dir, "local")
  1383. if not os.path.exists(local_path):
  1384. os.mkdir(local_path)
  1385. for subdir_name in os.listdir(home_dir):
  1386. if subdir_name == "local":
  1387. continue
  1388. copyfile(
  1389. os.path.abspath(os.path.join(home_dir, subdir_name)),
  1390. os.path.join(local_path, subdir_name),
  1391. symlink,
  1392. )
  1393. def fix_lib64(lib_dir, symlink=True):
  1394. """
  1395. Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
  1396. instead of lib/pythonX.Y. If this is such a platform we'll just create a
  1397. symlink so lib64 points to lib
  1398. """
  1399. # PyPy's library path scheme is not affected by this.
  1400. # Return early or we will die on the following assert.
  1401. if is_pypy:
  1402. logger.debug("PyPy detected, skipping lib64 symlinking")
  1403. return
  1404. # Check we have a lib64 library path
  1405. if not [p for p in distutils.sysconfig.get_config_vars().values() if isinstance(p, basestring) and "lib64" in p]:
  1406. return
  1407. logger.debug("This system uses lib64; symlinking lib64 to lib")
  1408. assert os.path.basename(lib_dir) == "python%s" % sys.version[:3], "Unexpected python lib dir: %r" % lib_dir
  1409. lib_parent = os.path.dirname(lib_dir)
  1410. top_level = os.path.dirname(lib_parent)
  1411. lib_dir = os.path.join(top_level, "lib")
  1412. lib64_link = os.path.join(top_level, "lib64")
  1413. assert os.path.basename(lib_parent) == "lib", "Unexpected parent dir: %r" % lib_parent
  1414. if os.path.lexists(lib64_link):
  1415. return
  1416. if symlink:
  1417. os.symlink(lib_dir, lib64_link)
  1418. else:
  1419. copyfile(lib_dir, lib64_link)
  1420. def resolve_interpreter(exe):
  1421. """
  1422. If the executable given isn't an absolute path, search $PATH for the interpreter
  1423. """
  1424. # If the "executable" is a version number, get the installed executable for
  1425. # that version
  1426. orig_exe = exe
  1427. python_versions = get_installed_pythons()
  1428. if exe in python_versions:
  1429. exe = python_versions[exe]
  1430. if os.path.abspath(exe) != exe:
  1431. exe = distutils.spawn.find_executable(exe) or exe
  1432. if not os.path.exists(exe):
  1433. logger.fatal("The path {} (from --python={}) does not exist".format(exe, orig_exe))
  1434. raise SystemExit(3)
  1435. if not is_executable(exe):
  1436. logger.fatal("The path {} (from --python={}) is not an executable file".format(exe, orig_exe))
  1437. raise SystemExit(3)
  1438. return exe
  1439. def is_executable(exe):
  1440. """Checks a file is executable"""
  1441. return os.path.isfile(exe) and os.access(exe, os.X_OK)
  1442. # Relocating the environment:
  1443. def make_environment_relocatable(home_dir):
  1444. """
  1445. Makes the already-existing environment use relative paths, and takes out
  1446. the #!-based environment selection in scripts.
  1447. """
  1448. home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
  1449. activate_this = os.path.join(bin_dir, "activate_this.py")
  1450. if not os.path.exists(activate_this):
  1451. logger.fatal(
  1452. "The environment doesn't have a file %s -- please re-run virtualenv "
  1453. "on this environment to update it" % activate_this
  1454. )
  1455. fixup_scripts(home_dir, bin_dir)
  1456. fixup_pth_and_egg_link(home_dir)
  1457. # FIXME: need to fix up distutils.cfg
  1458. OK_ABS_SCRIPTS = [
  1459. "python",
  1460. "python%s" % sys.version[:3],
  1461. "activate",
  1462. "activate.bat",
  1463. "activate_this.py",
  1464. "activate.fish",
  1465. "activate.csh",
  1466. ]
  1467. def fixup_scripts(home_dir, bin_dir):
  1468. if is_win:
  1469. new_shebang_args = ("%s /c" % os.path.normcase(os.environ.get("COMSPEC", "cmd.exe")), "", ".exe")
  1470. else:
  1471. new_shebang_args = ("/usr/bin/env", sys.version[:3], "")
  1472. # This is what we expect at the top of scripts:
  1473. shebang = "#!%s" % os.path.normcase(os.path.join(os.path.abspath(bin_dir), "python%s" % new_shebang_args[2]))
  1474. # This is what we'll put:
  1475. new_shebang = "#!%s python%s%s" % new_shebang_args
  1476. for filename in os.listdir(bin_dir):
  1477. filename = os.path.join(bin_dir, filename)
  1478. if not os.path.isfile(filename):
  1479. # ignore subdirs, e.g. .svn ones.
  1480. continue
  1481. lines = None
  1482. with open(filename, "rb") as f:
  1483. try:
  1484. lines = f.read().decode("utf-8").splitlines()
  1485. except UnicodeDecodeError:
  1486. # This is probably a binary program instead
  1487. # of a script, so just ignore it.
  1488. continue
  1489. if not lines:
  1490. logger.warn("Script %s is an empty file" % filename)
  1491. continue
  1492. old_shebang = lines[0].strip()
  1493. old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:])
  1494. if not old_shebang.startswith(shebang):
  1495. if os.path.basename(filename) in OK_ABS_SCRIPTS:
  1496. logger.debug("Cannot make script %s relative" % filename)
  1497. elif lines[0].strip() == new_shebang:
  1498. logger.info("Script %s has already been made relative" % filename)
  1499. else:
  1500. logger.warn(
  1501. "Script %s cannot be made relative (it's not a normal script that starts with %s)"
  1502. % (filename, shebang)
  1503. )
  1504. continue
  1505. logger.notify("Making script %s relative" % filename)
  1506. script = relative_script([new_shebang] + lines[1:])
  1507. with open(filename, "wb") as f:
  1508. f.write("\n".join(script).encode("utf-8"))
  1509. def relative_script(lines):
  1510. "Return a script that'll work in a relocatable environment."
  1511. activate = (
  1512. "import os; "
  1513. "activate_this=os.path.join(os.path.dirname(os.path.realpath(__file__)), 'activate_this.py'); "
  1514. "exec(compile(open(activate_this).read(), activate_this, 'exec'), dict(__file__=activate_this)); "
  1515. "del os, activate_this"
  1516. )
  1517. # Find the last future statement in the script. If we insert the activation
  1518. # line before a future statement, Python will raise a SyntaxError.
  1519. activate_at = None
  1520. for idx, line in reversed(list(enumerate(lines))):
  1521. if line.split()[:3] == ["from", "__future__", "import"]:
  1522. activate_at = idx + 1
  1523. break
  1524. if activate_at is None:
  1525. # Activate after the shebang.
  1526. activate_at = 1
  1527. return lines[:activate_at] + ["", activate, ""] + lines[activate_at:]
  1528. def fixup_pth_and_egg_link(home_dir, sys_path=None):
  1529. """Makes .pth and .egg-link files use relative paths"""
  1530. home_dir = os.path.normcase(os.path.abspath(home_dir))
  1531. if sys_path is None:
  1532. sys_path = sys.path
  1533. for path in sys_path:
  1534. if not path:
  1535. path = "."
  1536. if not os.path.isdir(path):
  1537. continue
  1538. path = os.path.normcase(os.path.abspath(path))
  1539. if not path.startswith(home_dir):
  1540. logger.debug("Skipping system (non-environment) directory %s" % path)
  1541. continue
  1542. for filename in os.listdir(path):
  1543. filename = os.path.join(path, filename)
  1544. if filename.endswith(".pth"):
  1545. if not os.access(filename, os.W_OK):
  1546. logger.warn("Cannot write .pth file %s, skipping" % filename)
  1547. else:
  1548. fixup_pth_file(filename)
  1549. if filename.endswith(".egg-link"):
  1550. if not os.access(filename, os.W_OK):
  1551. logger.warn("Cannot write .egg-link file %s, skipping" % filename)
  1552. else:
  1553. fixup_egg_link(filename)
  1554. def fixup_pth_file(filename):
  1555. lines = []
  1556. prev_lines = []
  1557. with open(filename) as f:
  1558. prev_lines = f.readlines()
  1559. for line in prev_lines:
  1560. line = line.strip()
  1561. if not line or line.startswith("#") or line.startswith("import ") or os.path.abspath(line) != line:
  1562. lines.append(line)
  1563. else:
  1564. new_value = make_relative_path(filename, line)
  1565. if line != new_value:
  1566. logger.debug("Rewriting path {} as {} (in {})".format(line, new_value, filename))
  1567. lines.append(new_value)
  1568. if lines == prev_lines:
  1569. logger.info("No changes to .pth file %s" % filename)
  1570. return
  1571. logger.notify("Making paths in .pth file %s relative" % filename)
  1572. with open(filename, "w") as f:
  1573. f.write("\n".join(lines) + "\n")
  1574. def fixup_egg_link(filename):
  1575. with open(filename) as f:
  1576. link = f.readline().strip()
  1577. if os.path.abspath(link) != link:
  1578. logger.debug("Link in %s already relative" % filename)
  1579. return
  1580. new_link = make_relative_path(filename, link)
  1581. logger.notify("Rewriting link {} in {} as {}".format(link, filename, new_link))
  1582. with open(filename, "w") as f:
  1583. f.write(new_link)
  1584. def make_relative_path(source, dest, dest_is_directory=True):
  1585. """
  1586. Make a filename relative, where the filename is dest, and it is
  1587. being referred to from the filename source.
  1588. >>> make_relative_path('/usr/share/something/a-file.pth',
  1589. ... '/usr/share/another-place/src/Directory')
  1590. '../another-place/src/Directory'
  1591. >>> make_relative_path('/usr/share/something/a-file.pth',
  1592. ... '/home/user/src/Directory')
  1593. '../../../home/user/src/Directory'
  1594. >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
  1595. './'
  1596. """
  1597. source = os.path.dirname(source)
  1598. if not dest_is_directory:
  1599. dest_filename = os.path.basename(dest)
  1600. dest = os.path.dirname(dest)
  1601. dest = os.path.normpath(os.path.abspath(dest))
  1602. source = os.path.normpath(os.path.abspath(source))
  1603. dest_parts = dest.strip(os.path.sep).split(os.path.sep)
  1604. source_parts = source.strip(os.path.sep).split(os.path.sep)
  1605. while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
  1606. dest_parts.pop(0)
  1607. source_parts.pop(0)
  1608. full_parts = [".."] * len(source_parts) + dest_parts
  1609. if not dest_is_directory:
  1610. full_parts.append(dest_filename)
  1611. if not full_parts:
  1612. # Special case for the current directory (otherwise it'd be '')
  1613. return "./"
  1614. return os.path.sep.join(full_parts)
  1615. # Bootstrap script creation:
  1616. def create_bootstrap_script(extra_text, python_version=""):
  1617. """
  1618. Creates a bootstrap script, which is like this script but with
  1619. extend_parser, adjust_options, and after_install hooks.
  1620. This returns a string that (written to disk of course) can be used
  1621. as a bootstrap script with your own customizations. The script
  1622. will be the standard virtualenv.py script, with your extra text
  1623. added (your extra text should be Python code).
  1624. If you include these functions, they will be called:
  1625. ``extend_parser(optparse_parser)``:
  1626. You can add or remove options from the parser here.
  1627. ``adjust_options(options, args)``:
  1628. You can change options here, or change the args (if you accept
  1629. different kinds of arguments, be sure you modify ``args`` so it is
  1630. only ``[DEST_DIR]``).
  1631. ``after_install(options, home_dir)``:
  1632. After everything is installed, this function is called. This
  1633. is probably the function you are most likely to use. An
  1634. example would be::
  1635. def after_install(options, home_dir):
  1636. subprocess.call([join(home_dir, 'bin', 'easy_install'),
  1637. 'MyPackage'])
  1638. subprocess.call([join(home_dir, 'bin', 'my-package-script'),
  1639. 'setup', home_dir])
  1640. This example immediately installs a package, and runs a setup
  1641. script from that package.
  1642. If you provide something like ``python_version='2.5'`` then the
  1643. script will start with ``#!/usr/bin/env python2.5`` instead of
  1644. ``#!/usr/bin/env python``. You can use this when the script must
  1645. be run with a particular Python version.
  1646. """
  1647. filename = __file__
  1648. if filename.endswith(".pyc"):
  1649. filename = filename[:-1]
  1650. with codecs.open(filename, "r", encoding="utf-8") as f:
  1651. content = f.read()
  1652. py_exe = "python%s" % python_version
  1653. content = ("#!/usr/bin/env %s\n" % py_exe) + "# WARNING: This file is generated\n" + content
  1654. return content.replace("##EXT" "END##", extra_text)
  1655. # EXTEND
  1656. def convert(s):
  1657. b = base64.b64decode(s.encode("ascii"))
  1658. return zlib.decompress(b).decode("utf-8")
  1659. # file site.py
  1660. SITE_PY = convert(
  1661. """
  1662. eJy1Pf1z2zaWv+uvQOnJmEplOrHbXtepe+MkTus7N/Em6WxuU5+OkiCJNUWqBGlZ2+n+7fc+ABDg
  1663. h2zf9jSdVCKBh4eH940HOAiCs/VaZjOxymdVKoWScTFdinVcLpWY54Uol0kxO1jHRbmFp9ObeCGV
  1664. KHOhtirCVtFg8PRf/Ayeio/LRBkU4FtclfkqLpNpnKZbkazWeVHKmZhVRZItRJIlZRKnyT+gRZ5F
  1665. 4um/jsHgIhMw8zSRhbiVhQK4SuRzcbUtl3kmwmqNc34efR0fD0dCTYtkXUKDQuMMFFnG5SCTcgZo
  1666. QstKASmTUh6otZwm82RqG27yKp2JdRpPpfif/+GpUdP9/YHKV3KzlIUUGSADMCXAWiMe8DUpxDSf
  1667. yUiIl3Ia4wD8vCbWgKGNcM0UkjHLRZpnC5hTJqdSqbjYinBSlQSIUBazHHBKAIMySdPBJi9u1BCW
  1668. lNZjA49EzOzhT4bZA+aJ47c5B3B8lw1+zpK7EcMG7kFw5ZLZppDz5E7ECBZ+yjs5HetnYTIXs2Q+
  1669. Bxpk5RCbDBgBJdJkcrim5fhOr9D3h4SV5coYxpCIMjfml9QjGlyUIk4VsG21Rhopwvy1nCRxBtTI
  1670. bmE4gAgkHXSNM0tUaceh2YkcABS4jiVIyUqJcBUnGTDrT/GU0P5bks3yjRoSBWC1lPi1UqU7/7CD
  1671. ANDaIcBogItlVrPK0uRGptshIPARsC+kqtISBWKWFHJa5kUiFQEA1LZC3gHSIxEXUpOQOdPI7Yjo
  1672. TzRJMlxYFDAUeHyJJJkni6ogCRPzBDgXuOLNu/fi9fnLi7O3mscMMJbZxQpwBii00A5OMIA4rFRx
  1673. mOYg0NHgEv8n4tkMhWyB4wNedYPDe1d6EMLc11Gzj7PgQHa9uHoYmGMJyoTGGlC/36HLSC2BPn/c
  1674. s96DwVkfVWji/G2zzEEms3glxTJm/kLOGHyn4XwfrcvlC+AGhXBKIJXCxUEEE4QHJHFpFuaZFGtg
  1675. sTTJ5HAAFJpQW38VgRXe5tkBrXWDEwBCMcjgpfNsSCNmEibahvUC9YVpvKWZ6SYDu86rvCDFAfyf
  1676. TUkXpXF2QzgqYij+NpGLJMsQIeSFwf7ePg2sbhLgxFkkLqkV6QXTSOyz9uKWKBIV8BIyHfCkvItX
  1677. 61SOWHxRt+5WIzSYLIVZ65Q5DlqWpF5p1eqpdvLeUfSpwXWEZrksJACvJp7QzfN8JCagswmbdbxi
  1678. 8So3OXHOoEOeqBPyBLWEvvgdKHqmVLWS9iXyCmgWYqjBPE/TfAMkOxkMhNjDRsYo+8wJb+Ed/Atw
  1679. 8d9UltPlYOCMZAFrUIh8HygEAiZBZpqrNRIet2lWbiqZJGNNkRczWdBQDyP2ISP+wMY418HbvNRG
  1680. jaeLq5yvkhJV0kSbzIQtXrZfsn58wfOGaYDlVkQz07Sm0wqnl66X8UQal2Qi5ygJepFe2GWHMQcd
  1681. Y5ItLsWKrQy8A7LIhC1It2JBpTMvJTkBAIOFL86SdZVSI4UMJmIYaLUm+KsYTXqunSVgbzbLA1RI
  1682. bL6nYH8At3+AGG2WCdBnChBAw6CWguWbJGWBDkKtjwa+0Tf9eXzg1Iu5tk085DxOUm3l42xwQQ/P
  1683. i4LEdyrX2GukiaFghlmJrt0iAzqimAdBMNAOjMiV+QaMNBiUxfYEeEGYgcbjSZWg5RuP0dbrH2rA
  1684. wwhnZK+bbWfhgYownd4CmZwu8yJf4Ws7uQ+gTWAs7DHYE1ekZiR7yB4rvkD6uTp9bZqi8Xb4WaAi
  1685. Gly9P39z8en8gzgVn2udNmoqtGsY8zyLga/JJABXNYatlRm0RM2XoPITb8C+E1eAQaPeJL8yLitg
  1686. XkD9Y1HRa5jG1Hs5OH979vLyfPzzh/P34w8XH88BQTA0crBHU0b7WIHHqCKQDmDLmYq0gR20etCD
  1687. l2cf7IPBOFHjb74CfoMn4UKWwMVFCDMeiWAV3yng0GBETYeIY6sBmPBgOBTfiyPx9Kk4PiJ46+16
  1688. C+DA8jqN8eFYG/Vxks3zYEiNf2Wv/pT1lHbhPp98dS1OT0Xwa3wbBwNwo+qmzBQ/kUR93K4ldC3h
  1689. f2GuhoPBYCbnIH43EoU0fEq+8ZB7wKpA01zb6l/zJDPvmTHdMUiHhNQDkBiPp2msFDYejwNBNC8i
  1690. 9qRRxEJosd66bYZ6TPwUEhYxwy4j/KcDl3hC/XA8xsXtYhqBbK6msZLciicKHcdj1FDjcahHBNEl
  1691. 8QD3ipXOvjBNUEMVCXixxGaosSYqT/EnDoAyT9KGgRTqRFwPHShFt3FaSRU6swJyhQ16oVZNFPEe
  1692. +CMhmN16kYbEPoYj4BWQLM1BTRZIrRosfvbAnwF1ZII0DOQ4tmIyIW7/wZEEDQsu5T6qc6UaUFj7
  1693. iavzK3H87OgA3RWIKWeWHl5ztMBJVkn7cA4LZNid8eVeRhxcSsxRj+LTk90wV5Fdi/bqz82qFnKV
  1694. 38oZoIvc6SyseE9vIPSGiUxjWDhQ3GTwWUUaxzDGQJOnD6KAzgGQb0VQzJKb1d7jaF9mChQNR85E
  1695. ax3Ws61bF/ltgt7EZKtfgjEEZYgm0XguA2flPL5CmwfyD25uhqTayH1Qd0XFHinhjSDRHsxqxRkR
  1696. uEvUxNf09SbLN9mYQ91TVKrh0HIrCpPmV2xQr8GeeANWBpDMIXKricZQwKcXKE8HgDxMH6YLlKXg
  1697. AQCBJVcUjzmwTCxHU+SwEIdFGMMXggS2kOgQ3JohKJYyxHAg0dvIPjCaASHB5Kz2supAcxnKl2kG
  1698. Azsk8dnuMuIY0wfQoGIEZjHU0LiRod/nE1C94tJVRE6/AZrcT58+Md+oJWVQELMJzhr9hTlZw2i9
  1699. BcuZgCIwPhfnY4gPNuC+AphKad4UBx9EvmZ/Cxb0Sks3GHqI38pyfXJ4uNlsIp0/yIvFoZoffv3t
  1700. N998+4z14GxGDATzccRFJ9OiQ3qHPmv0nTEw35ulazBkkvnsSLBCSX4XOZuI3w9VMsvFycHQ6kxk
  1701. 49oO47/GVwEVMjaDDpjOQN2gRun3Pw5+P4mO/wgibBKXodsjHLL7oe2mtVS+aYUeZQ4GH9yTaV6h
  1702. Ra4ZQokvYTiIxGdyUi0Ci4FnB80PmDCKa2hZ4eD5NWLgM4hhL2tvx6gtiD3Qrjsr8J7ZJyYvSGsK
  1703. pDJap1aYvO3WZobGs4fLvfUpHeExU0wUMglKht/kwYJoG7clCD/ahUWb57iw5uNZBGPljTGfzbQH
  1704. GaIAETK4GiNX/BzuRtcWpGrDOho0jasjQVODNzhhcmtwZC33EeS+oECAwnpeWt0CCNXIEZpMgFkG
  1705. aOGO07J7TV5w3CBkglPxnJ5I8IVPWu+e8dpWaUqpmwaXelRhwN5Ko8XOgTNDAwBEowi4oQlH3jUW
  1706. hdegA1bOyR5ksHmLmfCN5//tNX2Y1mLv6s0k7gKBaxRy0ulB0AnlUx6hUCBN69Dv2cfilrbtwXZa
  1707. HuIps0ok0qpHuJrao1OodhqoeZKhCnYWKZqmOXjEVi0SH9XvfaeB4h183GnUtARqOtT0cFqdkt/n
  1708. CeC+boeJskWFKQU344IorRJFVg7ptIR/wL+gTAalnYCYBM2CeaiU+TP7E2TOzld/6eEPS2nkCLdp
  1709. nz/SshkaDrpBSECdcQEByIB4bTkk75EVQQrM5SyNJ9fwWvYKNsGIFIiYYzxIwQDW9NILa/BJhLsc
  1710. JJwI+a5Uci2+hBgWzFGDtR+mtf9cBjWJhtBpQX6CzlCcutkLJ3Nx2shk+Lzs5zBoQ2SdA/NOwOtx
  1711. s/kuhxt+tYkVcNh9nW2RAmVMuZZg6KJ6bSjjZoy/OHVa1NQygxhe8gby9m3MSMOBXW8NGlbcgPEW
  1712. vTmWfuzmJLBvGOTqSK7uAjQtiZrmKqDAtpmdcD+aLdq0sdheJhME6C1AMLz2IMlUJygwj/J/GeR+
  1713. 6N5kMe8xi4tNkgWkuzT9Tv2laeFhSekZuMMPFFIdwkQxrXn4pgAJof3NQ5An0gUQm8t9pV3/Ntzm
  1714. HDsb4MebfGBHZLiB501/Pjm+bhNm9DDQlq7nd2URK1y/lJeRxaQP0HV7bqSXkQhxttVbmXqrG0OK
  1715. IlcQcop3Hz4JpBhneTfx9l4SdaPrIwlK7V6CNDAmVgHYqBKRSQ6D3dzYieefhVs3jXdCd1TZ4/rv
  1716. QgtgH8y2GWa0uoBet55Ah2++GnekJF10v/nqkeToEseGc2YHHnquWyHjlAy9857yedk9K2g7roes
  1717. Zykk0+vfJkSbVzSaNg/d3QI/BiqmtyUY82ejmoztqePH93h64Wl7sgNYK6I0nz1aFAjA88mvEMUq
  1718. nQC7jZOUcvxAjIMDVIImAufUQrfwepB2yrdDgq4QSX1+htzBIf+wPR3tNZ2ZfHBHpGo+61i1UdnT
  1719. G/r1fpS3Se/uRfYrh04z7lvwwwdoBG/krslqy2Z6PeONhaMOtfUI7P4EvPqZ80/A4dmDUHjUQAxN
  1720. K85hwyZ0TcW1AgbYA1Rzj4uyw0FpD807Y3PjZrDQKfEUpfOp2NDuOCX6cK8CoMzYAemAg3yo91hf
  1721. VUXBO6Uk5GtZHODm30hgYZDxNKjeqA3m8K0sERPbbEqJU6eMJO9i3ECnQu1MgtqD7eadZW4SJzK7
  1722. TQroCyolDH5899N5h33Qw2Cnh+tJbw2xK7uwOC1cxYe7Wj4+ZvvWpPX0qG28Wtk8ExF2T+GeqN7b
  1723. ceM9UYq1pks5vRlL2ujFZca+TmrzFb5GVOz+r1+uo+I51RzBVKZphTRgNwqLxeZVNqVkdynBJOvK
  1724. Tqz0oO1bTuLM03ghQuo8w/yBXk1KMdzGhXYy1kWOtYSiSmaHi2Qm5G9VnGKAJudzwAW3IvSriIen
  1725. NIJ4zTvQXGOm5LQqknILNIhVrndyaLPaaTjZ8kRDD0nO2TMFcfv6RHzAaeN7JtzMkMuEeX7iGieJ
  1726. ERR2cLaWI3oO77N8jKOOkbzAUIRUe2eVHg+aI+Q6Mw7z1yM030h65W4X0Zq7REUt45HSjRlzMtcI
  1727. JRxizMq/6afPiS5z9WC56MdysRvLRRPLRSeWCx/LxW4sXZnAha3zD0YUunIQzeR0Z3mEmz7gcc7j
  1728. 6ZLbYa0e1uQBRLE2IZARKi5Z9ZIUvFtDQEjvOfuH9LAud0i4CLDIOZOpQSL7416EDrdMsbHTmYon
  1729. dGeeivF4+ko+/L6HUUSlPRPqzgI3i8s48gRjkeYTkFuL7qgGMBLN6g/Oe2W34wnn6Jqq/uq/Pv74
  1730. 7i02R1B2u5q64SKi2saphE/jYqHa4lQHDGvgR2rpF01QNw1wrzNLss9Zkv2R2Ocsyb4eZo//eU1b
  1731. 9sg5YkM7zrlYgw2lKhzbzK1V2d9vPNdFLfo5sznvGYBbkJWOS9BDpbOrq9dnH884fRP8M3BFxhDX
  1732. lw8XH9PCNmh7QG5zS3LsU5vI2v65c/KI7bCE6dXy9BoPjvoCQx/H/9d5AkEBiUin4R43zcdnAazu
  1733. bxVKuSEu+wr2ncP4jofgyF1X/rY5gL9hhB7yGNDXHkxoplLHMg2Va43bDno4QB8XcTS9Z58OdugO
  1734. r8mhh23W7zO109RKli/Pf7h4e3nx8urs44+O14Tez7sPh0fi/KdPgvbHUeWzGxHjnnCJpRigit2j
  1735. HGKWw38VhtOzquTEF/R6fXmp09QrLObH6k7U0hE85zoOC40zE5xZsw91AQZilGqf3Dk1QeUKdKoC
  1736. XfQVV+yrXFeA0mGMCfp3lfb29WkYc2qGNvQiYHho7JKCQXCNDbyiOt3SBCIF73/okyQdSGmrZnfE
  1737. U8q8tLZJneS/SS17+SnqDE/qzlozfg5cXIPrSK3TBHTli8AKgO6GhQE13+iHdmeP8epSOk53GFk3
  1738. 5Fn3YoHlEi8CnpvuP6wZ7bcKMKwZ7DXMO5O0LU4lpljdI/ax0T5vf8s7+GqXXq+BggXDXY4SF9Ew
  1739. XQKzjyGeE8sEfG7gySWYK3StAUJjJfyM6IljfWSOu9LBq9Xs4K+BJojf+pdfOpqXRXrwd7GGwEFw
  1740. DUXQQUy38WuIFSIZifN3b4YBI0f1iOKvFRZAgwmnrJIj7FS4wTuH41DJdK731X11gC+0YaXXg0b/
  1741. Qq4L3b/bnQxQBH7/IyQ7+/sfhoC22sUOMML5DJvwscLb4ocnpdxNWPPZEx+WMk11We/F68tz8Lmw
  1742. 6BzliLcezmFMDtRxG1GXIPFJrgYo3GSE1wUyc4GuH+0xzyKvWWc+EAWPenvb0na1KOfW7tVKsBVx
  1743. oly0Q5y2Jowpm46Qo2FJzOoG+FtLqW2DdHbbEN1RdJgzxlcFFfL5rAEsTU9jDiYgysCadpPd5J20
  1744. JCtN4VaaTEGdguYFvToCWUHq4sEtYsA84/xiXihz3gMerrdFsliWmF6GzhHVmmPzn84+XV68pfLr
  1745. o+PaXe3g0RG50CPeQz/FGilMFMAXt+4J+Wo8dlm38QphoBKC/zVf8eb8KQ/Q6scpLS+/rV/xgZtT
  1746. J4biGYCeqtZNIUHH2enWJT21MDCuNoLEj1sCVWPmg6EsGNb3691ud35tVrQtGxaFXA/z8hHJ8fna
  1747. VuTozk5FTvOjpzhf45bCLOxuBG+7ZMt8JtD1pvWmr/bH/bSkEI/+AUbt1v4Ypjim1VRPx+G1Pmah
  1748. cFBb2l/coMBpN81QkoGGodt56PJYtybWzZkBvWrSFjDxnUbXCGK3PgcUtZ/hYWKJ3QoQTEeq1X+i
  1749. Qi4gkPqIQwWe1BNF+iMQT0QYOoI7Goqn4sibpWMP7p+lVl5gI38ETaiLEam+PS+AFeHLb+xA8itC
  1750. DBXpiajDQZxelts6GfxsluhdPvdn2SkElP9DuSvibCFDhjUyML/0yd2TviR16xH7c3LdZVrEBTip
  1751. dz083paM7py9Qa3BCq12N3Lb1Ec+ebBBZ1H8ToL54It4A8p/XZUhr2TPJl/noaF+qPdDxOoraKr3
  1752. P8MAPejfusrzfMCd1NCw0NP7rWfLidfGerTWQjaOdOzbF9qVnRYQopVqH5F0jmEZp9T6AbXJPa2N
  1753. fmCf6ky9/d1xHMbJpligPLgPkp8hufiABp+FS6jutz4+oN/N5K1MwTqANQ2xuvtXW909jGzGorPo
  1754. 5aFIXG2vtt0o0JsagRNTZY7jUH15Z8pk17jeytZI+I+D4BcdecTZDUWXr/52MRKv3r6Hf1/Kd2Aq
  1755. 8RDXSPwd0BKv8gLCSD6GSOfDsWC95PgwrxSe9CJolMTno/Toll155MUNA11J75fQW0UosGgQfXG8
  1756. vwFQrHFmGtAh3dojMDXi8NscZmn4ncYn7KJOoF86owT9Vf5PomN1qHtEy3KVoolwEh81kM/B5cWr
  1757. 87cfzqPyDjna/AyunTb+xpUkG4CPCtw8Ggn7ZFrhE93TcZh/lOm6w1/WMac5N4Axp9iHgGRt40y+
  1758. MyC2UUVcYOJArLezfBphS5AAPqxUbsCBHjrh5b0W3jOvCCsc6n2n2ovHx0ATEeAZLGyip0ANafx4
  1759. gmdk+HEU9FjckaDcL/zv6c1m5qaO9WEHmtCgiVo9zdDvX+u8JVNWQ7ScRKidWsLbY29pEqvVZOqe
  1760. jXqXCX3LA6gz2guQ87hKSyEziJ8orKfj9qDT3eNMLCy80my46IwPJWbSTbxVTi1HrESAo9IerMRN
  1761. C0rsQdT9U3zDmh/PWYmKj3cCdEKUQqXc6aqq6ZKFmaMfrW5bu9ubJDt2yxQ0kXlQjoanqqY2TBR9
  1762. REZpIUtNAH4QDj8/r/fTKfc79Ur0pmtdiQffnj59Goh/v9+9YQyiNM9vwO8CiJ1uySW97jHNek52
  1763. kTqq48yrCFhxupSf4cE1pabt8yqjHOSOrrQQ0v7fwOA1qdnQdGhYXs7PFbwNyy14N0dbk5+zhC5x
  1764. wSySRIWr78LBDJORJOJFUAL7sZomyT7nImAdtnmF548wo6gZRd4BrycIZoRvcfuIw+klOpFU/2fZ
  1765. xqIDcyHAARfn8HB0apPO3gCi46utxnN8kSVlXTT/zN1b1AebS3s5i2YoEW9QJsxEGtRwDrN5TFqv
  1766. JvzexZxeYJJPPz9vFIo58+TX9yEPTA1Cls/nBlV4aJZpmstiaowqrlkyTUoHjGmHcLgzXUpDFica
  1767. dKAUgDInGzCzwmzffmFXxsX0He2zHpiRdHlKaS/64RxQnDVKtKKoHp+yTZaQlnPNF6qwf0tJbO0Q
  1768. eIOJLzTXY920dyGBe3yryvRFA1zgUN8+AHDochurHC1HeorCuVHJwme+7bkdAD8UijNyt0lRVnE6
  1769. 1ufZx+jIje3Os0bUHvvZeaTN+iojtILJ4kCXKaO7MKzPt2E5oylDPxVznYuI3KM0/qmTdY5u4BF7
  1770. SuBJIGlmY3MQ1CSLPluGtUfrdB2awxYI6ktzWKPH/zZnBVpV9i7mOu+vC6h6nGi/LI5O5IvvRXg8
  1771. goi7cWhtvcU7agDZJ7OGA0bdYCpO+G/m2DzuL74/FeHzkfh6B/SoZ4CTI3eEZtzagNAL5Pj60WRM
  1772. kwmRDQ8t3N/UVMeNNErD6ya121T5jojylwZR+ASULvJ8/rixgxUogHkiZwdPFBJC41Lr2H42pWHx
  1773. /K8uoCPDx0dfxT4X2+3zqdkJxBabWqE5qs14u3YUc6ZWqyE+dog6g22gPTNt6kIaxW32GiwsfNP4
  1774. NYgFAMZdO2H4DfdM4b2mhetj9W6Q6kppC7Yj8Ncn1Hi/q25Yy9u9ztyjBPleBsC90FreXQF5BKfv
  1775. 3HV3ePnP5x+uvO7bzGwhek9dvOdNdJa/d6zq7hJ0Tx5t3Xm95ubTnVTzuKWr678kNQ6UWn7A+TQX
  1776. 6pHbeIJFr3yTRm6LX1d4ZR3tLqN5S6XrBHEwzHcToVdCWQAqoYLVAL+omuNm8C3dwHemqNQLL9r4
  1777. 6uj5yJxqZEB6AsfR8Zf6ojrqZk5u+z7zSAdh8FL3O4r+zQGWlH5v+6oVn9C0ThsX1viDceJrGI0t
  1778. HWojc3+BfL1mscCb3WpisqtsLzF4A57LBHwWc0VjDt4XRJZRF7qu2qhFuE+/PV6KfW2Ig+4Slj4N
  1779. uEv7PZqVda9uM4CxPHLuMuY36JZV6xOb9jKGAbcdQ7cGkXjipvOADRsFNJnlTbBr+tx/19x1i4Gd
  1780. uSkoaM3dP9/m0kD37TeFXTTgPIMmxIMq42ulbS2CNy+PRq5eH+milnaxttsK59ljF1r9TJEMptaJ
  1781. GzWyhjlX8dT9joVTB3zLa0dxk3M6zWWIxnRbur7J6Q8x81x4gs/tqWaqJpppztNBC93fNeaSzrFc
  1782. LNQ4xsvjxhTrUi1VK4QxwdMbuvpLxmprQh68MQVAGDbShaJuMThwBCg5vsSWa5GcOzEEDU01rk7R
  1783. rEpmrMt1fAXgIk5TUn+TLueq1yCVmHVWVbEuICgN9FWnXCTTVYlbAzUptFWsbgzqpsdI33xJGpEq
  1784. s8yZRk6ONipsgAhsfVs6fTy274BrntUnvJOR5QaZVStZxGV9s4m/D59A5FOPQMddcXWd/Fgtjg02
  1785. cRFLLHM4SGGqyn7/EqI7P7TdcaR7aPXcw/mJeui862NOiztmxPJxcmevNHNv1ZnR3bmua2eb1Xxn
  1786. r3KBhTCXdZF61GkrfquvD+JLLDmBjs6hw0Eg++5pMr9s2moy9k0tGs4zVye0L4rB08pkVzsveWvy
  1787. QPuWt0Ycasf3VYZllZZz2NPYUlF71J06px5t6KRysF7znlSOX8b+yFSOB/8xqRw+D1KkeNdDijeH
  1788. OcjpvJ1JLmLOhY6X+Ddx4nZiqzIJOHmy1Uy/wMouytfFWgid9ss8vxmPmX8u5saT5XG0QdJ1+uaG
  1789. 8xE1wn6ck1M6E/wxnuCWLusqJfSEEEPc6EXlYVAR/zzUu1lj0K104gA6mK98syhCIY9Jj56DUiyS
  1790. 2QxvS2Od72XPkC+9NdDIsxtB2z545R0dAfjw8ez9x5+vnIG8DSWD5djQIWxv6IDKvEvK2sS2b1bi
  1791. dgZE57t6zZv+dSfT8GJS+ZPj+b+HEUzRmX/nPJ5JQj4ZctXvKt6a+8hklleLJZebwFwcaP6iGQ8L
  1792. W+FNz3PwWkpTsZbR5LhYxRKSceQ5j2eU2zZWyTwm0wSv6MbAwHc0va76PlqsHqAx0TXF3WPaK3Jb
  1793. NknEb3D/Uskx9BxPEtALAf4r/vsC6D42hA92KaFeQOCfnggHRD8XWBD4hev1kFZOXl8v+LsPnZHU
  1794. WWbe8G4zH44kh3eFlyLQ3b2KI1++5V6Vgi9gF82iiz0+rsNl1QX63FkuIir6KKbMIiGMEyGJzQMt
  1795. aZSZ0MWLNTi8RP7dB/EJjLdemaHpgFs1dFe7OSWKF/FmPPqUjnpsmshtYvbZ+LJdDUXfyOuHhKw8
  1796. O7gG90/GUz6MahTLGKzlAu002rJnTfpeYJWaVTwbvJMf794EFWd0LmDUUFVRAwYWyi8qPCpLl/mZ
  1797. P2GA6YTbPJlxhT5KqBkG744FBdIAQ/um7gWSVKW6MXJG+hgRxNvs4tnW2gA5awAqlwVJd1PbocIe
  1798. YX1Zkwi6xGBSLZRbY5AoVcmvv/3q672VWjz/y7ffHH/jdTTT6bkyzzklFfwTM3VBg46NcsfOjVRf
  1799. fsySkgjpH507q53S1GYd/KDC3xToK2qAzdN/vbh5+HkgdiDoIBm+gVZv8/INevWE70hcyYLuxcoz
  1800. etBTWbXXONTHfx8DdSVFbWTt+DeihS5EHxhYedW39LDkf3ne2bFNRTaHkbGcoUcOJzbs8DywnK1p
  1801. cO11xcBPmgY6Suo883fPbhg7JO6NwLWTDH3GgBgh4V8uazII7vm5da6Su8Be5s+BpHOSCp309j2R
  1802. 1JVv/FVO4sG7m9OM1rW15ccb9PiHy3cvzy6JAuOrs1f/efYDlYfjkjcC+Afv/WX5AdP4wDtE5u4D
  1803. 6prersFrbDvu5OZzyBpC632rGLIDQveZ865lbMZ27uu+Dq2ju+1OgPjuaTeg9kWxnZBbSSp9l5Zb
  1804. x9s4ODbQT/mUj/nlVEiaR6aAyB2rsUeJQx47p2faAQlLUF1cZIDXZSE64mltmfetujNcOzjTmT99
  1805. qXPPfv7QHhmj5cMwAZnTFoOYA7O24IAzPs0/y0TmG68bMJehgQRPpXMvL13Jy6BK/+8/FRA6okHW
  1806. f2lpZP+WArXjwhdl/0gIVrBNtZfcOu/fnp8bQ89k2kMFUJSsJM2Fs4yKUZq6TMyWVz5R4vMB3c1x
  1807. gKrq2v7CVdMJw78lWERZ2nsbFRdac+0YNJ5XqVsYafu0OlAejQpt8rlzGBb05SFQupZuBdKBKSj2
  1808. YyZbsf9E7essFx7zIUrqS1cd5NHKOdgbaj0TB303T7g3LwjxvL/hrHG5g+5xxD3UPT1UZY73OyYS
  1809. j5v0XSkhvifIXKsl6LpGL5uDpYF6CwS+3n5+fmKLJpDj8bWjh6gqPnAyJZ8dR2vn7cBOd/z6+xfF
  1810. HyN7HA3T+cPmKNdB41xaf9a4dc62J7NsqjYZUuC9795END28P5kSDJq4Wg48oZmJ8Pc/hnZ2zrFi
  1811. PQX7ZNiedq3F+kDxQekHgGrpRfGkwB2o5nPn8MuWD7CFz+zRN7px3a2lCRw5oWjZ5xHuYdJrNXrN
  1812. 7nS7yIO6M4qmPzdo8qRefhB3dka41dCL//vNRHPqNU/0+BR8UUt3/+cP6N8+oGG7H+3KGthWx52X
  1813. C3DqB0/1YM1zk0vN8wgsD6jSkBT4ExFa2cfrq2pCugxVTw4Zg/4yCJ0VQg+bsrjkFY+1U2ENxeB/
  1814. AfPVUFM=
  1815. """
  1816. )
  1817. # file activate.sh
  1818. ACTIVATE_SH = convert(
  1819. """
  1820. eJytVd9v2kAMfs9fYQLq2m4MscdNVKMqEkgtVIQxbeuUHolpTgsXdHehpT/+9/mSEBJS2MOaB0ji
  1821. z77P9menDpOAK5jzEGERKw0zhFihD/dcB2CrKJYewoyLFvM0XzGNNpzOZbSAGVPBqVWHdRSDx4SI
  1822. NMhYANfgc4meDteW5ePGC45P4MkCumKhUENzDsu1H3lw1vJx1RJxGMKns6O2lWDqINGgotAHFCsu
  1823. I7FAoWHFJGezEFWGqsEvaD5C42naHb93X+A3+elYCgVaxgh8DmQAys9HL2SS0mIaWBgm7mTN/O3G
  1824. kzu6vHCng/HkW/fSve5O+hTOpnhfQAcoEry5jKVjNypoO0fgwzKSOgHm79KUK06Jfc7/RebHpD8a
  1825. 9kdXvT2UcnuFWG6p0stNB0mWUUQ1q3uiGRVEMfXHR03dTuQATPjwqIIPcB9wL4CArRAY/ZHJixYL
  1826. Y9YBtcAoLQtFevOoI9QaHcEdMSAB0d08kuZhyUiSmav6CPCdVBnFOjNrLu6yMCWgKRA0TInBC5i4
  1827. QwX3JG/mm581GKnSsSSxJTFHf9MAKr8w5T/vOv1mUurn5/zlT6fvTntjZzAaNl9rQ5JkU5KIc0GX
  1828. inagwU57T2eddqWlTrvaS6d9sImZeUMkhWysveF0m37NcGub9Dpgi0j4qGiOzATjDr06OBjOYQOo
  1829. 7RBoGtNm9Denv1i0LVI7lxJDXLHSSBeWRflsyyqw7diuW3h0XdvK6lBMyaoMG1UyHdTsoYBuue75
  1830. YOgOu1c91/2cwYpznPPeDoQpGL2xSm09NKp7BsvQ2hnT3aMs07lUnskpxewvBk73/LLnXo9HV9eT
  1831. ijB3hWBO2ygoiWg/bKuZxqCCQq0DD3vkWIVvI2KosIw+vqW1gIItEG5KJb+xb09g65ktwYKgTc51
  1832. uGJ/EFQs0ayEWLCQM5V9N4g+1+8UbXOJzF8bqhKtIqIwicWvzNFROZJlpfD8A7Vc044R0FxkcezG
  1833. VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs
  1834. """
  1835. )
  1836. # file activate.fish
  1837. ACTIVATE_FISH = convert(
  1838. """
  1839. eJyFVlFv2zYQftevuMoOnBS1g70WGIZ08RADSRw4boBhGGhGOsUcKFIjKbUu9uN7lCyJsrVWDxZE
  1840. fnf38e6+oyew3QsLmZAIeWkdvCKUFlP6EeoNdlaXJkF4FeqaJ05U3OEiE3a/g/dfhNsLBRxMqZQH
  1841. +3W4hL1zxcfra/9l9yjlItE5XIFFa4VW7xfRBG41KO28IQgHqTCYOHlYRFFWKoqiFaTYhoN5CrPl
  1842. V8JVwriSS1QV5DpF4CoFg640CpwGt0dyanIugRDCaJWjcotZBPRMCGjRgZZpuAsVN4K/SrQ1SmTg
  1843. kHIwVxBP2fr+lr2sNtvPN/fs6WZ7F9cY/3hP87ev4FfhHDjEIYwDUKXRz6L+ub1bP96tH5Yjsbu9
  1844. Uwbdxo95DGE/YPPH6vmOPW3WD09btn5Zbjar24DPBJ7JO1eAeeEOIHVCBdhNffVZW01WcEcdQ0Xi
  1845. UuovdakM5roiqM5gV4MLo8nDrm281tYS891ieBQJ5+6jgNHScItBu8zsSYymc6zTBmsy2og3objs
  1846. 44ThIbAdAyTAqK9YgPqZBZ5ZjNZqLPPDah3RbVGXjy/DKsZTbt6qv375O4Z3v8JMaZXSsim9tnA2
  1847. KKLM5u3eu3HOxSHVyfhWL9eOX81xAp+V5yiMQYkVDyW3iAKRD5lFUdvmwckgZiz4ZCzuYWcSg2kt
  1848. tIFS42lgfs3Yp9Uje7x5WJKnI7zju5v2+tj5bNLiImreMP8XTtQzTiNQ6BgeQy91trrp12e6OLg9
  1849. LczzZg3qejboTqnfhidjt6vnm0/3y2PnxMcB+LsuDnWzJyUVgwoxlEQXm5NYTrvzKMBBz4ftftbN
  1850. A/ioGqjleIUDQlPruCvtB8i0CW0sobi/Jmwh+YFujLNx4MM3xq2TcBw8NSR1hcYIujfIa0Xv9LcA
  1851. s8r8jfQB/vF3YGGwoBTX5MLbQvEc+9jhpOw78yhX1k/IuoxGKJfB7MJe2NkoHC7pLCzRks7eXGNX
  1852. nQeUFv/H3eWFvYLZiDFcvtIQ9IyH3REHbtsp0qRgMzIQu3R2NsleQ4z+Op72WY/hP2j+KXTA0QE3
  1853. nFutYMbG3AnpuuO/AygvqEs=
  1854. """
  1855. )
  1856. # file activate.csh
  1857. ACTIVATE_CSH = convert(
  1858. """
  1859. eJx9k9tq20AQhu/3Kf7IJm5N4vRarts6caCBxAnBCZSmLCtpXC1IK2e1svFNn72zklzkA9WFkOb0
  1860. z34708Mi1SWWOiPkVekQEaqSEmy0SxGURWVjQqTNlYqdXitHo7hMAwyXtsjBn8OR6OFHUSFWxhQO
  1861. tjLQDom2FLts6703ljgvQbTFTK11QphpXGeq1Pic1IYk+vY7VzobxUX+ZSRESQ6GNpk2NBm8iYEQ
  1862. KtOqREK7LjBwxN32v8rH+5l8vXtevEzv5dN08R1nE3zC+Tm4CJk1alvQP4oL3wMfVRkvduQdw1Kq
  1863. ynSMkzrPjw9Pi64SVsxj5SaHQnXgf6Rq/7hx+W53jtv5aysdvJ2Fw8BrBaYwCZts5SFQW/OITMe6
  1864. 2iZFzPR6eKm1tbWU0VoZh7WyWkUZlSPRyd1XqC/ioCsEUnZ+pQya6zoiyChazGL/JjrZ4fuVlNd3
  1865. czmfPtxKGf7L4Ecv8aGj1ZBiuZpE8BEuJSPAj1fn8tKonDDBqRxBWUkng/e6cV6aTKKXHtlNUWWJ
  1866. 3wdtoDyZS20c2ZoV+SLaFiYn4y44mGM2qY5TXoOSLtBvxgG8WhUTXfIgJ1CG14qw8XXNwHFWrCxB
  1867. RUXl/HHaGeK47Ubx5ngCPHmt9eDEJ8aIiTex/hh1cseAyR8Mg367VWwYdiuG+4RaSebzs7+jFb7/
  1868. Qqd+g6mF1Uz2LnK3rfX08dulhcFl3vwL0SyW+At+C2qe
  1869. """
  1870. )
  1871. # file activate.bat
  1872. ACTIVATE_BAT = convert(
  1873. """
  1874. eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV
  1875. mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O
  1876. CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5
  1877. xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ
  1878. MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U
  1879. +g8CsNTr
  1880. """
  1881. )
  1882. # file deactivate.bat
  1883. DEACTIVATE_BAT = convert(
  1884. """
  1885. eJyFkN0KgkAUhO8X9h0GQapXCIQEDQX/EBO6kso1F9KN3Or1201Si6JzN+fMGT5mxQ61gKgqSijp
  1886. mETup9nGDgo3yi29S90QjmhnEteOYb6AFNjdBC9xvoj9iTUd7lzWkDVrwFuYiZ15JiW8QiskSlbx
  1887. lpUo4sApXtlJGodJhqNQWW7k+Ou831ACNZrC6BeW+eXPNEbfl7OiXr6H/oHZZl4ceXHoToG0nuIM
  1888. pk+k4fAba/wd0Pr4P2CqyLeOlJ4iKfkJo6v/iaH9YzfPMEoeMG2RUA==
  1889. """
  1890. )
  1891. # file activate.ps1
  1892. ACTIVATE_PS = convert(
  1893. """
  1894. eJylWemSo1h2/t8R/Q6amopxd8hdQoC2ctQPdpAAiV1gOzLYxCI2sQom5sn8w4/kV/AFZVZmZVVP
  1895. j8cZoYwU957vnnPuWb5D/s9//fefZ2oYVbNLlPiztKnqmePPvLyeVXlTur43u5R5OjvlSvhvsz5v
  1896. Zq6dZWC1bLJZVP/8059nXlT6bp30n2ZkPqsB1OfZp9mnhe3WUWvX/qeiWv7807iR5s4C9XnmJr6d
  1897. zZpi1mRNBfBbu6w+/fzTx8oto6L+rLKc8nTCVHb2ZfYx7aOszV27jvLsU9q7eZramfepsOvwVQLH
  1898. FOqJ5GQgUBVJVP82Ls9+Kf0qT1r/8e3Dx6+4i0+fPvw6++1kl35Wv6IAgCcRE6hvUT5+Bf+N9+3L
  1899. aMilydxRn1mQ5I6dfPb8F1Nnv8z+veqi2g3/c/ZRzDPSr+qyGRf92a9/HWVn4Ce6gH01WHqcAMyP
  1900. bCfxPz8defJJ52RVw/iHA36d/fUhMv589LP284tffl/oVaD00xyY/7J19uG7vR9mv1VuXvjPljxE
  1901. //Y7er6Y/fkpT7ynNirrxk6eChAcRf1O069bn1e/vHn0A+nvVI5qP3097z9+V+QbVSf/vFhHifq3
  1902. Ko0QYMO7y30nMvstme74R+p8t9Uvy7y0H5FQgdzJQAq4eVZHWeP/yJN/+i4i3ir455niJ5eZ97z+
  1903. pz/wyWvMfT3qb48ka7LKr2dRWfqJ39pZ/TW+qp9/ehOpv2V55r0qM8p+fGvel9fIByvvjQerb75O
  1904. ws/J8H0Qf3mN3Gek58cf3sMunp5wTpyS8An8jNueFOr09PRhNn8LMrrzT99dHlBVwXCeejrJR+Gk
  1905. fvXu+3T9Ufj+dfbhw+jDb6P3Rzu/fBfdPz7lBfjtDWOeN7NnRelfovusHmulP3ObcixDs8f+f505
  1906. TQ2Kb/Yv4HdUuXbpgSL76RWkK0Ec/BbmoEp/+OXjL38Yy7/+Ovsw3bXfJVHmvwL95R9JydeoUjgG
  1907. GID7QTQGe5DZdVP6MyfJ3eu4LHCc4mPm/pBbXNi6Iia5RA6e2SpBUKlGYBJ1JwZsjwdaSQYCwQQa
  1908. JjBXhogqBpMkfMQIYhfsUwJjwC2BlL6uTc9ltNsHHIlJGIbj2GUg68DQKk4t3StUmcWlFeURAwso
  1909. 7P1HIKiOkEz60KEkFuY0hkmasip9vFMCZDhqXXi+wPGJCK3hMmL0pzQIgnUNbGJckiBwOgqwjsOx
  1910. gMP3JCbiwfUWXiNm10E4gKIxEt8JUjWeQeqSxIwYVLffqyRlCLjEYEuNIkJB1BA5dDOZdGAoUFn5
  1911. ysdUKRDXx/pdiDRYj73zPuEouRgxLDiBTKMLJFjvPSZJbUMMPUYLNDjJnDRprIEqBMKd5LG7ELzF
  1912. H2Wm1vxVLmmdCMe9s5w7yL7w2GvHhq4okO5dIDlIiLlOUCXYGJ+pr8+mux2fxwQekxQvYA998VAg
  1913. FK270zGm4YGo41iukroImec9JMG7mqPukEWg98OATbY89lQql4iJiei9peCUbXiFx9AVR4kJ0Luw
  1914. 0iQ2z3LC0WJhwavCSd37kcTgUXbCwASVX749Q6zMszhwJBdo7L5wDLr3FXzvZHLipsvEYpLJXyq8
  1915. v1mGCI0YQAYH94pz8ft7pEBcHEH8bbFxnQgOY8xifXTkuVjz0xvmnPbL/YgBkVshGQLj4JToxUwc
  1916. WY/bkCXrS0iLa1m636BTrEp3GQRyR0viYU942upSH3JhJaKmEk96eGtLtFtXsdcLwdWzEER2Ot+y
  1917. CGvkJIRAon68O3FALrgQYW0dWQy75WqXZW1/lyj3OsW6dSn2OHy4XNc2ezOQfaa0sj8/65bSXEid
  1918. 8BdtfWcUqjsQtlhWvLsrnFzLTY5A8n4wcm3EUK31au5CLFrY8tbd+odFSuyWaIrnaxHypNUSXjhX
  1919. xbN9c2faUsHUxiJcGAv66kiyilTEiFHUNa8nXJxdGxMtd/OhvYVqforv7oU0qcv8TG515ordEn+L
  1920. 2dtQmgvLG+NJMdb72+PgTHfbaMdu0035jecoh69B3cB8rSM7kFMypGISu8AxrcM6Cl8M2HGMCVba
  1921. gkqwpUBcTHpgktmx0rT/iOMmRYv4kYQIy+FDnjG2mwMfBygasOLhhgj4doxjj+skU8BtjKZQfsTY
  1922. 3G9XiW4SGk5ZQcghmzpJkr3pBRJiCGKsRxqNAx1wkur4AavxICjxgKJxye2w3AxHDJuVIZfMWx7x
  1923. EK9fDSDGe48VB4dYxSA3Wxe2BhOmGhPZQwJdTXqwnawJNNft11gyYuTEkeGMEPJYbM33O4DkNu4j
  1924. vwcX7hoTxD+PiKkLiyGfir1DYllOGAGHmuF4/ogx6QCDNeLv6lAJHINN/lQwyldxRGA1hugr5uFT
  1925. UH8dDcEkDhcYs+MDkzt0Jo5LGgtqq8Glf1/HEYNH8NZhkthXVp0FMETsW4wD8w9gwEnjMXrvGPrV
  1926. NmjIesaiJHNvchaHmQ4qBeBeMInEAgwXaIwhDIJRMIaZU9zUX0hJJukrrU6+oMTWUXDSYejB7bGe
  1927. o/HeNpbg3GugGCvIOu9ry5CLqR5Ru8hO9SlvPQJXQd1qbGOVva9b7vCD3jDWFNCD3EzgMUS3RwwR
  1928. PQLIBJXU1ZGqrX51wns8qpGcjW5SEeiUlG9IVq7iM7liF1yvRm0hRFfb9uU71+5WI4Zjyx4a5por
  1929. dGSM7rmYQAxsR+cirSNLRUhiyrLXa2YrSxThCQqoCAFIxmZ5luaudrhPcUoiVM0zjEszcSzwG0pq
  1930. YS5PNuiypKrePXfc2S37ux8Jjgarp2hzRvzE6STBRfd0skcnn/Y7OsSHxsKXpA5XIhyVjO4QCLNY
  1931. zhXYy09kzC8Jm0o62V6o0O16g9v2dNeCssdyoiimGkQf9Khb9TljEvNhydh+ZRjRaenTB4yHOm7D
  1932. BUrLDxrSL/Vi01amfT/q+M2qfYdWDZmd4uMcExVdlhKeBTXkIYgE6hO3SrsA9MjNeb+7NytvLeuG
  1933. gKonWau8OUlaBc6mu7Qa2mgXjBg67cAWs7nJ8plQbn2FzpuFyOMn5xwt0kWiQZB7JCU1IRZ+08XX
  1934. HSvVcnmWFsOtwvfKerJlP/d5plvejpd4zup4srCk4pLz1w2XG4kstTK/rDZ5VFL27WRpnGEugvJ8
  1935. 25XrmDxgBTLVIMs7SMXpCIbsoL4lGnrZLEausA/L0t1t0/JopLpwWOANLWMXaZWTmpDpKWBXAy/E
  1936. h8uUt65uLCLB79BlfwmDg9MVlyFFeLxcWu28oPDADYx1nsm8gmXImRUgX6yHOXa9s+tSvqynu4VT
  1937. M+QpiuHtgt3KS0zAchR3dPpoyavr2RWILu8AUVqCfsmyNgbyjgKxzlHNM0caMb7lSf93DjH545lH
  1938. /LMcYsR44RH/LIeYeuUzj5g4BI6eSZW6CyrgTQO1FAYJRGU+Phuen0GiGnTiEvjI7O6gs/mvPAhS
  1939. 6UFDAc9aidGStUkPta4FaiOhrEHJSaS07i2fBFySklXqJGDQoyaPfBFUYykF9ZBJGkHaduRjL0t1
  1940. FgFqV2Ub6Bu/CiqpFaGTrgq3x4XJp0ZytQygl4pd3tYsQqIMKn3eC+HV876x3qXOAHpyxI1nTTzo
  1941. leuDuithZBBwJ3DHIAZyAvwNjnVPPoabnrjJTrcFdrUW1LXXcOa+SGCziaa6fkm3lsczUJMIzuIq
  1942. 8chFNjeVFpunPtsp61N4uyV0JuYMu28dR/YBlyJ2CieZ6ZGKKWzEKG324mwES1tCYnxENZj0mMaN
  1943. 4aE5rmrzfoiGaDjuachHe1my9HuhMV57NRZzho8J8TDVU36Tci1iLT07uJMH1rTUDcqeIwXVaa1j
  1944. 6eUVWRPdRYBbMFt7Kbp2vEDp9DlOCKnFEaY6cbo9puw0iSU31xNaRlfEoY1Yu0NbsTZNGtOP3oLt
  1945. 8MxPtXTvozHChRZbQtfl3CeZbUiyk0/19hTwey6nYgKNBPq6YowqWA1wFlwhnm+QvSXU7pWtsizF
  1946. T6x02NpIXmiitw09QdxPsR4cu0Ms1fDeUhjAcCiaOOjkLYbo1MtI4XTp+jktynWBC8myGjZbT6ND
  1947. pcwEwGvFc3mbehRaMnOYzo/nJE2XpbPG6LqIscO1YkFPdE9XmDwxRrFYVgY+9zTpqiDBMe3oob/5
  1948. anMuJn9AcXPzkAi7H5n7UpdpaamzPH9BsEFHuyTG7QZec/O62UTnu1/pjat4lSc18A6JOxe+iiPG
  1949. /QDve5bILXYu931ddgp067b1phSOzVXbBd1pm4ICtk4DI9G1Iym4rKrxsRIRVN321mLiY/bF7WLN
  1950. qVHZp9wsbaza4EJ7uxZU4rzRNv7czQqDQSuOPWWtrtrDrky3co9fuXtNE1MtzCSEznIpAP1wjwUC
  1951. jmFMHARHD9Q+MlXHuRbwJ1mgsBgDdRKdOB05ctUODBEdN91tQGLNg2dpE28Fs2T0hj+SWGceJl4E
  1952. qIsI5k1aevs9J6eerWLeg/uiFB1ImtETQckZ+Za7tG26XJiqxPmCtsvcbcc+uHOM40FH55gGUehp
  1953. xJD2SdVQleUMVd4cyTjCXOhWuqCWc+ELDwR/m8A2gh7zOcQmPvjCBR+8kCPGOQlw8eaNDWBON6M/
  1954. 5L/MrpruxRBXfIZfrRiD3mHkf4QB6tGjN7zhaQ8sAt91b/kl1wV+3u3v5nfz8TgbP+vxw/l4mvnl
  1955. G94mcm6fhcB8N4d7MD1wTDJM/RbRE4vAQxMWWzeVx74TeMwWfMLkbY/RUxrUZvnlvN4600sbzPwT
  1956. pzP0xmOFwIHNhxz9TZ/COfaFR3eBm+oAhwb8WAP7VxXoWZMtDsI9ZJmJLzcWo1+B3NLNcMD5tQD0
  1957. hWDk1C5zL0xjFYMe2loRDtnAnhFzxPCNpLF6vBvPBritmd5BL6Uh29g1bo92gdW9mYXGOGBOAuEa
  1958. L/pOMfbQ+W1PLhwYDaSzDs7a9fZZXglgbgNxZFvUqAvovUwyngd6jzT1W+Df3k1pYEeSgL4Vuimw
  1959. lUlqIAt8TQUaDKZOduQCD2zuek+AnhXH0A24C+Fxt8uRHzzrzv0DvkU7MZjy5oIT2+n9B69iZU6k
  1960. wR41k69x+Ttz1TjTmQNXj3PVYy571I9IehOTEkVdVHwjkO6rHwcMD6M691i5O0bb1oHFwX2DP93t
  1961. S/4gegTOn2JKiHbgGYh9MAeC6vMWjwhj+SueaSQT5+ezh90uIo76gRloF1vj9343eAYH4ukeuojQ
  1962. j2sWozVf51RCmGra9G4rkFwBvzHMH8xt/O/MQ4/6QWFhOVD6euhyqj7EGS2HRBV30am/6kW+oqLe
  1963. 32x0fwstS4mM5EOgEERkrAOEvfnexJOPta1U65USw0UKXOLb6EGGVIrgXYdQg8qz2VsH35f9uTNw
  1964. ybAoW19TOLRKuO5S7tDTcnqtSRc6igzXxp07Toohc0I+oCv+6BIiu1Jvt43OqAR2WEXCpm7Zjk7A
  1965. XJHMubVO8XAaF/Q0z1WNHJNHvWwXu1u3sGHY3O/kjbkkoVZTKoS7WXf4IGi2SZ42LJwq8n1/hDOM
  1966. lCy8LqMJI1D7C4kkpr6EhYSLVoTU+YhErMmyvCjCCUGilWEvjvQ+kuCNcbqnimvqYXTLh4JLaRUd
  1967. MU6gH+YR3u7kw9kL1NSilicREqVVzBDYoIH6LtwBR8dBvqrgI7zjmBOn+/+8sxzfV44Yf/DOEhVI
  1968. 8+WdZfttTZ5ib8p9IQKdIE1qEKsrjno/++MnMy1A3kuBBI0zh4KOMwWuVEdQs21cIiYMn8RMPMjH
  1969. vkJhJocA24HNeUccMCIA6YHloFfjVwYMe4zCOQgpUXtsoIQXmSlOH3LgYfft+2ipupMxJrzD18c8
  1970. eYs3cX7gUxyXdaaDaFKJbC5Ctp5R+7KGBYvdqVx/9055fBepALsILmuP1jQje7ZID85lXZcpTVoH
  1971. IY/7O6LFB4G4iTGYNJ3mYEK3c0cTCyoBd7pUwj1M4JbjNWXvHad8kdYuJ0EHmToSXXpe3HF0xyU8
  1972. y2p3MaSuerthGQ2hDhh92XF4vTPLTRxdI3nnxlx1YQ8TL3Tja37Y85sA3vZUwfNXtl76ObK5gMF9
  1973. l5AGZa+sG6Kt+vOc685hqeHpMtyeSwhB6FCd3lvqVNEow5pna6fkF0Owz4hhD9thXO9z028914jE
  1974. 8+WSV3uWtpWLSZJOJFYnmWQXS7tNnRFjFS82eHja4i5uy2u62Na0IzKca7As48Y3XshUF+2WiLNx
  1975. 0IIM++JGJbiNzhMi7by23Y0YTO+ZtRychi3D+jmeH2IEMvFEGGTuQps2RzMcgWIRolHna8Pu1LuZ
  1976. h7rDpAsDOiQoP+kh75d0F+ku76rHvReInAe3Untw53EtlrEbrJTTLoTbBYHa6n1b9+66phD1eArh
  1977. y87ZklMdU+aKo2Plvmj2t/Kk3kkyPy4lMVYD3vV007dIal4uxNhmrLUrKN7WcxDKZpAoJheQ03iP
  1978. f8/UTro4JqLuSEdaljdrcm6JwcnVVpFoIU7aShIXrG0F3wmsVnDUQvGJq5jsTF+/LhdTLWRojQ9E
  1979. QU4584Qe+LbZ9Um4YhokbMmVLobsek4nZ0zs6B7aNOdrtWrobXoBE5VOZLk3zab3q0jc5+tTVWIr
  1980. CxQqtDi7qZkJ2W6TFaeFtKPYvdF9+fL6LyUq877/h9L/AoalQfY=
  1981. """
  1982. )
  1983. # file distutils-init.py
  1984. DISTUTILS_INIT = convert(
  1985. """
  1986. eJytV21v5DQQ/u5fMaRCJLANcHxBlVYI7g504nSgU7+gqorcxNk1zdrB9m679+uZsfPivGyPD0Sq
  1987. 5PWMZ8bPPDPjykOrjQN5aJkMS237lT0PyydulFQ7y9gV6LbUlQBpQWkHHE7SuCNvhDrBQVfHRmzA
  1988. angSUHIFR4uaDpyGWqoK3F6AdVUjH9DQO2+bK/cF3OIBbR5BK2jP7XmDimj/cLQOHgT6CIZxlzsw
  1989. wspKWJCKzKEdtHbdnt1eq29RT9ZSVNfP+Tn/BJU0onTanIfL+dgZQ4HiBwFbvG7ecrfPux0SWXd0
  1990. srEF7Ucaf2up0pl6GgzmRVHLRhRFtoFkMJBkTNbDcaXNgRbp1EEG20UQ6eLMYD+7YYBfn4+cFmly
  1991. i7BGaRg8QMvLR75DBB18aYG3reDGUjYQ1YAfWMKh0SV3EtHnNmyerROH0dBPeBfRWBG8Fz7yosil
  1992. ssK49LsNzC8FV8iOf/gN/Prjq+/9ISN4U4yRbYlzeaN5VYTkpkkxXmFUTDbwQSsx97CBNEER/ZGd
  1993. P3//rXjz7uPb17d/fPwry7zDK3it27O/jhGNOCHREAdn5MPRCetVnDmHG4VbGXGSFlEoCgxvGm8e
  1994. S/0R8VyK1sHPvcW3xmgzWmu5tR1YJ2EuWx2EjNVGR5BDR1na2FBCSq1quaN7SYuCG/soW8aGKzxw
  1995. KyzGonasC+0DZjaKalTAOHBBtYxQlnt4OMqmKsSzg5GcUGlh1VcOHpV+gj3+IWt2wnk8seJsVFze
  1996. zp6K9wmLXD9ZuKai33NTUXUESpEKUtDoY9cHvG9R0dXy1ohaPmeMCsb/brirkfxUHAka/eFVEi4x
  1997. xSgv9eHAVZWPN+hQGzeQ0RqXwwbzdsoG8zNqpROVbExjJWrqXLyRn0ShW6oRm1rR1JEOfRQ37uaI
  1998. jOHmjCnGOsMWRtydatK3VN3C3f1ETTRoEvmmLHbIUqSLI5soodl/c7HYy23bSNe3GyvajLEXjUQV
  1999. P2mLlDNP7ZBILMz3SJGkq8T+m4Ccr8PKXkjzanKHH10fCQbmuxFDthBx4SryQquOlfaGMYqWhlYR
  2000. Cs93YEKR1PI30oa6x8jzhRbDMRKIM92PmVP7QtjCqpsOi45ZCHWYVlgMrbbyORnzjQPW+DPdPEvy
  2001. 9hwBV++S0K2G5r16aPXMXGuR8T7ZE8U4aq8uLYnSqdIYC5Y5NgscNjiPGgwi9cAsy4t0cqEq+yRx
  2002. IC4iXikBbwhpedAnkdLxjE1FNA9Vla6Eb4Q7GhXUWHgTfCbliM8KDWJ6jS18yjFsqkV4vhRSlVSm
  2003. vWI+FXWsGsSzkyk1zcK2osQnULnFEg352VIP6uBBHMPmsjd1+959XMsxHstwp057l1jF7FKYOPMq
  2004. XfphuDTXC9klDGJ4ijk8M3vYuC6hSQ/QF9BE8RJNasQVjjSSXkQ3VgJqWf8j3IuopjF9FnzUuQx+
  2005. JFwHf4ZmMUezt9eJTzyMnImpSLYKfyRPv+ZmZztgPT6dxRU/ne6Qg5ceEPRhvDTN1lradIg1fogN
  2006. 56YTeQiK3qaly3y6k/fvfsGHaOL/N8KONihN29OwfdcfuMdo+rjwicftIz6NqDfyphmOzh8FUQjU
  2007. OmchoHvC5YLn/jHq19/AXef8fuqdzMaUHI4sSBblY4VlK1J2kRsLnsW8+Rc/zwIT
  2008. """
  2009. )
  2010. # file distutils.cfg
  2011. DISTUTILS_CFG = convert(
  2012. """
  2013. eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
  2014. xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
  2015. 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
  2016. """
  2017. )
  2018. # file activate_this.py
  2019. ACTIVATE_THIS = convert(
  2020. """
  2021. eJyNU8Fu2zAMvesrCA1FbSxzhvUWIIcOGLDDNvTQyxAEhmLTiVZZMiTFif9+pFwnbtFiM2BbFJ8e
  2022. +ShSSvl1gGPQdg94xqrRBrN40KHk1QJqXcWsTEZZri+OPIfBHeGkjRGqirpXEYG90Gsfj8qg7YFe
  2023. 7Z1t0cZCiEf2VsrCDike1nA6oE0s7TFE3gJy4lmHyMk8DPHgLGgb0Xce6bsA66KIB5zH2Gm77BJU
  2024. SCmFiH5YCaBnylngucIuwi/V4jfvnR/dXmkKeB8C+qidTZ4sefiRv6e0/NGOuox+wmuFbjsVD8vo
  2025. lpP4kkFFN9y+Ltn7yDyXKWAudNs5H8GFaRV0xMt6CEI4U5culMwFawIWz7Ut9hgz+XD/+F0uQMpc
  2026. XF2bcXs74vlkUWtvqQzZZKtd4P8lWbrVjxM4YMfGNa7YKarY+2T/JiehDcspOqNi43wL6zXIk7Z3
  2027. X+R4K6ybglVPao9hFuuP0zbj+CTyh96xVoZ+mqAkHE3A/ycxI8nYOTdBwk1KrEcfqBs2q7vtGyGo
  2028. DfuSYNM1GGrVLOkhOxeC8YWqa/5TNbIXieSCkR6VKYmn0WciSGeTIa5L2uckxQf46XoeKpqLuqZ5
  2029. IbY2QHRpq6Ebpo5pksHxV8LiaZ7dZiuoxukUTdGrZMdK0XUkN80VQ17oW12GYc5bqK5DW2d8LL8g
  2030. JlqS11LOz95pd7P6zE04pxF/AX70hVA=
  2031. """
  2032. )
  2033. # file python-config
  2034. PYTHON_CONFIG = convert(
  2035. """
  2036. eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue
  2037. e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll
  2038. rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn
  2039. 3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/
  2040. dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7
  2041. PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM
  2042. osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT
  2043. /mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad
  2044. 0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1
  2045. 1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV
  2046. 8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE
  2047. LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl
  2048. g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD
  2049. /vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9
  2050. MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA==
  2051. """
  2052. )
  2053. MH_MAGIC = 0xFEEDFACE
  2054. MH_CIGAM = 0xCEFAEDFE
  2055. MH_MAGIC_64 = 0xFEEDFACF
  2056. MH_CIGAM_64 = 0xCFFAEDFE
  2057. FAT_MAGIC = 0xCAFEBABE
  2058. BIG_ENDIAN = ">"
  2059. LITTLE_ENDIAN = "<"
  2060. LC_LOAD_DYLIB = 0xC
  2061. maxint = majver == 3 and getattr(sys, "maxsize") or getattr(sys, "maxint")
  2062. class fileview(object):
  2063. """
  2064. A proxy for file-like objects that exposes a given view of a file.
  2065. Modified from macholib.
  2066. """
  2067. def __init__(self, fileobj, start=0, size=maxint):
  2068. if isinstance(fileobj, fileview):
  2069. self._fileobj = fileobj._fileobj
  2070. else:
  2071. self._fileobj = fileobj
  2072. self._start = start
  2073. self._end = start + size
  2074. self._pos = 0
  2075. def __repr__(self):
  2076. return "<fileview [%d, %d] %r>" % (self._start, self._end, self._fileobj)
  2077. def tell(self):
  2078. return self._pos
  2079. def _checkwindow(self, seekto, op):
  2080. if not (self._start <= seekto <= self._end):
  2081. raise IOError("%s to offset %d is outside window [%d, %d]" % (op, seekto, self._start, self._end))
  2082. def seek(self, offset, whence=0):
  2083. seekto = offset
  2084. if whence == os.SEEK_SET:
  2085. seekto += self._start
  2086. elif whence == os.SEEK_CUR:
  2087. seekto += self._start + self._pos
  2088. elif whence == os.SEEK_END:
  2089. seekto += self._end
  2090. else:
  2091. raise IOError("Invalid whence argument to seek: {!r}".format(whence))
  2092. self._checkwindow(seekto, "seek")
  2093. self._fileobj.seek(seekto)
  2094. self._pos = seekto - self._start
  2095. def write(self, bytes):
  2096. here = self._start + self._pos
  2097. self._checkwindow(here, "write")
  2098. self._checkwindow(here + len(bytes), "write")
  2099. self._fileobj.seek(here, os.SEEK_SET)
  2100. self._fileobj.write(bytes)
  2101. self._pos += len(bytes)
  2102. def read(self, size=maxint):
  2103. assert size >= 0
  2104. here = self._start + self._pos
  2105. self._checkwindow(here, "read")
  2106. size = min(size, self._end - here)
  2107. self._fileobj.seek(here, os.SEEK_SET)
  2108. bytes = self._fileobj.read(size)
  2109. self._pos += len(bytes)
  2110. return bytes
  2111. def read_data(file, endian, num=1):
  2112. """
  2113. Read a given number of 32-bits unsigned integers from the given file
  2114. with the given endianness.
  2115. """
  2116. res = struct.unpack(endian + "L" * num, file.read(num * 4))
  2117. if len(res) == 1:
  2118. return res[0]
  2119. return res
  2120. def mach_o_change(path, what, value):
  2121. """
  2122. Replace a given name (what) in any LC_LOAD_DYLIB command found in
  2123. the given binary with a new name (value), provided it's shorter.
  2124. """
  2125. def do_macho(file, bits, endian):
  2126. # Read Mach-O header (the magic number is assumed read by the caller)
  2127. cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file, endian, 6)
  2128. # 64-bits header has one more field.
  2129. if bits == 64:
  2130. read_data(file, endian)
  2131. # The header is followed by ncmds commands
  2132. for _ in range(ncmds):
  2133. where = file.tell()
  2134. # Read command header
  2135. cmd, cmdsize = read_data(file, endian, 2)
  2136. if cmd == LC_LOAD_DYLIB:
  2137. # The first data field in LC_LOAD_DYLIB commands is the
  2138. # offset of the name, starting from the beginning of the
  2139. # command.
  2140. name_offset = read_data(file, endian)
  2141. file.seek(where + name_offset, os.SEEK_SET)
  2142. # Read the NUL terminated string
  2143. load = file.read(cmdsize - name_offset).decode()
  2144. load = load[: load.index("\0")]
  2145. # If the string is what is being replaced, overwrite it.
  2146. if load == what:
  2147. file.seek(where + name_offset, os.SEEK_SET)
  2148. file.write(value.encode() + "\0".encode())
  2149. # Seek to the next command
  2150. file.seek(where + cmdsize, os.SEEK_SET)
  2151. def do_file(file, offset=0, size=maxint):
  2152. file = fileview(file, offset, size)
  2153. # Read magic number
  2154. magic = read_data(file, BIG_ENDIAN)
  2155. if magic == FAT_MAGIC:
  2156. # Fat binaries contain nfat_arch Mach-O binaries
  2157. nfat_arch = read_data(file, BIG_ENDIAN)
  2158. for _ in range(nfat_arch):
  2159. # Read arch header
  2160. cputype, cpusubtype, offset, size, align = read_data(file, BIG_ENDIAN, 5)
  2161. do_file(file, offset, size)
  2162. elif magic == MH_MAGIC:
  2163. do_macho(file, 32, BIG_ENDIAN)
  2164. elif magic == MH_CIGAM:
  2165. do_macho(file, 32, LITTLE_ENDIAN)
  2166. elif magic == MH_MAGIC_64:
  2167. do_macho(file, 64, BIG_ENDIAN)
  2168. elif magic == MH_CIGAM_64:
  2169. do_macho(file, 64, LITTLE_ENDIAN)
  2170. assert len(what) >= len(value)
  2171. with open(path, "r+b") as f:
  2172. do_file(f)
  2173. if __name__ == "__main__":
  2174. main()
  2175. # TODO:
  2176. # Copy python.exe.manifest
  2177. # Monkeypatch distutils.sysconfig