| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 """Create a "virtual" Python installation | 2 """Create a "virtual" Python installation""" |
| 3 """ | |
| 4 | 3 |
| 5 __version__ = "12.0" | 4 import os |
| 6 virtualenv_version = __version__ # legacy | 5 import sys |
| 7 | 6 |
| 8 # NB: avoid placing additional imports here, before sys.path is fixed! | 7 # If we are running in a new interpreter to create a virtualenv, |
| 9 | 8 # we do NOT want paths from our existing location interfering with anything, |
| 10 import sys | 9 # So we remove this file's directory from sys.path - most likely to be |
| 11 import os | 10 # the previous interpreter's site-packages. Solves #705, #763, #779 |
| 12 | |
| 13 # | |
| 14 # RATIONALE: | |
| 15 # This script is both it's own "host" and "guest". If it's running in "guest | |
| 16 # mode" (inside the virtualenv interpreter), it's essentially invoked via: | |
| 17 # /path/to/python /path/to/this/script.py | |
| 18 # | |
| 19 # Which, by the nature of Python, will put `/path/to/this` on the system path | |
| 20 # as the first argument. Now this can cause many subtle bugs, because the | |
| 21 # rest of the script is now looking to import from the "host" Python version | |
| 22 # first. This has been especially troublesome when trying to create a Python | |
| 23 # 3 "guest" env using a Python 2 "host", but even with minor Python | |
| 24 # differences, there may been some bleeding between environments that doesn't | |
| 25 # stand out as obviously. | |
| 26 # | |
| 27 # This removes the first argument off the system path, to avoid any accidental | |
| 28 # usage of the "host" library directories. | |
| 29 # | |
| 30 if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): | 11 if os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'): |
| 31 del sys.path[0] | 12 for path in sys.path[:]: |
| 13 if os.path.realpath(os.path.dirname(__file__)) == os.path.realpath(path)
: |
| 14 sys.path.remove(path) |
| 32 | 15 |
| 33 import base64 | 16 import base64 |
| 34 import codecs | 17 import codecs |
| 35 import optparse | 18 import optparse |
| 36 import re | 19 import re |
| 37 import shutil | 20 import shutil |
| 38 import logging | 21 import logging |
| 39 import tempfile | |
| 40 import zlib | 22 import zlib |
| 41 import errno | 23 import errno |
| 42 import glob | 24 import glob |
| 43 import distutils.sysconfig | 25 import distutils.sysconfig |
| 44 from distutils.util import strtobool | |
| 45 import struct | 26 import struct |
| 46 import subprocess | 27 import subprocess |
| 47 import tarfile | 28 import pkgutil |
| 29 import tempfile |
| 30 import textwrap |
| 31 from distutils.util import strtobool |
| 32 from os.path import join |
| 33 |
| 34 try: |
| 35 import ConfigParser |
| 36 except ImportError: |
| 37 import configparser as ConfigParser |
| 38 |
| 39 __version__ = "15.1.0" |
| 40 virtualenv_version = __version__ # legacy |
| 48 | 41 |
| 49 if sys.version_info < (2, 6): | 42 if sys.version_info < (2, 6): |
| 50 print('ERROR: %s' % sys.exc_info()[1]) | 43 print('ERROR: %s' % sys.exc_info()[1]) |
| 51 print('ERROR: this script requires Python 2.6 or greater.') | 44 print('ERROR: this script requires Python 2.6 or greater.') |
| 52 sys.exit(101) | 45 sys.exit(101) |
| 53 | 46 |
| 54 try: | 47 try: |
| 55 basestring | 48 basestring |
| 56 except NameError: | 49 except NameError: |
| 57 basestring = str | 50 basestring = str |
| 58 | 51 |
| 59 try: | |
| 60 import ConfigParser | |
| 61 except ImportError: | |
| 62 import configparser as ConfigParser | |
| 63 | |
| 64 join = os.path.join | |
| 65 py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) | 52 py_version = 'python%s.%s' % (sys.version_info[0], sys.version_info[1]) |
| 66 | 53 |
| 67 is_jython = sys.platform.startswith('java') | 54 is_jython = sys.platform.startswith('java') |
| 68 is_pypy = hasattr(sys, 'pypy_version_info') | 55 is_pypy = hasattr(sys, 'pypy_version_info') |
| 69 is_win = (sys.platform == 'win32') | 56 is_win = (sys.platform == 'win32') |
| 70 is_cygwin = (sys.platform == 'cygwin') | 57 is_cygwin = (sys.platform == 'cygwin') |
| 71 is_darwin = (sys.platform == 'darwin') | 58 is_darwin = (sys.platform == 'darwin') |
| 72 abiflags = getattr(sys, 'abiflags', '') | 59 abiflags = getattr(sys, 'abiflags', '') |
| 73 | 60 |
| 74 user_dir = os.path.expanduser('~') | 61 user_dir = os.path.expanduser('~') |
| (...skipping 17 matching lines...) Expand all Loading... |
| 92 return {} | 79 return {} |
| 93 else: | 80 else: |
| 94 try: | 81 try: |
| 95 import winreg | 82 import winreg |
| 96 except ImportError: | 83 except ImportError: |
| 97 import _winreg as winreg | 84 import _winreg as winreg |
| 98 | 85 |
| 99 def get_installed_pythons(): | 86 def get_installed_pythons(): |
| 100 try: | 87 try: |
| 101 python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, | 88 python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE, |
| 102 "Software\\Python\\PythonCore") | 89 "Software\\Python\\PythonCore") |
| 103 except WindowsError: | 90 except WindowsError: |
| 104 # No registered Python installations | 91 # No registered Python installations |
| 105 return {} | 92 return {} |
| 106 i = 0 | 93 i = 0 |
| 107 versions = [] | 94 versions = [] |
| 108 while True: | 95 while True: |
| 109 try: | 96 try: |
| 110 versions.append(winreg.EnumKey(python_core, i)) | 97 versions.append(winreg.EnumKey(python_core, i)) |
| 111 i = i + 1 | 98 i = i + 1 |
| 112 except WindowsError: | 99 except WindowsError: |
| (...skipping 26 matching lines...) Expand all Loading... |
| 139 | 126 |
| 140 majver, minver = sys.version_info[:2] | 127 majver, minver = sys.version_info[:2] |
| 141 if majver == 2: | 128 if majver == 2: |
| 142 if minver >= 6: | 129 if minver >= 6: |
| 143 REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) | 130 REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc']) |
| 144 if minver >= 7: | 131 if minver >= 7: |
| 145 REQUIRED_MODULES.extend(['_weakrefset']) | 132 REQUIRED_MODULES.extend(['_weakrefset']) |
| 146 elif majver == 3: | 133 elif majver == 3: |
| 147 # Some extra modules are needed for Python 3, but different ones | 134 # Some extra modules are needed for Python 3, but different ones |
| 148 # for different versions. | 135 # for different versions. |
| 149 REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io', | 136 REQUIRED_MODULES.extend([ |
| 150 '_weakrefset', 'copyreg', 'tempfile', 'random', | 137 » '_abcoll', 'warnings', 'linecache', 'abc', 'io', '_weakrefset', |
| 151 '__future__', 'collections', 'keyword', 'tarfile', | 138 » 'copyreg', 'tempfile', 'random', '__future__', 'collections', |
| 152 'shutil', 'struct', 'copy', 'tokenize', 'token', | 139 » 'keyword', 'tarfile', 'shutil', 'struct', 'copy', 'tokenize', |
| 153 'functools', 'heapq', 'bisect', 'weakref', | 140 » 'token', 'functools', 'heapq', 'bisect', 'weakref', 'reprlib' |
| 154 'reprlib']) | 141 ]) |
| 155 if minver >= 2: | 142 if minver >= 2: |
| 156 REQUIRED_FILES[-1] = 'config-%s' % majver | 143 REQUIRED_FILES[-1] = 'config-%s' % majver |
| 157 if minver >= 3: | 144 if minver >= 3: |
| 158 import sysconfig | 145 import sysconfig |
| 159 platdir = sysconfig.get_config_var('PLATDIR') | 146 platdir = sysconfig.get_config_var('PLATDIR') |
| 160 REQUIRED_FILES.append(platdir) | 147 REQUIRED_FILES.append(platdir) |
| 161 # The whole list of 3.3 modules is reproduced below - the current | |
| 162 # uncommented ones are required for 3.3 as of now, but more may be | |
| 163 # added as 3.3 development continues. | |
| 164 REQUIRED_MODULES.extend([ | 148 REQUIRED_MODULES.extend([ |
| 165 #"aifc", | 149 » 'base64', '_dummy_thread', 'hashlib', 'hmac', |
| 166 #"antigravity", | 150 » 'imp', 'importlib', 'rlcompleter' |
| 167 #"argparse", | |
| 168 #"ast", | |
| 169 #"asynchat", | |
| 170 #"asyncore", | |
| 171 "base64", | |
| 172 #"bdb", | |
| 173 #"binhex", | |
| 174 #"bisect", | |
| 175 #"calendar", | |
| 176 #"cgi", | |
| 177 #"cgitb", | |
| 178 #"chunk", | |
| 179 #"cmd", | |
| 180 #"codeop", | |
| 181 #"code", | |
| 182 #"colorsys", | |
| 183 #"_compat_pickle", | |
| 184 #"compileall", | |
| 185 #"concurrent", | |
| 186 #"configparser", | |
| 187 #"contextlib", | |
| 188 #"cProfile", | |
| 189 #"crypt", | |
| 190 #"csv", | |
| 191 #"ctypes", | |
| 192 #"curses", | |
| 193 #"datetime", | |
| 194 #"dbm", | |
| 195 #"decimal", | |
| 196 #"difflib", | |
| 197 #"dis", | |
| 198 #"doctest", | |
| 199 #"dummy_threading", | |
| 200 "_dummy_thread", | |
| 201 #"email", | |
| 202 #"filecmp", | |
| 203 #"fileinput", | |
| 204 #"formatter", | |
| 205 #"fractions", | |
| 206 #"ftplib", | |
| 207 #"functools", | |
| 208 #"getopt", | |
| 209 #"getpass", | |
| 210 #"gettext", | |
| 211 #"glob", | |
| 212 #"gzip", | |
| 213 "hashlib", | |
| 214 #"heapq", | |
| 215 "hmac", | |
| 216 #"html", | |
| 217 #"http", | |
| 218 #"idlelib", | |
| 219 #"imaplib", | |
| 220 #"imghdr", | |
| 221 "imp", | |
| 222 "importlib", | |
| 223 #"inspect", | |
| 224 #"json", | |
| 225 #"lib2to3", | |
| 226 #"logging", | |
| 227 #"macpath", | |
| 228 #"macurl2path", | |
| 229 #"mailbox", | |
| 230 #"mailcap", | |
| 231 #"_markupbase", | |
| 232 #"mimetypes", | |
| 233 #"modulefinder", | |
| 234 #"multiprocessing", | |
| 235 #"netrc", | |
| 236 #"nntplib", | |
| 237 #"nturl2path", | |
| 238 #"numbers", | |
| 239 #"opcode", | |
| 240 #"optparse", | |
| 241 #"os2emxpath", | |
| 242 #"pdb", | |
| 243 #"pickle", | |
| 244 #"pickletools", | |
| 245 #"pipes", | |
| 246 #"pkgutil", | |
| 247 #"platform", | |
| 248 #"plat-linux2", | |
| 249 #"plistlib", | |
| 250 #"poplib", | |
| 251 #"pprint", | |
| 252 #"profile", | |
| 253 #"pstats", | |
| 254 #"pty", | |
| 255 #"pyclbr", | |
| 256 #"py_compile", | |
| 257 #"pydoc_data", | |
| 258 #"pydoc", | |
| 259 #"_pyio", | |
| 260 #"queue", | |
| 261 #"quopri", | |
| 262 #"reprlib", | |
| 263 "rlcompleter", | |
| 264 #"runpy", | |
| 265 #"sched", | |
| 266 #"shelve", | |
| 267 #"shlex", | |
| 268 #"smtpd", | |
| 269 #"smtplib", | |
| 270 #"sndhdr", | |
| 271 #"socket", | |
| 272 #"socketserver", | |
| 273 #"sqlite3", | |
| 274 #"ssl", | |
| 275 #"stringprep", | |
| 276 #"string", | |
| 277 #"_strptime", | |
| 278 #"subprocess", | |
| 279 #"sunau", | |
| 280 #"symbol", | |
| 281 #"symtable", | |
| 282 #"sysconfig", | |
| 283 #"tabnanny", | |
| 284 #"telnetlib", | |
| 285 #"test", | |
| 286 #"textwrap", | |
| 287 #"this", | |
| 288 #"_threading_local", | |
| 289 #"threading", | |
| 290 #"timeit", | |
| 291 #"tkinter", | |
| 292 #"tokenize", | |
| 293 #"token", | |
| 294 #"traceback", | |
| 295 #"trace", | |
| 296 #"tty", | |
| 297 #"turtledemo", | |
| 298 #"turtle", | |
| 299 #"unittest", | |
| 300 #"urllib", | |
| 301 #"uuid", | |
| 302 #"uu", | |
| 303 #"wave", | |
| 304 #"weakref", | |
| 305 #"webbrowser", | |
| 306 #"wsgiref", | |
| 307 #"xdrlib", | |
| 308 #"xml", | |
| 309 #"xmlrpc", | |
| 310 #"zipfile", | |
| 311 ]) | 151 ]) |
| 312 if minver >= 4: | 152 if minver >= 4: |
| 313 REQUIRED_MODULES.extend([ | 153 REQUIRED_MODULES.extend([ |
| 314 'operator', | 154 'operator', |
| 315 '_collections_abc', | 155 '_collections_abc', |
| 316 '_bootlocale', | 156 '_bootlocale', |
| 317 ]) | 157 ]) |
| 158 if minver >= 6: |
| 159 REQUIRED_MODULES.extend(['enum']) |
| 318 | 160 |
| 319 if is_pypy: | 161 if is_pypy: |
| 320 # these are needed to correctly display the exceptions that may happen | 162 # these are needed to correctly display the exceptions that may happen |
| 321 # during the bootstrap | 163 # during the bootstrap |
| 322 REQUIRED_MODULES.extend(['traceback', 'linecache']) | 164 REQUIRED_MODULES.extend(['traceback', 'linecache']) |
| 323 | 165 |
| 166 if majver == 3: |
| 167 # _functools is needed to import locale during stdio initialization and |
| 168 # needs to be copied on PyPy because it's not built in |
| 169 REQUIRED_MODULES.append('_functools') |
| 170 |
| 171 |
| 324 class Logger(object): | 172 class Logger(object): |
| 325 | 173 |
| 326 """ | 174 """ |
| 327 Logging object for use in command-line script. Allows ranges of | 175 Logging object for use in command-line script. Allows ranges of |
| 328 levels, to avoid some redundancy of displayed information. | 176 levels, to avoid some redundancy of displayed information. |
| 329 """ | 177 """ |
| 330 | 178 |
| 331 DEBUG = logging.DEBUG | 179 DEBUG = logging.DEBUG |
| 332 INFO = logging.INFO | 180 INFO = logging.INFO |
| 333 NOTIFY = (logging.INFO+logging.WARN)/2 | 181 NOTIFY = (logging.INFO+logging.WARN)/2 |
| 334 WARN = WARNING = logging.WARN | 182 WARN = WARNING = logging.WARN |
| 335 ERROR = logging.ERROR | 183 ERROR = logging.ERROR |
| 336 FATAL = logging.FATAL | 184 FATAL = logging.FATAL |
| 337 | 185 |
| 338 LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] | 186 LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL] |
| 339 | 187 |
| 340 def __init__(self, consumers): | 188 def __init__(self, consumers): |
| 341 self.consumers = consumers | 189 self.consumers = consumers |
| 342 self.indent = 0 | 190 self.indent = 0 |
| 343 self.in_progress = None | 191 self.in_progress = None |
| 344 self.in_progress_hanging = False | 192 self.in_progress_hanging = False |
| 345 | 193 |
| 346 def debug(self, msg, *args, **kw): | 194 def debug(self, msg, *args, **kw): |
| 347 self.log(self.DEBUG, msg, *args, **kw) | 195 self.log(self.DEBUG, msg, *args, **kw) |
| 196 |
| 348 def info(self, msg, *args, **kw): | 197 def info(self, msg, *args, **kw): |
| 349 self.log(self.INFO, msg, *args, **kw) | 198 self.log(self.INFO, msg, *args, **kw) |
| 199 |
| 350 def notify(self, msg, *args, **kw): | 200 def notify(self, msg, *args, **kw): |
| 351 self.log(self.NOTIFY, msg, *args, **kw) | 201 self.log(self.NOTIFY, msg, *args, **kw) |
| 202 |
| 352 def warn(self, msg, *args, **kw): | 203 def warn(self, msg, *args, **kw): |
| 353 self.log(self.WARN, msg, *args, **kw) | 204 self.log(self.WARN, msg, *args, **kw) |
| 205 |
| 354 def error(self, msg, *args, **kw): | 206 def error(self, msg, *args, **kw): |
| 355 self.log(self.ERROR, msg, *args, **kw) | 207 self.log(self.ERROR, msg, *args, **kw) |
| 208 |
| 356 def fatal(self, msg, *args, **kw): | 209 def fatal(self, msg, *args, **kw): |
| 357 self.log(self.FATAL, msg, *args, **kw) | 210 self.log(self.FATAL, msg, *args, **kw) |
| 211 |
| 358 def log(self, level, msg, *args, **kw): | 212 def log(self, level, msg, *args, **kw): |
| 359 if args: | 213 if args: |
| 360 if kw: | 214 if kw: |
| 361 raise TypeError( | 215 raise TypeError( |
| 362 "You may give positional or keyword arguments, not both") | 216 "You may give positional or keyword arguments, not both") |
| 363 args = args or kw | 217 args = args or kw |
| 364 rendered = None | 218 rendered = None |
| 365 for consumer_level, consumer in self.consumers: | 219 for consumer_level, consumer in self.consumers: |
| 366 if self.level_matches(level, consumer_level): | 220 if self.level_matches(level, consumer_level): |
| 367 if (self.in_progress_hanging | 221 if (self.in_progress_hanging |
| (...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 443 if isinstance(level, slice): | 297 if isinstance(level, slice): |
| 444 start, stop = level.start, level.stop | 298 start, stop = level.start, level.stop |
| 445 if start is not None and start > consumer_level: | 299 if start is not None and start > consumer_level: |
| 446 return False | 300 return False |
| 447 if stop is not None and stop <= consumer_level: | 301 if stop is not None and stop <= consumer_level: |
| 448 return False | 302 return False |
| 449 return True | 303 return True |
| 450 else: | 304 else: |
| 451 return level >= consumer_level | 305 return level >= consumer_level |
| 452 | 306 |
| 453 #@classmethod | 307 @classmethod |
| 454 def level_for_integer(cls, level): | 308 def level_for_integer(cls, level): |
| 455 levels = cls.LEVELS | 309 levels = cls.LEVELS |
| 456 if level < 0: | 310 if level < 0: |
| 457 return levels[0] | 311 return levels[0] |
| 458 if level >= len(levels): | 312 if level >= len(levels): |
| 459 return levels[-1] | 313 return levels[-1] |
| 460 return levels[level] | 314 return levels[level] |
| 461 | 315 |
| 462 level_for_integer = classmethod(level_for_integer) | |
| 463 | |
| 464 # create a silent logger just to prevent this from being undefined | 316 # create a silent logger just to prevent this from being undefined |
| 465 # will be overridden with requested verbosity main() is called. | 317 # will be overridden with requested verbosity main() is called. |
| 466 logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) | 318 logger = Logger([(Logger.LEVELS[-1], sys.stdout)]) |
| 467 | 319 |
| 468 def mkdir(path): | 320 def mkdir(path): |
| 469 if not os.path.exists(path): | 321 if not os.path.exists(path): |
| 470 logger.info('Creating %s', path) | 322 logger.info('Creating %s', path) |
| 471 os.makedirs(path) | 323 os.makedirs(path) |
| 472 else: | 324 else: |
| 473 logger.info('Directory %s already exists', path) | 325 logger.info('Directory %s already exists', path) |
| (...skipping 26 matching lines...) Expand all Loading... |
| 500 except (OSError, NotImplementedError): | 352 except (OSError, NotImplementedError): |
| 501 logger.info('Symlinking failed, copying to %s', dest) | 353 logger.info('Symlinking failed, copying to %s', dest) |
| 502 copyfileordir(src, dest, symlink) | 354 copyfileordir(src, dest, symlink) |
| 503 else: | 355 else: |
| 504 logger.info('Copying to %s', dest) | 356 logger.info('Copying to %s', dest) |
| 505 copyfileordir(src, dest, symlink) | 357 copyfileordir(src, dest, symlink) |
| 506 | 358 |
| 507 def writefile(dest, content, overwrite=True): | 359 def writefile(dest, content, overwrite=True): |
| 508 if not os.path.exists(dest): | 360 if not os.path.exists(dest): |
| 509 logger.info('Writing %s', dest) | 361 logger.info('Writing %s', dest) |
| 510 f = open(dest, 'wb') | 362 with open(dest, 'wb') as f: |
| 511 f.write(content.encode('utf-8')) | 363 f.write(content.encode('utf-8')) |
| 512 f.close() | |
| 513 return | 364 return |
| 514 else: | 365 else: |
| 515 f = open(dest, 'rb') | 366 with open(dest, 'rb') as f: |
| 516 c = f.read() | 367 c = f.read() |
| 517 f.close() | |
| 518 if c != content.encode("utf-8"): | 368 if c != content.encode("utf-8"): |
| 519 if not overwrite: | 369 if not overwrite: |
| 520 logger.notify('File %s exists with different content; not overwr
iting', dest) | 370 logger.notify('File %s exists with different content; not overwr
iting', dest) |
| 521 return | 371 return |
| 522 logger.notify('Overwriting %s with new content', dest) | 372 logger.notify('Overwriting %s with new content', dest) |
| 523 f = open(dest, 'wb') | 373 with open(dest, 'wb') as f: |
| 524 f.write(content.encode('utf-8')) | 374 f.write(content.encode('utf-8')) |
| 525 f.close() | |
| 526 else: | 375 else: |
| 527 logger.info('Content %s already in place', dest) | 376 logger.info('Content %s already in place', dest) |
| 528 | 377 |
| 529 def rmtree(dir): | 378 def rmtree(dir): |
| 530 if os.path.exists(dir): | 379 if os.path.exists(dir): |
| 531 logger.notify('Deleting tree %s', dir) | 380 logger.notify('Deleting tree %s', dir) |
| 532 shutil.rmtree(dir) | 381 shutil.rmtree(dir) |
| 533 else: | 382 else: |
| 534 logger.info('Do not need to delete %s; already gone', dir) | 383 logger.info('Do not need to delete %s; already gone', dir) |
| 535 | 384 |
| 536 def make_exe(fn): | 385 def make_exe(fn): |
| 537 if hasattr(os, 'chmod'): | 386 if hasattr(os, 'chmod'): |
| 538 oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 | 387 oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777 |
| 539 newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 | 388 newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777 |
| 540 os.chmod(fn, newmode) | 389 os.chmod(fn, newmode) |
| 541 logger.info('Changed mode of %s to %s', fn, oct(newmode)) | 390 logger.info('Changed mode of %s to %s', fn, oct(newmode)) |
| 542 | 391 |
| 543 def _find_file(filename, dirs): | 392 def _find_file(filename, dirs): |
| 544 for dir in reversed(dirs): | 393 for dir in reversed(dirs): |
| 545 files = glob.glob(os.path.join(dir, filename)) | 394 files = glob.glob(os.path.join(dir, filename)) |
| 546 if files and os.path.isfile(files[0]): | 395 if files and os.path.isfile(files[0]): |
| 547 return True, files[0] | 396 return True, files[0] |
| 548 return False, filename | 397 return False, filename |
| 549 | 398 |
| 550 def file_search_dirs(): | 399 def file_search_dirs(): |
| 551 here = os.path.dirname(os.path.abspath(__file__)) | 400 here = os.path.dirname(os.path.abspath(__file__)) |
| 552 dirs = ['.', here, | 401 dirs = [here, join(here, 'virtualenv_support')] |
| 553 join(here, 'virtualenv_support')] | |
| 554 if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': | 402 if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv': |
| 555 # Probably some boot script; just in case virtualenv is installed... | 403 # Probably some boot script; just in case virtualenv is installed... |
| 556 try: | 404 try: |
| 557 import virtualenv | 405 import virtualenv |
| 558 except ImportError: | 406 except ImportError: |
| 559 pass | 407 pass |
| 560 else: | 408 else: |
| 561 dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virt
ualenv_support')) | 409 dirs.append(os.path.join( |
| 410 os.path.dirname(virtualenv.__file__), 'virtualenv_support')) |
| 562 return [d for d in dirs if os.path.isdir(d)] | 411 return [d for d in dirs if os.path.isdir(d)] |
| 563 | 412 |
| 564 | 413 |
| 565 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): | 414 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter): |
| 566 """ | 415 """ |
| 567 Custom help formatter for use in ConfigOptionParser that updates | 416 Custom help formatter for use in ConfigOptionParser that updates |
| 568 the defaults before expanding them, allowing them to show up correctly | 417 the defaults before expanding them, allowing them to show up correctly |
| 569 in the help listing | 418 in the help listing |
| 570 """ | 419 """ |
| 571 def expand_default(self, option): | 420 def expand_default(self, option): |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 730 '--relocatable', | 579 '--relocatable', |
| 731 dest='relocatable', | 580 dest='relocatable', |
| 732 action='store_true', | 581 action='store_true', |
| 733 help='Make an EXISTING virtualenv environment relocatable. ' | 582 help='Make an EXISTING virtualenv environment relocatable. ' |
| 734 'This fixes up scripts and makes all .pth files relative.') | 583 'This fixes up scripts and makes all .pth files relative.') |
| 735 | 584 |
| 736 parser.add_option( | 585 parser.add_option( |
| 737 '--no-setuptools', | 586 '--no-setuptools', |
| 738 dest='no_setuptools', | 587 dest='no_setuptools', |
| 739 action='store_true', | 588 action='store_true', |
| 740 help='Do not install setuptools (or pip) in the new virtualenv.') | 589 help='Do not install setuptools in the new virtualenv.') |
| 741 | 590 |
| 742 parser.add_option( | 591 parser.add_option( |
| 743 '--no-pip', | 592 '--no-pip', |
| 744 dest='no_pip', | 593 dest='no_pip', |
| 745 action='store_true', | 594 action='store_true', |
| 746 help='Do not install pip in the new virtualenv.') | 595 help='Do not install pip in the new virtualenv.') |
| 747 | 596 |
| 597 parser.add_option( |
| 598 '--no-wheel', |
| 599 dest='no_wheel', |
| 600 action='store_true', |
| 601 help='Do not install wheel in the new virtualenv.') |
| 602 |
| 748 default_search_dirs = file_search_dirs() | 603 default_search_dirs = file_search_dirs() |
| 749 parser.add_option( | 604 parser.add_option( |
| 750 '--extra-search-dir', | 605 '--extra-search-dir', |
| 751 dest="search_dirs", | 606 dest="search_dirs", |
| 752 action="append", | 607 action="append", |
| 753 metavar='DIR', | 608 metavar='DIR', |
| 754 default=default_search_dirs, | 609 default=default_search_dirs, |
| 755 help="Directory to look for setuptools/pip distributions in. " | 610 help="Directory to look for setuptools/pip distributions in. " |
| 756 "This option can be used multiple times.") | 611 "This option can be used multiple times.") |
| 757 | 612 |
| 758 parser.add_option( | 613 parser.add_option( |
| 614 "--download", |
| 615 dest="download", |
| 616 default=True, |
| 617 action="store_true", |
| 618 help="Download preinstalled packages from PyPI.", |
| 619 ) |
| 620 |
| 621 parser.add_option( |
| 622 "--no-download", |
| 759 '--never-download', | 623 '--never-download', |
| 760 dest="never_download", | 624 dest="download", |
| 761 action="store_true", | 625 action="store_false", |
| 762 default=True, | 626 help="Do not download preinstalled packages from PyPI.", |
| 763 help="DEPRECATED. Retained only for backward compatibility. This option
has no effect. " | 627 ) |
| 764 "Virtualenv never downloads pip or setuptools.") | |
| 765 | 628 |
| 766 parser.add_option( | 629 parser.add_option( |
| 767 '--prompt', | 630 '--prompt', |
| 768 dest='prompt', | 631 dest='prompt', |
| 769 help='Provides an alternative prompt prefix for this environment.') | 632 help='Provides an alternative prompt prefix for this environment.') |
| 770 | 633 |
| 771 parser.add_option( | 634 parser.add_option( |
| 772 '--setuptools', | 635 '--setuptools', |
| 773 dest='setuptools', | 636 dest='setuptools', |
| 774 action='store_true', | 637 action='store_true', |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 812 parser.print_help() | 675 parser.print_help() |
| 813 sys.exit(2) | 676 sys.exit(2) |
| 814 if len(args) > 1: | 677 if len(args) > 1: |
| 815 print('There must be only one argument: DEST_DIR (you gave %s)' % ( | 678 print('There must be only one argument: DEST_DIR (you gave %s)' % ( |
| 816 ' '.join(args))) | 679 ' '.join(args))) |
| 817 parser.print_help() | 680 parser.print_help() |
| 818 sys.exit(2) | 681 sys.exit(2) |
| 819 | 682 |
| 820 home_dir = args[0] | 683 home_dir = args[0] |
| 821 | 684 |
| 685 if os.path.exists(home_dir) and os.path.isfile(home_dir): |
| 686 logger.fatal('ERROR: File already exists and is not a directory.') |
| 687 logger.fatal('Please provide a different path or delete the file.') |
| 688 sys.exit(3) |
| 689 |
| 822 if os.environ.get('WORKING_ENV'): | 690 if os.environ.get('WORKING_ENV'): |
| 823 logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') | 691 logger.fatal('ERROR: you cannot run virtualenv while in a workingenv') |
| 824 logger.fatal('Please deactivate your workingenv, then re-run this script
') | 692 logger.fatal('Please deactivate your workingenv, then re-run this script
') |
| 825 sys.exit(3) | 693 sys.exit(3) |
| 826 | 694 |
| 827 if 'PYTHONHOME' in os.environ: | 695 if 'PYTHONHOME' in os.environ: |
| 828 logger.warn('PYTHONHOME is set. You *must* activate the virtualenv befo
re using it') | 696 logger.warn('PYTHONHOME is set. You *must* activate the virtualenv befo
re using it') |
| 829 del os.environ['PYTHONHOME'] | 697 del os.environ['PYTHONHOME'] |
| 830 | 698 |
| 831 if options.relocatable: | 699 if options.relocatable: |
| 832 make_environment_relocatable(home_dir) | 700 make_environment_relocatable(home_dir) |
| 833 return | 701 return |
| 834 | 702 |
| 835 if not options.never_download: | |
| 836 logger.warn('The --never-download option is for backward compatibility o
nly.') | |
| 837 logger.warn('Setting it to false is no longer supported, and will be ign
ored.') | |
| 838 | |
| 839 create_environment(home_dir, | 703 create_environment(home_dir, |
| 840 site_packages=options.system_site_packages, | 704 site_packages=options.system_site_packages, |
| 841 clear=options.clear, | 705 clear=options.clear, |
| 842 unzip_setuptools=options.unzip_setuptools, | 706 unzip_setuptools=options.unzip_setuptools, |
| 843 prompt=options.prompt, | 707 prompt=options.prompt, |
| 844 search_dirs=options.search_dirs, | 708 search_dirs=options.search_dirs, |
| 845 never_download=True, | 709 download=options.download, |
| 846 no_setuptools=options.no_setuptools, | 710 no_setuptools=options.no_setuptools, |
| 847 no_pip=options.no_pip, | 711 no_pip=options.no_pip, |
| 712 no_wheel=options.no_wheel, |
| 848 symlink=options.symlink) | 713 symlink=options.symlink) |
| 849 if 'after_install' in globals(): | 714 if 'after_install' in globals(): |
| 850 after_install(options, home_dir) | 715 after_install(options, home_dir) |
| 851 | 716 |
| 852 def call_subprocess(cmd, show_stdout=True, | 717 def call_subprocess(cmd, show_stdout=True, |
| 853 filter_stdout=None, cwd=None, | 718 filter_stdout=None, cwd=None, |
| 854 raise_on_returncode=True, extra_env=None, | 719 raise_on_returncode=True, extra_env=None, |
| 855 remove_from_env=None): | 720 remove_from_env=None, stdin=None): |
| 856 cmd_parts = [] | 721 cmd_parts = [] |
| 857 for part in cmd: | 722 for part in cmd: |
| 858 if len(part) > 45: | 723 if len(part) > 45: |
| 859 part = part[:20]+"..."+part[-20:] | 724 part = part[:20]+"..."+part[-20:] |
| 860 if ' ' in part or '\n' in part or '"' in part or "'" in part: | 725 if ' ' in part or '\n' in part or '"' in part or "'" in part: |
| 861 part = '"%s"' % part.replace('"', '\\"') | 726 part = '"%s"' % part.replace('"', '\\"') |
| 862 if hasattr(part, 'decode'): | 727 if hasattr(part, 'decode'): |
| 863 try: | 728 try: |
| 864 part = part.decode(sys.getdefaultencoding()) | 729 part = part.decode(sys.getdefaultencoding()) |
| 865 except UnicodeDecodeError: | 730 except UnicodeDecodeError: |
| 866 part = part.decode(sys.getfilesystemencoding()) | 731 part = part.decode(sys.getfilesystemencoding()) |
| 867 cmd_parts.append(part) | 732 cmd_parts.append(part) |
| 868 cmd_desc = ' '.join(cmd_parts) | 733 cmd_desc = ' '.join(cmd_parts) |
| 869 if show_stdout: | 734 if show_stdout: |
| 870 stdout = None | 735 stdout = None |
| 871 else: | 736 else: |
| 872 stdout = subprocess.PIPE | 737 stdout = subprocess.PIPE |
| 873 logger.debug("Running command %s" % cmd_desc) | 738 logger.debug("Running command %s" % cmd_desc) |
| 874 if extra_env or remove_from_env: | 739 if extra_env or remove_from_env: |
| 875 env = os.environ.copy() | 740 env = os.environ.copy() |
| 876 if extra_env: | 741 if extra_env: |
| 877 env.update(extra_env) | 742 env.update(extra_env) |
| 878 if remove_from_env: | 743 if remove_from_env: |
| 879 for varname in remove_from_env: | 744 for varname in remove_from_env: |
| 880 env.pop(varname, None) | 745 env.pop(varname, None) |
| 881 else: | 746 else: |
| 882 env = None | 747 env = None |
| 883 try: | 748 try: |
| 884 proc = subprocess.Popen( | 749 proc = subprocess.Popen( |
| 885 cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout, | 750 cmd, stderr=subprocess.STDOUT, |
| 751 stdin=None if stdin is None else subprocess.PIPE, |
| 752 stdout=stdout, |
| 886 cwd=cwd, env=env) | 753 cwd=cwd, env=env) |
| 887 except Exception: | 754 except Exception: |
| 888 e = sys.exc_info()[1] | 755 e = sys.exc_info()[1] |
| 889 logger.fatal( | 756 logger.fatal( |
| 890 "Error %s while executing command %s" % (e, cmd_desc)) | 757 "Error %s while executing command %s" % (e, cmd_desc)) |
| 891 raise | 758 raise |
| 892 all_output = [] | 759 all_output = [] |
| 893 if stdout is not None: | 760 if stdout is not None: |
| 761 if stdin is not None: |
| 762 proc.stdin.write(stdin) |
| 763 proc.stdin.close() |
| 764 |
| 894 stdout = proc.stdout | 765 stdout = proc.stdout |
| 895 encoding = sys.getdefaultencoding() | 766 encoding = sys.getdefaultencoding() |
| 896 fs_encoding = sys.getfilesystemencoding() | 767 fs_encoding = sys.getfilesystemencoding() |
| 897 while 1: | 768 while 1: |
| 898 line = stdout.readline() | 769 line = stdout.readline() |
| 899 try: | 770 try: |
| 900 line = line.decode(encoding) | 771 line = line.decode(encoding) |
| 901 except UnicodeDecodeError: | 772 except UnicodeDecodeError: |
| 902 line = line.decode(fs_encoding) | 773 line = line.decode(fs_encoding) |
| 903 if not line: | 774 if not line: |
| 904 break | 775 break |
| 905 line = line.rstrip() | 776 line = line.rstrip() |
| 906 all_output.append(line) | 777 all_output.append(line) |
| 907 if filter_stdout: | 778 if filter_stdout: |
| 908 level = filter_stdout(line) | 779 level = filter_stdout(line) |
| 909 if isinstance(level, tuple): | 780 if isinstance(level, tuple): |
| 910 level, line = level | 781 level, line = level |
| 911 logger.log(level, line) | 782 logger.log(level, line) |
| 912 if not logger.stdout_level_matches(level): | 783 if not logger.stdout_level_matches(level): |
| 913 logger.show_progress() | 784 logger.show_progress() |
| 914 else: | 785 else: |
| 915 logger.info(line) | 786 logger.info(line) |
| 916 else: | 787 else: |
| 917 proc.communicate() | 788 proc.communicate(stdin) |
| 918 proc.wait() | 789 proc.wait() |
| 919 if proc.returncode: | 790 if proc.returncode: |
| 920 if raise_on_returncode: | 791 if raise_on_returncode: |
| 921 if all_output: | 792 if all_output: |
| 922 logger.notify('Complete output from command %s:' % cmd_desc) | 793 logger.notify('Complete output from command %s:' % cmd_desc) |
| 923 logger.notify('\n'.join(all_output) + '\n-----------------------
-----------------') | 794 logger.notify('\n'.join(all_output) + '\n-----------------------
-----------------') |
| 924 raise OSError( | 795 raise OSError( |
| 925 "Command %s failed with error code %s" | 796 "Command %s failed with error code %s" |
| 926 % (cmd_desc, proc.returncode)) | 797 % (cmd_desc, proc.returncode)) |
| 927 else: | 798 else: |
| (...skipping 25 matching lines...) Expand all Loading... |
| 953 files = glob.glob(os.path.join(dirname, project + '-*.whl')) | 824 files = glob.glob(os.path.join(dirname, project + '-*.whl')) |
| 954 if files: | 825 if files: |
| 955 wheels.append(os.path.abspath(files[0])) | 826 wheels.append(os.path.abspath(files[0])) |
| 956 break | 827 break |
| 957 else: | 828 else: |
| 958 # We're out of luck, so quit with a suitable error | 829 # We're out of luck, so quit with a suitable error |
| 959 logger.fatal('Cannot find a wheel for %s' % (project,)) | 830 logger.fatal('Cannot find a wheel for %s' % (project,)) |
| 960 | 831 |
| 961 return wheels | 832 return wheels |
| 962 | 833 |
| 963 def install_wheel(project_names, py_executable, search_dirs=None): | 834 def install_wheel(project_names, py_executable, search_dirs=None, |
| 835 download=False): |
| 964 if search_dirs is None: | 836 if search_dirs is None: |
| 965 search_dirs = file_search_dirs() | 837 search_dirs = file_search_dirs() |
| 966 | 838 |
| 967 wheels = find_wheels(['setuptools', 'pip'], search_dirs) | 839 wheels = find_wheels(['setuptools', 'pip'], search_dirs) |
| 968 pythonpath = os.pathsep.join(wheels) | 840 pythonpath = os.pathsep.join(wheels) |
| 969 findlinks = ' '.join(search_dirs) | |
| 970 | 841 |
| 971 cmd = [ | 842 # PIP_FIND_LINKS uses space as the path separator and thus cannot have paths |
| 972 py_executable, '-c', | 843 # with spaces in them. Convert any of those to local file:// URL form. |
| 973 'import sys, pip; sys.exit(pip.main(["install", "--ignore-installed"] +
sys.argv[1:]))', | 844 try: |
| 974 ] + project_names | 845 from urlparse import urljoin |
| 846 from urllib import pathname2url |
| 847 except ImportError: |
| 848 from urllib.parse import urljoin |
| 849 from urllib.request import pathname2url |
| 850 def space_path2url(p): |
| 851 if ' ' not in p: |
| 852 return p |
| 853 return urljoin('file:', pathname2url(os.path.abspath(p))) |
| 854 findlinks = ' '.join(space_path2url(d) for d in search_dirs) |
| 855 |
| 856 SCRIPT = textwrap.dedent(""" |
| 857 import sys |
| 858 import pkgutil |
| 859 import tempfile |
| 860 import os |
| 861 |
| 862 import pip |
| 863 |
| 864 cert_data = pkgutil.get_data("pip._vendor.requests", "cacert.pem") |
| 865 if cert_data is not None: |
| 866 cert_file = tempfile.NamedTemporaryFile(delete=False) |
| 867 cert_file.write(cert_data) |
| 868 cert_file.close() |
| 869 else: |
| 870 cert_file = None |
| 871 |
| 872 try: |
| 873 args = ["install", "--ignore-installed"] |
| 874 if cert_file is not None: |
| 875 args += ["--cert", cert_file.name] |
| 876 args += sys.argv[1:] |
| 877 |
| 878 sys.exit(pip.main(args)) |
| 879 finally: |
| 880 if cert_file is not None: |
| 881 os.remove(cert_file.name) |
| 882 """).encode("utf8") |
| 883 |
| 884 cmd = [py_executable, '-'] + project_names |
| 975 logger.start_progress('Installing %s...' % (', '.join(project_names))) | 885 logger.start_progress('Installing %s...' % (', '.join(project_names))) |
| 976 logger.indent += 2 | 886 logger.indent += 2 |
| 887 |
| 888 env = { |
| 889 "PYTHONPATH": pythonpath, |
| 890 "JYTHONPATH": pythonpath, # for Jython < 3.x |
| 891 "PIP_FIND_LINKS": findlinks, |
| 892 "PIP_USE_WHEEL": "1", |
| 893 "PIP_ONLY_BINARY": ":all:", |
| 894 "PIP_USER": "0", |
| 895 } |
| 896 |
| 897 if not download: |
| 898 env["PIP_NO_INDEX"] = "1" |
| 899 |
| 977 try: | 900 try: |
| 978 call_subprocess(cmd, show_stdout=False, | 901 call_subprocess(cmd, show_stdout=False, extra_env=env, stdin=SCRIPT) |
| 979 extra_env = { | |
| 980 'PYTHONPATH': pythonpath, | |
| 981 'PIP_FIND_LINKS': findlinks, | |
| 982 'PIP_USE_WHEEL': '1', | |
| 983 'PIP_PRE': '1', | |
| 984 'PIP_NO_INDEX': '1' | |
| 985 } | |
| 986 ) | |
| 987 finally: | 902 finally: |
| 988 logger.indent -= 2 | 903 logger.indent -= 2 |
| 989 logger.end_progress() | 904 logger.end_progress() |
| 990 | 905 |
| 906 |
| 991 def create_environment(home_dir, site_packages=False, clear=False, | 907 def create_environment(home_dir, site_packages=False, clear=False, |
| 992 unzip_setuptools=False, | 908 unzip_setuptools=False, |
| 993 prompt=None, search_dirs=None, never_download=False, | 909 prompt=None, search_dirs=None, download=False, |
| 994 no_setuptools=False, no_pip=False, symlink=True): | 910 no_setuptools=False, no_pip=False, no_wheel=False, |
| 911 symlink=True): |
| 995 """ | 912 """ |
| 996 Creates a new environment in ``home_dir``. | 913 Creates a new environment in ``home_dir``. |
| 997 | 914 |
| 998 If ``site_packages`` is true, then the global ``site-packages/`` | 915 If ``site_packages`` is true, then the global ``site-packages/`` |
| 999 directory will be on the path. | 916 directory will be on the path. |
| 1000 | 917 |
| 1001 If ``clear`` is true (default False) then the environment will | 918 If ``clear`` is true (default False) then the environment will |
| 1002 first be cleared. | 919 first be cleared. |
| 1003 """ | 920 """ |
| 1004 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | 921 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) |
| 1005 | 922 |
| 1006 py_executable = os.path.abspath(install_python( | 923 py_executable = os.path.abspath(install_python( |
| 1007 home_dir, lib_dir, inc_dir, bin_dir, | 924 home_dir, lib_dir, inc_dir, bin_dir, |
| 1008 site_packages=site_packages, clear=clear, symlink=symlink)) | 925 site_packages=site_packages, clear=clear, symlink=symlink)) |
| 1009 | 926 |
| 1010 install_distutils(home_dir) | 927 install_distutils(home_dir) |
| 1011 | 928 |
| 929 to_install = [] |
| 930 |
| 1012 if not no_setuptools: | 931 if not no_setuptools: |
| 1013 to_install = ['setuptools'] | 932 to_install.append('setuptools') |
| 1014 if not no_pip: | 933 |
| 1015 to_install.append('pip') | 934 if not no_pip: |
| 1016 install_wheel(to_install, py_executable, search_dirs) | 935 to_install.append('pip') |
| 936 |
| 937 if not no_wheel: |
| 938 to_install.append('wheel') |
| 939 |
| 940 if to_install: |
| 941 install_wheel( |
| 942 to_install, |
| 943 py_executable, |
| 944 search_dirs, |
| 945 download=download, |
| 946 ) |
| 1017 | 947 |
| 1018 install_activate(home_dir, bin_dir, prompt) | 948 install_activate(home_dir, bin_dir, prompt) |
| 1019 | 949 |
| 950 install_python_config(home_dir, bin_dir, prompt) |
| 951 |
| 1020 def is_executable_file(fpath): | 952 def is_executable_file(fpath): |
| 1021 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) | 953 return os.path.isfile(fpath) and os.access(fpath, os.X_OK) |
| 1022 | 954 |
| 1023 def path_locations(home_dir): | 955 def path_locations(home_dir): |
| 1024 """Return the path locations for the environment (where libraries are, | 956 """Return the path locations for the environment (where libraries are, |
| 1025 where scripts go, etc)""" | 957 where scripts go, etc)""" |
| 958 home_dir = os.path.abspath(home_dir) |
| 1026 # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its | 959 # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its |
| 1027 # prefix arg is broken: http://bugs.python.org/issue3386 | 960 # prefix arg is broken: http://bugs.python.org/issue3386 |
| 1028 if is_win: | 961 if is_win: |
| 1029 # Windows has lots of problems with executables with spaces in | 962 # Windows has lots of problems with executables with spaces in |
| 1030 # the name; this function will remove them (using the ~1 | 963 # the name; this function will remove them (using the ~1 |
| 1031 # format): | 964 # format): |
| 1032 mkdir(home_dir) | 965 mkdir(home_dir) |
| 1033 if ' ' in home_dir: | 966 if ' ' in home_dir: |
| 1034 import ctypes | 967 import ctypes |
| 1035 GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW | 968 GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW |
| (...skipping 16 matching lines...) Expand all Loading... |
| 1052 if is_jython: | 985 if is_jython: |
| 1053 lib_dir = join(home_dir, 'Lib') | 986 lib_dir = join(home_dir, 'Lib') |
| 1054 inc_dir = join(home_dir, 'Include') | 987 inc_dir = join(home_dir, 'Include') |
| 1055 bin_dir = join(home_dir, 'bin') | 988 bin_dir = join(home_dir, 'bin') |
| 1056 elif is_pypy: | 989 elif is_pypy: |
| 1057 lib_dir = home_dir | 990 lib_dir = home_dir |
| 1058 inc_dir = join(home_dir, 'include') | 991 inc_dir = join(home_dir, 'include') |
| 1059 bin_dir = join(home_dir, 'bin') | 992 bin_dir = join(home_dir, 'bin') |
| 1060 elif not is_win: | 993 elif not is_win: |
| 1061 lib_dir = join(home_dir, 'lib', py_version) | 994 lib_dir = join(home_dir, 'lib', py_version) |
| 1062 multiarch_exec = '/usr/bin/multiarch-platform' | 995 inc_dir = join(home_dir, 'include', py_version + abiflags) |
| 1063 if is_executable_file(multiarch_exec): | |
| 1064 # In Mageia (2) and Mandriva distros the include dir must be like: | |
| 1065 # virtualenv/include/multiarch-x86_64-linux/python2.7 | |
| 1066 # instead of being virtualenv/include/python2.7 | |
| 1067 p = subprocess.Popen(multiarch_exec, stdout=subprocess.PIPE, stderr=
subprocess.PIPE) | |
| 1068 stdout, stderr = p.communicate() | |
| 1069 # stdout.strip is needed to remove newline character | |
| 1070 inc_dir = join(home_dir, 'include', stdout.strip(), py_version + abi
flags) | |
| 1071 else: | |
| 1072 inc_dir = join(home_dir, 'include', py_version + abiflags) | |
| 1073 bin_dir = join(home_dir, 'bin') | 996 bin_dir = join(home_dir, 'bin') |
| 1074 return home_dir, lib_dir, inc_dir, bin_dir | 997 return home_dir, lib_dir, inc_dir, bin_dir |
| 1075 | 998 |
| 1076 | 999 |
| 1077 def change_prefix(filename, dst_prefix): | 1000 def change_prefix(filename, dst_prefix): |
| 1078 prefixes = [sys.prefix] | 1001 prefixes = [sys.prefix] |
| 1079 | 1002 |
| 1080 if is_darwin: | 1003 if is_darwin: |
| 1081 prefixes.extend(( | 1004 prefixes.extend(( |
| 1082 os.path.join("/Library/Python", sys.version[:3], "site-packages"), | 1005 os.path.join("/Library/Python", sys.version[:3], "site-packages"), |
| 1083 os.path.join(sys.prefix, "Extras", "lib", "python"), | 1006 os.path.join(sys.prefix, "Extras", "lib", "python"), |
| 1084 os.path.join("~", "Library", "Python", sys.version[:3], "site-packag
es"), | 1007 os.path.join("~", "Library", "Python", sys.version[:3], "site-packag
es"), |
| 1085 # Python 2.6 no-frameworks | 1008 # Python 2.6 no-frameworks |
| 1086 os.path.join("~", ".local", "lib","python", sys.version[:3], "site-p
ackages"), | 1009 os.path.join("~", ".local", "lib","python", sys.version[:3], "site-p
ackages"), |
| 1087 # System Python 2.7 on OSX Mountain Lion | 1010 # System Python 2.7 on OSX Mountain Lion |
| 1088 os.path.join("~", "Library", "Python", sys.version[:3], "lib", "pyth
on", "site-packages"))) | 1011 os.path.join("~", "Library", "Python", sys.version[:3], "lib", "pyth
on", "site-packages"))) |
| 1089 | 1012 |
| 1090 if hasattr(sys, 'real_prefix'): | 1013 if hasattr(sys, 'real_prefix'): |
| 1091 prefixes.append(sys.real_prefix) | 1014 prefixes.append(sys.real_prefix) |
| 1092 if hasattr(sys, 'base_prefix'): | 1015 if hasattr(sys, 'base_prefix'): |
| 1093 prefixes.append(sys.base_prefix) | 1016 prefixes.append(sys.base_prefix) |
| 1094 prefixes = list(map(os.path.expanduser, prefixes)) | 1017 prefixes = list(map(os.path.expanduser, prefixes)) |
| 1095 prefixes = list(map(os.path.abspath, prefixes)) | 1018 prefixes = list(map(os.path.abspath, prefixes)) |
| 1096 # Check longer prefixes first so we don't split in the middle of a filename | 1019 # Check longer prefixes first so we don't split in the middle of a filename |
| 1097 prefixes = sorted(prefixes, key=len, reverse=True) | 1020 prefixes = sorted(prefixes, key=len, reverse=True) |
| 1098 filename = os.path.abspath(filename) | 1021 filename = os.path.abspath(filename) |
| 1022 # On Windows, make sure drive letter is uppercase |
| 1023 if is_win and filename[0] in 'abcdefghijklmnopqrstuvwxyz': |
| 1024 filename = filename[0].upper() + filename[1:] |
| 1025 for i, prefix in enumerate(prefixes): |
| 1026 if is_win and prefix[0] in 'abcdefghijklmnopqrstuvwxyz': |
| 1027 prefixes[i] = prefix[0].upper() + prefix[1:] |
| 1099 for src_prefix in prefixes: | 1028 for src_prefix in prefixes: |
| 1100 if filename.startswith(src_prefix): | 1029 if filename.startswith(src_prefix): |
| 1101 _, relpath = filename.split(src_prefix, 1) | 1030 _, relpath = filename.split(src_prefix, 1) |
| 1102 if src_prefix != os.sep: # sys.prefix == "/" | 1031 if src_prefix != os.sep: # sys.prefix == "/" |
| 1103 assert relpath[0] == os.sep | 1032 assert relpath[0] == os.sep |
| 1104 relpath = relpath[1:] | 1033 relpath = relpath[1:] |
| 1105 return join(dst_prefix, relpath) | 1034 return join(dst_prefix, relpath) |
| 1106 assert False, "Filename %s does not start with any of these prefixes: %s" %
\ | 1035 assert False, "Filename %s does not start with any of these prefixes: %s" %
\ |
| 1107 (filename, prefixes) | 1036 (filename, prefixes) |
| 1108 | 1037 |
| 1109 def copy_required_modules(dst_prefix, symlink): | 1038 def copy_required_modules(dst_prefix, symlink): |
| 1110 import imp | 1039 import imp |
| 1040 |
| 1111 for modname in REQUIRED_MODULES: | 1041 for modname in REQUIRED_MODULES: |
| 1112 if modname in sys.builtin_module_names: | 1042 if modname in sys.builtin_module_names: |
| 1113 logger.info("Ignoring built-in bootstrap module: %s" % modname) | 1043 logger.info("Ignoring built-in bootstrap module: %s" % modname) |
| 1114 continue | 1044 continue |
| 1115 try: | 1045 try: |
| 1116 f, filename, _ = imp.find_module(modname) | 1046 f, filename, _ = imp.find_module(modname) |
| 1117 except ImportError: | 1047 except ImportError: |
| 1118 logger.info("Cannot import bootstrap module: %s" % modname) | 1048 logger.info("Cannot import bootstrap module: %s" % modname) |
| 1119 else: | 1049 else: |
| 1120 if f is not None: | 1050 if f is not None: |
| 1121 f.close() | 1051 f.close() |
| 1122 # special-case custom readline.so on OS X, but not for pypy: | 1052 # special-case custom readline.so on OS X, but not for pypy: |
| 1123 if modname == 'readline' and sys.platform == 'darwin' and not ( | 1053 if modname == 'readline' and sys.platform == 'darwin' and not ( |
| 1124 is_pypy or filename.endswith(join('lib-dynload', 'readline.s
o'))): | 1054 is_pypy or filename.endswith(join('lib-dynload', 'readline.s
o'))): |
| 1125 dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[
:3], 'readline.so') | 1055 dst_filename = join(dst_prefix, 'lib', 'python%s' % sys.version[
:3], 'readline.so') |
| 1126 elif modname == 'readline' and sys.platform == 'win32': | 1056 elif modname == 'readline' and sys.platform == 'win32': |
| 1127 # special-case for Windows, where readline is not a | 1057 # special-case for Windows, where readline is not a |
| 1128 # standard module, though it may have been installed in | 1058 # standard module, though it may have been installed in |
| 1129 # site-packages by a third-party package | 1059 # site-packages by a third-party package |
| 1130 pass | 1060 pass |
| 1131 else: | 1061 else: |
| 1132 dst_filename = change_prefix(filename, dst_prefix) | 1062 dst_filename = change_prefix(filename, dst_prefix) |
| 1133 copyfile(filename, dst_filename, symlink) | 1063 copyfile(filename, dst_filename, symlink) |
| 1134 if filename.endswith('.pyc'): | 1064 if filename.endswith('.pyc'): |
| 1135 pyfile = filename[:-1] | 1065 pyfile = filename[:-1] |
| 1136 if os.path.exists(pyfile): | 1066 if os.path.exists(pyfile): |
| 1137 copyfile(pyfile, dst_filename[:-1], symlink) | 1067 copyfile(pyfile, dst_filename[:-1], symlink) |
| 1138 | 1068 |
| 1069 def copy_tcltk(src, dest, symlink): |
| 1070 """ copy tcl/tk libraries on Windows (issue #93) """ |
| 1071 for libversion in '8.5', '8.6': |
| 1072 for libname in 'tcl', 'tk': |
| 1073 srcdir = join(src, 'tcl', libname + libversion) |
| 1074 destdir = join(dest, 'tcl', libname + libversion) |
| 1075 # Only copy the dirs from the above combinations that exist |
| 1076 if os.path.exists(srcdir) and not os.path.exists(destdir): |
| 1077 copyfileordir(srcdir, destdir, symlink) |
| 1078 |
| 1139 | 1079 |
| 1140 def subst_path(prefix_path, prefix, home_dir): | 1080 def subst_path(prefix_path, prefix, home_dir): |
| 1141 prefix_path = os.path.normpath(prefix_path) | 1081 prefix_path = os.path.normpath(prefix_path) |
| 1142 prefix = os.path.normpath(prefix) | 1082 prefix = os.path.normpath(prefix) |
| 1143 home_dir = os.path.normpath(home_dir) | 1083 home_dir = os.path.normpath(home_dir) |
| 1144 if not prefix_path.startswith(prefix): | 1084 if not prefix_path.startswith(prefix): |
| 1145 logger.warn('Path not in prefix %r %r', prefix_path, prefix) | 1085 logger.warn('Path not in prefix %r %r', prefix_path, prefix) |
| 1146 return | 1086 return |
| 1147 return prefix_path.replace(prefix, home_dir, 1) | 1087 return prefix_path.replace(prefix, home_dir, 1) |
| 1148 | 1088 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1185 if not os.path.isdir(stdlib_dir): | 1125 if not os.path.isdir(stdlib_dir): |
| 1186 continue | 1126 continue |
| 1187 for fn in os.listdir(stdlib_dir): | 1127 for fn in os.listdir(stdlib_dir): |
| 1188 bn = os.path.splitext(fn)[0] | 1128 bn = os.path.splitext(fn)[0] |
| 1189 if fn != 'site-packages' and bn in REQUIRED_FILES: | 1129 if fn != 'site-packages' and bn in REQUIRED_FILES: |
| 1190 copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) | 1130 copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink) |
| 1191 # ...and modules | 1131 # ...and modules |
| 1192 copy_required_modules(home_dir, symlink) | 1132 copy_required_modules(home_dir, symlink) |
| 1193 finally: | 1133 finally: |
| 1194 logger.indent -= 2 | 1134 logger.indent -= 2 |
| 1135 # ...copy tcl/tk |
| 1136 if is_win: |
| 1137 copy_tcltk(prefix, home_dir, symlink) |
| 1195 mkdir(join(lib_dir, 'site-packages')) | 1138 mkdir(join(lib_dir, 'site-packages')) |
| 1196 import site | 1139 import site |
| 1197 site_filename = site.__file__ | 1140 site_filename = site.__file__ |
| 1198 if site_filename.endswith('.pyc'): | 1141 if site_filename.endswith('.pyc') or site_filename.endswith('.pyo'): |
| 1199 site_filename = site_filename[:-1] | 1142 site_filename = site_filename[:-1] |
| 1200 elif site_filename.endswith('$py.class'): | 1143 elif site_filename.endswith('$py.class'): |
| 1201 site_filename = site_filename.replace('$py.class', '.py') | 1144 site_filename = site_filename.replace('$py.class', '.py') |
| 1202 site_filename_dst = change_prefix(site_filename, home_dir) | 1145 site_filename_dst = change_prefix(site_filename, home_dir) |
| 1203 site_dir = os.path.dirname(site_filename_dst) | 1146 site_dir = os.path.dirname(site_filename_dst) |
| 1204 writefile(site_filename_dst, SITE_PY) | 1147 writefile(site_filename_dst, SITE_PY) |
| 1205 writefile(join(site_dir, 'orig-prefix.txt'), prefix) | 1148 writefile(join(site_dir, 'orig-prefix.txt'), prefix) |
| 1206 site_packages_filename = join(site_dir, 'no-global-site-packages.txt') | 1149 site_packages_filename = join(site_dir, 'no-global-site-packages.txt') |
| 1207 if not site_packages: | 1150 if not site_packages: |
| 1208 writefile(site_packages_filename, '') | 1151 writefile(site_packages_filename, '') |
| (...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1421 | 1364 |
| 1422 for pth in required_symlinks: | 1365 for pth in required_symlinks: |
| 1423 full_pth = join(bin_dir, pth) | 1366 full_pth = join(bin_dir, pth) |
| 1424 if os.path.exists(full_pth): | 1367 if os.path.exists(full_pth): |
| 1425 os.unlink(full_pth) | 1368 os.unlink(full_pth) |
| 1426 if symlink: | 1369 if symlink: |
| 1427 os.symlink(py_executable_base, full_pth) | 1370 os.symlink(py_executable_base, full_pth) |
| 1428 else: | 1371 else: |
| 1429 copyfile(py_executable, full_pth, symlink) | 1372 copyfile(py_executable, full_pth, symlink) |
| 1430 | 1373 |
| 1431 if is_win and ' ' in py_executable: | |
| 1432 # There's a bug with subprocess on Windows when using a first | |
| 1433 # argument that has a space in it. Instead we have to quote | |
| 1434 # the value: | |
| 1435 py_executable = '"%s"' % py_executable | |
| 1436 # NOTE: keep this check as one line, cmd.exe doesn't cope with line breaks | |
| 1437 cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' | 1374 cmd = [py_executable, '-c', 'import sys;out=sys.stdout;' |
| 1438 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] | 1375 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))'] |
| 1439 logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) | 1376 logger.info('Testing executable with %s %s "%s"' % tuple(cmd)) |
| 1440 try: | 1377 try: |
| 1441 proc = subprocess.Popen(cmd, | 1378 proc = subprocess.Popen(cmd, |
| 1442 stdout=subprocess.PIPE) | 1379 stdout=subprocess.PIPE) |
| 1443 proc_stdout, proc_stderr = proc.communicate() | 1380 proc_stdout, proc_stderr = proc.communicate() |
| 1444 except OSError: | 1381 except OSError: |
| 1445 e = sys.exc_info()[1] | 1382 e = sys.exc_info()[1] |
| 1446 if e.errno == errno.EACCES: | 1383 if e.errno == errno.EACCES: |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1483 | 1420 |
| 1484 if site_packages: | 1421 if site_packages: |
| 1485 if os.path.exists(site_packages_filename): | 1422 if os.path.exists(site_packages_filename): |
| 1486 logger.info('Deleting %s' % site_packages_filename) | 1423 logger.info('Deleting %s' % site_packages_filename) |
| 1487 os.unlink(site_packages_filename) | 1424 os.unlink(site_packages_filename) |
| 1488 | 1425 |
| 1489 return py_executable | 1426 return py_executable |
| 1490 | 1427 |
| 1491 | 1428 |
| 1492 def install_activate(home_dir, bin_dir, prompt=None): | 1429 def install_activate(home_dir, bin_dir, prompt=None): |
| 1493 home_dir = os.path.abspath(home_dir) | |
| 1494 if is_win or is_jython and os._name == 'nt': | 1430 if is_win or is_jython and os._name == 'nt': |
| 1495 files = { | 1431 files = { |
| 1496 'activate.bat': ACTIVATE_BAT, | 1432 'activate.bat': ACTIVATE_BAT, |
| 1497 'deactivate.bat': DEACTIVATE_BAT, | 1433 'deactivate.bat': DEACTIVATE_BAT, |
| 1498 'activate.ps1': ACTIVATE_PS, | 1434 'activate.ps1': ACTIVATE_PS, |
| 1499 } | 1435 } |
| 1500 | 1436 |
| 1501 # MSYS needs paths of the form /c/path/to/file | 1437 # MSYS needs paths of the form /c/path/to/file |
| 1502 drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) | 1438 drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/')) |
| 1503 home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) | 1439 home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail) |
| 1504 | 1440 |
| 1505 # Run-time conditional enables (basic) Cygwin compatibility | 1441 # Run-time conditional enables (basic) Cygwin compatibility |
| 1506 home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'
; else echo '%s'; fi;)""" % | 1442 home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s'
; else echo '%s'; fi;)""" % |
| 1507 (home_dir, home_dir_msys)) | 1443 (home_dir, home_dir_msys)) |
| 1508 files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) | 1444 files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh) |
| 1509 | 1445 |
| 1510 else: | 1446 else: |
| 1511 files = {'activate': ACTIVATE_SH} | 1447 files = {'activate': ACTIVATE_SH} |
| 1512 | 1448 |
| 1513 # suppling activate.fish in addition to, not instead of, the | 1449 # suppling activate.fish in addition to, not instead of, the |
| 1514 # bash script support. | 1450 # bash script support. |
| 1515 files['activate.fish'] = ACTIVATE_FISH | 1451 files['activate.fish'] = ACTIVATE_FISH |
| 1516 | 1452 |
| 1517 # same for csh/tcsh support... | 1453 # same for csh/tcsh support... |
| 1518 files['activate.csh'] = ACTIVATE_CSH | 1454 files['activate.csh'] = ACTIVATE_CSH |
| 1519 | 1455 |
| 1520 files['activate_this.py'] = ACTIVATE_THIS | 1456 files['activate_this.py'] = ACTIVATE_THIS |
| 1457 |
| 1458 install_files(home_dir, bin_dir, prompt, files) |
| 1459 |
| 1460 def install_files(home_dir, bin_dir, prompt, files): |
| 1521 if hasattr(home_dir, 'decode'): | 1461 if hasattr(home_dir, 'decode'): |
| 1522 home_dir = home_dir.decode(sys.getfilesystemencoding()) | 1462 home_dir = home_dir.decode(sys.getfilesystemencoding()) |
| 1523 vname = os.path.basename(home_dir) | 1463 vname = os.path.basename(home_dir) |
| 1524 for name, content in files.items(): | 1464 for name, content in files.items(): |
| 1525 content = content.replace('__VIRTUAL_PROMPT__', prompt or '') | 1465 content = content.replace('__VIRTUAL_PROMPT__', prompt or '') |
| 1526 content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vn
ame) | 1466 content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vn
ame) |
| 1527 content = content.replace('__VIRTUAL_ENV__', home_dir) | 1467 content = content.replace('__VIRTUAL_ENV__', home_dir) |
| 1528 content = content.replace('__VIRTUAL_NAME__', vname) | 1468 content = content.replace('__VIRTUAL_NAME__', vname) |
| 1529 content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) | 1469 content = content.replace('__BIN_NAME__', os.path.basename(bin_dir)) |
| 1530 writefile(os.path.join(bin_dir, name), content) | 1470 writefile(os.path.join(bin_dir, name), content) |
| 1531 | 1471 |
| 1472 def install_python_config(home_dir, bin_dir, prompt=None): |
| 1473 if sys.platform == 'win32' or is_jython and os._name == 'nt': |
| 1474 files = {} |
| 1475 else: |
| 1476 files = {'python-config': PYTHON_CONFIG} |
| 1477 install_files(home_dir, bin_dir, prompt, files) |
| 1478 for name, content in files.items(): |
| 1479 make_exe(os.path.join(bin_dir, name)) |
| 1480 |
| 1532 def install_distutils(home_dir): | 1481 def install_distutils(home_dir): |
| 1533 distutils_path = change_prefix(distutils.__path__[0], home_dir) | 1482 distutils_path = change_prefix(distutils.__path__[0], home_dir) |
| 1534 mkdir(distutils_path) | 1483 mkdir(distutils_path) |
| 1535 ## FIXME: maybe this prefix setting should only be put in place if | 1484 ## FIXME: maybe this prefix setting should only be put in place if |
| 1536 ## there's a local distutils.cfg with a prefix setting? | 1485 ## there's a local distutils.cfg with a prefix setting? |
| 1537 home_dir = os.path.abspath(home_dir) | 1486 home_dir = os.path.abspath(home_dir) |
| 1538 ## FIXME: this is breaking things, removing for now: | 1487 ## FIXME: this is breaking things, removing for now: |
| 1539 #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir | 1488 #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir |
| 1540 writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) | 1489 writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT) |
| 1541 writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, over
write=False) | 1490 writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, over
write=False) |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1559 continue | 1508 continue |
| 1560 copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)
), \ | 1509 copyfile(os.path.abspath(os.path.join(home_dir, subdir_name)
), \ |
| 1561 os.path.join(local_p
ath, subdir_name), symlink) | 1510 os.path.join(local_p
ath, subdir_name), symlink) |
| 1562 | 1511 |
| 1563 def fix_lib64(lib_dir, symlink=True): | 1512 def fix_lib64(lib_dir, symlink=True): |
| 1564 """ | 1513 """ |
| 1565 Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y | 1514 Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y |
| 1566 instead of lib/pythonX.Y. If this is such a platform we'll just create a | 1515 instead of lib/pythonX.Y. If this is such a platform we'll just create a |
| 1567 symlink so lib64 points to lib | 1516 symlink so lib64 points to lib |
| 1568 """ | 1517 """ |
| 1569 if [p for p in distutils.sysconfig.get_config_vars().values() | 1518 # PyPy's library path scheme is not affected by this. |
| 1570 if isinstance(p, basestring) and 'lib64' in p]: | 1519 # Return early or we will die on the following assert. |
| 1571 # PyPy's library path scheme is not affected by this. | 1520 if is_pypy: |
| 1572 # Return early or we will die on the following assert. | 1521 logger.debug('PyPy detected, skipping lib64 symlinking') |
| 1573 if is_pypy: | 1522 return |
| 1574 logger.debug('PyPy detected, skipping lib64 symlinking') | 1523 # Check we have a lib64 library path |
| 1575 return | 1524 if not [p for p in distutils.sysconfig.get_config_vars().values() |
| 1525 if isinstance(p, basestring) and 'lib64' in p]: |
| 1526 return |
| 1576 | 1527 |
| 1577 logger.debug('This system uses lib64; symlinking lib64 to lib') | 1528 logger.debug('This system uses lib64; symlinking lib64 to lib') |
| 1578 | 1529 |
| 1579 assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( | 1530 assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], ( |
| 1580 "Unexpected python lib dir: %r" % lib_dir) | 1531 "Unexpected python lib dir: %r" % lib_dir) |
| 1581 lib_parent = os.path.dirname(lib_dir) | 1532 lib_parent = os.path.dirname(lib_dir) |
| 1582 top_level = os.path.dirname(lib_parent) | 1533 top_level = os.path.dirname(lib_parent) |
| 1583 lib_dir = os.path.join(top_level, 'lib') | 1534 lib_dir = os.path.join(top_level, 'lib') |
| 1584 lib64_link = os.path.join(top_level, 'lib64') | 1535 lib64_link = os.path.join(top_level, 'lib64') |
| 1585 assert os.path.basename(lib_parent) == 'lib', ( | 1536 assert os.path.basename(lib_parent) == 'lib', ( |
| 1586 "Unexpected parent dir: %r" % lib_parent) | 1537 "Unexpected parent dir: %r" % lib_parent) |
| 1587 if os.path.lexists(lib64_link): | 1538 if os.path.lexists(lib64_link): |
| 1588 return | 1539 return |
| 1589 if symlink: | 1540 if symlink: |
| 1590 os.symlink('lib', lib64_link) | 1541 os.symlink('lib', lib64_link) |
| 1591 else: | 1542 else: |
| 1592 copyfile('lib', lib64_link) | 1543 copyfile('lib', lib64_link) |
| 1593 | 1544 |
| 1594 def resolve_interpreter(exe): | 1545 def resolve_interpreter(exe): |
| 1595 """ | 1546 """ |
| 1596 If the executable given isn't an absolute path, search $PATH for the interpr
eter | 1547 If the executable given isn't an absolute path, search $PATH for the interpr
eter |
| 1597 """ | 1548 """ |
| 1598 # If the "executable" is a version number, get the installed executable for | 1549 # If the "executable" is a version number, get the installed executable for |
| 1599 # that version | 1550 # that version |
| 1551 orig_exe = exe |
| 1600 python_versions = get_installed_pythons() | 1552 python_versions = get_installed_pythons() |
| 1601 if exe in python_versions: | 1553 if exe in python_versions: |
| 1602 exe = python_versions[exe] | 1554 exe = python_versions[exe] |
| 1603 | 1555 |
| 1604 if os.path.abspath(exe) != exe: | 1556 if os.path.abspath(exe) != exe: |
| 1605 paths = os.environ.get('PATH', '').split(os.pathsep) | 1557 paths = os.environ.get('PATH', '').split(os.pathsep) |
| 1606 for path in paths: | 1558 for path in paths: |
| 1607 if os.path.exists(os.path.join(path, exe)): | 1559 if os.path.exists(join(path, exe)): |
| 1608 exe = os.path.join(path, exe) | 1560 exe = join(path, exe) |
| 1609 break | 1561 break |
| 1610 if not os.path.exists(exe): | 1562 if not os.path.exists(exe): |
| 1611 logger.fatal('The executable %s (from --python=%s) does not exist' % (ex
e, exe)) | 1563 logger.fatal('The path %s (from --python=%s) does not exist' % (exe, ori
g_exe)) |
| 1612 raise SystemExit(3) | 1564 raise SystemExit(3) |
| 1613 if not is_executable(exe): | 1565 if not is_executable(exe): |
| 1614 logger.fatal('The executable %s (from --python=%s) is not executable' %
(exe, exe)) | 1566 logger.fatal('The path %s (from --python=%s) is not an executable file'
% (exe, orig_exe)) |
| 1615 raise SystemExit(3) | 1567 raise SystemExit(3) |
| 1616 return exe | 1568 return exe |
| 1617 | 1569 |
| 1618 def is_executable(exe): | 1570 def is_executable(exe): |
| 1619 """Checks a file is executable""" | 1571 """Checks a file is executable""" |
| 1620 return os.access(exe, os.X_OK) | 1572 return os.path.isfile(exe) and os.access(exe, os.X_OK) |
| 1621 | 1573 |
| 1622 ############################################################ | 1574 ############################################################ |
| 1623 ## Relocating the environment: | 1575 ## Relocating the environment: |
| 1624 | 1576 |
| 1625 def make_environment_relocatable(home_dir): | 1577 def make_environment_relocatable(home_dir): |
| 1626 """ | 1578 """ |
| 1627 Makes the already-existing environment use relative paths, and takes out | 1579 Makes the already-existing environment use relative paths, and takes out |
| 1628 the #!-based environment selection in scripts. | 1580 the #!-based environment selection in scripts. |
| 1629 """ | 1581 """ |
| 1630 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) | 1582 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir) |
| (...skipping 22 matching lines...) Expand all Loading... |
| 1653 shebang = '#!%s' % os.path.normcase(os.path.join( | 1605 shebang = '#!%s' % os.path.normcase(os.path.join( |
| 1654 os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) | 1606 os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2])) |
| 1655 # This is what we'll put: | 1607 # This is what we'll put: |
| 1656 new_shebang = '#!%s python%s%s' % new_shebang_args | 1608 new_shebang = '#!%s python%s%s' % new_shebang_args |
| 1657 | 1609 |
| 1658 for filename in os.listdir(bin_dir): | 1610 for filename in os.listdir(bin_dir): |
| 1659 filename = os.path.join(bin_dir, filename) | 1611 filename = os.path.join(bin_dir, filename) |
| 1660 if not os.path.isfile(filename): | 1612 if not os.path.isfile(filename): |
| 1661 # ignore subdirs, e.g. .svn ones. | 1613 # ignore subdirs, e.g. .svn ones. |
| 1662 continue | 1614 continue |
| 1663 f = open(filename, 'rb') | 1615 lines = None |
| 1664 try: | 1616 with open(filename, 'rb') as f: |
| 1665 try: | 1617 try: |
| 1666 lines = f.read().decode('utf-8').splitlines() | 1618 lines = f.read().decode('utf-8').splitlines() |
| 1667 except UnicodeDecodeError: | 1619 except UnicodeDecodeError: |
| 1668 # This is probably a binary program instead | 1620 # This is probably a binary program instead |
| 1669 # of a script, so just ignore it. | 1621 # of a script, so just ignore it. |
| 1670 continue | 1622 continue |
| 1671 finally: | |
| 1672 f.close() | |
| 1673 if not lines: | 1623 if not lines: |
| 1674 logger.warn('Script %s is an empty file' % filename) | 1624 logger.warn('Script %s is an empty file' % filename) |
| 1675 continue | 1625 continue |
| 1676 | 1626 |
| 1677 old_shebang = lines[0].strip() | 1627 old_shebang = lines[0].strip() |
| 1678 old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) | 1628 old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:]) |
| 1679 | 1629 |
| 1680 if not old_shebang.startswith(shebang): | 1630 if not old_shebang.startswith(shebang): |
| 1681 if os.path.basename(filename) in OK_ABS_SCRIPTS: | 1631 if os.path.basename(filename) in OK_ABS_SCRIPTS: |
| 1682 logger.debug('Cannot make script %s relative' % filename) | 1632 logger.debug('Cannot make script %s relative' % filename) |
| 1683 elif lines[0].strip() == new_shebang: | 1633 elif lines[0].strip() == new_shebang: |
| 1684 logger.info('Script %s has already been made relative' % filenam
e) | 1634 logger.info('Script %s has already been made relative' % filenam
e) |
| 1685 else: | 1635 else: |
| 1686 logger.warn('Script %s cannot be made relative (it\'s not a norm
al script that starts with %s)' | 1636 logger.warn('Script %s cannot be made relative (it\'s not a norm
al script that starts with %s)' |
| 1687 % (filename, shebang)) | 1637 % (filename, shebang)) |
| 1688 continue | 1638 continue |
| 1689 logger.notify('Making script %s relative' % filename) | 1639 logger.notify('Making script %s relative' % filename) |
| 1690 script = relative_script([new_shebang] + lines[1:]) | 1640 script = relative_script([new_shebang] + lines[1:]) |
| 1691 f = open(filename, 'wb') | 1641 with open(filename, 'wb') as f: |
| 1692 f.write('\n'.join(script).encode('utf-8')) | 1642 f.write('\n'.join(script).encode('utf-8')) |
| 1693 f.close() | 1643 |
| 1694 | 1644 |
| 1695 def relative_script(lines): | 1645 def relative_script(lines): |
| 1696 "Return a script that'll work in a relocatable environment." | 1646 "Return a script that'll work in a relocatable environment." |
| 1697 activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.re
alpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(),
activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this" | 1647 activate = "import os; activate_this=os.path.join(os.path.dirname(os.path.re
alpath(__file__)), 'activate_this.py'); exec(compile(open(activate_this).read(),
activate_this, 'exec'), dict(__file__=activate_this)); del os, activate_this" |
| 1698 # Find the last future statement in the script. If we insert the activation | 1648 # Find the last future statement in the script. If we insert the activation |
| 1699 # line before a future statement, Python will raise a SyntaxError. | 1649 # line before a future statement, Python will raise a SyntaxError. |
| 1700 activate_at = None | 1650 activate_at = None |
| 1701 for idx, line in reversed(list(enumerate(lines))): | 1651 for idx, line in reversed(list(enumerate(lines))): |
| 1702 if line.split()[:3] == ['from', '__future__', 'import']: | 1652 if line.split()[:3] == ['from', '__future__', 'import']: |
| 1703 activate_at = idx + 1 | 1653 activate_at = idx + 1 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1730 fixup_pth_file(filename) | 1680 fixup_pth_file(filename) |
| 1731 if filename.endswith('.egg-link'): | 1681 if filename.endswith('.egg-link'): |
| 1732 if not os.access(filename, os.W_OK): | 1682 if not os.access(filename, os.W_OK): |
| 1733 logger.warn('Cannot write .egg-link file %s, skipping' % fil
ename) | 1683 logger.warn('Cannot write .egg-link file %s, skipping' % fil
ename) |
| 1734 else: | 1684 else: |
| 1735 fixup_egg_link(filename) | 1685 fixup_egg_link(filename) |
| 1736 | 1686 |
| 1737 def fixup_pth_file(filename): | 1687 def fixup_pth_file(filename): |
| 1738 lines = [] | 1688 lines = [] |
| 1739 prev_lines = [] | 1689 prev_lines = [] |
| 1740 f = open(filename) | 1690 with open(filename) as f: |
| 1741 prev_lines = f.readlines() | 1691 prev_lines = f.readlines() |
| 1742 f.close() | |
| 1743 for line in prev_lines: | 1692 for line in prev_lines: |
| 1744 line = line.strip() | 1693 line = line.strip() |
| 1745 if (not line or line.startswith('#') or line.startswith('import ') | 1694 if (not line or line.startswith('#') or line.startswith('import ') |
| 1746 or os.path.abspath(line) != line): | 1695 or os.path.abspath(line) != line): |
| 1747 lines.append(line) | 1696 lines.append(line) |
| 1748 else: | 1697 else: |
| 1749 new_value = make_relative_path(filename, line) | 1698 new_value = make_relative_path(filename, line) |
| 1750 if line != new_value: | 1699 if line != new_value: |
| 1751 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_valu
e, filename)) | 1700 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_valu
e, filename)) |
| 1752 lines.append(new_value) | 1701 lines.append(new_value) |
| 1753 if lines == prev_lines: | 1702 if lines == prev_lines: |
| 1754 logger.info('No changes to .pth file %s' % filename) | 1703 logger.info('No changes to .pth file %s' % filename) |
| 1755 return | 1704 return |
| 1756 logger.notify('Making paths in .pth file %s relative' % filename) | 1705 logger.notify('Making paths in .pth file %s relative' % filename) |
| 1757 f = open(filename, 'w') | 1706 with open(filename, 'w') as f: |
| 1758 f.write('\n'.join(lines) + '\n') | 1707 f.write('\n'.join(lines) + '\n') |
| 1759 f.close() | |
| 1760 | 1708 |
| 1761 def fixup_egg_link(filename): | 1709 def fixup_egg_link(filename): |
| 1762 f = open(filename) | 1710 with open(filename) as f: |
| 1763 link = f.readline().strip() | 1711 link = f.readline().strip() |
| 1764 f.close() | |
| 1765 if os.path.abspath(link) != link: | 1712 if os.path.abspath(link) != link: |
| 1766 logger.debug('Link in %s already relative' % filename) | 1713 logger.debug('Link in %s already relative' % filename) |
| 1767 return | 1714 return |
| 1768 new_link = make_relative_path(filename, link) | 1715 new_link = make_relative_path(filename, link) |
| 1769 logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) | 1716 logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link)) |
| 1770 f = open(filename, 'w') | 1717 with open(filename, 'w') as f: |
| 1771 f.write(new_link) | 1718 f.write(new_link) |
| 1772 f.close() | |
| 1773 | 1719 |
| 1774 def make_relative_path(source, dest, dest_is_directory=True): | 1720 def make_relative_path(source, dest, dest_is_directory=True): |
| 1775 """ | 1721 """ |
| 1776 Make a filename relative, where the filename is dest, and it is | 1722 Make a filename relative, where the filename is dest, and it is |
| 1777 being referred to from the filename source. | 1723 being referred to from the filename source. |
| 1778 | 1724 |
| 1779 >>> make_relative_path('/usr/share/something/a-file.pth', | 1725 >>> make_relative_path('/usr/share/something/a-file.pth', |
| 1780 ... '/usr/share/another-place/src/Directory') | 1726 ... '/usr/share/another-place/src/Directory') |
| 1781 '../another-place/src/Directory' | 1727 '../another-place/src/Directory' |
| 1782 >>> make_relative_path('/usr/share/something/a-file.pth', | 1728 >>> make_relative_path('/usr/share/something/a-file.pth', |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1845 script from that package. | 1791 script from that package. |
| 1846 | 1792 |
| 1847 If you provide something like ``python_version='2.5'`` then the | 1793 If you provide something like ``python_version='2.5'`` then the |
| 1848 script will start with ``#!/usr/bin/env python2.5`` instead of | 1794 script will start with ``#!/usr/bin/env python2.5`` instead of |
| 1849 ``#!/usr/bin/env python``. You can use this when the script must | 1795 ``#!/usr/bin/env python``. You can use this when the script must |
| 1850 be run with a particular Python version. | 1796 be run with a particular Python version. |
| 1851 """ | 1797 """ |
| 1852 filename = __file__ | 1798 filename = __file__ |
| 1853 if filename.endswith('.pyc'): | 1799 if filename.endswith('.pyc'): |
| 1854 filename = filename[:-1] | 1800 filename = filename[:-1] |
| 1855 f = codecs.open(filename, 'r', encoding='utf-8') | 1801 with codecs.open(filename, 'r', encoding='utf-8') as f: |
| 1856 content = f.read() | 1802 content = f.read() |
| 1857 f.close() | |
| 1858 py_exe = 'python%s' % python_version | 1803 py_exe = 'python%s' % python_version |
| 1859 content = (('#!/usr/bin/env %s\n' % py_exe) | 1804 content = (('#!/usr/bin/env %s\n' % py_exe) |
| 1860 + '## WARNING: This file is generated\n' | 1805 + '## WARNING: This file is generated\n' |
| 1861 + content) | 1806 + content) |
| 1862 return content.replace('##EXT' 'END##', extra_text) | 1807 return content.replace('##EXT' 'END##', extra_text) |
| 1863 | 1808 |
| 1864 ##EXTEND## | 1809 ##EXTEND## |
| 1865 | 1810 |
| 1866 def convert(s): | 1811 def convert(s): |
| 1867 b = base64.b64decode(s.encode('ascii')) | 1812 b = base64.b64decode(s.encode('ascii')) |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2007 Q+6hHuihalPc51hgzNIcqicV3xFkPs4UdMGX53zgGbre9sPX28uXR/ZwAfkdXzuKhLLJRo5hv3Sy | 1952 Q+6hHuihalPc51hgzNIcqicV3xFkPs4UdMGX53zgGbre9sPX28uXR/ZwAfkdXzuKhLLJRo5hv3Sy |
| 2008 MXdeKul0J2Ypp5Suh3s1JySsW1w5UNknGNrbdEpSBvY/Js+BIY289/0hM9PDu3p/1MbUst4RTEmM | 1953 MXdeKul0J2Ypp5Suh3s1JySsW1w5UNknGNrbdEpSBvY/Js+BIY289/0hM9PDu3p/1MbUst4RTEmM |
| 2009 n6kJTcsp4tG42yeT7nQbtdUFwgVJjwDSUYEAC8F0dKOTILrlLO/xC70bnNd0Ha97whQ6UkHJYj5H | 1954 n6kJTcsp4tG42yeT7nQbtdUFwgVJjwDSUYEAC8F0dKOTILrlLO/xC70bnNd0Ha97whQ6UkHJYj5H |
| 2010 cA/j+zX4tbtTIfGjujOKpj83aHOgXnIQbvYduNXEC4UMm4T21Bs+GHABuCa7v//LR/TvpjHa7oe7 | 1955 cA/j+zX4tbtTIfGjujOKpj83aHOgXnIQbvYduNXEC4UMm4T21Bs+GHABuCa7v//LR/TvpjHa7oe7 |
| 2011 /Grb6lVvHSD7spj5iplBLRKZxxEYGdCbY9LWWC5hBB2voWno6DJUMzfkC3T8KJsWL9umDQY5szPt | 1956 /Grb6lVvHSD7spj5iplBLRKZxxEYGdCbY9LWWC5hBB2voWno6DJUMzfkC3T8KJsWL9umDQY5szPt |
| 2012 AVijEPwfucjncQ== | 1957 AVijEPwfucjncQ== |
| 2013 """) | 1958 """) |
| 2014 | 1959 |
| 2015 ##file activate.sh | 1960 ##file activate.sh |
| 2016 ACTIVATE_SH = convert(""" | 1961 ACTIVATE_SH = convert(""" |
| 2017 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 | 1975 VzsV75usvTdYef+57v5n1b225qhXfwEmxHEs |
| 2031 +n8O9H8f5vsGOWXsL1+1k3g= | |
| 2032 """) | 1976 """) |
| 2033 | 1977 |
| 2034 ##file activate.fish | 1978 ##file activate.fish |
| 2035 ACTIVATE_FISH = convert(""" | 1979 ACTIVATE_FISH = convert(""" |
| 2036 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 | 1994 wYyNuRPSTcd/B48Ppeg= |
| 2051 32XS1ITj/qLjN72ob0hc5C9bzw8MhfmL | |
| 2052 """) | 1995 """) |
| 2053 | 1996 |
| 2054 ##file activate.csh | 1997 ##file activate.csh |
| 2055 ACTIVATE_CSH = convert(""" | 1998 ACTIVATE_CSH = convert(""" |
| 2056 eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc | 1999 eJx1U2FP2zAQ/e5f8TAV3Soo+0zXbYUiDQkKQgVp2ibjJNfFUuIg22nVf885SVFLO3+I7Lt3fr6X |
| 2057 ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw | 2000 d8eY58ZjYQpCWfuAhFB7yrAyIYf0Ve1SQmLsuU6DWepAw9TnEoOFq0rwdjAUx/hV1Ui1tVWAqy1M |
| 2058 tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D | 2001 QGYcpaFYx+yVI67LkKwx1UuTEaYGl4X2Bl+zJpAlP/6V2hTDtCq/DYXQhdEeGW040Q/Eb+t9V/e3 |
| 2059 r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW | 2002 U/V88zh/mtyqh8n8J47G+IKTE3gKZJdoYrK3h5MRU1tGYS83gqNc+3yEgyyP93cP820evHLvr2H8 |
| 2060 VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs | 2003 kaYB/peoyY7aVHzpJnE9e+6I5Z+ji4GMTNJWNuOQq6MA1N25p8pW9HWdVWlfsNpPDbdxjgpaahuw |
| 2061 cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V | 2004 1M7opCA/FFu1uwxC7L8KUqmto1KyQe3rx0I0Eovdf7BVe67U5c1MzSZ310pddGheZoFPWyytRkzU |
| 2062 tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g | 2005 aCA/I+RkBXhFXr5aWV0SxjhUI6jwdAj8kmhPzX7nTfJFkM3MImp2VdVFFq1vLHSU5szYQK4Ri+Jd |
| 2063 QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k | 2006 xlW2JBtOGcyYVW7SnB3v6RS91g3gKapZ0oWxbHVteYIIq3iv7QeuSrUj6KSqQ+yqsxDj1ivNQxKF |
| 2064 TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa | 2007 YON10Q+NH/ARS95i5Tuqq2Vxfvc23f/FO6zrtXXmJr+ZtMY9/A15ZXFWtmch2rEQ4g1ryVHH |
| 2065 n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H | |
| 2066 37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD | |
| 2067 """) | 2008 """) |
| 2068 | 2009 |
| 2069 ##file activate.bat | 2010 ##file activate.bat |
| 2070 ACTIVATE_BAT = convert(""" | 2011 ACTIVATE_BAT = convert(""" |
| 2071 eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT | 2012 eJx9Ul9LhEAQfxf8DoOclI/dYyFkaCmcq4gZQTBUrincuZFbff12T133TM+nnd35/Zvxlr7XDFhV |
| 2072 PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt | 2013 mUZHOVhFlOWP3g4DUriIWoVomYZpNBWUtGpaWgImO191pFkSpzlcmgaI70jVX7n2Qp8tuByg+46O |
| 2073 r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X | 2014 CMHbMq64T+nmlJt082D1T44muCDk2prgEHF4mdI9RaS/QwSt3zSyIAaftRccvqVTBziD1x/WlPD5 |
| 2074 0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw== | 2015 xd729NDBb8Nr4DU9QNMKsJeH9pkhPedhQsIkDuCDCa6A+NF9IevVFAohkqizdHetg/tkWvPoftWJ |
| 2016 MCqnOxv7/x7Np6yv9P2Ker5dmX8yNyCkkWnbZy3N5LarczlqL8htx2EM9rQ/2H5BvIsIEi8OEG8U |
| 2017 +g8CsNTr |
| 2075 """) | 2018 """) |
| 2076 | 2019 |
| 2077 ##file deactivate.bat | 2020 ##file deactivate.bat |
| 2078 DEACTIVATE_BAT = convert(""" | 2021 DEACTIVATE_BAT = convert(""" |
| 2079 eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho | 2022 eJyFkN0KgkAUhO8F32EQpHqFQEjQUPAPMaErqVxzId3IrV6/XST/UDx3c86c4WMO5FYysKJQFVVp |
| 2080 cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx | 2023 CEfqxsnJ9DI7SA25i20fFqs3HO+GYLsDZ7h8GM3xfLHrg1QNvpSX4CWpQGvokZk4uqrQAjXjyElB |
| 2081 EchHtwsohN1bILUgw61c/Vy4AJYPYm4= | 2024 a5IjCz0r+2dHcehHCe5MZNmB5R7TdqMqECMptHZh6DN/utb7Zs6Cej8OXYE5J04YOKFvD4GkHuJ0 |
| 2025 pilSd1jG6n87tDZ+BUwUOepI6CGSkFMYWf0ihvT33Qj1A+tCkSI= |
| 2082 """) | 2026 """) |
| 2083 | 2027 |
| 2084 ##file activate.ps1 | 2028 ##file activate.ps1 |
| 2085 ACTIVATE_PS = convert(""" | 2029 ACTIVATE_PS = convert(""" |
| 2086 eJylWdmO41hyfW+g/0FTU7C7IXeJIqmtB/3AnZRIStxF2kaBm7gv4ipyMF/mB3+Sf8GXVGVl1tLT | 2030 eJylWdmO41hyfW+g/0FTU7C7IXeJIqmtB/3AnZRIStxF2kaBm7gv4ipyMF/mB3+Sf8GXVGVl1tLT |
| 2087 43ECSqR4b5wbETeWE8z/+a///vNCDaN6cYtSf5G1dbNw/IVXNIu6aCvX9xa3qsgWl0IJ/7IYinbh | 2031 43ECSqR4b5wbETeWE8z/+a///vNCDaN6cYtSf5G1dbNw/IVXNIu6aCvX9xa3qsgWl0IJ/7IYinbh |
| 2088 2nkOVqs2X0TNjz/8eeFFle826fBhQRaLBkD9uviw+LCy3Sbq7Mb/UNbrH3+YNtLcVaB+Xbipb+eL | 2032 2nkOVqs2X0TNjz/8eeFFle826fBhQRaLBkD9uviw+LCy3Sbq7Mb/UNbrH3+YNtLcVaB+Xbipb+eL |
| 2089 tly0eVsD/M6u6g8//vC+dquobH5VWU75eMFUdvHb4n02RHlXuHYTFfmHbHCLLLNz70NpN+GrBI4p | 2033 tly0eVsD/M6u6g8//vC+dquobH5VWU75eMFUdvHb4n02RHlXuHYTFfmHbHCLLLNz70NpN+GrBI4p |
| 2090 1EeSk4FAXaZR88u0vPip8usi7fznt3fvP+OuPnx49/Pil4td+XnzigIAPoqYQH2J8v4z+C+8b98m | 2034 1EeSk4FAXaZR88u0vPip8usi7fznt3fvP+OuPnx49/Pil4td+XnzigIAPoqYQH2J8v4z+C+8b98m |
| 2091 Q25t7k76LIK0cOz0V89/MXXx0+Lf6z5q3PA/F+/FIif9uqnaadFf/PzXSXYBfqIb2NeApecJwPzI | 2035 Q25t7k76LIK0cOz0V89/MXXx0+Lf6z5q3PA/F+/FIif9uqnaadFf/PzXSXYBfqIb2NeApecJwPzI |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2213 5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq | 2157 5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq |
| 2214 siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa | 2158 siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa |
| 2215 xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb | 2159 xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb |
| 2216 yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF | 2160 yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF |
| 2217 7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py | 2161 7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py |
| 2218 m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC | 2162 m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC |
| 2219 6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw | 2163 6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw |
| 2220 VF5PnJ+ts3a9/Mz38RpG/AUSzYUW | 2164 VF5PnJ+ts3a9/Mz38RpG/AUSzYUW |
| 2221 """) | 2165 """) |
| 2222 | 2166 |
| 2167 ##file python-config |
| 2168 PYTHON_CONFIG = convert(""" |
| 2169 eJyNVV1P2zAUfc+v8ODBiSABxlulTipbO6p1LWqBgVhlhcZpPYUkctzSivHfd6+dpGloGH2Ja/ue |
| 2170 e+65Hz78xNhtf3x90xmw7vCWsRPGLvpDNuz87MKfdKMWSWxZ4ilNpCLZJiuWc66SVFUOZkkcirll |
| 2171 rfxIBAzOMtImDzSVPBRrekwoX/OZu/0r4lm0DHiG60g86u8sjPw5rCyy86NRkB8QuuBRSqfAKESn |
| 2172 3orLTCQxE3GYkC9tYp8fk89OSwNsmXgizrhUtnumeSgeo5GbLUMk49Rv+2nK48Cm/qMwfp333J2/ |
| 2173 dVcAGE0CIQHBsgIeEr4Wij0LtWDLzJ9ze5YEvH2WI6CHTAVcSu9ZCsXtgxu81CIvp6/k4eXsdfo7 |
| 2174 PvDCRD75yi41QitfzlcPp1OI7i/1/iQitqnr0iMgQ+A6wa+IKwwdxyk9IiXNAzgquTFU8NIxAVjM |
| 2175 osm1Zz526e+shQ4hKRVci69nPC3Kw4NQEmkQ65E7OodxorSvxjvpBjQHDmWFIQ1mlmzlS5vedseT |
| 2176 /mgIEsMJ7Lxz2bLAF9M5xeLEhdbHxpWOw0GdkJApMVBRF1y+a0z3c9WZPAXGFcFrJgCIB+024uad |
| 2177 0CrzmEoRa3Ub4swNIHPGf7QDV+2uj2OiFWsChgCwjKqN6rp5izpbH6Wc1O1TclQTP/XVwi6anTr1 |
| 2178 1sbubjZLI1+VptPSdCfwnFBrB1jvebrTA9uUhU2/9gad7xPqeFkaQcnnLbCViZK8d7R1kxzFrIJV |
| 2179 8EaLYmKYpvGVkig+3C5HCXbM1jGCGekiM2pRCVPyRyXYdPf6kcbWEQ36F5V4Gq9N7icNNw+JHwRE |
| 2180 LTgxRXACpvnQv/PuT0xCCAywY/K4hE6Now2qDwaSE5FB+1agsoUveYDepS83qFcF1NufvULD3fTl |
| 2181 g6Hgf7WBt6lzMeiyyWVn3P1WVbwaczHmTzE9A5SyItTVgFYyvs/L/fXlaNgbw8v3azT+0eikVlWD |
| 2182 /vBHbzQumP23uBCjsYdrL9OWARwxs/nuLOzeXbPJTa/Xv6sUmQir5pC1YRLz3eA+CD8Z0XpcW8v9 |
| 2183 MZWF36ryyXXf3yBIz6nzqz8Muyz0m5Qj7OexfYo/Ph3LqvkHUg7AuA== |
| 2184 """) |
| 2185 |
| 2223 MH_MAGIC = 0xfeedface | 2186 MH_MAGIC = 0xfeedface |
| 2224 MH_CIGAM = 0xcefaedfe | 2187 MH_CIGAM = 0xcefaedfe |
| 2225 MH_MAGIC_64 = 0xfeedfacf | 2188 MH_MAGIC_64 = 0xfeedfacf |
| 2226 MH_CIGAM_64 = 0xcffaedfe | 2189 MH_CIGAM_64 = 0xcffaedfe |
| 2227 FAT_MAGIC = 0xcafebabe | 2190 FAT_MAGIC = 0xcafebabe |
| 2228 BIG_ENDIAN = '>' | 2191 BIG_ENDIAN = '>' |
| 2229 LITTLE_ENDIAN = '<' | 2192 LITTLE_ENDIAN = '<' |
| 2230 LC_LOAD_DYLIB = 0xc | 2193 LC_LOAD_DYLIB = 0xc |
| 2231 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') | 2194 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint') |
| 2232 | 2195 |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2349 elif magic == MH_MAGIC: | 2312 elif magic == MH_MAGIC: |
| 2350 do_macho(file, 32, BIG_ENDIAN) | 2313 do_macho(file, 32, BIG_ENDIAN) |
| 2351 elif magic == MH_CIGAM: | 2314 elif magic == MH_CIGAM: |
| 2352 do_macho(file, 32, LITTLE_ENDIAN) | 2315 do_macho(file, 32, LITTLE_ENDIAN) |
| 2353 elif magic == MH_MAGIC_64: | 2316 elif magic == MH_MAGIC_64: |
| 2354 do_macho(file, 64, BIG_ENDIAN) | 2317 do_macho(file, 64, BIG_ENDIAN) |
| 2355 elif magic == MH_CIGAM_64: | 2318 elif magic == MH_CIGAM_64: |
| 2356 do_macho(file, 64, LITTLE_ENDIAN) | 2319 do_macho(file, 64, LITTLE_ENDIAN) |
| 2357 | 2320 |
| 2358 assert(len(what) >= len(value)) | 2321 assert(len(what) >= len(value)) |
| 2359 do_file(open(path, 'r+b')) | 2322 |
| 2323 with open(path, 'r+b') as f: |
| 2324 do_file(f) |
| 2360 | 2325 |
| 2361 | 2326 |
| 2362 if __name__ == '__main__': | 2327 if __name__ == '__main__': |
| 2363 main() | 2328 main() |
| 2364 | 2329 |
| 2365 ## TODO: | 2330 # TODO: |
| 2366 ## Copy python.exe.manifest | 2331 # Copy python.exe.manifest |
| 2367 ## Monkeypatch distutils.sysconfig | 2332 # Monkeypatch distutils.sysconfig |
| OLD | NEW |