Adding support for a workingenv sandbox to setuptools/distutils
It seems that all I blog about is workingenv.
This time it's a snippet of code that adds a "sandbox" command to distutils, which automatically creates a workingenv from the setuptools extras_require, install_requires and dependency_links options listed in your setup() call. It only supports *nix systems for now, but could easily be extended to support Windows.
Here's the code:
import os from setuptools import setup, find_packages from distutils.cmd import Command class sandbox(Command): description = 'Create a development sandbox using workingenv' user_options = [ ('path=', None, 'workingenv path'), ('extras', None, 'also include "extras" requirements'), ] def initialize_options(self): self.path = 'wenv' self.extras = False def finalize_options(self): pass def run(self): requires = open('requirements.txt', 'w') try: requirements = self.distribution.dependency_links + \ self.distribution.install_requires if self.extras: extras = self.distribution.extras_require or {} requirements += extras.values() requires.write('\n'.join(requirements)) finally: requires.close() cwd = os.getcwd() import workingenv workingenv.main(['--always-unzip', '--requirements=requirements.txt', '--site-packages', '--verbose', self.path]) os.chdir(cwd) os.symlink(self.path + '/bin/activate', 'sandbox') print print 'XXX: Use ". sandbox" to activate the development sandbox' setup( name='MyCoolPackage', version='0.0.0.1', packages=find_packages(), # Add the sandbox command cmdclass={'sandbox': sandbox}, # Search some extra locations for dependencies dependency_links=[ 'http://svn.edgewall.org/repos/genshi/trunk#egg=Genshi-dev', 'http://trac.pocoo.org/repos/werkzeug/trunk#egg=Werkzeug-dev', 'http://svn.sqlalchemy.org/sqlalchemy/trunk#egg=SQLAlchemy-dev', ], install_requires=[ 'setuptools >= 0.6b1', 'Genshi >= 0.5.dev-r698,==dev', 'Werkzeug >= 0.1.dev-r3831,==dev', 'SQLAlchemy >= 0.4.0.dev-r3203,==dev', 'AuthKit >= 0.3.0pre5', ], )
And here's an example of how to use it:
$ python setup.py sandbox --help Common commands: (see '--help-commands' for more) ... Options for 'sandbox' command: --path workingenv path --extras also include "extras" requirements ... $ python setup.py sandbox --path=mysandbox --extras running sandbox Reading requirement requirements.txt Making working environment in /home/athomas/p/test/mysandbox Creating lib/python2.5 ... ...Installing http://svn.edgewall.org/repos/genshi/trunk#egg=Genshi-dev, http://trac.pocoo.org/repos/werkzeug/trunk#egg=Werkzeug-dev, http://svn.sqlalchemy.org/sqlalchemy/trunk#egg=SQLAlchemy-dev, setuptools >= 0.6b1, Genshi >= 0.5.dev-r698,==dev, Werkzeug >= 0.1.dev-r3831,==dev, SQLAlchemy >= 0.4.0.dev-r3203,==dev, AuthKit >= 0.3.0pre5 ...done. XXX: Use ". sandbox" to activate the development sandbox
Activating a `workingenv` from Python
It can, under some circumstances, be useful to be able to activate a workingenv from Python. Here's a quick function to achieve that:
import sys import os def activate_workingenv(root): """Make modules in a self-contained workingenv available.""" # Add ./bin directory to path. bin_dir = os.path.join(root, './bin') try: os.environ['PATH'] = os.path.pathsep.join([bin_dir, os.environ['PATH']]) except KeyError: os.environ['PATH'] = bin_dir # Add ./lib to linker path lib_dir = os.path.join(root, './lib') try: os.environ['LD_LIBRARY_PATH'] = \ os.path.pathsep.join([lib_dir, os.environ['LD_LIBRARY_PATH']]) except KeyError: os.environ['LD_LIBRARY_PATH'] = lib_dir # Find the workingenv Python package root python_version = '.'.join(map(str, sys.version_info[:2])) package_root = os.path.join(root, './lib/python' + python_version) # Find and insert setuptools into sys.path sys.path.insert(0, package_root) real_setuptools = open(os.path.join(package_root, 'setuptools.pth')).read().strip() sys.path.insert(0, os.path.join(package_root, real_setuptools)) # Load all distributions into the working set. from pkg_resources import working_set, Environment env = Environment(root) env.scan() distributions, errors = working_set.find_plugins(env) for dist in distributions: working_set.add(dist) return distributions, errors
It's UNIX-centric due to the use of LD_LIBRARY_PATH, but if you're not using shared libraries it's not really necessary anyway.
Use it like so:
from activate_workingenv import activate_workingenv activate_workingenv('./wenv') import some_module_from_the_workingenv

rss