changeset: 77036:11fd82c0e1dd branch: venv parent: 77034:173f8879c54f user: Vinay Sajip date: Wed May 16 20:29:56 2012 +0100 files: Lib/venv/__init__.py description: Added --upgrade option to pyvenv. diff -r 173f8879c54f -r 11fd82c0e1dd Lib/venv/__init__.py --- a/Lib/venv/__init__.py Wed May 16 09:50:16 2012 +0100 +++ b/Lib/venv/__init__.py Wed May 16 20:29:56 2012 +0100 @@ -61,13 +61,15 @@ 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): + 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): """ @@ -84,20 +86,26 @@ raise ValueError( "Symlinking is not supported on OSX framework Python.") env_dir = os.path.abspath(env_dir) - context = self.create_directories(env_dir) + context = self.ensure_directories(env_dir) self.create_configuration(context) self.setup_python(context) - self.setup_scripts(context) - self.post_setup(context) + if not self.upgrade: + self.setup_scripts(context) + self.post_setup(context) - def create_directories(self, env_dir): + 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. """ - if os.path.exists(env_dir) and not self.clear: + + def create_if_needed(d): + if not os.path.exists(d): + os.makedirs(d) + + if os.path.exists(env_dir) and not (self.clear or self.upgrade): raise ValueError('Directory exists: %s' % env_dir) if os.path.exists(env_dir) and self.clear: shutil.rmtree(env_dir) @@ -105,7 +113,7 @@ context.env_dir = env_dir context.env_name = os.path.split(env_dir)[1] context.prompt = '(%s) ' % context.env_name - os.makedirs(env_dir) + create_if_needed(env_dir) env = os.environ if sys.platform == 'darwin' and '__PYTHONV_LAUNCHER__' in env: executable = os.environ['__PYTHONV_LAUNCHER__'] @@ -124,12 +132,12 @@ 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) - os.mkdir(path) - os.makedirs(libpath) + 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) - os.mkdir(binpath) + create_if_needed(binpath) return context def create_configuration(self, context): @@ -166,7 +174,8 @@ force_copy = not self.symlinks if not force_copy: try: - os.symlink(src, dst) + 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 @@ -374,8 +383,10 @@ from threading import Thread from urllib.request import urlretrieve - # This is a placeholder URL - there are stale-data problems with - # the BitBucket CDN + # This version of distribute_setup.py fetches a + # venv-aware version of distribute + # This class won't be checked into Python, anyway, + # so it's just for exploring venvs url = 'http://www.red-dove.com/distribute_setup.py' binpath = context.bin_path distpath = os.path.join(binpath, 'distribute_setup.py') @@ -453,7 +464,12 @@ action='store_true', dest='system_site', help="Give the virtual environment access to the " "system site-packages dir. ") - parser.add_argument('--symlinks', default=False, + if os.name == 'nt' or (sys.platform == 'darwin' and + 'Library/Framework' in sys.base_prefix): + use_symlinks = False + else: + use_symlinks = True + parser.add_argument('--symlinks', default=use_symlinks, action='store_true', dest='symlinks', help="Attempt to symlink rather than copy.") parser.add_argument('--clear', default=False, action='store_true', @@ -462,11 +478,19 @@ 'exists. If not specified and ' 'the directory exists, an error' ' is raised.') + parser.add_argument('--upgrade', default=False, action='store_true', + dest='upgrade', help='Upgrade the environment ' + 'directory to use this version ' + 'of Python, assuming it has been ' + 'upgraded in-place.') options = parser.parse_args(args) + if options.upgrade and options.clear: + raise ValueError('you cannot supply --upgrade and --clear together.') # XXX This will be changed to EnvBuilder builder = DistributeEnvBuilder(system_site_packages=options.system_site, clear=options.clear, symlinks=options.symlinks, + upgrade=options.upgrade, nodist=options.nodist) for d in options.dirs: builder.create(d)