| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  | """
 | 
					
						
							|  |  |  | Virtual environment (venv) package for Python. Based on PEP 405. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-25 00:47:46 +01:00
										 |  |  | Copyright (C) 2011-2012 Vinay Sajip. | 
					
						
							|  |  |  | Licensed to the PSF under a contributor agreement. | 
					
						
							| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  | usage: python -m venv [-h] [--system-site-packages] [--symlinks] [--clear] | 
					
						
							|  |  |  |             [--upgrade] | 
					
						
							| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  |             ENV_DIR [ENV_DIR ...] | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Creates virtual Python environments in one or more target directories. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | positional arguments: | 
					
						
							|  |  |  |   ENV_DIR               A directory to create the environment in. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | optional arguments: | 
					
						
							|  |  |  |   -h, --help            show this help message and exit | 
					
						
							|  |  |  |   --system-site-packages | 
					
						
							|  |  |  |                         Give the virtual environment access to the system | 
					
						
							|  |  |  |                         site-packages dir. | 
					
						
							|  |  |  |   --symlinks            Attempt to symlink rather than copy. | 
					
						
							|  |  |  |   --clear               Delete the environment directory if it already exists. | 
					
						
							|  |  |  |                         If not specified and the directory exists, an error is | 
					
						
							|  |  |  |                         raised. | 
					
						
							|  |  |  |   --upgrade             Upgrade the environment directory to use this version | 
					
						
							|  |  |  |                         of Python, assuming Python has been upgraded in-place. | 
					
						
							|  |  |  | """
 | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | import base64 | 
					
						
							|  |  |  | import io | 
					
						
							|  |  |  | import logging | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import os.path | 
					
						
							|  |  |  | import shutil | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  | import sysconfig | 
					
						
							| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  | try: | 
					
						
							|  |  |  |     import threading | 
					
						
							| 
									
										
										
										
											2013-07-04 17:43:24 -04:00
										 |  |  | except ImportError: | 
					
						
							| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  |     threading = None | 
					
						
							| 
									
										
										
										
											2013-07-12 21:10:19 +01:00
										 |  |  | import types | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | logger = logging.getLogger(__name__) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class EnvBuilder: | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     This class exists to allow virtual environment creation to be | 
					
						
							|  |  |  |     customised. The constructor parameters determine the builder's | 
					
						
							|  |  |  |     behaviour when called upon to create a virtual environment. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     By default, the builder makes the system (global) site-packages dir | 
					
						
							| 
									
										
										
										
											2012-11-14 11:18:35 +00:00
										 |  |  |     *un*available to the created environment. | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-14 11:18:35 +00:00
										 |  |  |     If invoked using the Python -m option, the default is to use copying | 
					
						
							|  |  |  |     on Windows platforms but symlinks elsewhere. If instantiated some | 
					
						
							|  |  |  |     other way, the default is to *not* use symlinks. | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param system_site_packages: If True, the system (global) site-packages | 
					
						
							|  |  |  |                                  dir is available to created environments. | 
					
						
							|  |  |  |     :param clear: If True and the target directory exists, it is deleted. | 
					
						
							|  |  |  |                   Otherwise, if the target directory exists, an error is | 
					
						
							|  |  |  |                   raised. | 
					
						
							|  |  |  |     :param symlinks: If True, attempt to symlink rather than copy files into | 
					
						
							|  |  |  |                      virtual environment. | 
					
						
							|  |  |  |     :param upgrade: If True, upgrade an existing virtual environment. | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def __init__(self, system_site_packages=False, clear=False, | 
					
						
							|  |  |  |                  symlinks=False, upgrade=False): | 
					
						
							|  |  |  |         self.system_site_packages = system_site_packages | 
					
						
							|  |  |  |         self.clear = clear | 
					
						
							|  |  |  |         self.symlinks = symlinks | 
					
						
							|  |  |  |         self.upgrade = upgrade | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create(self, env_dir): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Create a virtual environment in a directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param env_dir: The target directory to create an environment in. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         env_dir = os.path.abspath(env_dir) | 
					
						
							|  |  |  |         context = self.ensure_directories(env_dir) | 
					
						
							|  |  |  |         self.create_configuration(context) | 
					
						
							|  |  |  |         self.setup_python(context) | 
					
						
							|  |  |  |         if not self.upgrade: | 
					
						
							|  |  |  |             self.setup_scripts(context) | 
					
						
							|  |  |  |             self.post_setup(context) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-11 17:22:45 +01:00
										 |  |  |     def clear_directory(self, path): | 
					
						
							|  |  |  |         for fn in os.listdir(path): | 
					
						
							|  |  |  |             fn = os.path.join(path, fn) | 
					
						
							|  |  |  |             if os.path.islink(fn) or os.path.isfile(fn): | 
					
						
							|  |  |  |                 os.remove(fn) | 
					
						
							|  |  |  |             elif os.path.isdir(fn): | 
					
						
							|  |  |  |                 shutil.rmtree(fn) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |     def ensure_directories(self, env_dir): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Create the directories for the environment. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Returns a context object which holds paths in the environment, | 
					
						
							|  |  |  |         for use by subsequent logic. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         def create_if_needed(d): | 
					
						
							|  |  |  |             if not os.path.exists(d): | 
					
						
							|  |  |  |                 os.makedirs(d) | 
					
						
							| 
									
										
										
										
											2012-10-11 17:22:45 +01:00
										 |  |  |             elif os.path.islink(d) or os.path.isfile(d): | 
					
						
							|  |  |  |                 raise ValueError('Unable to create directory %r' % d) | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if os.path.exists(env_dir) and self.clear: | 
					
						
							| 
									
										
										
										
											2012-10-11 17:22:45 +01:00
										 |  |  |             self.clear_directory(env_dir) | 
					
						
							| 
									
										
										
										
											2013-07-12 21:10:19 +01:00
										 |  |  |         context = types.SimpleNamespace() | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         context.env_dir = env_dir | 
					
						
							|  |  |  |         context.env_name = os.path.split(env_dir)[1] | 
					
						
							|  |  |  |         context.prompt = '(%s) ' % context.env_name | 
					
						
							|  |  |  |         create_if_needed(env_dir) | 
					
						
							|  |  |  |         env = os.environ | 
					
						
							| 
									
										
										
										
											2012-06-25 00:47:46 +01:00
										 |  |  |         if sys.platform == 'darwin' and '__PYVENV_LAUNCHER__' in env: | 
					
						
							|  |  |  |             executable = os.environ['__PYVENV_LAUNCHER__'] | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             executable = sys.executable | 
					
						
							|  |  |  |         dirname, exename = os.path.split(os.path.abspath(executable)) | 
					
						
							|  |  |  |         context.executable = executable | 
					
						
							|  |  |  |         context.python_dir = dirname | 
					
						
							|  |  |  |         context.python_exe = exename | 
					
						
							|  |  |  |         if sys.platform == 'win32': | 
					
						
							|  |  |  |             binname = 'Scripts' | 
					
						
							|  |  |  |             incpath = 'Include' | 
					
						
							|  |  |  |             libpath = os.path.join(env_dir, 'Lib', 'site-packages') | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             binname = 'bin' | 
					
						
							|  |  |  |             incpath = 'include' | 
					
						
							|  |  |  |             libpath = os.path.join(env_dir, 'lib', 'python%d.%d' % sys.version_info[:2], 'site-packages') | 
					
						
							|  |  |  |         context.inc_path = path = os.path.join(env_dir, incpath) | 
					
						
							|  |  |  |         create_if_needed(path) | 
					
						
							|  |  |  |         create_if_needed(libpath) | 
					
						
							|  |  |  |         context.bin_path = binpath = os.path.join(env_dir, binname) | 
					
						
							|  |  |  |         context.bin_name = binname | 
					
						
							|  |  |  |         context.env_exe = os.path.join(binpath, exename) | 
					
						
							|  |  |  |         create_if_needed(binpath) | 
					
						
							|  |  |  |         return context | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def create_configuration(self, context): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Create a configuration file indicating where the environment's Python | 
					
						
							|  |  |  |         was copied from, and whether the system site-packages should be made | 
					
						
							|  |  |  |         available in the environment. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param context: The information for the environment creation request | 
					
						
							|  |  |  |                         being processed. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         context.cfg_path = path = os.path.join(context.env_dir, 'pyvenv.cfg') | 
					
						
							|  |  |  |         with open(path, 'w', encoding='utf-8') as f: | 
					
						
							|  |  |  |             f.write('home = %s\n' % context.python_dir) | 
					
						
							|  |  |  |             if self.system_site_packages: | 
					
						
							|  |  |  |                 incl = 'true' | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 incl = 'false' | 
					
						
							|  |  |  |             f.write('include-system-site-packages = %s\n' % incl) | 
					
						
							|  |  |  |             f.write('version = %d.%d.%d\n' % sys.version_info[:3]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if os.name == 'nt': | 
					
						
							|  |  |  |         def include_binary(self, f): | 
					
						
							|  |  |  |             if f.endswith(('.pyd', '.dll')): | 
					
						
							|  |  |  |                 result = True | 
					
						
							|  |  |  |             else: | 
					
						
							|  |  |  |                 result = f.startswith('python') and f.endswith('.exe') | 
					
						
							|  |  |  |             return result | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def symlink_or_copy(self, src, dst): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Try symlinking a file, and if that fails, fall back to copying. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         force_copy = not self.symlinks | 
					
						
							|  |  |  |         if not force_copy: | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 if not os.path.islink(dst): # can't link to itself! | 
					
						
							|  |  |  |                     os.symlink(src, dst) | 
					
						
							|  |  |  |             except Exception:   # may need to use a more specific exception | 
					
						
							|  |  |  |                 logger.warning('Unable to symlink %r to %r', src, dst) | 
					
						
							|  |  |  |                 force_copy = True | 
					
						
							|  |  |  |         if force_copy: | 
					
						
							|  |  |  |             shutil.copyfile(src, dst) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setup_python(self, context): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Set up a Python executable in the environment. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param context: The information for the environment creation request | 
					
						
							|  |  |  |                         being processed. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         binpath = context.bin_path | 
					
						
							|  |  |  |         exename = context.python_exe | 
					
						
							|  |  |  |         path = context.env_exe | 
					
						
							|  |  |  |         copier = self.symlink_or_copy | 
					
						
							|  |  |  |         copier(context.executable, path) | 
					
						
							|  |  |  |         dirname = context.python_dir | 
					
						
							|  |  |  |         if os.name != 'nt': | 
					
						
							|  |  |  |             if not os.path.islink(path): | 
					
						
							|  |  |  |                 os.chmod(path, 0o755) | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  |             for suffix in ('python', 'python3'): | 
					
						
							|  |  |  |                 path = os.path.join(binpath, suffix) | 
					
						
							|  |  |  |                 if not os.path.exists(path): | 
					
						
							|  |  |  |                     os.symlink(exename, path) | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         else: | 
					
						
							|  |  |  |             subdir = 'DLLs' | 
					
						
							|  |  |  |             include = self.include_binary | 
					
						
							|  |  |  |             files = [f for f in os.listdir(dirname) if include(f)] | 
					
						
							|  |  |  |             for f in files: | 
					
						
							|  |  |  |                 src = os.path.join(dirname, f) | 
					
						
							|  |  |  |                 dst = os.path.join(binpath, f) | 
					
						
							|  |  |  |                 if dst != context.env_exe:  # already done, above | 
					
						
							|  |  |  |                     copier(src, dst) | 
					
						
							|  |  |  |             dirname = os.path.join(dirname, subdir) | 
					
						
							|  |  |  |             if os.path.isdir(dirname): | 
					
						
							|  |  |  |                 files = [f for f in os.listdir(dirname) if include(f)] | 
					
						
							|  |  |  |                 for f in files: | 
					
						
							|  |  |  |                     src = os.path.join(dirname, f) | 
					
						
							|  |  |  |                     dst = os.path.join(binpath, f) | 
					
						
							|  |  |  |                     copier(src, dst) | 
					
						
							|  |  |  |             # copy init.tcl over | 
					
						
							|  |  |  |             for root, dirs, files in os.walk(context.python_dir): | 
					
						
							|  |  |  |                 if 'init.tcl' in files: | 
					
						
							|  |  |  |                     tcldir = os.path.basename(root) | 
					
						
							|  |  |  |                     tcldir = os.path.join(context.env_dir, 'Lib', tcldir) | 
					
						
							|  |  |  |                     os.makedirs(tcldir) | 
					
						
							|  |  |  |                     src = os.path.join(root, 'init.tcl') | 
					
						
							|  |  |  |                     dst = os.path.join(tcldir, 'init.tcl') | 
					
						
							|  |  |  |                     shutil.copyfile(src, dst) | 
					
						
							|  |  |  |                     break | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def setup_scripts(self, context): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Set up scripts into the created environment from a directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         This method installs the default scripts into the environment | 
					
						
							|  |  |  |         being created. You can prevent the default installation by overriding | 
					
						
							|  |  |  |         this method if you really need to, or if you need to specify | 
					
						
							|  |  |  |         a different location for the scripts to install. By default, the | 
					
						
							|  |  |  |         'scripts' directory in the venv package is used as the source of | 
					
						
							|  |  |  |         scripts to install. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         path = os.path.abspath(os.path.dirname(__file__)) | 
					
						
							|  |  |  |         path = os.path.join(path, 'scripts') | 
					
						
							|  |  |  |         self.install_scripts(context, path) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def post_setup(self, context): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Hook for post-setup modification of the venv. Subclasses may install | 
					
						
							|  |  |  |         additional packages or scripts here, add activation shell scripts, etc. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param context: The information for the environment creation request | 
					
						
							|  |  |  |                         being processed. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         pass | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def replace_variables(self, text, context): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Replace variable placeholders in script text with context-specific | 
					
						
							|  |  |  |         variables. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Return the text passed in , but with variables replaced. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param text: The text in which to replace placeholder variables. | 
					
						
							|  |  |  |         :param context: The information for the environment creation request | 
					
						
							|  |  |  |                         being processed. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         text = text.replace('__VENV_DIR__', context.env_dir) | 
					
						
							|  |  |  |         text = text.replace('__VENV_NAME__', context.prompt) | 
					
						
							|  |  |  |         text = text.replace('__VENV_BIN_NAME__', context.bin_name) | 
					
						
							|  |  |  |         text = text.replace('__VENV_PYTHON__', context.env_exe) | 
					
						
							|  |  |  |         return text | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def install_scripts(self, context, path): | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         Install scripts into the created environment from a directory. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         :param context: The information for the environment creation request | 
					
						
							|  |  |  |                         being processed. | 
					
						
							|  |  |  |         :param path:    Absolute pathname of a directory containing script. | 
					
						
							|  |  |  |                         Scripts in the 'common' subdirectory of this directory, | 
					
						
							|  |  |  |                         and those in the directory named for the platform | 
					
						
							|  |  |  |                         being run on, are installed in the created environment. | 
					
						
							|  |  |  |                         Placeholder variables are replaced with environment- | 
					
						
							|  |  |  |                         specific values. | 
					
						
							|  |  |  |         """
 | 
					
						
							|  |  |  |         binpath = context.bin_path | 
					
						
							|  |  |  |         plen = len(path) | 
					
						
							|  |  |  |         for root, dirs, files in os.walk(path): | 
					
						
							|  |  |  |             if root == path: # at top-level, remove irrelevant dirs | 
					
						
							|  |  |  |                 for d in dirs[:]: | 
					
						
							|  |  |  |                     if d not in ('common', os.name): | 
					
						
							|  |  |  |                         dirs.remove(d) | 
					
						
							|  |  |  |                 continue # ignore files in top level | 
					
						
							|  |  |  |             for f in files: | 
					
						
							|  |  |  |                 srcfile = os.path.join(root, f) | 
					
						
							|  |  |  |                 suffix = root[plen:].split(os.sep)[2:] | 
					
						
							|  |  |  |                 if not suffix: | 
					
						
							|  |  |  |                     dstdir = binpath | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     dstdir = os.path.join(binpath, *suffix) | 
					
						
							|  |  |  |                 if not os.path.exists(dstdir): | 
					
						
							|  |  |  |                     os.makedirs(dstdir) | 
					
						
							|  |  |  |                 dstfile = os.path.join(dstdir, f) | 
					
						
							|  |  |  |                 with open(srcfile, 'rb') as f: | 
					
						
							|  |  |  |                     data = f.read() | 
					
						
							|  |  |  |                 if srcfile.endswith('.exe'): | 
					
						
							|  |  |  |                     mode = 'wb' | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     mode = 'w' | 
					
						
							| 
									
										
										
										
											2012-10-28 12:39:39 +00:00
										 |  |  |                     try: | 
					
						
							|  |  |  |                         data = data.decode('utf-8') | 
					
						
							|  |  |  |                         data = self.replace_variables(data, context) | 
					
						
							|  |  |  |                     except UnicodeDecodeError as e: | 
					
						
							|  |  |  |                         data = None | 
					
						
							|  |  |  |                         logger.warning('unable to copy script %r, ' | 
					
						
							|  |  |  |                                        'may be binary: %s', srcfile, e) | 
					
						
							|  |  |  |                 if data is not None: | 
					
						
							|  |  |  |                     with open(dstfile, mode) as f: | 
					
						
							|  |  |  |                         f.write(data) | 
					
						
							|  |  |  |                     shutil.copymode(srcfile, dstfile) | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def create(env_dir, system_site_packages=False, clear=False, symlinks=False): | 
					
						
							|  |  |  |     """
 | 
					
						
							|  |  |  |     Create a virtual environment in a directory. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-11-14 11:18:35 +00:00
										 |  |  |     By default, makes the system (global) site-packages dir *un*available to | 
					
						
							|  |  |  |     the created environment, and uses copying rather than symlinking for files | 
					
						
							|  |  |  |     obtained from the source Python installation. | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     :param env_dir: The target directory to create an environment in. | 
					
						
							|  |  |  |     :param system_site_packages: If True, the system (global) site-packages | 
					
						
							|  |  |  |                                  dir is available to the environment. | 
					
						
							|  |  |  |     :param clear: If True and the target directory exists, it is deleted. | 
					
						
							|  |  |  |                   Otherwise, if the target directory exists, an error is | 
					
						
							|  |  |  |                   raised. | 
					
						
							|  |  |  |     :param symlinks: If True, attempt to symlink rather than copy files into | 
					
						
							|  |  |  |                      virtual environment. | 
					
						
							|  |  |  |     """
 | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  |     builder = EnvBuilder(system_site_packages=system_site_packages, | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |                                    clear=clear, symlinks=symlinks) | 
					
						
							|  |  |  |     builder.create(env_dir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def main(args=None): | 
					
						
							|  |  |  |     compatible = True | 
					
						
							|  |  |  |     if sys.version_info < (3, 3): | 
					
						
							|  |  |  |         compatible = False | 
					
						
							|  |  |  |     elif not hasattr(sys, 'base_prefix'): | 
					
						
							|  |  |  |         compatible = False | 
					
						
							|  |  |  |     if not compatible: | 
					
						
							| 
									
										
										
										
											2012-06-25 00:47:46 +01:00
										 |  |  |         raise ValueError('This script is only for use with Python 3.3') | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |     else: | 
					
						
							|  |  |  |         import argparse | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         parser = argparse.ArgumentParser(prog=__name__, | 
					
						
							|  |  |  |                                          description='Creates virtual Python ' | 
					
						
							|  |  |  |                                                      'environments in one or ' | 
					
						
							|  |  |  |                                                      'more target ' | 
					
						
							| 
									
										
										
										
											2012-07-08 17:50:42 +01:00
										 |  |  |                                                      'directories.', | 
					
						
							|  |  |  |                                          epilog='Once an environment has been ' | 
					
						
							|  |  |  |                                                 'created, you may wish to ' | 
					
						
							|  |  |  |                                                 'activate it, e.g. by ' | 
					
						
							|  |  |  |                                                 'sourcing an activate script ' | 
					
						
							|  |  |  |                                                 'in its bin directory.') | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         parser.add_argument('dirs', metavar='ENV_DIR', nargs='+', | 
					
						
							|  |  |  |                             help='A directory to create the environment in.') | 
					
						
							|  |  |  |         parser.add_argument('--system-site-packages', default=False, | 
					
						
							|  |  |  |                             action='store_true', dest='system_site', | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  |                             help='Give the virtual environment access to the ' | 
					
						
							|  |  |  |                                  'system site-packages dir.') | 
					
						
							| 
									
										
										
										
											2012-07-17 17:33:46 +01:00
										 |  |  |         if os.name == 'nt': | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |             use_symlinks = False | 
					
						
							|  |  |  |         else: | 
					
						
							|  |  |  |             use_symlinks = True | 
					
						
							| 
									
										
										
										
											2013-08-25 00:04:06 +01:00
										 |  |  |         group = parser.add_mutually_exclusive_group() | 
					
						
							|  |  |  |         group.add_argument('--symlinks', default=use_symlinks, | 
					
						
							|  |  |  |                            action='store_true', dest='symlinks', | 
					
						
							|  |  |  |                            help='Try to use symlinks rather than copies, ' | 
					
						
							|  |  |  |                                 'when symlinks are not the default for ' | 
					
						
							|  |  |  |                                 'the platform.') | 
					
						
							|  |  |  |         group.add_argument('--copies', default=not use_symlinks, | 
					
						
							|  |  |  |                            action='store_false', dest='symlinks', | 
					
						
							|  |  |  |                            help='Try to use copies rather than symlinks, ' | 
					
						
							|  |  |  |                                 'even when symlinks are the default for ' | 
					
						
							|  |  |  |                                 'the platform.') | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         parser.add_argument('--clear', default=False, action='store_true', | 
					
						
							| 
									
										
										
										
											2012-10-11 17:22:45 +01:00
										 |  |  |                             dest='clear', help='Delete the contents of the ' | 
					
						
							|  |  |  |                                                'environment directory if it ' | 
					
						
							|  |  |  |                                                'already exists, before ' | 
					
						
							|  |  |  |                                                'environment creation.') | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         parser.add_argument('--upgrade', default=False, action='store_true', | 
					
						
							|  |  |  |                             dest='upgrade', help='Upgrade the environment ' | 
					
						
							|  |  |  |                                                'directory to use this version ' | 
					
						
							| 
									
										
										
										
											2012-05-26 20:36:12 +01:00
										 |  |  |                                                'of Python, assuming Python ' | 
					
						
							|  |  |  |                                                'has been upgraded in-place.') | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         options = parser.parse_args(args) | 
					
						
							|  |  |  |         if options.upgrade and options.clear: | 
					
						
							|  |  |  |             raise ValueError('you cannot supply --upgrade and --clear together.') | 
					
						
							| 
									
										
										
										
											2012-05-28 16:33:01 +01:00
										 |  |  |         builder = EnvBuilder(system_site_packages=options.system_site, | 
					
						
							|  |  |  |                              clear=options.clear, symlinks=options.symlinks, | 
					
						
							|  |  |  |                              upgrade=options.upgrade) | 
					
						
							| 
									
										
										
										
											2012-05-26 03:45:29 +01:00
										 |  |  |         for d in options.dirs: | 
					
						
							|  |  |  |             builder.create(d) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | if __name__ == '__main__': | 
					
						
							|  |  |  |     rc = 1 | 
					
						
							|  |  |  |     try: | 
					
						
							|  |  |  |         main() | 
					
						
							|  |  |  |         rc = 0 | 
					
						
							|  |  |  |     except Exception as e: | 
					
						
							|  |  |  |         print('Error: %s' % e, file=sys.stderr) | 
					
						
							|  |  |  |     sys.exit(rc) |