From 26d5f83132a57a284c8cd5d2914ed19c449b7654 Mon Sep 17 00:00:00 2001 From: Sam Vilain Date: Tue, 6 May 2014 15:20:37 -0700 Subject: [PATCH 1/2] Update shebang manipulation to work in more cases If a python interpreter is specified to virtualenv using, eg --python=python2.7, then this script ends up not rewriting the #! lines. Instead of a suffix match, check that they end with something that exists in the bin directory, and if so update them to point to that same thing in the new path. --- virtualenv_tools.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/virtualenv_tools.py b/virtualenv_tools.py index f5671c1..7ab6a85 100644 --- a/virtualenv_tools.py +++ b/virtualenv_tools.py @@ -52,7 +52,7 @@ def _handle_sub(match): f.writelines(lines) -def update_script(script_filename, new_path): +def update_script(script_filename, bin_dir, new_path): """Updates shebang lines for actual scripts.""" with open(script_filename) as f: lines = list(f) @@ -65,11 +65,15 @@ def update_script(script_filename, new_path): if not args: return - if not args[0].endswith('/bin/python') or \ - '/usr/bin/env python' in args[0]: + if args[0].endswith("bin/env"): + bin_file = args[1] + else: + _, bin_file = os.path.split(args[0]) + + if not os.path.exists(os.path.join(bin_dir, bin_file)): return - new_bin = os.path.join(new_path, 'bin', 'python') + new_bin = os.path.join(new_path, 'bin', bin_file) if new_bin == args[0]: return @@ -86,7 +90,7 @@ def update_scripts(bin_dir, new_path): if fn in ACTIVATION_SCRIPTS: update_activation_script(os.path.join(bin_dir, fn), new_path) else: - update_script(os.path.join(bin_dir, fn), new_path) + update_script(os.path.join(bin_dir, fn), bin_dir, new_path) def update_pyc(filename, new_path): From 49b89312a08d2cdbbdee8329c21fc7aba32032ef Mon Sep 17 00:00:00 2001 From: Sam Vilain Date: Tue, 6 May 2014 15:23:50 -0700 Subject: [PATCH 2/2] Add support for PyPy virtualenv directories PyPy uses a slightly different virtualenv layout; instead of lib/python2.7 you'll see lib-python/2.7; adapt accordingly. Also its bin/python ends up being a symlink. Finally, there is a bin/__pycache__ directory which needs skipping in update_script(). --- virtualenv_tools.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/virtualenv_tools.py b/virtualenv_tools.py index 7ab6a85..eecee6d 100644 --- a/virtualenv_tools.py +++ b/virtualenv_tools.py @@ -24,7 +24,7 @@ 'activate.csh', 'activate.fish' ] -_pybin_match = re.compile(r'^python\d+\.\d+$') +_pybin_match = re.compile(r'^lib[/-]python/?\d+\.\d+$') _activation_path_re = re.compile(r'^(?:set -gx |setenv |)VIRTUAL_ENV[ =]"(.*?)"\s*$') @@ -54,6 +54,8 @@ def _handle_sub(match): def update_script(script_filename, bin_dir, new_path): """Updates shebang lines for actual scripts.""" + if not os.path.isfile(script_filename): + return with open(script_filename) as f: lines = list(f) if not lines: @@ -171,19 +173,23 @@ def update_paths(base, new_path): return False bin_dir = os.path.join(base, 'bin') - base_lib_dir = os.path.join(base, 'lib') lib_dir = None lib_name = None - if os.path.isdir(base_lib_dir): - for folder in os.listdir(base_lib_dir): - if _pybin_match.match(folder): - lib_name = folder - lib_dir = os.path.join(base_lib_dir, folder) - break + for base_lib_dir in os.listdir(base): + if base_lib_dir.startswith("lib"): + subdir = os.path.join(base, base_lib_dir) + if os.path.isdir(subdir): + for folder in os.listdir(subdir): + if _pybin_match.match("/".join((base_lib_dir, folder))): + lib_name = folder + lib_dir = os.path.join(subdir, folder) + break + if lib_dir: + break if lib_dir is None or not os.path.isdir(bin_dir) \ - or not os.path.isfile(os.path.join(bin_dir, 'python')): + or not os.path.exists(os.path.join(bin_dir, 'python')): print 'error: %s does not refer to a python installation' % base return False