Permalink
Browse files

issue-1: issue-2: Chain extension virtualenvs in sys.path and in PATH.

  • Loading branch information...
1 parent 6af375b commit 9b954a8cc8ff57bcc05d3469f7fcb7fc65decdd9 Ben Weaver committed Mar 1, 2010
Showing with 74 additions and 18 deletions.
  1. +3 −6 bin/ve-extend
  2. +71 −12 vecmd/commands.py
View
@@ -1,12 +1,9 @@
#!/usr/bin/env python
-#### virtualenv-commands
-#### Extend an Environment
-
### Copyright (c) 2009, Coptix, Inc. All rights reserved.
### See the LICENSE file for license terms and warranty disclaimer.
-"""Extend a destination virtualenv with the source virtualenvs.
+"""ve-extend -- Extend a destination virtualenv with source virtualenvs.
Extending a virtual environment means "chaining" it to some other
source environments. Anything in the destination virtualenv overrides
@@ -33,10 +30,10 @@ def main(*args, **options):
print 'Nothing modified.'
return 0
- vecmd.write_extensions(dest, source)
+ vecmd.extend(dest, source)
print 'Done modifying "%s".' % dest
if options.get('verbose'):
- print 'sys.path = ', vecmd.sys_path(dest)
+ print '### sys.path ###\n', vecmd.sys_path(dest)
def confirm_existing(ve):
if vecmd.has_extensions(ve):
View
@@ -16,7 +16,7 @@
'create',
'virtualenv', 'python',
- 'has_extensions', 'extends_path', 'extends', 'write_extensions',
+ 'has_extensions', 'customize_path', 'extends', 'extend',
'clone'
)
@@ -32,10 +32,15 @@ def is_virtualenv(ve):
and os.path.isfile(interpreter(ve))
)
+def bin_folder(ve):
+ """Return a path to the bin folder of the virtualenv ve."""
+
+ return os.path.join(ve, 'bin')
+
def interpreter(ve):
"""Return a path to the python interpreter for the virtualenv ve."""
- return os.path.join(ve, 'bin/python')
+ return os.path.join(bin_folder(ve), 'python')
def version(ve):
"""Return the major.minor version of the python interpreter in
@@ -53,7 +58,7 @@ def without_site_packages(path):
return path.rsplit('/lib/', 2)[0]
def sys_path(ve):
- return python(ve, 'import sys; print sys.path')
+ return python(ve, """import sys; print '\\n'.join(sys.path)""")
### Command execution
@@ -86,33 +91,87 @@ def python(ve, command):
## site.addsitedir() recursively expands the directory (processes any
## `.pth' files, runs its sitecustomize.py, etc).
-EXTENDS = 'sitecustomize.py'
+ACTIVATE = """
+
+## extend() was automatically added by ve-extend
+extend () {
+ local ve="$1"
+ local ext="$ve/.extends"
+ if [ -e "$ext" ]; then
+ for item in `cat $ext | awk -F: '{print $1}'`; do
+ extend $item
+ done
+ fi
+ PATH="$ve/bin:$PATH"
+}
+extend $VIRTUAL_ENV
+"""
+
+CUSTOMIZE = """
+## This module was automatically generated by ve-extend.
+import os, site
+
+def extend(ve):
+ ext = os.path.join(ve, '.extends')
+ if os.path.exists(ext):
+ for line in open(ext, 'r'):
+ add(*line.strip().split(':'))
+
+def add(ve, version):
+ packages = os.path.join(ve, 'lib/python%s/site-packages' % version)
+ site.addsitedir(packages)
+ extend(ve)
+
+extend(os.path.join(os.path.dirname(__file__), '../../..'))
+"""
def has_extensions(ve):
return is_virtualenv(ve) and os.path.exists(extends_path(ve))
def extends_path(ve):
- return os.path.join(site_packages(ve), EXTENDS)
+ return os.path.join(ve, '.extends')
+
+def customize_path(ve):
+ return os.path.join(site_packages(ve), 'sitecustomize.py')
+
+def activate_path(ve):
+ return os.path.join(bin_folder(ve), 'activate')
def extends(ve):
if has_extensions(ve):
with extensions_file(ve) as port:
- return filter(None, (_extension_to_ve(l) for l in port.readlines()))
+ return filter(bool, (_extension_to_ve(l) for l in port))
return []
-def write_extensions(ve, extends):
+def extend(ve, extends):
+ _write_extensions(ve, extends)
+ _extend_activate(ve)
+ _customize(ve)
+
+def _write_extensions(ve, extends):
with extensions_file(ve, 'w') as port:
- print >> port, 'import site'
for source_ve in extends:
print >> port, _ve_to_extension(source_ve)
+def _extend_activate(ve):
+ with contextlib.closing(open(activate_path(ve), 'r+')) as port:
+ lines = port.readlines()
+ port.seek(0)
+ port.truncate()
+ for line in lines:
+ if line.startswith('PATH='):
+ line = ACTIVATE
+ print >> port, line,
+
+def _customize(ve):
+ with contextlib.closing(open(customize_path(ve), 'w')) as port:
+ print >> port, CUSTOMIZE
+
def _ve_to_extension(ve):
- return 'site.addsitedir("%s")' % os.path.abspath(site_packages(ve))
+ return '%s:%s' % (ve, version(ve))
-_EXTENSION = re.compile('site\.addsitedir\("([^"]+)"\)')
def _extension_to_ve(ext):
- match = _EXTENSION.match(ext)
- return match and without_site_packages(match.group(1))
+ return ext.strip().split(':')[0]
def extensions_file(ve, *args):
assert is_virtualenv(ve)

0 comments on commit 9b954a8

Please sign in to comment.