Doug Hellmann avatar Doug Hellmann committed 0340455 Merge

merge 2.0 changes into tip

Comments (0)

Files changed (45)

 syntax: glob
+distribute*.egg
+distribute*.tar.gz
 README.html
 virtualenvwrapper.egg-info
-paver-minilib.zip
-setup.py
 trace.txt
-docs
+dist
+docs/build
+docs/website
 *.pyc
 sphinx/web/templates/base.html
 tests/catch_output
 tests/testpackage/build
 tests/testpackage/dist
 tests/testpackage/testpackage.egg-info
+virtualenvwrapper/docs
 
 syntax: re
 .DS_Store
 include setup.py
-include paver-minilib.zip
-include pavement.py
+include distribute_setup.py
 include tests/*
 recursive-include virtualenvwrapper *.html *.txt *.css *.js *.png
-recursive-include docsource *.rst
+recursive-include docs *.rst
+# Get the version of the app.  This is used in the doc build.
+export VERSION=$(shell python setup.py --version)
+
+# Default target is to build the source distribution.
+.PHONY: sdist
+sdist: html
+	python setup.py sdist
+
+# Documentation
+.PHONY: html
+html:
+	rm -rf virtualenvwrapper/docs
+	(cd docs && $(MAKE) html SPHINXOPTS="-c sphinx/pkg")
+	cp -r docs/build/html virtualenvwrapper/docs
+
+# Website copy of documentation
+.PHONY: website
+website: docs/sphinx/web/templates/base.html
+	rm -rf docs/website
+	(cd docs && $(MAKE) html SPHINXOPTS="-c sphinx/web" BUILDDIR="website")
+
+installwebsite: website
+	(cd docs/website/html && rsync --rsh=ssh --archive --delete --verbose . www.doughellmann.com:/var/www/doughellmann/DocumentRoot/docs/virtualenvwrapper2/)
+
+# Register the new version on pypi
+.PHONY: register
+register:
+	python setup.py register
+
+# Copy the base template from my website build directory
+docs/sphinx/web/templates/base.html: ~/Devel/doughellmann/doughellmann/templates/base.html
+	cp $< $@
+
+# Testing
+TEST_SCRIPTS=$(wildcard tests/test*.sh)
+
+.PHONY: develop test test-bash test-sh test-zsh test-loop test-install
+test: develop test-bash test-sh test-zsh test-install
+
+develop:
+	python setup.py develop
+
+test-bash:
+	TEST_SHELL=bash $(MAKE) test-loop
+
+test-sh:
+	TEST_SHELL=sh $(MAKE) test-loop
+
+test-zsh:
+	TEST_SHELL="zsh -o shwordsplit" $(MAKE) test-loop
+
+test-loop:
+	@for test_script in $(wildcard tests/test*.sh) ; do \
+	 	echo '********************************************************************************' ; \
+		echo "Running $$test_script with $(TEST_SHELL)" ; \
+		SHUNIT_PARENT=$$test_script $(TEST_SHELL) $$test_script || exit 1 ; \
+		echo ; \
+	done
+
+test-install:
+	bash ./tests/manual_test_install.sh `pwd`/dist "$(VERSION)"

README

-#################
-virtualenvwrapper
-#################
-
-virtualenvwrapper is a set of extensions to Ian Bicking's `virtualenv
-<http://pypi.python.org/pypi/virtualenv>`_ tool.  The extensions include
-wrappers for creating and deleting virtual environments and otherwise
-managing your development workflow, making it easier to work on more
-than one project at a time without introducing conflicts in their
-dependencies.
-
-========
-Features
-========
-
-1.  Organizes all of your virtual environments in one place.
-
-2.  Wrappers for creating, copying and deleting environments, including
-    user-configurable hooks.
-
-3.  Use a single command to switch between environments.
-
-4.  Tab completion for commands that take a virtual environment as
-    argument.
-
-Rich Leland has created a short `screencast
-<http://mathematism.com/2009/jul/30/presentation-pip-and-virtualenv/>`__
-showing off the features of virtualenvwrapper.
-
-===========
-Quick Setup
-===========
-
-1. Create a directory to hold all of the virtual environments. The default is
-   ``$HOME/.virtualenvs``.
-
-2. Add two lines to your .bashrc to set the location where the virtual environments should
-   live and the location of the script installed with this package::
-
-    export WORKON_HOME=$HOME/.virtualenvs
-    source /usr/local/bin/virtualenvwrapper_bashrc
-
-3. Run: ``source ~/.bashrc``
-4. Run: ``workon``
-5. A list of environments, empty, is printed.
-6. Run: ``mkvirtualenv temp``
-7. A new environment, ``temp`` is created and activated.
-8. Run: ``workon``
-9. This time, the ``temp`` environment is included.
-
-=======
-License
-=======
-
-Copyright Doug Hellmann, All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Doug Hellmann not be used
-in advertising or publicity pertaining to distribution of the software
-without specific, written prior permission.
-
-DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
-INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
-EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
-CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
-USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
-OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE.
+#################
+virtualenvwrapper
+#################
+
+virtualenvwrapper is a set of extensions to Ian Bicking's `virtualenv
+<http://pypi.python.org/pypi/virtualenv>`_ tool.  The extensions include
+wrappers for creating and deleting virtual environments and otherwise
+managing your development workflow, making it easier to work on more
+than one project at a time without introducing conflicts in their
+dependencies.
+
+========
+Features
+========
+
+1.  Organizes all of your virtual environments in one place.
+
+2.  Wrappers for creating, copying and deleting environments, including
+    user-configurable hooks.
+
+3.  Use a single command to switch between environments.
+
+4.  Tab completion for commands that take a virtual environment as
+    argument.
+
+5. User-configurable hooks for all operations.
+
+6. Plugin system for more creating sharable extensions.
+
+Rich Leland has created a short `screencast
+<http://mathematism.com/2009/jul/30/presentation-pip-and-virtualenv/>`__
+showing off the features of virtualenvwrapper.
+
+===========
+Quick Setup
+===========
+
+1. Create a directory to hold all of the virtual environments. The default is
+   ``$HOME/.virtualenvs``.
+
+2. Add two lines to your shell startup file (``.bashrc``,
+   ``.profile``, etc.) to set the location where the virtual
+   environments should live and the location of the script installed
+   with this package::
+
+    export WORKON_HOME=$HOME/.virtualenvs
+    source /usr/local/bin/virtualenvwrapper.sh
+
+3. Reload the startup file (e.g., run: ``source ~/.bashrc``).
+4. Run: ``workon``
+5. A list of environments, empty, is printed.
+6. Run: ``mkvirtualenv temp``
+7. A new environment, ``temp`` is created and activated.
+8. Run: ``workon``
+9. This time, the ``temp`` environment is included.
+
+Upgrading from 1.x
+==================
+
+The shell script containing the wrapper functions has been renamed in
+the 2.x series to reflect the fact that shells other than bash are
+supported.  In your startup file, change ``source
+/usr/local/bin/virtualenvwrapper_bashrc`` to ``source
+/usr/local/bin/virtualenvwrapper.sh``.
+
+=======
+License
+=======
+
+Copyright Doug Hellmann, All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Doug Hellmann not be used
+in advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.
+
+DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.

distribute_setup.py

+#!python
+"""Bootstrap distribute installation
+
+If you want to use setuptools in your package's setup.py, just include this
+file in the same directory with it, and add this to the top of your setup.py::
+
+    from distribute_setup import use_setuptools
+    use_setuptools()
+
+If you want to require a specific version of setuptools, set a download
+mirror, or use an alternate download directory, you can do so by supplying
+the appropriate options to ``use_setuptools()``.
+
+This file can also be run as a script to install or upgrade setuptools.
+"""
+import os
+import sys
+import time
+import fnmatch
+import tempfile
+import tarfile
+from distutils import log
+
+try:
+    from site import USER_SITE
+except ImportError:
+    USER_SITE = None
+
+try:
+    import subprocess
+
+    def _python_cmd(*args):
+        args = (sys.executable,) + args
+        return subprocess.call(args) == 0
+
+except ImportError:
+    # will be used for python 2.3
+    def _python_cmd(*args):
+        args = (sys.executable,) + args
+        # quoting arguments if windows
+        if sys.platform == 'win32':
+            def quote(arg):
+                if ' ' in arg:
+                    return '"%s"' % arg
+                return arg
+            args = [quote(arg) for arg in args]
+        return os.spawnl(os.P_WAIT, sys.executable, *args) == 0
+
+DEFAULT_VERSION = "0.6.10"
+DEFAULT_URL = "http://pypi.python.org/packages/source/d/distribute/"
+SETUPTOOLS_FAKED_VERSION = "0.6c11"
+
+SETUPTOOLS_PKG_INFO = """\
+Metadata-Version: 1.0
+Name: setuptools
+Version: %s
+Summary: xxxx
+Home-page: xxx
+Author: xxx
+Author-email: xxx
+License: xxx
+Description: xxx
+""" % SETUPTOOLS_FAKED_VERSION
+
+
+def _install(tarball):
+    # extracting the tarball
+    tmpdir = tempfile.mkdtemp()
+    log.warn('Extracting in %s', tmpdir)
+    old_wd = os.getcwd()
+    try:
+        os.chdir(tmpdir)
+        tar = tarfile.open(tarball)
+        _extractall(tar)
+        tar.close()
+
+        # going in the directory
+        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+        os.chdir(subdir)
+        log.warn('Now working in %s', subdir)
+
+        # installing
+        log.warn('Installing Distribute')
+        if not _python_cmd('setup.py', 'install'):
+            log.warn('Something went wrong during the installation.')
+            log.warn('See the error message above.')
+    finally:
+        os.chdir(old_wd)
+
+
+def _build_egg(egg, tarball, to_dir):
+    # extracting the tarball
+    tmpdir = tempfile.mkdtemp()
+    log.warn('Extracting in %s', tmpdir)
+    old_wd = os.getcwd()
+    try:
+        os.chdir(tmpdir)
+        tar = tarfile.open(tarball)
+        _extractall(tar)
+        tar.close()
+
+        # going in the directory
+        subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0])
+        os.chdir(subdir)
+        log.warn('Now working in %s', subdir)
+
+        # building an egg
+        log.warn('Building a Distribute egg in %s', to_dir)
+        _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir)
+
+    finally:
+        os.chdir(old_wd)
+    # returning the result
+    log.warn(egg)
+    if not os.path.exists(egg):
+        raise IOError('Could not build the egg.')
+
+
+def _do_download(version, download_base, to_dir, download_delay):
+    egg = os.path.join(to_dir, 'distribute-%s-py%d.%d.egg'
+                       % (version, sys.version_info[0], sys.version_info[1]))
+    if not os.path.exists(egg):
+        tarball = download_setuptools(version, download_base,
+                                      to_dir, download_delay)
+        _build_egg(egg, tarball, to_dir)
+    sys.path.insert(0, egg)
+    import setuptools
+    setuptools.bootstrap_install_from = egg
+
+
+def use_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+                   to_dir=os.curdir, download_delay=15, no_fake=True):
+    # making sure we use the absolute path
+    to_dir = os.path.abspath(to_dir)
+    was_imported = 'pkg_resources' in sys.modules or \
+        'setuptools' in sys.modules
+    try:
+        try:
+            import pkg_resources
+            if not hasattr(pkg_resources, '_distribute'):
+                if not no_fake:
+                    _fake_setuptools()
+                raise ImportError
+        except ImportError:
+            return _do_download(version, download_base, to_dir, download_delay)
+        try:
+            pkg_resources.require("distribute>="+version)
+            return
+        except pkg_resources.VersionConflict:
+            e = sys.exc_info()[1]
+            if was_imported:
+                sys.stderr.write(
+                "The required version of distribute (>=%s) is not available,\n"
+                "and can't be installed while this script is running. Please\n"
+                "install a more recent version first, using\n"
+                "'easy_install -U distribute'."
+                "\n\n(Currently using %r)\n" % (version, e.args[0]))
+                sys.exit(2)
+            else:
+                del pkg_resources, sys.modules['pkg_resources']    # reload ok
+                return _do_download(version, download_base, to_dir,
+                                    download_delay)
+        except pkg_resources.DistributionNotFound:
+            return _do_download(version, download_base, to_dir,
+                                download_delay)
+    finally:
+        if not no_fake:
+            _create_fake_setuptools_pkg_info(to_dir)
+
+def download_setuptools(version=DEFAULT_VERSION, download_base=DEFAULT_URL,
+                        to_dir=os.curdir, delay=15):
+    """Download distribute from a specified location and return its filename
+
+    `version` should be a valid distribute version number that is available
+    as an egg for download under the `download_base` URL (which should end
+    with a '/'). `to_dir` is the directory where the egg will be downloaded.
+    `delay` is the number of seconds to pause before an actual download
+    attempt.
+    """
+    # making sure we use the absolute path
+    to_dir = os.path.abspath(to_dir)
+    try:
+        from urllib.request import urlopen
+    except ImportError:
+        from urllib2 import urlopen
+    tgz_name = "distribute-%s.tar.gz" % version
+    url = download_base + tgz_name
+    saveto = os.path.join(to_dir, tgz_name)
+    src = dst = None
+    if not os.path.exists(saveto):  # Avoid repeated downloads
+        try:
+            log.warn("Downloading %s", url)
+            src = urlopen(url)
+            # Read/write all in one block, so we don't create a corrupt file
+            # if the download is interrupted.
+            data = src.read()
+            dst = open(saveto, "wb")
+            dst.write(data)
+        finally:
+            if src:
+                src.close()
+            if dst:
+                dst.close()
+    return os.path.realpath(saveto)
+
+
+def _patch_file(path, content):
+    """Will backup the file then patch it"""
+    existing_content = open(path).read()
+    if existing_content == content:
+        # already patched
+        log.warn('Already patched.')
+        return False
+    log.warn('Patching...')
+    _rename_path(path)
+    f = open(path, 'w')
+    try:
+        f.write(content)
+    finally:
+        f.close()
+    return True
+
+
+def _same_content(path, content):
+    return open(path).read() == content
+
+def _no_sandbox(function):
+    def __no_sandbox(*args, **kw):
+        try:
+            from setuptools.sandbox import DirectorySandbox
+            def violation(*args):
+                pass
+            DirectorySandbox._old = DirectorySandbox._violation
+            DirectorySandbox._violation = violation
+            patched = True
+        except ImportError:
+            patched = False
+
+        try:
+            return function(*args, **kw)
+        finally:
+            if patched:
+                DirectorySandbox._violation = DirectorySandbox._old
+                del DirectorySandbox._old
+
+    return __no_sandbox
+
+@_no_sandbox
+def _rename_path(path):
+    new_name = path + '.OLD.%s' % time.time()
+    log.warn('Renaming %s into %s', path, new_name)
+    os.rename(path, new_name)
+    return new_name
+
+def _remove_flat_installation(placeholder):
+    if not os.path.isdir(placeholder):
+        log.warn('Unkown installation at %s', placeholder)
+        return False
+    found = False
+    for file in os.listdir(placeholder):
+        if fnmatch.fnmatch(file, 'setuptools*.egg-info'):
+            found = True
+            break
+    if not found:
+        log.warn('Could not locate setuptools*.egg-info')
+        return
+
+    log.warn('Removing elements out of the way...')
+    pkg_info = os.path.join(placeholder, file)
+    if os.path.isdir(pkg_info):
+        patched = _patch_egg_dir(pkg_info)
+    else:
+        patched = _patch_file(pkg_info, SETUPTOOLS_PKG_INFO)
+
+    if not patched:
+        log.warn('%s already patched.', pkg_info)
+        return False
+    # now let's move the files out of the way
+    for element in ('setuptools', 'pkg_resources.py', 'site.py'):
+        element = os.path.join(placeholder, element)
+        if os.path.exists(element):
+            _rename_path(element)
+        else:
+            log.warn('Could not find the %s element of the '
+                     'Setuptools distribution', element)
+    return True
+
+
+def _after_install(dist):
+    log.warn('After install bootstrap.')
+    placeholder = dist.get_command_obj('install').install_purelib
+    _create_fake_setuptools_pkg_info(placeholder)
+
+@_no_sandbox
+def _create_fake_setuptools_pkg_info(placeholder):
+    if not placeholder or not os.path.exists(placeholder):
+        log.warn('Could not find the install location')
+        return
+    pyver = '%s.%s' % (sys.version_info[0], sys.version_info[1])
+    setuptools_file = 'setuptools-%s-py%s.egg-info' % \
+            (SETUPTOOLS_FAKED_VERSION, pyver)
+    pkg_info = os.path.join(placeholder, setuptools_file)
+    if os.path.exists(pkg_info):
+        log.warn('%s already exists', pkg_info)
+        return
+
+    log.warn('Creating %s', pkg_info)
+    f = open(pkg_info, 'w')
+    try:
+        f.write(SETUPTOOLS_PKG_INFO)
+    finally:
+        f.close()
+
+    pth_file = os.path.join(placeholder, 'setuptools.pth')
+    log.warn('Creating %s', pth_file)
+    f = open(pth_file, 'w')
+    try:
+        f.write(os.path.join(os.curdir, setuptools_file))
+    finally:
+        f.close()
+
+def _patch_egg_dir(path):
+    # let's check if it's already patched
+    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+    if os.path.exists(pkg_info):
+        if _same_content(pkg_info, SETUPTOOLS_PKG_INFO):
+            log.warn('%s already patched.', pkg_info)
+            return False
+    _rename_path(path)
+    os.mkdir(path)
+    os.mkdir(os.path.join(path, 'EGG-INFO'))
+    pkg_info = os.path.join(path, 'EGG-INFO', 'PKG-INFO')
+    f = open(pkg_info, 'w')
+    try:
+        f.write(SETUPTOOLS_PKG_INFO)
+    finally:
+        f.close()
+    return True
+
+
+def _before_install():
+    log.warn('Before install bootstrap.')
+    _fake_setuptools()
+
+
+def _under_prefix(location):
+    if 'install' not in sys.argv:
+        return True
+    args = sys.argv[sys.argv.index('install')+1:]
+    for index, arg in enumerate(args):
+        for option in ('--root', '--prefix'):
+            if arg.startswith('%s=' % option):
+                top_dir = arg.split('root=')[-1]
+                return location.startswith(top_dir)
+            elif arg == option:
+                if len(args) > index:
+                    top_dir = args[index+1]
+                    return location.startswith(top_dir)
+            elif option == '--user' and USER_SITE is not None:
+                return location.startswith(USER_SITE)
+    return True
+
+
+def _fake_setuptools():
+    log.warn('Scanning installed packages')
+    try:
+        import pkg_resources
+    except ImportError:
+        # we're cool
+        log.warn('Setuptools or Distribute does not seem to be installed.')
+        return
+    ws = pkg_resources.working_set
+    try:
+        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools',
+                                  replacement=False))
+    except TypeError:
+        # old distribute API
+        setuptools_dist = ws.find(pkg_resources.Requirement.parse('setuptools'))
+
+    if setuptools_dist is None:
+        log.warn('No setuptools distribution found')
+        return
+    # detecting if it was already faked
+    setuptools_location = setuptools_dist.location
+    log.warn('Setuptools installation detected at %s', setuptools_location)
+
+    # if --root or --preix was provided, and if
+    # setuptools is not located in them, we don't patch it
+    if not _under_prefix(setuptools_location):
+        log.warn('Not patching, --root or --prefix is installing Distribute'
+                 ' in another location')
+        return
+
+    # let's see if its an egg
+    if not setuptools_location.endswith('.egg'):
+        log.warn('Non-egg installation')
+        res = _remove_flat_installation(setuptools_location)
+        if not res:
+            return
+    else:
+        log.warn('Egg installation')
+        pkg_info = os.path.join(setuptools_location, 'EGG-INFO', 'PKG-INFO')
+        if (os.path.exists(pkg_info) and
+            _same_content(pkg_info, SETUPTOOLS_PKG_INFO)):
+            log.warn('Already patched.')
+            return
+        log.warn('Patching...')
+        # let's create a fake egg replacing setuptools one
+        res = _patch_egg_dir(setuptools_location)
+        if not res:
+            return
+    log.warn('Patched done.')
+    _relaunch()
+
+
+def _relaunch():
+    log.warn('Relaunching...')
+    # we have to relaunch the process
+    args = [sys.executable] + sys.argv
+    sys.exit(subprocess.call(args))
+
+
+def _extractall(self, path=".", members=None):
+    """Extract all members from the archive to the current working
+       directory and set owner, modification time and permissions on
+       directories afterwards. `path' specifies a different directory
+       to extract to. `members' is optional and must be a subset of the
+       list returned by getmembers().
+    """
+    import copy
+    import operator
+    from tarfile import ExtractError
+    directories = []
+
+    if members is None:
+        members = self
+
+    for tarinfo in members:
+        if tarinfo.isdir():
+            # Extract directories with a safe mode.
+            directories.append(tarinfo)
+            tarinfo = copy.copy(tarinfo)
+            tarinfo.mode = 448 # decimal for oct 0700
+        self.extract(tarinfo, path)
+
+    # Reverse sort directories.
+    if sys.version_info < (2, 4):
+        def sorter(dir1, dir2):
+            return cmp(dir1.name, dir2.name)
+        directories.sort(sorter)
+        directories.reverse()
+    else:
+        directories.sort(key=operator.attrgetter('name'), reverse=True)
+
+    # Set correct owner, mtime and filemode on directories.
+    for tarinfo in directories:
+        dirpath = os.path.join(path, tarinfo.name)
+        try:
+            self.chown(tarinfo, dirpath)
+            self.utime(tarinfo, dirpath)
+            self.chmod(tarinfo, dirpath)
+        except ExtractError:
+            e = sys.exc_info()[1]
+            if self.errorlevel > 1:
+                raise
+            else:
+                self._dbg(1, "tarfile: %s" % e)
+
+
+def main(argv, version=DEFAULT_VERSION):
+    """Install or upgrade setuptools and EasyInstall"""
+    tarball = download_setuptools()
+    _install(tarball)
+
+
+if __name__ == '__main__':
+    main(sys.argv[1:])
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS    =
+SPHINXBUILD   = sphinx-build
+PAPER         =
+BUILDDIR      = build
+
+# Internal variables.
+PAPEROPT_a4     = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source
+
+.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+help:
+	@echo "Please use \`make <target>' where <target> is one of"
+	@echo "  html      to make standalone HTML files"
+	@echo "  dirhtml   to make HTML files named index.html in directories"
+	@echo "  pickle    to make pickle files"
+	@echo "  json      to make JSON files"
+	@echo "  htmlhelp  to make HTML files and a HTML help project"
+	@echo "  qthelp    to make HTML files and a qthelp project"
+	@echo "  latex     to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
+	@echo "  changes   to make an overview of all changed/added/deprecated items"
+	@echo "  linkcheck to check all external links for integrity"
+	@echo "  doctest   to run all doctests embedded in the documentation (if enabled)"
+
+clean:
+	-rm -rf $(BUILDDIR)/*
+
+html:
+	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
+
+dirhtml:
+	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
+	@echo
+	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
+
+pickle:
+	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
+	@echo
+	@echo "Build finished; now you can process the pickle files."
+
+json:
+	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
+	@echo
+	@echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
+	@echo
+	@echo "Build finished; now you can run HTML Help Workshop with the" \
+	      ".hhp project file in $(BUILDDIR)/htmlhelp."
+
+qthelp:
+	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
+	@echo
+	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
+	      ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
+	@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/virtualenvwrapper.qhcp"
+	@echo "To view the help file:"
+	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/virtualenvwrapper.qhc"
+
+latex:
+	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
+	@echo
+	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
+	@echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+	      "run these through (pdf)latex."
+
+changes:
+	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
+	@echo
+	@echo "The overview file is in $(BUILDDIR)/changes."
+
+linkcheck:
+	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
+	@echo
+	@echo "Link check complete; look for any errors in the above output " \
+	      "or in $(BUILDDIR)/linkcheck/output.txt."
+
+doctest:
+	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
+	@echo "Testing of doctests in the sources finished, look at the " \
+	      "results in $(BUILDDIR)/doctest/output.txt."

docs/source/command_ref.rst

+.. Quick reference documentation for virtualenvwrapper command line functions
+    Originally contributed Thursday, May 28, 2009 by Steve Steiner (ssteinerX@gmail.com)
+
+#################
+Command Reference
+#################
+
+All of the commands below are to be used on the Terminal command line.
+
+=====================
+Managing Environments
+=====================
+
+mkvirtualenv
+------------
+
+Create a new environment, in the WORKON_HOME.
+
+Syntax::
+
+    mkvirtualenv [options] ENVNAME
+
+(any options are passed directly to ``virtualenv``)
+
+.. seealso::
+
+   * :ref:`scripts-premkvirtualenv`
+   * :ref:`scripts-postmkvirtualenv`
+
+rmvirtualenv
+------------
+
+Remove an environment, in the WORKON_HOME.
+
+Syntax::
+
+    rmvirtualenv ENVNAME
+
+.. seealso::
+
+   * :ref:`scripts-prermvirtualenv`
+   * :ref:`scripts-postrmvirtualenv`
+
+cpvirtualenv
+------------
+
+Duplicate an environment, in the WORKON_HOME.
+
+Syntax::
+
+    cpvirtualenv ENVNAME TARGETENVNAME
+
+.. note::
+
+   The environment created by the copy operation is made `relocatable
+   <http://virtualenv.openplans.org/#making-environments-relocatable>`__.
+
+==================================
+Controlling the Active Environment
+==================================
+
+workon
+------
+
+List or change working virtual environments
+
+Syntax::
+
+    workon [environment_name]
+
+If no ``environment_name`` is given the list of available environments
+is printed to stdout.
+
+.. seealso::
+
+   * :ref:`scripts-predeactivate`
+   * :ref:`scripts-postdeactivate`
+   * :ref:`scripts-preactivate`
+   * :ref:`scripts-postactivate`
+
+deactivate
+----------
+
+Switch from a virtual environment to the system-installed version of
+Python.
+
+Syntax::
+
+    deactivate
+
+.. note::
+
+    This command is actually part of virtualenv, but is wrapped to
+    provide before and after hooks, just as workon does for activate.
+
+.. seealso::
+
+   * :ref:`scripts-predeactivate`
+   * :ref:`scripts-postdeactivate`
+
+==================================
+Quickly Navigating to a virtualenv
+==================================
+
+There are two functions to provide shortcuts to navigate into the the
+currently-active virtualenv.
+
+cdvirtualenv
+------------
+
+Change the current working directory to ``$VIRTUAL_ENV``.
+
+Syntax::
+
+    cdvirtualenv [subdir]
+
+Calling ``cdvirtualenv`` changes the current working directory to the
+top of the virtualenv (``$VIRTUAL_ENV``).  An optional argument is
+appended to the path, allowing navigation directly into a
+subdirectory.
+
+::
+
+  $ workon pymotw
+  $ echo $VIRTUAL_ENV
+  /Users/dhellmann/.virtualenvs/pymotw
+  $ cdvirtualenv
+  $ pwd
+  /Users/dhellmann/.virtualenvs/pymotw
+  $ cdvirtualenv bin
+  $ pwd
+  /Users/dhellmann/.virtualenvs/pymotw/bin
+
+cdsitepackages
+--------------
+
+Change the current working directory to the ``site-packages`` for
+``$VIRTUAL_ENV``.
+
+Syntax::
+
+    cdsitepackages [subdir]
+
+Because the exact path to the site-packages directory in the
+virtualenv depends on the version of Python, ``cdsitepackages`` is
+provided as a shortcut for ``cdvirtualenv
+lib/python${pyvers}/site-packages``. An optional argument is also
+allowed, to specify a directory hierarchy within the ``site-packages``
+directory to change into.
+
+::
+
+  $ workon pymotw
+  $ echo $VIRTUAL_ENV
+  /Users/dhellmann/.virtualenvs/pymotw
+  $ cdsitepackages PyMOTW/bisect/
+  $ pwd
+  /Users/dhellmann/.virtualenvs/pymotw/lib/python2.6/site-packages/PyMOTW/bisect
+
+lssitepackages
+--------------
+
+Calling ``lssitepackages`` shows the content of the ``site-packages``
+directory of the currently-active virtualenv.
+
+Syntax::
+
+    lssitepackages
+
+===============
+Path Management
+===============
+
+add2virtualenv
+--------------
+
+Adds the specified directories to the Python path for the
+currently-active virtualenv.
+
+Syntax::
+
+    add2virtualenv directory1 directory2 ...
+
+Sometimes it is desirable to share installed packages that are not in
+the system ``site-pacakges`` directory and which should not be
+installed in each virtualenv.  One possible solution is to symlink the
+source into the environment ``site-packages`` directory, but it is
+also easy to add extra directories to the PYTHONPATH by including them
+in a ``.pth`` file inside ``site-packages`` using ``add2virtualenv``.
+
+1. Check out the source for a big project, such as Django.
+2. Run: ``add2virtualenv path_to_source``.
+3. Run: ``add2virtualenv``.
+4. A usage message and list of current "extra" paths is printed.
+
+The directory names are added to a path file named
+``virtualenv_path_extensions.pth`` inside the site-packages directory
+for the environment.
+
+*Based on a contribution from James Bennett and Jannis Leidel.*

docs/source/developers.rst

+##############
+For Developers
+##############
+
+If you would like to contribute to virtualenvwrapper directly, these
+instructions should help you get started.  Patches, bug reports, and
+feature requests are all welcome through the `BitBucket site
+<http://bitbucket.org/dhellmann/virtualenvwrapper/>`_.  Contributions
+in the form of patches or pull requests are easier to integrate and
+will receive priority attention.
+
+Building Documentation
+======================
+
+The documentation for virtualenvwrapper is written in reStructuredText
+and converted to HTML using Sphinx. The build itself is driven by
+make.  You will need the following packages in order to build the
+docs:
+
+- Sphinx
+- docutils
+
+Once all of the tools are installed into a virtualenv using
+pip, run ``make html`` to generate the HTML version of the
+documentation::
+
+    $ make html
+    rm -rf virtualenvwrapper/docs
+    (cd docs && make html SPHINXOPTS="-c sphinx/pkg")
+    sphinx-build -b html -d build/doctrees  -c sphinx/pkg source build/html
+    Running Sphinx v0.6.4
+    loading pickled environment... done
+    building [html]: targets for 2 source files that are out of date
+    updating environment: 0 added, 2 changed, 0 removed
+    reading sources... [ 50%] command_ref
+    reading sources... [100%] developers
+    
+    looking for now-outdated files... none found
+    pickling environment... done
+    checking consistency... done
+    preparing documents... done
+    writing output... [ 33%] command_ref
+    writing output... [ 66%] developers
+    writing output... [100%] index
+    
+    writing additional files... search
+    copying static files... WARNING: static directory '/Users/dhellmann/Devel/virtualenvwrapper/plugins/docs/sphinx/pkg/static' does not exist
+    done
+    dumping search index... done
+    dumping object inventory... done
+    build succeeded, 1 warning.
+    
+    Build finished. The HTML pages are in build/html.
+    cp -r docs/build/html virtualenvwrapper/docs
+    
+The output version of the documentation ends up in
+``./virtualenvwrapper/docs`` inside your sandbox.
+
+Running Tests
+=============
+
+The test suite for virtualenvwrapper uses `shunit2
+<http://shunit2.googlecode.com/>`_.  To run the tests under bash, sh,
+and zsh, use ``make test``.  To add new tests, modify or create an
+appropriate script in the ``tests`` directory.

docs/source/extensions.rst

+=====================
+ Existing Extensions
+=====================
+
+Below is a list of some of the extensions available for use with
+virtualenvwrapper.
+
+.. _extensions-user_scripts:
+
+user_scripts
+============
+
+The ``user_scripts`` extension is delivered with virtualenvwrapper and
+enabled by default.  It implements the user customization script
+features described in :ref:`scripts`.

docs/source/history.rst

+===============
+Release History
+===============
+
+2.0
+
+  - Rewrote hook management using Distribute_ entry points to make it
+    easier to share extensions.
+
+.. _Distribute: http://packages.python.org/distribute/
+
+1.27
+  
+  - Added cpvirtualenv command [Thomas Desvenain]
+
+1.26
+
+  - Fix a problem with error messages showing up during init for users
+    with the wrappers installed site-wide but who are not actually
+    using them.  See issue #26.
+  - Split up the tests into multiple files.
+  - Run all tests with all supported shells.
+
+1.25
+
+  - Merged in changes to cdsitepackages from William McVey.  It now
+    takes an argument and supports tab-completion for directories
+    within site-packages.
+
+1.24.2
+
+  - Add user provided :ref:`tips-and-tricks` section.
+  - Add link to Rich Leland's screencast to :ref:`references` section.
+
+1.24.1
+
+  - Add license text to the header of the script.
+
+1.24
+
+  - Resolve a bug with the preactivate hook not being run properly.
+    Refer to issue #21 for complete details.
+
+1.23
+
+  - Resolve a bug with the postmkvirtualenv hook not being run
+    properly.  Refer to issues #19 and #20 for complete details.
+
+1.22
+
+  - Automatically create any missing hook scripts as stubs with
+    comments to expose the feature in case users are not aware of it.
+
+1.21
+
+  - Better protection of ``$WORKON_HOME`` does not exist when the wrapper script is sourced.
+
+1.20
+
+  - Incorporate lssitepackages feature from Sander Smits.
+  - Refactor some of the functions that were using copy-and-paste code to build path names.
+  - Add a few tests.
+
+1.19
+
+  - Fix problem with add2virtualenv and relative paths. Thanks to Doug Latornell for the bug report James Bennett for the suggested fix.
+
+1.18.1
+
+  - Incorporate patch from Sascha Brossmann to fix a issue #15. Directory normalization was causing ``WORKON_HOME`` to appear to be a missing directory if there were control characters in the output of ``pwd``.
+
+1.18
+
+  - Remove warning during installation if sphinxcontrib.paverutils is not installed. (#10)
+  - Added some basic developer information to the documentation.
+  - Added documentation for deactivate command.
+
+1.17
+
+  - Added documentation updates provided by Steve Steiner.
+
+1.16
+
+  - Merged in changes to ``cdvirtualenv`` from wam and added tests and docs.
+  - Merged in changes to make error messages go to stderr, also provided by wam.
+
+1.15
+  - Better error handling in mkvirtualenv.
+  - Remove bogus VIRTUALENV_WRAPPER_BIN variable.
+
+1.14
+  - Wrap the virtualenv version of deactivate() with one that lets us invoke
+    the predeactivate hooks.
+  - Fix virtualenvwrapper_show_workon_options for colorized versions of ls and
+    write myself a note so I don't break it again later.
+  - Convert test.sh to use true tests with `shunit2 <http://shunit2.googlecode.com/>`_
+
+1.13
+  - Fix issue #5 by correctly handling symlinks and limiting the list of envs to things 
+    that look like they can be activated.
+
+1.12
+  - Check return value of virtualenvwrapper_verify_workon_home everywhere, thanks to 
+    Jeff Forcier for pointing out the errors.
+  - Fix instructions at top of README, pointed out by Matthew Scott.
+  - Add cdvirtualenv and cdsitepackages, contributed by James Bennett.
+  - Enhance test.sh.
+
+1.11
+  - Optimize virtualenvwrapper_show_workon_options.
+  - Add global postactivate hook.
+
+1.10
+  - Pull in fix for colorized ls from Jeff Forcier (b42a25f7b74a).
+
+1.9
+  - Add more hooks for operations to run before and after creating or deleting environments based on changes from Chris Hasenpflug.
+
+1.8.1
+  - Corrected a problem with change to mkvirtualenv that lead to release 1.8 by using an alternate fix proposed by James in comments on release 1.4.
+
+1.8
+  - Fix for processing the argument list in mkvirtualenv from jorgevargas (BitBucket issue #1)
+
+1.7
+  - Move to bitbucket.org for hosting
+  - clean up TODO list and svn keywords
+  - add license section below
+
+1.6.1
+
+  - More zsh support (fixes to rmvirtualenv) from Byron Clark.
+
+1.6
+
+  - Add completion support for zsh, courtesy of Ted Leung.
+
+1.5
+
+  - Fix some issues with spaces in directory or env names.  They still don't really work with virtualenv, though.
+  - Added documentation for the postactivate and predeactivate scripts.
+
+1.4
+
+  - Includes a new .pth management function based on work contributed by James Bennett and Jannis Leidel.
+
+1.3.x
+
+  - Includes a fix for a nasty bug in rmvirtualenv identified by John Shimek.

docs/source/hooks.rst

+===============================
+ Customizing Virtualenvwrapper
+===============================
+
+virtualenvwrapper adds several hook points you can use to change your
+settings, shell environment, or other configuration values when
+creating, deleting, or moving between environments. These hooks are
+exposed in two ways:
+
+.. toctree::
+   :maxdepth: 1
+
+   scripts
+   plugins

docs/source/index.rst

+.. virtualenvwrapper documentation master file, created by
+   sphinx-quickstart on Thu May 28 22:35:13 2009.
+   You can adapt this file completely to your liking, but it should at least
+   contain the root `toctree` directive.
+
+###########################
+virtualenvwrapper |release|
+###########################
+
+virtualenvwrapper is a set of extensions to Ian Bicking's `virtualenv
+<http://pypi.python.org/pypi/virtualenv>`_ tool.  The extensions
+include wrappers for creating and deleting virtual environments and
+otherwise managing your development workflow, making it easier to work
+on more than one project at a time without introducing conflicts in
+their dependencies.
+
+========
+Features
+========
+
+1. Organizes all of your virtual environments in one place.
+2. Wrappers for managing your virtual environments (create, delete,
+   copy).
+3. Use a single command to switch between environments.
+4. Tab completion for commands that take a virtual environment as
+   argument.
+5. User-configurable hooks for all operations (see :ref:`scripts`).
+6. Plugin system for more creating sharable extensions (see
+   :ref:`plugins`).
+
+===========
+Quick Setup
+===========
+
+1. Create a directory to hold all of the virtual environments. The default is
+   ``$HOME/.virtualenvs``.
+
+2. Add two lines to your shell startup file (``.bashrc``,
+   ``.profile``, etc.) to set the location where the virtual
+   environments should live and the location of the script installed
+   with this package::
+
+    export WORKON_HOME=$HOME/.virtualenvs
+    source /usr/local/bin/virtualenvwrapper.sh
+
+3. Reload the startup file (e.g., run: ``source ~/.bashrc``).
+4. Run: ``workon``
+5. A list of environments, empty, is printed.
+6. Run: ``mkvirtualenv temp``
+7. A new environment, ``temp`` is created and activated.
+8. Run: ``workon``
+9. This time, the ``temp`` environment is included.
+
+Upgrading from 1.x
+==================
+
+The shell script containing the wrapper functions has been renamed in
+the 2.x series to reflect the fact that shells other than bash are
+supported.  In your startup file, change ``source
+/usr/local/bin/virtualenvwrapper_bashrc`` to ``source
+/usr/local/bin/virtualenvwrapper.sh``.
+
+=======
+Details
+=======
+
+.. toctree::
+   :maxdepth: 2
+
+   command_ref
+   hooks
+   tips
+   developers
+   extensions
+   history
+
+.. _references:
+
+==========
+References
+==========
+
+`virtualenv <http://pypi.python.org/pypi/virtualenv>`_, from Ian
+Bicking, is a pre-requisite to using these extensions.
+
+For more details, refer to the column I wrote for the May 2008 issue
+of Python Magazine: `virtualenvwrapper | And Now For Something
+Completely Different
+<http://www.doughellmann.com/articles/CompletelyDifferent-2008-05-virtualenvwrapper/index.html>`_.
+
+Rich Leland has created a short `screencast
+<http://mathematism.com/2009/jul/30/presentation-pip-and-virtualenv/>`__
+showing off the features of virtualenvwrapper.
+
+=======
+License
+=======
+
+Copyright Doug Hellmann, All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Doug Hellmann not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DOUG HELLMANN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+EVENT SHALL DOUG HELLMANN BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE.

docs/source/plugins.rst

+.. _plugins:
+
+===================
+ Extension Plugins
+===================
+
+virtualenvwrapper includes several ways to modify its behavior.
+End-users can use shell scripts or other programs for personal
+customization (see :ref:`scripts`).  Extensions can also be
+implemented in Python by using Distribute_ *entry points*, making it
+possible to share common behaviors between systems.
+
+Defining an Extension
+=====================
+
+.. note::
+
+  Virtualenvwrapper is delivered with a plugin for creating and
+  running the user customization scripts
+  (:ref:`extensions-user_scripts`).  The examples below are taken from
+  the implementation of that plugin.
+
+Code Organization
+-----------------
+
+The Python package for ``virtualenvwrapper`` is a *namespace package*.
+That means multiple libraries can install code into the package, even
+if they are not distributed together or installed into the same
+directory.  Extensions can (optionally) use the ``virtualenvwrapper``
+namespace by setting up their source tree like:
+
+* virtualenvwrapper/
+
+  * __init__.py
+  * user_scripts.py
+
+And placing the following code in ``__init__.py``::
+
+    """virtualenvwrapper module
+    """
+
+    __import__('pkg_resources').declare_namespace(__name__)
+
+.. note::
+
+    Extensions can be loaded from any package, so using the
+    ``virtualenvwrapper`` namespace is not required.
+
+Extension API
+-------------
+
+After the package is established, the next step is to create a module
+to hold the extension code.  For example,
+``virtualenvwrapper/user_scripts.py``.  The module should contain the
+actual extension entry points.  Supporting code can be included, or
+imported from elsewhere using standard Python code organization
+techniques.
+
+The API is the same for every extension point.  Each uses a Python
+function that takes a single argument, a list of strings passed to the
+hook loader on the command line.  
+
+::
+
+    def function_name(args):
+        # args is a list of strings passed to the hook loader
+
+The contents of the argument list are defined for each extension point
+below (see :ref:`plugins-extension-points`).
+
+Extension Invocation
+--------------------
+
+Direct Action
+~~~~~~~~~~~~~
+
+Plugins can attach to each hook in two different ways.  The default is
+to have a function run and do some work directly.  For example, the
+``initialize()`` function for the user scripts plugin creates default
+user scripts when ``virtualenvwrapper.sh`` is loaded.
+
+::
+
+    def initialize(args):
+        for filename, comment in GLOBAL_HOOKS:
+            make_hook(os.path.join('$WORKON_HOME', filename), comment)
+        return 
+
+.. _plugins-user-env:
+
+Modifying the User Environment
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+There are cases where the extension needs to update the user's
+environment (e.g., changing the current working directory or setting
+environment variables).  Modifications to the user environment must be
+made within the user's current shell, and cannot be run in a separate
+process.  To have code run in the user's shell process, extensions can
+define hook functions to return the text of the shell statements to be
+executed.  These *source* hooks are run after the regular hooks with
+the same name, and should not do any work of their own.
+
+The ``initialize_source()`` hook for the user scripts plugin looks for
+a global initialize script and causes it to be run in the current
+shell process.
+
+::
+
+    def initialize_source(args):
+        return """
+    #
+    # Run user-provided scripts
+    #
+    [ -f "$WORKON_HOME/initialize" ] && source "$WORKON_HOME/initialize"
+    """
+
+.. warning::
+
+    Because the extension is modifying the user's working shell, care
+    must be taken not to corrupt the environment by overwriting
+    existing variable values unexpectedly.  Avoid creating temporary
+    variables where possible, and use unique names where variables
+    cannot be avoided.  Prefixing variables with the extension name is
+    a good way to manage the namespace.  For example, instead of
+    ``temp_file`` use ``user_scripts_temp_file``.  Use ``unset`` to
+    release temporary variable names when they are no longer needed.
+
+.. warning::
+
+    virtualenvwrapper works under several shells with slightly
+    different syntax (bash, sh, zsh, ksh).  Take this portability into
+    account when defining source hooks.  Sticking to the simplest
+    possible syntax usually avoids problems, but there may be cases
+    where examining the ``SHELL`` environment variable to generate
+    different syntax for each case is the only way to achieve the
+    desired result.
+    
+Registering Entry Points
+------------------------
+
+The functions defined in the plugin need to be registered as *entry
+points* in order for virtualenvwrapper's hook loader to find them.
+Distribute_ entry points are configured in the ``setup.py`` for your
+package by mapping the entry point name to the function in the package
+that implements it.
+
+This partial copy of virtualenvwrapper's ``setup.py`` illustrates how
+the ``initialize()`` and ``initialize_source()`` entry points are
+configured.
+
+::
+    
+    # Bootstrap installation of Distribute
+    import distribute_setup
+    distribute_setup.use_setuptools()
+    
+    from setuptools import setup
+    
+    setup(
+        name = 'virtualenvwrapper',
+        version = '2.0',
+        
+        description = 'Enhancements to virtualenv',
+    
+        # ... details omitted ...
+    
+        entry_points = {
+            'virtualenvwrapper.initialize': [
+                'user_scripts = virtualenvwrapper.user_scripts:initialize',
+                ],
+            'virtualenvwrapper.initialize_source': [
+                'user_scripts = virtualenvwrapper.user_scripts:initialize_source',
+                ],
+    
+            # ... details omitted ...
+            },
+        )
+    
+The ``entry_points`` argument to ``setup()`` is a dictionary mapping
+the entry point *group names* to lists of entry point specifiers.  A
+different group name is defined by virtualenvwrapper for each
+extension point (see :ref:`plugins-extension-points`).
+
+The entry point specifiers are strings with the syntax ``name =
+package.module:function``.  By convention, the *name* of each entry
+point is the plugin name, but that is not required (the names are not
+used).
+
+The Hook Loader
+---------------
+
+Extensions are run through a command line application implemented in
+``virtualenvwrapper.hook_loader``.  Because ``virtualenvwrapper.sh``
+is the primary caller and users do not typically need to run the app
+directly, no separate script is installed.  Instead, to run the
+application, use the ``-m`` option to the interpreter::
+
+  $ python -m virtualenvwrapper.hook_loader -h
+  Usage: virtualenvwrapper.hook_loader [options] <hook> [<arguments>]
+
+  Manage hooks for virtualenvwrapper
+
+  Options:
+    -h, --help     show this help message and exit
+    -s, --source   Print the shell commands to be run in the current shell
+    -v, --verbose  Show more information on the console
+    -q, --quiet    Show less information on the console
+
+To run the extensions for the initialize hook::
+
+  $ python -m virtualenvwrapper.hook_loader -v initialize
+
+To get the shell commands for the initialize hook::
+
+  $ python -m virtualenvwrapper.hook_loader --source initialize
+
+Logging
+-------
+
+The hook loader configures logging so that messages are written to
+``$WORKON_HOME/hook.log``.  Messages also may be written to stderr,
+depending on the verbosity flag.  The default is for messages at *info*
+or higher levels to be written to stderr, and *debug* or higher to go to
+the log file.  Using logging in this way provides a convenient
+mechanism for users to control the verbosity of extensions.
+
+To use logging from within your extension, simply instantiate a logger
+and call its ``info()``, ``debug()`` and other methods with the
+messages.
+
+::
+
+    import logging
+    log = logging.getLogger(__name__)
+
+    def pre_mkvirtualenv(args):
+        log.debug('pre_mkvirtualenv %s', str(args))
+        # ...
+
+.. seealso::
+
+   * `Standard library documentation for logging <http://docs.python.org/library/logging.html>`__
+   * `PyMOTW for logging <http://www.doughellmann.com/PyMOTW/logging/>`__
+
+.. _plugins-extension-points:
+
+Extension Points
+================
+
+The extension point names for native plugins follow a naming
+convention with several parts:
+``virtualenvwrapper.(pre|post)_<event>[_source]``.  The *<event>* is
+the action taken by the user or virtualenvwrapper that triggers the
+extension.  ``(pre|post)`` indicates whether to call the extension
+before or after the event.  The suffix ``_source`` is added for
+extensions that return shell code instead of taking action directly
+(see :ref:`plugins-user-env`).
+
+.. _plugins-initialize:
+
+initialize
+----------
+
+The ``virtualenvwrapper.initialize`` hooks are run each time
+``virtualenvwrapper.sh`` is loaded into the user's environment.
+
+.. _plugins-pre_mkvirtualenv:
+
+pre_mkvirtualenv
+----------------
+
+The ``virtualenvwrapper.pre_mkvirtualenv`` hooks are run after the
+virtual environment is created, but before the new environment is
+activated.  The current working directory for when the hook is run is
+``$WORKON_HOME`` and the name of the new environment is passed as an
+argument.
+
+.. _plugins-post_mkvirtualenv:
+
+post_mkvirtualenv
+-----------------
+
+The ``virtualenvwrapper.post_mkvirtualenv`` hooks are run after a new
+virtual environment is created and activated.  ``$VIRTUAL_ENV`` is set
+to point to the new environment.
+
+.. _plugins-pre_activate:
+
+pre_activate
+------------
+
+The ``virtualenvwrapper.pre_activate`` hooks are run just before an
+environment is enabled.  The environment name is passed as the first
+argument.
+
+.. _plugins-post_activate:
+
+post_activate
+-------------
+
+The ``virtualenvwrapper.post_activate`` hooks are run just after an
+environment is enabled.  ``$VIRTUAL_ENV`` is set to point to the
+current environment.
+
+.. _plugins-pre_deactivate:
+
+pre_deactivate
+--------------
+
+The ``virtualenvwrapper.pre_deactivate`` hooks are run just before an
+environment is disabled.  ``$VIRTUAL_ENV`` is set to point to the
+current environment.
+
+.. _plugins-post_deactivate:
+
+post_deactivate
+---------------
+
+The ``virtualenvwrapper.post_deactivate`` hooks are run just after an
+environment is disabled.  The name of the environment just deactivated
+is passed as the first argument.
+
+.. _plugins-pre_rmvirtualenv:
+
+pre_rmvirtualenv
+----------------
+
+The ``virtualenvwrapper.pre_rmvirtualenv`` hooks are run just before
+an environment is deleted.  The name of the environment being deleted
+is passed as the first argument.
+
+.. _plugins-post_rmvirtualenv:
+
+post_rmvirtualenv
+-----------------
+
+The ``virtualenvwrapper.post_rmvirtualenv`` hooks are run just after
+an environment is deleted.  The name of the environment being deleted
+is passed as the first argument.
+
+.. _Distribute: http://packages.python.org/distribute/

docs/source/scripts.rst

+.. _scripts:
+
+========================
+ Per-User Customization
+========================
+
+The end-user customization scripts are either *sourced* (allowing them
+to modify your shell environment) or *run* as an external program at
+the appropriate trigger time.
+
+.. _scripts-initialize:
+
+initialize
+==========
+
+  :Global/Local: global
+  :Argument(s): None
+  :Sourced/Run: run
+
+``$WORKON_HOME/initialize`` is sourced when ``virtualenvwrapper.sh``
+is loaded into your environment.  Use it to adjust global settings
+when virtualenvwrapper is enabled.
+
+.. _scripts-premkvirtualenv:
+
+premkvirtualenv
+===============
+
+  :Global/Local: global
+  :Argument(s): name of new environment
+  :Sourced/Run: run
+
+``$WORKON_HOME/premkvirtualenv`` is run as an external program after
+the virtual environment is created but before the current environment
+is switched to point to the new env. The current working directory for
+the script is ``$WORKON_HOME`` and the name of the new environment is
+passed as an argument to the script.
+
+.. _scripts-postmkvirtualenv:
+
+postmkvirtualenv
+================
+
+  :Global/Local: global
+  :Argument(s): none
+  :Sourced/Run: sourced
+
+``$WORKON_HOME/postmkvirtualenv`` is sourced after the new environment
+is created and activated.
+
+.. _scripts-preactivate:
+
+preactivate
+===========
+
+  :Global/Local: global, local
+  :Argument(s): environment name
+  :Sourced/Run: run
+
+The global ``$WORKON_HOME/preactivate`` script is run before the new
+environment is enabled.  The environment name is passed as the first
+argument.
+
+The local ``$VIRTUAL_ENV/bin/preactivate`` hook is run before the new
+environment is enabled.  The environment name is passed as the first
+argument.
+
+.. _scripts-postactivate:
+
+postactivate
+============
+
+  :Global/Local: global, local
+  :Argument(s): none
+  :Sourced/Run: sourced
+
+The global ``$WORKON_HOME/postactivate`` script is sourced after the
+new environment is enabled. ``$VIRTUAL_ENV`` refers to the new
+environment at the time the script runs.
+
+This example script adds a space between the virtual environment name
+and your old PS1 by making use of ``_OLD_VIRTUAL_PS1``.
+
+::
+
+    PS1="(`basename \"$VIRTUAL_ENV\"`) $_OLD_VIRTUAL_PS1"
+
+The local ``$VIRTUAL_ENV/bin/postactivate`` script is sourced after
+the new environment is enabled. ``$VIRTUAL_ENV`` refers to the new
+environment at the time the script runs.
+
+This example script for the PyMOTW environment changes the current
+working directory and the PATH variable to refer to the source tree
+containing the PyMOTW source.
+
+::
+
+    pymotw_root=/Users/dhellmann/Documents/PyMOTW
+    cd $pymotw_root
+    PATH=$pymotw_root/bin:$PATH
+
+.. _scripts-predeactivate:
+
+predeactivate
+=============
+
+  :Global/Local: local, global
+  :Argument(s): none
+  :Sourced/Run: sourced
+
+The local ``$VIRTUAL_ENV/bin/predeactivate`` script is sourced before the
+current environment is deactivated, and can be used to disable or
+clear settings in your environment. ``$VIRTUAL_ENV`` refers to the old
+environment at the time the script runs.
+
+The global ``$WORKON_HOME/predeactivate`` script is sourced before the
+current environment is deactivated.  ``$VIRTUAL_ENV`` refers to the
+old environment at the time the script runs.
+
+.. _scripts-postdeactivate:
+
+postdeactivate
+==============
+
+  :Global/Local: local, global
+  :Argument(s): none
+  :Sourced/Run: sourced
+
+The ``$VIRTUAL_ENV/bin/postdeactivate`` script is sourced after the
+current environment is deactivated, and can be used to disable or
+clear settings in your environment.  The path to the environment just
+deactivated is available in ``$VIRTUALENVWRAPPER_LAST_VIRTUALENV``.
+
+.. _scripts-prermvirtualenv:
+
+prermvirtualenv
+===============
+
+  :Global/Local: global
+  :Argument(s): environment name
+  :Sourced/Run: run
+
+The ``$WORKON_HOME/prermvirtualenv`` script is run as an external
+program before the environment is removed. The full path to the
+environment directory is passed as an argument to the script.
+
+.. _scripts-postrmvirtualenv:
+
+postrmvirtualenv
+================
+
+  :Global/Local: global
+  :Argument(s): environment name
+  :Sourced/Run: run
+
+The ``$WORKON_HOME/postrmvirtualenv`` script is run as an external
+program after the environment is removed. The full path to the
+environment directory is passed as an argument to the script.

docs/source/tips.rst

+.. _tips-and-tricks:
+
+=================
+ Tips and Tricks
+=================
+
+This is a list of user-contributed tips for making virtualenv and
+virtualenvwrapper even more useful.  If you have tip to share, drop me
+an email or post a comment on `this blog post
+<http://blog.doughellmann.com/2010/01/virtualenvwrapper-tips-and-tricks.html>`__
+and I'll add it here.
+
+zsh Prompt
+==========
+
+From `Nat <http://www.blogger.com/profile/16779944428406910187>`_:
+
+Using zsh, I added some bits to ``$WORKON_HOME/post(de)activate`` to show
+the active virtualenv on the right side of my screen instead.
+
+in ``postactivate``::
+
+    PS1="$_OLD_VIRTUAL_PS1"
+    _OLD_RPROMPT="$RPROMPT"
+    RPROMPT="%{${fg_bold[white]}%}(env: %{${fg[green]}%}`basename \"$VIRTUAL_ENV\"`%{${fg_bold[white]}%})%{${reset_color}%} $RPROMPT"
+
+and in ``postdeactivate``::
+
+    RPROMPT="$_OLD_RPROMPT"
+
+Adjust colors according to your own personal tastes or environment.
+
+Updating cached ``$PATH`` entries
+=================================
+
+From `Nat <http://www.blogger.com/profile/16779944428406910187>`_:
+
+I also added the command 'rehash' to ``$WORKON_HOME/postactivate`` and
+``$WORKON_HOME/postdeactivate`` as I was having some problems with zsh
+not picking up the new paths immediately.
+
+Tying to pip's virtualenv support
+=================================
+
+Via http://becomingguru.com/:
+
+Add this to your shell login script to make pip use the same directory
+for virtualenvs as virtualenvwrapper::
+
+    export PIP_VIRTUALENV_BASE=$WORKON_HOME
+
+and Via Nat:
+
+in addition to what becomingguru said, this line is key::
+
+   export PIP_RESPECT_VIRTUALENV=true
+
+That makes pip detect an active virtualenv and install to it, without
+having to pass it the -E parameter.
+
+Creating Project Work Directories
+=================================
+
+Via `James <http://www.blogger.com/profile/02618224969192901883>`_:
+
+In the ``postmkvirtualenv`` script I have the following to create a
+directory based on the project name, add that directory to the python
+path and then cd into it::
+
+    proj_name=$(echo $VIRTUAL_ENV|awk -F'/' '{print $NF}')
+    mkdir $HOME/projects/$proj_name
+    add2virtualenv $HOME/projects/$proj_name
+    cd $HOME/projects/$proj_name
+
+
+In the ``postactivate`` script I have it set to automatically change
+to the project directory when I use the workon command::
+
+    proj_name=$(echo $VIRTUAL_ENV|awk -F'/' '{print $NF}')
+    cd ~/projects/$proj_name
+
+Automatically Run workon When Entering a Directory
+==================================================
+
+`Justin Lily posted
+<http://justinlilly.com/blog/2009/mar/28/virtualenv-wrapper-helper/>`__
+about about some code he added to his shell environment to look at the
+directory each time he runs ``cd``.  If it finds a ``.venv`` file, it
+activates the environment named within.  On leaving that directory,
+the current virtualenv is automatically deactivated.
+
+`Harry Marr <http://www.blogger.com/profile/17141199633387157732>`__
+wrote a similar function that works with `git repositories
+<http://hmarr.com/2010/jan/19/making-virtualenv-play-nice-with-git/>`__.
+
+Installing Common Tools Automatically in New Environments
+=========================================================
+
+Via `rizumu <http://rizumu.myopenid.com/>`__:
+
+I have this postmkvirtualenv to install the get a basic setup.
+
+::
+
+    $ cat postmkvirtualenv
+    #!/usr/bin/env bash
+    curl -O http://python-distribute.org/distribute_setup.p... />python distribute_setup.py
+    rm distribute_setup.py
+    easy_install pip==dev
+    pip install Mercurial
+
+Then I have a pip requirement file with my dev tools.
+
+::
+
+    $ cat developer_requirements.txt
+    ipdb
+    ipython
+    pastescript
+    nose
+    http://douglatornell.ca/software/python/Nosy-1.0.tar.gz
+    coverage
+    sphinx
+    grin
+    pyflakes
+    pep8
+
+Then each project has it's own pip requirement file for things like
+PIL, psycopg2, django-apps, numpy, etc.
+
+Changing the Default Behavior of ``cd``
+=======================================
+
+Via `mae <http://www.blogger.com/profile/10879711379090472478>`__:
+
+This is supposed to be executed after workon, that is as a
+``postactivate`` hook. It basically overrides ``cd`` to know about the
+VENV so instead of doing ``cd`` to go to ``~`` you will go to the venv
+root, IMO very handy and I can't live without it anymore. if you pass
+it a proper path then it will do the right thing.
+
+::
+
+    cd () {
+        if (( $# == 0 ))
+        then
+            builtin cd $VIRTUAL_ENV
+        else
+            builtin cd "$@"
+        fi
+    }
+
+    cd

docs/sphinx/pkg/conf.py

+# -*- coding: utf-8 -*-
+#
+# virtualenvwrapper documentation build configuration file, created by
+# sphinx-quickstart on Thu May 28 22:35:13 2009.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+
+# -- General configuration -----------------------------------------------------
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = []
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['templates']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'virtualenvwrapper'
+copyright = u'2009, Doug Hellmann'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+#
+# The short X.Y version.
+version = os.environ['VERSION']
+# The full version, including alpha/beta/rc tags.
+release = version
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of documents that shouldn't be included in the build.
+#unused_docs = []
+
+# List of directories, relative to source directory, that shouldn't be searched
+# for source files.
+exclude_trees = ['_build']
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+#show_authors = False
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+#modindex_common_prefix = []
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages.  Major themes that come with
+# Sphinx are currently 'default' and 'sphinxdoc'.
+html_theme = 'sphinxdoc'
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further.  For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+#html_theme_path = []
+
+# The name for this set of Sphinx documents.  If None, it defaults to
+# "<project> v<release> documentation".
+#html_title = None
+
+# A shorter title for the navigation bar.  Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+html_use_modindex = False
+
+# If false, no index is generated.
+html_use_index = False
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+#html_show_sourcelink = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a <link> tag referring to it.  The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'virtualenvwrapperdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+  ('index', 'virtualenvwrapper.tex', u'virtualenvwrapper Documentation',
+   u'Doug Hellmann', 'manual'),
+]
+