Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(19)

Side by Side Diff: bootstrap/virtualenv/virtualenv.py

Issue 1407953011: Re-land: Removed virtualenv from depot_tools (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/depot_tools
Patch Set: Re-added files that were present before virtualenv Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « bootstrap/virtualenv/tox.ini ('k') | bootstrap/virtualenv/virtualenv_embedded/activate.bat » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 #!/usr/bin/env python
2 """Create a "virtual" Python installation
3 """
4
5 __version__ = "12.0"
6 virtualenv_version = __version__ # legacy
7
8 # NB: avoid placing additional imports here, before sys.path is fixed!
9
10 import sys
11 import os
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'):
31 del sys.path[0]
32
33 import base64
34 import codecs
35 import optparse
36 import re
37 import shutil
38 import logging
39 import tempfile
40 import zlib
41 import errno
42 import glob
43 import distutils.sysconfig
44 from distutils.util import strtobool
45 import struct
46 import subprocess
47 import tarfile
48
49 if sys.version_info < (2, 6):
50 print('ERROR: %s' % sys.exc_info()[1])
51 print('ERROR: this script requires Python 2.6 or greater.')
52 sys.exit(101)
53
54 try:
55 basestring
56 except NameError:
57 basestring = str
58
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])
66
67 is_jython = sys.platform.startswith('java')
68 is_pypy = hasattr(sys, 'pypy_version_info')
69 is_win = (sys.platform == 'win32')
70 is_cygwin = (sys.platform == 'cygwin')
71 is_darwin = (sys.platform == 'darwin')
72 abiflags = getattr(sys, 'abiflags', '')
73
74 user_dir = os.path.expanduser('~')
75 if is_win:
76 default_storage_dir = os.path.join(user_dir, 'virtualenv')
77 else:
78 default_storage_dir = os.path.join(user_dir, '.virtualenv')
79 default_config_file = os.path.join(default_storage_dir, 'virtualenv.ini')
80
81 if is_pypy:
82 expected_exe = 'pypy'
83 elif is_jython:
84 expected_exe = 'jython'
85 else:
86 expected_exe = 'python'
87
88 # Return a mapping of version -> Python executable
89 # Only provided for Windows, where the information in the registry is used
90 if not is_win:
91 def get_installed_pythons():
92 return {}
93 else:
94 try:
95 import winreg
96 except ImportError:
97 import _winreg as winreg
98
99 def get_installed_pythons():
100 try:
101 python_core = winreg.CreateKey(winreg.HKEY_LOCAL_MACHINE,
102 "Software\\Python\\PythonCore")
103 except WindowsError:
104 # No registered Python installations
105 return {}
106 i = 0
107 versions = []
108 while True:
109 try:
110 versions.append(winreg.EnumKey(python_core, i))
111 i = i + 1
112 except WindowsError:
113 break
114 exes = dict()
115 for ver in versions:
116 try:
117 path = winreg.QueryValue(python_core, "%s\\InstallPath" % ver)
118 except WindowsError:
119 continue
120 exes[ver] = join(path, "python.exe")
121
122 winreg.CloseKey(python_core)
123
124 # Add the major versions
125 # Sort the keys, then repeatedly update the major version entry
126 # Last executable (i.e., highest version) wins with this approach
127 for ver in sorted(exes):
128 exes[ver[0]] = exes[ver]
129
130 return exes
131
132 REQUIRED_MODULES = ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
133 'fnmatch', 'locale', 'encodings', 'codecs',
134 'stat', 'UserDict', 'readline', 'copy_reg', 'types',
135 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
136 'zlib']
137
138 REQUIRED_FILES = ['lib-dynload', 'config']
139
140 majver, minver = sys.version_info[:2]
141 if majver == 2:
142 if minver >= 6:
143 REQUIRED_MODULES.extend(['warnings', 'linecache', '_abcoll', 'abc'])
144 if minver >= 7:
145 REQUIRED_MODULES.extend(['_weakrefset'])
146 elif majver == 3:
147 # Some extra modules are needed for Python 3, but different ones
148 # for different versions.
149 REQUIRED_MODULES.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
150 '_weakrefset', 'copyreg', 'tempfile', 'random',
151 '__future__', 'collections', 'keyword', 'tarfile',
152 'shutil', 'struct', 'copy', 'tokenize', 'token',
153 'functools', 'heapq', 'bisect', 'weakref',
154 'reprlib'])
155 if minver >= 2:
156 REQUIRED_FILES[-1] = 'config-%s' % majver
157 if minver >= 3:
158 import sysconfig
159 platdir = sysconfig.get_config_var('PLATDIR')
160 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([
165 #"aifc",
166 #"antigravity",
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 ])
312 if minver >= 4:
313 REQUIRED_MODULES.extend([
314 'operator',
315 '_collections_abc',
316 '_bootlocale',
317 ])
318
319 if is_pypy:
320 # these are needed to correctly display the exceptions that may happen
321 # during the bootstrap
322 REQUIRED_MODULES.extend(['traceback', 'linecache'])
323
324 class Logger(object):
325
326 """
327 Logging object for use in command-line script. Allows ranges of
328 levels, to avoid some redundancy of displayed information.
329 """
330
331 DEBUG = logging.DEBUG
332 INFO = logging.INFO
333 NOTIFY = (logging.INFO+logging.WARN)/2
334 WARN = WARNING = logging.WARN
335 ERROR = logging.ERROR
336 FATAL = logging.FATAL
337
338 LEVELS = [DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
339
340 def __init__(self, consumers):
341 self.consumers = consumers
342 self.indent = 0
343 self.in_progress = None
344 self.in_progress_hanging = False
345
346 def debug(self, msg, *args, **kw):
347 self.log(self.DEBUG, msg, *args, **kw)
348 def info(self, msg, *args, **kw):
349 self.log(self.INFO, msg, *args, **kw)
350 def notify(self, msg, *args, **kw):
351 self.log(self.NOTIFY, msg, *args, **kw)
352 def warn(self, msg, *args, **kw):
353 self.log(self.WARN, msg, *args, **kw)
354 def error(self, msg, *args, **kw):
355 self.log(self.ERROR, msg, *args, **kw)
356 def fatal(self, msg, *args, **kw):
357 self.log(self.FATAL, msg, *args, **kw)
358 def log(self, level, msg, *args, **kw):
359 if args:
360 if kw:
361 raise TypeError(
362 "You may give positional or keyword arguments, not both")
363 args = args or kw
364 rendered = None
365 for consumer_level, consumer in self.consumers:
366 if self.level_matches(level, consumer_level):
367 if (self.in_progress_hanging
368 and consumer in (sys.stdout, sys.stderr)):
369 self.in_progress_hanging = False
370 sys.stdout.write('\n')
371 sys.stdout.flush()
372 if rendered is None:
373 if args:
374 rendered = msg % args
375 else:
376 rendered = msg
377 rendered = ' '*self.indent + rendered
378 if hasattr(consumer, 'write'):
379 consumer.write(rendered+'\n')
380 else:
381 consumer(rendered)
382
383 def start_progress(self, msg):
384 assert not self.in_progress, (
385 "Tried to start_progress(%r) while in_progress %r"
386 % (msg, self.in_progress))
387 if self.level_matches(self.NOTIFY, self._stdout_level()):
388 sys.stdout.write(msg)
389 sys.stdout.flush()
390 self.in_progress_hanging = True
391 else:
392 self.in_progress_hanging = False
393 self.in_progress = msg
394
395 def end_progress(self, msg='done.'):
396 assert self.in_progress, (
397 "Tried to end_progress without start_progress")
398 if self.stdout_level_matches(self.NOTIFY):
399 if not self.in_progress_hanging:
400 # Some message has been printed out since start_progress
401 sys.stdout.write('...' + self.in_progress + msg + '\n')
402 sys.stdout.flush()
403 else:
404 sys.stdout.write(msg + '\n')
405 sys.stdout.flush()
406 self.in_progress = None
407 self.in_progress_hanging = False
408
409 def show_progress(self):
410 """If we are in a progress scope, and no log messages have been
411 shown, write out another '.'"""
412 if self.in_progress_hanging:
413 sys.stdout.write('.')
414 sys.stdout.flush()
415
416 def stdout_level_matches(self, level):
417 """Returns true if a message at this level will go to stdout"""
418 return self.level_matches(level, self._stdout_level())
419
420 def _stdout_level(self):
421 """Returns the level that stdout runs at"""
422 for level, consumer in self.consumers:
423 if consumer is sys.stdout:
424 return level
425 return self.FATAL
426
427 def level_matches(self, level, consumer_level):
428 """
429 >>> l = Logger([])
430 >>> l.level_matches(3, 4)
431 False
432 >>> l.level_matches(3, 2)
433 True
434 >>> l.level_matches(slice(None, 3), 3)
435 False
436 >>> l.level_matches(slice(None, 3), 2)
437 True
438 >>> l.level_matches(slice(1, 3), 1)
439 True
440 >>> l.level_matches(slice(2, 3), 1)
441 False
442 """
443 if isinstance(level, slice):
444 start, stop = level.start, level.stop
445 if start is not None and start > consumer_level:
446 return False
447 if stop is not None and stop <= consumer_level:
448 return False
449 return True
450 else:
451 return level >= consumer_level
452
453 #@classmethod
454 def level_for_integer(cls, level):
455 levels = cls.LEVELS
456 if level < 0:
457 return levels[0]
458 if level >= len(levels):
459 return levels[-1]
460 return levels[level]
461
462 level_for_integer = classmethod(level_for_integer)
463
464 # create a silent logger just to prevent this from being undefined
465 # will be overridden with requested verbosity main() is called.
466 logger = Logger([(Logger.LEVELS[-1], sys.stdout)])
467
468 def mkdir(path):
469 if not os.path.exists(path):
470 logger.info('Creating %s', path)
471 os.makedirs(path)
472 else:
473 logger.info('Directory %s already exists', path)
474
475 def copyfileordir(src, dest, symlink=True):
476 if os.path.isdir(src):
477 shutil.copytree(src, dest, symlink)
478 else:
479 shutil.copy2(src, dest)
480
481 def copyfile(src, dest, symlink=True):
482 if not os.path.exists(src):
483 # Some bad symlink in the src
484 logger.warn('Cannot find file %s (bad symlink)', src)
485 return
486 if os.path.exists(dest):
487 logger.debug('File %s already exists', dest)
488 return
489 if not os.path.exists(os.path.dirname(dest)):
490 logger.info('Creating parent directories for %s', os.path.dirname(dest))
491 os.makedirs(os.path.dirname(dest))
492 if not os.path.islink(src):
493 srcpath = os.path.abspath(src)
494 else:
495 srcpath = os.readlink(src)
496 if symlink and hasattr(os, 'symlink') and not is_win:
497 logger.info('Symlinking %s', dest)
498 try:
499 os.symlink(srcpath, dest)
500 except (OSError, NotImplementedError):
501 logger.info('Symlinking failed, copying to %s', dest)
502 copyfileordir(src, dest, symlink)
503 else:
504 logger.info('Copying to %s', dest)
505 copyfileordir(src, dest, symlink)
506
507 def writefile(dest, content, overwrite=True):
508 if not os.path.exists(dest):
509 logger.info('Writing %s', dest)
510 f = open(dest, 'wb')
511 f.write(content.encode('utf-8'))
512 f.close()
513 return
514 else:
515 f = open(dest, 'rb')
516 c = f.read()
517 f.close()
518 if c != content.encode("utf-8"):
519 if not overwrite:
520 logger.notify('File %s exists with different content; not overwr iting', dest)
521 return
522 logger.notify('Overwriting %s with new content', dest)
523 f = open(dest, 'wb')
524 f.write(content.encode('utf-8'))
525 f.close()
526 else:
527 logger.info('Content %s already in place', dest)
528
529 def rmtree(dir):
530 if os.path.exists(dir):
531 logger.notify('Deleting tree %s', dir)
532 shutil.rmtree(dir)
533 else:
534 logger.info('Do not need to delete %s; already gone', dir)
535
536 def make_exe(fn):
537 if hasattr(os, 'chmod'):
538 oldmode = os.stat(fn).st_mode & 0xFFF # 0o7777
539 newmode = (oldmode | 0x16D) & 0xFFF # 0o555, 0o7777
540 os.chmod(fn, newmode)
541 logger.info('Changed mode of %s to %s', fn, oct(newmode))
542
543 def _find_file(filename, dirs):
544 for dir in reversed(dirs):
545 files = glob.glob(os.path.join(dir, filename))
546 if files and os.path.isfile(files[0]):
547 return True, files[0]
548 return False, filename
549
550 def file_search_dirs():
551 here = os.path.dirname(os.path.abspath(__file__))
552 dirs = ['.', here,
553 join(here, 'virtualenv_support')]
554 if os.path.splitext(os.path.dirname(__file__))[0] != 'virtualenv':
555 # Probably some boot script; just in case virtualenv is installed...
556 try:
557 import virtualenv
558 except ImportError:
559 pass
560 else:
561 dirs.append(os.path.join(os.path.dirname(virtualenv.__file__), 'virt ualenv_support'))
562 return [d for d in dirs if os.path.isdir(d)]
563
564
565 class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
566 """
567 Custom help formatter for use in ConfigOptionParser that updates
568 the defaults before expanding them, allowing them to show up correctly
569 in the help listing
570 """
571 def expand_default(self, option):
572 if self.parser is not None:
573 self.parser.update_defaults(self.parser.defaults)
574 return optparse.IndentedHelpFormatter.expand_default(self, option)
575
576
577 class ConfigOptionParser(optparse.OptionParser):
578 """
579 Custom option parser which updates its defaults by checking the
580 configuration files and environmental variables
581 """
582 def __init__(self, *args, **kwargs):
583 self.config = ConfigParser.RawConfigParser()
584 self.files = self.get_config_files()
585 self.config.read(self.files)
586 optparse.OptionParser.__init__(self, *args, **kwargs)
587
588 def get_config_files(self):
589 config_file = os.environ.get('VIRTUALENV_CONFIG_FILE', False)
590 if config_file and os.path.exists(config_file):
591 return [config_file]
592 return [default_config_file]
593
594 def update_defaults(self, defaults):
595 """
596 Updates the given defaults with values from the config files and
597 the environ. Does a little special handling for certain types of
598 options (lists).
599 """
600 # Then go and look for the other sources of configuration:
601 config = {}
602 # 1. config files
603 config.update(dict(self.get_config_section('virtualenv')))
604 # 2. environmental variables
605 config.update(dict(self.get_environ_vars()))
606 # Then set the options with those values
607 for key, val in config.items():
608 key = key.replace('_', '-')
609 if not key.startswith('--'):
610 key = '--%s' % key # only prefer long opts
611 option = self.get_option(key)
612 if option is not None:
613 # ignore empty values
614 if not val:
615 continue
616 # handle multiline configs
617 if option.action == 'append':
618 val = val.split()
619 else:
620 option.nargs = 1
621 if option.action == 'store_false':
622 val = not strtobool(val)
623 elif option.action in ('store_true', 'count'):
624 val = strtobool(val)
625 try:
626 val = option.convert_value(key, val)
627 except optparse.OptionValueError:
628 e = sys.exc_info()[1]
629 print("An error occurred during configuration: %s" % e)
630 sys.exit(3)
631 defaults[option.dest] = val
632 return defaults
633
634 def get_config_section(self, name):
635 """
636 Get a section of a configuration
637 """
638 if self.config.has_section(name):
639 return self.config.items(name)
640 return []
641
642 def get_environ_vars(self, prefix='VIRTUALENV_'):
643 """
644 Returns a generator with all environmental vars with prefix VIRTUALENV
645 """
646 for key, val in os.environ.items():
647 if key.startswith(prefix):
648 yield (key.replace(prefix, '').lower(), val)
649
650 def get_default_values(self):
651 """
652 Overridding to make updating the defaults after instantiation of
653 the option parser possible, update_defaults() does the dirty work.
654 """
655 if not self.process_default_values:
656 # Old, pre-Optik 1.5 behaviour.
657 return optparse.Values(self.defaults)
658
659 defaults = self.update_defaults(self.defaults.copy()) # ours
660 for option in self._get_all_options():
661 default = defaults.get(option.dest)
662 if isinstance(default, basestring):
663 opt_str = option.get_opt_string()
664 defaults[option.dest] = option.check_value(opt_str, default)
665 return optparse.Values(defaults)
666
667
668 def main():
669 parser = ConfigOptionParser(
670 version=virtualenv_version,
671 usage="%prog [OPTIONS] DEST_DIR",
672 formatter=UpdatingDefaultsHelpFormatter())
673
674 parser.add_option(
675 '-v', '--verbose',
676 action='count',
677 dest='verbose',
678 default=0,
679 help="Increase verbosity.")
680
681 parser.add_option(
682 '-q', '--quiet',
683 action='count',
684 dest='quiet',
685 default=0,
686 help='Decrease verbosity.')
687
688 parser.add_option(
689 '-p', '--python',
690 dest='python',
691 metavar='PYTHON_EXE',
692 help='The Python interpreter to use, e.g., --python=python2.5 will use t he python2.5 '
693 'interpreter to create the new environment. The default is the interpre ter that '
694 'virtualenv was installed with (%s)' % sys.executable)
695
696 parser.add_option(
697 '--clear',
698 dest='clear',
699 action='store_true',
700 help="Clear out the non-root install and start from scratch.")
701
702 parser.set_defaults(system_site_packages=False)
703 parser.add_option(
704 '--no-site-packages',
705 dest='system_site_packages',
706 action='store_false',
707 help="DEPRECATED. Retained only for backward compatibility. "
708 "Not having access to global site-packages is now the default behav ior.")
709
710 parser.add_option(
711 '--system-site-packages',
712 dest='system_site_packages',
713 action='store_true',
714 help="Give the virtual environment access to the global site-packages.")
715
716 parser.add_option(
717 '--always-copy',
718 dest='symlink',
719 action='store_false',
720 default=True,
721 help="Always copy files rather than symlinking.")
722
723 parser.add_option(
724 '--unzip-setuptools',
725 dest='unzip_setuptools',
726 action='store_true',
727 help="Unzip Setuptools when installing it.")
728
729 parser.add_option(
730 '--relocatable',
731 dest='relocatable',
732 action='store_true',
733 help='Make an EXISTING virtualenv environment relocatable. '
734 'This fixes up scripts and makes all .pth files relative.')
735
736 parser.add_option(
737 '--no-setuptools',
738 dest='no_setuptools',
739 action='store_true',
740 help='Do not install setuptools (or pip) in the new virtualenv.')
741
742 parser.add_option(
743 '--no-pip',
744 dest='no_pip',
745 action='store_true',
746 help='Do not install pip in the new virtualenv.')
747
748 default_search_dirs = file_search_dirs()
749 parser.add_option(
750 '--extra-search-dir',
751 dest="search_dirs",
752 action="append",
753 metavar='DIR',
754 default=default_search_dirs,
755 help="Directory to look for setuptools/pip distributions in. "
756 "This option can be used multiple times.")
757
758 parser.add_option(
759 '--never-download',
760 dest="never_download",
761 action="store_true",
762 default=True,
763 help="DEPRECATED. Retained only for backward compatibility. This option has no effect. "
764 "Virtualenv never downloads pip or setuptools.")
765
766 parser.add_option(
767 '--prompt',
768 dest='prompt',
769 help='Provides an alternative prompt prefix for this environment.')
770
771 parser.add_option(
772 '--setuptools',
773 dest='setuptools',
774 action='store_true',
775 help="DEPRECATED. Retained only for backward compatibility. This option has no effect.")
776
777 parser.add_option(
778 '--distribute',
779 dest='distribute',
780 action='store_true',
781 help="DEPRECATED. Retained only for backward compatibility. This option has no effect.")
782
783 if 'extend_parser' in globals():
784 extend_parser(parser)
785
786 options, args = parser.parse_args()
787
788 global logger
789
790 if 'adjust_options' in globals():
791 adjust_options(options, args)
792
793 verbosity = options.verbose - options.quiet
794 logger = Logger([(Logger.level_for_integer(2 - verbosity), sys.stdout)])
795
796 if options.python and not os.environ.get('VIRTUALENV_INTERPRETER_RUNNING'):
797 env = os.environ.copy()
798 interpreter = resolve_interpreter(options.python)
799 if interpreter == sys.executable:
800 logger.warn('Already using interpreter %s' % interpreter)
801 else:
802 logger.notify('Running virtualenv with interpreter %s' % interpreter )
803 env['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
804 file = __file__
805 if file.endswith('.pyc'):
806 file = file[:-1]
807 popen = subprocess.Popen([interpreter, file] + sys.argv[1:], env=env )
808 raise SystemExit(popen.wait())
809
810 if not args:
811 print('You must provide a DEST_DIR')
812 parser.print_help()
813 sys.exit(2)
814 if len(args) > 1:
815 print('There must be only one argument: DEST_DIR (you gave %s)' % (
816 ' '.join(args)))
817 parser.print_help()
818 sys.exit(2)
819
820 home_dir = args[0]
821
822 if os.environ.get('WORKING_ENV'):
823 logger.fatal('ERROR: you cannot run virtualenv while in a workingenv')
824 logger.fatal('Please deactivate your workingenv, then re-run this script ')
825 sys.exit(3)
826
827 if 'PYTHONHOME' in os.environ:
828 logger.warn('PYTHONHOME is set. You *must* activate the virtualenv befo re using it')
829 del os.environ['PYTHONHOME']
830
831 if options.relocatable:
832 make_environment_relocatable(home_dir)
833 return
834
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,
840 site_packages=options.system_site_packages,
841 clear=options.clear,
842 unzip_setuptools=options.unzip_setuptools,
843 prompt=options.prompt,
844 search_dirs=options.search_dirs,
845 never_download=True,
846 no_setuptools=options.no_setuptools,
847 no_pip=options.no_pip,
848 symlink=options.symlink)
849 if 'after_install' in globals():
850 after_install(options, home_dir)
851
852 def call_subprocess(cmd, show_stdout=True,
853 filter_stdout=None, cwd=None,
854 raise_on_returncode=True, extra_env=None,
855 remove_from_env=None):
856 cmd_parts = []
857 for part in cmd:
858 if len(part) > 45:
859 part = part[:20]+"..."+part[-20:]
860 if ' ' in part or '\n' in part or '"' in part or "'" in part:
861 part = '"%s"' % part.replace('"', '\\"')
862 if hasattr(part, 'decode'):
863 try:
864 part = part.decode(sys.getdefaultencoding())
865 except UnicodeDecodeError:
866 part = part.decode(sys.getfilesystemencoding())
867 cmd_parts.append(part)
868 cmd_desc = ' '.join(cmd_parts)
869 if show_stdout:
870 stdout = None
871 else:
872 stdout = subprocess.PIPE
873 logger.debug("Running command %s" % cmd_desc)
874 if extra_env or remove_from_env:
875 env = os.environ.copy()
876 if extra_env:
877 env.update(extra_env)
878 if remove_from_env:
879 for varname in remove_from_env:
880 env.pop(varname, None)
881 else:
882 env = None
883 try:
884 proc = subprocess.Popen(
885 cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
886 cwd=cwd, env=env)
887 except Exception:
888 e = sys.exc_info()[1]
889 logger.fatal(
890 "Error %s while executing command %s" % (e, cmd_desc))
891 raise
892 all_output = []
893 if stdout is not None:
894 stdout = proc.stdout
895 encoding = sys.getdefaultencoding()
896 fs_encoding = sys.getfilesystemencoding()
897 while 1:
898 line = stdout.readline()
899 try:
900 line = line.decode(encoding)
901 except UnicodeDecodeError:
902 line = line.decode(fs_encoding)
903 if not line:
904 break
905 line = line.rstrip()
906 all_output.append(line)
907 if filter_stdout:
908 level = filter_stdout(line)
909 if isinstance(level, tuple):
910 level, line = level
911 logger.log(level, line)
912 if not logger.stdout_level_matches(level):
913 logger.show_progress()
914 else:
915 logger.info(line)
916 else:
917 proc.communicate()
918 proc.wait()
919 if proc.returncode:
920 if raise_on_returncode:
921 if all_output:
922 logger.notify('Complete output from command %s:' % cmd_desc)
923 logger.notify('\n'.join(all_output) + '\n----------------------- -----------------')
924 raise OSError(
925 "Command %s failed with error code %s"
926 % (cmd_desc, proc.returncode))
927 else:
928 logger.warn(
929 "Command %s had error code %s"
930 % (cmd_desc, proc.returncode))
931
932 def filter_install_output(line):
933 if line.strip().startswith('running'):
934 return Logger.INFO
935 return Logger.DEBUG
936
937 def find_wheels(projects, search_dirs):
938 """Find wheels from which we can import PROJECTS.
939
940 Scan through SEARCH_DIRS for a wheel for each PROJECT in turn. Return
941 a list of the first wheel found for each PROJECT
942 """
943
944 wheels = []
945
946 # Look through SEARCH_DIRS for the first suitable wheel. Don't bother
947 # about version checking here, as this is simply to get something we can
948 # then use to install the correct version.
949 for project in projects:
950 for dirname in search_dirs:
951 # This relies on only having "universal" wheels available.
952 # The pattern could be tightened to require -py2.py3-none-any.whl.
953 files = glob.glob(os.path.join(dirname, project + '-*.whl'))
954 if files:
955 wheels.append(os.path.abspath(files[0]))
956 break
957 else:
958 # We're out of luck, so quit with a suitable error
959 logger.fatal('Cannot find a wheel for %s' % (project,))
960
961 return wheels
962
963 def install_wheel(project_names, py_executable, search_dirs=None):
964 if search_dirs is None:
965 search_dirs = file_search_dirs()
966
967 wheels = find_wheels(['setuptools', 'pip'], search_dirs)
968 pythonpath = os.pathsep.join(wheels)
969 findlinks = ' '.join(search_dirs)
970
971 cmd = [
972 py_executable, '-c',
973 'import sys, pip; sys.exit(pip.main(["install", "--ignore-installed"] + sys.argv[1:]))',
974 ] + project_names
975 logger.start_progress('Installing %s...' % (', '.join(project_names)))
976 logger.indent += 2
977 try:
978 call_subprocess(cmd, show_stdout=False,
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:
988 logger.indent -= 2
989 logger.end_progress()
990
991 def create_environment(home_dir, site_packages=False, clear=False,
992 unzip_setuptools=False,
993 prompt=None, search_dirs=None, never_download=False,
994 no_setuptools=False, no_pip=False, symlink=True):
995 """
996 Creates a new environment in ``home_dir``.
997
998 If ``site_packages`` is true, then the global ``site-packages/``
999 directory will be on the path.
1000
1001 If ``clear`` is true (default False) then the environment will
1002 first be cleared.
1003 """
1004 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1005
1006 py_executable = os.path.abspath(install_python(
1007 home_dir, lib_dir, inc_dir, bin_dir,
1008 site_packages=site_packages, clear=clear, symlink=symlink))
1009
1010 install_distutils(home_dir)
1011
1012 if not no_setuptools:
1013 to_install = ['setuptools']
1014 if not no_pip:
1015 to_install.append('pip')
1016 install_wheel(to_install, py_executable, search_dirs)
1017
1018 install_activate(home_dir, bin_dir, prompt)
1019
1020 def is_executable_file(fpath):
1021 return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
1022
1023 def path_locations(home_dir):
1024 """Return the path locations for the environment (where libraries are,
1025 where scripts go, etc)"""
1026 # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
1027 # prefix arg is broken: http://bugs.python.org/issue3386
1028 if is_win:
1029 # Windows has lots of problems with executables with spaces in
1030 # the name; this function will remove them (using the ~1
1031 # format):
1032 mkdir(home_dir)
1033 if ' ' in home_dir:
1034 import ctypes
1035 GetShortPathName = ctypes.windll.kernel32.GetShortPathNameW
1036 size = max(len(home_dir)+1, 256)
1037 buf = ctypes.create_unicode_buffer(size)
1038 try:
1039 u = unicode
1040 except NameError:
1041 u = str
1042 ret = GetShortPathName(u(home_dir), buf, size)
1043 if not ret:
1044 print('Error: the path "%s" has a space in it' % home_dir)
1045 print('We could not determine the short pathname for it.')
1046 print('Exiting.')
1047 sys.exit(3)
1048 home_dir = str(buf.value)
1049 lib_dir = join(home_dir, 'Lib')
1050 inc_dir = join(home_dir, 'Include')
1051 bin_dir = join(home_dir, 'Scripts')
1052 if is_jython:
1053 lib_dir = join(home_dir, 'Lib')
1054 inc_dir = join(home_dir, 'Include')
1055 bin_dir = join(home_dir, 'bin')
1056 elif is_pypy:
1057 lib_dir = home_dir
1058 inc_dir = join(home_dir, 'include')
1059 bin_dir = join(home_dir, 'bin')
1060 elif not is_win:
1061 lib_dir = join(home_dir, 'lib', py_version)
1062 multiarch_exec = '/usr/bin/multiarch-platform'
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')
1074 return home_dir, lib_dir, inc_dir, bin_dir
1075
1076
1077 def change_prefix(filename, dst_prefix):
1078 prefixes = [sys.prefix]
1079
1080 if is_darwin:
1081 prefixes.extend((
1082 os.path.join("/Library/Python", sys.version[:3], "site-packages"),
1083 os.path.join(sys.prefix, "Extras", "lib", "python"),
1084 os.path.join("~", "Library", "Python", sys.version[:3], "site-packag es"),
1085 # Python 2.6 no-frameworks
1086 os.path.join("~", ".local", "lib","python", sys.version[:3], "site-p ackages"),
1087 # System Python 2.7 on OSX Mountain Lion
1088 os.path.join("~", "Library", "Python", sys.version[:3], "lib", "pyth on", "site-packages")))
1089
1090 if hasattr(sys, 'real_prefix'):
1091 prefixes.append(sys.real_prefix)
1092 if hasattr(sys, 'base_prefix'):
1093 prefixes.append(sys.base_prefix)
1094 prefixes = list(map(os.path.expanduser, prefixes))
1095 prefixes = list(map(os.path.abspath, prefixes))
1096 # Check longer prefixes first so we don't split in the middle of a filename
1097 prefixes = sorted(prefixes, key=len, reverse=True)
1098 filename = os.path.abspath(filename)
1099 for src_prefix in prefixes:
1100 if filename.startswith(src_prefix):
1101 _, relpath = filename.split(src_prefix, 1)
1102 if src_prefix != os.sep: # sys.prefix == "/"
1103 assert relpath[0] == os.sep
1104 relpath = relpath[1:]
1105 return join(dst_prefix, relpath)
1106 assert False, "Filename %s does not start with any of these prefixes: %s" % \
1107 (filename, prefixes)
1108
1109 def copy_required_modules(dst_prefix, symlink):
1110 import imp
1111 for modname in REQUIRED_MODULES:
1112 if modname in sys.builtin_module_names:
1113 logger.info("Ignoring built-in bootstrap module: %s" % modname)
1114 continue
1115 try:
1116 f, filename, _ = imp.find_module(modname)
1117 except ImportError:
1118 logger.info("Cannot import bootstrap module: %s" % modname)
1119 else:
1120 if f is not None:
1121 f.close()
1122 # special-case custom readline.so on OS X, but not for pypy:
1123 if modname == 'readline' and sys.platform == 'darwin' and not (
1124 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')
1126 elif modname == 'readline' and sys.platform == 'win32':
1127 # special-case for Windows, where readline is not a
1128 # standard module, though it may have been installed in
1129 # site-packages by a third-party package
1130 pass
1131 else:
1132 dst_filename = change_prefix(filename, dst_prefix)
1133 copyfile(filename, dst_filename, symlink)
1134 if filename.endswith('.pyc'):
1135 pyfile = filename[:-1]
1136 if os.path.exists(pyfile):
1137 copyfile(pyfile, dst_filename[:-1], symlink)
1138
1139
1140 def subst_path(prefix_path, prefix, home_dir):
1141 prefix_path = os.path.normpath(prefix_path)
1142 prefix = os.path.normpath(prefix)
1143 home_dir = os.path.normpath(home_dir)
1144 if not prefix_path.startswith(prefix):
1145 logger.warn('Path not in prefix %r %r', prefix_path, prefix)
1146 return
1147 return prefix_path.replace(prefix, home_dir, 1)
1148
1149
1150 def install_python(home_dir, lib_dir, inc_dir, bin_dir, site_packages, clear, sy mlink=True):
1151 """Install just the base environment, no distutils patches etc"""
1152 if sys.executable.startswith(bin_dir):
1153 print('Please use the *system* python to run this script')
1154 return
1155
1156 if clear:
1157 rmtree(lib_dir)
1158 ## FIXME: why not delete it?
1159 ## Maybe it should delete everything with #!/path/to/venv/python in it
1160 logger.notify('Not deleting %s', bin_dir)
1161
1162 if hasattr(sys, 'real_prefix'):
1163 logger.notify('Using real prefix %r' % sys.real_prefix)
1164 prefix = sys.real_prefix
1165 elif hasattr(sys, 'base_prefix'):
1166 logger.notify('Using base prefix %r' % sys.base_prefix)
1167 prefix = sys.base_prefix
1168 else:
1169 prefix = sys.prefix
1170 mkdir(lib_dir)
1171 fix_lib64(lib_dir, symlink)
1172 stdlib_dirs = [os.path.dirname(os.__file__)]
1173 if is_win:
1174 stdlib_dirs.append(join(os.path.dirname(stdlib_dirs[0]), 'DLLs'))
1175 elif is_darwin:
1176 stdlib_dirs.append(join(stdlib_dirs[0], 'site-packages'))
1177 if hasattr(os, 'symlink'):
1178 logger.info('Symlinking Python bootstrap modules')
1179 else:
1180 logger.info('Copying Python bootstrap modules')
1181 logger.indent += 2
1182 try:
1183 # copy required files...
1184 for stdlib_dir in stdlib_dirs:
1185 if not os.path.isdir(stdlib_dir):
1186 continue
1187 for fn in os.listdir(stdlib_dir):
1188 bn = os.path.splitext(fn)[0]
1189 if fn != 'site-packages' and bn in REQUIRED_FILES:
1190 copyfile(join(stdlib_dir, fn), join(lib_dir, fn), symlink)
1191 # ...and modules
1192 copy_required_modules(home_dir, symlink)
1193 finally:
1194 logger.indent -= 2
1195 mkdir(join(lib_dir, 'site-packages'))
1196 import site
1197 site_filename = site.__file__
1198 if site_filename.endswith('.pyc'):
1199 site_filename = site_filename[:-1]
1200 elif site_filename.endswith('$py.class'):
1201 site_filename = site_filename.replace('$py.class', '.py')
1202 site_filename_dst = change_prefix(site_filename, home_dir)
1203 site_dir = os.path.dirname(site_filename_dst)
1204 writefile(site_filename_dst, SITE_PY)
1205 writefile(join(site_dir, 'orig-prefix.txt'), prefix)
1206 site_packages_filename = join(site_dir, 'no-global-site-packages.txt')
1207 if not site_packages:
1208 writefile(site_packages_filename, '')
1209
1210 if is_pypy or is_win:
1211 stdinc_dir = join(prefix, 'include')
1212 else:
1213 stdinc_dir = join(prefix, 'include', py_version + abiflags)
1214 if os.path.exists(stdinc_dir):
1215 copyfile(stdinc_dir, inc_dir, symlink)
1216 else:
1217 logger.debug('No include dir %s' % stdinc_dir)
1218
1219 platinc_dir = distutils.sysconfig.get_python_inc(plat_specific=1)
1220 if platinc_dir != stdinc_dir:
1221 platinc_dest = distutils.sysconfig.get_python_inc(
1222 plat_specific=1, prefix=home_dir)
1223 if platinc_dir == platinc_dest:
1224 # Do platinc_dest manually due to a CPython bug;
1225 # not http://bugs.python.org/issue3386 but a close cousin
1226 platinc_dest = subst_path(platinc_dir, prefix, home_dir)
1227 if platinc_dest:
1228 # PyPy's stdinc_dir and prefix are relative to the original binary
1229 # (traversing virtualenvs), whereas the platinc_dir is relative to
1230 # the inner virtualenv and ignores the prefix argument.
1231 # This seems more evolved than designed.
1232 copyfile(platinc_dir, platinc_dest, symlink)
1233
1234 # pypy never uses exec_prefix, just ignore it
1235 if sys.exec_prefix != prefix and not is_pypy:
1236 if is_win:
1237 exec_dir = join(sys.exec_prefix, 'lib')
1238 elif is_jython:
1239 exec_dir = join(sys.exec_prefix, 'Lib')
1240 else:
1241 exec_dir = join(sys.exec_prefix, 'lib', py_version)
1242 for fn in os.listdir(exec_dir):
1243 copyfile(join(exec_dir, fn), join(lib_dir, fn), symlink)
1244
1245 if is_jython:
1246 # Jython has either jython-dev.jar and javalib/ dir, or just
1247 # jython.jar
1248 for name in 'jython-dev.jar', 'javalib', 'jython.jar':
1249 src = join(prefix, name)
1250 if os.path.exists(src):
1251 copyfile(src, join(home_dir, name), symlink)
1252 # XXX: registry should always exist after Jython 2.5rc1
1253 src = join(prefix, 'registry')
1254 if os.path.exists(src):
1255 copyfile(src, join(home_dir, 'registry'), symlink=False)
1256 copyfile(join(prefix, 'cachedir'), join(home_dir, 'cachedir'),
1257 symlink=False)
1258
1259 mkdir(bin_dir)
1260 py_executable = join(bin_dir, os.path.basename(sys.executable))
1261 if 'Python.framework' in prefix:
1262 # OS X framework builds cause validation to break
1263 # https://github.com/pypa/virtualenv/issues/322
1264 if os.environ.get('__PYVENV_LAUNCHER__'):
1265 del os.environ["__PYVENV_LAUNCHER__"]
1266 if re.search(r'/Python(?:-32|-64)*$', py_executable):
1267 # The name of the python executable is not quite what
1268 # we want, rename it.
1269 py_executable = os.path.join(
1270 os.path.dirname(py_executable), 'python')
1271
1272 logger.notify('New %s executable in %s', expected_exe, py_executable)
1273 pcbuild_dir = os.path.dirname(sys.executable)
1274 pyd_pth = os.path.join(lib_dir, 'site-packages', 'virtualenv_builddir_pyd.pt h')
1275 if is_win and os.path.exists(os.path.join(pcbuild_dir, 'build.bat')):
1276 logger.notify('Detected python running from build directory %s', pcbuild _dir)
1277 logger.notify('Writing .pth file linking to build directory for *.pyd fi les')
1278 writefile(pyd_pth, pcbuild_dir)
1279 else:
1280 pcbuild_dir = None
1281 if os.path.exists(pyd_pth):
1282 logger.info('Deleting %s (not Windows env or not build directory pyt hon)' % pyd_pth)
1283 os.unlink(pyd_pth)
1284
1285 if sys.executable != py_executable:
1286 ## FIXME: could I just hard link?
1287 executable = sys.executable
1288 shutil.copyfile(executable, py_executable)
1289 make_exe(py_executable)
1290 if is_win or is_cygwin:
1291 pythonw = os.path.join(os.path.dirname(sys.executable), 'pythonw.exe ')
1292 if os.path.exists(pythonw):
1293 logger.info('Also created pythonw.exe')
1294 shutil.copyfile(pythonw, os.path.join(os.path.dirname(py_executa ble), 'pythonw.exe'))
1295 python_d = os.path.join(os.path.dirname(sys.executable), 'python_d.e xe')
1296 python_d_dest = os.path.join(os.path.dirname(py_executable), 'python _d.exe')
1297 if os.path.exists(python_d):
1298 logger.info('Also created python_d.exe')
1299 shutil.copyfile(python_d, python_d_dest)
1300 elif os.path.exists(python_d_dest):
1301 logger.info('Removed python_d.exe as it is no longer at the sour ce')
1302 os.unlink(python_d_dest)
1303 # we need to copy the DLL to enforce that windows will load the corr ect one.
1304 # may not exist if we are cygwin.
1305 py_executable_dll = 'python%s%s.dll' % (
1306 sys.version_info[0], sys.version_info[1])
1307 py_executable_dll_d = 'python%s%s_d.dll' % (
1308 sys.version_info[0], sys.version_info[1])
1309 pythondll = os.path.join(os.path.dirname(sys.executable), py_executa ble_dll)
1310 pythondll_d = os.path.join(os.path.dirname(sys.executable), py_execu table_dll_d)
1311 pythondll_d_dest = os.path.join(os.path.dirname(py_executable), py_e xecutable_dll_d)
1312 if os.path.exists(pythondll):
1313 logger.info('Also created %s' % py_executable_dll)
1314 shutil.copyfile(pythondll, os.path.join(os.path.dirname(py_execu table), py_executable_dll))
1315 if os.path.exists(pythondll_d):
1316 logger.info('Also created %s' % py_executable_dll_d)
1317 shutil.copyfile(pythondll_d, pythondll_d_dest)
1318 elif os.path.exists(pythondll_d_dest):
1319 logger.info('Removed %s as the source does not exist' % pythondl l_d_dest)
1320 os.unlink(pythondll_d_dest)
1321 if is_pypy:
1322 # make a symlink python --> pypy-c
1323 python_executable = os.path.join(os.path.dirname(py_executable), 'py thon')
1324 if sys.platform in ('win32', 'cygwin'):
1325 python_executable += '.exe'
1326 logger.info('Also created executable %s' % python_executable)
1327 copyfile(py_executable, python_executable, symlink)
1328
1329 if is_win:
1330 for name in ['libexpat.dll', 'libpypy.dll', 'libpypy-c.dll',
1331 'libeay32.dll', 'ssleay32.dll', 'sqlite3.dll',
1332 'tcl85.dll', 'tk85.dll']:
1333 src = join(prefix, name)
1334 if os.path.exists(src):
1335 copyfile(src, join(bin_dir, name), symlink)
1336
1337 for d in sys.path:
1338 if d.endswith('lib_pypy'):
1339 break
1340 else:
1341 logger.fatal('Could not find lib_pypy in sys.path')
1342 raise SystemExit(3)
1343 logger.info('Copying lib_pypy')
1344 copyfile(d, os.path.join(home_dir, 'lib_pypy'), symlink)
1345
1346 if os.path.splitext(os.path.basename(py_executable))[0] != expected_exe:
1347 secondary_exe = os.path.join(os.path.dirname(py_executable),
1348 expected_exe)
1349 py_executable_ext = os.path.splitext(py_executable)[1]
1350 if py_executable_ext.lower() == '.exe':
1351 # python2.4 gives an extension of '.4' :P
1352 secondary_exe += py_executable_ext
1353 if os.path.exists(secondary_exe):
1354 logger.warn('Not overwriting existing %s script %s (you must use %s) '
1355 % (expected_exe, secondary_exe, py_executable))
1356 else:
1357 logger.notify('Also creating executable in %s' % secondary_exe)
1358 shutil.copyfile(sys.executable, secondary_exe)
1359 make_exe(secondary_exe)
1360
1361 if '.framework' in prefix:
1362 if 'Python.framework' in prefix:
1363 logger.debug('MacOSX Python framework detected')
1364 # Make sure we use the embedded interpreter inside
1365 # the framework, even if sys.executable points to
1366 # the stub executable in ${sys.prefix}/bin
1367 # See http://groups.google.com/group/python-virtualenv/
1368 # browse_thread/thread/17cab2f85da75951
1369 original_python = os.path.join(
1370 prefix, 'Resources/Python.app/Contents/MacOS/Python')
1371 if 'EPD' in prefix:
1372 logger.debug('EPD framework detected')
1373 original_python = os.path.join(prefix, 'bin/python')
1374 shutil.copy(original_python, py_executable)
1375
1376 # Copy the framework's dylib into the virtual
1377 # environment
1378 virtual_lib = os.path.join(home_dir, '.Python')
1379
1380 if os.path.exists(virtual_lib):
1381 os.unlink(virtual_lib)
1382 copyfile(
1383 os.path.join(prefix, 'Python'),
1384 virtual_lib,
1385 symlink)
1386
1387 # And then change the install_name of the copied python executable
1388 try:
1389 mach_o_change(py_executable,
1390 os.path.join(prefix, 'Python'),
1391 '@executable_path/../.Python')
1392 except:
1393 e = sys.exc_info()[1]
1394 logger.warn("Could not call mach_o_change: %s. "
1395 "Trying to call install_name_tool instead." % e)
1396 try:
1397 call_subprocess(
1398 ["install_name_tool", "-change",
1399 os.path.join(prefix, 'Python'),
1400 '@executable_path/../.Python',
1401 py_executable])
1402 except:
1403 logger.fatal("Could not call install_name_tool -- you must "
1404 "have Apple's development tools installed")
1405 raise
1406
1407 if not is_win:
1408 # Ensure that 'python', 'pythonX' and 'pythonX.Y' all exist
1409 py_exe_version_major = 'python%s' % sys.version_info[0]
1410 py_exe_version_major_minor = 'python%s.%s' % (
1411 sys.version_info[0], sys.version_info[1])
1412 py_exe_no_version = 'python'
1413 required_symlinks = [ py_exe_no_version, py_exe_version_major,
1414 py_exe_version_major_minor ]
1415
1416 py_executable_base = os.path.basename(py_executable)
1417
1418 if py_executable_base in required_symlinks:
1419 # Don't try to symlink to yourself.
1420 required_symlinks.remove(py_executable_base)
1421
1422 for pth in required_symlinks:
1423 full_pth = join(bin_dir, pth)
1424 if os.path.exists(full_pth):
1425 os.unlink(full_pth)
1426 if symlink:
1427 os.symlink(py_executable_base, full_pth)
1428 else:
1429 copyfile(py_executable, full_pth, symlink)
1430
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;'
1438 'getattr(out, "buffer", out).write(sys.prefix.encode("utf-8"))']
1439 logger.info('Testing executable with %s %s "%s"' % tuple(cmd))
1440 try:
1441 proc = subprocess.Popen(cmd,
1442 stdout=subprocess.PIPE)
1443 proc_stdout, proc_stderr = proc.communicate()
1444 except OSError:
1445 e = sys.exc_info()[1]
1446 if e.errno == errno.EACCES:
1447 logger.fatal('ERROR: The executable %s could not be run: %s' % (py_e xecutable, e))
1448 sys.exit(100)
1449 else:
1450 raise e
1451
1452 proc_stdout = proc_stdout.strip().decode("utf-8")
1453 proc_stdout = os.path.normcase(os.path.abspath(proc_stdout))
1454 norm_home_dir = os.path.normcase(os.path.abspath(home_dir))
1455 if hasattr(norm_home_dir, 'decode'):
1456 norm_home_dir = norm_home_dir.decode(sys.getfilesystemencoding())
1457 if proc_stdout != norm_home_dir:
1458 logger.fatal(
1459 'ERROR: The executable %s is not functioning' % py_executable)
1460 logger.fatal(
1461 'ERROR: It thinks sys.prefix is %r (should be %r)'
1462 % (proc_stdout, norm_home_dir))
1463 logger.fatal(
1464 'ERROR: virtualenv is not compatible with this system or executable' )
1465 if is_win:
1466 logger.fatal(
1467 'Note: some Windows users have reported this error when they '
1468 'installed Python for "Only this user" or have multiple '
1469 'versions of Python installed. Copying the appropriate '
1470 'PythonXX.dll to the virtualenv Scripts/ directory may fix '
1471 'this problem.')
1472 sys.exit(100)
1473 else:
1474 logger.info('Got sys.prefix result: %r' % proc_stdout)
1475
1476 pydistutils = os.path.expanduser('~/.pydistutils.cfg')
1477 if os.path.exists(pydistutils):
1478 logger.notify('Please make sure you remove any previous custom paths fro m '
1479 'your %s file.' % pydistutils)
1480 ## FIXME: really this should be calculated earlier
1481
1482 fix_local_scheme(home_dir, symlink)
1483
1484 if site_packages:
1485 if os.path.exists(site_packages_filename):
1486 logger.info('Deleting %s' % site_packages_filename)
1487 os.unlink(site_packages_filename)
1488
1489 return py_executable
1490
1491
1492 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':
1495 files = {
1496 'activate.bat': ACTIVATE_BAT,
1497 'deactivate.bat': DEACTIVATE_BAT,
1498 'activate.ps1': ACTIVATE_PS,
1499 }
1500
1501 # MSYS needs paths of the form /c/path/to/file
1502 drive, tail = os.path.splitdrive(home_dir.replace(os.sep, '/'))
1503 home_dir_msys = (drive and "/%s%s" or "%s%s") % (drive[:1], tail)
1504
1505 # Run-time conditional enables (basic) Cygwin compatibility
1506 home_dir_sh = ("""$(if [ "$OSTYPE" "==" "cygwin" ]; then cygpath -u '%s' ; else echo '%s'; fi;)""" %
1507 (home_dir, home_dir_msys))
1508 files['activate'] = ACTIVATE_SH.replace('__VIRTUAL_ENV__', home_dir_sh)
1509
1510 else:
1511 files = {'activate': ACTIVATE_SH}
1512
1513 # suppling activate.fish in addition to, not instead of, the
1514 # bash script support.
1515 files['activate.fish'] = ACTIVATE_FISH
1516
1517 # same for csh/tcsh support...
1518 files['activate.csh'] = ACTIVATE_CSH
1519
1520 files['activate_this.py'] = ACTIVATE_THIS
1521 if hasattr(home_dir, 'decode'):
1522 home_dir = home_dir.decode(sys.getfilesystemencoding())
1523 vname = os.path.basename(home_dir)
1524 for name, content in files.items():
1525 content = content.replace('__VIRTUAL_PROMPT__', prompt or '')
1526 content = content.replace('__VIRTUAL_WINPROMPT__', prompt or '(%s)' % vn ame)
1527 content = content.replace('__VIRTUAL_ENV__', home_dir)
1528 content = content.replace('__VIRTUAL_NAME__', vname)
1529 content = content.replace('__BIN_NAME__', os.path.basename(bin_dir))
1530 writefile(os.path.join(bin_dir, name), content)
1531
1532 def install_distutils(home_dir):
1533 distutils_path = change_prefix(distutils.__path__[0], home_dir)
1534 mkdir(distutils_path)
1535 ## FIXME: maybe this prefix setting should only be put in place if
1536 ## there's a local distutils.cfg with a prefix setting?
1537 home_dir = os.path.abspath(home_dir)
1538 ## FIXME: this is breaking things, removing for now:
1539 #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
1540 writefile(os.path.join(distutils_path, '__init__.py'), DISTUTILS_INIT)
1541 writefile(os.path.join(distutils_path, 'distutils.cfg'), DISTUTILS_CFG, over write=False)
1542
1543 def fix_local_scheme(home_dir, symlink=True):
1544 """
1545 Platforms that use the "posix_local" install scheme (like Ubuntu with
1546 Python 2.7) need to be given an additional "local" location, sigh.
1547 """
1548 try:
1549 import sysconfig
1550 except ImportError:
1551 pass
1552 else:
1553 if sysconfig._get_default_scheme() == 'posix_local':
1554 local_path = os.path.join(home_dir, 'local')
1555 if not os.path.exists(local_path):
1556 os.mkdir(local_path)
1557 for subdir_name in os.listdir(home_dir):
1558 if subdir_name == 'local':
1559 continue
1560 copyfile(os.path.abspath(os.path.join(home_dir, subdir_name) ), \
1561 os.path.join(local_p ath, subdir_name), symlink)
1562
1563 def fix_lib64(lib_dir, symlink=True):
1564 """
1565 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
1567 symlink so lib64 points to lib
1568 """
1569 if [p for p in distutils.sysconfig.get_config_vars().values()
1570 if isinstance(p, basestring) and 'lib64' in p]:
1571 # PyPy's library path scheme is not affected by this.
1572 # Return early or we will die on the following assert.
1573 if is_pypy:
1574 logger.debug('PyPy detected, skipping lib64 symlinking')
1575 return
1576
1577 logger.debug('This system uses lib64; symlinking lib64 to lib')
1578
1579 assert os.path.basename(lib_dir) == 'python%s' % sys.version[:3], (
1580 "Unexpected python lib dir: %r" % lib_dir)
1581 lib_parent = os.path.dirname(lib_dir)
1582 top_level = os.path.dirname(lib_parent)
1583 lib_dir = os.path.join(top_level, 'lib')
1584 lib64_link = os.path.join(top_level, 'lib64')
1585 assert os.path.basename(lib_parent) == 'lib', (
1586 "Unexpected parent dir: %r" % lib_parent)
1587 if os.path.lexists(lib64_link):
1588 return
1589 if symlink:
1590 os.symlink('lib', lib64_link)
1591 else:
1592 copyfile('lib', lib64_link)
1593
1594 def resolve_interpreter(exe):
1595 """
1596 If the executable given isn't an absolute path, search $PATH for the interpr eter
1597 """
1598 # If the "executable" is a version number, get the installed executable for
1599 # that version
1600 python_versions = get_installed_pythons()
1601 if exe in python_versions:
1602 exe = python_versions[exe]
1603
1604 if os.path.abspath(exe) != exe:
1605 paths = os.environ.get('PATH', '').split(os.pathsep)
1606 for path in paths:
1607 if os.path.exists(os.path.join(path, exe)):
1608 exe = os.path.join(path, exe)
1609 break
1610 if not os.path.exists(exe):
1611 logger.fatal('The executable %s (from --python=%s) does not exist' % (ex e, exe))
1612 raise SystemExit(3)
1613 if not is_executable(exe):
1614 logger.fatal('The executable %s (from --python=%s) is not executable' % (exe, exe))
1615 raise SystemExit(3)
1616 return exe
1617
1618 def is_executable(exe):
1619 """Checks a file is executable"""
1620 return os.access(exe, os.X_OK)
1621
1622 ############################################################
1623 ## Relocating the environment:
1624
1625 def make_environment_relocatable(home_dir):
1626 """
1627 Makes the already-existing environment use relative paths, and takes out
1628 the #!-based environment selection in scripts.
1629 """
1630 home_dir, lib_dir, inc_dir, bin_dir = path_locations(home_dir)
1631 activate_this = os.path.join(bin_dir, 'activate_this.py')
1632 if not os.path.exists(activate_this):
1633 logger.fatal(
1634 'The environment doesn\'t have a file %s -- please re-run virtualenv '
1635 'on this environment to update it' % activate_this)
1636 fixup_scripts(home_dir, bin_dir)
1637 fixup_pth_and_egg_link(home_dir)
1638 ## FIXME: need to fix up distutils.cfg
1639
1640 OK_ABS_SCRIPTS = ['python', 'python%s' % sys.version[:3],
1641 'activate', 'activate.bat', 'activate_this.py',
1642 'activate.fish', 'activate.csh']
1643
1644 def fixup_scripts(home_dir, bin_dir):
1645 if is_win:
1646 new_shebang_args = (
1647 '%s /c' % os.path.normcase(os.environ.get('COMSPEC', 'cmd.exe')),
1648 '', '.exe')
1649 else:
1650 new_shebang_args = ('/usr/bin/env', sys.version[:3], '')
1651
1652 # This is what we expect at the top of scripts:
1653 shebang = '#!%s' % os.path.normcase(os.path.join(
1654 os.path.abspath(bin_dir), 'python%s' % new_shebang_args[2]))
1655 # This is what we'll put:
1656 new_shebang = '#!%s python%s%s' % new_shebang_args
1657
1658 for filename in os.listdir(bin_dir):
1659 filename = os.path.join(bin_dir, filename)
1660 if not os.path.isfile(filename):
1661 # ignore subdirs, e.g. .svn ones.
1662 continue
1663 f = open(filename, 'rb')
1664 try:
1665 try:
1666 lines = f.read().decode('utf-8').splitlines()
1667 except UnicodeDecodeError:
1668 # This is probably a binary program instead
1669 # of a script, so just ignore it.
1670 continue
1671 finally:
1672 f.close()
1673 if not lines:
1674 logger.warn('Script %s is an empty file' % filename)
1675 continue
1676
1677 old_shebang = lines[0].strip()
1678 old_shebang = old_shebang[0:2] + os.path.normcase(old_shebang[2:])
1679
1680 if not old_shebang.startswith(shebang):
1681 if os.path.basename(filename) in OK_ABS_SCRIPTS:
1682 logger.debug('Cannot make script %s relative' % filename)
1683 elif lines[0].strip() == new_shebang:
1684 logger.info('Script %s has already been made relative' % filenam e)
1685 else:
1686 logger.warn('Script %s cannot be made relative (it\'s not a norm al script that starts with %s)'
1687 % (filename, shebang))
1688 continue
1689 logger.notify('Making script %s relative' % filename)
1690 script = relative_script([new_shebang] + lines[1:])
1691 f = open(filename, 'wb')
1692 f.write('\n'.join(script).encode('utf-8'))
1693 f.close()
1694
1695 def relative_script(lines):
1696 "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"
1698 # Find the last future statement in the script. If we insert the activation
1699 # line before a future statement, Python will raise a SyntaxError.
1700 activate_at = None
1701 for idx, line in reversed(list(enumerate(lines))):
1702 if line.split()[:3] == ['from', '__future__', 'import']:
1703 activate_at = idx + 1
1704 break
1705 if activate_at is None:
1706 # Activate after the shebang.
1707 activate_at = 1
1708 return lines[:activate_at] + ['', activate, ''] + lines[activate_at:]
1709
1710 def fixup_pth_and_egg_link(home_dir, sys_path=None):
1711 """Makes .pth and .egg-link files use relative paths"""
1712 home_dir = os.path.normcase(os.path.abspath(home_dir))
1713 if sys_path is None:
1714 sys_path = sys.path
1715 for path in sys_path:
1716 if not path:
1717 path = '.'
1718 if not os.path.isdir(path):
1719 continue
1720 path = os.path.normcase(os.path.abspath(path))
1721 if not path.startswith(home_dir):
1722 logger.debug('Skipping system (non-environment) directory %s' % path )
1723 continue
1724 for filename in os.listdir(path):
1725 filename = os.path.join(path, filename)
1726 if filename.endswith('.pth'):
1727 if not os.access(filename, os.W_OK):
1728 logger.warn('Cannot write .pth file %s, skipping' % filename )
1729 else:
1730 fixup_pth_file(filename)
1731 if filename.endswith('.egg-link'):
1732 if not os.access(filename, os.W_OK):
1733 logger.warn('Cannot write .egg-link file %s, skipping' % fil ename)
1734 else:
1735 fixup_egg_link(filename)
1736
1737 def fixup_pth_file(filename):
1738 lines = []
1739 prev_lines = []
1740 f = open(filename)
1741 prev_lines = f.readlines()
1742 f.close()
1743 for line in prev_lines:
1744 line = line.strip()
1745 if (not line or line.startswith('#') or line.startswith('import ')
1746 or os.path.abspath(line) != line):
1747 lines.append(line)
1748 else:
1749 new_value = make_relative_path(filename, line)
1750 if line != new_value:
1751 logger.debug('Rewriting path %s as %s (in %s)' % (line, new_valu e, filename))
1752 lines.append(new_value)
1753 if lines == prev_lines:
1754 logger.info('No changes to .pth file %s' % filename)
1755 return
1756 logger.notify('Making paths in .pth file %s relative' % filename)
1757 f = open(filename, 'w')
1758 f.write('\n'.join(lines) + '\n')
1759 f.close()
1760
1761 def fixup_egg_link(filename):
1762 f = open(filename)
1763 link = f.readline().strip()
1764 f.close()
1765 if os.path.abspath(link) != link:
1766 logger.debug('Link in %s already relative' % filename)
1767 return
1768 new_link = make_relative_path(filename, link)
1769 logger.notify('Rewriting link %s in %s as %s' % (link, filename, new_link))
1770 f = open(filename, 'w')
1771 f.write(new_link)
1772 f.close()
1773
1774 def make_relative_path(source, dest, dest_is_directory=True):
1775 """
1776 Make a filename relative, where the filename is dest, and it is
1777 being referred to from the filename source.
1778
1779 >>> make_relative_path('/usr/share/something/a-file.pth',
1780 ... '/usr/share/another-place/src/Directory')
1781 '../another-place/src/Directory'
1782 >>> make_relative_path('/usr/share/something/a-file.pth',
1783 ... '/home/user/src/Directory')
1784 '../../../home/user/src/Directory'
1785 >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1786 './'
1787 """
1788 source = os.path.dirname(source)
1789 if not dest_is_directory:
1790 dest_filename = os.path.basename(dest)
1791 dest = os.path.dirname(dest)
1792 dest = os.path.normpath(os.path.abspath(dest))
1793 source = os.path.normpath(os.path.abspath(source))
1794 dest_parts = dest.strip(os.path.sep).split(os.path.sep)
1795 source_parts = source.strip(os.path.sep).split(os.path.sep)
1796 while dest_parts and source_parts and dest_parts[0] == source_parts[0]:
1797 dest_parts.pop(0)
1798 source_parts.pop(0)
1799 full_parts = ['..']*len(source_parts) + dest_parts
1800 if not dest_is_directory:
1801 full_parts.append(dest_filename)
1802 if not full_parts:
1803 # Special case for the current directory (otherwise it'd be '')
1804 return './'
1805 return os.path.sep.join(full_parts)
1806
1807
1808
1809 ############################################################
1810 ## Bootstrap script creation:
1811
1812 def create_bootstrap_script(extra_text, python_version=''):
1813 """
1814 Creates a bootstrap script, which is like this script but with
1815 extend_parser, adjust_options, and after_install hooks.
1816
1817 This returns a string that (written to disk of course) can be used
1818 as a bootstrap script with your own customizations. The script
1819 will be the standard virtualenv.py script, with your extra text
1820 added (your extra text should be Python code).
1821
1822 If you include these functions, they will be called:
1823
1824 ``extend_parser(optparse_parser)``:
1825 You can add or remove options from the parser here.
1826
1827 ``adjust_options(options, args)``:
1828 You can change options here, or change the args (if you accept
1829 different kinds of arguments, be sure you modify ``args`` so it is
1830 only ``[DEST_DIR]``).
1831
1832 ``after_install(options, home_dir)``:
1833
1834 After everything is installed, this function is called. This
1835 is probably the function you are most likely to use. An
1836 example would be::
1837
1838 def after_install(options, home_dir):
1839 subprocess.call([join(home_dir, 'bin', 'easy_install'),
1840 'MyPackage'])
1841 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1842 'setup', home_dir])
1843
1844 This example immediately installs a package, and runs a setup
1845 script from that package.
1846
1847 If you provide something like ``python_version='2.5'`` then the
1848 script will start with ``#!/usr/bin/env python2.5`` instead of
1849 ``#!/usr/bin/env python``. You can use this when the script must
1850 be run with a particular Python version.
1851 """
1852 filename = __file__
1853 if filename.endswith('.pyc'):
1854 filename = filename[:-1]
1855 f = codecs.open(filename, 'r', encoding='utf-8')
1856 content = f.read()
1857 f.close()
1858 py_exe = 'python%s' % python_version
1859 content = (('#!/usr/bin/env %s\n' % py_exe)
1860 + '## WARNING: This file is generated\n'
1861 + content)
1862 return content.replace('##EXT' 'END##', extra_text)
1863
1864 ##EXTEND##
1865
1866 def convert(s):
1867 b = base64.b64decode(s.encode('ascii'))
1868 return zlib.decompress(b).decode('utf-8')
1869
1870 ##file site.py
1871 SITE_PY = convert("""
1872 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
2012 AVijEPwfucjncQ==
2013 """)
2014
2015 ##file activate.sh
2016 ACTIVATE_SH = convert("""
2017 eJytVVFvokAQfudXTLEPtTlLeo9tvMSmJpq02hSvl7u2wRUG2QR2DSxSe7n/frOACEVNLlceRHa+
2018 nfl25pvZDswCnoDPQ4QoTRQsENIEPci4CsBMZBq7CAsuLOYqvmYKTTj3YxnBgiXBudGBjUzBZUJI
2019 BXEqgCvweIyuCjeG4eF2F5x14bcB9KQiQQWrjSddI1/oQIx6SYYeoFjzWIoIhYI1izlbhJjkKO7D
2020 M/QEmKfO9O7WeRo/zr4P7pyHwWxkwitcgwpQ5Ej96OX+PmiFwLeVjFUOrNYKaq1Nud3nR2n8nI2m
2021 k9H0friPTGVsUdptaxGrTEfpNVFEskxpXtUkkCkl1UNF9cgLBkx48J4EXyALuBtAwNYIjF5kcmUU
2022 abMKmMq1ULoiRbgsDEkTSsKSGFCJ6Z8vY/2xYiSacmtyAfCDdCNTVZoVF8vSTQOoEwSnOrngBkws
2023 MYGMBMg8/bMBLSYKS7pYEXP0PqT+ZmBT0Xuy+Pplj5yn4aM9nk72JD8/Wi+Gr98sD9eWSMOwkapD
2024 BbUv91XSvmyVkICt2tmXR4tWmrcUCsjWOpw87YidEC8i0gdTSOFhouJUNxR+4NYBG0MftoCTD9F7
2025 2rTtxG3oPwY1b2HncYwhrlmj6Wq924xtGDWqfdNxap+OYxplEurnMVo9RWks+rH8qKEtx7kZT5zJ
2026 4H7oOFclrN6uFe+d+nW2aIUsSgs/42EIPuOhXq+jEo3S6tX6w2ilNkDnIpHCWdEQhFgwj9pkk7FN
2027 l/y5eQvRSIQ5+TrL05lewxWpt/Lbhes5cJF3mLET1MGhcKCF+40tNWnUulxrpojwDo2sObdje3Bz
2028 N3QeHqf3D7OjEXMVV8LN3ZlvuzoWHqiUcNKHtwNd0IbvPGKYYM31nPKCgkUILw3KL+Y8l7aO1ArS
2029 Ad37nIU0fCj5NE5gQCuC5sOSu+UdI2NeXg/lFkQIlFpdWVaWZRfvqGiirC9o6liJ9FXGYrSY9mI1
2030 D/Ncozgn13vJvsznr7DnkJWXsyMH7e42ljdJ+aqNDF1bFnKWFLdj31xtaJYK6EXFgqmV/ymD/ROG
2031 +n8O9H8f5vsGOWXsL1+1k3g=
2032 """)
2033
2034 ##file activate.fish
2035 ACTIVATE_FISH = convert("""
2036 eJydVW2P2jgQ/s6vmAZQoVpA9/WkqqJaTou0u6x2uZVOVWWZZEKsS+yc7UDpr+84bziQbauLxEvs
2037 eXnsZ56ZIWwTYSAWKUJWGAs7hMJgBEdhEwiMKnSIsBNywUMrDtziPBYmCeBDrFUG7v8HmCTW5n8u
2038 Fu7NJJim81Bl08EQTqqAkEupLOhCgrAQCY2hTU+DQVxIiqgkRNiEBphFEKy+kd1BaFvwFOUBuIxA
2039 oy20BKtAKp3xFMo0QNtCK5mhtMEA6BmSpUELKo38TThwLfguRVNaiRgs0llnEoIR29zfstf18/bv
2040 5T17Wm7vAiiN3ONCzfbfwC3DtWXXDqHfAGX0q6z/bO82j3ebh1VwnbrduwTQbvwcRtesAfMGor/W
2041 L3fs6Xnz8LRlm9fV8/P61sM0LDNwCZjl9gSpCokJRzpryGQ5t8kNGFUt51QjOZGu0Mj35FlYlXEr
2042 yC09EVOp4lEXfF84Lz1qbhBsgl59vDedXI3rTV03xipduSgt9kLytI3XmBp3aV6MPoMQGNUU62T6
2043 uQdeefTy1Hfj10zVHg2pq8fXDoHBiOv94csfXwN49xECqWREy7pwukKfvxdMY2j23vXDPuuxxeE+
2044 JOdCOhxCE3N44B1ZeSLuZh8Mmkr2wEPAmPfKWHA2uxIRjEopdbQYjDz3BWOf14/scfmwoki1eQvX
2045 ExBdF60Mqh+Y/QcX4uiH4Amwzx79KOVFtbL63sXJbtcvy8/3q5rupmO5CnE91wBviQAhjUUegYpL
2046 vVEbpLt2/W+PklRgq5Ku6mp+rpMhhCo/lXthQTxJ2ysO4Ka0ad97S7VT/n6YXus6fzk3fLnBZW5C
2047 KDC6gSO62QDqgFqLCCtPmjegjnLeAdArtSE8VYGbAJ/aLb+vnQutFhk768E9uRbSxhCMzdgEveYw
2048 IZ5ZqFKl6+kz7UR4U+buqQZXu9SIujrAfD7f0FXpozB4Q0gwp31H9mVTZGGC4b871/wm7lvyDLu1
2049 FUyvTj/yvD66k3UPTs08x1AQQaGziOl0S1qRkPG9COtBTSTWM9NzQ4R64B+Px/l3tDzCgxv5C6Ni
2050 e+QaF9xFWrxx0V/G5uvYQOdiZzvYpQUVQSIsTr1TTghI33GnPbTA7/GCqcE3oE3GZurq4HeQXQD6
2051 32XS1ITj/qLjN72ob0hc5C9bzw8MhfmL
2052 """)
2053
2054 ##file activate.csh
2055 ACTIVATE_CSH = convert("""
2056 eJx9VG1P2zAQ/u5fcYQKNgTNPtN1WxlIQ4KCUEGaxuQ6yYVYSuzKdhqVX7+zk3bpy5YPUXL3PPfc
2057 ne98DLNCWshliVDV1kGCUFvMoJGugMjq2qQIiVSxSJ1cCofD1BYRnOVGV0CfZ0N2DD91DalQSjsw
2058 tQLpIJMGU1euvPe7QeJlkKzgWixlhnAt4aoUVsLnLBiy5NtbJWQ5THX1ZciYKKWwkOFaE04dUm6D
2059 r/zh7pq/3D7Nnid3/HEy+wFHY/gEJydg0aFaQrBFgz1c5DG1IhTs+UZgsBC2GMFBlaeH+8dZXwcW
2060 VPvCjXdlAvCfQsE7al0+07XjZvrSCUevR5dnkVeKlFYZmUztG4BdzL2u9KyLVabTU0bdfg7a0hgs
2061 cSmUg6UwUiQl2iHrcbcVGNvPCiLOe7+cRwG13z9qRGgx2z6DHjfm/Op2yqeT+xvOLzs0PTKHDz2V
2062 tkckFHoQfQRXoGJAj9el0FyJCmEMhzgMS4sB7KPOE2ExoLcSieYwDvR+cP8cg11gKkVJc2wRcm1g
2063 QhYFlXiTaTfO2ki0fQoiFM4tLuO4aZrhOzqR4dIPcWx17hphMBY+Srwh7RTyN83XOWkcSPh1Pg/k
2064 TXX/jbJTbMtUmcxZ+/bbqOsy82suFQg/BhdSOTRhMNBHlUarCpU7JzBhmkKmRejKOQzayQe6MWoa
2065 n1wqWmuh6LZAaHxcdeqIlVLhIBJdO9/kbl0It2oEXQj+eGjJOuvOIR/YGRqvFhttUB2XTvLXYN2H
2066 37CBdbW2W7j2r2+VsCn0doVWcFG1/4y1VwBjfwAyoZhD
2067 """)
2068
2069 ##file activate.bat
2070 ACTIVATE_BAT = convert("""
2071 eJx9UdEKgjAUfW6wfxjiIH+hEDKUFHSKLCMI7kNOEkIf9P9pTJ3OLJ/03HPPPed4Es9XS9qqwqgT
2072 PbGKKOdXL4aAFS7A4gvAwgijuiKlqOpGlATS2NeMLE+TjJM9RkQ+SmqAXLrBo1LLIeLdiWlD6jZt
2073 r7VNubWkndkXaxg5GO3UaOOKS6drO3luDDiO5my3iA0YAKGzPRV1ack8cOdhysI0CYzIPzjSiH5X
2074 0QcvC8Lfaj0emsVKYF2rhL5L3fCkVjV76kShi59NHwDniAHzkgDgqBcwOgTMx+gDQQqXCw==
2075 """)
2076
2077 ##file deactivate.bat
2078 DEACTIVATE_BAT = convert("""
2079 eJxzSE3OyFfIT0vj4ipOLVEI8wwKCXX0iXf1C7Pl4spMU0hJTcvMS01RiPf3cYmHyQYE+fsGhCho
2080 cCkAAUibEkTEVhWLMlUlLk6QGixStlyaeCyJDPHw9/Pw93VFsQguim4ZXAJoIUw5DhX47XUM8UCx
2081 EchHtwsohN1bILUgw61c/Vy4AJYPYm4=
2082 """)
2083
2084 ##file activate.ps1
2085 ACTIVATE_PS = convert("""
2086 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
2172 rKQDxR6N/rffXv+lROXet/9Q+l9I4D1U
2173 """)
2174
2175 ##file distutils-init.py
2176 DISTUTILS_INIT = convert("""
2177 eJytV1uL4zYUfvevOE0ottuMW9q3gVDa3aUMXXbLMlDKMBiNrSTqOJKRlMxkf33PkXyRbGe7Dw2E
2178 UXTu37lpxLFV2oIyifAncxmOL0xLIfcG+gv80x9VW6maw7o/CANSWWBwFtqeWMPlGY6qPjV8A0bB
2179 C4eKSTgZ5LRgFeyErMEeOBhbN+Ipgeizhjtnhkn7DdyjuNLPoCS0l/ayQTG0djwZC08cLXozeMss
2180 aG5EzQ0IScpnWtHSTXuxByV/QCmxE7y+eS0uxWeoheaVVfqSJHiU7Mhhi6gULbOHorshkrEnKxpT
2181 0n3A8Y8SMpuwZx6aoix3ouFlmW8gHRSkeSJ2g7hU+kiHLDaQw3bmRDaTGfTnty7gPm0FHbIBg9U9
2182 oh1kZzAFLaue2R6htPCtAda2nGlDSUJ4PZBgCJBGVcwKTAMz/vJiLD+Oin5Z5QlvDPdulC6EsiyE
2183 NFzb7McNTKJzbJqzphx92VKRFY1idenzmq3K0emRcbWBD0ryqc4NZGmKOOOX9Pz5x+/l27tP797c
2184 f/z0d+4NruGNai8uAM0bfsYaw8itFk8ny41jsfpyO+BWlpqfhcG4yxLdi/0tQqoT4a8Vby382mt8
2185 p7XSo7aWGdPBc+b6utaBmCQ7rQKQoWtAuthQCiold2KfJIPTT8xwg9blPumc+YDZC/wYGdAyHpJk
2186 vUbHbHWAp5No6pK/WhhLEWrFjUwtPEv1Agf8YmnsuXUQYkeZoHm8ogP16gt2uHoxcEMdf2C6pmbw
2187 hUMsWGhanboh4IzzmsIpWs134jVPqD/c74bZHdY69UKKSn/+KfVhxLgUlToemayLMYQOqfEC61bh
2188 cbhwaqoGUzIyZRFHPmau5juaWqwRn3mpWmoEA5nhzS5gog/5jbcFQqOZvmBasZtwYlG93k5GEiyw
2189 buHhMWLjDarEGpMGB2LFs5nIJkhp/nUmZneFaRth++lieJtHepIvKgx6PJqIlD9X2j6pG1i9x3pZ
2190 5bHuCPFiirGHeO7McvoXkz786GaKVzC9DSpnOxJdc4xm6NSVq7lNEnKdVlnpu9BNYoKX2Iq3wvgh
2191 gGEUM66kK6j4NiyoneuPLSwaCWDxczgaolEWpiMyDVDb7dNuLAbriL8ig8mmeju31oNvQdpnvEPC
2192 1vAXbWacGRVrGt/uXN/gU0CDDwgooKRrHfTBb1/s9lYZ8ZqOBU0yLvpuP6+K9hLFsvIjeNhBi0KL
2193 MlOuWRn3FRwx5oHXjl0YImUx0+gLzjGchrgzca026ETmYJzPD+IpuKzNi8AFn048Thd63OdD86M6
2194 84zE8yQm0VqXdbbgvub2pKVnS76icBGdeTHHXTKspUmr4NYo/furFLKiMdQzFjHJNcdAnMhltBJK
2195 0/IKX3DVFqvPJ2dLE7bDBkH0l/PJ29074+F0CsGYOxsb7U3myTUncYfXqnLLfa6sJybX4g+hmcjO
2196 kMRBfA1JellfRRKJcyRpxdS4rIl6FdmQCWjo/o9Qz7yKffoP4JHjOvABcRn4CZIT2RH4jnxmfpVG
2197 qgLaAvQBNfuO6X0/Ux02nb4FKx3vgP+XnkX0QW9pLy/NsXgdN24dD3LxO2Nwil7Zlc1dqtP3d7/h
2198 kzp1/+7hGBuY4pk0XD/0Ao/oTe/XGrfyM773aB7iUhgkpy+dwAMalxMP0DrBcsVw/6p25+/hobP9
2199 GBknrWExDhLJ1bwt1NcCNblaFbMKCyvmX0PeRaQ=
2200 """)
2201
2202 ##file distutils.cfg
2203 DISTUTILS_CFG = convert("""
2204 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
2205 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
2206 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
2207 """)
2208
2209 ##file activate_this.py
2210 ACTIVATE_THIS = convert("""
2211 eJyNU01v2zAMvetXEB4K21jnDOstQA4dMGCHbeihlyEIDMWmE62yJEiKE//7kXKdpEWLzYBt8evx
2212 kRSzLPs6wiEoswM8YdMpjUXcq1Dz6RZa1cSiTkJdr86GsoTRHuCotBayiWqQEYGtMCgfD1KjGYBe
2213 5a3p0cRKiEe2NtLAFikftnDco0ko/SFEVgEZ8aRCZDIPY9xbA8pE9M4jfW/B2CjiHq9zbJVZuOQq
2214 siwTIvpxKYCembPAU4Muwi/Z4zfvrZ/MXipKeB8C+qisSZYiWfjJfs+0/MFMdWn1hJcO5U7G/SLa
2215 xVx8zU6VG/PXLXvfsyyzUqjeWR8hjGE+2iCE1W1tQ82hsCJN9dzKaoexyB/uH79TnjwvxcW0ntSb
2216 yZ8jq1Z5Q1UXsyy3gf9nbjTEj7NzQMfCJa/YSmrQ+2D/BqfiOi6sclrGzvoeVivIj8rcfcmnIQRF
2217 7XCyeZI7DFe5/lhlCs5PRf5QW66VXT/NrlQ46oD/D6InkOmi3IQcbhKxAX2g4a+Xd5s3UtCtG2py
2218 m8eg6WYWqR6SL5OjKMGfSrYt/6kxxQtOpeAgj1LXBNmpE2ElmCSIy5H0zFd8gJ924HWijWhb2hRC
2219 6wNEm1QdDZtuSZcEprIUBo/XRNcbQe1OUbQ/r3hPTaPJJDNtFLu8KHV5XoNr3Eo6h6YtOKw8e8yw
2220 VF5PnJ+ts3a9/Mz38RpG/AUSzYUW
2221 """)
2222
2223 MH_MAGIC = 0xfeedface
2224 MH_CIGAM = 0xcefaedfe
2225 MH_MAGIC_64 = 0xfeedfacf
2226 MH_CIGAM_64 = 0xcffaedfe
2227 FAT_MAGIC = 0xcafebabe
2228 BIG_ENDIAN = '>'
2229 LITTLE_ENDIAN = '<'
2230 LC_LOAD_DYLIB = 0xc
2231 maxint = majver == 3 and getattr(sys, 'maxsize') or getattr(sys, 'maxint')
2232
2233
2234 class fileview(object):
2235 """
2236 A proxy for file-like objects that exposes a given view of a file.
2237 Modified from macholib.
2238 """
2239
2240 def __init__(self, fileobj, start=0, size=maxint):
2241 if isinstance(fileobj, fileview):
2242 self._fileobj = fileobj._fileobj
2243 else:
2244 self._fileobj = fileobj
2245 self._start = start
2246 self._end = start + size
2247 self._pos = 0
2248
2249 def __repr__(self):
2250 return '<fileview [%d, %d] %r>' % (
2251 self._start, self._end, self._fileobj)
2252
2253 def tell(self):
2254 return self._pos
2255
2256 def _checkwindow(self, seekto, op):
2257 if not (self._start <= seekto <= self._end):
2258 raise IOError("%s to offset %d is outside window [%d, %d]" % (
2259 op, seekto, self._start, self._end))
2260
2261 def seek(self, offset, whence=0):
2262 seekto = offset
2263 if whence == os.SEEK_SET:
2264 seekto += self._start
2265 elif whence == os.SEEK_CUR:
2266 seekto += self._start + self._pos
2267 elif whence == os.SEEK_END:
2268 seekto += self._end
2269 else:
2270 raise IOError("Invalid whence argument to seek: %r" % (whence,))
2271 self._checkwindow(seekto, 'seek')
2272 self._fileobj.seek(seekto)
2273 self._pos = seekto - self._start
2274
2275 def write(self, bytes):
2276 here = self._start + self._pos
2277 self._checkwindow(here, 'write')
2278 self._checkwindow(here + len(bytes), 'write')
2279 self._fileobj.seek(here, os.SEEK_SET)
2280 self._fileobj.write(bytes)
2281 self._pos += len(bytes)
2282
2283 def read(self, size=maxint):
2284 assert size >= 0
2285 here = self._start + self._pos
2286 self._checkwindow(here, 'read')
2287 size = min(size, self._end - here)
2288 self._fileobj.seek(here, os.SEEK_SET)
2289 bytes = self._fileobj.read(size)
2290 self._pos += len(bytes)
2291 return bytes
2292
2293
2294 def read_data(file, endian, num=1):
2295 """
2296 Read a given number of 32-bits unsigned integers from the given file
2297 with the given endianness.
2298 """
2299 res = struct.unpack(endian + 'L' * num, file.read(num * 4))
2300 if len(res) == 1:
2301 return res[0]
2302 return res
2303
2304
2305 def mach_o_change(path, what, value):
2306 """
2307 Replace a given name (what) in any LC_LOAD_DYLIB command found in
2308 the given binary with a new name (value), provided it's shorter.
2309 """
2310
2311 def do_macho(file, bits, endian):
2312 # Read Mach-O header (the magic number is assumed read by the caller)
2313 cputype, cpusubtype, filetype, ncmds, sizeofcmds, flags = read_data(file , endian, 6)
2314 # 64-bits header has one more field.
2315 if bits == 64:
2316 read_data(file, endian)
2317 # The header is followed by ncmds commands
2318 for n in range(ncmds):
2319 where = file.tell()
2320 # Read command header
2321 cmd, cmdsize = read_data(file, endian, 2)
2322 if cmd == LC_LOAD_DYLIB:
2323 # The first data field in LC_LOAD_DYLIB commands is the
2324 # offset of the name, starting from the beginning of the
2325 # command.
2326 name_offset = read_data(file, endian)
2327 file.seek(where + name_offset, os.SEEK_SET)
2328 # Read the NUL terminated string
2329 load = file.read(cmdsize - name_offset).decode()
2330 load = load[:load.index('\0')]
2331 # If the string is what is being replaced, overwrite it.
2332 if load == what:
2333 file.seek(where + name_offset, os.SEEK_SET)
2334 file.write(value.encode() + '\0'.encode())
2335 # Seek to the next command
2336 file.seek(where + cmdsize, os.SEEK_SET)
2337
2338 def do_file(file, offset=0, size=maxint):
2339 file = fileview(file, offset, size)
2340 # Read magic number
2341 magic = read_data(file, BIG_ENDIAN)
2342 if magic == FAT_MAGIC:
2343 # Fat binaries contain nfat_arch Mach-O binaries
2344 nfat_arch = read_data(file, BIG_ENDIAN)
2345 for n in range(nfat_arch):
2346 # Read arch header
2347 cputype, cpusubtype, offset, size, align = read_data(file, BIG_E NDIAN, 5)
2348 do_file(file, offset, size)
2349 elif magic == MH_MAGIC:
2350 do_macho(file, 32, BIG_ENDIAN)
2351 elif magic == MH_CIGAM:
2352 do_macho(file, 32, LITTLE_ENDIAN)
2353 elif magic == MH_MAGIC_64:
2354 do_macho(file, 64, BIG_ENDIAN)
2355 elif magic == MH_CIGAM_64:
2356 do_macho(file, 64, LITTLE_ENDIAN)
2357
2358 assert(len(what) >= len(value))
2359 do_file(open(path, 'r+b'))
2360
2361
2362 if __name__ == '__main__':
2363 main()
2364
2365 ## TODO:
2366 ## Copy python.exe.manifest
2367 ## Monkeypatch distutils.sysconfig
OLDNEW
« no previous file with comments | « bootstrap/virtualenv/tox.ini ('k') | bootstrap/virtualenv/virtualenv_embedded/activate.bat » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698