2 """Create a "virtual" Python installation
5 # If you change the version here, change it in setup.py
6 # and docs/conf.py as well.
7 virtualenv_version
= "1.6.1"
19 import distutils
.sysconfig
23 if sys
.version_info
<= (2, 3):
24 print('ERROR: %s' % sys
.exc_info()[1])
25 print('ERROR: this script requires Python 2.4 or greater; or at least the subprocess module.')
26 print('If you copy subprocess.py from a newer version of Python this script will probably work')
33 from sets
import Set
as set
40 py_version
= 'python%s.%s' % (sys
.version_info
[0], sys
.version_info
[1])
42 is_jython
= sys
.platform
.startswith('java')
43 is_pypy
= hasattr(sys
, 'pypy_version_info')
44 abiflags
= getattr(sys
, 'abiflags', '')
49 expected_exe
= 'jython'
51 expected_exe
= 'python'
54 REQUIRED_MODULES
= ['os', 'posix', 'posixpath', 'nt', 'ntpath', 'genericpath',
55 'fnmatch', 'locale', 'encodings', 'codecs',
56 'stat', 'UserDict', 'readline', 'copy_reg', 'types',
57 're', 'sre', 'sre_parse', 'sre_constants', 'sre_compile',
60 REQUIRED_FILES
= ['lib-dynload', 'config']
62 majver
, minver
= sys
.version_info
[:2]
65 REQUIRED_MODULES
.extend(['warnings', 'linecache', '_abcoll', 'abc'])
67 REQUIRED_MODULES
.extend(['_weakrefset'])
69 REQUIRED_MODULES
.extend(['sets', '__future__'])
71 # Some extra modules are needed for Python 3, but different ones
72 # for different versions.
73 REQUIRED_MODULES
.extend(['_abcoll', 'warnings', 'linecache', 'abc', 'io',
74 '_weakrefset', 'copyreg', 'tempfile', 'random',
75 '__future__', 'collections', 'keyword', 'tarfile',
76 'shutil', 'struct', 'copy'])
78 REQUIRED_FILES
[-1] = 'config-%s' % majver
80 # The whole list of 3.3 modules is reproduced below - the current
81 # uncommented ones are required for 3.3 as of now, but more may be
82 # added as 3.3 development continues.
83 REQUIRED_MODULES
.extend([
232 # these are needed to correctly display the exceptions that may happen
233 # during the bootstrap
234 REQUIRED_MODULES
.extend(['traceback', 'linecache'])
236 class Logger(object):
239 Logging object for use in command-line script. Allows ranges of
240 levels, to avoid some redundancy of displayed information.
243 DEBUG
= logging
.DEBUG
245 NOTIFY
= (logging
.INFO
+logging
.WARN
)/2
246 WARN
= WARNING
= logging
.WARN
247 ERROR
= logging
.ERROR
248 FATAL
= logging
.FATAL
250 LEVELS
= [DEBUG
, INFO
, NOTIFY
, WARN
, ERROR
, FATAL
]
252 def __init__(self
, consumers
):
253 self
.consumers
= consumers
255 self
.in_progress
= None
256 self
.in_progress_hanging
= False
258 def debug(self
, msg
, *args
, **kw
):
259 self
.log(self
.DEBUG
, msg
, *args
, **kw
)
260 def info(self
, msg
, *args
, **kw
):
261 self
.log(self
.INFO
, msg
, *args
, **kw
)
262 def notify(self
, msg
, *args
, **kw
):
263 self
.log(self
.NOTIFY
, msg
, *args
, **kw
)
264 def warn(self
, msg
, *args
, **kw
):
265 self
.log(self
.WARN
, msg
, *args
, **kw
)
266 def error(self
, msg
, *args
, **kw
):
267 self
.log(self
.WARN
, msg
, *args
, **kw
)
268 def fatal(self
, msg
, *args
, **kw
):
269 self
.log(self
.FATAL
, msg
, *args
, **kw
)
270 def log(self
, level
, msg
, *args
, **kw
):
274 "You may give positional or keyword arguments, not both")
277 for consumer_level
, consumer
in self
.consumers
:
278 if self
.level_matches(level
, consumer_level
):
279 if (self
.in_progress_hanging
280 and consumer
in (sys
.stdout
, sys
.stderr
)):
281 self
.in_progress_hanging
= False
282 sys
.stdout
.write('\n')
286 rendered
= msg
% args
289 rendered
= ' '*self
.indent
+ rendered
290 if hasattr(consumer
, 'write'):
291 consumer
.write(rendered
+'\n')
295 def start_progress(self
, msg
):
296 assert not self
.in_progress
, (
297 "Tried to start_progress(%r) while in_progress %r"
298 % (msg
, self
.in_progress
))
299 if self
.level_matches(self
.NOTIFY
, self
._stdout
_level
()):
300 sys
.stdout
.write(msg
)
302 self
.in_progress_hanging
= True
304 self
.in_progress_hanging
= False
305 self
.in_progress
= msg
307 def end_progress(self
, msg
='done.'):
308 assert self
.in_progress
, (
309 "Tried to end_progress without start_progress")
310 if self
.stdout_level_matches(self
.NOTIFY
):
311 if not self
.in_progress_hanging
:
312 # Some message has been printed out since start_progress
313 sys
.stdout
.write('...' + self
.in_progress
+ msg
+ '\n')
316 sys
.stdout
.write(msg
+ '\n')
318 self
.in_progress
= None
319 self
.in_progress_hanging
= False
321 def show_progress(self
):
322 """If we are in a progress scope, and no log messages have been
323 shown, write out another '.'"""
324 if self
.in_progress_hanging
:
325 sys
.stdout
.write('.')
328 def stdout_level_matches(self
, level
):
329 """Returns true if a message at this level will go to stdout"""
330 return self
.level_matches(level
, self
._stdout
_level
())
332 def _stdout_level(self
):
333 """Returns the level that stdout runs at"""
334 for level
, consumer
in self
.consumers
:
335 if consumer
is sys
.stdout
:
339 def level_matches(self
, level
, consumer_level
):
342 >>> l.level_matches(3, 4)
344 >>> l.level_matches(3, 2)
346 >>> l.level_matches(slice(None, 3), 3)
348 >>> l.level_matches(slice(None, 3), 2)
350 >>> l.level_matches(slice(1, 3), 1)
352 >>> l.level_matches(slice(2, 3), 1)
355 if isinstance(level
, slice):
356 start
, stop
= level
.start
, level
.stop
357 if start
is not None and start
> consumer_level
:
359 if stop
is not None or stop
<= consumer_level
:
363 return level
>= consumer_level
366 def level_for_integer(cls
, level
):
370 if level
>= len(levels
):
374 level_for_integer
= classmethod(level_for_integer
)
376 # create a silent logger just to prevent this from being undefined
377 # will be overridden with requested verbosity main() is called.
378 logger
= Logger([(Logger
.LEVELS
[-1], sys
.stdout
)])
381 if not os
.path
.exists(path
):
382 logger
.info('Creating %s', path
)
385 logger
.info('Directory %s already exists', path
)
387 def copyfileordir(src
, dest
):
388 if os
.path
.isdir(src
):
389 shutil
.copytree(src
, dest
, True)
391 shutil
.copy2(src
, dest
)
393 def copyfile(src
, dest
, symlink
=True):
394 if not os
.path
.exists(src
):
395 # Some bad symlink in the src
396 logger
.warn('Cannot find file %s (bad symlink)', src
)
398 if os
.path
.exists(dest
):
399 logger
.debug('File %s already exists', dest
)
401 if not os
.path
.exists(os
.path
.dirname(dest
)):
402 logger
.info('Creating parent directories for %s' % os
.path
.dirname(dest
))
403 os
.makedirs(os
.path
.dirname(dest
))
404 if not os
.path
.islink(src
):
405 srcpath
= os
.path
.abspath(src
)
407 srcpath
= os
.readlink(src
)
408 if symlink
and hasattr(os
, 'symlink'):
409 logger
.info('Symlinking %s', dest
)
411 os
.symlink(srcpath
, dest
)
412 except (OSError, NotImplementedError):
413 logger
.info('Symlinking failed, copying to %s', dest
)
414 copyfileordir(src
, dest
)
416 logger
.info('Copying to %s', dest
)
417 copyfileordir(src
, dest
)
419 def writefile(dest
, content
, overwrite
=True):
420 if not os
.path
.exists(dest
):
421 logger
.info('Writing %s', dest
)
423 f
.write(content
.encode('utf-8'))
432 logger
.notify('File %s exists with different content; not overwriting', dest
)
434 logger
.notify('Overwriting %s with new content', dest
)
436 f
.write(content
.encode('utf-8'))
439 logger
.info('Content %s already in place', dest
)
442 if os
.path
.exists(dir):
443 logger
.notify('Deleting tree %s', dir)
446 logger
.info('Do not need to delete %s; already gone', dir)
449 if hasattr(os
, 'chmod'):
450 oldmode
= os
.stat(fn
).st_mode
& 0xFFF # 0o7777
451 newmode
= (oldmode |
0x16D) & 0xFFF # 0o555, 0o7777
452 os
.chmod(fn
, newmode
)
453 logger
.info('Changed mode of %s to %s', fn
, oct(newmode
))
455 def _find_file(filename
, dirs
):
457 if os
.path
.exists(join(dir, filename
)):
458 return join(dir, filename
)
461 def _install_req(py_executable
, unzip
=False, distribute
=False,
462 search_dirs
=None, never_download
=False):
464 if search_dirs
is None:
465 search_dirs
= file_search_dirs()
468 setup_fn
= 'setuptools-0.6c11-py%s.egg' % sys
.version
[:3]
469 project_name
= 'setuptools'
470 bootstrap_script
= EZ_SETUP_PY
474 source
= 'distribute-0.6.16.tar.gz'
475 project_name
= 'distribute'
476 bootstrap_script
= DISTRIBUTE_SETUP_PY
478 # check if the global Python has distribute installed or plain
481 if not hasattr(pkg_resources
, '_distribute'):
482 location
= os
.path
.dirname(pkg_resources
.__file
__)
483 logger
.notify("A globally installed setuptools was found (in %s)" % location
)
484 logger
.notify("Use the --no-site-packages option to use distribute in "
489 if setup_fn
is not None:
490 setup_fn
= _find_file(setup_fn
, search_dirs
)
492 if source
is not None:
493 source
= _find_file(source
, search_dirs
)
495 if is_jython
and os
._name
== 'nt':
496 # Jython's .bat sys.executable can't handle a command line
497 # argument with newlines
498 fd
, ez_setup
= tempfile
.mkstemp('.py')
499 os
.write(fd
, bootstrap_script
)
501 cmd
= [py_executable
, ez_setup
]
503 cmd
= [py_executable
, '-c', bootstrap_script
]
505 cmd
.append('--always-unzip')
508 if logger
.stdout_level_matches(logger
.DEBUG
):
511 old_chdir
= os
.getcwd()
512 if setup_fn
is not None and os
.path
.exists(setup_fn
):
513 logger
.info('Using existing %s egg: %s' % (project_name
, setup_fn
))
515 if os
.environ
.get('PYTHONPATH'):
516 env
['PYTHONPATH'] = setup_fn
+ os
.path
.pathsep
+ os
.environ
['PYTHONPATH']
518 env
['PYTHONPATH'] = setup_fn
520 # the source is found, let's chdir
521 if source
is not None and os
.path
.exists(source
):
522 logger
.info('Using existing %s egg: %s' % (project_name
, source
))
523 os
.chdir(os
.path
.dirname(source
))
524 # in this case, we want to be sure that PYTHONPATH is unset (not
525 # just empty, really unset), else CPython tries to import the
526 # site.py that it's in virtualenv_support
527 remove_from_env
.append('PYTHONPATH')
530 logger
.fatal("Can't find any local distributions of %s to install "
531 "and --never-download is set. Either re-run virtualenv "
532 "without the --never-download option, or place a %s "
533 "distribution (%s) in one of these "
534 "locations: %r" % (project_name
, project_name
,
539 logger
.info('No %s egg found; downloading' % project_name
)
540 cmd
.extend(['--always-copy', '-U', project_name
])
541 logger
.start_progress('Installing %s...' % project_name
)
544 if project_name
== 'distribute':
545 env
['DONT_PATCH_SETUPTOOLS'] = 'true'
547 def _filter_ez_setup(line
):
548 return filter_ez_setup(line
, project_name
)
550 if not os
.access(os
.getcwd(), os
.W_OK
):
551 cwd
= tempfile
.mkdtemp()
552 if source
is not None and os
.path
.exists(source
):
553 # the current working dir is hostile, let's copy the
554 # tarball to a temp dir
555 target
= os
.path
.join(cwd
, os
.path
.split(source
)[-1])
556 shutil
.copy(source
, target
)
558 call_subprocess(cmd
, show_stdout
=False,
559 filter_stdout
=_filter_ez_setup
,
561 remove_from_env
=remove_from_env
,
565 logger
.end_progress()
566 if os
.getcwd() != old_chdir
:
568 if is_jython
and os
._name
== 'nt':
571 def file_search_dirs():
572 here
= os
.path
.dirname(os
.path
.abspath(__file__
))
574 join(here
, 'virtualenv_support')]
575 if os
.path
.splitext(os
.path
.dirname(__file__
))[0] != 'virtualenv':
576 # Probably some boot script; just in case virtualenv is installed...
582 dirs
.append(os
.path
.join(os
.path
.dirname(virtualenv
.__file
__), 'virtualenv_support'))
583 return [d
for d
in dirs
if os
.path
.isdir(d
)]
585 def install_setuptools(py_executable
, unzip
=False,
586 search_dirs
=None, never_download
=False):
587 _install_req(py_executable
, unzip
,
588 search_dirs
=search_dirs
, never_download
=never_download
)
590 def install_distribute(py_executable
, unzip
=False,
591 search_dirs
=None, never_download
=False):
592 _install_req(py_executable
, unzip
, distribute
=True,
593 search_dirs
=search_dirs
, never_download
=never_download
)
595 _pip_re
= re
.compile(r
'^pip-.*(zip|tar.gz|tar.bz2|tgz|tbz)$', re
.I
)
596 def install_pip(py_executable
, search_dirs
=None, never_download
=False):
597 if search_dirs
is None:
598 search_dirs
= file_search_dirs()
601 for dir in search_dirs
:
602 filenames
.extend([join(dir, fn
) for fn
in os
.listdir(dir)
603 if _pip_re
.search(fn
)])
604 filenames
= [(os
.path
.basename(filename
).lower(), i
, filename
) for i
, filename
in enumerate(filenames
)]
606 filenames
= [filename
for basename
, i
, filename
in filenames
]
610 filename
= filenames
[-1]
611 easy_install_script
= 'easy_install'
612 if sys
.platform
== 'win32':
613 easy_install_script
= 'easy_install-script.py'
614 cmd
= [py_executable
, join(os
.path
.dirname(py_executable
), easy_install_script
), filename
]
615 if filename
== 'pip':
617 logger
.fatal("Can't find any local distributions of pip to install "
618 "and --never-download is set. Either re-run virtualenv "
619 "without the --never-download option, or place a pip "
620 "source distribution (zip/tar.gz/tar.bz2) in one of these "
621 "locations: %r" % search_dirs
)
623 logger
.info('Installing pip from network...')
625 logger
.info('Installing existing %s distribution: %s' % (
626 os
.path
.basename(filename
), filename
))
627 logger
.start_progress('Installing pip...')
629 def _filter_setup(line
):
630 return filter_ez_setup(line
, 'pip')
632 call_subprocess(cmd
, show_stdout
=False,
633 filter_stdout
=_filter_setup
)
636 logger
.end_progress()
638 def filter_ez_setup(line
, project_name
='setuptools'):
641 if project_name
== 'distribute':
642 for prefix
in ('Extracting', 'Now working', 'Installing', 'Before',
643 'Scanning', 'Setuptools', 'Egg', 'Already',
644 'running', 'writing', 'reading', 'installing',
645 'creating', 'copying', 'byte-compiling', 'removing',
647 if line
.startswith(prefix
):
650 for prefix
in ['Reading ', 'Best match', 'Processing setuptools',
651 'Copying setuptools', 'Adding setuptools',
652 'Installing ', 'Installed ']:
653 if line
.startswith(prefix
):
658 parser
= optparse
.OptionParser(
659 version
=virtualenv_version
,
660 usage
="%prog [OPTIONS] DEST_DIR")
667 help="Increase verbosity")
674 help='Decrease verbosity')
679 metavar
='PYTHON_EXE',
680 help='The Python interpreter to use, e.g., --python=python2.5 will use the python2.5 '
681 'interpreter to create the new environment. The default is the interpreter that '
682 'virtualenv was installed with (%s)' % sys
.executable
)
688 help="Clear out the non-root install and start from scratch")
691 '--no-site-packages',
692 dest
='no_site_packages',
694 help="Don't give access to the global site-packages dir to the "
695 "virtual environment")
698 '--unzip-setuptools',
699 dest
='unzip_setuptools',
701 help="Unzip Setuptools or Distribute when installing it")
707 help='Make an EXISTING virtualenv environment relocatable. '
708 'This fixes up scripts and makes all .pth files relative')
712 dest
='use_distribute',
714 help='Use Distribute instead of Setuptools. Set environ variable '
715 'VIRTUALENV_USE_DISTRIBUTE to make it the default ')
717 default_search_dirs
= file_search_dirs()
719 '--extra-search-dir',
722 default
=default_search_dirs
,
723 help="Directory to look for setuptools/distribute/pip distributions in. "
724 "You can add any number of additional --extra-search-dir paths.")
728 dest
="never_download",
730 help="Never download anything from the network. Instead, virtualenv will fail "
731 "if local distributions of setuptools/distribute/pip are not present.")
736 help='Provides an alternative prompt prefix for this environment')
738 if 'extend_parser' in globals():
739 extend_parser(parser
)
741 options
, args
= parser
.parse_args()
745 if 'adjust_options' in globals():
746 adjust_options(options
, args
)
748 verbosity
= options
.verbose
- options
.quiet
749 logger
= Logger([(Logger
.level_for_integer(2-verbosity
), sys
.stdout
)])
751 if options
.python
and not os
.environ
.get('VIRTUALENV_INTERPRETER_RUNNING'):
752 env
= os
.environ
.copy()
753 interpreter
= resolve_interpreter(options
.python
)
754 if interpreter
== sys
.executable
:
755 logger
.warn('Already using interpreter %s' % interpreter
)
757 logger
.notify('Running virtualenv with interpreter %s' % interpreter
)
758 env
['VIRTUALENV_INTERPRETER_RUNNING'] = 'true'
760 if file.endswith('.pyc'):
762 popen
= subprocess
.Popen([interpreter
, file] + sys
.argv
[1:], env
=env
)
763 raise SystemExit(popen
.wait())
766 print('You must provide a DEST_DIR')
770 print('There must be only one argument: DEST_DIR (you gave %s)' % (
777 if os
.environ
.get('WORKING_ENV'):
778 logger
.fatal('ERROR: you cannot run virtualenv while in a workingenv')
779 logger
.fatal('Please deactivate your workingenv, then re-run this script')
782 if 'PYTHONHOME' in os
.environ
:
783 logger
.warn('PYTHONHOME is set. You *must* activate the virtualenv before using it')
784 del os
.environ
['PYTHONHOME']
786 if options
.relocatable
:
787 make_environment_relocatable(home_dir
)
790 create_environment(home_dir
, site_packages
=not options
.no_site_packages
, clear
=options
.clear
,
791 unzip_setuptools
=options
.unzip_setuptools
,
792 use_distribute
=options
.use_distribute
or majver
> 2,
793 prompt
=options
.prompt
,
794 search_dirs
=options
.search_dirs
,
795 never_download
=options
.never_download
)
796 if 'after_install' in globals():
797 after_install(options
, home_dir
)
799 def call_subprocess(cmd
, show_stdout
=True,
800 filter_stdout
=None, cwd
=None,
801 raise_on_returncode
=True, extra_env
=None,
802 remove_from_env
=None):
806 part
= part
[:20]+"..."+part
[-20:]
807 if ' ' in part
or '\n' in part
or '"' in part
or "'" in part
:
808 part
= '"%s"' % part
.replace('"', '\\"')
809 cmd_parts
.append(part
)
810 cmd_desc
= ' '.join(cmd_parts
)
814 stdout
= subprocess
.PIPE
815 logger
.debug("Running command %s" % cmd_desc
)
816 if extra_env
or remove_from_env
:
817 env
= os
.environ
.copy()
819 env
.update(extra_env
)
821 for varname
in remove_from_env
:
822 env
.pop(varname
, None)
826 proc
= subprocess
.Popen(
827 cmd
, stderr
=subprocess
.STDOUT
, stdin
=None, stdout
=stdout
,
830 e
= sys
.exc_info()[1]
832 "Error %s while executing command %s" % (e
, cmd_desc
))
835 if stdout
is not None:
837 encoding
= sys
.getdefaultencoding()
839 line
= stdout
.readline().decode(encoding
)
843 all_output
.append(line
)
845 level
= filter_stdout(line
)
846 if isinstance(level
, tuple):
848 logger
.log(level
, line
)
849 if not logger
.stdout_level_matches(level
):
850 logger
.show_progress()
857 if raise_on_returncode
:
859 logger
.notify('Complete output from command %s:' % cmd_desc
)
860 logger
.notify('\n'.join(all_output
) + '\n----------------------------------------')
862 "Command %s failed with error code %s"
863 % (cmd_desc
, proc
.returncode
))
866 "Command %s had error code %s"
867 % (cmd_desc
, proc
.returncode
))
870 def create_environment(home_dir
, site_packages
=True, clear
=False,
871 unzip_setuptools
=False, use_distribute
=False,
872 prompt
=None, search_dirs
=None, never_download
=False):
874 Creates a new environment in ``home_dir``.
876 If ``site_packages`` is true (the default) then the global
877 ``site-packages/`` directory will be on the path.
879 If ``clear`` is true (default False) then the environment will
882 home_dir
, lib_dir
, inc_dir
, bin_dir
= path_locations(home_dir
)
884 py_executable
= os
.path
.abspath(install_python(
885 home_dir
, lib_dir
, inc_dir
, bin_dir
,
886 site_packages
=site_packages
, clear
=clear
))
888 install_distutils(home_dir
)
890 if use_distribute
or os
.environ
.get('VIRTUALENV_USE_DISTRIBUTE'):
891 install_distribute(py_executable
, unzip
=unzip_setuptools
,
892 search_dirs
=search_dirs
, never_download
=never_download
)
894 install_setuptools(py_executable
, unzip
=unzip_setuptools
,
895 search_dirs
=search_dirs
, never_download
=never_download
)
897 install_pip(py_executable
, search_dirs
=search_dirs
, never_download
=never_download
)
899 install_activate(home_dir
, bin_dir
, prompt
)
901 def path_locations(home_dir
):
902 """Return the path locations for the environment (where libraries are,
903 where scripts go, etc)"""
904 # XXX: We'd use distutils.sysconfig.get_python_inc/lib but its
905 # prefix arg is broken: http://bugs.python.org/issue3386
906 if sys
.platform
== 'win32':
907 # Windows has lots of problems with executables with spaces in
908 # the name; this function will remove them (using the ~1
915 print('Error: the path "%s" has a space in it' % home_dir
)
916 print('To handle these kinds of paths, the win32api module must be installed:')
917 print(' http://sourceforge.net/projects/pywin32/')
919 home_dir
= win32api
.GetShortPathName(home_dir
)
920 lib_dir
= join(home_dir
, 'Lib')
921 inc_dir
= join(home_dir
, 'Include')
922 bin_dir
= join(home_dir
, 'Scripts')
924 lib_dir
= join(home_dir
, 'Lib')
925 inc_dir
= join(home_dir
, 'Include')
926 bin_dir
= join(home_dir
, 'bin')
929 inc_dir
= join(home_dir
, 'include')
930 bin_dir
= join(home_dir
, 'bin')
932 lib_dir
= join(home_dir
, 'lib', py_version
)
933 inc_dir
= join(home_dir
, 'include', py_version
+ abiflags
)
934 bin_dir
= join(home_dir
, 'bin')
935 return home_dir
, lib_dir
, inc_dir
, bin_dir
938 def change_prefix(filename
, dst_prefix
):
939 prefixes
= [sys
.prefix
]
941 if sys
.platform
== "darwin":
943 os
.path
.join("/Library/Python", sys
.version
[:3], "site-packages"),
944 os
.path
.join(sys
.prefix
, "Extras", "lib", "python"),
945 os
.path
.join("~", "Library", "Python", sys
.version
[:3], "site-packages")))
947 if hasattr(sys
, 'real_prefix'):
948 prefixes
.append(sys
.real_prefix
)
949 prefixes
= list(map(os
.path
.abspath
, prefixes
))
950 filename
= os
.path
.abspath(filename
)
951 for src_prefix
in prefixes
:
952 if filename
.startswith(src_prefix
):
953 _
, relpath
= filename
.split(src_prefix
, 1)
954 assert relpath
[0] == os
.sep
955 relpath
= relpath
[1:]
956 return join(dst_prefix
, relpath
)
957 assert False, "Filename %s does not start with any of these prefixes: %s" % \
960 def copy_required_modules(dst_prefix
):
962 for modname
in REQUIRED_MODULES
:
963 if modname
in sys
.builtin_module_names
:
964 logger
.info("Ignoring built-in bootstrap module: %s" % modname
)
967 f
, filename
, _
= imp
.find_module(modname
)
969 logger
.info("Cannot import bootstrap module: %s" % modname
)
973 dst_filename
= change_prefix(filename
, dst_prefix
)
974 copyfile(filename
, dst_filename
)
975 if filename
.endswith('.pyc'):
976 pyfile
= filename
[:-1]
977 if os
.path
.exists(pyfile
):
978 copyfile(pyfile
, dst_filename
[:-1])
981 def install_python(home_dir
, lib_dir
, inc_dir
, bin_dir
, site_packages
, clear
):
982 """Install just the base environment, no distutils patches etc"""
983 if sys
.executable
.startswith(bin_dir
):
984 print('Please use the *system* python to run this script')
989 ## FIXME: why not delete it?
990 ## Maybe it should delete everything with #!/path/to/venv/python in it
991 logger
.notify('Not deleting %s', bin_dir
)
993 if hasattr(sys
, 'real_prefix'):
994 logger
.notify('Using real prefix %r' % sys
.real_prefix
)
995 prefix
= sys
.real_prefix
1000 stdlib_dirs
= [os
.path
.dirname(os
.__file
__)]
1001 if sys
.platform
== 'win32':
1002 stdlib_dirs
.append(join(os
.path
.dirname(stdlib_dirs
[0]), 'DLLs'))
1003 elif sys
.platform
== 'darwin':
1004 stdlib_dirs
.append(join(stdlib_dirs
[0], 'site-packages'))
1005 if hasattr(os
, 'symlink'):
1006 logger
.info('Symlinking Python bootstrap modules')
1008 logger
.info('Copying Python bootstrap modules')
1011 # copy required files...
1012 for stdlib_dir
in stdlib_dirs
:
1013 if not os
.path
.isdir(stdlib_dir
):
1015 for fn
in os
.listdir(stdlib_dir
):
1016 bn
= os
.path
.splitext(fn
)[0]
1017 if fn
!= 'site-packages' and bn
in REQUIRED_FILES
:
1018 copyfile(join(stdlib_dir
, fn
), join(lib_dir
, fn
))
1020 copy_required_modules(home_dir
)
1023 mkdir(join(lib_dir
, 'site-packages'))
1025 site_filename
= site
.__file
__
1026 if site_filename
.endswith('.pyc'):
1027 site_filename
= site_filename
[:-1]
1028 elif site_filename
.endswith('$py.class'):
1029 site_filename
= site_filename
.replace('$py.class', '.py')
1030 site_filename_dst
= change_prefix(site_filename
, home_dir
)
1031 site_dir
= os
.path
.dirname(site_filename_dst
)
1032 writefile(site_filename_dst
, SITE_PY
)
1033 writefile(join(site_dir
, 'orig-prefix.txt'), prefix
)
1034 site_packages_filename
= join(site_dir
, 'no-global-site-packages.txt')
1035 if not site_packages
:
1036 writefile(site_packages_filename
, '')
1038 if os
.path
.exists(site_packages_filename
):
1039 logger
.info('Deleting %s' % site_packages_filename
)
1040 os
.unlink(site_packages_filename
)
1043 stdinc_dir
= join(prefix
, 'include')
1045 stdinc_dir
= join(prefix
, 'include', py_version
+ abiflags
)
1046 if os
.path
.exists(stdinc_dir
):
1047 copyfile(stdinc_dir
, inc_dir
)
1049 logger
.debug('No include dir %s' % stdinc_dir
)
1051 # pypy never uses exec_prefix, just ignore it
1052 if sys
.exec_prefix
!= prefix
and not is_pypy
:
1053 if sys
.platform
== 'win32':
1054 exec_dir
= join(sys
.exec_prefix
, 'lib')
1056 exec_dir
= join(sys
.exec_prefix
, 'Lib')
1058 exec_dir
= join(sys
.exec_prefix
, 'lib', py_version
)
1059 for fn
in os
.listdir(exec_dir
):
1060 copyfile(join(exec_dir
, fn
), join(lib_dir
, fn
))
1063 # Jython has either jython-dev.jar and javalib/ dir, or just
1065 for name
in 'jython-dev.jar', 'javalib', 'jython.jar':
1066 src
= join(prefix
, name
)
1067 if os
.path
.exists(src
):
1068 copyfile(src
, join(home_dir
, name
))
1069 # XXX: registry should always exist after Jython 2.5rc1
1070 src
= join(prefix
, 'registry')
1071 if os
.path
.exists(src
):
1072 copyfile(src
, join(home_dir
, 'registry'), symlink
=False)
1073 copyfile(join(prefix
, 'cachedir'), join(home_dir
, 'cachedir'),
1077 py_executable
= join(bin_dir
, os
.path
.basename(sys
.executable
))
1078 if 'Python.framework' in prefix
:
1079 if re
.search(r
'/Python(?:-32|-64)*$', py_executable
):
1080 # The name of the python executable is not quite what
1081 # we want, rename it.
1082 py_executable
= os
.path
.join(
1083 os
.path
.dirname(py_executable
), 'python')
1085 logger
.notify('New %s executable in %s', expected_exe
, py_executable
)
1086 if sys
.executable
!= py_executable
:
1087 ## FIXME: could I just hard link?
1088 executable
= sys
.executable
1089 if sys
.platform
== 'cygwin' and os
.path
.exists(executable
+ '.exe'):
1090 # Cygwin misreports sys.executable sometimes
1091 executable
+= '.exe'
1092 py_executable
+= '.exe'
1093 logger
.info('Executable actually exists in %s' % executable
)
1094 shutil
.copyfile(executable
, py_executable
)
1095 make_exe(py_executable
)
1096 if sys
.platform
== 'win32' or sys
.platform
== 'cygwin':
1097 pythonw
= os
.path
.join(os
.path
.dirname(sys
.executable
), 'pythonw.exe')
1098 if os
.path
.exists(pythonw
):
1099 logger
.info('Also created pythonw.exe')
1100 shutil
.copyfile(pythonw
, os
.path
.join(os
.path
.dirname(py_executable
), 'pythonw.exe'))
1102 # make a symlink python --> pypy-c
1103 python_executable
= os
.path
.join(os
.path
.dirname(py_executable
), 'python')
1104 logger
.info('Also created executable %s' % python_executable
)
1105 copyfile(py_executable
, python_executable
)
1107 if os
.path
.splitext(os
.path
.basename(py_executable
))[0] != expected_exe
:
1108 secondary_exe
= os
.path
.join(os
.path
.dirname(py_executable
),
1110 py_executable_ext
= os
.path
.splitext(py_executable
)[1]
1111 if py_executable_ext
== '.exe':
1112 # python2.4 gives an extension of '.4' :P
1113 secondary_exe
+= py_executable_ext
1114 if os
.path
.exists(secondary_exe
):
1115 logger
.warn('Not overwriting existing %s script %s (you must use %s)'
1116 % (expected_exe
, secondary_exe
, py_executable
))
1118 logger
.notify('Also creating executable in %s' % secondary_exe
)
1119 shutil
.copyfile(sys
.executable
, secondary_exe
)
1120 make_exe(secondary_exe
)
1122 if 'Python.framework' in prefix
:
1123 logger
.debug('MacOSX Python framework detected')
1125 # Make sure we use the the embedded interpreter inside
1126 # the framework, even if sys.executable points to
1127 # the stub executable in ${sys.prefix}/bin
1128 # See http://groups.google.com/group/python-virtualenv/
1129 # browse_thread/thread/17cab2f85da75951
1130 original_python
= os
.path
.join(
1131 prefix
, 'Resources/Python.app/Contents/MacOS/Python')
1132 shutil
.copy(original_python
, py_executable
)
1134 # Copy the framework's dylib into the virtual
1136 virtual_lib
= os
.path
.join(home_dir
, '.Python')
1138 if os
.path
.exists(virtual_lib
):
1139 os
.unlink(virtual_lib
)
1141 os
.path
.join(prefix
, 'Python'),
1144 # And then change the install_name of the copied python executable
1147 ["install_name_tool", "-change",
1148 os
.path
.join(prefix
, 'Python'),
1149 '@executable_path/../.Python',
1153 "Could not call install_name_tool -- you must have Apple's development tools installed")
1156 # Some tools depend on pythonX.Y being present
1157 py_executable_version
= '%s.%s' % (
1158 sys
.version_info
[0], sys
.version_info
[1])
1159 if not py_executable
.endswith(py_executable_version
):
1160 # symlinking pythonX.Y > python
1161 pth
= py_executable
+ '%s.%s' % (
1162 sys
.version_info
[0], sys
.version_info
[1])
1163 if os
.path
.exists(pth
):
1165 os
.symlink('python', pth
)
1167 # reverse symlinking python -> pythonX.Y (with --python)
1168 pth
= join(bin_dir
, 'python')
1169 if os
.path
.exists(pth
):
1171 os
.symlink(os
.path
.basename(py_executable
), pth
)
1173 if sys
.platform
== 'win32' and ' ' in py_executable
:
1174 # There's a bug with subprocess on Windows when using a first
1175 # argument that has a space in it. Instead we have to quote
1177 py_executable
= '"%s"' % py_executable
1178 cmd
= [py_executable
, '-c', 'import sys; print(sys.prefix)']
1179 logger
.info('Testing executable with %s %s "%s"' % tuple(cmd
))
1181 proc
= subprocess
.Popen(cmd
,
1182 stdout
=subprocess
.PIPE
)
1183 proc_stdout
, proc_stderr
= proc
.communicate()
1185 e
= sys
.exc_info()[1]
1186 if e
.errno
== errno
.EACCES
:
1187 logger
.fatal('ERROR: The executable %s could not be run: %s' % (py_executable
, e
))
1192 proc_stdout
= proc_stdout
.strip().decode(sys
.getdefaultencoding())
1193 proc_stdout
= os
.path
.normcase(os
.path
.abspath(proc_stdout
))
1194 if proc_stdout
!= os
.path
.normcase(os
.path
.abspath(home_dir
)):
1196 'ERROR: The executable %s is not functioning' % py_executable
)
1198 'ERROR: It thinks sys.prefix is %r (should be %r)'
1199 % (proc_stdout
, os
.path
.normcase(os
.path
.abspath(home_dir
))))
1201 'ERROR: virtualenv is not compatible with this system or executable')
1202 if sys
.platform
== 'win32':
1204 'Note: some Windows users have reported this error when they installed Python for "Only this user". The problem may be resolvable if you install Python "For all users". (See https://bugs.launchpad.net/virtualenv/+bug/352844)')
1207 logger
.info('Got sys.prefix result: %r' % proc_stdout
)
1209 pydistutils
= os
.path
.expanduser('~/.pydistutils.cfg')
1210 if os
.path
.exists(pydistutils
):
1211 logger
.notify('Please make sure you remove any previous custom paths from '
1212 'your %s file.' % pydistutils
)
1213 ## FIXME: really this should be calculated earlier
1214 return py_executable
1216 def install_activate(home_dir
, bin_dir
, prompt
=None):
1217 if sys
.platform
== 'win32' or is_jython
and os
._name
== 'nt':
1218 files
= {'activate.bat': ACTIVATE_BAT
,
1219 'deactivate.bat': DEACTIVATE_BAT
}
1220 if os
.environ
.get('OS') == 'Windows_NT' and os
.environ
.get('OSTYPE') == 'cygwin':
1221 files
['activate'] = ACTIVATE_SH
1223 files
= {'activate': ACTIVATE_SH
}
1225 # suppling activate.fish in addition to, not instead of, the
1226 # bash script support.
1227 files
['activate.fish'] = ACTIVATE_FISH
1229 # same for csh/tcsh support...
1230 files
['activate.csh'] = ACTIVATE_CSH
1234 files
['activate_this.py'] = ACTIVATE_THIS
1235 vname
= os
.path
.basename(os
.path
.abspath(home_dir
))
1236 for name
, content
in files
.items():
1237 content
= content
.replace('__VIRTUAL_PROMPT__', prompt
or '')
1238 content
= content
.replace('__VIRTUAL_WINPROMPT__', prompt
or '(%s)' % vname
)
1239 content
= content
.replace('__VIRTUAL_ENV__', os
.path
.abspath(home_dir
))
1240 content
= content
.replace('__VIRTUAL_NAME__', vname
)
1241 content
= content
.replace('__BIN_NAME__', os
.path
.basename(bin_dir
))
1242 writefile(os
.path
.join(bin_dir
, name
), content
)
1244 def install_distutils(home_dir
):
1245 distutils_path
= change_prefix(distutils
.__path
__[0], home_dir
)
1246 mkdir(distutils_path
)
1247 ## FIXME: maybe this prefix setting should only be put in place if
1248 ## there's a local distutils.cfg with a prefix setting?
1249 home_dir
= os
.path
.abspath(home_dir
)
1250 ## FIXME: this is breaking things, removing for now:
1251 #distutils_cfg = DISTUTILS_CFG + "\n[install]\nprefix=%s\n" % home_dir
1252 writefile(os
.path
.join(distutils_path
, '__init__.py'), DISTUTILS_INIT
)
1253 writefile(os
.path
.join(distutils_path
, 'distutils.cfg'), DISTUTILS_CFG
, overwrite
=False)
1255 def fix_lib64(lib_dir
):
1257 Some platforms (particularly Gentoo on x64) put things in lib64/pythonX.Y
1258 instead of lib/pythonX.Y. If this is such a platform we'll just create a
1259 symlink so lib64 points to lib
1261 if [p
for p
in distutils
.sysconfig
.get_config_vars().values()
1262 if isinstance(p
, basestring
) and 'lib64' in p
]:
1263 logger
.debug('This system uses lib64; symlinking lib64 to lib')
1264 assert os
.path
.basename(lib_dir
) == 'python%s' % sys
.version
[:3], (
1265 "Unexpected python lib dir: %r" % lib_dir
)
1266 lib_parent
= os
.path
.dirname(lib_dir
)
1267 assert os
.path
.basename(lib_parent
) == 'lib', (
1268 "Unexpected parent dir: %r" % lib_parent
)
1269 copyfile(lib_parent
, os
.path
.join(os
.path
.dirname(lib_parent
), 'lib64'))
1271 def resolve_interpreter(exe
):
1273 If the executable given isn't an absolute path, search $PATH for the interpreter
1275 if os
.path
.abspath(exe
) != exe
:
1276 paths
= os
.environ
.get('PATH', '').split(os
.pathsep
)
1278 if os
.path
.exists(os
.path
.join(path
, exe
)):
1279 exe
= os
.path
.join(path
, exe
)
1281 if not os
.path
.exists(exe
):
1282 logger
.fatal('The executable %s (from --python=%s) does not exist' % (exe
, exe
))
1284 if not is_executable(exe
):
1285 logger
.fatal('The executable %s (from --python=%s) is not executable' % (exe
, exe
))
1289 def is_executable(exe
):
1290 """Checks a file is executable"""
1291 return os
.access(exe
, os
.X_OK
)
1293 ############################################################
1294 ## Relocating the environment:
1296 def make_environment_relocatable(home_dir
):
1298 Makes the already-existing environment use relative paths, and takes out
1299 the #!-based environment selection in scripts.
1301 home_dir
, lib_dir
, inc_dir
, bin_dir
= path_locations(home_dir
)
1302 activate_this
= os
.path
.join(bin_dir
, 'activate_this.py')
1303 if not os
.path
.exists(activate_this
):
1305 'The environment doesn\'t have a file %s -- please re-run virtualenv '
1306 'on this environment to update it' % activate_this
)
1307 fixup_scripts(home_dir
)
1308 fixup_pth_and_egg_link(home_dir
)
1309 ## FIXME: need to fix up distutils.cfg
1311 OK_ABS_SCRIPTS
= ['python', 'python%s' % sys
.version
[:3],
1312 'activate', 'activate.bat', 'activate_this.py']
1314 def fixup_scripts(home_dir
):
1315 # This is what we expect at the top of scripts:
1316 shebang
= '#!%s/bin/python' % os
.path
.normcase(os
.path
.abspath(home_dir
))
1317 # This is what we'll put:
1318 new_shebang
= '#!/usr/bin/env python%s' % sys
.version
[:3]
1319 activate
= "import os; activate_this=os.path.join(os.path.dirname(__file__), 'activate_this.py'); execfile(activate_this, dict(__file__=activate_this)); del os, activate_this"
1320 if sys
.platform
== 'win32':
1321 bin_suffix
= 'Scripts'
1324 bin_dir
= os
.path
.join(home_dir
, bin_suffix
)
1325 home_dir
, lib_dir
, inc_dir
, bin_dir
= path_locations(home_dir
)
1326 for filename
in os
.listdir(bin_dir
):
1327 filename
= os
.path
.join(bin_dir
, filename
)
1328 if not os
.path
.isfile(filename
):
1329 # ignore subdirs, e.g. .svn ones.
1331 f
= open(filename
, 'rb')
1332 lines
= f
.readlines()
1335 logger
.warn('Script %s is an empty file' % filename
)
1337 if not lines
[0].strip().startswith(shebang
):
1338 if os
.path
.basename(filename
) in OK_ABS_SCRIPTS
:
1339 logger
.debug('Cannot make script %s relative' % filename
)
1340 elif lines
[0].strip() == new_shebang
:
1341 logger
.info('Script %s has already been made relative' % filename
)
1343 logger
.warn('Script %s cannot be made relative (it\'s not a normal script that starts with %s)'
1344 % (filename
, shebang
))
1346 logger
.notify('Making script %s relative' % filename
)
1347 lines
= [new_shebang
+'\n', activate
+'\n'] + lines
[1:]
1348 f
= open(filename
, 'wb')
1352 def fixup_pth_and_egg_link(home_dir
, sys_path
=None):
1353 """Makes .pth and .egg-link files use relative paths"""
1354 home_dir
= os
.path
.normcase(os
.path
.abspath(home_dir
))
1355 if sys_path
is None:
1357 for path
in sys_path
:
1360 if not os
.path
.isdir(path
):
1362 path
= os
.path
.normcase(os
.path
.abspath(path
))
1363 if not path
.startswith(home_dir
):
1364 logger
.debug('Skipping system (non-environment) directory %s' % path
)
1366 for filename
in os
.listdir(path
):
1367 filename
= os
.path
.join(path
, filename
)
1368 if filename
.endswith('.pth'):
1369 if not os
.access(filename
, os
.W_OK
):
1370 logger
.warn('Cannot write .pth file %s, skipping' % filename
)
1372 fixup_pth_file(filename
)
1373 if filename
.endswith('.egg-link'):
1374 if not os
.access(filename
, os
.W_OK
):
1375 logger
.warn('Cannot write .egg-link file %s, skipping' % filename
)
1377 fixup_egg_link(filename
)
1379 def fixup_pth_file(filename
):
1383 prev_lines
= f
.readlines()
1385 for line
in prev_lines
:
1387 if (not line
or line
.startswith('#') or line
.startswith('import ')
1388 or os
.path
.abspath(line
) != line
):
1391 new_value
= make_relative_path(filename
, line
)
1392 if line
!= new_value
:
1393 logger
.debug('Rewriting path %s as %s (in %s)' % (line
, new_value
, filename
))
1394 lines
.append(new_value
)
1395 if lines
== prev_lines
:
1396 logger
.info('No changes to .pth file %s' % filename
)
1398 logger
.notify('Making paths in .pth file %s relative' % filename
)
1399 f
= open(filename
, 'w')
1400 f
.write('\n'.join(lines
) + '\n')
1403 def fixup_egg_link(filename
):
1405 link
= f
.read().strip()
1407 if os
.path
.abspath(link
) != link
:
1408 logger
.debug('Link in %s already relative' % filename
)
1410 new_link
= make_relative_path(filename
, link
)
1411 logger
.notify('Rewriting link %s in %s as %s' % (link
, filename
, new_link
))
1412 f
= open(filename
, 'w')
1416 def make_relative_path(source
, dest
, dest_is_directory
=True):
1418 Make a filename relative, where the filename is dest, and it is
1419 being referred to from the filename source.
1421 >>> make_relative_path('/usr/share/something/a-file.pth',
1422 ... '/usr/share/another-place/src/Directory')
1423 '../another-place/src/Directory'
1424 >>> make_relative_path('/usr/share/something/a-file.pth',
1425 ... '/home/user/src/Directory')
1426 '../../../home/user/src/Directory'
1427 >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
1430 source
= os
.path
.dirname(source
)
1431 if not dest_is_directory
:
1432 dest_filename
= os
.path
.basename(dest
)
1433 dest
= os
.path
.dirname(dest
)
1434 dest
= os
.path
.normpath(os
.path
.abspath(dest
))
1435 source
= os
.path
.normpath(os
.path
.abspath(source
))
1436 dest_parts
= dest
.strip(os
.path
.sep
).split(os
.path
.sep
)
1437 source_parts
= source
.strip(os
.path
.sep
).split(os
.path
.sep
)
1438 while dest_parts
and source_parts
and dest_parts
[0] == source_parts
[0]:
1441 full_parts
= ['..']*len(source_parts
) + dest_parts
1442 if not dest_is_directory
:
1443 full_parts
.append(dest_filename
)
1445 # Special case for the current directory (otherwise it'd be '')
1447 return os
.path
.sep
.join(full_parts
)
1451 ############################################################
1452 ## Bootstrap script creation:
1454 def create_bootstrap_script(extra_text
, python_version
=''):
1456 Creates a bootstrap script, which is like this script but with
1457 extend_parser, adjust_options, and after_install hooks.
1459 This returns a string that (written to disk of course) can be used
1460 as a bootstrap script with your own customizations. The script
1461 will be the standard virtualenv.py script, with your extra text
1462 added (your extra text should be Python code).
1464 If you include these functions, they will be called:
1466 ``extend_parser(optparse_parser)``:
1467 You can add or remove options from the parser here.
1469 ``adjust_options(options, args)``:
1470 You can change options here, or change the args (if you accept
1471 different kinds of arguments, be sure you modify ``args`` so it is
1472 only ``[DEST_DIR]``).
1474 ``after_install(options, home_dir)``:
1476 After everything is installed, this function is called. This
1477 is probably the function you are most likely to use. An
1480 def after_install(options, home_dir):
1481 subprocess.call([join(home_dir, 'bin', 'easy_install'),
1483 subprocess.call([join(home_dir, 'bin', 'my-package-script'),
1486 This example immediately installs a package, and runs a setup
1487 script from that package.
1489 If you provide something like ``python_version='2.4'`` then the
1490 script will start with ``#!/usr/bin/env python2.4`` instead of
1491 ``#!/usr/bin/env python``. You can use this when the script must
1492 be run with a particular Python version.
1495 if filename
.endswith('.pyc'):
1496 filename
= filename
[:-1]
1497 f
= open(filename
, 'rb')
1500 py_exe
= 'python%s' % python_version
1501 content
= (('#!/usr/bin/env %s\n' % py_exe
)
1502 + '## WARNING: This file is generated\n'
1504 return content
.replace('##EXT' 'END##', extra_text
)
1509 b
= base64
.b64decode(s
.encode('ascii'))
1510 return zlib
.decompress(b
).decode('utf-8')
1513 SITE_PY
= convert("""
1514 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
1656 EZ_SETUP_PY
= convert("""
1657 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
1723 BDaonX65d/fwEjNqlDjLVIvM9X+XVxF7
1730 ##file distribute_setup.py
1731 DISTRIBUTE_SETUP_PY
= convert("""
1732 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
1818 ACTIVATE_SH
= convert("""
1819 eJytVU1v4jAQPW9+xTT0ANVS1GsrDlRFAqmFqmG72m0rY5IJsRRslDiktNr/vuMQ8tFQpNU2B4I9
1820 H36eeW/SglkgYvBFiLBKYg0LhCRGD1KhA7BjlUQuwkLIHne12HCNNpz5kVrBgsfBmdWCrUrA5VIq
1821 DVEiQWjwRISuDreW5eE+CtodeLeAnhZEGKMGFXqAciMiJVcoNWx4JPgixDjzEj48QVeCfcqmtzfs
1822 cfww+zG4ZfeD2ciGF7gCHaDMPM1jtvuHXAsPfF2rSGeOxV4iDY5GUGb3xVEYv2aj6WQ0vRseAlMY
1823 G5DKsAawwnQUXt2LQOYlzZoYByqhonqoqfxZf4BLD97i4DukgXADCPgGgdOLTK5arYxZB1xnrc9T
1824 EQFcHoZEAa1gSQioo/TPV5FZrDlxJA+NzwF+Ek1UonOzFnKZp6k5mgLBqSkuuAGXS4whJb5xz/xs
1825 wXCHjiVerAk5eh9Kfz1wqOldtVv9dkbscfjgjKeTA8XPrtaNauX5rInOxaHuOReNtpFjo1/OxdFG
1826 5eY9hJ3L3jqcPJbATggXAemDLZX0MNZRYjSDH7C1wMHQh73DyYfTu8a0F9v+6D8W6XNnF1GEIXW/
1827 JrSKPOtnW1YFat9mrLJkzLbyIlTvYzV0RGXcaTBfVLx7jF2PJ2wyuBsydpm7VSVa4C4Zb6pFO2TR
1828 huypCEPwuQjNftUrNl6GsYZzuFrrLdC9iJjQ3omAPBbcI2lsU77tUD43kw1NPZhTrnZWzuQKLomx
1829 Rd4OXM1ByExVVkmoTwfBJ7Lt10Iq1Kgo23Bmd8Ib1KrGbsbO4Pp2yO4fpnf3s6MnZiwuiJuls1/L
1830 Pu4yUCvhpA+vZaJvWWDTr0yFYYyVnHMqCEq+QniuYX225xmnzRENjbXACF3wkCYNVZ1mBwxoR9Iw
1831 WAo3/36oSOTfgjwEEQKt15e9Xpqm52+oaXxszmnE9GLl65RH2OMmS6+u5acKxDmlPgj2eT5/gQOX
1832 LLK0j1y0Uwbmn438VZkVpqlfNKa/YET/53j+99G8H8tUhr9ZSXs2
1839 ##file activate.fish
1840 ACTIVATE_FISH
= convert("""
1841 eJydVm1v4jgQ/s6vmA1wBxUE7X2stJVYlVWR2lK13d6d9laRk0yIr8HmbIe0++tvnIQQB9pbXT5A
1842 Ys/LM55nZtyHx5RrSHiGsMm1gRAh1xhDwU0Kng8hFzMWGb5jBv2E69SDs0TJDdj3MxilxmzPZzP7
1843 pVPMMl+q9bjXh1eZQ8SEkAZULoAbiLnCyGSvvV6SC7IoBcS4Nw0wjcFbvJDcjiuTswzFDpiIQaHJ
1844 lQAjQUi1YRmUboC2uZJig8J4PaCnT5IaDcgsbm/CjinOwgx1KcUTMEhhTgV4g2B1fRk8Le8fv86v
1845 g7v545UHpZB9rKnp+gXsMhxLunIIpwVQxP/l9c/Hq9Xt1epm4R27bva6AJqN92G4YhbMG2i+LB+u
1846 grv71c3dY7B6WtzfLy9bePbp0taDTXSwJQJszUnnp0y57mvpPcrF7ZODyhswtd59+/jdgw+fwBNS
1847 xLSscksUPIDqwwNmCez3PpxGeyBYg6HE0YdcWBxcKczYzuVJi5Wu915vn5oWePCCoPUZBN5B7IgV
1848 MCi54ZDLG7TUZ0HweXkb3M5vFmSpFm/gthhBx0UrveoPpv9AJ9unIbQYdUoe21bKg2q48sPFGVwu
1849 H+afrxd1qvclaNlRFyh1EQ2sSccEuNAGWQwysfVpz1tPajUqbqJUnEcIJkWo6OXDaodK8ZiLdbmM
1850 L1wb+9H0D+pcyPSrX5u5kgWSygRYXCnJUi/KKcuU4cqsAyTKZBiissLc7NFwizvjxtieKBVCIdWz
1851 fzilzPaYyljZN0cGN1v7NnaIPNCGmVy3GKuJaQ6iVjE1Qfm+36hglErwmnAD8hu0dDy4uICBA8ZV
1852 pQr/q/+O0KFW2kjelu9Dgb9SDBsWV4F4x5CswgS0zBVlk5tDMP5bVtUGpslbm81Lu2sdKq7uNMGh
1853 MVQ4fy9xhogC1lS5guhISa0DlBWv0O8odT6/LP+4WZzDV6FzIkEqC0uolGZSZoMnlpxplmD2euaT
1854 O4hkTpPnbztDccey0bhjDaBIqaWQa0uwEtQEwtyU56i4fq54F9IE3ORR6mKriODM4XOYZwaVYLYz
1855 7SPbKkz4i7VkB6/Ot1upDE3znNqYKpM8raa0Bx8vfvntJ32UENsM4aI6gJL+jJwhxhh3jVIDOcpi
1856 m0r2hmEtS8XXXNBk71QCDXTBNhhPiHX2LtHkrVIlhoEshH/EZgdq53Eirqs5iFKMnkOmqZTtr3Xq
1857 djvPTWZT4S3NT5aVLgurMPUWI07BRVYqkQrmtCKohNY8qu9EdACoT6ki0a66XxVF4f9AQ3W38yO5
1858 mWmZmIIpnDFrbXakvKWeZhLwhvrbUH8fahhqD0YUcBDJjEBMQwiznE4y5QbHrbhHBOnUAYzb2tVN
1859 jJa65e+eE2Ya30E2GurxUP8ssA6e/wOnvo3V78d3vTcvMB3n7l3iX1JXWqk=
1867 ACTIVATE_CSH
= convert("""
1868 eJx9U11vmzAUffevOCVRu+UB9pws29Kl0iq1aVWllaZlcgxciiViItsQdb9+xiQp+dh4QOB7Pu49
1869 XHqY59IgkwVhVRmLmFAZSrGRNkdgykonhFiqSCRW1sJSmJg8wCDT5QrucRCyHn6WFRKhVGmhKwVp
1870 kUpNiS3emup3TY6XIn7DVNQyJUwlrgthJD6n/iCNv72uhCzCpFx9CRkThRQGKe08cWXJ9db/yh/u
1871 pvzl9mn+PLnjj5P5D1yM8QmXlzBkSdXwZ0H/BBc0mEo5FE5qI2jKhclHOOvy9HD/OO/6YO1mX9vx
1872 sY0H/tPIV0dtqel0V7iZvWyNg8XFcBA0ToEqVeqOdNUEQFvN41SumAv32VtJrakQNSmLWmgp4oJM
1873 yDoBHgoydtoEAs47r5wHHnUal5vbJ8oOI+9wI86vb2d8Nrm/4Xy4RZ8R85E4uTZPB5EZPnTaaAGu
1874 E59J8BE2J8XgrkbLeXMlVoQxznEYFYY8uFFdxsKQRx90Giwx9vSueHP1YNaUSFG4vTaErNSYuBOF
1875 lXiVyXa9Sy3JdClEyK1dD6Nos9mEf8iKlOpmqSNTZnYjNEWiUYn2pKNB3ttcLJ3HmYYXy6Un76f7
1876 r8rRsC1TpTJj7f19m5sUf/V3Ir+x/yjtLu8KjLX/CmN/AcVGUUo=
1884 ACTIVATE_BAT
= convert("""
1885 eJyFUkEKgzAQvAfyhz0YaL9QEWpRqlSjWGspFPZQTevFHOr/adQaU1GaUzI7Mzu7ZF89XhKkEJS8
1886 qxaKMMsvboQ+LxxE44VICSW1gEa2UFaibqoS0iyJ0xw2lIA6nX5AHCu1jpRsv5KRjknkac9VLVug
1887 sX9mtzxIeJDE/mg4OGp47qoLo3NHX2jsMB3AiDht5hryAUOEifoTdCXbSh7V0My2NMq/Xbh5MEjU
1888 ZT63gpgNT9lKOJ/CtHsvT99re3pX303kydn4HeyOeAg5cjf2EW1D6HOPkg9NGKhu
1895 ##file deactivate.bat
1896 DEACTIVATE_BAT
= convert("""
1897 eJxzSE3OyFfIT0vj4spMU0hJTcvMS01RiPf3cYkP8wwKCXX0iQ8I8vcNCFHQ4FIAguLUEgWIgK0q
1898 FlWqXJpcICVYpGzx2BAZ4uHv5+Hv6wq1BWINXBTdKriEKkI1DhW2QAfhttcxxANiFZCBbglQSJUL
1899 i2dASrm4rFz9XLgAwJNbyQ==
1906 ##file distutils-init.py
1907 DISTUTILS_INIT
= convert("""
1908 eJytV92L4zYQf/dfMU0ottuse7RvC6FQrg8Lxz2Ugz4si9HacqKuIxlJ2ST313dG8odkO9d7aGBB
1909 luZLv/nNjFacOqUtKJMIvzK3cXlhWgp5MDBsqK5SNYftsBAGpLLA4F1oe2Ytl+9wUvW55TswCi4c
1910 KibhbFDSglXQCFmDPXIwtm7FawLRbwtPzg2T9gf4gupKv4GS0N262w7V0NvpbCy8cvTo3eAus6C5
1911 ETU3ICQZX1hFTw/dzR6V/AW1RCN4/XAtbsVXqIXmlVX6liS4lOzEYY9QFB2zx6LfoSNjz1a0pqT9
1912 QOIfJWQ2E888NEVZNqLlZZnvIB0NpHkimlFdKn2iRRY7yGG/CCJb6Iz280d34SFXBS2yEYPNF0Q7
1913 yM7oCjpWvbEDQmnhRwOs6zjThpKE8HogwRAgraqYFZgGZvzmzVh+mgz9vskT3hruwyjdFcqyENJw
1914 bbMPO5jdzonxK68QKT7B57CMRRG5shRSWDTX3dI8LzRndZbnSWL1zfvriUmK4TcGWSnZiEPCrxXv
1915 bM+sP7VW2is2WgWXCO3sAu3Rzysz3FiNCA8WPyM4gb1JAAmCiyTZbhFjWx3h9SzauuRXC9MFoVbc
1916 yNTCm1QXOOIfIn/g1kGMhDUBN72hI5XCBQtIXQw8UEEdma6Jaz4vJIJ51Orc15hzzmu6TdFp3ogr
1917 Aof0c98tsw1SiaiWotHffk3XYCkqdToxWRfTFXqgpg2khcLluOHMVC0zZhLKIomesfSreUNNgbXi
1918 Ky9VRzwzkBneNoGQyyvGjbsFQqOZvpWIjqH281lJ/jireFgR3cPzSyTGWzQpDNIU+03Fs4XKLkhp
1919 /n0uFnuF6VphB44b3uWRneSbBoMSioqE8oeF0JY+qTvYfEK+bPLYdoR4McfYQ7wMZj39q0kfP8q+
1920 FfsymO0GzNlPh644Jje06ulqHpOEQqdJUfoidI2O4CWx4qOglLye6RrFQirpCRXvhoRqXH3sYdVJ
1921 AItvc+VUsLO2v2hVAWrNIfVGtkG351cUMNncbh/WdowtSPtCdkzYFv6mwYc9o2Jt68ud6wectBr8
1922 hYAulPSlgzH44YbV3ikjrulEaNJxt+/H3wZ7bXSXje/YY4tfVVrVmUstaDwwOBLMg6iduDB0lMVC
1923 UyzYx7Ab4kjCqdViEJmDcdk/SKbgsjYXgfMznUWcrtS4z4fmJ/XOM1LPk/iIpqass5XwNbdnLb1Y
1924 8h3ERXSWZI6rZJxKs1LBqVH65w0Oy4ra0CBYxEeuOMbDmV5GI6E0Ha/wgVTtkX0+OXvqsD02CKLf
1925 XHbeft85D7tTCMYy2Njp4DJP7gWJr6paVWXZ1+/6YXLv/iE0M90FktiI7yFJD9e7SOLhEkkaMTUO
1926 azq9i2woBNR0/0eoF1HFMf0H8ChxH/jgcB34GZIz3Qn4/vid+VEamQrOVqAPTrOfmD4MPdVh09tb
1927 8dLLjvh/61lEP4yW5vJaH4vHcevG8agXvzPGoOhhXNncpTr99PTHx6e/UvffFLaxUSjuSeP286Dw
1928 gtEMcW1xKr/he4/6IQ6FUXP+0gkioHY5iwC9Eyx3HKO7af0zPPe+XyLn7fAY78k4aiR387bCr5XT
1929 5C4rFgwLGfMvJuAMew==
1936 ##file distutils.cfg
1937 DISTUTILS_CFG
= convert("""
1938 eJxNj00KwkAMhfc9xYNuxe4Ft57AjYiUtDO1wXSmNJnK3N5pdSEEAu8nH6lxHVlRhtDHMPATA4uH
1939 xJ4EFmGbvfJiicSHFRzUSISMY6hq3GLCRLnIvSTnEefN0FIjw5tF0Hkk9Q5dRunBsVoyFi24aaLg
1940 9FDOlL0FPGluf4QjcInLlxd6f6rqkgPu/5nHLg0cXCscXoozRrP51DRT3j9QNl99AP53T2Q=
1947 ##file activate_this.py
1948 ACTIVATE_THIS
= convert("""
1949 eJyNUlGL2zAMfvevEBlHEujSsXsL9GGDvW1jD3sZpQQ3Ua7aJXawnbT595Ocpe0dO5ghseVP+vRJ
1950 VpIkn2cYPZknwAvWLXWYhRP5Sk4baKgOWRWNqtpdgTyH2Y5wpq5Tug406YAgKEzkwqg7NBPwR86a
1951 Hk0olPopaK0NHJHzYQPnE5rI0o8+yBUwiBfyQcT8mMPJGiAT0A0O+b8BY4MKJ7zPcSSzHaKrSpJE
1952 qeDmUgGvVbPCS41DgO+6xy/OWbfAThMn/OQ9ukDWRCSLiKzk1yrLjWapq6NnvHUoHXQ4bYPdrsVX
1953 4lQMc/q6ZW975nmSK+oH6wL42a9H65U6aha342Mh0UVDzrD87C1bH73s16R5zsStkBZDp0NrXQ+7
1954 HaRnMo8f06UBnljKoOtn/YT+LtdvSyaT/BtIv9KR60nF9f3qmuYKO4//T9ItJMsjPfgUHqKwCZ3n
1955 xu/Lx8M/UvCLTxW7VULHxB1PRRbrYfvWNY5S8it008jOjcleaMqVBDnUXcWULV2YK9JEQ92OfC96
1956 1Tv4ZicZZZ7GpuEpZbbeQ7DxquVx5hdqoyFSSmXwfC90f1Dc7hjFs/tK99I0fpkI8zSLy4tSy+sI
1957 3vMWehjQNJmE5VePlZbL61nzX3S93ZcfDqznnkb9AZ3GWJU=
1964 if __name__
== '__main__':
1968 ## Copy python.exe.manifest
1969 ## Monkeypatch distutils.sysconfig