diff options
author | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
---|---|---|
committer | Nishanth Amuluru | 2011-01-11 22:41:51 +0530 |
commit | b03203c8cb991c16ac8a3d74c8c4078182d0bb48 (patch) | |
tree | 7cf13b2deacbfaaec99edb431b83ddd5ea734a52 /eggs/zc.buildout-1.5.2-py2.6.egg/zc | |
parent | 0c50203cd9eb94b819883c3110922e873f003138 (diff) | |
download | pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.gz pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.tar.bz2 pytask-b03203c8cb991c16ac8a3d74c8c4078182d0bb48.zip |
removed all the buildout files
Diffstat (limited to 'eggs/zc.buildout-1.5.2-py2.6.egg/zc')
31 files changed, 0 insertions, 16907 deletions
diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.py deleted file mode 100644 index 35cf25b..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -try: - __import__('pkg_resources').declare_namespace(__name__) -except: - # bootstrapping - pass diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.pyo b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.pyo Binary files differdeleted file mode 100644 index bd07b10..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/__init__.pyo +++ /dev/null diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/__init__.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/__init__.py deleted file mode 100644 index ac268c0..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/__init__.py +++ /dev/null @@ -1,24 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Buildout package - -$Id: __init__.py 69990 2006-09-05 22:55:53Z jim $ -""" - -class UserError(Exception): - """Errors made by a user - """ - - def __str__(self): - return " ".join(map(str, self)) diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/allowhosts.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/allowhosts.txt deleted file mode 100644 index be5ab4f..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/allowhosts.txt +++ /dev/null @@ -1,128 +0,0 @@ -Allow hosts ------------ - -On some environments the links visited by `zc.buildout` can be forbidden -by paranoiac firewalls. These URL might be on the chain of links -visited by `zc.buildout` whether they are defined in the `find-links` option -or by various eggs in their `url`, `download_url` and `dependency_links` metadata. - -It is even harder to track that package_index works like a spider and -might visit links and go to other location. - -The `allow-hosts` option provides a way to prevent this, and -works exactly like the one provided in `easy_install` -(see `easy_install allow-hosts option`_). - -You can provide a list of allowed host, together with wildcards:: - - [buildout] - ... - - allow-hosts = - *.python.org - example.com - -Let's create a develop egg in our buildout that specifies -`dependency_links` which points to a server in the outside world:: - - >>> mkdir(sample_buildout, 'allowdemo') - >>> write(sample_buildout, 'allowdemo', 'dependencydemo.py', - ... 'import eggrecipekss.core') - >>> write(sample_buildout, 'allowdemo', 'setup.py', - ... '''from setuptools import setup; setup( - ... name='allowdemo', py_modules=['dependencydemo'], - ... install_requires = 'kss.core', - ... dependency_links = ['http://dist.plone.org'], - ... zip_safe=True, version='1') - ... ''') - -Now let's configure the buildout to use the develop egg, -together with some rules that disallow any website but PyPI and -local files:: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = allowdemo - ... parts = eggs - ... allow-hosts = - ... pypi.python.org - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = allowdemo - ... ''') - -Now we can run the buildout and make sure all attempts to dist.plone.org fails:: - - >>> print system(buildout) # doctest: +ELLIPSIS - Develop: '/sample-buildout/allowdemo' - ... - Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts - ... - While: - Installing eggs. - Getting distribution for 'kss.core'. - Error: Couldn't find a distribution for 'kss.core'. - <BLANKLINE> - -That's what we wanted : this will prevent any attempt to access -unwanted domains. For instance, some packages are listing in their -links `svn://` links. These can lead to error in some cases, and -can therefore be protected like this:: - -XXX (showcase with a svn:// file) - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = allowdemo - ... parts = eggs - ... allow-hosts = - ... ^(!svn://).* - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = allowdemo - ... ''') - -Now we can run the buildout and make sure all attempts to dist.plone.org fails:: - - >>> print system(buildout) # doctest: +ELLIPSIS - Develop: '/sample-buildout/allowdemo' - ... - Link to http://dist.plone.org ***BLOCKED*** by --allow-hosts - ... - While: - Installing eggs. - Getting distribution for 'kss.core'. - Error: Couldn't find a distribution for 'kss.core'. - <BLANKLINE> - -Test for issues ---------------- - -Test for 1.0.5 breakage as in https://bugs.launchpad.net/zc.buildout/+bug/239212:: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... parts=python - ... foo = ${python:interpreter} - ... - ... [python] - ... recipe=zc.recipe.egg - ... eggs=zc.buildout - ... interpreter=python - ... ''') - >>> print system(buildout) - Unused options for buildout: 'foo'. - Installing python. - Generated script '/sample-buildout/bin/buildout'. - Generated interpreter '/sample-buildout/bin/python'. - <BLANKLINE> - -The bug 239212 above would have got us an *AttributeError* on *buildout._allow_hosts*. -This was fixed in this changeset: -http://svn.zope.org/zc.buildout/trunk/src/zc/buildout/buildout.py?rev=87309&r1=87277&r2=87309 - diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/bootstrap.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/bootstrap.txt deleted file mode 100644 index 794b912..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/bootstrap.txt +++ /dev/null @@ -1,360 +0,0 @@ -Make sure the bootstrap script actually works:: - - >>> import os, sys - >>> from os.path import dirname, join - >>> import zc.buildout - >>> bootstrap_py = join( - ... dirname( - ... dirname( - ... dirname( - ... dirname(zc.buildout.__file__) - ... ) - ... ) - ... ), - ... 'bootstrap', 'bootstrap.py') - >>> sample_buildout = tmpdir('sample') - >>> os.chdir(sample_buildout) - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = - ... ''') - >>> write('bootstrap.py', open(bootstrap_py).read()) - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py'); print 'X' # doctest: +ELLIPSIS - X... - Creating directory '/sample/bin'. - Creating directory '/sample/parts'. - Creating directory '/sample/eggs'. - Creating directory '/sample/develop-eggs'. - Generated script '/sample/bin/buildout'. - ... - - >>> ls(sample_buildout) - d bin - - bootstrap.py - - buildout.cfg - d develop-eggs - d eggs - d parts - - - >>> ls(sample_buildout, 'bin') - - buildout - - >>> print 'X'; ls(sample_buildout, 'eggs') # doctest: +ELLIPSIS - X... - d zc.buildout-...egg - -The buildout script it has generated is a new-style script, using a -customized site.py. - - >>> buildout_script = join(sample_buildout, 'bin', 'buildout') - >>> if sys.platform.startswith('win'): - ... buildout_script += '-script.py' - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample/parts/buildout', - ] - <BLANKLINE> - <BLANKLINE> - import os - path = sys.path[0] - if os.environ.get('PYTHONPATH'): - path = os.pathsep.join([path, os.environ['PYTHONPATH']]) - os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '') - os.environ['PYTHONPATH'] = path - import site # imports custom buildout-generated site.py - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - <BLANKLINE> - -The bootstrap process prefers final versions of zc.buildout, so it has -selected the (generated-locally) 99.99 egg rather than the also-available -100.0b1 egg. We can see that in the buildout script's site.py. - - >>> buildout_site_py = join( - ... sample_buildout, 'parts', 'buildout', 'site.py') - >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS - "... - buildout_paths = [ - '/sample/eggs/setuptools-...egg', - '/sample/eggs/zc.buildout-99.99-pyN.N.egg' - ] - ... - -If you want to accept early releases of zc.buildout, you either need to -specify an explicit version (using --version here and specifying the -version in the buildout configuration file using the -``buildout-version`` option or the ``versions`` option) or specify that you -accept early releases by using ``--accept-buildout-test-releases`` on the -bootstrap script. - -Here's an example. - - >>> ignored = system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --accept-buildout-test-releases') - >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS - "... - buildout_paths = [ - '/sample/eggs/setuptools-...egg', - '/sample/eggs/zc.buildout-100.0b1-pyN.N.egg' - ] - ... - -Notice we are now using zc.buildout 100.0b1, a non-final release. - -The buildout script remembers the decision to accept early releases, and -alerts the user. - - >>> print system(join('bin', 'buildout')), - ... # doctest: +NORMALIZE_WHITESPACE - NOTE: Accepting early releases of build system packages. Rerun bootstrap - without --accept-buildout-test-releases (-t) to return to default - behavior. - -This is accomplished within the script itself. - - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true') - print ('NOTE: Accepting early releases of build system packages. Rerun ' - 'bootstrap without --accept-buildout-test-releases (-t) to return to ' - 'default behavior.') - ... - -As the note says, to undo, you just need to re-run bootstrap without ---accept-buildout-test-releases. - - >>> ignored = system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py') - >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS - "... - buildout_paths = [ - '/sample/eggs/setuptools-...egg', - '/sample/eggs/zc.buildout-99.99-pyN.N.egg' - ] - ... - >>> ('buildout:accept-buildout-test-releases=true' in - ... open(buildout_script).read()) - False - -Now we will try the `--version` option, which lets you define a version for -`zc.buildout`. If not provided, bootstrap will look for the latest one. - -Let's try with an unknown version:: - - >>> print 'XX'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --version UNKNOWN'); print 'X' # doctest: +ELLIPSIS - ... - X... - No local packages or download links found for zc.buildout==UNKNOWN... - ... - -Now let's try with `1.1.2`, which happens to exist:: - - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --version 1.1.2'); print 'X' - ... - X - Generated script '/sample/bin/buildout'. - <BLANKLINE> - X - -Versions older than 1.5.0 put their egg dependencies in the ``buildout`` script. -Let's make sure it was generated as we expect:: - - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample/eggs/setuptools-...egg', - '/sample/eggs/zc.buildout-1.1.2...egg', - ] - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - <BLANKLINE> - -Let's try with `1.2.1`:: - - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --version 1.2.1'); print 'X' # doctest: +ELLIPSIS - ... - X - Generated script '/sample/bin/buildout'. - <BLANKLINE> - X - -Let's make sure the generated ``buildout`` script uses it:: - - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample/eggs/setuptools-...egg', - '/sample/eggs/zc.buildout-1.2.1...egg', - ] - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - <BLANKLINE> - -``zc.buildout`` now can also run with `Distribute` with the `--distribute` -option:: - - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --distribute'); print 'X' # doctest: +ELLIPSIS - ... - X - ... - Generated script '/sample/bin/buildout'... - X - -Let's make sure the generated ``site.py`` uses it:: - >>> print open(buildout_site_py).read() # doctest: +ELLIPSIS - "... - buildout_paths = [ - '/sample/eggs/distribute-...egg', - '/sample/eggs/zc.buildout-99.99-pyN.N.egg' - ] - ... - -Make sure both options can be used together:: - - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --distribute --version 1.2.1'); print 'X' - ... # doctest: +ELLIPSIS - ... - X - ... - Generated script '/sample/bin/buildout'... - X - -Let's make sure the old-style generated ``buildout`` script uses -``Distribute`` *and* ``zc.buildout-1.2.1``:: - - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample/eggs/distribute-...egg', - '/sample/eggs/zc.buildout-1.2.1...egg', - ] - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - <BLANKLINE> - -Last, the -c option needs to work on bootstrap.py:: - - >>> conf_file = os.path.join(sample_buildout, 'other.cfg') - >>> f = open(conf_file, 'w') - >>> f.write('[buildout]\nparts=\n\n') - >>> f.close() - >>> print 'X'; print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py -c %s --distribute' % conf_file); print 'X' # doctest: +ELLIPSIS - ... - X - ... - Generated script '/sample/bin/buildout'... - X - -You can specify a location of ez_setup.py or distribute_setup, so you -can rely on a local or remote location. We'll write our own ez_setup.py -that we will also use to test some other bootstrap options. - - >>> write('ez_setup.py', '''\ - ... def use_setuptools(**kwargs): - ... import sys, pprint - ... pprint.pprint(kwargs, width=40) - ... sys.exit() - ... ''') - >>> print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --setup-source=./ez_setup.py') - ... # doctest: +ELLIPSIS - {'download_delay': 0, - 'to_dir': '...'} - <BLANKLINE> - -You can also pass a download-cache, and a place in which eggs should be stored -(they are normally stored in a temporary directory). - - >>> print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --setup-source=./ez_setup.py '+ - ... '--download-base=./download-cache --eggs=eggs') - ... # doctest: +ELLIPSIS - {'download_base': '/sample/download-cache/', - 'download_delay': 0, - 'to_dir': '/sample/eggs'} - <BLANKLINE> - -Here's the entire help text. - - >>> print system( - ... zc.buildout.easy_install._safe_arg(sys.executable)+' '+ - ... 'bootstrap.py --help'), - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - Usage: [DESIRED PYTHON FOR BUILDOUT] bootstrap.py [options] - <BLANKLINE> - Bootstraps a buildout-based project. - <BLANKLINE> - Simply run this script in a directory containing a buildout.cfg, using the - Python that you want bin/buildout to use. - <BLANKLINE> - Note that by using --setup-source and --download-base to point to - local resources, you can keep this script from going over the network. - <BLANKLINE> - <BLANKLINE> - Options: - -h, --help show this help message and exit - -v VERSION, --version=VERSION - use a specific zc.buildout version - -d, --distribute Use Distribute rather than Setuptools. - --setup-source=SETUP_SOURCE - Specify a URL or file location for the setup file. If - you use Setuptools, this will default to - http://peak.telecommunity.com/dist/ez_setup.py; if you - use Distribute, this will default to http://python- - distribute.org/distribute_setup.py. - --download-base=DOWNLOAD_BASE - Specify a URL or directory for downloading zc.buildout - and either Setuptools or Distribute. Defaults to PyPI. - --eggs=EGGS Specify a directory for storing eggs. Defaults to a - temporary directory that is deleted when the bootstrap - script completes. - -t, --accept-buildout-test-releases - Normally, if you do not specify a --version, the - bootstrap script and buildout gets the newest *final* - versions of zc.buildout and its recipes and extensions - for you. If you use this flag, bootstrap and buildout - will get the newest releases even if they are alphas - or betas. - -c CONFIG_FILE Specify the path to the buildout configuration file to - be used. diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.py deleted file mode 100644 index 6fe4e8b..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.py +++ /dev/null @@ -1,1835 +0,0 @@ -############################################################################## -# -# Copyright (c) 2005-2009 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Buildout main script -""" - -from rmtree import rmtree -try: - from hashlib import md5 -except ImportError: - # Python 2.4 and older - from md5 import md5 - -import ConfigParser -import copy -import distutils.errors -import glob -import itertools -import logging -import os -import pkg_resources -import re -import shutil -import sys -import tempfile -import UserDict -import warnings -import zc.buildout -import zc.buildout.download -import zc.buildout.easy_install - - -realpath = zc.buildout.easy_install.realpath - -pkg_resources_loc = pkg_resources.working_set.find( - pkg_resources.Requirement.parse('setuptools')).location - -_isurl = re.compile('([a-zA-Z0-9+.-]+)://').match - -is_jython = sys.platform.startswith('java') - -if is_jython: - import subprocess - -_sys_executable_has_broken_dash_S = ( - zc.buildout.easy_install._has_broken_dash_S(sys.executable)) - -class MissingOption(zc.buildout.UserError, KeyError): - """A required option was missing. - """ - -class MissingSection(zc.buildout.UserError, KeyError): - """A required section is missing. - """ - - def __str__(self): - return "The referenced section, %r, was not defined." % self[0] - - -def _annotate_section(section, note): - for key in section: - section[key] = (section[key], note) - return section - -def _annotate(data, note): - for key in data: - data[key] = _annotate_section(data[key], note) - return data - -def _print_annotate(data): - sections = data.keys() - sections.sort() - print - print "Annotated sections" - print "="*len("Annotated sections") - for section in sections: - print - print '[%s]' % section - keys = data[section].keys() - keys.sort() - for key in keys: - value, notes = data[section][key] - keyvalue = "%s= %s" % (key, value) - print keyvalue - line = ' ' - for note in notes.split(): - if note == '[+]': - line = '+= ' - elif note == '[-]': - line = '-= ' - else: - print line, note - line = ' ' - print - - -def _unannotate_section(section): - for key in section: - value, note = section[key] - section[key] = value - return section - -def _unannotate(data): - for key in data: - data[key] = _unannotate_section(data[key]) - return data - -_buildout_default_options = _annotate_section({ - 'accept-buildout-test-releases': 'false', - 'allow-hosts': '*', - 'allow-picked-versions': 'true', - 'allowed-eggs-from-site-packages': '*', - 'bin-directory': 'bin', - 'develop-eggs-directory': 'develop-eggs', - 'eggs-directory': 'eggs', - 'executable': sys.executable, - 'exec-sitecustomize': 'true', - 'find-links': '', - 'include-site-packages': 'true', - 'install-from-cache': 'false', - 'installed': '.installed.cfg', - 'log-format': '', - 'log-level': 'INFO', - 'newest': 'true', - 'offline': 'false', - 'parts-directory': 'parts', - 'prefer-final': 'false', - 'python': 'buildout', - 'relative-paths': 'false', - 'socket-timeout': '', - 'unzip': 'false', - 'use-dependency-links': 'true', - }, 'DEFAULT_VALUE') - - -class Buildout(UserDict.DictMixin): - - def __init__(self, config_file, cloptions, - user_defaults=True, windows_restart=False, command=None): - - __doing__ = 'Initializing.' - - self.__windows_restart = windows_restart - - # default options - data = dict(buildout=_buildout_default_options.copy()) - self._buildout_dir = os.getcwd() - - if not _isurl(config_file): - config_file = os.path.abspath(config_file) - base = os.path.dirname(config_file) - if not os.path.exists(config_file): - if command == 'init': - print 'Creating %r.' % config_file - open(config_file, 'w').write('[buildout]\nparts = \n') - elif command == 'setup': - # Sigh. This model of a buildout instance - # with methods is breaking down. :( - config_file = None - data['buildout']['directory'] = ('.', 'COMPUTED_VALUE') - else: - raise zc.buildout.UserError( - "Couldn't open %s" % config_file) - - if config_file: - data['buildout']['directory'] = (os.path.dirname(config_file), - 'COMPUTED_VALUE') - else: - base = None - - - cloptions = dict( - (section, dict((option, (value, 'COMMAND_LINE_VALUE')) - for (_, option, value) in v)) - for (section, v) in itertools.groupby(sorted(cloptions), - lambda v: v[0]) - ) - override = cloptions.get('buildout', {}).copy() - - # load user defaults, which override defaults - if user_defaults: - user_config = os.path.join(os.path.expanduser('~'), - '.buildout', 'default.cfg') - if os.path.exists(user_config): - _update(data, _open(os.path.dirname(user_config), user_config, - [], data['buildout'].copy(), override)) - - # load configuration files - if config_file: - _update(data, _open(os.path.dirname(config_file), config_file, [], - data['buildout'].copy(), override)) - - # apply command-line options - _update(data, cloptions) - - self._annotated = copy.deepcopy(data) - self._raw = _unannotate(data) - self._data = {} - self._parts = [] - # provide some defaults before options are parsed - # because while parsing options those attributes might be - # used already (Gottfried Ganssauge) - buildout_section = data['buildout'] - - # Try to make sure we have absolute paths for standard - # directories. We do this before doing substitutions, in case - # a one of these gets read by another section. If any - # variable references are used though, we leave it as is in - # _buildout_path. - if 'directory' in buildout_section: - self._buildout_dir = buildout_section['directory'] - for name in ('bin', 'parts', 'eggs', 'develop-eggs'): - d = self._buildout_path(buildout_section[name+'-directory']) - buildout_section[name+'-directory'] = d - - # Attributes on this buildout object shouldn't be used by - # recipes in their __init__. It can cause bugs, because the - # recipes will be instantiated below (``options = self['buildout']``) - # before this has completed initializing. These attributes are - # left behind for legacy support but recipe authors should - # beware of using them. A better practice is for a recipe to - # use the buildout['buildout'] options. - links = buildout_section['find-links'] - self._links = links and links.split() or () - allow_hosts = buildout_section['allow-hosts'].split('\n') - self._allow_hosts = tuple([host.strip() for host in allow_hosts - if host.strip() != '']) - self._logger = logging.getLogger('zc.buildout') - self.offline = (buildout_section['offline'] == 'true') - self.newest = (buildout_section['newest'] == 'true') - self.accept_buildout_test_releases = ( - buildout_section['accept-buildout-test-releases'] == 'true') - - ################################################################## - ## WARNING!!! - ## ALL ATTRIBUTES MUST HAVE REASONABLE DEFAULTS AT THIS POINT - ## OTHERWISE ATTRIBUTEERRORS MIGHT HAPPEN ANY TIME FROM RECIPES. - ## RECIPES SHOULD GENERALLY USE buildout['buildout'] OPTIONS, NOT - ## BUILDOUT ATTRIBUTES. - ################################################################## - # initialize some attrs and buildout directories. - options = self['buildout'] - - # now reinitialize - links = options.get('find-links', '') - self._links = links and links.split() or () - - allow_hosts = options['allow-hosts'].split('\n') - self._allow_hosts = tuple([host.strip() for host in allow_hosts - if host.strip() != '']) - - self._buildout_dir = options['directory'] - - # Make sure we have absolute paths for standard directories. We do this - # a second time here in case someone overrode these in their configs. - for name in ('bin', 'parts', 'eggs', 'develop-eggs'): - d = self._buildout_path(options[name+'-directory']) - options[name+'-directory'] = d - - if options['installed']: - options['installed'] = os.path.join(options['directory'], - options['installed']) - - self._setup_logging() - - versions = options.get('versions') - if versions: - zc.buildout.easy_install.default_versions(dict(self[versions])) - - - self.offline = options.get_bool('offline') - if self.offline: - options['newest'] = 'false' - self.newest = options.get_bool('newest') - zc.buildout.easy_install.prefer_final( - options.get_bool('prefer-final')) - self.accept_buildout_test_releases = options.get_bool( - 'accept-buildout-test-releases') - zc.buildout.easy_install.use_dependency_links( - options.get_bool('use-dependency-links')) - zc.buildout.easy_install.allow_picked_versions( - options.get_bool('allow-picked-versions')) - zc.buildout.easy_install.install_from_cache( - options.get_bool('install-from-cache')) - zc.buildout.easy_install.always_unzip(options.get_bool('unzip')) - allowed_eggs = tuple(name.strip() for name in options[ - 'allowed-eggs-from-site-packages'].split('\n')) - self.include_site_packages = options.get_bool('include-site-packages') - self.exec_sitecustomize = options.get_bool('exec-sitecustomize') - if (_sys_executable_has_broken_dash_S and - (not self.include_site_packages or allowed_eggs != ('*',))): - # We can't do this if the executable has a broken -S. - warnings.warn(zc.buildout.easy_install.BROKEN_DASH_S_WARNING) - self.include_site_packages = True - zc.buildout.easy_install.allowed_eggs_from_site_packages(allowed_eggs) - zc.buildout.easy_install.include_site_packages( - self.include_site_packages) - - download_cache = options.get('download-cache') - if download_cache: - download_cache = os.path.join(options['directory'], download_cache) - if not os.path.isdir(download_cache): - raise zc.buildout.UserError( - 'The specified download cache:\n' - '%r\n' - "Doesn't exist.\n" - % download_cache) - download_cache = os.path.join(download_cache, 'dist') - if not os.path.isdir(download_cache): - os.mkdir(download_cache) - - zc.buildout.easy_install.download_cache(download_cache) - - # "Use" each of the defaults so they aren't reported as unused options. - for name in _buildout_default_options: - options[name] - - # Do the same for extends-cache which is not among the defaults but - # wasn't recognized as having been used since it was used before - # tracking was turned on. - options.get('extends-cache') - - os.chdir(options['directory']) - - def _buildout_path(self, name): - if '${' in name: - return name - return os.path.join(self._buildout_dir, name) - - def bootstrap(self, args): - __doing__ = 'Bootstrapping.' - - self._setup_directories() - - options = self['buildout'] - - # Get a base working set for our distributions that corresponds to the - # stated desires in the configuration. - distributions = ['setuptools', 'zc.buildout'] - if options.get('offline') == 'true': - ws = zc.buildout.easy_install.working_set( - distributions, options['executable'], - [options['develop-eggs-directory'], - options['eggs-directory']], - prefer_final=not self.accept_buildout_test_releases, - ) - else: - ws = zc.buildout.easy_install.install( - distributions, options['eggs-directory'], - links=self._links, - index=options.get('index'), - executable=options['executable'], - path=[options['develop-eggs-directory']], - newest=self.newest, - allow_hosts=self._allow_hosts, - prefer_final=not self.accept_buildout_test_releases, - ) - - # Now copy buildout and setuptools eggs, and record destination eggs: - entries = [] - for name in 'setuptools', 'zc.buildout': - r = pkg_resources.Requirement.parse(name) - dist = ws.find(r) - if dist.precedence == pkg_resources.DEVELOP_DIST: - dest = os.path.join(self['buildout']['develop-eggs-directory'], - name+'.egg-link') - open(dest, 'w').write(dist.location) - entries.append(dist.location) - else: - dest = os.path.join(self['buildout']['eggs-directory'], - os.path.basename(dist.location)) - entries.append(dest) - if not os.path.exists(dest): - if os.path.isdir(dist.location): - shutil.copytree(dist.location, dest) - else: - shutil.copy2(dist.location, dest) - - # Create buildout script. - # Ideally the (possibly) new version of buildout would get a - # chance to write the script. Not sure how to do that. - ws = pkg_resources.WorkingSet(entries) - ws.require('zc.buildout') - partsdir = os.path.join(options['parts-directory'], 'buildout') - if not os.path.exists(partsdir): - os.mkdir(partsdir) - # (Honor the relative-paths option.) - relative_paths = options.get('relative-paths', 'false') - if relative_paths == 'true': - relative_paths = options['directory'] - else: - assert relative_paths == 'false' - relative_paths = '' - if (self.accept_buildout_test_releases and - self._annotated['buildout']['accept-buildout-test-releases'][1] == - 'COMMAND_LINE_VALUE'): - # Bootstrap was called with '--accept-buildout-test-releases'. - # Continue to honor that setting. - script_initialization = _early_release_initialization_code - else: - script_initialization = '' - zc.buildout.easy_install.sitepackage_safe_scripts( - options['bin-directory'], ws, options['executable'], partsdir, - reqs=['zc.buildout'], relative_paths=relative_paths, - include_site_packages=self.include_site_packages, - script_initialization=script_initialization, - exec_sitecustomize=self.exec_sitecustomize, - ) - - init = bootstrap - - def install(self, install_args): - __doing__ = 'Installing.' - - self._load_extensions() - self._setup_directories() - - # Add develop-eggs directory to path so that it gets searched - # for eggs: - sys.path.insert(0, self['buildout']['develop-eggs-directory']) - - # Check for updates. This could cause the process to be restarted. - self._maybe_upgrade() - - # load installed data - (installed_part_options, installed_exists - )= self._read_installed_part_options() - - # Remove old develop eggs - self._uninstall( - installed_part_options['buildout'].get( - 'installed_develop_eggs', '') - ) - - # Build develop eggs - installed_develop_eggs = self._develop() - installed_part_options['buildout']['installed_develop_eggs' - ] = installed_develop_eggs - - if installed_exists: - self._update_installed( - installed_develop_eggs=installed_develop_eggs) - - # get configured and installed part lists - conf_parts = self['buildout']['parts'] - conf_parts = conf_parts and conf_parts.split() or [] - installed_parts = installed_part_options['buildout']['parts'] - installed_parts = installed_parts and installed_parts.split() or [] - - if install_args: - install_parts = install_args - uninstall_missing = False - else: - install_parts = conf_parts - uninstall_missing = True - - # load and initialize recipes - [self[part]['recipe'] for part in install_parts] - if not install_args: - install_parts = self._parts - - if self._log_level < logging.DEBUG: - sections = list(self) - sections.sort() - print - print 'Configuration data:' - for section in self._data: - _save_options(section, self[section], sys.stdout) - print - - - # compute new part recipe signatures - self._compute_part_signatures(install_parts) - - # uninstall parts that are no-longer used or whose configs - # have changed - for part in reversed(installed_parts): - if part in install_parts: - old_options = installed_part_options[part].copy() - installed_files = old_options.pop('__buildout_installed__') - new_options = self.get(part) - if old_options == new_options: - # The options are the same, but are all of the - # installed files still there? If not, we should - # reinstall. - if not installed_files: - continue - for f in installed_files.split('\n'): - if not os.path.exists(self._buildout_path(f)): - break - else: - continue - - # output debugging info - if self._logger.getEffectiveLevel() < logging.DEBUG: - for k in old_options: - if k not in new_options: - self._logger.debug("Part %s, dropped option %s.", - part, k) - elif old_options[k] != new_options[k]: - self._logger.debug( - "Part %s, option %s changed:\n%r != %r", - part, k, new_options[k], old_options[k], - ) - for k in new_options: - if k not in old_options: - self._logger.debug("Part %s, new option %s.", - part, k) - - elif not uninstall_missing: - continue - - self._uninstall_part(part, installed_part_options) - installed_parts = [p for p in installed_parts if p != part] - - if installed_exists: - self._update_installed(parts=' '.join(installed_parts)) - - # Check for unused buildout options: - _check_for_unused_options_in_section(self, 'buildout') - - # install new parts - for part in install_parts: - signature = self[part].pop('__buildout_signature__') - saved_options = self[part].copy() - recipe = self[part].recipe - if part in installed_parts: # update - need_to_save_installed = False - __doing__ = 'Updating %s.', part - self._logger.info(*__doing__) - old_options = installed_part_options[part] - old_installed_files = old_options['__buildout_installed__'] - - try: - update = recipe.update - except AttributeError: - update = recipe.install - self._logger.warning( - "The recipe for %s doesn't define an update " - "method. Using its install method.", - part) - - try: - installed_files = self[part]._call(update) - except: - installed_parts.remove(part) - self._uninstall(old_installed_files) - if installed_exists: - self._update_installed( - parts=' '.join(installed_parts)) - raise - - old_installed_files = old_installed_files.split('\n') - if installed_files is None: - installed_files = old_installed_files - else: - if isinstance(installed_files, str): - installed_files = [installed_files] - else: - installed_files = list(installed_files) - - need_to_save_installed = [ - p for p in installed_files - if p not in old_installed_files] - - if need_to_save_installed: - installed_files = (old_installed_files - + need_to_save_installed) - - else: # install - need_to_save_installed = True - __doing__ = 'Installing %s.', part - self._logger.info(*__doing__) - installed_files = self[part]._call(recipe.install) - if installed_files is None: - self._logger.warning( - "The %s install returned None. A path or " - "iterable of paths should be returned.", - part) - installed_files = () - elif isinstance(installed_files, str): - installed_files = [installed_files] - else: - installed_files = list(installed_files) - - installed_part_options[part] = saved_options - saved_options['__buildout_installed__' - ] = '\n'.join(installed_files) - saved_options['__buildout_signature__'] = signature - - installed_parts = [p for p in installed_parts if p != part] - installed_parts.append(part) - _check_for_unused_options_in_section(self, part) - - if need_to_save_installed: - installed_part_options['buildout']['parts'] = ( - ' '.join(installed_parts)) - self._save_installed_options(installed_part_options) - installed_exists = True - else: - assert installed_exists - self._update_installed(parts=' '.join(installed_parts)) - - if installed_develop_eggs: - if not installed_exists: - self._save_installed_options(installed_part_options) - elif (not installed_parts) and installed_exists: - os.remove(self['buildout']['installed']) - - self._unload_extensions() - - def _update_installed(self, **buildout_options): - installed = self['buildout']['installed'] - f = open(installed, 'a') - f.write('\n[buildout]\n') - for option, value in buildout_options.items(): - _save_option(option, value, f) - f.close() - - def _uninstall_part(self, part, installed_part_options): - # uninstall part - __doing__ = 'Uninstalling %s.', part - self._logger.info(*__doing__) - - # run uninstall recipe - recipe, entry = _recipe(installed_part_options[part]) - try: - uninstaller = _install_and_load( - recipe, 'zc.buildout.uninstall', entry, self) - self._logger.info('Running uninstall recipe.') - uninstaller(part, installed_part_options[part]) - except (ImportError, pkg_resources.DistributionNotFound), v: - pass - - # remove created files and directories - self._uninstall( - installed_part_options[part]['__buildout_installed__']) - - def _setup_directories(self): - __doing__ = 'Setting up buildout directories' - - # Create buildout directories - for name in ('bin', 'parts', 'eggs', 'develop-eggs'): - d = self['buildout'][name+'-directory'] - if not os.path.exists(d): - self._logger.info('Creating directory %r.', d) - os.mkdir(d) - - def _develop(self): - """Install sources by running setup.py develop on them - """ - __doing__ = 'Processing directories listed in the develop option' - - develop = self['buildout'].get('develop') - if not develop: - return '' - - dest = self['buildout']['develop-eggs-directory'] - old_files = os.listdir(dest) - - env = dict(os.environ, PYTHONPATH=pkg_resources_loc) - here = os.getcwd() - try: - try: - for setup in develop.split(): - setup = self._buildout_path(setup) - files = glob.glob(setup) - if not files: - self._logger.warn("Couldn't develop %r (not found)", - setup) - else: - files.sort() - for setup in files: - self._logger.info("Develop: %r", setup) - __doing__ = 'Processing develop directory %r.', setup - zc.buildout.easy_install.develop(setup, dest) - except: - # if we had an error, we need to roll back changes, by - # removing any files we created. - self._sanity_check_develop_eggs_files(dest, old_files) - self._uninstall('\n'.join( - [os.path.join(dest, f) - for f in os.listdir(dest) - if f not in old_files - ])) - raise - - else: - self._sanity_check_develop_eggs_files(dest, old_files) - return '\n'.join([os.path.join(dest, f) - for f in os.listdir(dest) - if f not in old_files - ]) - - finally: - os.chdir(here) - - - def _sanity_check_develop_eggs_files(self, dest, old_files): - for f in os.listdir(dest): - if f in old_files: - continue - if not (os.path.isfile(os.path.join(dest, f)) - and f.endswith('.egg-link')): - self._logger.warning( - "Unexpected entry, %r, in develop-eggs directory.", f) - - def _compute_part_signatures(self, parts): - # Compute recipe signature and add to options - for part in parts: - options = self.get(part) - if options is None: - options = self[part] = {} - recipe, entry = _recipe(options) - req = pkg_resources.Requirement.parse(recipe) - sig = _dists_sig(pkg_resources.working_set.resolve([req])) - options['__buildout_signature__'] = ' '.join(sig) - - def _read_installed_part_options(self): - old = self['buildout']['installed'] - if old and os.path.isfile(old): - parser = ConfigParser.RawConfigParser() - parser.optionxform = lambda s: s - parser.read(old) - result = {} - for section in parser.sections(): - options = {} - for option, value in parser.items(section): - if '%(' in value: - for k, v in _spacey_defaults: - value = value.replace(k, v) - options[option] = value - result[section] = Options(self, section, options) - - return result, True - else: - return ({'buildout': Options(self, 'buildout', {'parts': ''})}, - False, - ) - - def _uninstall(self, installed): - for f in installed.split('\n'): - if not f: - continue - f = self._buildout_path(f) - if os.path.isdir(f): - rmtree(f) - elif os.path.isfile(f): - try: - os.remove(f) - except OSError: - if not ( - sys.platform == 'win32' and - (realpath(os.path.join(os.path.dirname(sys.argv[0]), - 'buildout.exe')) - == - realpath(f) - ) - # Sigh. This is the exectable used to run the buildout - # and, of course, it's in use. Leave it. - ): - raise - - def _install(self, part): - options = self[part] - recipe, entry = _recipe(options) - recipe_class = pkg_resources.load_entry_point( - recipe, 'zc.buildout', entry) - installed = recipe_class(self, part, options).install() - if installed is None: - installed = [] - elif isinstance(installed, basestring): - installed = [installed] - base = self._buildout_path('') - installed = [d.startswith(base) and d[len(base):] or d - for d in installed] - return ' '.join(installed) - - - def _save_installed_options(self, installed_options): - installed = self['buildout']['installed'] - if not installed: - return - f = open(installed, 'w') - _save_options('buildout', installed_options['buildout'], f) - for part in installed_options['buildout']['parts'].split(): - print >>f - _save_options(part, installed_options[part], f) - f.close() - - def _error(self, message, *args): - raise zc.buildout.UserError(message % args) - - def _setup_logging(self): - root_logger = logging.getLogger() - self._logger = logging.getLogger('zc.buildout') - handler = logging.StreamHandler(sys.stdout) - log_format = self['buildout']['log-format'] - if not log_format: - # No format specified. Use different formatter for buildout - # and other modules, showing logger name except for buildout - log_format = '%(name)s: %(message)s' - buildout_handler = logging.StreamHandler(sys.stdout) - buildout_handler.setFormatter(logging.Formatter('%(message)s')) - self._logger.propagate = False - self._logger.addHandler(buildout_handler) - - handler.setFormatter(logging.Formatter(log_format)) - root_logger.addHandler(handler) - - level = self['buildout']['log-level'] - if level in ('DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'): - level = getattr(logging, level) - else: - try: - level = int(level) - except ValueError: - self._error("Invalid logging level %s", level) - verbosity = self['buildout'].get('verbosity', 0) - try: - verbosity = int(verbosity) - except ValueError: - self._error("Invalid verbosity %s", verbosity) - - level -= verbosity - root_logger.setLevel(level) - self._log_level = level - - def _maybe_upgrade(self): - # See if buildout or setuptools need to be upgraded. - # If they do, do the upgrade and restart the buildout process. - __doing__ = 'Checking for upgrades.' - - if not self.newest: - return - - options = self['buildout'] - - specs = ['zc.buildout'] - if zc.buildout.easy_install.is_distribute: - specs.append('distribute') - else: - specs.append('setuptools') - ws = zc.buildout.easy_install.install( - [ - (spec + ' ' + options.get(spec+'-version', '')).strip() - for spec in specs - ], - options['eggs-directory'], - links = options.get('find-links', '').split(), - index = options.get('index'), - path = [options['develop-eggs-directory']], - allow_hosts = self._allow_hosts, - prefer_final=not self.accept_buildout_test_releases, - ) - - upgraded = [] - for project in 'zc.buildout', 'setuptools': - req = pkg_resources.Requirement.parse(project) - project_location = pkg_resources.working_set.find(req).location - if ws.find(req).location != project_location: - upgraded.append(ws.find(req)) - - if not upgraded: - return - - __doing__ = 'Upgrading.' - - should_run = realpath( - os.path.join(os.path.abspath(options['bin-directory']), - 'buildout') - ) - if sys.platform == 'win32': - should_run += '-script.py' - - if (realpath(os.path.abspath(sys.argv[0])) != should_run): - self._logger.debug("Running %r.", realpath(sys.argv[0])) - self._logger.debug("Local buildout is %r.", should_run) - self._logger.warn("Not upgrading because not running a local " - "buildout command.") - return - - if sys.platform == 'win32' and not self.__windows_restart: - args = map(zc.buildout.easy_install._safe_arg, sys.argv) - args.insert(1, '-W') - if not __debug__: - args.insert(0, '-O') - args.insert(0, zc.buildout.easy_install._safe_arg (sys.executable)) - os.execv(sys.executable, args) - - self._logger.info("Upgraded:\n %s;\nrestarting.", - ",\n ".join([("%s version %s" - % (dist.project_name, dist.version) - ) - for dist in upgraded - ] - ), - ) - - # the new dist is different, so we've upgraded. - # Update the scripts and return True - # Ideally the new version of buildout would get a chance to write the - # script. Not sure how to do that. - partsdir = os.path.join(options['parts-directory'], 'buildout') - if os.path.exists(partsdir): - # This is primarily for unit tests, in which .py files change too - # fast for Python to know to regenerate the .pyc/.pyo files. - shutil.rmtree(partsdir) - os.mkdir(partsdir) - if (self.accept_buildout_test_releases and - self._annotated['buildout']['accept-buildout-test-releases'][1] == - 'COMMAND_LINE_VALUE'): - # Bootstrap was called with '--accept-buildout-test-releases'. - # Continue to honor that setting. - script_initialization = _early_release_initialization_code - else: - script_initialization = '' - # (Honor the relative-paths option.) - relative_paths = options.get('relative-paths', 'false') - if relative_paths == 'true': - relative_paths = options['directory'] - else: - assert relative_paths == 'false' - relative_paths = '' - zc.buildout.easy_install.sitepackage_safe_scripts( - options['bin-directory'], ws, options['executable'], partsdir, - reqs=['zc.buildout'], relative_paths=relative_paths, - include_site_packages=self.include_site_packages, - script_initialization=script_initialization, - exec_sitecustomize=self.exec_sitecustomize, - ) - - # Restart - args = map(zc.buildout.easy_install._safe_arg, sys.argv) - if not __debug__: - args.insert(0, '-O') - args.insert(0, zc.buildout.easy_install._safe_arg(sys.executable)) - # We want to make sure that our new site.py is used for rerunning - # buildout, so we put the partsdir in PYTHONPATH for our restart. - # This overrides any set PYTHONPATH, but since we generally are - # trying to run with a completely "clean" python (only the standard - # library) then that should be fine. - env = os.environ.copy() - env['PYTHONPATH'] = partsdir - if is_jython: - sys.exit( - subprocess.Popen( - [sys.executable] + list(args), env=env).wait()) - else: - sys.exit(os.spawnve(os.P_WAIT, sys.executable, args, env)) - - def _load_extensions(self): - __doing__ = 'Loading extensions.' - specs = self['buildout'].get('extensions', '').split() - if specs: - path = [self['buildout']['develop-eggs-directory']] - if self.offline: - dest = None - path.append(self['buildout']['eggs-directory']) - else: - dest = self['buildout']['eggs-directory'] - if not os.path.exists(dest): - self._logger.info('Creating directory %r.', dest) - os.mkdir(dest) - - zc.buildout.easy_install.install( - specs, dest, path=path, - working_set=pkg_resources.working_set, - links = self['buildout'].get('find-links', '').split(), - index = self['buildout'].get('index'), - newest=self.newest, allow_hosts=self._allow_hosts, - prefer_final=not self.accept_buildout_test_releases) - - # Clear cache because extensions might now let us read pages we - # couldn't read before. - zc.buildout.easy_install.clear_index_cache() - - for ep in pkg_resources.iter_entry_points('zc.buildout.extension'): - ep.load()(self) - - def _unload_extensions(self): - __doing__ = 'Unloading extensions.' - specs = self['buildout'].get('extensions', '').split() - if specs: - for ep in pkg_resources.iter_entry_points( - 'zc.buildout.unloadextension'): - ep.load()(self) - - def setup(self, args): - if not args: - raise zc.buildout.UserError( - "The setup command requires the path to a setup script or \n" - "directory containing a setup script, and its arguments." - ) - setup = args.pop(0) - if os.path.isdir(setup): - setup = os.path.join(setup, 'setup.py') - - self._logger.info("Running setup script %r.", setup) - setup = os.path.abspath(setup) - - fd, tsetup = tempfile.mkstemp() - exe = zc.buildout.easy_install._safe_arg(sys.executable) - try: - os.write(fd, zc.buildout.easy_install.runsetup_template % dict( - setuptools=pkg_resources_loc, - setupdir=os.path.dirname(setup), - setup=setup, - __file__ = setup, - )) - if is_jython: - arg_list = list() - - for a in args: - arg_list.append(zc.buildout.easy_install._safe_arg(a)) - - subprocess.Popen([exe] + list(tsetup) + arg_list).wait() - - else: - os.spawnl(os.P_WAIT, sys.executable, exe, tsetup, - *[zc.buildout.easy_install._safe_arg(a) - for a in args]) - finally: - os.close(fd) - os.remove(tsetup) - - runsetup = setup # backward compat. - - def annotate(self, args): - _print_annotate(self._annotated) - - def __getitem__(self, section): - __doing__ = 'Getting section %s.', section - try: - return self._data[section] - except KeyError: - pass - - try: - data = self._raw[section] - except KeyError: - raise MissingSection(section) - - options = Options(self, section, data) - self._data[section] = options - options._initialize() - return options - - def __setitem__(self, key, value): - raise NotImplementedError('__setitem__') - - def __delitem__(self, key): - raise NotImplementedError('__delitem__') - - def keys(self): - return self._raw.keys() - - def __iter__(self): - return iter(self._raw) - - -def _install_and_load(spec, group, entry, buildout): - __doing__ = 'Loading recipe %r.', spec - try: - req = pkg_resources.Requirement.parse(spec) - - buildout_options = buildout['buildout'] - if pkg_resources.working_set.find(req) is None: - __doing__ = 'Installing recipe %s.', spec - if buildout.offline: - dest = None - path = [buildout_options['develop-eggs-directory'], - buildout_options['eggs-directory'], - ] - else: - dest = buildout_options['eggs-directory'] - path = [buildout_options['develop-eggs-directory']] - - zc.buildout.easy_install.install( - [spec], dest, - links=buildout._links, - index=buildout_options.get('index'), - path=path, - working_set=pkg_resources.working_set, - newest=buildout.newest, - allow_hosts=buildout._allow_hosts, - prefer_final=not buildout.accept_buildout_test_releases) - - __doing__ = 'Loading %s recipe entry %s:%s.', group, spec, entry - return pkg_resources.load_entry_point( - req.project_name, group, entry) - - except Exception, v: - buildout._logger.log( - 1, - "Could't load %s entry point %s\nfrom %s:\n%s.", - group, entry, spec, v) - raise - - -class Options(UserDict.DictMixin): - - def __init__(self, buildout, section, data): - self.buildout = buildout - self.name = section - self._raw = data - self._cooked = {} - self._data = {} - - def _initialize(self): - name = self.name - __doing__ = 'Initializing section %s.', name - - if '<' in self._raw: - self._raw = self._do_extend_raw(name, self._raw, []) - - # force substitutions - for k, v in self._raw.items(): - if '${' in v: - self._dosub(k, v) - - if self.name == 'buildout': - return # buildout section can never be a part - - recipe = self.get('recipe') - if not recipe: - return - - reqs, entry = _recipe(self._data) - buildout = self.buildout - recipe_class = _install_and_load(reqs, 'zc.buildout', entry, buildout) - - __doing__ = 'Initializing part %s.', name - self.recipe = recipe_class(buildout, name, self) - buildout._parts.append(name) - - def _do_extend_raw(self, name, data, doing): - if name == 'buildout': - return data - if name in doing: - raise zc.buildout.UserError("Infinite extending loop %r" % name) - doing.append(name) - try: - to_do = data.pop('<', None) - if to_do is None: - return data - __doing__ = 'Loading input sections for %r', name - - result = {} - for iname in to_do.split('\n'): - iname = iname.strip() - if not iname: - continue - raw = self.buildout._raw.get(iname) - if raw is None: - raise zc.buildout.UserError("No section named %r" % iname) - result.update(self._do_extend_raw(iname, raw, doing)) - - result.update(data) - return result - finally: - assert doing.pop() == name - - def _dosub(self, option, v): - __doing__ = 'Getting option %s:%s.', self.name, option - seen = [(self.name, option)] - v = '$$'.join([self._sub(s, seen) for s in v.split('$$')]) - self._cooked[option] = v - - def get(self, option, default=None, seen=None): - try: - return self._data[option] - except KeyError: - pass - - v = self._cooked.get(option) - if v is None: - v = self._raw.get(option) - if v is None: - return default - - __doing__ = 'Getting option %s:%s.', self.name, option - - if '${' in v: - key = self.name, option - if seen is None: - seen = [key] - elif key in seen: - raise zc.buildout.UserError( - "Circular reference in substitutions.\n" - ) - else: - seen.append(key) - v = '$$'.join([self._sub(s, seen) for s in v.split('$$')]) - seen.pop() - - self._data[option] = v - return v - - _template_split = re.compile('([$]{[^}]*})').split - _simple = re.compile('[-a-zA-Z0-9 ._]+$').match - _valid = re.compile('\${[-a-zA-Z0-9 ._]*:[-a-zA-Z0-9 ._]+}$').match - def _sub(self, template, seen): - value = self._template_split(template) - subs = [] - for ref in value[1::2]: - s = tuple(ref[2:-1].split(':')) - if not self._valid(ref): - if len(s) < 2: - raise zc.buildout.UserError("The substitution, %s,\n" - "doesn't contain a colon." - % ref) - if len(s) > 2: - raise zc.buildout.UserError("The substitution, %s,\n" - "has too many colons." - % ref) - if not self._simple(s[0]): - raise zc.buildout.UserError( - "The section name in substitution, %s,\n" - "has invalid characters." - % ref) - if not self._simple(s[1]): - raise zc.buildout.UserError( - "The option name in substitution, %s,\n" - "has invalid characters." - % ref) - - section, option = s - if not section: - section = self.name - v = self.buildout[section].get(option, None, seen) - if v is None: - if option == '_buildout_section_name_': - v = self.name - else: - raise MissingOption("Referenced option does not exist:", - section, option) - subs.append(v) - subs.append('') - - return ''.join([''.join(v) for v in zip(value[::2], subs)]) - - def __getitem__(self, key): - try: - return self._data[key] - except KeyError: - pass - - v = self.get(key) - if v is None: - raise MissingOption("Missing option: %s:%s" % (self.name, key)) - return v - - def __setitem__(self, option, value): - if not isinstance(value, str): - raise TypeError('Option values must be strings', value) - self._data[option] = value - - def __delitem__(self, key): - if key in self._raw: - del self._raw[key] - if key in self._data: - del self._data[key] - if key in self._cooked: - del self._cooked[key] - elif key in self._data: - del self._data[key] - else: - raise KeyError, key - - def keys(self): - raw = self._raw - return list(self._raw) + [k for k in self._data if k not in raw] - - def copy(self): - result = self._raw.copy() - result.update(self._cooked) - result.update(self._data) - return result - - def _call(self, f): - buildout_directory = self.buildout['buildout']['directory'] - self._created = [] - try: - try: - os.chdir(buildout_directory) - return f() - except: - for p in self._created: - if os.path.isdir(p): - rmtree(p) - elif os.path.isfile(p): - os.remove(p) - else: - self.buildout._logger.warn("Couldn't clean up %r.", p) - raise - finally: - self._created = None - os.chdir(buildout_directory) - - def created(self, *paths): - try: - self._created.extend(paths) - except AttributeError: - raise TypeError( - "Attempt to register a created path while not installing", - self.name) - return self._created - - def query_bool(self, name, default=None): - """Given a name, return a boolean value for that name. - - ``default``, if given, should be 'true', 'false', or None. - """ - if default is not None: - value = self.setdefault(name, default=default) - else: - value = self.get(name) - if value is None: - return value - return _convert_bool(name, value) - - def get_bool(self, name): - """Given a name, return a boolean value for that name. - """ - return _convert_bool(name, self[name]) - - -def _convert_bool(name, value): - if value not in ('true', 'false'): - raise zc.buildout.UserError( - 'Invalid value for %s option: %s' % (name, value)) - else: - return value == 'true' - -_spacey_nl = re.compile('[ \t\r\f\v]*\n[ \t\r\f\v\n]*' - '|' - '^[ \t\r\f\v]+' - '|' - '[ \t\r\f\v]+$' - ) - -_spacey_defaults = [ - ('%(__buildout_space__)s', ' '), - ('%(__buildout_space_n__)s', '\n'), - ('%(__buildout_space_r__)s', '\r'), - ('%(__buildout_space_f__)s', '\f'), - ('%(__buildout_space_v__)s', '\v'), - ] - -def _quote_spacey_nl(match): - match = match.group(0).split('\n', 1) - result = '\n\t'.join( - [(s - .replace(' ', '%(__buildout_space__)s') - .replace('\r', '%(__buildout_space_r__)s') - .replace('\f', '%(__buildout_space_f__)s') - .replace('\v', '%(__buildout_space_v__)s') - .replace('\n', '%(__buildout_space_n__)s') - ) - for s in match] - ) - return result - -def _save_option(option, value, f): - value = _spacey_nl.sub(_quote_spacey_nl, value) - if value.startswith('\n\t'): - value = '%(__buildout_space_n__)s' + value[2:] - if value.endswith('\n\t'): - value = value[:-2] + '%(__buildout_space_n__)s' - print >>f, option, '=', value - -def _save_options(section, options, f): - print >>f, '[%s]' % section - items = options.items() - items.sort() - for option, value in items: - _save_option(option, value, f) - -def _open(base, filename, seen, dl_options, override): - """Open a configuration file and return the result as a dictionary, - - Recursively open other files based on buildout options found. - """ - _update_section(dl_options, override) - _dl_options = _unannotate_section(dl_options.copy()) - is_temp = False - download = zc.buildout.download.Download( - _dl_options, cache=_dl_options.get('extends-cache'), fallback=True, - hash_name=True) - if _isurl(filename): - path, is_temp = download(filename) - fp = open(path) - base = filename[:filename.rfind('/')] - elif _isurl(base): - if os.path.isabs(filename): - fp = open(filename) - base = os.path.dirname(filename) - else: - filename = base + '/' + filename - path, is_temp = download(filename) - fp = open(path) - base = filename[:filename.rfind('/')] - else: - filename = os.path.join(base, filename) - fp = open(filename) - base = os.path.dirname(filename) - - if filename in seen: - if is_temp: - fp.close() - os.remove(path) - raise zc.buildout.UserError("Recursive file include", seen, filename) - - root_config_file = not seen - seen.append(filename) - - result = {} - - parser = ConfigParser.RawConfigParser() - parser.optionxform = lambda s: s - parser.readfp(fp) - if is_temp: - fp.close() - os.remove(path) - - extends = extended_by = None - for section in parser.sections(): - options = dict(parser.items(section)) - if section == 'buildout': - extends = options.pop('extends', extends) - extended_by = options.pop('extended-by', extended_by) - result[section] = options - - result = _annotate(result, filename) - - if root_config_file and 'buildout' in result: - dl_options = _update_section(dl_options, result['buildout']) - - if extends: - extends = extends.split() - eresult = _open(base, extends.pop(0), seen, dl_options, override) - for fname in extends: - _update(eresult, _open(base, fname, seen, dl_options, override)) - result = _update(eresult, result) - - if extended_by: - self._logger.warn( - "The extendedBy option is deprecated. Stop using it." - ) - for fname in extended_by.split(): - result = _update(result, - _open(base, fname, seen, dl_options, override)) - - seen.pop() - return result - - -ignore_directories = '.svn', 'CVS' -def _dir_hash(dir): - hash = md5() - for (dirpath, dirnames, filenames) in os.walk(dir): - dirnames[:] = [n for n in dirnames if n not in ignore_directories] - filenames[:] = [f for f in filenames - if (not (f.endswith('pyc') or f.endswith('pyo')) - and os.path.exists(os.path.join(dirpath, f))) - ] - hash.update(' '.join(dirnames)) - hash.update(' '.join(filenames)) - for name in filenames: - hash.update(open(os.path.join(dirpath, name)).read()) - return hash.digest().encode('base64').strip() - -def _dists_sig(dists): - result = [] - for dist in dists: - location = dist.location - if dist.precedence == pkg_resources.DEVELOP_DIST: - result.append(dist.project_name + '-' + _dir_hash(location)) - else: - result.append(os.path.basename(location)) - return result - -def _update_section(s1, s2): - s2 = s2.copy() # avoid mutating the second argument, which is unexpected - for k, v in s2.items(): - v2, note2 = v - if k.endswith('+'): - key = k.rstrip(' +') - v1, note1 = s1.get(key, ("", "")) - newnote = ' [+] '.join((note1, note2)).strip() - s2[key] = "\n".join((v1).split('\n') + - v2.split('\n')), newnote - del s2[k] - elif k.endswith('-'): - key = k.rstrip(' -') - v1, note1 = s1.get(key, ("", "")) - newnote = ' [-] '.join((note1, note2)).strip() - s2[key] = ("\n".join( - [v for v in v1.split('\n') - if v not in v2.split('\n')]), newnote) - del s2[k] - - s1.update(s2) - return s1 - -def _update(d1, d2): - for section in d2: - if section in d1: - d1[section] = _update_section(d1[section], d2[section]) - else: - d1[section] = d2[section] - return d1 - -def _recipe(options): - recipe = options['recipe'] - if ':' in recipe: - recipe, entry = recipe.split(':') - else: - entry = 'default' - - return recipe, entry - -def _doing(): - _, v, tb = sys.exc_info() - message = str(v) - doing = [] - while tb is not None: - d = tb.tb_frame.f_locals.get('__doing__') - if d: - doing.append(d) - tb = tb.tb_next - - if doing: - sys.stderr.write('While:\n') - for d in doing: - if not isinstance(d, str): - d = d[0] % d[1:] - sys.stderr.write(' %s\n' % d) - -def _error(*message): - sys.stderr.write('Error: ' + ' '.join(message) +'\n') - sys.exit(1) - -_internal_error_template = """ -An internal error occurred due to a bug in either zc.buildout or in a -recipe being used: -""" - -def _check_for_unused_options_in_section(buildout, section): - options = buildout[section] - unused = [option for option in options._raw if option not in options._data] - if unused: - buildout._logger.warn("Unused options for %s: %s." - % (section, ' '.join(map(repr, unused))) - ) - -_early_release_initialization_code = """\ -sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true') -print ('NOTE: Accepting early releases of build system packages. Rerun ' - 'bootstrap without --accept-buildout-test-releases (-t) to return to ' - 'default behavior.') -""" - -_usage = """\ -Usage: buildout [options] [assignments] [command [command arguments]] - -Options: - - -h, --help - - Print this message and exit. - - -v - - Increase the level of verbosity. This option can be used multiple times. - - -q - - Decrease the level of verbosity. This option can be used multiple times. - - -c config_file - - Specify the path to the buildout configuration file to be used. - This defaults to the file named "buildout.cfg" in the current - working directory. - - -t socket_timeout - - Specify the socket timeout in seconds. - - -U - - Don't read user defaults. - - -o - - Run in off-line mode. This is equivalent to the assignment - buildout:offline=true. - - -O - - Run in non-off-line mode. This is equivalent to the assignment - buildout:offline=false. This is the default buildout mode. The - -O option would normally be used to override a true offline - setting in a configuration file. - - -n - - Run in newest mode. This is equivalent to the assignment - buildout:newest=true. With this setting, which is the default, - buildout will try to find the newest versions of distributions - available that satisfy its requirements. - - -N - - Run in non-newest mode. This is equivalent to the assignment - buildout:newest=false. With this setting, buildout will not seek - new distributions if installed distributions satisfy it's - requirements. - - -D - - Debug errors. If an error occurs, then the post-mortem debugger - will be started. This is especially useful for debuging recipe - problems. - - -s - - Squelch warnings about using an executable with a broken -S - implementation. - -Assignments are of the form: section:option=value and are used to -provide configuration options that override those given in the -configuration file. For example, to run the buildout in offline mode, -use buildout:offline=true. - -Options and assignments can be interspersed. - -Commands: - - install [parts] - - Install parts. If no command arguments are given, then the parts - definition from the configuration file is used. Otherwise, the - arguments specify the parts to be installed. - - Note that the semantics differ depending on whether any parts are - specified. If parts are specified, then only those parts will be - installed. If no parts are specified, then the parts specified by - the buildout parts option will be installed along with all of - their dependencies. - - bootstrap - - Create a new buildout in the current working directory, copying - the buildout and setuptools eggs and, creating a basic directory - structure and a buildout-local buildout script. - - init - - Initialize a buildout, creating a buildout.cfg file if it doesn't - exist and then performing the same actions as for the buildout - command. - - setup script [setup command and options] - - Run a given setup script arranging that setuptools is in the - script's path and and that it has been imported so that - setuptools-provided commands (like bdist_egg) can be used even if - the setup script doesn't import setuptools itself. - - The script can be given either as a script path or a path to a - directory containing a setup.py script. - - annotate - - Display annotated sections. All sections are displayed, sorted - alphabetically. For each section, all key-value pairs are displayed, - sorted alphabetically, along with the origin of the value (file name or - COMPUTED_VALUE, DEFAULT_VALUE, COMMAND_LINE_VALUE). - -""" -def _help(): - print _usage - sys.exit(0) - -def main(args=None): - if args is None: - args = sys.argv[1:] - - config_file = 'buildout.cfg' - verbosity = 0 - options = [] - windows_restart = False - user_defaults = True - debug = False - ignore_broken_dash_s = False - while args: - if args[0][0] == '-': - op = orig_op = args.pop(0) - op = op[1:] - while op and op[0] in 'vqhWUoOnNDAs': - if op[0] == 'v': - verbosity += 10 - elif op[0] == 'q': - verbosity -= 10 - elif op[0] == 'W': - windows_restart = True - elif op[0] == 'U': - user_defaults = False - elif op[0] == 'o': - options.append(('buildout', 'offline', 'true')) - elif op[0] == 'O': - options.append(('buildout', 'offline', 'false')) - elif op[0] == 'n': - options.append(('buildout', 'newest', 'true')) - elif op[0] == 'N': - options.append(('buildout', 'newest', 'false')) - elif op[0] == 'D': - debug = True - elif op[0] == 's': - ignore_broken_dash_s = True - else: - _help() - op = op[1:] - - if op[:1] in ('c', 't'): - op_ = op[:1] - op = op[1:] - - if op_ == 'c': - if op: - config_file = op - else: - if args: - config_file = args.pop(0) - else: - _error("No file name specified for option", orig_op) - elif op_ == 't': - try: - timeout = int(args.pop(0)) - except IndexError: - _error("No timeout value specified for option", orig_op) - except ValueError: - _error("No timeout value must be numeric", orig_op) - - import socket - print 'Setting socket time out to %d seconds' % timeout - socket.setdefaulttimeout(timeout) - - elif op: - if orig_op == '--help': - _help() - _error("Invalid option", '-'+op[0]) - elif '=' in args[0]: - option, value = args.pop(0).split('=', 1) - if len(option.split(':')) != 2: - _error('Invalid option:', option) - section, option = option.split(':') - options.append((section.strip(), option.strip(), value.strip())) - else: - # We've run out of command-line options and option assignnemnts - # The rest should be commands, so we'll stop here - break - - if verbosity < 0 or ignore_broken_dash_s: - broken_dash_S_filter_action = 'ignore' - elif verbosity == 0: # This is the default. - broken_dash_S_filter_action = 'once' - else: - broken_dash_S_filter_action = 'default' - warnings.filterwarnings( - broken_dash_S_filter_action, - re.escape( - zc.buildout.easy_install.BROKEN_DASH_S_WARNING), - UserWarning) - if verbosity: - options.append(('buildout', 'verbosity', str(verbosity))) - - if args: - command = args.pop(0) - if command not in ( - 'install', 'bootstrap', 'runsetup', 'setup', 'init', - 'annotate', - ): - _error('invalid command:', command) - else: - command = 'install' - - try: - try: - buildout = Buildout(config_file, options, - user_defaults, windows_restart, command) - getattr(buildout, command)(args) - except SystemExit: - pass - except Exception, v: - _doing() - exc_info = sys.exc_info() - import pdb, traceback - if debug: - traceback.print_exception(*exc_info) - sys.stderr.write('\nStarting pdb:\n') - pdb.post_mortem(exc_info[2]) - else: - if isinstance(v, (zc.buildout.UserError, - distutils.errors.DistutilsError, - ) - ): - _error(str(v)) - else: - sys.stderr.write(_internal_error_template) - traceback.print_exception(*exc_info) - sys.exit(1) - - - finally: - logging.shutdown() - -if sys.version_info[:2] < (2, 4): - def reversed(iterable): - result = list(iterable); - result.reverse() - return result diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt deleted file mode 100644 index ba3a72f..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/buildout.txt +++ /dev/null @@ -1,2831 +0,0 @@ -Buildouts -========= - -The word "buildout" refers to a description of a set of parts and the -software to create and assemble them. It is often used informally to -refer to an installed system based on a buildout definition. For -example, if we are creating an application named "Foo", then "the Foo -buildout" is the collection of configuration and application-specific -software that allows an instance of the application to be created. We -may refer to such an instance of the application informally as "a Foo -buildout". - -This document describes how to define buildouts using buildout -configuration files and recipes. There are three ways to set up the -buildout software and create a buildout instance: - -1. Install the zc.buildout egg with easy_install and use the buildout - script installed in a Python scripts area. - -2. Use the buildout bootstrap script to create a buildout that - includes both the setuptools and zc.buildout eggs. This allows you - to use the buildout software without modifying a Python install. - The buildout script is installed into your buildout local scripts - area. - -3. Use a buildout command from an already installed buildout to - bootstrap a new buildout. (See the section on bootstraping later - in this document.) - -Often, a software project will be managed in a software repository, -such as a subversion repository, that includes some software source -directories, buildout configuration files, and a copy of the buildout -bootstrap script. To work on the project, one would check out the -project from the repository and run the bootstrap script which -installs setuptools and zc.buildout into the checkout as well as any -parts defined. - -We have a sample buildout that we created using the bootstrap command -of an existing buildout (method 3 above). It has the absolute minimum -information. We have bin, develop-eggs, eggs and parts directories, -and a configuration file: - - >>> ls(sample_buildout) - d bin - - buildout.cfg - d develop-eggs - d eggs - d parts - -The bin directory contains scripts. - - >>> ls(sample_buildout, 'bin') - - buildout - - >>> ls(sample_buildout, 'eggs') - - setuptools-0.6-py2.4.egg - - zc.buildout-1.0-py2.4.egg - -The develop-eggs directory is initially empty: - - >>> ls(sample_buildout, 'develop-eggs') - -The develop-eggs directory holds egg links for software being -developed in the buildout. We separate develop-eggs and other eggs to -allow eggs directories to be shared across multiple buildouts. For -example, a common developer technique is to define a common eggs -directory in their home that all non-develop eggs are stored in. This -allows larger buildouts to be set up much more quickly and saves disk -space. - -The parts directory just contains some helpers for the buildout script -itself. - - >>> ls(sample_buildout, 'parts') - d buildout - -The parts directory provides an area where recipes can install -part data. For example, if we built a custom Python, we would -install it in the part directory. Part data is stored in a -sub-directory of the parts directory with the same name as the part. - -Buildouts are defined using configuration files. These are in the -format defined by the Python ConfigParser module, with extensions -that we'll describe later. By default, when a buildout is run, it -looks for the file buildout.cfg in the directory where the buildout is -run. - -The minimal configuration file has a buildout section that defines no -parts: - - >>> cat(sample_buildout, 'buildout.cfg') - [buildout] - parts = - -A part is simply something to be created by a buildout. It can be -almost anything, such as a Python package, a program, a directory, or -even a configuration file. - -Recipes -------- - -A part is created by a recipe. Recipes are always installed as Python -eggs. They can be downloaded from a package server, such as the -Python Package Index, or they can be developed as part of a project -using a "develop" egg. - -A develop egg is a special kind of egg that gets installed as an "egg -link" that contains the name of a source directory. Develop eggs -don't have to be packaged for distribution to be used and can be -modified in place, which is especially useful while they are being -developed. - -Let's create a recipe as part of the sample project. We'll create a -recipe for creating directories. First, we'll create a recipes source -directory for our local recipes: - - >>> mkdir(sample_buildout, 'recipes') - -and then we'll create a source file for our mkdir recipe: - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... """ - ... import logging, os, zc.buildout - ... - ... class Mkdir: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... options['path'] = os.path.join( - ... buildout['buildout']['directory'], - ... options['path'], - ... ) - ... if not os.path.isdir(os.path.dirname(options['path'])): - ... logging.getLogger(self.name).error( - ... 'Cannot create %s. %s is not a directory.', - ... options['path'], os.path.dirname(options['path'])) - ... raise zc.buildout.UserError('Invalid Path') - ... - ... - ... def install(self): - ... path = self.options['path'] - ... logging.getLogger(self.name).info( - ... 'Creating directory %s', os.path.basename(path)) - ... os.mkdir(path) - ... return path - ... - ... def update(self): - ... pass - ... """) - -Currently, recipes must define 3 methods [#future_recipe_methods]_: - -- a constructor, - -- an install method, and - -- an update method. - -The constructor is responsible for updating a parts options to reflect -data read from other sections. The buildout system keeps track of -whether a part specification has changed. A part specification has -changed if it's options, after adjusting for data read from other -sections, has changed, or if the recipe has changed. Only the options -for the part are considered. If data are read from other sections, -then that information has to be reflected in the parts options. In -the Mkdir example, the given path is interpreted relative to the -buildout directory, and data from the buildout directory is read. The -path option is updated to reflect this. If the directory option was -changed in the buildout sections, we would know to update parts -created using the mkdir recipe using relative path names. - -When buildout is run, it saves configuration data for installed parts -in a file named ".installed.cfg". In subsequent runs, it compares -part-configuration data stored in the .installed.cfg file and the -part-configuration data loaded from the configuration files as -modified by recipe constructors to decide if the configuration of a -part has changed. If the configuration has changed, or if the recipe -has changed, then the part is uninstalled and reinstalled. The -buildout only looks at the part's options, so any data used to -configure the part needs to be reflected in the part's options. It is -the job of a recipe constructor to make sure that the options include -all relevant data. - -Of course, parts are also uninstalled if they are no-longer used. - -The recipe defines a constructor that takes a buildout object, a part -name, and an options dictionary. It saves them in instance attributes. -If the path is relative, we'll interpret it as relative to the -buildout directory. The buildout object passed in is a mapping from -section name to a mapping of options for that section. The buildout -directory is available as the directory option of the buildout -section. We normalize the path and save it back into the options -directory. - -The install method is responsible for creating the part. In this -case, we need the path of the directory to create. We'll use a path -option from our options dictionary. The install method logs what it's -doing using the Python logging call. We return the path that we -installed. If the part is uninstalled or reinstalled, then the path -returned will be removed by the buildout machinery. A recipe install -method is expected to return a string, or an iterable of strings -containing paths to be removed if a part is uninstalled. For most -recipes, this is all of the uninstall support needed. For more complex -uninstallation scenarios use `Uninstall recipes`_. - -The update method is responsible for updating an already installed -part. An empty method is often provided, as in this example, if parts -can't be updated. An update method can return None, a string, or an -iterable of strings. If a string or iterable of strings is returned, -then the saved list of paths to be uninstalled is updated with the new -information by adding any new files returned by the update method. - -We need to provide packaging information so that our recipe can be -installed as a develop egg. The minimum information we need to specify -[#packaging_info]_ is a name. For recipes, we also need to define the -names of the recipe classes as entry points. Packaging information is -provided via a setup.py script: - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup( - ... name = "recipes", - ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']}, - ... ) - ... """) - -Our setup script defines an entry point. Entry points provide -a way for an egg to define the services it provides. Here we've said -that we define a zc.buildout entry point named mkdir. Recipe -classes must be exposed as entry points in the zc.buildout group. we -give entry points names within the group. - -We also need a README.txt for our recipes to avoid an annoying warning -from distutils, on which setuptools and zc.buildout are based: - - >>> write(sample_buildout, 'recipes', 'README.txt', " ") - -Now let's update our buildout.cfg: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mystuff - ... """) - -Let's go through the changes one by one:: - - develop = recipes - -This tells the buildout to install a development egg for our recipes. -Any number of paths can be listed. The paths can be relative or -absolute. If relative, they are treated as relative to the buildout -directory. They can be directory or file paths. If a file path is -given, it should point to a Python setup script. If a directory path -is given, it should point to a directory containing a setup.py file. -Development eggs are installed before building any parts, as they may -provide locally-defined recipes needed by the parts. - -:: - - parts = data-dir - -Here we've named a part to be "built". We can use any name we want -except that different part names must be unique and recipes will often -use the part name to decide what to do. - -:: - - [data-dir] - recipe = recipes:mkdir - path = mystuff - - -When we name a part, we also create a section of the same -name that contains part data. In this section, we'll define -the recipe to be used to install the part. In this case, we also -specify the path to be created. - -Let's run the buildout. We do so by running the build script in the -buildout: - - >>> import os - >>> os.chdir(sample_buildout) - >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing data-dir. - data-dir: Creating directory mystuff - -We see that the recipe created the directory, as expected: - - >>> ls(sample_buildout) - - .installed.cfg - d bin - - buildout.cfg - d develop-eggs - d eggs - d mystuff - d parts - d recipes - -In addition, .installed.cfg has been created containing information -about the part we installed: - - >>> cat(sample_buildout, '.installed.cfg') - [buildout] - installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link - parts = data-dir - <BLANKLINE> - [data-dir] - __buildout_installed__ = /sample-buildout/mystuff - __buildout_signature__ = recipes-c7vHV6ekIDUPy/7fjAaYjg== - path = /sample-buildout/mystuff - recipe = recipes:mkdir - -Note that the directory we installed is included in .installed.cfg. -In addition, the path option includes the actual destination -directory. - -If we change the name of the directory in the configuration file, -we'll see that the directory gets removed and recreated: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mydata - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling data-dir. - Installing data-dir. - data-dir: Creating directory mydata - - >>> ls(sample_buildout) - - .installed.cfg - d bin - - buildout.cfg - d develop-eggs - d eggs - d mydata - d parts - d recipes - -If any of the files or directories created by a recipe are removed, -the part will be reinstalled: - - >>> rmdir(sample_buildout, 'mydata') - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling data-dir. - Installing data-dir. - data-dir: Creating directory mydata - -Error reporting ---------------- - -If a user makes an error, an error needs to be printed and work needs -to stop. This is accomplished by logging a detailed error message and -then raising a (or an instance of a subclass of a) -zc.buildout.UserError exception. Raising an error other than a -UserError still displays the error, but labels it as a bug in the -buildout software or recipe. In the sample above, of someone gives a -non-existent directory to create the directory in: - - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = /xxx/mydata - ... """) - -We'll get a user error, not a traceback. - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - data-dir: Cannot create /xxx/mydata. /xxx is not a directory. - While: - Installing. - Getting section data-dir. - Initializing part data-dir. - Error: Invalid Path - - -Recipe Error Handling ---------------------- - -If an error occurs during installation, it is up to the recipe to -clean up any system side effects, such as files created. Let's update -the mkdir recipe to support multiple paths: - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... """ - ... import logging, os, zc.buildout - ... - ... class Mkdir: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... - ... # Normalize paths and check that their parent - ... # directories exist: - ... paths = [] - ... for path in options['path'].split(): - ... path = os.path.join(buildout['buildout']['directory'], path) - ... if not os.path.isdir(os.path.dirname(path)): - ... logging.getLogger(self.name).error( - ... 'Cannot create %s. %s is not a directory.', - ... options['path'], os.path.dirname(options['path'])) - ... raise zc.buildout.UserError('Invalid Path') - ... paths.append(path) - ... options['path'] = ' '.join(paths) - ... - ... def install(self): - ... paths = self.options['path'].split() - ... for path in paths: - ... logging.getLogger(self.name).info( - ... 'Creating directory %s', os.path.basename(path)) - ... os.mkdir(path) - ... return paths - ... - ... def update(self): - ... pass - ... """) - -If there is an error creating a path, the install method will exit and -leave previously created paths in place: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = foo bin - ... """) - - >>> print system(buildout), # doctest: +ELLIPSIS - Develop: '/sample-buildout/recipes' - Uninstalling data-dir. - Installing data-dir. - data-dir: Creating directory foo - data-dir: Creating directory bin - While: - Installing data-dir. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - OSError: [Errno 17] File exists: '/sample-buildout/bin' - -We meant to create a directory bins, but typed bin. Now foo was -left behind. - - >>> os.path.exists('foo') - True - -If we fix the typo: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = foo bins - ... """) - - >>> print system(buildout), # doctest: +ELLIPSIS - Develop: '/sample-buildout/recipes' - Installing data-dir. - data-dir: Creating directory foo - While: - Installing data-dir. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - OSError: [Errno 17] File exists: '/sample-buildout/foo' - -Now they fail because foo exists, because it was left behind. - - >>> remove('foo') - -Let's fix the recipe: - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... """ - ... import logging, os, zc.buildout - ... - ... class Mkdir: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... - ... # Normalize paths and check that their parent - ... # directories exist: - ... paths = [] - ... for path in options['path'].split(): - ... path = os.path.join(buildout['buildout']['directory'], path) - ... if not os.path.isdir(os.path.dirname(path)): - ... logging.getLogger(self.name).error( - ... 'Cannot create %s. %s is not a directory.', - ... options['path'], os.path.dirname(options['path'])) - ... raise zc.buildout.UserError('Invalid Path') - ... paths.append(path) - ... options['path'] = ' '.join(paths) - ... - ... def install(self): - ... paths = self.options['path'].split() - ... created = [] - ... try: - ... for path in paths: - ... logging.getLogger(self.name).info( - ... 'Creating directory %s', os.path.basename(path)) - ... os.mkdir(path) - ... created.append(path) - ... except: - ... for d in created: - ... os.rmdir(d) - ... raise - ... - ... return paths - ... - ... def update(self): - ... pass - ... """) - -And put back the typo: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = foo bin - ... """) - -When we rerun the buildout: - - >>> print system(buildout), # doctest: +ELLIPSIS - Develop: '/sample-buildout/recipes' - Installing data-dir. - data-dir: Creating directory foo - data-dir: Creating directory bin - While: - Installing data-dir. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - OSError: [Errno 17] File exists: '/sample-buildout/bin' - -.. Wait for the file to really disappear. My linux is weird. - - >>> wait_until("foo goes away", lambda : not os.path.exists('foo'), - ... timeout=200) - -we get the same error, but we don't get the directory left behind: - - >>> os.path.exists('foo') - False - -It's critical that recipes clean up partial effects when errors -occur. Because recipes most commonly create files and directories, -buildout provides a helper API for removing created files when an -error occurs. Option objects have a created method that can be called -to record files as they are created. If the install or update method -returns with an error, then any registered paths are removed -automatically. The method returns the files registered and can be -used to return the files created. Let's use this API to simplify the -recipe: - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... """ - ... import logging, os, zc.buildout - ... - ... class Mkdir: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... - ... # Normalize paths and check that their parent - ... # directories exist: - ... paths = [] - ... for path in options['path'].split(): - ... path = os.path.join(buildout['buildout']['directory'], path) - ... if not os.path.isdir(os.path.dirname(path)): - ... logging.getLogger(self.name).error( - ... 'Cannot create %s. %s is not a directory.', - ... options['path'], os.path.dirname(options['path'])) - ... raise zc.buildout.UserError('Invalid Path') - ... paths.append(path) - ... options['path'] = ' '.join(paths) - ... - ... def install(self): - ... paths = self.options['path'].split() - ... for path in paths: - ... logging.getLogger(self.name).info( - ... 'Creating directory %s', os.path.basename(path)) - ... os.mkdir(path) - ... self.options.created(path) - ... - ... return self.options.created() - ... - ... def update(self): - ... pass - ... """) - -.. - - >>> remove(sample_buildout, 'recipes', 'mkdir.pyc') - -We returned by calling created, taking advantage of the fact that it -returns the registered paths. We did this for illustrative purposes. -It would be simpler just to return the paths as before. - -If we rerun the buildout, again, we'll get the error and no -directories will be created: - - >>> print system(buildout), # doctest: +ELLIPSIS - Develop: '/sample-buildout/recipes' - Installing data-dir. - data-dir: Creating directory foo - data-dir: Creating directory bin - While: - Installing data-dir. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - OSError: [Errno 17] File exists: '/sample-buildout/bin' - - >>> os.path.exists('foo') - False - -Now, we'll fix the typo again and we'll get the directories we expect: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = foo bins - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing data-dir. - data-dir: Creating directory foo - data-dir: Creating directory bins - - >>> os.path.exists('foo') - True - >>> os.path.exists('bins') - True - -Configuration file syntax -------------------------- - -As mentioned earlier, buildout configuration files use the format -defined by the Python ConfigParser module with extensions. The -extensions are: - -- option names are case sensitive - -- option values can use a substitution syntax, described below, to - refer to option values in specific sections. - -- option values can be appended or removed using the - and + - operators. - -The ConfigParser syntax is very flexible. Section names can contain -any characters other than newlines and right square braces ("]"). -Option names can contain any characters other than newlines, colons, -and equal signs, can not start with a space, and don't include -trailing spaces. - -It is likely that, in the future, some characters will be given -special buildout-defined meanings. This is already true of the -characters ":", "$", "%", "(", and ")". For now, it is a good idea to -keep section and option names simple, sticking to alphanumeric -characters, hyphens, and periods. - -Annotated sections ------------------- - -When used with the `annotate` command, buildout displays annotated sections. -All sections are displayed, sorted alphabetically. For each section, -all key-value pairs are displayed, sorted alphabetically, along with -the origin of the value (file name or COMPUTED_VALUE, DEFAULT_VALUE, -COMMAND_LINE_VALUE). - - >>> print system(buildout+ ' annotate'), - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - <BLANKLINE> - Annotated sections - ================== - <BLANKLINE> - [buildout] - accept-buildout-test-releases= false - DEFAULT_VALUE - allow-hosts= * - DEFAULT_VALUE - allow-picked-versions= true - DEFAULT_VALUE - allowed-eggs-from-site-packages= * - DEFAULT_VALUE - bin-directory= bin - DEFAULT_VALUE - develop= recipes - /sample-buildout/buildout.cfg - develop-eggs-directory= develop-eggs - DEFAULT_VALUE - directory= /sample-buildout - COMPUTED_VALUE - eggs-directory= eggs - DEFAULT_VALUE - exec-sitecustomize= true - DEFAULT_VALUE - executable= ... - DEFAULT_VALUE - find-links= - DEFAULT_VALUE - include-site-packages= true - DEFAULT_VALUE - install-from-cache= false - DEFAULT_VALUE - installed= .installed.cfg - DEFAULT_VALUE - log-format= - DEFAULT_VALUE - log-level= INFO - DEFAULT_VALUE - newest= true - DEFAULT_VALUE - offline= false - DEFAULT_VALUE - parts= data-dir - /sample-buildout/buildout.cfg - parts-directory= parts - DEFAULT_VALUE - prefer-final= false - DEFAULT_VALUE - python= buildout - DEFAULT_VALUE - relative-paths= false - DEFAULT_VALUE - socket-timeout= - DEFAULT_VALUE - unzip= false - DEFAULT_VALUE - use-dependency-links= true - DEFAULT_VALUE - <BLANKLINE> - [data-dir] - path= foo bins - /sample-buildout/buildout.cfg - recipe= recipes:mkdir - /sample-buildout/buildout.cfg - <BLANKLINE> - -Variable substitutions ----------------------- - -Buildout configuration files support variable substitution. -To illustrate this, we'll create an debug recipe to -allow us to see interactions with the buildout: - - >>> write(sample_buildout, 'recipes', 'debug.py', - ... """ - ... class Debug: - ... - ... def __init__(self, buildout, name, options): - ... self.buildout = buildout - ... self.name = name - ... self.options = options - ... - ... def install(self): - ... items = self.options.items() - ... items.sort() - ... for option, value in items: - ... print option, value - ... return () - ... - ... update = install - ... """) - -This recipe doesn't actually create anything. The install method -doesn't return anything, because it didn't create any files or -directories. - -We also have to update our setup script: - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... entry_points = ( - ... ''' - ... [zc.buildout] - ... mkdir = mkdir:Mkdir - ... debug = debug:Debug - ... ''') - ... setup(name="recipes", entry_points=entry_points) - ... """) - -We've rearranged the script a bit to make the entry points easier to -edit. In particular, entry points are now defined as a configuration -string, rather than a dictionary. - -Let's update our configuration to provide variable substitution -examples: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir debug - ... log-level = INFO - ... - ... [debug] - ... recipe = recipes:debug - ... File 1 = ${data-dir:path}/file - ... File 2 = ${debug:File 1}/log - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mydata - ... """) - -We used a string-template substitution for File 1 and File 2. This -type of substitution uses the string.Template syntax. Names -substituted are qualified option names, consisting of a section name -and option name joined by a colon. - -Now, if we run the buildout, we'll see the options with the values -substituted. - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling data-dir. - Installing data-dir. - data-dir: Creating directory mydata - Installing debug. - File 1 /sample-buildout/mydata/file - File 2 /sample-buildout/mydata/file/log - recipe recipes:debug - -Note that the substitution of the data-dir path option reflects the -update to the option performed by the mkdir recipe. - -It might seem surprising that mydata was created again. This is -because we changed our recipes package by adding the debug module. -The buildout system didn't know if this module could effect the mkdir -recipe, so it assumed it could and reinstalled mydata. If we rerun -the buildout: - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Updating data-dir. - Updating debug. - File 1 /sample-buildout/mydata/file - File 2 /sample-buildout/mydata/file/log - recipe recipes:debug - -We can see that mydata was not recreated. - -Note that, in this case, we didn't specify a log level, so -we didn't get output about what the buildout was doing. - -Section and option names in variable substitutions are only allowed to -contain alphanumeric characters, hyphens, periods and spaces. This -restriction might be relaxed in future releases. - -We can ommit the section name in a variable substitution to refer to -the current section. We can also use the special option, -_buildout_section_name_ to get the current section name. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir debug - ... log-level = INFO - ... - ... [debug] - ... recipe = recipes:debug - ... File 1 = ${data-dir:path}/file - ... File 2 = ${:File 1}/log - ... my_name = ${:_buildout_section_name_} - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mydata - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Updating data-dir. - Installing debug. - File 1 /sample-buildout/mydata/file - File 2 /sample-buildout/mydata/file/log - my_name debug - recipe recipes:debug - -Automatic part selection and ordering -------------------------------------- - -When a section with a recipe is referred to, either through variable -substitution or by an initializing recipe, the section is treated as a -part and added to the part list before the referencing part. For -example, we can leave data-dir out of the parts list: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... log-level = INFO - ... - ... [debug] - ... recipe = recipes:debug - ... File 1 = ${data-dir:path}/file - ... File 2 = ${debug:File 1}/log - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mydata - ... """) - - -It will still be treated as a part: - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Updating data-dir. - Installing debug. - File 1 /sample-buildout/mydata/file - File 2 /sample-buildout/mydata/file/log - recipe recipes:debug - - >>> cat('.installed.cfg') # doctest: +ELLIPSIS - [buildout] - installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link - parts = data-dir debug - ... - -Note that the data-dir part is included *before* the debug part, -because the debug part refers to the data-dir part. Even if we list -the data-dir part after the debug part, it will be included before: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug data-dir - ... log-level = INFO - ... - ... [debug] - ... recipe = recipes:debug - ... File 1 = ${data-dir:path}/file - ... File 2 = ${debug:File 1}/log - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mydata - ... """) - - -It will still be treated as a part: - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Updating data-dir. - Updating debug. - File 1 /sample-buildout/mydata/file - File 2 /sample-buildout/mydata/file/log - recipe recipes:debug - - >>> cat('.installed.cfg') # doctest: +ELLIPSIS - [buildout] - installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link - parts = data-dir debug - ... - -Extending sections (macros) ---------------------------- - -A section (other than the buildout section) can extend one or more -other sections using the ``<=`` option. Options from the referenced -sections are copied to the refering section *before* variable -substitution. This, together with the ability to refer to variables -of the current section allows sections to be used as macros. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = myfiles - ... log-level = INFO - ... - ... [debug] - ... recipe = recipes:debug - ... - ... [with_file1] - ... <= debug - ... file1 = ${:path}/file1 - ... color = red - ... - ... [with_file2] - ... <= debug - ... file2 = ${:path}/file2 - ... color = blue - ... - ... [myfiles] - ... <= with_file1 - ... with_file2 - ... path = mydata - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Uninstalling data-dir. - Installing myfiles. - color blue - file1 mydata/file1 - file2 mydata/file2 - path mydata - recipe recipes:debug - -In this example, the debug, with_file1 and with_file2 sections act as -macros. In particular, the variable substitutions are performed -relative to the myfiles section. - -Adding and removing options ---------------------------- - -We can append and remove values to an option by using the + and - -operators. - -This is illustrated below; first we define a base configuration. - - >>> write(sample_buildout, 'base.cfg', - ... """ - ... [buildout] - ... parts = part1 part2 part3 - ... - ... [part1] - ... recipe = - ... option = a1 a2 - ... - ... [part2] - ... recipe = - ... option = b1 b2 b3 b4 - ... - ... [part3] - ... recipe = - ... option = c1 c2 - ... - ... """) - -Extending this configuration, we can "adjust" the values set in the -base configuration file. - - >>> write(sample_buildout, 'extension1.cfg', - ... """ - ... [buildout] - ... extends = base.cfg - ... - ... # appending values - ... [part1] - ... option += a3 a4 - ... - ... # removing values - ... [part2] - ... option -= b1 b2 - ... - ... # alt. spelling - ... [part3] - ... option+=c3 c4 c5 - ... - ... # normal assignment - ... [part4] - ... option = h1 h2 - ... - ... """) - -An additional extension. - - >>> write(sample_buildout, 'extension2.cfg', - ... """ - ... [buildout] - ... extends = extension1.cfg - ... - ... # appending values - ... [part1] - ... option += a5 - ... - ... # removing values - ... [part2] - ... option -= b1 b2 b3 - ... - ... """) - -To verify that the options are adjusted correctly, we'll set up an -extension that prints out the options. - - >>> mkdir(sample_buildout, 'demo') - >>> write(sample_buildout, 'demo', 'demo.py', - ... """ - ... def ext(buildout): - ... print [part['option'] for name, part in buildout.items() \ - ... if name.startswith('part')] - ... """) - - >>> write(sample_buildout, 'demo', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup( - ... name="demo", - ... entry_points={'zc.buildout.extension': ['ext = demo:ext']}, - ... ) - ... """) - -Set up a buildout configuration for this extension. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = demo - ... parts = - ... """) - - >>> os.chdir(sample_buildout) - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/demo' - Uninstalling myfiles. - Getting distribution for 'recipes'. - zip_safe flag not set; analyzing archive contents... - Got recipes 0.0.0. - warning: install_lib: 'build/lib' does not exist -- no Python modules to install - -Verify option values. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = demo - ... extensions = demo - ... extends = extension2.cfg - ... """) - - >>> print system(os.path.join('bin', 'buildout')), - ['a1 a2/na3 a4/na5', 'b1 b2 b3 b4', 'c1 c2/nc3 c4 c5', 'h1 h2'] - Develop: '/sample-buildout/demo' - -Annotated sections output shows which files are responsible for which -operations. - - >>> print system(os.path.join('bin', 'buildout') + ' annotate'), - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - <BLANKLINE> - Annotated sections - ================== - ... - <BLANKLINE> - [part1] - option= a1 a2 - a3 a4 - a5 - /sample-buildout/base.cfg - += /sample-buildout/extension1.cfg - += /sample-buildout/extension2.cfg - recipe= - /sample-buildout/base.cfg - <BLANKLINE> - [part2] - option= b1 b2 b3 b4 - /sample-buildout/base.cfg - -= /sample-buildout/extension1.cfg - -= /sample-buildout/extension2.cfg - recipe= - /sample-buildout/base.cfg - <BLANKLINE> - [part3] - option= c1 c2 - c3 c4 c5 - /sample-buildout/base.cfg - += /sample-buildout/extension1.cfg - recipe= - /sample-buildout/base.cfg - <BLANKLINE> - [part4] - option= h1 h2 - /sample-buildout/extension1.cfg - -Cleanup. - - >>> os.remove(os.path.join(sample_buildout, 'base.cfg')) - >>> os.remove(os.path.join(sample_buildout, 'extension1.cfg')) - >>> os.remove(os.path.join(sample_buildout, 'extension2.cfg')) - -Multiple configuration files ----------------------------- - -A configuration file can "extend" another configuration file. -Options are read from the other configuration file if they aren't -already defined by your configuration file. - -The configuration files your file extends can extend -other configuration files. The same file may be -used more than once although, of course, cycles aren't allowed. - -To see how this works, we use an example: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... extends = base.cfg - ... - ... [debug] - ... op = buildout - ... """) - - >>> write(sample_buildout, 'base.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes:debug - ... op = base - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing debug. - op buildout - recipe recipes:debug - -The example is pretty trivial, but the pattern it illustrates is -pretty common. In a more practical example, the base buildout might -represent a product and the extending buildout might be a -customization. - -Here is a more elaborate example. - - >>> other = tmpdir('other') - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... extends = b1.cfg b2.cfg %(b3)s - ... - ... [debug] - ... op = buildout - ... """ % dict(b3=os.path.join(other, 'b3.cfg'))) - - >>> write(sample_buildout, 'b1.cfg', - ... """ - ... [buildout] - ... extends = base.cfg - ... - ... [debug] - ... op1 = b1 1 - ... op2 = b1 2 - ... """) - - >>> write(sample_buildout, 'b2.cfg', - ... """ - ... [buildout] - ... extends = base.cfg - ... - ... [debug] - ... op2 = b2 2 - ... op3 = b2 3 - ... """) - - >>> write(other, 'b3.cfg', - ... """ - ... [buildout] - ... extends = b3base.cfg - ... - ... [debug] - ... op4 = b3 4 - ... """) - - >>> write(other, 'b3base.cfg', - ... """ - ... [debug] - ... op5 = b3base 5 - ... """) - - >>> write(sample_buildout, 'base.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes:debug - ... name = base - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - name base - op buildout - op1 b1 1 - op2 b2 2 - op3 b2 3 - op4 b3 4 - op5 b3base 5 - recipe recipes:debug - -There are several things to note about this example: - -- We can name multiple files in an extends option. - -- We can reference files recursively. - -- Relative file names in extended options are interpreted relative to - the directory containing the referencing configuration file. - -Loading Configuration from URLs -------------------------------- - -Configuration files can be loaded from URLs. To see how this works, -we'll set up a web server with some configuration files. - - >>> server_data = tmpdir('server_data') - - >>> write(server_data, "r1.cfg", - ... """ - ... [debug] - ... op1 = r1 1 - ... op2 = r1 2 - ... """) - - >>> write(server_data, "r2.cfg", - ... """ - ... [buildout] - ... extends = r1.cfg - ... - ... [debug] - ... op2 = r2 2 - ... op3 = r2 3 - ... """) - - >>> server_url = start_server(server_data) - - >>> write('client.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... extends = %(url)s/r2.cfg - ... - ... [debug] - ... recipe = recipes:debug - ... name = base - ... """ % dict(url=server_url)) - - - >>> print system(buildout+ ' -c client.cfg'), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - name base - op1 r1 1 - op2 r2 2 - op3 r2 3 - recipe recipes:debug - -Here we specified a URL for the file we extended. The file we -downloaded, itself referred to a file on the server using a relative -URL reference. Relative references are interpreted relative to the -base URL when they appear in configuration files loaded via URL. - -We can also specify a URL as the configuration file to be used by a -buildout. - - >>> os.remove('client.cfg') - >>> write(server_data, 'remote.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... extends = r2.cfg - ... - ... [debug] - ... recipe = recipes:debug - ... name = remote - ... """) - - >>> print system(buildout + ' -c ' + server_url + '/remote.cfg'), - While: - Initializing. - Error: Missing option: buildout:directory - -Normally, the buildout directory defaults to directory -containing a configuration file. This won't work for configuration -files loaded from URLs. In this case, the buildout directory would -normally be defined on the command line: - - >>> print system(buildout - ... + ' -c ' + server_url + '/remote.cfg' - ... + ' buildout:directory=' + sample_buildout - ... ), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - name remote - op1 r1 1 - op2 r2 2 - op3 r2 3 - recipe recipes:debug - -User defaults -------------- - -If the file $HOME/.buildout/default.cfg, exists, it is read before -reading the configuration file. ($HOME is the value of the HOME -environment variable. The '/' is replaced by the operating system file -delimiter.) - - >>> old_home = os.environ['HOME'] - >>> home = tmpdir('home') - >>> mkdir(home, '.buildout') - >>> write(home, '.buildout', 'default.cfg', - ... """ - ... [debug] - ... op1 = 1 - ... op7 = 7 - ... """) - - >>> os.environ['HOME'] = home - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - name base - op buildout - op1 b1 1 - op2 b2 2 - op3 b2 3 - op4 b3 4 - op5 b3base 5 - op7 7 - recipe recipes:debug - -A buildout command-line argument, -U, can be used to suppress reading -user defaults: - - >>> print system(buildout + ' -U'), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - name base - op buildout - op1 b1 1 - op2 b2 2 - op3 b2 3 - op4 b3 4 - op5 b3base 5 - recipe recipes:debug - - >>> os.environ['HOME'] = old_home - -Log level ---------- - -We can control the level of logging by specifying a log level in out -configuration file. For example, so suppress info messages, we can -set the logging level to WARNING - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... log-level = WARNING - ... extends = b1.cfg b2.cfg - ... """) - - >>> print system(buildout), - name base - op1 b1 1 - op2 b2 2 - op3 b2 3 - recipe recipes:debug - -Uninstall recipes ------------------ - -As we've seen, when parts are installed, buildout keeps track of files -and directories that they create. When the parts are uninstalled these -files and directories are deleted. - -Sometimes more clean up is needed. For example, a recipe might add a -system service by calling chkconfig --add during installation. Later -during uninstallation, chkconfig --del will need to be called to -remove the system service. - -In order to deal with these uninstallation issues, you can register -uninstall recipes. Uninstall recipes are registered using the -'zc.buildout.uninstall' entry point. Parts specify uninstall recipes -using the 'uninstall' option. - -In comparison to regular recipes, uninstall recipes are much -simpler. They are simply callable objects that accept the name of the -part to be uninstalled and the part's options dictionary. Uninstall -recipes don't have access to the part itself since it maybe not be -able to be instantiated at uninstallation time. - -Here's a recipe that simulates installation of a system service, along -with an uninstall recipe that simulates removing the service. - - >>> write(sample_buildout, 'recipes', 'service.py', - ... """ - ... class Service: - ... - ... def __init__(self, buildout, name, options): - ... self.buildout = buildout - ... self.name = name - ... self.options = options - ... - ... def install(self): - ... print "chkconfig --add %s" % self.options['script'] - ... return () - ... - ... def update(self): - ... pass - ... - ... - ... def uninstall_service(name, options): - ... print "chkconfig --del %s" % options['script'] - ... """) - -To use these recipes we must register them using entry points. Make -sure to use the same name for the recipe and uninstall recipe. This is -required to let buildout know which uninstall recipe goes with which -recipe. - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... entry_points = ( - ... ''' - ... [zc.buildout] - ... mkdir = mkdir:Mkdir - ... debug = debug:Debug - ... service = service:Service - ... - ... [zc.buildout.uninstall] - ... service = service:uninstall_service - ... ''') - ... setup(name="recipes", entry_points=entry_points) - ... """) - -Here's how these recipes could be used in a buildout: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = service - ... - ... [service] - ... recipe = recipes:service - ... script = /path/to/script - ... """) - -When the buildout is run the service will be installed - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing service. - chkconfig --add /path/to/script - <BLANKLINE> - -The service has been installed. If the buildout is run again with no -changes, the service shouldn't be changed. - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Updating service. - <BLANKLINE> - -Now we change the service part to trigger uninstallation and -re-installation. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = service - ... - ... [service] - ... recipe = recipes:service - ... script = /path/to/a/different/script - ... """) - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Uninstalling service. - Running uninstall recipe. - chkconfig --del /path/to/script - Installing service. - chkconfig --add /path/to/a/different/script - <BLANKLINE> - -Now we remove the service part, and add another part. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes:debug - ... """) - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Uninstalling service. - Running uninstall recipe. - chkconfig --del /path/to/a/different/script - Installing debug. - recipe recipes:debug - <BLANKLINE> - -Uninstall recipes don't have to take care of removing all the files -and directories created by the part. This is still done automatically, -following the execution of the uninstall recipe. An upshot is that an -uninstallation recipe can access files and directories created by a -recipe before they are deleted. - -For example, here's an uninstallation recipe that simulates backing up -a directory before it is deleted. It is designed to work with the -mkdir recipe introduced earlier. - - >>> write(sample_buildout, 'recipes', 'backup.py', - ... """ - ... import os - ... def backup_directory(name, options): - ... path = options['path'] - ... size = len(os.listdir(path)) - ... print "backing up directory %s of size %s" % (path, size) - ... """) - -It must be registered with the zc.buildout.uninstall entry -point. Notice how it is given the name 'mkdir' to associate it with -the mkdir recipe. - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... entry_points = ( - ... ''' - ... [zc.buildout] - ... mkdir = mkdir:Mkdir - ... debug = debug:Debug - ... service = service:Service - ... - ... [zc.buildout.uninstall] - ... uninstall_service = service:uninstall_service - ... mkdir = backup:backup_directory - ... ''') - ... setup(name="recipes", entry_points=entry_points) - ... """) - -Now we can use it with a mkdir part. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = dir debug - ... - ... [dir] - ... recipe = recipes:mkdir - ... path = my_directory - ... - ... [debug] - ... recipe = recipes:debug - ... """) - -Run the buildout to install the part. - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing dir. - dir: Creating directory my_directory - Installing debug. - recipe recipes:debug - <BLANKLINE> - -Now we remove the part from the configuration file. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes:debug - ... """) - -When the buildout is run the part is removed, and the uninstall recipe -is run before the directory is deleted. - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Uninstalling dir. - Running uninstall recipe. - backing up directory /sample-buildout/my_directory of size 0 - Updating debug. - recipe recipes:debug - <BLANKLINE> - -Now we will return the registration to normal for the benefit of the -rest of the examples. - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... entry_points = ( - ... ''' - ... [zc.buildout] - ... mkdir = mkdir:Mkdir - ... debug = debug:Debug - ... ''') - ... setup(name="recipes", entry_points=entry_points) - ... """) - - -Command-line usage ------------------- - -A number of arguments can be given on the buildout command line. The -command usage is:: - - buildout [options and assignments] [command [command arguments]] - -The following options are supported: - --h (or --help) - Print basic usage information. If this option is used, then all - other options are ignored. - --c filename - The -c option can be used to specify a configuration file, rather than - buildout.cfg in the current directory. - - --t socket_timeout - - Specify the socket timeout in seconds. - --v - Increment the verbosity by 10. The verbosity is used to adjust - the logging level. The verbosity is subtracted from the numeric - value of the log-level option specified in the configuration file. - --q - Decrement the verbosity by 10. - --U - Don't read user-default configuration. - --o - Run in off-line mode. This is equivalent to the assignment - buildout:offline=true. - --O - Run in non-off-line mode. This is equivalent to the assignment - buildout:offline=false. This is the default buildout mode. The - -O option would normally be used to override a true offline - setting in a configuration file. - --n - Run in newest mode. This is equivalent to the assignment - buildout:newest=true. With this setting, which is the default, - buildout will try to find the newest versions of distributions - available that satisfy its requirements. - --N - Run in non-newest mode. This is equivalent to the assignment - buildout:newest=false. With this setting, buildout will not seek - new distributions if installed distributions satisfy it's - requirements. - -Assignments are of the form:: - - section_name:option_name=value - -Options and assignments can be given in any order. - -Here's an example: - - >>> write(sample_buildout, 'other.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... installed = .other.cfg - ... log-level = WARNING - ... - ... [debug] - ... name = other - ... recipe = recipes:debug - ... """) - -Note that we used the installed buildout option to specify an -alternate file to store information about installed parts. - - >>> print system(buildout+' -c other.cfg debug:op1=foo -v'), - Develop: '/sample-buildout/recipes' - Installing debug. - name other - op1 foo - recipe recipes:debug - -Here we used the -c option to specify an alternate configuration file, -and the -v option to increase the level of logging from the default, -WARNING. - -Options can also be combined in the usual Unix way, as in: - - >>> print system(buildout+' -vcother.cfg debug:op1=foo'), - Develop: '/sample-buildout/recipes' - Updating debug. - name other - op1 foo - recipe recipes:debug - -Here we combined the -v and -c options with the configuration file -name. Note that the -c option has to be last, because it takes an -argument. - - >>> os.remove(os.path.join(sample_buildout, 'other.cfg')) - >>> os.remove(os.path.join(sample_buildout, '.other.cfg')) - -The most commonly used command is 'install' and it takes a list of -parts to install. if any parts are specified, only those parts are -installed. To illustrate this, we'll update our configuration and run -the buildout in the usual way: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug d1 d2 d3 - ... - ... [d1] - ... recipe = recipes:mkdir - ... path = d1 - ... - ... [d2] - ... recipe = recipes:mkdir - ... path = d2 - ... - ... [d3] - ... recipe = recipes:mkdir - ... path = d3 - ... - ... [debug] - ... recipe = recipes:debug - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling debug. - Installing debug. - recipe recipes:debug - Installing d1. - d1: Creating directory d1 - Installing d2. - d2: Creating directory d2 - Installing d3. - d3: Creating directory d3 - - >>> ls(sample_buildout) - - .installed.cfg - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d d1 - d d2 - d d3 - d demo - d develop-eggs - d eggs - d parts - d recipes - - >>> cat(sample_buildout, '.installed.cfg') - ... # doctest: +NORMALIZE_WHITESPACE - [buildout] - installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link - parts = debug d1 d2 d3 - <BLANKLINE> - [debug] - __buildout_installed__ = - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - recipe = recipes:debug - <BLANKLINE> - [d1] - __buildout_installed__ = /sample-buildout/d1 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/d1 - recipe = recipes:mkdir - <BLANKLINE> - [d2] - __buildout_installed__ = /sample-buildout/d2 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/d2 - recipe = recipes:mkdir - <BLANKLINE> - [d3] - __buildout_installed__ = /sample-buildout/d3 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/d3 - recipe = recipes:mkdir - -Now we'll update our configuration file: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug d2 d3 d4 - ... - ... [d2] - ... recipe = recipes:mkdir - ... path = data2 - ... - ... [d3] - ... recipe = recipes:mkdir - ... path = data3 - ... - ... [d4] - ... recipe = recipes:mkdir - ... path = ${d2:path}-extra - ... - ... [debug] - ... recipe = recipes:debug - ... x = 1 - ... """) - -and run the buildout specifying just d3 and d4: - - >>> print system(buildout+' install d3 d4'), - Develop: '/sample-buildout/recipes' - Uninstalling d3. - Installing d3. - d3: Creating directory data3 - Installing d4. - d4: Creating directory data2-extra - - >>> ls(sample_buildout) - - .installed.cfg - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d d1 - d d2 - d data2-extra - d data3 - d demo - d develop-eggs - d eggs - d parts - d recipes - -Only the d3 and d4 recipes ran. d3 was removed and data3 and data2-extra -were created. - -The .installed.cfg is only updated for the recipes that ran: - - >>> cat(sample_buildout, '.installed.cfg') - ... # doctest: +NORMALIZE_WHITESPACE - [buildout] - installed_develop_eggs = /sample-buildout/develop-eggs/recipes.egg-link - parts = debug d1 d2 d3 d4 - <BLANKLINE> - [debug] - __buildout_installed__ = - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - recipe = recipes:debug - <BLANKLINE> - [d1] - __buildout_installed__ = /sample-buildout/d1 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/d1 - recipe = recipes:mkdir - <BLANKLINE> - [d2] - __buildout_installed__ = /sample-buildout/d2 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/d2 - recipe = recipes:mkdir - <BLANKLINE> - [d3] - __buildout_installed__ = /sample-buildout/data3 - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/data3 - recipe = recipes:mkdir - <BLANKLINE> - [d4] - __buildout_installed__ = /sample-buildout/data2-extra - __buildout_signature__ = recipes-PiIFiO8ny5yNZ1S3JfT0xg== - path = /sample-buildout/data2-extra - recipe = recipes:mkdir - -Note that the installed data for debug, d1, and d2 haven't changed, -because we didn't install those parts and that the d1 and d2 -directories are still there. - -Now, if we run the buildout without the install command: - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling d2. - Uninstalling d1. - Uninstalling debug. - Installing debug. - recipe recipes:debug - x 1 - Installing d2. - d2: Creating directory data2 - Updating d3. - Updating d4. - -We see the output of the debug recipe and that data2 was created. We -also see that d1 and d2 have gone away: - - >>> ls(sample_buildout) - - .installed.cfg - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d data2 - d data2-extra - d data3 - d demo - d develop-eggs - d eggs - d parts - d recipes - -Alternate directory and file locations --------------------------------------- - -The buildout normally puts the bin, eggs, and parts directories in the -directory in the directory containing the configuration file. You can -provide alternate locations, and even names for these directories. - - >>> alt = tmpdir('sample-alt') - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = - ... develop-eggs-directory = %(developbasket)s - ... eggs-directory = %(basket)s - ... bin-directory = %(scripts)s - ... parts-directory = %(work)s - ... """ % dict( - ... developbasket = os.path.join(alt, 'developbasket'), - ... basket = os.path.join(alt, 'basket'), - ... scripts = os.path.join(alt, 'scripts'), - ... work = os.path.join(alt, 'work'), - ... )) - - >>> print system(buildout), - Creating directory '/sample-alt/scripts'. - Creating directory '/sample-alt/work'. - Creating directory '/sample-alt/basket'. - Creating directory '/sample-alt/developbasket'. - Develop: '/sample-buildout/recipes' - Uninstalling d4. - Uninstalling d3. - Uninstalling d2. - Uninstalling debug. - - >>> ls(alt) - d basket - d developbasket - d scripts - d work - - >>> ls(alt, 'developbasket') - - recipes.egg-link - -You can also specify an alternate buildout directory: - - >>> rmdir(alt) - >>> alt = tmpdir('sample-alt') - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... directory = %(alt)s - ... develop = %(recipes)s - ... parts = - ... """ % dict( - ... alt=alt, - ... recipes=os.path.join(sample_buildout, 'recipes'), - ... )) - - >>> print system(buildout), - Creating directory '/sample-alt/bin'. - Creating directory '/sample-alt/parts'. - Creating directory '/sample-alt/eggs'. - Creating directory '/sample-alt/develop-eggs'. - Develop: '/sample-buildout/recipes' - - >>> ls(alt) - - .installed.cfg - d bin - d develop-eggs - d eggs - d parts - - >>> ls(alt, 'develop-eggs') - - recipes.egg-link - -Logging control ---------------- - -Three buildout options are used to control logging: - -log-level - specifies the log level - -verbosity - adjusts the log level - -log-format - allows an alternate logging for mat to be specified - -We've already seen the log level and verbosity. Let's look at an example -of changing the format: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = - ... log-level = 25 - ... verbosity = 5 - ... log-format = %(levelname)s %(message)s - ... """) - -Here, we've changed the format to include the log-level name, rather -than the logger name. - -We've also illustrated, with a contrived example, that the log level -can be a numeric value and that the verbosity can be specified in the -configuration file. Because the verbosity is subtracted from the log -level, we get a final log level of 20, which is the INFO level. - - >>> print system(buildout), - INFO Develop: '/sample-buildout/recipes' - -Predefined buildout options ---------------------------- - -Buildouts have a number of predefined options that recipes can use -and that users can override in their configuration files. To see -these, we'll run a minimal buildout configuration with a debug logging -level. One of the features of debug logging is that the configuration -database is shown. - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... parts = - ... """) - - >>> print system(buildout+' -vv'), # doctest: +NORMALIZE_WHITESPACE - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout X.X. - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = V.V - <BLANKLINE> - Configuration data: - [buildout] - accept-buildout-test-releases = false - allow-hosts = * - allow-picked-versions = true - allowed-eggs-from-site-packages = * - bin-directory = /sample-buildout/bin - develop-eggs-directory = /sample-buildout/develop-eggs - directory = /sample-buildout - eggs-directory = /sample-buildout/eggs - exec-sitecustomize = true - executable = python - find-links = - include-site-packages = true - install-from-cache = false - installed = /sample-buildout/.installed.cfg - log-format = - log-level = INFO - newest = true - offline = false - parts = - parts-directory = /sample-buildout/parts - prefer-final = false - python = buildout - relative-paths = false - socket-timeout = - unzip = false - use-dependency-links = true - verbosity = 20 - <BLANKLINE> - -All of these options can be overridden by configuration files or by -command-line assignments. We've discussed most of these options -already, but let's review them and touch on some we haven't discussed: - -allowed-eggs-from-site-packages - Sometimes you need or want to control what eggs from site-packages are - used. The allowed-eggs-from-site-packages option allows you to specify a - whitelist of project names that may be included from site-packages. You - can use globs to specify the value. It defaults to a single value of '*', - indicating that any package may come from site-packages. - - Here's a usage example:: - - [buildout] - ... - - allowed-eggs-from-site-packages = - demo - bigdemo - zope.* - - This option interacts with the ``include-site-packages`` option in the - following ways. - - If ``include-site-packages`` is true, then - ``allowed-eggs-from-site-packages`` filters what eggs from site-packages - may be chosen. Therefore, if ``allowed-eggs-from-site-packages`` is an - empty list, then no eggs from site-packages are chosen, but site-packages - will still be included at the end of path lists. - - If ``include-site-packages`` is false, the value of - ``allowed-eggs-from-site-packages`` is irrelevant. - - See the ``include-site-packages`` description for more information. - -bin-directory - The directory path where scripts are written. This can be a - relative path, which is interpreted relative to the directory - option. - -develop-eggs-directory - The directory path where development egg links are created for software - being created in the local project. This can be a relative path, - which is interpreted relative to the directory option. - -directory - The buildout directory. This is the base for other buildout file - and directory locations, when relative locations are used. - -eggs-directory - The directory path where downloaded eggs are put. It is common to share - this directory across buildouts. Eggs in this directory should - *never* be modified. This can be a relative path, which is - interpreted relative to the directory option. - -exec-sitecustomize - Normally the Python's real sitecustomize module is processed. - If you do not want it to be processed in order to increase the - repeatability of your buildout, set this value to 'false'. This will - be honored irrespective of the setting for include-site-packages. - This option will be honored by some recipes and not others. - z3c.recipe.scripts honors this and zc.recipe.egg does not, for - instance. - -executable - The Python executable used to run the buildout. See the python - option below. - -include-site-packages - You can choose not to have the site-packages of the underlying Python - available to your script or interpreter, in addition to the packages - from your eggs. This can increase repeatability for your buildout. - This option will be better used by some recipes than others. - z3c.recipe.scripts honors this fully and zc.recipe.egg only - partially, for instance. - -installed - The file path where information about the results of the previous - buildout run is written. This can be a relative path, which is - interpreted relative to the directory option. This file provides - an inventory of installed parts with information needed to decide - which if any parts need to be uninstalled. - -log-format - The format used for logging messages. - -log-level - The log level before verbosity adjustment - -parts - A white space separated list of parts to be installed. - -parts-directory - A working directory that parts can used to store data. - -python - The name of a section containing information about the default - Python interpreter. Recipes that need a installation - typically have options to tell them which Python installation to - use. By convention, if a section-specific option isn't used, the - option is looked for in the buildout section. The option must - point to a section with an executable option giving the path to a - Python executable. By default, the buildout section defines the - default Python as the Python used to run the buildout. - -relative-paths - The paths generated by zc.buildout are absolute by default, and this - option is ``false``. However, if you set this value to be ``true``, - bin/buildout will be generated with code that makes the paths relative. - Some recipes, such as zc.recipe.egg and z3c.recipe.scripts, honor this - value as well. - -unzip - By default, zc.buildout doesn't unzip zip-safe eggs ("unzip = false"). - This follows the policy followed by setuptools itself. Experience shows - this policy to to be inconvenient. Zipped eggs make debugging more - difficult and often import more slowly. You can include an unzip option in - the buildout section to change the default unzipping policy ("unzip = - true"). - -use-dependency-links - By default buildout will obey the setuptools dependency_links metadata - when it looks for dependencies. This behavior can be controlled with - the use-dependency-links buildout option:: - - [buildout] - ... - use-dependency-links = false - - The option defaults to true. If you set it to false, then dependency - links are only looked for in the locations specified by find-links. - -verbosity - A log-level adjustment. Typically, this is set via the -q and -v - command-line options. - - -Creating new buildouts and bootstrapping ----------------------------------------- - -If zc.buildout is installed, you can use it to create a new buildout -with it's own local copies of zc.buildout and setuptools and with -local buildout scripts. - - >>> sample_bootstrapped = tmpdir('sample-bootstrapped') - - >>> print system(buildout - ... +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg') - ... +' init'), - Creating '/sample-bootstrapped/setup.cfg'. - Creating directory '/sample-bootstrapped/bin'. - Creating directory '/sample-bootstrapped/parts'. - Creating directory '/sample-bootstrapped/eggs'. - Creating directory '/sample-bootstrapped/develop-eggs'. - Generated script '/sample-bootstrapped/bin/buildout'. - -Note that a basic setup.cfg was created for us. - - >>> ls(sample_bootstrapped) - d bin - d develop-eggs - d eggs - d parts - - setup.cfg - - >>> ls(sample_bootstrapped, 'bin') - - buildout - - >>> _ = (ls(sample_bootstrapped, 'eggs'), - ... ls(sample_bootstrapped, 'develop-eggs')) - - setuptools-0.6-py2.3.egg - - zc.buildout-1.0-py2.3.egg - -(We list both the eggs and develop-eggs directories because the -buildout or setuptools egg could be installed in the develop-eggs -directory if the original buildout had develop eggs for either -buildout or setuptools.) - -If relative-paths is ``true``, the buildout script uses relative paths. - - >>> write(sample_bootstrapped, 'setup.cfg', - ... ''' - ... [buildout] - ... relative-paths = true - ... parts = - ... ''') - - >>> print system(buildout - ... +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg') - ... +' bootstrap'), - Generated script '/sample-bootstrapped/bin/buildout'. - - >>> buildout_script = join(sample_bootstrapped, 'bin', 'buildout') - >>> import sys - >>> if sys.platform.startswith('win'): - ... buildout_script += '-script.py' - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #!... -S - <BLANKLINE> - import os - <BLANKLINE> - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - <BLANKLINE> - import sys - sys.path[0:0] = [ - join(base, 'parts/buildout'), - ] - <BLANKLINE> - <BLANKLINE> - import os - path = sys.path[0] - if os.environ.get('PYTHONPATH'): - path = os.pathsep.join([path, os.environ['PYTHONPATH']]) - os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '') - os.environ['PYTHONPATH'] = path - import site # imports custom buildout-generated site.py - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - <BLANKLINE> - - -Note that, in the above two examples, the buildout script was installed -but not run. To run the buildout, we'd have to run the installed -buildout script. - -If we have an existing buildout that already has a buildout.cfg, we'll -normally use the bootstrap command instead of init. It will complain -if there isn't a configuration file: - - >>> sample_bootstrapped2 = tmpdir('sample-bootstrapped2') - - >>> print system(buildout - ... +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg') - ... +' bootstrap'), - While: - Initializing. - Error: Couldn't open /sample-bootstrapped2/setup.cfg - - >>> write(sample_bootstrapped2, 'setup.cfg', - ... """ - ... [buildout] - ... parts = - ... """) - - >>> print system(buildout - ... +' -c'+os.path.join(sample_bootstrapped2, 'setup.cfg') - ... +' bootstrap'), - Creating directory '/sample-bootstrapped2/bin'. - Creating directory '/sample-bootstrapped2/parts'. - Creating directory '/sample-bootstrapped2/eggs'. - Creating directory '/sample-bootstrapped2/develop-eggs'. - Generated script '/sample-bootstrapped2/bin/buildout'. - - -Newest and Offline Modes ------------------------- - -By default buildout and recipes will try to find the newest versions -of distributions needed to satisfy requirements. This can be very -time consuming, especially when incrementally working on setting up a -buildout or working on a recipe. The buildout newest option can be -used to to suppress this. If the newest option is set to false, then -new distributions won't be sought if an installed distribution meets -requirements. The newest option can be set to false using the -N -command-line option. - -The offline option goes a bit further. If the buildout offline option -is given a value of "true", the buildout and recipes that are aware of -the option will avoid doing network access. This is handy when -running the buildout when not connected to the internet. It also -makes buildouts run much faster. This option is typically set using -the buildout -o option. - -Preferring Final Releases -------------------------- - -Currently, when searching for new releases of your project's -dependencies, the newest available release is used. This isn't usually -ideal, as you may get a development release or alpha releases not ready -to be widely used. You can request that final releases be preferred -using the ``prefer-final`` option in the buildout section:: - - [buildout] - ... - prefer-final = true - -When the ``prefer-final`` option is set to true, then when searching for -new releases, final releases are preferred. If there are final -releases that satisfy distribution requirements, then those releases -are used even if newer non-final releases are available. - -In buildout version 2, all final releases will be preferred by -default--that is ``prefer-final`` will also default to 'true'. You will -then need to use a 'false' value for ``prefer-final`` to get the newest -releases. - -A separate option controls the behavior of the build system itself. -When buildout looks for recipes, extensions, and for updates to itself, -it does prefer final releases by default, as of the 1.5.0 release. The -``accept-buildout-test-releases`` option will let you override this behavior. -However, it is typically changed by the --accept-buildout-test-releases -option to the bootstrap script, since bootstrapping is the first step to -selecting a buildout. - -Finding distributions ---------------------- - -By default, buildout searches the Python Package Index when looking -for distributions. You can, instead, specify your own index to search -using the `index` option:: - - [buildout] - ... - index = http://index.example.com/ - -This index, or the default of http://pypi.python.org/simple/ if no -index is specified, will always be searched for distributions unless -running buildout with options that prevent searching for -distributions. The latest version of the distribution that meets the -requirements of the buildout will always be used. - -You can also specify more locations to search for distributions using -the `find-links` option. All locations specified will be searched for -distributions along with the package index as described before. - -Locations can be urls:: - - [buildout] - ... - find-links = http://download.zope.org/distribution/ - -They can also be directories on disk:: - - [buildout] - ... - find-links = /some/path - -Finally, they can also be direct paths to distributions:: - - [buildout] - ... - find-links = /some/path/someegg-1.0.0-py2.3.egg - -Any number of locations can be specified in the `find-links` option:: - - [buildout] - ... - find-links = - http://download.zope.org/distribution/ - /some/otherpath - /some/path/someegg-1.0.0-py2.3.egg - -Dependency links ----------------- - -By default buildout will obey the setuptools dependency_links metadata -when it looks for dependencies. This behavior can be controlled with -the use-dependency-links buildout option:: - - [buildout] - ... - use-dependency-links = false - -The option defaults to true. If you set it to false, then dependency -links are only looked for in the locations specified by find-links. - -Controlling the installation database -------------------------------------- - -The buildout installed option is used to specify the file used to save -information on installed parts. This option is initialized to -".installed.cfg", but it can be overridden in the configuration file -or on the command line: - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes:debug - ... """) - - >>> print system(buildout+' buildout:installed=inst.cfg'), - Develop: '/sample-buildout/recipes' - Installing debug. - recipe recipes:debug - - >>> ls(sample_buildout) - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d demo - d develop-eggs - d eggs - - inst.cfg - d parts - d recipes - -The installation database can be disabled by supplying an empty -buildout installed option: - - >>> os.remove('inst.cfg') - >>> print system(buildout+' buildout:installed='), - Develop: '/sample-buildout/recipes' - Installing debug. - recipe recipes:debug - - >>> ls(sample_buildout) - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d demo - d develop-eggs - d eggs - d parts - d recipes - - -Note that there will be no installation database if there are no parts: - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... parts = - ... """) - - >>> print system(buildout+' buildout:installed=inst.cfg'), - - >>> ls(sample_buildout) - - b1.cfg - - b2.cfg - - base.cfg - d bin - - buildout.cfg - d demo - d develop-eggs - d eggs - d parts - d recipes - -Extensions ----------- - -A feature allows code to be loaded and run after -configuration files have been read but before the buildout has begun -any processing. The intent is to allow special plugins such as -urllib2 request handlers to be loaded. - -To load an extension, we use the extensions option and list one or -more distribution requirements, on separate lines. The distributions -named will be loaded and any ``zc.buildout.extension`` entry points found -will be called with the buildout as an argument. When buildout -finishes processing, any ``zc.buildout.unloadextension`` entry points -found will be called with the buildout as an argument. - -Let's create a sample extension in our sample buildout created in the -previous section: - - >>> mkdir(sample_bootstrapped, 'demo') - - >>> write(sample_bootstrapped, 'demo', 'demo.py', - ... """ - ... def ext(buildout): - ... print 'ext', list(buildout) - ... def unload(buildout): - ... print 'unload', list(buildout) - ... """) - - >>> write(sample_bootstrapped, 'demo', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup( - ... name = "demo", - ... entry_points = { - ... 'zc.buildout.extension': ['ext = demo:ext'], - ... 'zc.buildout.unloadextension': ['ext = demo:unload'], - ... }, - ... ) - ... """) - -Our extension just prints out the word 'demo', and lists the sections -found in the buildout passed to it. - -We'll update our buildout.cfg to list the demo directory as a develop -egg to be built: - - >>> write(sample_bootstrapped, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = demo - ... parts = - ... """) - - >>> os.chdir(sample_bootstrapped) - >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')), - Develop: '/sample-bootstrapped/demo' - -Now we can add the extensions option. We were a bit tricky and ran -the buildout once with the demo develop egg defined but without the -extension option. This is because extensions are loaded before the -buildout creates develop eggs. We needed to use a separate buildout -run to create the develop egg. Normally, when eggs are loaded from -the network, we wouldn't need to do anything special. - - >>> write(sample_bootstrapped, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = demo - ... extensions = demo - ... parts = - ... """) - -We see that our extension is loaded and executed: - - >>> print system(os.path.join(sample_bootstrapped, 'bin', 'buildout')), - ext ['buildout'] - Develop: '/sample-bootstrapped/demo' - unload ['buildout'] - -Allow hosts ------------ - -On some environments the links visited by `zc.buildout` can be forbidden -by paranoiac firewalls. These URL might be on the chain of links -visited by `zc.buildout` wheter they are defined in the `find-links` option, -wheter they are defined by various eggs in their `url`, `download_url`, -`dependency_links` metadata. - -It is even harder to track that package_index works like a spider and -might visit links and go to other location. - -The `allow-hosts` option provides a way to prevent this, and -works exactly like the one provided in `easy_install`. - -You can provide a list of allowed host, together with wildcards:: - - [buildout] - ... - - allow-hosts = - *.python.org - example.com - -All urls that does not match these hosts will not be visited. - -.. [#future_recipe_methods] In the future, additional methods may be - added. Older recipes with fewer methods will still be - supported. - -.. [#packaging_info] If we wanted to create a distribution from this - package, we would need specify much more information. See the - `setuptools documentation - <http://peak.telecommunity.com/DevCenter/setuptools>`_. diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/debugging.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/debugging.txt deleted file mode 100644 index 1a421a0..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/debugging.txt +++ /dev/null @@ -1,97 +0,0 @@ -Debugging buildouts -=================== - -Buildouts can be pretty complex. When things go wrong, it isn't -always obvious why. Errors can occur due to problems in user input or -due to bugs in zc.buildout or recipes. When an error occurs, Python's -post-mortem debugger can be used to inspect the state of the buildout -or recipe code where the error occurred. To enable this, use the -D -option to the buildout. Let's create a recipe that has a bug: - - >>> mkdir(sample_buildout, 'recipes') - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... """ - ... import os, zc.buildout - ... - ... class Mkdir: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... options['path'] = os.path.join( - ... buildout['buildout']['directory'], - ... options['path'], - ... ) - ... - ... def install(self): - ... directory = self.options['directory'] - ... os.mkdir(directory) - ... return directory - ... - ... def update(self): - ... pass - ... """) - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup(name = "recipes", - ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']}, - ... ) - ... """) - -And create a buildout that uses it: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... path = mystuff - ... """) - -If we run the buildout, we'll get an error: - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing data-dir. - While: - Installing data-dir. - Error: Missing option: data-dir:directory - - -If we want to debug the error, we can add the -D option. Here's we'll -supply some input: - - >>> print system(buildout+" -D", """\ - ... up - ... p self.options.keys() - ... q - ... """), - Develop: '/sample-buildout/recipes' - Installing data-dir. - > /zc/buildout/buildout.py(925)__getitem__() - -> raise MissingOption("Missing option: %s:%s" % (self.name, key)) - (Pdb) > /sample-buildout/recipes/mkdir.py(14)install() - -> directory = self.options['directory'] - (Pdb) ['path', 'recipe'] - (Pdb) While: - Installing data-dir. - Traceback (most recent call last): - File "/zc/buildout/buildout.py", line 1352, in main - getattr(buildout, command)(args) - File "/zc/buildout/buildout.py", line 383, in install - installed_files = self[part]._call(recipe.install) - File "/zc/buildout/buildout.py", line 961, in _call - return f() - File "/sample-buildout/recipes/mkdir.py", line 14, in install - directory = self.options['directory'] - File "/zc/buildout/buildout.py", line 925, in __getitem__ - raise MissingOption("Missing option: %s:%s" % (self.name, key)) - MissingOption: Missing option: data-dir:directory - <BLANKLINE> - Starting pdb: diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/dependencylinks.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/dependencylinks.txt deleted file mode 100644 index 4414feb..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/dependencylinks.txt +++ /dev/null @@ -1,199 +0,0 @@ -Dependency links ----------------- - -By default buildout will obey the setuptools dependency_links metadata -when it looks for dependencies. This behavior can be controlled with -the use-dependency-links buildout option. - - [buildout] - ... - use-dependency-links = false - -The option defaults to true. If you set it to false, then dependency -links are only looked for in the locations specified by find-links. - -Let's see this feature in action. To begin, let's create a new egg -repository. This repository uses the same sample eggs as the normal -testing repository. - - >>> link_server2 = start_server(sample_eggs) - -Turn on logging on this server so that we can see when eggs are pulled -from it. - - >>> get(link_server2 + 'enable_server_logging') - GET 200 /enable_server_logging - '' - -Let's create a develop egg in our buildout that specifies -dependency_links which point to the new server. - - >>> mkdir(sample_buildout, 'depdemo') - >>> write(sample_buildout, 'depdemo', 'dependencydemo.py', - ... 'import eggrecipedemoneeded') - >>> write(sample_buildout, 'depdemo', 'setup.py', - ... '''from setuptools import setup; setup( - ... name='depdemo', py_modules=['dependencydemo'], - ... install_requires = 'demoneeded', - ... dependency_links = ['%s'], - ... zip_safe=True, version='1') - ... ''' % link_server2) - -Now let's configure the buildout to use the develop egg. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = depdemo - ... parts = eggs - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = depdemo - ... ''') - -Now we can run the buildout. - - >>> print system(buildout) - GET 200 / - GET 200 /demoneeded-1.2c1.zip - Develop: '/sample-buildout/depdemo' - Installing eggs. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - <BLANKLINE> - -Notice that the egg was retrieved from the logging server. - -Now let's change the egg so that it doesn't specify dependency links. - - >>> write(sample_buildout, 'depdemo', 'setup.py', - ... '''from setuptools import setup; setup( - ... name='depdemo', py_modules=['dependencydemo'], - ... install_requires = 'demoneeded', - ... zip_safe=True, version='1') - ... ''') - -Now we'll remove the existing dependency egg, and rerunning the -buildout to see where the egg comes from this time. - - >>> from glob import glob - >>> from os.path import join - >>> def remove_demoneeded_egg(): - ... for egg in glob(join(sample_buildout, 'eggs', 'demoneeded*.egg')): - ... remove(sample_buildout, 'eggs', egg) - >>> remove_demoneeded_egg() - >>> print system(buildout) # doctest: +ELLIPSIS - Develop: '/sample-buildout/depdemo' - ... - Getting distribution for 'demoneeded'. - While: - Updating eggs. - Getting distribution for 'demoneeded'. - Error: Couldn't find a distribution for 'demoneeded'. - <BLANKLINE> - -Now it can't find the dependency since neither the buildout -configuration nor setup specifies where to look. - -Let's change things so that the buildout configuration specifies where -to look for eggs. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = depdemo - ... parts = eggs - ... find-links = %s - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = depdemo - ... ''' % link_server) - - >>> print system(buildout) - Develop: '/sample-buildout/depdemo' - Installing eggs. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - <BLANKLINE> - -This time the dependency egg was found on the server without logging -configured. - -Now let's change things once again so that both buildout and setup -specify different places to look for the dependency egg. - - >>> write(sample_buildout, 'depdemo', 'setup.py', - ... '''from setuptools import setup; setup( - ... name='depdemo', py_modules=['dependencydemo'], - ... install_requires = 'demoneeded', - ... dependency_links = ['%s'], - ... zip_safe=True, version='1') - ... ''' % link_server2) - - >>> remove_demoneeded_egg() - >>> print system(buildout) #doctest: +ELLIPSIS - GET 200 /... - Develop: '/sample-buildout/depdemo' - Updating eggs. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - <BLANKLINE> - -So when both setuptools and buildout specify places to search for -eggs, the dependency_links takes precedence over find-links. - -There is a buildout option that you can specify to change this -behavior. It is the use-dependency-links option. This option defaults -to true. When you specify false for this option, buildout will ignore -dependency_links and only look for eggs using find-links. - -Here is an example of using this option to disable dependency_links. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = depdemo - ... parts = eggs - ... find-links = %s - ... use-dependency-links = false - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = depdemo - ... ''' % link_server) - - >>> remove_demoneeded_egg() - >>> print system(buildout) - Develop: '/sample-buildout/depdemo' - Updating eggs. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - <BLANKLINE> - -Notice that this time the egg isn't downloaded from the logging server. - -If we set the option to true, things return to the way they were -before. The dependency's are looked for first in the logging server. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = depdemo - ... parts = eggs - ... find-links = %s - ... use-dependency-links = true - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = depdemo - ... ''' % link_server) - >>> remove_demoneeded_egg() - >>> print system(buildout) #doctest: +ELLIPSIS - GET 200 /... - Develop: '/sample-buildout/depdemo' - Updating eggs. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - <BLANKLINE> diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/distribute.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/distribute.txt deleted file mode 100644 index da6b723..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/distribute.txt +++ /dev/null @@ -1,23 +0,0 @@ -Distribute Support -================== - -Distribute is a drop-in replacement for Setuptools. - -zc.buildout is now compatible with Distribute 0.6. To use Distribute in your -buildout, you need use the ``--distribute`` option of the ``bootstrap.py`` -script:: - - $ python bootstrap.py --distribute - -This will download and install the latest Distribute 0.6 release in the -``eggs`` directory, and use this version for the scripts that are created -in ``bin``. - -Notice that if you have a shared eggs directory, a buildout that uses -Distribute will not interfer with other buildouts that are based on Setuptools -and that are sharing the same eggs directory. - -Form more information about the Distribute project, see: -http://python-distribute.org - - diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py deleted file mode 100644 index 3d1295b..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.py +++ /dev/null @@ -1,251 +0,0 @@ -############################################################################## -# -# Copyright (c) 2009 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Buildout download infrastructure""" - -try: - from hashlib import md5 -except ImportError: - from md5 import new as md5 -from zc.buildout.easy_install import realpath -import logging -import os -import os.path -import re -import shutil -import tempfile -import urllib -import urlparse -import zc.buildout - - -class URLOpener(urllib.FancyURLopener): - http_error_default = urllib.URLopener.http_error_default - - -class ChecksumError(zc.buildout.UserError): - pass - - -url_opener = URLOpener() - - -class Download(object): - """Configurable download utility. - - Handles the download cache and offline mode. - - Download(options=None, cache=None, namespace=None, hash_name=False) - - options: mapping of buildout options (e.g. a ``buildout`` config section) - cache: path to the download cache (excluding namespaces) - namespace: namespace directory to use inside the cache - hash_name: whether to use a hash of the URL as cache file name - logger: an optional logger to receive download-related log messages - - """ - - def __init__(self, options={}, cache=-1, namespace=None, - offline=-1, fallback=False, hash_name=False, logger=None): - self.directory = options.get('directory', '') - self.cache = cache - if cache == -1: - self.cache = options.get('download-cache') - self.namespace = namespace - self.offline = offline - if offline == -1: - self.offline = (options.get('offline') == 'true' - or options.get('install-from-cache') == 'true') - self.fallback = fallback - self.hash_name = hash_name - self.logger = logger or logging.getLogger('zc.buildout') - - @property - def download_cache(self): - if self.cache is not None: - return realpath(os.path.join(self.directory, self.cache)) - - @property - def cache_dir(self): - if self.download_cache is not None: - return os.path.join(self.download_cache, self.namespace or '') - - def __call__(self, url, md5sum=None, path=None): - """Download a file according to the utility's configuration. - - url: URL to download - md5sum: MD5 checksum to match - path: where to place the downloaded file - - Returns the path to the downloaded file. - - """ - if self.cache: - local_path, is_temp = self.download_cached(url, md5sum) - else: - local_path, is_temp = self.download(url, md5sum, path) - - return locate_at(local_path, path), is_temp - - def download_cached(self, url, md5sum=None): - """Download a file from a URL using the cache. - - This method assumes that the cache has been configured. Optionally, it - raises a ChecksumError if a cached copy of a file has an MD5 mismatch, - but will not remove the copy in that case. - - """ - if not os.path.exists(self.download_cache): - raise zc.buildout.UserError( - 'The directory:\n' - '%r\n' - "to be used as a download cache doesn't exist.\n" - % self.download_cache) - cache_dir = self.cache_dir - if not os.path.exists(cache_dir): - os.mkdir(cache_dir) - cache_key = self.filename(url) - cached_path = os.path.join(cache_dir, cache_key) - - self.logger.debug('Searching cache at %s' % cache_dir) - if os.path.isfile(cached_path): - is_temp = False - if self.fallback: - try: - _, is_temp = self.download(url, md5sum, cached_path) - except ChecksumError: - raise - except Exception: - pass - - if not check_md5sum(cached_path, md5sum): - raise ChecksumError( - 'MD5 checksum mismatch for cached download ' - 'from %r at %r' % (url, cached_path)) - self.logger.debug('Using cache file %s' % cached_path) - else: - self.logger.debug('Cache miss; will cache %s as %s' % - (url, cached_path)) - _, is_temp = self.download(url, md5sum, cached_path) - - return cached_path, is_temp - - def download(self, url, md5sum=None, path=None): - """Download a file from a URL to a given or temporary path. - - An online resource is always downloaded to a temporary file and moved - to the specified path only after the download is complete and the - checksum (if given) matches. If path is None, the temporary file is - returned and the client code is responsible for cleaning it up. - - """ - if re.match(r"^[A-Za-z]:\\", url): - url = 'file:' + url - parsed_url = urlparse.urlparse(url, 'file') - url_scheme, _, url_path = parsed_url[:3] - if url_scheme == 'file': - self.logger.debug('Using local resource %s' % url) - if not check_md5sum(url_path, md5sum): - raise ChecksumError( - 'MD5 checksum mismatch for local resource at %r.' % - url_path) - return locate_at(url_path, path), False - - if self.offline: - raise zc.buildout.UserError( - "Couldn't download %r in offline mode." % url) - - self.logger.info('Downloading %s' % url) - urllib._urlopener = url_opener - handle, tmp_path = tempfile.mkstemp(prefix='buildout-') - try: - try: - tmp_path, headers = urllib.urlretrieve(url, tmp_path) - if not check_md5sum(tmp_path, md5sum): - raise ChecksumError( - 'MD5 checksum mismatch downloading %r' % url) - finally: - os.close(handle) - except: - os.remove(tmp_path) - raise - - if path: - shutil.move(tmp_path, path) - return path, False - else: - return tmp_path, True - - def filename(self, url): - """Determine a file name from a URL according to the configuration. - - """ - if self.hash_name: - return md5(url).hexdigest() - else: - if re.match(r"^[A-Za-z]:\\", url): - url = 'file:' + url - parsed = urlparse.urlparse(url, 'file') - url_path = parsed[2] - - if parsed[0] == 'file': - while True: - url_path, name = os.path.split(url_path) - if name: - return name - if not url_path: - break - else: - for name in reversed(url_path.split('/')): - if name: - return name - - url_host, url_port = parsed[-2:] - return '%s:%s' % (url_host, url_port) - - -def check_md5sum(path, md5sum): - """Tell whether the MD5 checksum of the file at path matches. - - No checksum being given is considered a match. - - """ - if md5sum is None: - return True - - f = open(path, 'rb') - checksum = md5() - try: - chunk = f.read(2**16) - while chunk: - checksum.update(chunk) - chunk = f.read(2**16) - return checksum.hexdigest() == md5sum - finally: - f.close() - - -def remove(path): - if os.path.exists(path): - os.remove(path) - - -def locate_at(source, dest): - if dest is None or realpath(dest) == realpath(source): - return source - - try: - os.link(source, dest) - except (AttributeError, OSError): - shutil.copyfile(source, dest) - return dest diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.txt deleted file mode 100644 index 5184800..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/download.txt +++ /dev/null @@ -1,550 +0,0 @@ -Using the download utility -========================== - -The ``zc.buildout.download`` module provides a download utility that handles -the details of downloading files needed for a buildout run from the internet. -It downloads files to the local file system, using the download cache if -desired and optionally checking the downloaded files' MD5 checksum. - -We setup an HTTP server that provides a file we want to download: - ->>> server_data = tmpdir('sample_files') ->>> write(server_data, 'foo.txt', 'This is a foo text.') ->>> server_url = start_server(server_data) - -We also use a fresh directory for temporary files in order to make sure that -all temporary files have been cleaned up in the end: - ->>> import tempfile ->>> old_tempdir = tempfile.tempdir ->>> tempfile.tempdir = tmpdir('tmp') - - -Downloading without using the cache ------------------------------------ - -If no download cache should be used, the download utility is instantiated -without any arguments: - ->>> from zc.buildout.download import Download ->>> download = Download() ->>> print download.cache_dir -None - -Downloading a file is achieved by calling the utility with the URL as an -argument. A tuple is returned that consists of the path to the downloaded copy -of the file and a boolean value indicating whether this is a temporary file -meant to be cleaned up during the same buildout run: - ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/.../buildout-... ->>> cat(path) -This is a foo text. - -As we aren't using the download cache and haven't specified a target path -either, the download has ended up in a temporary file: - ->>> is_temp -True - ->>> import tempfile ->>> path.startswith(tempfile.gettempdir()) -True - -We are responsible for cleaning up temporary files behind us: - ->>> remove(path) - -When trying to access a file that doesn't exist, we'll get an exception: - ->>> try: download(server_url+'not-there') # doctest: +ELLIPSIS -... except: print 'download error' -... else: print 'woops' -download error - -Downloading a local file doesn't produce a temporary file but simply returns -the local file itself: - ->>> download(join(server_data, 'foo.txt')) -('/sample_files/foo.txt', False) - -We can also have the downloaded file's MD5 sum checked: - ->>> try: from hashlib import md5 -... except ImportError: from md5 import new as md5 - ->>> path, is_temp = download(server_url+'foo.txt', -... md5('This is a foo text.').hexdigest()) ->>> is_temp -True ->>> remove(path) - ->>> download(server_url+'foo.txt', -... md5('The wrong text.').hexdigest()) -Traceback (most recent call last): -ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt' - -The error message in the event of an MD5 checksum mismatch for a local file -reads somewhat differently: - ->>> download(join(server_data, 'foo.txt'), -... md5('This is a foo text.').hexdigest()) -('/sample_files/foo.txt', False) - ->>> download(join(server_data, 'foo.txt'), -... md5('The wrong text.').hexdigest()) -Traceback (most recent call last): -ChecksumError: MD5 checksum mismatch for local resource at '/sample_files/foo.txt'. - -Finally, we can download the file to a specified place in the file system: - ->>> target_dir = tmpdir('download-target') ->>> path, is_temp = download(server_url+'foo.txt', -... path=join(target_dir, 'downloaded.txt')) ->>> print path -/download-target/downloaded.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False - -Trying to download a file in offline mode will result in an error: - ->>> download = Download(cache=None, offline=True) ->>> download(server_url+'foo.txt') -Traceback (most recent call last): -UserError: Couldn't download 'http://localhost/foo.txt' in offline mode. - -As an exception to this rule, file system paths and URLs in the ``file`` -scheme will still work: - ->>> cat(download(join(server_data, 'foo.txt'))[0]) -This is a foo text. ->>> cat(download('file:' + join(server_data, 'foo.txt'))[0]) -This is a foo text. - ->>> remove(path) - - -Downloading using the download cache ------------------------------------- - -In order to make use of the download cache, we need to configure the download -utility differently. To do this, we pass a directory path as the ``cache`` -attribute upon instantiation: - ->>> cache = tmpdir('download-cache') ->>> download = Download(cache=cache) ->>> print download.cache_dir -/download-cache/ - -Simple usage -~~~~~~~~~~~~ - -When using the cache, a file will be stored in the cache directory when it is -first downloaded. The file system path returned by the download utility points -to the cached copy: - ->>> ls(cache) ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/download-cache/foo.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False - -Whenever the file is downloaded again, the cached copy is used. Let's change -the file on the server to see this: - ->>> write(server_data, 'foo.txt', 'The wrong text.') ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/download-cache/foo.txt ->>> cat(path) -This is a foo text. - -If we specify an MD5 checksum for a file that is already in the cache, the -cached copy's checksum will be verified: - ->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest()) -Traceback (most recent call last): -ChecksumError: MD5 checksum mismatch for cached download - from 'http://localhost/foo.txt' at '/download-cache/foo.txt' - -Trying to access another file at a different URL which has the same base name -will result in the cached copy being used: - ->>> mkdir(server_data, 'other') ->>> write(server_data, 'other', 'foo.txt', 'The wrong text.') ->>> path, is_temp = download(server_url+'other/foo.txt') ->>> print path -/download-cache/foo.txt ->>> cat(path) -This is a foo text. - -Given a target path for the download, the utility will provide a copy of the -file at that location both when first downloading the file and when using a -cached copy: - ->>> remove(cache, 'foo.txt') ->>> ls(cache) ->>> write(server_data, 'foo.txt', 'This is a foo text.') - ->>> path, is_temp = download(server_url+'foo.txt', -... path=join(target_dir, 'downloaded.txt')) ->>> print path -/download-target/downloaded.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False ->>> ls(cache) -- foo.txt - ->>> remove(path) ->>> write(server_data, 'foo.txt', 'The wrong text.') - ->>> path, is_temp = download(server_url+'foo.txt', -... path=join(target_dir, 'downloaded.txt')) ->>> print path -/download-target/downloaded.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False - -In offline mode, downloads from any URL will be successful if the file is -found in the cache: - ->>> download = Download(cache=cache, offline=True) ->>> cat(download(server_url+'foo.txt')[0]) -This is a foo text. - -Local resources will be cached just like any others since download caches are -sometimes used to create source distributions: - ->>> remove(cache, 'foo.txt') ->>> ls(cache) - ->>> write(server_data, 'foo.txt', 'This is a foo text.') ->>> download = Download(cache=cache) - ->>> cat(download('file:' + join(server_data, 'foo.txt'), path=path)[0]) -This is a foo text. ->>> ls(cache) -- foo.txt - ->>> remove(cache, 'foo.txt') - ->>> cat(download(join(server_data, 'foo.txt'), path=path)[0]) -This is a foo text. ->>> ls(cache) -- foo.txt - ->>> remove(cache, 'foo.txt') - -However, resources with checksum mismatches will not be copied to the cache: - ->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest()) -Traceback (most recent call last): -ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt' ->>> ls(cache) - ->>> remove(path) - -Finally, let's see what happens if the download cache to be used doesn't exist -as a directory in the file system yet: - ->>> Download(cache=join(cache, 'non-existent'))(server_url+'foo.txt') -Traceback (most recent call last): -UserError: The directory: -'/download-cache/non-existent' -to be used as a download cache doesn't exist. - -Using namespace sub-directories of the download cache -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -It is common to store cached copies of downloaded files within sub-directories -of the download cache to keep some degree of order. For example, zc.buildout -stores downloaded distributions in a sub-directory named "dist". Those -sub-directories are also known as namespaces. So far, we haven't specified any -namespaces to use, so the download utility stored files directly inside the -download cache. Let's use a namespace "test" instead: - ->>> download = Download(cache=cache, namespace='test') ->>> print download.cache_dir -/download-cache/test - -The namespace sub-directory hasn't been created yet: - ->>> ls(cache) - -Downloading a file now creates the namespace sub-directory and places a copy -of the file inside it: - ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/download-cache/test/foo.txt ->>> ls(cache) -d test ->>> ls(cache, 'test') -- foo.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False - -The next time we want to download that file, the copy from inside the cache -namespace is used. To see this clearly, we put a file with the same name but -different content both on the server and in the cache's root directory: - ->>> write(server_data, 'foo.txt', 'The wrong text.') ->>> write(cache, 'foo.txt', 'The wrong text.') - ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/download-cache/test/foo.txt ->>> cat(path) -This is a foo text. - ->>> rmdir(cache, 'test') ->>> remove(cache, 'foo.txt') ->>> write(server_data, 'foo.txt', 'This is a foo text.') - -Using a hash of the URL as the filename in the cache -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -So far, the base name of the downloaded file read from the URL has been used -for the name of the cached copy of the file. This may not be desirable in some -cases, for example when downloading files from different locations that have -the same base name due to some naming convention, or if the file content -depends on URL parameters. In such cases, an MD5 hash of the complete URL may -be used as the filename in the cache: - ->>> download = Download(cache=cache, hash_name=True) ->>> path, is_temp = download(server_url+'foo.txt') ->>> print path -/download-cache/09f5793fcdc1716727f72d49519c688d ->>> cat(path) -This is a foo text. ->>> ls(cache) -- 09f5793fcdc1716727f72d49519c688d - -The path was printed just to illustrate matters; we cannot know the real -checksum since we don't know which port the server happens to listen at when -the test is run, so we don't actually know the full URL of the file. Let's -check that the checksum actually belongs to the particular URL used: - ->>> path.lower() == join(cache, md5(server_url+'foo.txt').hexdigest()).lower() -True - -The cached copy is used when downloading the file again: - ->>> write(server_data, 'foo.txt', 'The wrong text.') ->>> (path, is_temp) == download(server_url+'foo.txt') -True ->>> cat(path) -This is a foo text. ->>> ls(cache) -- 09f5793fcdc1716727f72d49519c688d - -If we change the URL, even in such a way that it keeps the base name of the -file the same, the file will be downloaded again this time and put in the -cache under a different name: - ->>> path2, is_temp = download(server_url+'other/foo.txt') ->>> print path2 -/download-cache/537b6d73267f8f4447586989af8c470e ->>> path == path2 -False ->>> path2.lower() == join(cache, md5(server_url+'other/foo.txt').hexdigest()).lower() -True ->>> cat(path) -This is a foo text. ->>> cat(path2) -The wrong text. ->>> ls(cache) -- 09f5793fcdc1716727f72d49519c688d -- 537b6d73267f8f4447586989af8c470e - ->>> remove(path) ->>> remove(path2) ->>> write(server_data, 'foo.txt', 'This is a foo text.') - - -Using the cache purely as a fall-back -------------------------------------- - -Sometimes it is desirable to try downloading a file from the net if at all -possible, and use the cache purely as a fall-back option when a server is -down or if we are in offline mode. This mode is only in effect if a download -cache is configured in the first place: - ->>> download = Download(cache=cache, fallback=True) ->>> print download.cache_dir -/download-cache/ - -A downloaded file will be cached: - ->>> ls(cache) ->>> path, is_temp = download(server_url+'foo.txt') ->>> ls(cache) -- foo.txt ->>> cat(cache, 'foo.txt') -This is a foo text. ->>> is_temp -False - -If the file cannot be served, the cached copy will be used: - ->>> remove(server_data, 'foo.txt') ->>> try: Download()(server_url+'foo.txt') # doctest: +ELLIPSIS -... except: print 'download error' -... else: print 'woops' -download error ->>> path, is_temp = download(server_url+'foo.txt') ->>> cat(path) -This is a foo text. ->>> is_temp -False - -Similarly, if the file is served but we're in offline mode, we'll fall back to -using the cache: - ->>> write(server_data, 'foo.txt', 'The wrong text.') ->>> get(server_url+'foo.txt') -'The wrong text.' - ->>> offline_download = Download(cache=cache, offline=True, fallback=True) ->>> path, is_temp = offline_download(server_url+'foo.txt') ->>> print path -/download-cache/foo.txt ->>> cat(path) -This is a foo text. ->>> is_temp -False - -However, when downloading the file normally with the cache being used in -fall-back mode, the file will be downloaded from the net and the cached copy -will be replaced with the new content: - ->>> cat(download(server_url+'foo.txt')[0]) -The wrong text. ->>> cat(cache, 'foo.txt') -The wrong text. - -When trying to download a resource whose checksum does not match, the cached -copy will neither be used nor overwritten: - ->>> write(server_data, 'foo.txt', 'This is a foo text.') ->>> download(server_url+'foo.txt', md5('The wrong text.').hexdigest()) -Traceback (most recent call last): -ChecksumError: MD5 checksum mismatch downloading 'http://localhost/foo.txt' ->>> cat(cache, 'foo.txt') -The wrong text. - - -Configuring the download utility from buildout options ------------------------------------------------------- - -The configuration options explained so far derive from the build logic -implemented by the calling code. Other options configure the download utility -for use in a particular project or buildout run; they are read from the -``buildout`` configuration section. The latter can be passed directly as the -first argument to the download utility's constructor. - -The location of the download cache is specified by the ``download-cache`` -option: - ->>> download = Download({'download-cache': cache}, namespace='cmmi') ->>> print download.cache_dir -/download-cache/cmmi - -If the ``download-cache`` option specifies a relative path, it is understood -relative to the current working directory, or to the buildout directory if -that is given: - ->>> download = Download({'download-cache': 'relative-cache'}) ->>> print download.cache_dir -/sample-buildout/relative-cache/ - ->>> download = Download({'directory': join(sample_buildout, 'root'), -... 'download-cache': 'relative-cache'}) ->>> print download.cache_dir -/sample-buildout/root/relative-cache/ - -Keyword parameters take precedence over the corresponding options: - ->>> download = Download({'download-cache': cache}, cache=None) ->>> print download.cache_dir -None - -Whether to assume offline mode can be inferred from either the ``offline`` or -the ``install-from-cache`` option. As usual with zc.buildout, these options -must assume one of the values 'true' and 'false': - ->>> download = Download({'offline': 'true'}) ->>> download.offline -True - ->>> download = Download({'offline': 'false'}) ->>> download.offline -False - ->>> download = Download({'install-from-cache': 'true'}) ->>> download.offline -True - ->>> download = Download({'install-from-cache': 'false'}) ->>> download.offline -False - -These two options are combined using logical 'or': - ->>> download = Download({'offline': 'true', 'install-from-cache': 'false'}) ->>> download.offline -True - ->>> download = Download({'offline': 'false', 'install-from-cache': 'true'}) ->>> download.offline -True - -The ``offline`` keyword parameter takes precedence over both the ``offline`` -and ``install-from-cache`` options: - ->>> download = Download({'offline': 'true'}, offline=False) ->>> download.offline -False - ->>> download = Download({'install-from-cache': 'false'}, offline=True) ->>> download.offline -True - - -Regressions ------------ - -MD5 checksum calculation needs to be reliable on all supported systems, which -requires text files to be treated as binary to avoid implicit line-ending -conversions: - ->>> text = 'First line of text.\r\nSecond line.\r\n' ->>> f = open(join(server_data, 'foo.txt'), 'wb') ->>> f.write(text) ->>> f.close() ->>> path, is_temp = Download()(server_url+'foo.txt', md5(text).hexdigest()) ->>> remove(path) - - -Clean up --------- - -We should have cleaned up all temporary files created by downloading things: - ->>> ls(tempfile.tempdir) - -Reset the global temporary directory: - ->>> tempfile.tempdir = old_tempdir diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/downloadcache.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/downloadcache.txt deleted file mode 100644 index 6035bd2..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/downloadcache.txt +++ /dev/null @@ -1,141 +0,0 @@ -Using a download cache -====================== - -Normally, when distributions are installed, if any processing is -needed, they are downloaded from the internet to a temporary directory -and then installed from there. A download cache can be used to avoid -the download step. This can be useful to reduce network access and to -create source distributions of an entire buildout. - -The buildout download-cache option can be used to specify a directory -to be used as a download cache. - -In this example, we'll create a directory to hold the cache: - - >>> cache = tmpdir('cache') - -And set up a buildout that downloads some eggs: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... download-cache = %(cache)s - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = demo ==0.2 - ... ''' % globals()) - -We specified a link server that has some distributions available for -download: - - >>> print get(link_server), - <html><body> - <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br> - <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> - <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> - <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> - <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> - <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> - <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> - <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> - <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> - <a href="index/">index/</a><br> - <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br> - </body></html> - - -We'll enable logging on the link server so we can see what's going on: - - >>> get(link_server+'enable_server_logging') - GET 200 /enable_server_logging - '' - -We also specified a download cache. - -If we run the buildout, we'll see the eggs installed from the link -server as usual: - - >>> print system(buildout), - GET 200 / - GET 200 /demo-0.2-py2.4.egg - GET 200 /demoneeded-1.2c1.zip - Installing eggs. - Getting distribution for 'demo==0.2'. - Got demo 0.2. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - Generated script '/sample-buildout/bin/demo'. - -We'll also get the download cache populated. The buildout doesn't put -files in the cache directly. It creates an intermediate directory, -dist: - - - >>> ls(cache) - d dist - - >>> ls(cache, 'dist') - - demo-0.2-py2.4.egg - - demoneeded-1.2c1.zip - -If we remove the installed eggs from eggs directory and re-run the buildout: - - >>> import os - >>> for f in os.listdir('eggs'): - ... if f.startswith('demo'): - ... remove('eggs', f) - - >>> print system(buildout), - GET 200 / - Updating eggs. - Getting distribution for 'demo==0.2'. - Got demo 0.2. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - -We see that the distributions aren't downloaded, because they're -downloaded from the cache. - -Installing solely from a download cache ---------------------------------------- - -A download cache can be used as the basis of application source -releases. In an application source release, we want to distribute an -application that can be built without making any network accesses. In -this case, we distribute a buildout with download cache and tell the -buildout to install from the download cache only, without making -network accesses. The buildout install-from-cache option can be used -to signal that packages should be installed only from the download -cache. - -Let's remove our installed eggs and run the buildout with the -install-from-cache option set to true: - - >>> for f in os.listdir('eggs'): - ... if f.startswith('demo'): - ... remove('eggs', f) - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... download-cache = %(cache)s - ... install-from-cache = true - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout), - Uninstalling eggs. - Installing eggs. - Getting distribution for 'demo'. - Got demo 0.2. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - Generated script '/sample-buildout/bin/demo'. diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.py deleted file mode 100644 index b09c0c5..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.py +++ /dev/null @@ -1,1906 +0,0 @@ -############################################################################# -# -# Copyright (c) 2005 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Python easy_install API - -This module provides a high-level Python API for installing packages. -It doesn't install scripts. It uses setuptools and requires it to be -installed. -""" - -import distutils.errors -import fnmatch -import glob -import logging -import os -import pkg_resources -import py_compile -import re -import setuptools.archive_util -import setuptools.command.setopt -import setuptools.package_index -import shutil -import subprocess -import sys -import tempfile -import warnings -import zc.buildout -import zipimport - -_oprp = getattr(os.path, 'realpath', lambda path: path) -def realpath(path): - return os.path.normcase(os.path.abspath(_oprp(path))) - -default_index_url = os.environ.get( - 'buildout-testing-index-url', - 'http://pypi.python.org/simple', - ) - -logger = logging.getLogger('zc.buildout.easy_install') - -url_match = re.compile('[a-z0-9+.-]+://').match - -is_win32 = sys.platform == 'win32' -is_jython = sys.platform.startswith('java') -is_distribute = ( - pkg_resources.Requirement.parse('setuptools').key=='distribute') - -BROKEN_DASH_S_WARNING = ( - 'Buildout has been asked to exclude or limit site-packages so that ' - 'builds can be repeatable when using a system Python. However, ' - 'the chosen Python executable has a broken implementation of -S (see ' - 'https://bugs.launchpad.net/virtualenv/+bug/572545 for an example ' - "problem) and this breaks buildout's ability to isolate site-packages. " - "If the executable already has a clean site-packages (e.g., " - "using virtualenv's ``--no-site-packages`` option) you may be getting " - 'equivalent repeatability. To silence this warning, use the -s argument ' - 'to the buildout script. Alternatively, use a Python executable with a ' - 'working -S (such as a standard Python binary).') - -if is_jython: - import java.lang.System - jython_os_name = (java.lang.System.getProperties()['os.name']).lower() - -setuptools_loc = pkg_resources.working_set.find( - pkg_resources.Requirement.parse('setuptools') - ).location - -# Include buildout and setuptools eggs in paths. We prevent dupes just to -# keep from duplicating any log messages about them. -buildout_loc = pkg_resources.working_set.find( - pkg_resources.Requirement.parse('zc.buildout')).location -buildout_and_setuptools_path = [setuptools_loc] -if os.path.normpath(setuptools_loc) != os.path.normpath(buildout_loc): - buildout_and_setuptools_path.append(buildout_loc) - -def _has_broken_dash_S(executable): - """Detect https://bugs.launchpad.net/virtualenv/+bug/572545 .""" - # The first attempt here was to simply have the executable attempt to import - # ConfigParser and return the return code. That worked except for tests on - # Windows, where the return code was wrong for the fake Python executable - # generated by the virtualenv.txt test, apparently because setuptools' .exe - # file does not pass the -script.py's returncode back properly, at least in - # some circumstances. Therefore...print statements. - stdout, stderr = subprocess.Popen( - [executable, '-Sc', - 'try:\n' - ' import ConfigParser\n' - 'except ImportError:\n' - ' print 1\n' - 'else:\n' - ' print 0\n'], - stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate() - return bool(int(stdout.strip())) - -def _get_system_paths(executable): - """Return lists of standard lib and site paths for executable. - """ - # We want to get a list of the site packages, which is not easy. - # The canonical way to do this is to use - # distutils.sysconfig.get_python_lib(), but that only returns a - # single path, which does not reflect reality for many system - # Pythons, which have multiple additions. Instead, we start Python - # with -S, which does not import site.py and set up the extra paths - # like site-packages or (Ubuntu/Debian) dist-packages and - # python-support. We then compare that sys.path with the normal one - # (minus user packages if this is Python 2.6, because we don't - # support those (yet?). The set of the normal one minus the set of - # the ones in ``python -S`` is the set of packages that are - # effectively site-packages. - # - # The given executable might not be the current executable, so it is - # appropriate to do another subprocess to figure out what the - # additional site-package paths are. Moreover, even if this - # executable *is* the current executable, this code might be run in - # the context of code that has manipulated the sys.path--for - # instance, to add local zc.buildout or setuptools eggs. - def get_sys_path(*args, **kwargs): - cmd = [executable] - cmd.extend(args) - cmd.extend([ - "-c", "import sys, os;" - "print repr([os.path.normpath(p) for p in sys.path if p])"]) - # Windows needs some (as yet to be determined) part of the real env. - env = os.environ.copy() - # We need to make sure that PYTHONPATH, which will often be set - # to include a custom buildout-generated site.py, is not set, or - # else we will not get an accurate sys.path for the executable. - env.pop('PYTHONPATH', None) - env.update(kwargs) - _proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) - stdout, stderr = _proc.communicate(); - if _proc.returncode: - raise RuntimeError( - 'error trying to get system packages:\n%s' % (stderr,)) - res = eval(stdout.strip()) - try: - res.remove('.') - except ValueError: - pass - return res - stdlib = get_sys_path('-S') # stdlib only - no_user_paths = get_sys_path(PYTHONNOUSERSITE='x') - site_paths = [p for p in no_user_paths if p not in stdlib] - return (stdlib, site_paths) - -def _get_version_info(executable): - cmd = [executable, '-Sc', - 'import sys; print(repr(tuple(x for x in sys.version_info)))'] - _proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = _proc.communicate(); - if _proc.returncode: - raise RuntimeError( - 'error trying to get system packages:\n%s' % (stderr,)) - return eval(stdout.strip()) - - -class IncompatibleVersionError(zc.buildout.UserError): - """A specified version is incompatible with a given requirement. - """ - -_versions = {sys.executable: '%d.%d' % sys.version_info[:2]} -def _get_version(executable): - try: - return _versions[executable] - except KeyError: - cmd = _safe_arg(executable) + ' -V' - p = subprocess.Popen(cmd, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - close_fds=not is_win32) - i, o = (p.stdin, p.stdout) - i.close() - version = o.read().strip() - o.close() - pystring, version = version.split() - assert pystring == 'Python' - version = re.match('(\d[.]\d)([.].*\d)?$', version).group(1) - _versions[executable] = version - return version - -FILE_SCHEME = re.compile('file://', re.I).match - - -class AllowHostsPackageIndex(setuptools.package_index.PackageIndex): - """Will allow urls that are local to the system. - - No matter what is allow_hosts. - """ - def url_ok(self, url, fatal=False): - if FILE_SCHEME(url): - return True - return setuptools.package_index.PackageIndex.url_ok(self, url, False) - - -_indexes = {} -def _get_index(executable, index_url, find_links, allow_hosts=('*',), - path=None): - # If path is None, the index will use sys.path. If you provide an empty - # path ([]), it will complain uselessly about missing index pages for - # packages found in the paths that you expect to use. Therefore, this path - # is always the same as the _env path in the Installer. - key = executable, index_url, tuple(find_links) - index = _indexes.get(key) - if index is not None: - return index - - if index_url is None: - index_url = default_index_url - index = AllowHostsPackageIndex( - index_url, hosts=allow_hosts, search_path=path, - python=_get_version(executable) - ) - - if find_links: - index.add_find_links(find_links) - - _indexes[key] = index - return index - -clear_index_cache = _indexes.clear - -if is_win32: - # work around spawn lamosity on windows - # XXX need safe quoting (see the subprocess.list2cmdline) and test - def _safe_arg(arg): - return '"%s"' % arg -else: - _safe_arg = str - -# The following string is used to run easy_install in -# Installer._call_easy_install. It is usually started with python -S -# (that is, don't import site at start). That flag, and all of the code -# in this snippet above the last two lines, exist to work around a -# relatively rare problem. If -# -# - your buildout configuration is trying to install a package that is within -# a namespace package, and -# -# - you use a Python that has a different version of this package -# installed in in its site-packages using -# --single-version-externally-managed (that is, using the mechanism -# sometimes used by system packagers: -# http://peak.telecommunity.com/DevCenter/setuptools#install-command ), and -# -# - the new package tries to do sys.path tricks in the setup.py to get a -# __version__, -# -# then the older package will be loaded first, making the setup version -# the wrong number. While very arguably packages simply shouldn't do -# the sys.path tricks, some do, and we don't want buildout to fall over -# when they do. -# -# The namespace packages installed in site-packages with -# --single-version-externally-managed use a mechanism that cause them to -# be processed when site.py is imported (see -# http://mail.python.org/pipermail/distutils-sig/2009-May/011730.html -# for another description of the problem). Simply starting Python with -# -S addresses the problem in Python 2.4 and 2.5, but Python 2.6's -# distutils imports a value from the site module, so we unfortunately -# have to do more drastic surgery in the _easy_install_preface code below. -# -# Here's an example of the .pth files created by setuptools when using that -# flag: -# -# import sys,new,os; -# p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('<NAMESPACE>',)); -# ie = os.path.exists(os.path.join(p,'__init__.py')); -# m = not ie and sys.modules.setdefault('<NAMESPACE>',new.module('<NAMESPACE>')); -# mp = (m or []) and m.__dict__.setdefault('__path__',[]); -# (p not in mp) and mp.append(p) -# -# The code, below, then, runs under -S, indicating that site.py should -# not be loaded initially. It gets the initial sys.path under these -# circumstances, and then imports site (because Python 2.6's distutils -# will want it, as mentioned above). It then reinstates the old sys.path -# value. Then it removes namespace packages (created by the setuptools -# code above) from sys.modules. It identifies namespace packages by -# iterating over every loaded module. It first looks if there is a -# __path__, so it is a package; and then it sees if that __path__ does -# not have an __init__.py. (Note that PEP 382, -# http://www.python.org/dev/peps/pep-0382, makes it possible to have a -# namespace package that has an __init__.py, but also should make it -# unnecessary for site.py to preprocess these packages, so it should be -# fine, as far as can be guessed as of this writing.) Finally, it -# imports easy_install and runs it. -_easy_install_preface = '''\ -import sys,os;\ -p = sys.path[:];\ -import site;\ -sys.path[:] = p;\ -[sys.modules.pop(k) for k, v in sys.modules.items()\ - if hasattr(v, '__path__') and len(v.__path__)==1 and\ - not os.path.exists(os.path.join(v.__path__[0],'__init__.py'))];''' -_easy_install_cmd = ( - 'from setuptools.command.easy_install import main;main()') - - -class Installer: - - _versions = {} - _download_cache = None - _install_from_cache = False - _prefer_final = True - _use_dependency_links = True - _allow_picked_versions = True - _always_unzip = False - _include_site_packages = True - _allowed_eggs_from_site_packages = ('*',) - - def __init__(self, - dest=None, - links=(), - index=None, - executable=sys.executable, - always_unzip=None, - path=None, - newest=True, - versions=None, - use_dependency_links=None, - allow_hosts=('*',), - include_site_packages=None, - allowed_eggs_from_site_packages=None, - prefer_final=None, - ): - self._dest = dest - self._allow_hosts = allow_hosts - - if self._install_from_cache: - if not self._download_cache: - raise ValueError("install_from_cache set to true with no" - " download cache") - links = () - index = 'file://' + self._download_cache - - if use_dependency_links is not None: - self._use_dependency_links = use_dependency_links - if prefer_final is not None: - self._prefer_final = prefer_final - self._links = links = list(_fix_file_links(links)) - if self._download_cache and (self._download_cache not in links): - links.insert(0, self._download_cache) - - self._index_url = index - self._executable = executable - self._has_broken_dash_S = _has_broken_dash_S(self._executable) - if always_unzip is not None: - self._always_unzip = always_unzip - path = (path and path[:] or []) - if include_site_packages is not None: - self._include_site_packages = include_site_packages - if allowed_eggs_from_site_packages is not None: - self._allowed_eggs_from_site_packages = tuple( - allowed_eggs_from_site_packages) - if self._has_broken_dash_S: - if (not self._include_site_packages or - self._allowed_eggs_from_site_packages != ('*',)): - # We can't do this if the executable has a broken -S. - warnings.warn(BROKEN_DASH_S_WARNING) - self._include_site_packages = True - self._allowed_eggs_from_site_packages = ('*',) - self._easy_install_cmd = _easy_install_cmd - else: - self._easy_install_cmd = _easy_install_preface + _easy_install_cmd - self._easy_install_cmd = _safe_arg(self._easy_install_cmd) - stdlib, self._site_packages = _get_system_paths(executable) - version_info = _get_version_info(executable) - if version_info == sys.version_info: - # Maybe we can add the buildout and setuptools path. If we - # are including site_packages, we only have to include the extra - # bits here, so we don't duplicate. On the other hand, if we - # are not including site_packages, we only want to include the - # parts that are not in site_packages, so the code is the same. - path.extend( - set(buildout_and_setuptools_path).difference( - self._site_packages)) - if self._include_site_packages: - path.extend(self._site_packages) - if dest is not None and dest not in path: - path.insert(0, dest) - self._path = path - if self._dest is None: - newest = False - self._newest = newest - self._env = pkg_resources.Environment(path, - python=_get_version(executable)) - self._index = _get_index(executable, index, links, self._allow_hosts, - self._path) - - if versions is not None: - self._versions = versions - - _allowed_eggs_from_site_packages_regex = None - def allow_site_package_egg(self, name): - if (not self._include_site_packages or - not self._allowed_eggs_from_site_packages): - # If the answer is a blanket "no," perform a shortcut. - return False - if self._allowed_eggs_from_site_packages_regex is None: - pattern = '(%s)' % ( - '|'.join( - fnmatch.translate(name) - for name in self._allowed_eggs_from_site_packages), - ) - self._allowed_eggs_from_site_packages_regex = re.compile(pattern) - return bool(self._allowed_eggs_from_site_packages_regex.match(name)) - - def _satisfied(self, req, source=None): - # We get all distributions that match the given requirement. If we are - # not supposed to include site-packages for the given egg, we also - # filter those out. Even if include_site_packages is False and so we - # have excluded site packages from the _env's paths (see - # Installer.__init__), we need to do the filtering here because an - # .egg-link, such as one for setuptools or zc.buildout installed by - # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a - # path in our _site_packages. - dists = [dist for dist in self._env[req.project_name] if ( - dist in req and ( - dist.location not in self._site_packages or - self.allow_site_package_egg(dist.project_name)) - ) - ] - if not dists: - logger.debug('We have no distributions for %s that satisfies %r.', - req.project_name, str(req)) - - return None, self._obtain(req, source) - - # Note that dists are sorted from best to worst, as promised by - # env.__getitem__ - - for dist in dists: - if (dist.precedence == pkg_resources.DEVELOP_DIST and - dist.location not in self._site_packages): - # System eggs are sometimes installed as develop eggs. - # Those are not the kind of develop eggs we are looking for - # here: we want ones that the buildout itself has locally as - # develop eggs. - logger.debug('We have a develop egg: %s', dist) - return dist, None - - # Special common case, we have a specification for a single version: - specs = req.specs - if len(specs) == 1 and specs[0][0] == '==': - logger.debug('We have the distribution that satisfies %r.', - str(req)) - return dists[0], None - - if self._prefer_final: - fdists = [dist for dist in dists - if _final_version(dist.parsed_version) - ] - if fdists: - # There are final dists, so only use those - dists = fdists - - if not self._newest: - # We don't need the newest, so we'll use the newest one we - # find, which is the first returned by - # Environment.__getitem__. - return dists[0], None - - best_we_have = dists[0] # Because dists are sorted from best to worst - - # We have some installed distros. There might, theoretically, be - # newer ones. Let's find out which ones are available and see if - # any are newer. We only do this if we're willing to install - # something, which is only true if dest is not None: - - if self._dest is not None: - best_available = self._obtain(req, source) - else: - best_available = None - - if best_available is None: - # That's a bit odd. There aren't any distros available. - # We should use the best one we have that meets the requirement. - logger.debug( - 'There are no distros available that meet %r.\n' - 'Using our best, %s.', - str(req), best_available) - return best_we_have, None - - if self._prefer_final: - if _final_version(best_available.parsed_version): - if _final_version(best_we_have.parsed_version): - if (best_we_have.parsed_version - < - best_available.parsed_version - ): - return None, best_available - else: - return None, best_available - else: - if (not _final_version(best_we_have.parsed_version) - and - (best_we_have.parsed_version - < - best_available.parsed_version - ) - ): - return None, best_available - else: - if (best_we_have.parsed_version - < - best_available.parsed_version - ): - return None, best_available - - logger.debug( - 'We have the best distribution that satisfies %r.', - str(req)) - return best_we_have, None - - def _load_dist(self, dist): - dists = pkg_resources.Environment( - dist.location, - python=_get_version(self._executable), - )[dist.project_name] - assert len(dists) == 1 - return dists[0] - - def _call_easy_install(self, spec, ws, dest, dist): - - tmp = tempfile.mkdtemp(dir=dest) - try: - path = setuptools_loc - - args = ('-c', self._easy_install_cmd, '-mUNxd', _safe_arg(tmp)) - if not self._has_broken_dash_S: - args = ('-S',) + args - if self._always_unzip: - args += ('-Z', ) - level = logger.getEffectiveLevel() - if level > 0: - args += ('-q', ) - elif level < 0: - args += ('-v', ) - - args += (_safe_arg(spec), ) - - if level <= logging.DEBUG: - logger.debug('Running easy_install:\n%s "%s"\npath=%s\n', - self._executable, '" "'.join(args), path) - - if is_jython: - extra_env = dict(os.environ, PYTHONPATH=path) - else: - args += (dict(os.environ, PYTHONPATH=path), ) - - sys.stdout.flush() # We want any pending output first - - if is_jython: - exit_code = subprocess.Popen( - [_safe_arg(self._executable)] + list(args), - env=extra_env).wait() - else: - exit_code = os.spawnle( - os.P_WAIT, self._executable, _safe_arg (self._executable), - *args) - - dists = [] - env = pkg_resources.Environment( - [tmp], - python=_get_version(self._executable), - ) - for project in env: - dists.extend(env[project]) - - if exit_code: - logger.error( - "An error occurred when trying to install %s. " - "Look above this message for any errors that " - "were output by easy_install.", - dist) - - if not dists: - raise zc.buildout.UserError("Couldn't install: %s" % dist) - - if len(dists) > 1: - logger.warn("Installing %s\n" - "caused multiple distributions to be installed:\n" - "%s\n", - dist, '\n'.join(map(str, dists))) - else: - d = dists[0] - if d.project_name != dist.project_name: - logger.warn("Installing %s\n" - "Caused installation of a distribution:\n" - "%s\n" - "with a different project name.", - dist, d) - if d.version != dist.version: - logger.warn("Installing %s\n" - "Caused installation of a distribution:\n" - "%s\n" - "with a different version.", - dist, d) - - result = [] - for d in dists: - newloc = os.path.join(dest, os.path.basename(d.location)) - if os.path.exists(newloc): - if os.path.isdir(newloc): - shutil.rmtree(newloc) - else: - os.remove(newloc) - os.rename(d.location, newloc) - - [d] = pkg_resources.Environment( - [newloc], - python=_get_version(self._executable), - )[d.project_name] - - result.append(d) - - return result - - finally: - shutil.rmtree(tmp) - - def _obtain(self, requirement, source=None): - # initialize out index for this project: - index = self._index - - if index.obtain(requirement) is None: - # Nothing is available. - return None - - # Filter the available dists for the requirement and source flag. If - # we are not supposed to include site-packages for the given egg, we - # also filter those out. Even if include_site_packages is False and so - # we have excluded site packages from the _env's paths (see - # Installer.__init__), we need to do the filtering here because an - # .egg-link, such as one for setuptools or zc.buildout installed by - # zc.buildout.buildout.Buildout.bootstrap, can indirectly include a - # path in our _site_packages. - dists = [dist for dist in index[requirement.project_name] if ( - dist in requirement and ( - dist.location not in self._site_packages or - self.allow_site_package_egg(dist.project_name)) - and ( - (not source) or - (dist.precedence == pkg_resources.SOURCE_DIST)) - ) - ] - - # If we prefer final dists, filter for final and use the - # result if it is non empty. - if self._prefer_final: - fdists = [dist for dist in dists - if _final_version(dist.parsed_version) - ] - if fdists: - # There are final dists, so only use those - dists = fdists - - # Now find the best one: - best = [] - bestv = () - for dist in dists: - distv = dist.parsed_version - if distv > bestv: - best = [dist] - bestv = distv - elif distv == bestv: - best.append(dist) - - if not best: - return None - - if len(best) == 1: - return best[0] - - if self._download_cache: - for dist in best: - if (realpath(os.path.dirname(dist.location)) - == - self._download_cache - ): - return dist - - best.sort() - return best[-1] - - def _fetch(self, dist, tmp, download_cache): - if (download_cache - and (realpath(os.path.dirname(dist.location)) == download_cache) - ): - return dist - - new_location = self._index.download(dist.location, tmp) - if (download_cache - and (realpath(new_location) == realpath(dist.location)) - and os.path.isfile(new_location) - ): - # setuptools avoids making extra copies, but we want to copy - # to the download cache - shutil.copy2(new_location, tmp) - new_location = os.path.join(tmp, os.path.basename(new_location)) - - return dist.clone(location=new_location) - - def _get_dist(self, requirement, ws, always_unzip): - - __doing__ = 'Getting distribution for %r.', str(requirement) - - # Maybe an existing dist is already the best dist that satisfies the - # requirement - dist, avail = self._satisfied(requirement) - - if dist is None: - if self._dest is not None: - logger.info(*__doing__) - - # Retrieve the dist: - if avail is None: - raise MissingDistribution(requirement, ws) - - # We may overwrite distributions, so clear importer - # cache. - sys.path_importer_cache.clear() - - tmp = self._download_cache - if tmp is None: - tmp = tempfile.mkdtemp('get_dist') - - try: - dist = self._fetch(avail, tmp, self._download_cache) - - if dist is None: - raise zc.buildout.UserError( - "Couldn't download distribution %s." % avail) - - if dist.precedence == pkg_resources.EGG_DIST: - # It's already an egg, just fetch it into the dest - - newloc = os.path.join( - self._dest, os.path.basename(dist.location)) - - if os.path.isdir(dist.location): - # we got a directory. It must have been - # obtained locally. Just copy it. - shutil.copytree(dist.location, newloc) - else: - - if self._always_unzip: - should_unzip = True - else: - metadata = pkg_resources.EggMetadata( - zipimport.zipimporter(dist.location) - ) - should_unzip = ( - metadata.has_metadata('not-zip-safe') - or - not metadata.has_metadata('zip-safe') - ) - - if should_unzip: - setuptools.archive_util.unpack_archive( - dist.location, newloc) - else: - shutil.copyfile(dist.location, newloc) - - redo_pyc(newloc) - - # Getting the dist from the environment causes the - # distribution meta data to be read. Cloning isn't - # good enough. - dists = pkg_resources.Environment( - [newloc], - python=_get_version(self._executable), - )[dist.project_name] - else: - # It's some other kind of dist. We'll let easy_install - # deal with it: - dists = self._call_easy_install( - dist.location, ws, self._dest, dist) - for dist in dists: - redo_pyc(dist.location) - - finally: - if tmp != self._download_cache: - shutil.rmtree(tmp) - - self._env.scan([self._dest]) - dist = self._env.best_match(requirement, ws) - logger.info("Got %s.", dist) - - else: - dists = [dist] - - for dist in dists: - if (dist.has_metadata('dependency_links.txt') - and not self._install_from_cache - and self._use_dependency_links - ): - for link in dist.get_metadata_lines('dependency_links.txt'): - link = link.strip() - if link not in self._links: - logger.debug('Adding find link %r from %s', link, dist) - self._links.append(link) - self._index = _get_index(self._executable, - self._index_url, self._links, - self._allow_hosts, self._path) - - for dist in dists: - # Check whether we picked a version and, if we did, report it: - if not ( - dist.precedence == pkg_resources.DEVELOP_DIST - or - (len(requirement.specs) == 1 - and - requirement.specs[0][0] == '==') - ): - logger.debug('Picked: %s = %s', - dist.project_name, dist.version) - if not self._allow_picked_versions: - raise zc.buildout.UserError( - 'Picked: %s = %s' % (dist.project_name, dist.version) - ) - - return dists - - def _maybe_add_setuptools(self, ws, dist): - if dist.has_metadata('namespace_packages.txt'): - for r in dist.requires(): - if r.project_name in ('setuptools', 'distribute'): - break - else: - # We have a namespace package but no requirement for setuptools - if dist.precedence == pkg_resources.DEVELOP_DIST: - logger.warn( - "Develop distribution: %s\n" - "uses namespace packages but the distribution " - "does not require setuptools.", - dist) - requirement = self._constrain( - pkg_resources.Requirement.parse('setuptools') - ) - if ws.find(requirement) is None: - for dist in self._get_dist(requirement, ws, False): - ws.add(dist) - - - def _constrain(self, requirement): - if is_distribute and requirement.key == 'setuptools': - requirement = pkg_resources.Requirement.parse('distribute') - version = self._versions.get(requirement.project_name) - if version: - if version not in requirement: - logger.error("The version, %s, is not consistent with the " - "requirement, %r.", version, str(requirement)) - raise IncompatibleVersionError("Bad version", version) - - requirement = pkg_resources.Requirement.parse( - "%s[%s] ==%s" % (requirement.project_name, - ','.join(requirement.extras), - version)) - - return requirement - - def install(self, specs, working_set=None): - - logger.debug('Installing %s.', repr(specs)[1:-1]) - - path = self._path - destination = self._dest - if destination is not None and destination not in path: - path.insert(0, destination) - - requirements = [self._constrain(pkg_resources.Requirement.parse(spec)) - for spec in specs] - - - - if working_set is None: - ws = pkg_resources.WorkingSet([]) - else: - ws = working_set - - for requirement in requirements: - for dist in self._get_dist(requirement, ws, self._always_unzip): - ws.add(dist) - self._maybe_add_setuptools(ws, dist) - - # OK, we have the requested distributions and they're in the working - # set, but they may have unmet requirements. We'll resolve these - # requirements. This is code modified from - # pkg_resources.WorkingSet.resolve. We can't reuse that code directly - # because we have to constrain our requirements (see - # versions_section_ignored_for_dependency_in_favor_of_site_packages in - # zc.buildout.tests). - requirements.reverse() # Set up the stack. - processed = {} # This is a set of processed requirements. - best = {} # This is a mapping of key -> dist. - # Note that we don't use the existing environment, because we want - # to look for new eggs unless what we have is the best that - # matches the requirement. - env = pkg_resources.Environment(ws.entries) - while requirements: - # Process dependencies breadth-first. - req = self._constrain(requirements.pop(0)) - if req in processed: - # Ignore cyclic or redundant dependencies. - continue - dist = best.get(req.key) - if dist is None: - # Find the best distribution and add it to the map. - dist = ws.by_key.get(req.key) - if dist is None: - try: - dist = best[req.key] = env.best_match(req, ws) - except pkg_resources.VersionConflict, err: - raise VersionConflict(err, ws) - if dist is None or ( - dist.location in self._site_packages and not - self.allow_site_package_egg(dist.project_name)): - # If we didn't find a distribution in the - # environment, or what we found is from site - # packages and not allowed to be there, try - # again. - if destination: - logger.debug('Getting required %r', str(req)) - else: - logger.debug('Adding required %r', str(req)) - _log_requirement(ws, req) - for dist in self._get_dist(req, - ws, self._always_unzip): - ws.add(dist) - self._maybe_add_setuptools(ws, dist) - if dist not in req: - # Oops, the "best" so far conflicts with a dependency. - raise VersionConflict( - pkg_resources.VersionConflict(dist, req), ws) - requirements.extend(dist.requires(req.extras)[::-1]) - processed[req] = True - if dist.location in self._site_packages: - logger.debug('Egg from site-packages: %s', dist) - return ws - - def build(self, spec, build_ext): - - requirement = self._constrain(pkg_resources.Requirement.parse(spec)) - - dist, avail = self._satisfied(requirement, 1) - if dist is not None: - return [dist.location] - - # Retrieve the dist: - if avail is None: - raise zc.buildout.UserError( - "Couldn't find a source distribution for %r." - % str(requirement)) - - logger.debug('Building %r', spec) - - tmp = self._download_cache - if tmp is None: - tmp = tempfile.mkdtemp('get_dist') - - try: - dist = self._fetch(avail, tmp, self._download_cache) - - build_tmp = tempfile.mkdtemp('build') - try: - setuptools.archive_util.unpack_archive(dist.location, - build_tmp) - if os.path.exists(os.path.join(build_tmp, 'setup.py')): - base = build_tmp - else: - setups = glob.glob( - os.path.join(build_tmp, '*', 'setup.py')) - if not setups: - raise distutils.errors.DistutilsError( - "Couldn't find a setup script in %s" - % os.path.basename(dist.location) - ) - if len(setups) > 1: - raise distutils.errors.DistutilsError( - "Multiple setup scripts in %s" - % os.path.basename(dist.location) - ) - base = os.path.dirname(setups[0]) - - setup_cfg = os.path.join(base, 'setup.cfg') - if not os.path.exists(setup_cfg): - f = open(setup_cfg, 'w') - f.close() - setuptools.command.setopt.edit_config( - setup_cfg, dict(build_ext=build_ext)) - - dists = self._call_easy_install( - base, pkg_resources.WorkingSet(), - self._dest, dist) - - for dist in dists: - redo_pyc(dist.location) - - return [dist.location for dist in dists] - finally: - shutil.rmtree(build_tmp) - - finally: - if tmp != self._download_cache: - shutil.rmtree(tmp) - -def default_versions(versions=None): - old = Installer._versions - if versions is not None: - Installer._versions = versions - return old - -def download_cache(path=-1): - old = Installer._download_cache - if path != -1: - if path: - path = realpath(path) - Installer._download_cache = path - return old - -def install_from_cache(setting=None): - old = Installer._install_from_cache - if setting is not None: - Installer._install_from_cache = bool(setting) - return old - -def prefer_final(setting=None): - old = Installer._prefer_final - if setting is not None: - Installer._prefer_final = bool(setting) - return old - -def include_site_packages(setting=None): - old = Installer._include_site_packages - if setting is not None: - Installer._include_site_packages = bool(setting) - return old - -def allowed_eggs_from_site_packages(setting=None): - old = Installer._allowed_eggs_from_site_packages - if setting is not None: - Installer._allowed_eggs_from_site_packages = tuple(setting) - return old - -def use_dependency_links(setting=None): - old = Installer._use_dependency_links - if setting is not None: - Installer._use_dependency_links = bool(setting) - return old - -def allow_picked_versions(setting=None): - old = Installer._allow_picked_versions - if setting is not None: - Installer._allow_picked_versions = bool(setting) - return old - -def always_unzip(setting=None): - old = Installer._always_unzip - if setting is not None: - Installer._always_unzip = bool(setting) - return old - -def install(specs, dest, - links=(), index=None, - executable=sys.executable, always_unzip=None, - path=None, working_set=None, newest=True, versions=None, - use_dependency_links=None, allow_hosts=('*',), - include_site_packages=None, allowed_eggs_from_site_packages=None, - prefer_final=None): - installer = Installer( - dest, links, index, executable, always_unzip, path, newest, - versions, use_dependency_links, allow_hosts=allow_hosts, - include_site_packages=include_site_packages, - allowed_eggs_from_site_packages=allowed_eggs_from_site_packages, - prefer_final=prefer_final) - return installer.install(specs, working_set) - - -def build(spec, dest, build_ext, - links=(), index=None, - executable=sys.executable, - path=None, newest=True, versions=None, allow_hosts=('*',), - include_site_packages=None, allowed_eggs_from_site_packages=None): - installer = Installer( - dest, links, index, executable, True, path, newest, versions, - allow_hosts=allow_hosts, - include_site_packages=include_site_packages, - allowed_eggs_from_site_packages=allowed_eggs_from_site_packages) - return installer.build(spec, build_ext) - - - -def _rm(*paths): - for path in paths: - if os.path.isdir(path): - shutil.rmtree(path) - elif os.path.exists(path): - os.remove(path) - -def _copyeggs(src, dest, suffix, undo): - result = [] - undo.append(lambda : _rm(*result)) - for name in os.listdir(src): - if name.endswith(suffix): - new = os.path.join(dest, name) - _rm(new) - os.rename(os.path.join(src, name), new) - result.append(new) - - assert len(result) == 1, str(result) - undo.pop() - - return result[0] - -def develop(setup, dest, - build_ext=None, - executable=sys.executable): - - if os.path.isdir(setup): - directory = setup - setup = os.path.join(directory, 'setup.py') - else: - directory = os.path.dirname(setup) - - undo = [] - try: - if build_ext: - setup_cfg = os.path.join(directory, 'setup.cfg') - if os.path.exists(setup_cfg): - os.rename(setup_cfg, setup_cfg+'-develop-aside') - def restore_old_setup(): - if os.path.exists(setup_cfg): - os.remove(setup_cfg) - os.rename(setup_cfg+'-develop-aside', setup_cfg) - undo.append(restore_old_setup) - else: - open(setup_cfg, 'w') - undo.append(lambda: os.remove(setup_cfg)) - setuptools.command.setopt.edit_config( - setup_cfg, dict(build_ext=build_ext)) - - fd, tsetup = tempfile.mkstemp() - undo.append(lambda: os.remove(tsetup)) - undo.append(lambda: os.close(fd)) - - os.write(fd, runsetup_template % dict( - setuptools=setuptools_loc, - setupdir=directory, - setup=setup, - __file__ = setup, - )) - - tmp3 = tempfile.mkdtemp('build', dir=dest) - undo.append(lambda : shutil.rmtree(tmp3)) - - args = [ - zc.buildout.easy_install._safe_arg(tsetup), - '-q', 'develop', '-mxN', - '-d', _safe_arg(tmp3), - ] - - log_level = logger.getEffectiveLevel() - if log_level <= 0: - if log_level == 0: - del args[1] - else: - args[1] == '-v' - if log_level < logging.DEBUG: - logger.debug("in: %r\n%s", directory, ' '.join(args)) - - if is_jython: - assert subprocess.Popen([_safe_arg(executable)] + args).wait() == 0 - else: - assert os.spawnl(os.P_WAIT, executable, _safe_arg(executable), - *args) == 0 - - return _copyeggs(tmp3, dest, '.egg-link', undo) - - finally: - undo.reverse() - [f() for f in undo] - -def working_set(specs, executable, path, include_site_packages=None, - allowed_eggs_from_site_packages=None, prefer_final=None): - return install( - specs, None, executable=executable, path=path, - include_site_packages=include_site_packages, - allowed_eggs_from_site_packages=allowed_eggs_from_site_packages, - prefer_final=prefer_final) - -############################################################################ -# Script generation functions - -def scripts( - reqs, working_set, executable, dest, - scripts=None, - extra_paths=(), - arguments='', - interpreter=None, - initialization='', - relative_paths=False, - ): - """Generate scripts and/or an interpreter. - - See sitepackage_safe_scripts for a version that can be used with a Python - that has code installed in site-packages. It has more options and a - different approach. - """ - path = _get_path(working_set, extra_paths) - if initialization: - initialization = '\n'+initialization+'\n' - generated = _generate_scripts( - reqs, working_set, dest, path, scripts, relative_paths, - initialization, executable, arguments) - if interpreter: - sname = os.path.join(dest, interpreter) - spath, rpsetup = _relative_path_and_setup(sname, path, relative_paths) - generated.extend( - _pyscript(spath, sname, executable, rpsetup)) - return generated - -# We need to give an alternate name to the ``scripts`` function so that it -# can be referenced within sitepackage_safe_scripts, which uses ``scripts`` -# as an argument name. -_original_scripts_function = scripts - -def sitepackage_safe_scripts( - dest, working_set, executable, site_py_dest, - reqs=(), - scripts=None, - interpreter=None, - extra_paths=(), - initialization='', - include_site_packages=False, - exec_sitecustomize=False, - relative_paths=False, - script_arguments='', - script_initialization='', - ): - """Generate scripts and/or an interpreter from a system Python. - - This accomplishes the same job as the ``scripts`` function, above, - but it does so in an alternative way that allows safely including - Python site packages, if desired, and choosing to execute the Python's - sitecustomize. - """ - if _has_broken_dash_S(executable): - if not include_site_packages: - warnings.warn(BROKEN_DASH_S_WARNING) - return _original_scripts_function( - reqs, working_set, executable, dest, scripts, extra_paths, - script_arguments, interpreter, initialization, relative_paths) - generated = [] - generated.append(_generate_sitecustomize( - site_py_dest, executable, initialization, exec_sitecustomize)) - generated.append(_generate_site( - site_py_dest, working_set, executable, extra_paths, - include_site_packages, relative_paths)) - script_initialization = _script_initialization_template % dict( - site_py_dest=site_py_dest, - script_initialization=script_initialization) - if not script_initialization.endswith('\n'): - script_initialization += '\n' - generated.extend(_generate_scripts( - reqs, working_set, dest, [site_py_dest], scripts, relative_paths, - script_initialization, executable, script_arguments, block_site=True)) - if interpreter: - generated.extend(_generate_interpreter( - interpreter, dest, executable, site_py_dest, relative_paths)) - return generated - -_script_initialization_template = ''' -import os -path = sys.path[0] -if os.environ.get('PYTHONPATH'): - path = os.pathsep.join([path, os.environ['PYTHONPATH']]) -os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '') -os.environ['PYTHONPATH'] = path -import site # imports custom buildout-generated site.py -%(script_initialization)s''' - -# Utilities for the script generation functions. - -# These are shared by both ``scripts`` and ``sitepackage_safe_scripts`` - -def _get_path(working_set, extra_paths=()): - """Given working set and extra paths, return a normalized path list.""" - path = [dist.location for dist in working_set] - path.extend(extra_paths) - return map(realpath, path) - -def _generate_scripts(reqs, working_set, dest, path, scripts, relative_paths, - initialization, executable, arguments, - block_site=False): - """Generate scripts for the given requirements. - - - reqs is an iterable of string requirements or entry points. - - The requirements must be findable in the given working_set. - - The dest is the directory in which the scripts should be created. - - The path is a list of paths that should be added to sys.path. - - The scripts is an optional dictionary. If included, the keys should be - the names of the scripts that should be created, as identified in their - entry points; and the values should be the name the script should - actually be created with. - - relative_paths, if given, should be the path that is the root of the - buildout (the common path that should be the root of what is relative). - """ - if isinstance(reqs, str): - raise TypeError('Expected iterable of requirements or entry points,' - ' got string.') - generated = [] - entry_points = [] - for req in reqs: - if isinstance(req, str): - req = pkg_resources.Requirement.parse(req) - dist = working_set.find(req) - for name in pkg_resources.get_entry_map(dist, 'console_scripts'): - entry_point = dist.get_entry_info('console_scripts', name) - entry_points.append( - (name, entry_point.module_name, - '.'.join(entry_point.attrs)) - ) - else: - entry_points.append(req) - for name, module_name, attrs in entry_points: - if scripts is not None: - sname = scripts.get(name) - if sname is None: - continue - else: - sname = name - sname = os.path.join(dest, sname) - spath, rpsetup = _relative_path_and_setup(sname, path, relative_paths) - generated.extend( - _script(sname, executable, rpsetup, spath, initialization, - module_name, attrs, arguments, block_site=block_site)) - return generated - -def _relative_path_and_setup(sname, path, - relative_paths=False, indent_level=1, - omit_os_import=False): - """Return a string of code of paths and of setup if appropriate. - - - sname is the full path to the script name to be created. - - path is the list of paths to be added to sys.path. - - relative_paths, if given, should be the path that is the root of the - buildout (the common path that should be the root of what is relative). - - indent_level is the number of four-space indents that the path should - insert before each element of the path. - """ - if relative_paths: - relative_paths = os.path.normcase(relative_paths) - sname = os.path.normcase(os.path.abspath(sname)) - spath = _format_paths( - [_relativitize(os.path.normcase(path_item), sname, relative_paths) - for path_item in path], indent_level=indent_level) - rpsetup = relative_paths_setup - if not omit_os_import: - rpsetup = '\n\nimport os\n' + rpsetup - for i in range(_relative_depth(relative_paths, sname)): - rpsetup += "\nbase = os.path.dirname(base)" - else: - spath = _format_paths((repr(p) for p in path), - indent_level=indent_level) - rpsetup = '' - return spath, rpsetup - -def _relative_depth(common, path): - """Return number of dirs separating ``path`` from ancestor, ``common``. - - For instance, if path is /foo/bar/baz/bing, and common is /foo, this will - return 2--in UNIX, the number of ".." to get from bing's directory - to foo. - - This is a helper for _relative_path_and_setup. - """ - n = 0 - while 1: - dirname = os.path.dirname(path) - if dirname == path: - raise AssertionError("dirname of %s is the same" % dirname) - if dirname == common: - break - n += 1 - path = dirname - return n - -def _relative_path(common, path): - """Return the relative path from ``common`` to ``path``. - - This is a helper for _relativitize, which is a helper to - _relative_path_and_setup. - """ - r = [] - while 1: - dirname, basename = os.path.split(path) - r.append(basename) - if dirname == common: - break - if dirname == path: - raise AssertionError("dirname of %s is the same" % dirname) - path = dirname - r.reverse() - return os.path.join(*r) - -def _relativitize(path, script, relative_paths): - """Return a code string for the given path. - - Path is relative to the base path ``relative_paths``if the common prefix - between ``path`` and ``script`` starts with ``relative_paths``. - """ - if path == script: - raise AssertionError("path == script") - common = os.path.dirname(os.path.commonprefix([path, script])) - if (common == relative_paths or - common.startswith(os.path.join(relative_paths, '')) - ): - return "join(base, %r)" % _relative_path(common, path) - else: - return repr(path) - -relative_paths_setup = """ -join = os.path.join -base = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))""" - -def _write_script(full_name, contents, logged_type): - """Write contents of script in full_name, logging the action. - - The only tricky bit in this function is that it supports Windows by - creating exe files using a pkg_resources helper. - """ - generated = [] - script_name = full_name - if is_win32: - script_name += '-script.py' - # Generate exe file and give the script a magic name. - exe = full_name + '.exe' - new_data = pkg_resources.resource_string('setuptools', 'cli.exe') - if not os.path.exists(exe) or (open(exe, 'rb').read() != new_data): - # Only write it if it's different. - open(exe, 'wb').write(new_data) - generated.append(exe) - changed = not (os.path.exists(script_name) and - open(script_name).read() == contents) - if changed: - open(script_name, 'w').write(contents) - try: - os.chmod(script_name, 0755) - except (AttributeError, os.error): - pass - logger.info("Generated %s %r.", logged_type, full_name) - generated.append(script_name) - return generated - -def _format_paths(paths, indent_level=1): - """Format paths for inclusion in a script.""" - separator = ',\n' + indent_level * ' ' - return separator.join(paths) - -def _script(dest, executable, relative_paths_setup, path, initialization, - module_name, attrs, arguments, block_site=False): - if block_site: - dash_S = ' -S' - else: - dash_S = '' - contents = script_template % dict( - python=_safe_arg(executable), - dash_S=dash_S, - path=path, - module_name=module_name, - attrs=attrs, - arguments=arguments, - initialization=initialization, - relative_paths_setup=relative_paths_setup, - ) - return _write_script(dest, contents, 'script') - -if is_jython and jython_os_name == 'linux': - script_header = '#!/usr/bin/env %(python)s%(dash_S)s' -else: - script_header = '#!%(python)s%(dash_S)s' - -sys_path_template = '''\ -import sys -sys.path[0:0] = [ - %s, - ] -''' - -script_template = script_header + '''\ -%(relative_paths_setup)s - -import sys -sys.path[0:0] = [ - %(path)s, - ] - -%(initialization)s -import %(module_name)s - -if __name__ == '__main__': - %(module_name)s.%(attrs)s(%(arguments)s) -''' - -# These are used only by the older ``scripts`` function. - -def _pyscript(path, dest, executable, rsetup): - contents = py_script_template % dict( - python=_safe_arg(executable), - dash_S='', - path=path, - relative_paths_setup=rsetup, - ) - return _write_script(dest, contents, 'interpreter') - -py_script_template = script_header + '''\ -%(relative_paths_setup)s - -import sys - -sys.path[0:0] = [ - %(path)s, - ] - -_interactive = True -if len(sys.argv) > 1: - _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:') - _interactive = False - for (_opt, _val) in _options: - if _opt == '-i': - _interactive = True - elif _opt == '-c': - exec _val - elif _opt == '-m': - sys.argv[1:] = _args - _args = [] - __import__("runpy").run_module( - _val, {}, "__main__", alter_sys=True) - - if _args: - sys.argv[:] = _args - __file__ = _args[0] - del _options, _args - execfile(__file__) - -if _interactive: - del _interactive - __import__("code").interact(banner="", local=globals()) -''' - -# These are used only by the newer ``sitepackage_safe_scripts`` function. - -def _get_module_file(executable, name, silent=False): - """Return a module's file path. - - - executable is a path to the desired Python executable. - - name is the name of the (pure, not C) Python module. - """ - cmd = [executable, "-Sc", - "import imp; " - "fp, path, desc = imp.find_module(%r); " - "fp.close(); " - "print path" % (name,)] - env = os.environ.copy() - # We need to make sure that PYTHONPATH, which will often be set to - # include a custom buildout-generated site.py, is not set, or else - # we will not get an accurate value for the "real" site.py and - # sitecustomize.py. - env.pop('PYTHONPATH', None) - _proc = subprocess.Popen( - cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env) - stdout, stderr = _proc.communicate(); - if _proc.returncode: - if not silent: - logger.info( - 'Could not find file for module %s:\n%s', name, stderr) - return None - # else: ... - res = stdout.strip() - if res.endswith('.pyc') or res.endswith('.pyo'): - raise RuntimeError('Cannot find uncompiled version of %s' % (name,)) - if not os.path.exists(res): - raise RuntimeError( - 'File does not exist for module %s:\n%s' % (name, res)) - return res - -def _generate_sitecustomize(dest, executable, initialization='', - exec_sitecustomize=False): - """Write a sitecustomize file with optional custom initialization. - - The created script will execute the underlying Python's - sitecustomize if exec_sitecustomize is True. - """ - sitecustomize_path = os.path.join(dest, 'sitecustomize.py') - sitecustomize = open(sitecustomize_path, 'w') - if initialization: - sitecustomize.write(initialization + '\n') - if exec_sitecustomize: - real_sitecustomize_path = _get_module_file( - executable, 'sitecustomize', silent=True) - if real_sitecustomize_path: - real_sitecustomize = open(real_sitecustomize_path, 'r') - sitecustomize.write( - '\n# The following is from\n# %s\n' % - (real_sitecustomize_path,)) - sitecustomize.write(real_sitecustomize.read()) - real_sitecustomize.close() - sitecustomize.close() - return sitecustomize_path - -def _generate_site(dest, working_set, executable, extra_paths=(), - include_site_packages=False, relative_paths=False): - """Write a site.py file with eggs from working_set. - - extra_paths will be added to the path. If include_site_packages is True, - paths from the underlying Python will be added. - """ - path = _get_path(working_set, extra_paths) - site_path = os.path.join(dest, 'site.py') - original_path_setup = preamble = '' - if include_site_packages: - stdlib, site_paths = _get_system_paths(executable) - # We want to make sure that paths from site-packages, such as those - # allowed by allowed_eggs_from_site_packages, always come last, or - # else site-packages paths may include packages that mask the eggs we - # really want. - path = [p for p in path if p not in site_paths] - # Now we set up the code we need. - original_path_setup = original_path_snippet % ( - _format_paths((repr(p) for p in site_paths), 2),) - distribution = working_set.find( - pkg_resources.Requirement.parse('setuptools')) - if distribution is not None: - # We need to worry about namespace packages. - if relative_paths: - location = _relativitize( - distribution.location, - os.path.normcase(os.path.abspath(site_path)), - relative_paths) - else: - location = repr(distribution.location) - preamble = namespace_include_site_packages_setup % (location,) - original_path_setup = ( - addsitedir_namespace_originalpackages_snippet + - original_path_setup) - else: - preamble = '\n setuptools_path = None' - egg_path_string, relative_preamble = _relative_path_and_setup( - site_path, path, relative_paths, indent_level=2, omit_os_import=True) - if relative_preamble: - relative_preamble = '\n'.join( - [(line and ' %s' % (line,) or line) - for line in relative_preamble.split('\n')]) - preamble = relative_preamble + preamble - addsitepackages_marker = 'def addsitepackages(' - enableusersite_marker = 'ENABLE_USER_SITE = ' - successful_rewrite = False - real_site_path = _get_module_file(executable, 'site') - real_site = open(real_site_path, 'r') - site = open(site_path, 'w') - try: - for line in real_site.readlines(): - if line.startswith(enableusersite_marker): - site.write(enableusersite_marker) - site.write('False # buildout does not support user sites.\n') - elif line.startswith(addsitepackages_marker): - site.write(addsitepackages_script % ( - preamble, egg_path_string, original_path_setup)) - site.write(line[len(addsitepackages_marker):]) - successful_rewrite = True - else: - site.write(line) - finally: - site.close() - real_site.close() - if not successful_rewrite: - raise RuntimeError( - 'Buildout did not successfully rewrite %s to %s' % - (real_site_path, site_path)) - return site_path - -namespace_include_site_packages_setup = ''' - setuptools_path = %s - sys.path.append(setuptools_path) - known_paths.add(os.path.normcase(setuptools_path)) - import pkg_resources''' - -addsitedir_namespace_originalpackages_snippet = ''' - pkg_resources.working_set.add_entry(sitedir)''' - -original_path_snippet = ''' - sys.__egginsert = len(buildout_paths) # Support distribute. - original_paths = [ - %s - ] - for path in original_paths: - if path == setuptools_path or path not in known_paths: - addsitedir(path, known_paths)''' - -addsitepackages_script = '''\ -def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - - See original_addsitepackages, below, for the original version."""%s - buildout_paths = [ - %s - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase)%s - return known_paths - -def original_addsitepackages(''' - -def _generate_interpreter(name, dest, executable, site_py_dest, - relative_paths=False): - """Write an interpreter script, using the site.py approach.""" - full_name = os.path.join(dest, name) - site_py_dest_string, rpsetup = _relative_path_and_setup( - full_name, [site_py_dest], relative_paths, omit_os_import=True) - if rpsetup: - rpsetup += "\n" - if sys.platform == 'win32': - windows_import = '\nimport subprocess' - # os.exec* is a mess on Windows, particularly if the path - # to the executable has spaces and the Python is using MSVCRT. - # The standard fix is to surround the executable's path with quotes, - # but that has been unreliable in testing. - # - # Here's a demonstration of the problem. Given a Python - # compiled with a MSVCRT-based compiler, such as the free Visual - # C++ 2008 Express Edition, and an executable path with spaces - # in it such as the below, we see the following. - # - # >>> import os - # >>> p0 = 'C:\\Documents and Settings\\Administrator\\My Documents\\Downloads\\Python-2.6.4\\PCbuild\\python.exe' - # >>> os.path.exists(p0) - # True - # >>> os.execv(p0, []) - # Traceback (most recent call last): - # File "<stdin>", line 1, in <module> - # OSError: [Errno 22] Invalid argument - # - # That seems like a standard problem. The standard solution is - # to quote the path (see, for instance - # http://bugs.python.org/issue436259). However, this solution, - # and other variations, fail: - # - # >>> p1 = '"C:\\Documents and Settings\\Administrator\\My Documents\\Downloads\\Python-2.6.4\\PCbuild\\python.exe"' - # >>> os.execv(p1, []) - # Traceback (most recent call last): - # File "<stdin>", line 1, in <module> - # OSError: [Errno 22] Invalid argument - # - # We simply use subprocess instead, since it handles everything - # nicely, and the transparency of exec* (that is, not running, - # perhaps unexpectedly, in a subprocess) is arguably not a - # necessity, at least for many use cases. - execute = 'subprocess.call(argv, env=environ)' - else: - windows_import = '' - execute = 'os.execve(sys.executable, argv, environ)' - contents = interpreter_template % dict( - python=_safe_arg(executable), - dash_S=' -S', - site_dest=site_py_dest_string, - relative_paths_setup=rpsetup, - windows_import=windows_import, - execute=execute, - ) - return _write_script(full_name, contents, 'interpreter') - -interpreter_template = script_header + ''' -import os -import sys%(windows_import)s -%(relative_paths_setup)s -argv = [sys.executable] + sys.argv[1:] -environ = os.environ.copy() -path = %(site_dest)s -if environ.get('PYTHONPATH'): - path = os.pathsep.join([path, environ['PYTHONPATH']]) -environ['PYTHONPATH'] = path -%(execute)s -''' - -# End of script generation code. -############################################################################ - -runsetup_template = """ -import sys -sys.path.insert(0, %(setupdir)r) -sys.path.insert(0, %(setuptools)r) -import os, setuptools - -__file__ = %(__file__)r - -os.chdir(%(setupdir)r) -sys.argv[0] = %(setup)r -execfile(%(setup)r) -""" - - -class VersionConflict(zc.buildout.UserError): - - def __init__(self, err, ws): - ws = list(ws) - ws.sort() - self.err, self.ws = err, ws - - def __str__(self): - existing_dist, req = self.err - result = ["There is a version conflict.", - "We already have: %s" % existing_dist, - ] - for dist in self.ws: - if req in dist.requires(): - result.append("but %s requires %r." % (dist, str(req))) - return '\n'.join(result) - - -class MissingDistribution(zc.buildout.UserError): - - def __init__(self, req, ws): - ws = list(ws) - ws.sort() - self.data = req, ws - - def __str__(self): - req, ws = self.data - return "Couldn't find a distribution for %r." % str(req) - -def _log_requirement(ws, req): - ws = list(ws) - ws.sort() - for dist in ws: - if req in dist.requires(): - logger.debug(" required by %s." % dist) - -def _fix_file_links(links): - for link in links: - if link.startswith('file://') and link[-1] != '/': - if os.path.isdir(link[7:]): - # work around excessive restriction in setuptools: - link += '/' - yield link - -_final_parts = '*final-', '*final' -def _final_version(parsed_version): - for part in parsed_version: - if (part[:1] == '*') and (part not in _final_parts): - return False - return True - -def redo_pyc(egg): - if not os.path.isdir(egg): - return - for dirpath, dirnames, filenames in os.walk(egg): - for filename in filenames: - if not filename.endswith('.py'): - continue - filepath = os.path.join(dirpath, filename) - if not (os.path.exists(filepath+'c') - or os.path.exists(filepath+'o')): - # If it wasn't compiled, it may not be compilable - continue - - # OK, it looks like we should try to compile. - - # Remove old files. - for suffix in 'co': - if os.path.exists(filepath+suffix): - os.remove(filepath+suffix) - - # Compile under current optimization - try: - py_compile.compile(filepath) - except py_compile.PyCompileError: - logger.warning("Couldn't compile %s", filepath) - else: - # Recompile under other optimization. :) - args = [_safe_arg(sys.executable)] - if __debug__: - args.append('-O') - args.extend(['-m', 'py_compile', _safe_arg(filepath)]) - - if is_jython: - subprocess.call([sys.executable, args]) - else: - os.spawnv(os.P_WAIT, sys.executable, args) - diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.txt deleted file mode 100644 index ec654cd..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/easy_install.txt +++ /dev/null @@ -1,1985 +0,0 @@ -Python API for egg and script installation -========================================== - -The easy_install module provides some functions to provide support for -egg and script installation. It provides functionality at the python -level that is similar to easy_install, with a few exceptions: - -- By default, we look for new packages *and* the packages that - they depend on. This is somewhat like (and uses) the --upgrade - option of easy_install, except that we also upgrade required - packages. - -- If the highest-revision package satisfying a specification is - already present, then we don't try to get another one. This saves a - lot of search time in the common case that packages are pegged to - specific versions. - -- If there is a develop egg that satisfies a requirement, we don't - look for additional distributions. We always give preference to - develop eggs. - -- Distutils options for building extensions can be passed. - -Distribution installation -------------------------- - -The easy_install module provides a function, install, for installing one -or more packages and their dependencies. The install function takes 2 -positional arguments: - -- An iterable of setuptools requirement strings for the distributions - to be installed, and - -- A destination directory to install to and to satisfy requirements - from. The destination directory can be None, in which case, no new - distributions are downloaded and there will be an error if the - needed distributions can't be found among those already installed. - -It supports a number of optional keyword arguments: - -links - A sequence of URLs, file names, or directories to look for - links to distributions. - -index - The URL of an index server, or almost any other valid URL. :) - - If not specified, the Python Package Index, - http://pypi.python.org/simple/, is used. You can specify an - alternate index with this option. If you use the links option and - if the links point to the needed distributions, then the index can - be anything and will be largely ignored. In the examples, here, - we'll just point to an empty directory on our link server. This - will make our examples run a little bit faster. - -executable - A path to a Python executable. Distributions will be installed - using this executable and will be for the matching Python version. - -path - A list of additional directories to search for locally-installed - distributions. - -always_unzip - A flag indicating that newly-downloaded distributions should be - directories even if they could be installed as zip files. - -working_set - An existing working set to be augmented with additional - distributions, if necessary to satisfy requirements. This allows - you to call install multiple times, if necessary, to gather - multiple sets of requirements. - -newest - A boolean value indicating whether to search for new distributions - when already-installed distributions meet the requirement. When - this is true, the default, and when the destination directory is - not None, then the install function will search for the newest - distributions that satisfy the requirements. - -versions - A dictionary mapping project names to version numbers to be used - when selecting distributions. This can be used to specify a set of - distribution versions independent of other requirements. - -use_dependency_links - A flag indicating whether to search for dependencies using the - setup dependency_links metadata or not. If true, links are searched - for using dependency_links in preference to other - locations. Defaults to true. - -include_site_packages - A flag indicating whether Python's non-standard-library packages should - be available for finding dependencies. Defaults to true. - - Paths outside of Python's standard library--or more precisely, those that - are not included when Python is started with the -S argument--are loosely - referred to as "site-packages" here. - -relative_paths - Adjust egg paths so they are relative to the script path. This - allows scripts to work when scripts and eggs are moved, as long as - they are both moved in the same way. - -The install method returns a working set containing the distributions -needed to meet the given requirements. - -We have a link server that has a number of eggs: - - >>> print get(link_server), - <html><body> - <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br> - <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> - <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> - <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> - <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> - <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> - <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> - <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> - <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> - <a href="index/">index/</a><br> - <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br> - </body></html> - -Let's make a directory and install the demo egg to it, using the demo: - - >>> dest = tmpdir('sample-install') - >>> import zc.buildout.easy_install - >>> ws = zc.buildout.easy_install.install( - ... ['demo==0.2'], dest, - ... links=[link_server], index=link_server+'index/') - -We requested version 0.2 of the demo distribution to be installed into -the destination server. We specified that we should search for links -on the link server and that we should use the (empty) link server -index directory as a package index. - -The working set contains the distributions we retrieved. - - >>> for dist in ws: - ... print dist - demo 0.2 - demoneeded 1.1 - -We got demoneeded because it was a dependency of demo. - -And the actual eggs were added to the eggs directory. - - >>> ls(dest) - - demo-0.2-py2.4.egg - - demoneeded-1.1-py2.4.egg - -If we remove the version restriction on demo, but specify a false -value for newest, no new distributions will be installed: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... newest=False) - >>> ls(dest) - - demo-0.2-py2.4.egg - - demoneeded-1.1-py2.4.egg - -If we leave off the newest option, we'll get an update for demo: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/') - >>> ls(dest) - - demo-0.2-py2.4.egg - - demo-0.3-py2.4.egg - - demoneeded-1.1-py2.4.egg - -Note that we didn't get the newest versions available. There were -release candidates for newer versions of both packages. By default, -final releases are preferred. We can change this behavior using the -prefer_final function: - - >>> zc.buildout.easy_install.prefer_final(False) - True - -The old setting is returned. - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/') - >>> for dist in ws: - ... print dist - demo 0.4c1 - demoneeded 1.2c1 - - >>> ls(dest) - - demo-0.2-py2.4.egg - - demo-0.3-py2.4.egg - - demo-0.4c1-py2.4.egg - - demoneeded-1.1-py2.4.egg - - demoneeded-1.2c1-py2.4.egg - -Let's put the setting back to the default. - - >>> zc.buildout.easy_install.prefer_final(True) - False - -We can supply additional distributions. We can also supply -specifications for distributions that would normally be found via -dependencies. We might do this to specify a specific version. - - >>> ws = zc.buildout.easy_install.install( - ... ['demo', 'other', 'demoneeded==1.0'], dest, - ... links=[link_server], index=link_server+'index/') - - >>> for dist in ws: - ... print dist - demo 0.3 - other 1.0 - demoneeded 1.0 - - >>> ls(dest) - - demo-0.2-py2.4.egg - - demo-0.3-py2.4.egg - - demo-0.4c1-py2.4.egg - - demoneeded-1.0-py2.4.egg - - demoneeded-1.1-py2.4.egg - - demoneeded-1.2c1-py2.4.egg - d other-1.0-py2.4.egg - -We can request that eggs be unzipped even if they are zip safe. This -can be useful when debugging. (Note that Distribute will unzip eggs by -default, so if you are using Distribute, most or all eggs will already be -unzipped without this flag.) - - >>> rmdir(dest) - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... always_unzip=True) - - >>> ls(dest) - d demo-0.3-py2.4.egg - d demoneeded-1.1-py2.4.egg - - >>> rmdir(dest) - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... always_unzip=False) - - >>> ls(dest) - - demo-0.3-py2.4.egg - - demoneeded-1.1-py2.4.egg - -We can also set a default by calling the always_unzip function: - - >>> zc.buildout.easy_install.always_unzip(True) - False - -The old default is returned: - - >>> rmdir(dest) - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/') - - >>> ls(dest) - d demo-0.3-py2.4.egg - d demoneeded-1.1-py2.4.egg - - - >>> zc.buildout.easy_install.always_unzip(False) - True - - >>> rmdir(dest) - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/') - - >>> ls(dest) - - demo-0.3-py2.4.egg - - demoneeded-1.1-py2.4.egg - - >>> rmdir(dest) - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... always_unzip=True) - - >>> ls(dest) - d demo-0.3-py2.4.egg - d demoneeded-1.1-py2.4.egg - -Specifying version information independent of requirements ----------------------------------------------------------- - -Sometimes it's useful to specify version information independent of -normal requirements specifications. For example, a buildout may need -to lock down a set of versions, without having to put put version -numbers in setup files or part definitions. If a dictionary is passed -to the install function, mapping project names to version numbers, -then the versions numbers will be used. - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... versions = dict(demo='0.2', demoneeded='1.0')) - >>> [d.version for d in ws] - ['0.2', '1.0'] - -In this example, we specified a version for demoneeded, even though we -didn't define a requirement for it. The versions specified apply to -dependencies as well as the specified requirements. - -If we specify a version that's incompatible with a requirement, then -we'll get an error: - - >>> from zope.testing.loggingsupport import InstalledHandler - >>> handler = InstalledHandler('zc.buildout.easy_install') - >>> import logging - >>> logging.getLogger('zc.buildout.easy_install').propagate = False - - >>> ws = zc.buildout.easy_install.install( - ... ['demo >0.2'], dest, links=[link_server], - ... index=link_server+'index/', - ... versions = dict(demo='0.2', demoneeded='1.0')) - Traceback (most recent call last): - ... - IncompatibleVersionError: Bad version 0.2 - - >>> print handler - zc.buildout.easy_install DEBUG - Installing 'demo >0.2'. - zc.buildout.easy_install ERROR - The version, 0.2, is not consistent with the requirement, 'demo>0.2'. - - >>> handler.clear() - -If no versions are specified, a debugging message will be output -reporting that a version was picked automatically: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... ) - - >>> print handler - zc.buildout.easy_install DEBUG - Installing 'demo'. - zc.buildout.easy_install DEBUG - We have the best distribution that satisfies 'demo'. - zc.buildout.easy_install DEBUG - Picked: demo = 0.3 - zc.buildout.easy_install DEBUG - Getting required 'demoneeded' - zc.buildout.easy_install DEBUG - required by demo 0.3. - zc.buildout.easy_install DEBUG - We have the best distribution that satisfies 'demoneeded'. - zc.buildout.easy_install DEBUG - Picked: demoneeded = 1.1 - - >>> handler.uninstall() - >>> logging.getLogger('zc.buildout.easy_install').propagate = True - -We can request that we get an error if versions are picked: - - >>> zc.buildout.easy_install.allow_picked_versions(False) - True - -(The old setting is returned.) - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... ) - Traceback (most recent call last): - ... - UserError: Picked: demo = 0.3 - - >>> zc.buildout.easy_install.allow_picked_versions(True) - False - -The function default_versions can be used to get and set default -version information to be used when no version information is passes. -If called with an argument, it sets the default versions: - - >>> zc.buildout.easy_install.default_versions(dict(demoneeded='1')) - {} - -It always returns the previous default versions. If called without an -argument, it simply returns the default versions without changing -them: - - >>> zc.buildout.easy_install.default_versions() - {'demoneeded': '1'} - -So with the default versions set, we'll get the requested version even -if the versions option isn't used: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... ) - - >>> [d.version for d in ws] - ['0.3', '1.0'] - -Of course, we can unset the default versions by passing an empty -dictionary: - - >>> zc.buildout.easy_install.default_versions({}) - {'demoneeded': '1'} - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], index=link_server+'index/', - ... ) - - >>> [d.version for d in ws] - ['0.3', '1.1'] - -Dependencies in Site Packages ------------------------------ - -Paths outside of Python's standard library--or more precisely, those that are -not included when Python is started with the -S argument--are loosely referred -to as "site-packages" here. These site-packages are searched by default for -distributions. This can be disabled, so that, for instance, a system Python -can be used with buildout, cleaned of any packages installed by a user or -system package manager. - -The default behavior can be controlled and introspected using -zc.buildout.easy_install.include_site_packages. - - >>> zc.buildout.easy_install.include_site_packages() - True - -Here's an example of using a Python executable that includes our dependencies. - -Our "py_path" will have the "demoneeded," and "demo" packages available. - We'll simply be asking for "demoneeded" here, but without any external - index or links. - - >>> from zc.buildout.tests import create_sample_sys_install - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None) - >>> [dist.project_name for dist in workingset] - ['demoneeded'] - -That worked fine. Let's try again with site packages not allowed. We'll -change the policy by changing the default. Notice that the function for -changing the default value returns the previous value. - - >>> zc.buildout.easy_install.include_site_packages(False) - True - - >>> zc.buildout.easy_install.include_site_packages() - False - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - >>> zc.buildout.easy_install.clear_index_cache() - -Now we'll reset the default. - - >>> zc.buildout.easy_install.include_site_packages(True) - False - - >>> zc.buildout.easy_install.include_site_packages() - True - -Dependency links ----------------- - -Setuptools allows metadata that describes where to search for package -dependencies. This option is called dependency_links. Buildout has its -own notion of where to look for dependencies, but it also uses the -setup tools dependency_links information if it's available. - -Let's demo this by creating an egg that specifies dependency_links. - -To begin, let's create a new egg repository. This repository hold a -newer version of the 'demoneeded' egg than the sample repository does. - - >>> repoloc = tmpdir('repo') - >>> from zc.buildout.tests import create_egg - >>> create_egg('demoneeded', '1.2', repoloc) - >>> link_server2 = start_server(repoloc) - -Turn on logging on this server so that we can see when eggs are pulled -from it. - - >>> get(link_server2 + 'enable_server_logging') - GET 200 /enable_server_logging - '' - -Now we can create an egg that specifies that its dependencies are -found on this server. - - >>> repoloc = tmpdir('repo2') - >>> create_egg('hasdeps', '1.0', repoloc, - ... install_requires = "'demoneeded'", - ... dependency_links = [link_server2]) - -Let's add the egg to another repository. - - >>> link_server3 = start_server(repoloc) - -Now let's install the egg. - - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, - ... links=[link_server3], index=link_server3+'index/') - GET 200 / - GET 200 /demoneeded-1.2-pyN.N.egg - -The server logs show that the dependency was retrieved from the server -specified in the dependency_links. - -Now let's see what happens if we provide two different ways to retrieve -the dependencies. - - >>> rmdir(example_dest) - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, index=link_server+'index/', - ... links=[link_server, link_server3]) - GET 200 / - GET 200 /demoneeded-1.2-pyN.N.egg - -Once again the dependency is fetched from the logging server even -though it is also available from the non-logging server. This is -because the version on the logging server is newer and buildout -normally chooses the newest egg available. - -If you wish to control where dependencies come from regardless of -dependency_links setup metadata use the 'use_dependency_links' option -to zc.buildout.easy_install.install(). - - >>> rmdir(example_dest) - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, index=link_server+'index/', - ... links=[link_server, link_server3], - ... use_dependency_links=False) - -Notice that this time the dependency egg is not fetched from the -logging server. When you specify not to use dependency_links, eggs -will only be searched for using the links you explicitly provide. - -Another way to control this option is with the -zc.buildout.easy_install.use_dependency_links() function. This -function sets the default behavior for the zc.buildout.easy_install() -function. - - >>> zc.buildout.easy_install.use_dependency_links(False) - True - -The function returns its previous setting. - - >>> rmdir(example_dest) - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, index=link_server+'index/', - ... links=[link_server, link_server3]) - -It can be overridden by passing a keyword argument to the install -function. - - >>> rmdir(example_dest) - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, index=link_server+'index/', - ... links=[link_server, link_server3], - ... use_dependency_links=True) - GET 200 /demoneeded-1.2-pyN.N.egg - -To return the dependency_links behavior to normal call the function again. - - >>> zc.buildout.easy_install.use_dependency_links(True) - False - >>> rmdir(example_dest) - >>> example_dest = tmpdir('example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['hasdeps'], example_dest, index=link_server+'index/', - ... links=[link_server, link_server3]) - GET 200 /demoneeded-1.2-pyN.N.egg - - -Script generation ------------------ - -The easy_install module provides support for creating scripts from eggs. -It provides two competing functions. One, ``scripts``, is a -well-established approach to generating reliable scripts with a "clean" -Python--e.g., one that does not have any packages in its site-packages. -The other, ``sitepackage_safe_scripts``, is newer, a bit trickier, and is -designed to work with a Python that has code in its site-packages, such -as a system Python. - -Both are similar to setuptools except that they provides facilities for -baking a script's path into the script. This has two advantages: - -- The eggs to be used by a script are not chosen at run time, making - startup faster and, more importantly, deterministic. - -- The script doesn't have to import pkg_resources because the logic that - pkg_resources would execute at run time is executed at script-creation - time. (There is an exception in ``sitepackage_safe_scripts`` if you - want to have your Python's site packages available, as discussed - below, but even in that case pkg_resources is only partially - activated, which can be a significant time savings.) - - -The ``scripts`` function -~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``scripts`` function is the first way to generate scripts that we'll -examine. It is the earlier approach that the package offered. Let's -create a destination directory for it to place them in: - - >>> bin = tmpdir('bin') - -Now, we'll use the scripts function to generate scripts in this directory -from the demo egg: - - >>> import sys - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin) - -the four arguments we passed were: - -1. A sequence of distribution requirements. These are of the same - form as setuptools requirements. Here we passed a single - requirement, for the version 0.1 demo distribution. - -2. A working set, - -3. The Python executable to use, and - -3. The destination directory. - -The bin directory now contains a generated script: - - >>> ls(bin) - - demo - -The return value is a list of the scripts generated: - - >>> import os, sys - >>> if sys.platform == 'win32': - ... scripts == [os.path.join(bin, 'demo.exe'), - ... os.path.join(bin, 'demo-script.py')] - ... else: - ... scripts == [os.path.join(bin, 'demo')] - True - -Note that in Windows, 2 files are generated for each script. A script -file, ending in '-script.py', and an exe file that allows the script -to be invoked directly without having to specify the Python -interpreter and without having to provide a '.py' suffix. - -The demo script run the entry point defined in the demo egg: - - >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample-install/demo-0.3-py2.4.egg', - '/sample-install/demoneeded-1.1-py2.4.egg', - ] - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main() - -Some things to note: - -- The demo and demoneeded eggs are added to the beginning of sys.path. - -- The module for the script entry point is imported and the entry - point, in this case, 'main', is run. - -Rather than requirement strings, you can pass tuples containing 3 -strings: - - - A script name, - - - A module, - - - An attribute expression for an entry point within the module. - -For example, we could have passed entry point information directly -rather than passing a requirement: - - >>> scripts = zc.buildout.easy_install.scripts( - ... [('demo', 'eggrecipedemo', 'main')], - ... ws, sys.executable, bin) - - >>> cat(bin, 'demo') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample-install/demo-0.3-py2.4.egg', - '/sample-install/demoneeded-1.1-py2.4.egg', - ] - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main() - -Passing entry-point information directly is handy when using eggs (or -distributions) that don't declare their entry points, such as -distributions that aren't based on setuptools. - -The interpreter keyword argument can be used to generate a script that can -be used to invoke the Python interactive interpreter with the path set -based on the working set. This generated script can also be used to -run other scripts with the path set on the working set: - - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin, interpreter='py') - - - >>> ls(bin) - - demo - - py - - >>> if sys.platform == 'win32': - ... scripts == [os.path.join(bin, 'demo.exe'), - ... os.path.join(bin, 'demo-script.py'), - ... os.path.join(bin, 'py.exe'), - ... os.path.join(bin, 'py-script.py')] - ... else: - ... scripts == [os.path.join(bin, 'demo'), - ... os.path.join(bin, 'py')] - True - -The py script simply runs the Python interactive interpreter with -the path set: - - >>> cat(bin, 'py') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import sys - <BLANKLINE> - sys.path[0:0] = [ - '/sample-install/demo-0.3-pyN.N.egg', - '/sample-install/demoneeded-1.1-pyN.N.egg', - ] - <BLANKLINE> - _interactive = True - if len(sys.argv) > 1: - _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:') - _interactive = False - for (_opt, _val) in _options: - if _opt == '-i': - _interactive = True - elif _opt == '-c': - exec _val - elif _opt == '-m': - sys.argv[1:] = _args - _args = [] - __import__("runpy").run_module( - _val, {}, "__main__", alter_sys=True) - <BLANKLINE> - if _args: - sys.argv[:] = _args - __file__ = _args[0] - del _options, _args - execfile(__file__) - <BLANKLINE> - if _interactive: - del _interactive - __import__("code").interact(banner="", local=globals()) - -If invoked with a script name and arguments, it will run that script, instead. - - >>> write('ascript', ''' - ... "demo doc" - ... print sys.argv - ... print (__name__, __file__, __doc__) - ... ''') - >>> print system(join(bin, 'py')+' ascript a b c'), - ['ascript', 'a', 'b', 'c'] - ('__main__', 'ascript', 'demo doc') - -For Python 2.5 and higher, you can also use the -m option to run a -module: - - >>> print system(join(bin, 'py')+' -m pdb'), - usage: pdb.py scriptfile [arg] ... - - >>> print system(join(bin, 'py')+' -m pdb what'), - Error: what does not exist - -An additional argument can be passed to define which scripts to install -and to provide script names. The argument is a dictionary mapping -original script names to new script names. - - >>> bin = tmpdir('bin2') - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin, dict(demo='run')) - - >>> if sys.platform == 'win32': - ... scripts == [os.path.join(bin, 'run.exe'), - ... os.path.join(bin, 'run-script.py')] - ... else: - ... scripts == [os.path.join(bin, 'run')] - True - >>> ls(bin) - - run - - >>> print system(os.path.join(bin, 'run')), - 3 1 - -The ``scripts`` function: Including extra paths in scripts -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -We can pass a keyword argument, extra paths, to cause additional paths -to be included in the a generated script: - - >>> foo = tmpdir('foo') - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin, dict(demo='run'), - ... extra_paths=[foo]) - - >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/sample-install/demo-0.3-py2.4.egg', - '/sample-install/demoneeded-1.1-py2.4.egg', - '/foo', - ] - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main() - -The ``scripts`` function: Providing script arguments -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -An "argument" keyword argument can be used to pass arguments to an -entry point. The value passed is a source string to be placed between the -parentheses in the call: - - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin, dict(demo='run'), - ... arguments='1, 2') - - >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - import sys - sys.path[0:0] = [ - '/sample-install/demo-0.3-py2.4.egg', - '/sample-install/demoneeded-1.1-py2.4.egg', - ] - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main(1, 2) - -The ``scripts`` function: Passing initialization code -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can also pass script initialization code: - - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, bin, dict(demo='run'), - ... arguments='1, 2', - ... initialization='import os\nos.chdir("foo")') - - >>> cat(bin, 'run') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - import sys - sys.path[0:0] = [ - '/sample-install/demo-0.3-py2.4.egg', - '/sample-install/demoneeded-1.1-py2.4.egg', - ] - <BLANKLINE> - import os - os.chdir("foo") - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main(1, 2) - -The ``scripts`` function: Relative paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Sometimes, you want to be able to move a buildout directory around and -have scripts still work without having to rebuild them. We can -control this using the relative_paths option to install. You need -to pass a common base directory of the scripts and eggs: - - >>> bo = tmpdir('bo') - >>> ba = tmpdir('ba') - >>> mkdir(bo, 'eggs') - >>> mkdir(bo, 'bin') - >>> mkdir(bo, 'other') - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], join(bo, 'eggs'), links=[link_server], - ... index=link_server+'index/') - - >>> scripts = zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, join(bo, 'bin'), dict(demo='run'), - ... extra_paths=[ba, join(bo, 'bar')], - ... interpreter='py', - ... relative_paths=bo) - - >>> cat(bo, 'bin', 'run') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import os - <BLANKLINE> - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - <BLANKLINE> - import sys - sys.path[0:0] = [ - join(base, 'eggs/demo-0.3-pyN.N.egg'), - join(base, 'eggs/demoneeded-1.1-pyN.N.egg'), - '/ba', - join(base, 'bar'), - ] - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main() - -Note that the extra path we specified that was outside the directory -passed as relative_paths wasn't converted to a relative path. - -Of course, running the script works: - - >>> print system(join(bo, 'bin', 'run')), - 3 1 - -We specified an interpreter and its paths are adjusted too: - - >>> cat(bo, 'bin', 'py') # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 - <BLANKLINE> - import os - <BLANKLINE> - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - <BLANKLINE> - import sys - <BLANKLINE> - sys.path[0:0] = [ - join(base, 'eggs/demo-0.3-pyN.N.egg'), - join(base, 'eggs/demoneeded-1.1-pyN.N.egg'), - '/ba', - join(base, 'bar'), - ] - <BLANKLINE> - _interactive = True - if len(sys.argv) > 1: - _options, _args = __import__("getopt").getopt(sys.argv[1:], 'ic:m:') - _interactive = False - for (_opt, _val) in _options: - if _opt == '-i': - _interactive = True - elif _opt == '-c': - exec _val - elif _opt == '-m': - sys.argv[1:] = _args - _args = [] - __import__("runpy").run_module( - _val, {}, "__main__", alter_sys=True) - <BLANKLINE> - if _args: - sys.argv[:] = _args - __file__ = _args[0] - del _options, _args - execfile(__file__) - <BLANKLINE> - if _interactive: - del _interactive - __import__("code").interact(banner="", local=globals()) - -The ``sitepackage_safe_scripts`` function -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The newer function for creating scripts is ``sitepackage_safe_scripts``. -It has the same basic functionality as the ``scripts`` function: it can -create scripts to run arbitrary entry points, and to run a Python -interpreter. The following are the differences from a user's -perspective. - -- It can be used safely with a Python that has packages installed itself, - such as a system-installed Python. - -- In contrast to the interpreter generated by the ``scripts`` method, which - supports only a small subset of the usual Python executable's options, - the interpreter generated by ``sitepackage_safe_scripts`` supports all - of them. This makes it possible to use as full Python replacement for - scripts that need the distributions specified in your buildout. - -- Both the interpreter and the entry point scripts allow you to include the - site packages, and/or the sitecustomize, of the Python executable, if - desired. - -It works by creating site.py and sitecustomize.py files that set up the -desired paths and initialization. These must be placed within an otherwise -empty directory. Typically this is in a recipe's parts directory. - -Here's the simplest example, building an interpreter script. - - >>> interpreter_dir = tmpdir('interpreter') - >>> interpreter_parts_dir = os.path.join( - ... interpreter_dir, 'parts', 'interpreter') - >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin') - >>> mkdir(interpreter_bin_dir) - >>> mkdir(interpreter_dir, 'eggs') - >>> mkdir(interpreter_dir, 'parts') - >>> mkdir(interpreter_parts_dir) - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], join(interpreter_dir, 'eggs'), links=[link_server], - ... index=link_server+'index/') - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py') - -Depending on whether the machine being used is running Windows or not, this -produces either three or four files. In both cases, we have site.py and -sitecustomize.py generated in the parts/interpreter directory. For Windows, -we have py.exe and py-script.py; for other operating systems, we have py. - - >>> sitecustomize_path = os.path.join( - ... interpreter_parts_dir, 'sitecustomize.py') - >>> site_path = os.path.join(interpreter_parts_dir, 'site.py') - >>> interpreter_path = os.path.join(interpreter_bin_dir, 'py') - >>> if sys.platform == 'win32': - ... py_path = os.path.join(interpreter_bin_dir, 'py-script.py') - ... expected = [sitecustomize_path, - ... site_path, - ... os.path.join(interpreter_bin_dir, 'py.exe'), - ... py_path] - ... else: - ... py_path = interpreter_path - ... expected = [sitecustomize_path, site_path, py_path] - ... - >>> assert generated == expected, repr((generated, expected)) - -We didn't ask for any initialization, and we didn't ask to use the underlying -sitecustomization, so sitecustomize.py is empty. - - >>> cat(sitecustomize_path) - -The interpreter script is simple. It puts the directory with the -site.py and sitecustomize.py on the PYTHONPATH and (re)starts Python. - - >>> cat(py_path) - #!/usr/bin/python -S - import os - import sys - <BLANKLINE> - argv = [sys.executable] + sys.argv[1:] - environ = os.environ.copy() - path = '/interpreter/parts/interpreter' - if environ.get('PYTHONPATH'): - path = os.pathsep.join([path, environ['PYTHONPATH']]) - environ['PYTHONPATH'] = path - os.execve(sys.executable, argv, environ) - -The site.py file is a modified version of the underlying Python's site.py. -The most important modification is that it has a different version of the -addsitepackages function. It sets up the Python path, similarly to the -behavior of the function it replaces. The following shows the part that -buildout inserts, in the simplest case. - - >>> sys.stdout.write('#\n'); cat(site_path) - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - buildout_paths = [ - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg' - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase) - return known_paths - <BLANKLINE> - def original_addsitepackages(known_paths):... - -Here are some examples of the interpreter in use. - - >>> print call_py(interpreter_path, "print 16+26") - 42 - <BLANKLINE> - >>> res = call_py(interpreter_path, "import sys; print sys.path") - >>> print res # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ['', - '/interpreter/parts/interpreter', - ..., - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'] - <BLANKLINE> - >>> clean_paths = eval(res.strip()) # This is used later for comparison. - -If you provide initialization, it goes in sitecustomize.py. - - >>> def reset_interpreter(): - ... # This is necessary because, in our tests, the timestamps of the - ... # .pyc files are not outdated when we want them to be. - ... rmdir(interpreter_bin_dir) - ... mkdir(interpreter_bin_dir) - ... rmdir(interpreter_parts_dir) - ... mkdir(interpreter_parts_dir) - ... - >>> reset_interpreter() - - >>> initialization_string = """\ - ... import os - ... os.environ['FOO'] = 'bar baz bing shazam'""" - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', initialization=initialization_string) - >>> cat(sitecustomize_path) - import os - os.environ['FOO'] = 'bar baz bing shazam' - >>> print call_py(interpreter_path, "import os; print os.environ['FOO']") - bar baz bing shazam - <BLANKLINE> - -If you use relative paths, this affects the interpreter and site.py. (This is -again the UNIX version; the Windows version uses subprocess instead of -os.execve.) - - >>> reset_interpreter() - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', relative_paths=interpreter_dir) - >>> cat(py_path) - #!/usr/bin/python -S - import os - import sys - <BLANKLINE> - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - <BLANKLINE> - argv = [sys.executable] + sys.argv[1:] - environ = os.environ.copy() - path = join(base, 'parts/interpreter') - if environ.get('PYTHONPATH'): - path = os.pathsep.join([path, environ['PYTHONPATH']]) - environ['PYTHONPATH'] = path - os.execve(sys.executable, argv, environ) - -For site.py, we again show only the pertinent parts. Notice that the egg -paths join a base to a path, as with the use of this argument in the -``scripts`` function. - - >>> sys.stdout.write('#\n'); cat(site_path) # doctest: +ELLIPSIS - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - base = os.path.dirname(base) - buildout_paths = [ - join(base, 'eggs/demo-0.3-pyN.N.egg'), - join(base, 'eggs/demoneeded-1.1-pyN.N.egg') - ]... - -The paths resolve in practice as you would expect. - - >>> print call_py(interpreter_path, - ... "import sys, pprint; pprint.pprint(sys.path)") - ... # doctest: +ELLIPSIS - ['', - '/interpreter/parts/interpreter', - ..., - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'] - <BLANKLINE> - -The ``extra_paths`` argument affects the path in site.py. Notice that -/interpreter/other is added after the eggs. - - >>> reset_interpreter() - >>> mkdir(interpreter_dir, 'other') - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', extra_paths=[join(interpreter_dir, 'other')]) - >>> sys.stdout.write('#\n'); cat(site_path) # doctest: +ELLIPSIS - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - buildout_paths = [ - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg', - '/interpreter/other' - ]... - - >>> print call_py(interpreter_path, - ... "import sys, pprint; pprint.pprint(sys.path)") - ... # doctest: +ELLIPSIS - ['', - '/interpreter/parts/interpreter', - ..., - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg', - '/interpreter/other'] - <BLANKLINE> - -The ``sitepackage_safe_scripts`` function: using site-packages -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -The ``sitepackage_safe_scripts`` function supports including site -packages. This has some advantages and some serious dangers. - -A typical reason to include site-packages is that it is easier to -install one or more dependencies in your Python than it is with -buildout. Some packages, such as lxml or Python PostgreSQL integration, -have dependencies that can be much easier to build and/or install using -other mechanisms, such as your operating system's package manager. By -installing some core packages into your Python's site-packages, this can -significantly simplify some application installations. - -However, doing this has a significant danger. One of the primary goals -of buildout is to provide repeatability. Some packages (one of the -better known Python openid packages, for instance) change their behavior -depending on what packages are available. If Python curl bindings are -available, these may be preferred by the library. If a certain XML -package is installed, it may be preferred by the library. These hidden -choices may cause small or large behavior differences. The fact that -they can be rarely encountered can actually make it worse: you forget -that this might be a problem, and debugging the differences can be -difficult. If you allow site-packages to be included in your buildout, -and the Python you use is not managed precisely by your application (for -instance, it is a system Python), you open yourself up to these -possibilities. Don't be unaware of the dangers. - -That explained, let's see how it works. If you don't use namespace packages, -this is very straightforward. - - >>> reset_interpreter() - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', include_site_packages=True) - >>> sys.stdout.write('#\n'); cat(site_path) - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - setuptools_path = None - buildout_paths = [ - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg' - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase) - sys.__egginsert = len(buildout_paths) # Support distribute. - original_paths = [ - ... - ] - for path in original_paths: - if path == setuptools_path or path not in known_paths: - addsitedir(path, known_paths) - return known_paths - <BLANKLINE> - def original_addsitepackages(known_paths):... - -It simply adds the original paths using addsitedir after the code to add the -buildout paths. - -Here's an example of the new script in use. Other documents and tests in -this package give the feature a more thorough workout, but this should -give you an idea of the feature. - - >>> res = call_py(interpreter_path, "import sys; print sys.path") - >>> print res # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ['', - '/interpreter/parts/interpreter', - ..., - '/interpreter/eggs/demo-0.3-py2.4.egg', - '/interpreter/eggs/demoneeded-1.1-py2.4.egg', - ...] - <BLANKLINE> - -The clean_paths gathered earlier is a subset of this full list of paths. - - >>> full_paths = eval(res.strip()) - >>> len(clean_paths) < len(full_paths) - True - >>> set(os.path.normpath(p) for p in clean_paths).issubset( - ... os.path.normpath(p) for p in full_paths) - True - -Unfortunately, because of how setuptools namespace packages are implemented -differently for operating system packages (debs or rpms) as opposed to -standard setuptools installation, there's a slightly trickier dance if you -use them. To show this we'll needs some extra eggs that use namespaces. -We'll use the ``tellmy.fortune`` package, which we'll need to make an initial -call to another text fixture to create. - - >>> from zc.buildout.tests import create_sample_namespace_eggs - >>> namespace_eggs = tmpdir('namespace_eggs') - >>> create_sample_namespace_eggs(namespace_eggs) - - >>> reset_interpreter() - >>> ws = zc.buildout.easy_install.install( - ... ['demo', 'tellmy.fortune'], join(interpreter_dir, 'eggs'), - ... links=[link_server, namespace_eggs], index=link_server+'index/') - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', include_site_packages=True) - >>> sys.stdout.write('#\n'); cat(site_path) - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - setuptools_path = '...setuptools...' - sys.path.append(setuptools_path) - known_paths.add(os.path.normcase(setuptools_path)) - import pkg_resources - buildout_paths = [ - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/tellmy.fortune-1.0-pyN.N.egg', - '...setuptools...', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg' - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase) - pkg_resources.working_set.add_entry(sitedir) - sys.__egginsert = len(buildout_paths) # Support distribute. - original_paths = [ - ... - ] - for path in original_paths: - if path == setuptools_path or path not in known_paths: - addsitedir(path, known_paths) - return known_paths - <BLANKLINE> - def original_addsitepackages(known_paths):... - - >>> print call_py(interpreter_path, "import sys; print sys.path") - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ['', - '/interpreter/parts/interpreter', - ..., - '...setuptools...', - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/tellmy.fortune-1.0-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg', - ...] - -As you can see, the script now first imports pkg_resources. Then we -need to process egg files specially to look for namespace packages there -*before* we process process lines in .pth files that use the "import" -feature--lines that might be part of the setuptools namespace package -implementation for system packages, as mentioned above, and that must -come after processing egg namespaces. - -The most complex that this function gets is if you use namespace packages, -include site-packages, and use relative paths. For completeness, we'll look -at that result. - - >>> reset_interpreter() - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... interpreter='py', include_site_packages=True, - ... relative_paths=interpreter_dir) - >>> sys.stdout.write('#\n'); cat(site_path) - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - #... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - join = os.path.join - base = os.path.dirname(os.path.abspath(os.path.realpath(__file__))) - base = os.path.dirname(base) - base = os.path.dirname(base) - setuptools_path = '...setuptools...' - sys.path.append(setuptools_path) - known_paths.add(os.path.normcase(setuptools_path)) - import pkg_resources - buildout_paths = [ - join(base, 'eggs/demo-0.3-pyN.N.egg'), - join(base, 'eggs/tellmy.fortune-1.0-pyN.N.egg'), - '...setuptools...', - join(base, 'eggs/demoneeded-1.1-pyN.N.egg') - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase) - pkg_resources.working_set.add_entry(sitedir) - sys.__egginsert = len(buildout_paths) # Support distribute. - original_paths = [ - ... - ] - for path in original_paths: - if path == setuptools_path or path not in known_paths: - addsitedir(path, known_paths) - return known_paths - <BLANKLINE> - def original_addsitepackages(known_paths):... - - >>> print call_py(interpreter_path, "import sys; print sys.path") - ... # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - ['', - '/interpreter/parts/interpreter', - ..., - '...setuptools...', - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/tellmy.fortune-1.0-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg', - ...] - -The ``exec_sitecustomize`` argument does the same thing for the -sitecustomize module--it allows you to include the code from the -sitecustomize module in the underlying Python if you set the argument to -True. The z3c.recipe.scripts package sets up the full environment necessary -to demonstrate this piece. - -The ``sitepackage_safe_scripts`` function: writing scripts for entry points -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -All of the examples so far for this function have been creating -interpreters. The function can also write scripts for entry -points. They are almost identical to the scripts that we saw for the -``scripts`` function except that they ``import site`` after setting the -sys.path to include our custom site.py and sitecustomize.py files. These -files then initialize the Python environment as we have already seen. Let's -see a simple example. - - >>> reset_interpreter() - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], join(interpreter_dir, 'eggs'), links=[link_server], - ... index=link_server+'index/') - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... reqs=['demo']) - -As before, in Windows, 2 files are generated for each script. A script -file, ending in '-script.py', and an exe file that allows the script -to be invoked directly without having to specify the Python -interpreter and without having to provide a '.py' suffix. This is in addition -to the site.py and sitecustomize.py files that are generated as with our -interpreter examples above. - - >>> if sys.platform == 'win32': - ... demo_path = os.path.join(interpreter_bin_dir, 'demo-script.py') - ... expected = [sitecustomize_path, - ... site_path, - ... os.path.join(interpreter_bin_dir, 'demo.exe'), - ... demo_path] - ... else: - ... demo_path = os.path.join(interpreter_bin_dir, 'demo') - ... expected = [sitecustomize_path, site_path, demo_path] - ... - >>> assert generated == expected, repr((generated, expected)) - -The demo script runs the entry point defined in the demo egg: - - >>> cat(demo_path) # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 -S - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/interpreter/parts/interpreter', - ] - <BLANKLINE> - <BLANKLINE> - import os - path = sys.path[0] - if os.environ.get('PYTHONPATH'): - path = os.pathsep.join([path, os.environ['PYTHONPATH']]) - os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '') - os.environ['PYTHONPATH'] = path - import site # imports custom buildout-generated site.py - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main() - - >>> demo_call = join(interpreter_bin_dir, 'demo') - >>> if sys.platform == 'win32': - ... demo_call = '"%s"' % demo_call - >>> print system(demo_call) - 3 1 - <BLANKLINE> - -There are a few differences from the ``scripts`` function. First, the -``reqs`` argument (an iterable of string requirements or entry point -tuples) is a keyword argument here. We see that in the example above. -Second, the ``arguments`` argument is now named ``script_arguments`` to -try and clarify that it does not affect interpreters. While the -``initialization`` argument continues to affect both the interpreters -and the entry point scripts, if you have initialization that is only -pertinent to the entry point scripts, you can use the -``script_initialization`` argument. - -Let's see ``script_arguments`` and ``script_initialization`` in action. - - >>> reset_interpreter() - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... reqs=['demo'], script_arguments='1, 2', - ... script_initialization='import os\nos.chdir("foo")') - - >>> cat(demo_path) # doctest: +NORMALIZE_WHITESPACE - #!/usr/local/bin/python2.4 -S - import sys - sys.path[0:0] = [ - '/interpreter/parts/interpreter', - ] - <BLANKLINE> - import os - path = sys.path[0] - if os.environ.get('PYTHONPATH'): - path = os.pathsep.join([path, os.environ['PYTHONPATH']]) - os.environ['BUILDOUT_ORIGINAL_PYTHONPATH'] = os.environ.get('PYTHONPATH', '') - os.environ['PYTHONPATH'] = path - import site # imports custom buildout-generated site.py - import os - os.chdir("foo") - <BLANKLINE> - import eggrecipedemo - <BLANKLINE> - if __name__ == '__main__': - eggrecipedemo.main(1, 2) - -Handling custom build options for extensions provided in source distributions ------------------------------------------------------------------------------ - -Sometimes, we need to control how extension modules are built. The -build function provides this level of control. It takes a single -package specification, downloads a source distribution, and builds it -with specified custom build options. - -The build function takes 3 positional arguments: - -spec - A package specification for a source distribution - -dest - A destination directory - -build_ext - A dictionary of options to be passed to the distutils build_ext - command when building extensions. - -It supports a number of optional keyword arguments: - -links - a sequence of URLs, file names, or directories to look for - links to distributions, - -index - The URL of an index server, or almost any other valid URL. :) - - If not specified, the Python Package Index, - http://pypi.python.org/simple/, is used. You can specify an - alternate index with this option. If you use the links option and - if the links point to the needed distributions, then the index can - be anything and will be largely ignored. In the examples, here, - we'll just point to an empty directory on our link server. This - will make our examples run a little bit faster. - -executable - A path to a Python executable. Distributions will be installed - using this executable and will be for the matching Python version. - -path - A list of additional directories to search for locally-installed - distributions. - -newest - A boolean value indicating whether to search for new distributions - when already-installed distributions meet the requirement. When - this is true, the default, and when the destination directory is - not None, then the install function will search for the newest - distributions that satisfy the requirements. - -versions - A dictionary mapping project names to version numbers to be used - when selecting distributions. This can be used to specify a set of - distribution versions independent of other requirements. - - -Our link server included a source distribution that includes a simple -extension, extdemo.c:: - - #include <Python.h> - #include <extdemo.h> - - static PyMethodDef methods[] = {}; - - PyMODINIT_FUNC - initextdemo(void) - { - PyObject *m; - m = Py_InitModule3("extdemo", methods, ""); - #ifdef TWO - PyModule_AddObject(m, "val", PyInt_FromLong(2)); - #else - PyModule_AddObject(m, "val", PyInt_FromLong(EXTDEMO)); - #endif - } - -The extension depends on a system-dependent include file, extdemo.h, -that defines a constant, EXTDEMO, that is exposed by the extension. - -We'll add an include directory to our sample buildout and add the -needed include file to it: - - >>> mkdir('include') - >>> write('include', 'extdemo.h', - ... """ - ... #define EXTDEMO 42 - ... """) - -Now, we can use the build function to create an egg from the source -distribution: - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/') - ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg'] - -The function returns the list of eggs - -Now if we look in our destination directory, we see we have an extdemo egg: - - >>> ls(dest) - - demo-0.2-py2.4.egg - d demo-0.3-py2.4.egg - - demoneeded-1.0-py2.4.egg - d demoneeded-1.1-py2.4.egg - d extdemo-1.4-py2.4-unix-i686.egg - -Let's update our link server with a new version of extdemo: - - >>> update_extdemo() - >>> print get(link_server), - <html><body> - <a href="bigdemo-0.1-py2.4.egg">bigdemo-0.1-py2.4.egg</a><br> - <a href="demo-0.1-py2.4.egg">demo-0.1-py2.4.egg</a><br> - <a href="demo-0.2-py2.4.egg">demo-0.2-py2.4.egg</a><br> - <a href="demo-0.3-py2.4.egg">demo-0.3-py2.4.egg</a><br> - <a href="demo-0.4c1-py2.4.egg">demo-0.4c1-py2.4.egg</a><br> - <a href="demoneeded-1.0.zip">demoneeded-1.0.zip</a><br> - <a href="demoneeded-1.1.zip">demoneeded-1.1.zip</a><br> - <a href="demoneeded-1.2c1.zip">demoneeded-1.2c1.zip</a><br> - <a href="extdemo-1.4.zip">extdemo-1.4.zip</a><br> - <a href="extdemo-1.5.zip">extdemo-1.5.zip</a><br> - <a href="index/">index/</a><br> - <a href="other-1.0-py2.4.egg">other-1.0-py2.4.egg</a><br> - </body></html> - -The easy_install caches information about servers to reduce network -access. To see the update, we have to call the clear_index_cache -function to clear the index cache: - - >>> zc.buildout.easy_install.clear_index_cache() - -If we run build with newest set to False, we won't get an update: - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/', - ... newest=False) - ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg'] - - >>> ls(dest) - - demo-0.2-py2.4.egg - d demo-0.3-py2.4.egg - - demoneeded-1.0-py2.4.egg - d demoneeded-1.1-py2.4.egg - d extdemo-1.4-py2.4-unix-i686.egg - -But if we run it with the default True setting for newest, then we'll -get an updated egg: - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/') - ['/sample-install/extdemo-1.5-py2.4-unix-i686.egg'] - - >>> ls(dest) - - demo-0.2-py2.4.egg - d demo-0.3-py2.4.egg - - demoneeded-1.0-py2.4.egg - d demoneeded-1.1-py2.4.egg - d extdemo-1.4-py2.4-unix-i686.egg - d extdemo-1.5-py2.4-unix-i686.egg - -The versions option also influences the versions used. For example, -if we specify a version for extdemo, then that will be used, even -though it isn't the newest. Let's clean out the destination directory -first: - - >>> import os - >>> for name in os.listdir(dest): - ... remove(dest, name) - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/', - ... versions=dict(extdemo='1.4')) - ['/sample-install/extdemo-1.4-py2.4-unix-i686.egg'] - - >>> ls(dest) - d extdemo-1.4-py2.4-unix-i686.egg - -Handling custom build options for extensions in develop eggs ------------------------------------------------------------- - -The develop function is similar to the build function, except that, -rather than building an egg from a source directory containing a -setup.py script. - -The develop function takes 2 positional arguments: - -setup - The path to a setup script, typically named "setup.py", or a - directory containing a setup.py script. - -dest - The directory to install the egg link to - -It supports some optional keyword argument: - -build_ext - A dictionary of options to be passed to the distutils build_ext - command when building extensions. - -executable - A path to a Python executable. Distributions will be installed - using this executable and will be for the matching Python version. - -We have a local directory containing the extdemo source: - - >>> ls(extdemo) - - MANIFEST - - MANIFEST.in - - README - - extdemo.c - - setup.py - -Now, we can use the develop function to create a develop egg from the source -distribution: - - >>> zc.buildout.easy_install.develop( - ... extdemo, dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}) - '/sample-install/extdemo.egg-link' - -The name of the egg link created is returned. - -Now if we look in our destination directory, we see we have an extdemo -egg link: - - >>> ls(dest) - d extdemo-1.4-py2.4-unix-i686.egg - - extdemo.egg-link - -And that the source directory contains the compiled extension: - - >>> ls(extdemo) - - MANIFEST - - MANIFEST.in - - README - d build - - extdemo.c - d extdemo.egg-info - - extdemo.so - - setup.py - -Download cache --------------- - -Normally, when distributions are installed, if any processing is -needed, they are downloaded from the internet to a temporary directory -and then installed from there. A download cache can be used to avoid -the download step. This can be useful to reduce network access and to -create source distributions of an entire buildout. - -A download cache is specified by calling the download_cache -function. The function always returns the previous setting. If no -argument is passed, then the setting is unchanged. If an argument is -passed, the download cache is set to the given path, which must point -to an existing directory. Passing None clears the cache setting. - -To see this work, we'll create a directory and set it as the cache -directory: - - >>> cache = tmpdir('cache') - >>> zc.buildout.easy_install.download_cache(cache) - -We'll recreate our destination directory: - - >>> remove(dest) - >>> dest = tmpdir('sample-install') - -We'd like to see what is being fetched from the server, so we'll -enable server logging: - - >>> get(link_server+'enable_server_logging') - GET 200 /enable_server_logging - '' - -Now, if we install demo, and extdemo: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo==0.2'], dest, - ... links=[link_server], index=link_server+'index/', - ... always_unzip=True) - GET 200 / - GET 404 /index/demo/ - GET 200 /index/ - GET 200 /demo-0.2-py2.4.egg - GET 404 /index/demoneeded/ - GET 200 /demoneeded-1.1.zip - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/') - GET 404 /index/extdemo/ - GET 200 /extdemo-1.5.zip - ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg'] - -Not only will we get eggs in our destination directory: - - >>> ls(dest) - d demo-0.2-py2.4.egg - d demoneeded-1.1-py2.4.egg - d extdemo-1.5-py2.4-linux-i686.egg - -But we'll get distributions in the cache directory: - - >>> ls(cache) - - demo-0.2-py2.4.egg - - demoneeded-1.1.zip - - extdemo-1.5.zip - -The cache directory contains uninstalled distributions, such as zipped -eggs or source distributions. - -Let's recreate our destination directory and clear the index cache: - - >>> remove(dest) - >>> dest = tmpdir('sample-install') - >>> zc.buildout.easy_install.clear_index_cache() - -Now when we install the distributions: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo==0.2'], dest, - ... links=[link_server], index=link_server+'index/', - ... always_unzip=True) - GET 200 / - GET 404 /index/demo/ - GET 200 /index/ - GET 404 /index/demoneeded/ - - >>> zc.buildout.easy_install.build( - ... 'extdemo', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/') - GET 404 /index/extdemo/ - ['/sample-install/extdemo-1.5-py2.4-linux-i686.egg'] - - >>> ls(dest) - d demo-0.2-py2.4.egg - d demoneeded-1.1-py2.4.egg - d extdemo-1.5-py2.4-linux-i686.egg - -Note that we didn't download the distributions from the link server. - -If we remove the restriction on demo, we'll download a newer version -from the link server: - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, - ... links=[link_server], index=link_server+'index/', - ... always_unzip=True) - GET 200 /demo-0.3-py2.4.egg - -Normally, the download cache is the preferred source of downloads, but -not the only one. - -Installing solely from a download cache ---------------------------------------- - -A download cache can be used as the basis of application source -releases. In an application source release, we want to distribute an -application that can be built without making any network accesses. In -this case, we distribute a download cache and tell the easy_install -module to install from the download cache only, without making network -accesses. The install_from_cache function can be used to signal that -packages should be installed only from the download cache. The -function always returns the previous setting. Calling it with no -arguments returns the current setting without changing it: - - >>> zc.buildout.easy_install.install_from_cache() - False - -Calling it with a boolean value changes the setting and returns the -previous setting: - - >>> zc.buildout.easy_install.install_from_cache(True) - False - -Let's remove demo-0.3-py2.4.egg from the cache, clear the index cache, -recreate the destination directory, and reinstall demo: - - >>> for f in os.listdir(cache): - ... if f.startswith('demo-0.3-'): - ... remove(cache, f) - - >>> zc.buildout.easy_install.clear_index_cache() - >>> remove(dest) - >>> dest = tmpdir('sample-install') - - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, - ... links=[link_server], index=link_server+'index/', - ... always_unzip=True) - - >>> ls(dest) - d demo-0.2-py2.4.egg - d demoneeded-1.1-py2.4.egg - -This time, we didn't download from or even query the link server. - -.. Disable the download cache: - - >>> zc.buildout.easy_install.download_cache(None) - '/cache' - - >>> zc.buildout.easy_install.install_from_cache(False) - True diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/extends-cache.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/extends-cache.txt deleted file mode 100644 index 5a0fbce..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/extends-cache.txt +++ /dev/null @@ -1,399 +0,0 @@ -Caching extended configuration -============================== - -As mentioned in the general buildout documentation, configuration files can -extend each other, including the ability to download configuration being -extended from a URL. If desired, zc.buildout caches downloaded configuration -in order to be able to use it when run offline. - -As we're going to talk about downloading things, let's start an HTTP server. -Also, all of the following will take place inside the sample buildout. - ->>> server_data = tmpdir('server_data') ->>> server_url = start_server(server_data) ->>> cd(sample_buildout) - -We also use a fresh directory for temporary files in order to make sure that -all temporary files have been cleaned up in the end: - ->>> import tempfile ->>> old_tempdir = tempfile.tempdir ->>> tempfile.tempdir = tmpdir('tmp') - - -Basic use of the extends cache ------------------------------- - -We put some base configuration on a server and reference it from a sample -buildout: - ->>> write(server_data, 'base.cfg', """\ -... [buildout] -... parts = -... foo = bar -... """) - ->>> write('buildout.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... """ % server_url) - -When trying to run this buildout offline, we'll find that we cannot read all -of the required configuration: - ->>> print system(buildout + ' -o') -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - -Trying the same online, we can: - ->>> print system(buildout) -Unused options for buildout: 'foo'. - -As long as we haven't said anything about caching downloaded configuration, -nothing gets cached. Offline mode will still cause the buildout to fail: - ->>> print system(buildout + ' -o') -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - -Let's now specify a cache for base configuration files. This cache is -different from the download cache used by recipes for caching distributions -and other files; one might, however, use a namespace subdirectory of the -download cache for it. The configuration cache we specify will be created when -running buildout and the base.cfg file will be put in it (with the file name -being a hash of the complete URL): - ->>> mkdir('cache') ->>> write('buildout.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... extends-cache = cache -... """ % server_url) - ->>> print system(buildout) -Unused options for buildout: 'foo'. - ->>> cache = join(sample_buildout, 'cache') ->>> ls(cache) -- 5aedc98d7e769290a29d654a591a3a45 - ->>> import os ->>> cat(cache, os.listdir(cache)[0]) -[buildout] -parts = -foo = bar - -We can now run buildout offline as it will read base.cfg from the cache: - ->>> print system(buildout + ' -o') -Unused options for buildout: 'foo'. - -The cache is being used purely as a fall-back in case we are offline or don't -have access to a configuration file to be downloaded. As long as we are -online, buildout attempts to download a fresh copy of each file even if a -cached copy of the file exists. To see this, we put different configuration in -the same place on the server and run buildout in offline mode so it takes -base.cfg from the cache: - ->>> write(server_data, 'base.cfg', """\ -... [buildout] -... parts = -... bar = baz -... """) - ->>> print system(buildout + ' -o') -Unused options for buildout: 'foo'. - -In online mode, buildout will download and use the modified version: - ->>> print system(buildout) -Unused options for buildout: 'bar'. - -Trying offline mode again, the new version will be used as it has been put in -the cache now: - ->>> print system(buildout + ' -o') -Unused options for buildout: 'bar'. - -Clean up: - ->>> rmdir(cache) - - -Specifying extends cache and offline mode ------------------------------------------ - -Normally, the values of buildout options such as the location of a download -cache or whether to use offline mode are determined by first reading the -user's default configuration, updating it with the project's configuration and -finally applying command-line options. User and project configuration are -assembled by reading a file such as ``~/.buildout/default.cfg``, -``buildout.cfg`` or a URL given on the command line, recursively (depth-first) -downloading any base configuration specified by the ``buildout:extends`` -option read from each of those config files, and finally evaluating each -config file to provide default values for options not yet read. - -This works fine for all options that do not influence how configuration is -downloaded in the first place. The ``extends-cache`` and ``offline`` options, -however, are treated differently from the procedure described in order to make -it simple and obvious to see where a particular configuration file came from -under any particular circumstances. - -- Offline and extends-cache settings are read from the two root config files - exclusively. Otherwise one could construct configuration files that, when - read, imply that they should have been read from a different source than - they have. Also, specifying the extends cache within a file that might have - to be taken from the cache before being read wouldn't make a lot of sense. - -- Offline and extends-cache settings given by the user's defaults apply to the - process of assembling the project's configuration. If no extends cache has - been specified by the user's default configuration, the project's root - config file must be available, be it from disk or from the net. - -- Offline mode turned on by the ``-o`` command line option is honoured from - the beginning even though command line options are applied to the - configuration last. If offline mode is not requested by the command line, it - may be switched on by either the user's or the project's config root. - -Extends cache -~~~~~~~~~~~~~ - -Let's see the above rules in action. We create a new home directory for our -user and write user and project configuration that recursively extends online -bases, using different caches: - ->>> mkdir('home') ->>> mkdir('home', '.buildout') ->>> mkdir('cache') ->>> mkdir('user-cache') ->>> os.environ['HOME'] = join(sample_buildout, 'home') ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... extends-cache = user-cache -... """) ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... """ % server_url) ->>> write(server_data, 'base_default.cfg', """\ -... [buildout] -... foo = bar -... offline = false -... """) - ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... extends-cache = cache -... """) ->>> write('fancy.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... """ % server_url) ->>> write(server_data, 'base.cfg', """\ -... [buildout] -... parts = -... offline = false -... """) - -Buildout will now assemble its configuration from all of these 6 files, -defaults first. The online resources end up in the respective extends caches: - ->>> print system(buildout) -Unused options for buildout: 'foo'. - ->>> ls('user-cache') -- 10e772cf422123ef6c64ae770f555740 ->>> cat('user-cache', os.listdir('user-cache')[0]) -[buildout] -foo = bar -offline = false - ->>> ls('cache') -- c72213127e6eb2208a3e1fc1dba771a7 ->>> cat('cache', os.listdir('cache')[0]) -[buildout] -parts = -offline = false - -If, on the other hand, the extends caches are specified in files that get -extended themselves, they won't be used for assembling the configuration they -belong to (user's or project's, resp.). The extends cache specified by the -user's defaults does, however, apply to downloading project configuration. -Let's rewrite the config files, clean out the caches and re-run buildout: - ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... """) ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... extends-cache = user-cache -... """ % server_url) - ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... """) ->>> write('fancy.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... extends-cache = cache -... """ % server_url) - ->>> remove('user-cache', os.listdir('user-cache')[0]) ->>> remove('cache', os.listdir('cache')[0]) - ->>> print system(buildout) -Unused options for buildout: 'foo'. - ->>> ls('user-cache') -- 0548bad6002359532de37385bb532e26 ->>> cat('user-cache', os.listdir('user-cache')[0]) -[buildout] -parts = -offline = false - ->>> ls('cache') - -Clean up: - ->>> rmdir('user-cache') ->>> rmdir('cache') - -Offline mode and installation from cache -----------------------------~~~~~~~~~~~~ - -If we run buildout in offline mode now, it will fail because it cannot get at -the remote configuration file needed by the user's defaults: - ->>> print system(buildout + ' -o') -While: - Initializing. -Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode. - -Let's now successively turn on offline mode by different parts of the -configuration and see when buildout applies this setting in each case: - ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... offline = true -... """) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode. - ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... """) ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... offline = true -... """ % server_url) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... """ % server_url) ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... offline = true -... """) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... """) ->>> write('fancy.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... offline = true -... """ % server_url) ->>> print system(buildout) -Unused options for buildout: 'foo'. - -The ``install-from-cache`` option is treated accordingly: - ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... install-from-cache = true -... """) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base_default.cfg' in offline mode. - ->>> write('home', '.buildout', 'default.cfg', """\ -... [buildout] -... extends = fancy_default.cfg -... """) ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... install-from-cache = true -... """ % server_url) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - ->>> write('home', '.buildout', 'fancy_default.cfg', """\ -... [buildout] -... extends = %sbase_default.cfg -... """ % server_url) ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... install-from-cache = true -... """) ->>> print system(buildout) -While: - Initializing. -Error: Couldn't download 'http://localhost/base.cfg' in offline mode. - ->>> write('buildout.cfg', """\ -... [buildout] -... extends = fancy.cfg -... """) ->>> write('fancy.cfg', """\ -... [buildout] -... extends = %sbase.cfg -... install-from-cache = true -... """ % server_url) ->>> print system(buildout) -While: - Installing. - Checking for upgrades. -An internal error occurred ... -ValueError: install_from_cache set to true with no download cache - - -Clean up --------- - -We should have cleaned up all temporary files created by downloading things: - ->>> ls(tempfile.tempdir) - -Reset the global temporary directory: - ->>> tempfile.tempdir = old_tempdir diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/repeatable.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/repeatable.txt deleted file mode 100644 index 09078bd..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/repeatable.txt +++ /dev/null @@ -1,180 +0,0 @@ -Repeatable buildouts: controlling eggs used -=========================================== - -One of the goals of zc.buildout is to provide enough control to make -buildouts repeatable. It should be possible to check the buildout -configuration files for a project into a version control system and -later use the checked in files to get the same buildout, subject to -changes in the environment outside the buildout. - -An advantage of using Python eggs is that depenencies of eggs used are -automatically determined and used. The automatic inclusion of -depenent distributions is at odds with the goal of repeatable -buildouts. - -To support repeatable buildouts, a versions section can be created -with options for each distribution name whos version is to be fixed. -The section can then be specified via the buildout versions option. - -To see how this works, we'll create two versions of a recipe egg: - - >>> mkdir('recipe') - >>> write('recipe', 'recipe.py', - ... ''' - ... class Recipe: - ... def __init__(*a): pass - ... def install(self): - ... print 'recipe v1' - ... return () - ... update = install - ... ''') - - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='spam', version='1', py_modules=['recipe'], - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - >>> write('recipe', 'README', '') - - >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'recipe/setup.py'. - ... - - >>> rmdir('recipe', 'build') - - >>> write('recipe', 'recipe.py', - ... ''' - ... class Recipe: - ... def __init__(*a): pass - ... def install(self): - ... print 'recipe v2' - ... return () - ... update = install - ... ''') - - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='spam', version='2', py_modules=['recipe'], - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - - >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'recipe/setup.py'. - ... - -and we'll configure a buildout to use it: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... - ... [foo] - ... recipe = spam - ... ''' % join('recipe', 'dist')) - -If we run the buildout, it will use version 2: - - >>> print system(buildout), - Getting distribution for 'spam'. - Got spam 2. - Installing foo. - recipe v2 - -We can specify a versions section that lists our recipe and name it in -the buildout section: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... versions = release-1 - ... - ... [release-1] - ... spam = 1 - ... eggs = 2.2 - ... - ... [foo] - ... recipe = spam - ... ''' % join('recipe', 'dist')) - -Here we created a release-1 section listing the version 1 for the spam -distribution. We told the buildout to use it by specifying release-1 -as in the versions option. - -Now, if we run the buildout, we'll use version 1 of the spam recipe: - - >>> print system(buildout), - Getting distribution for 'spam==1'. - Got spam 1. - Uninstalling foo. - Installing foo. - recipe v1 - -Running the buildout in verbose mode will help us get information -about versions used. If we run the buildout in verbose mode without -specifying a versions section: - - >>> print system(buildout+' buildout:versions= -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout 1.0.0. - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = 0.6 - Installing 'spam'. - We have the best distribution that satisfies 'spam'. - Picked: spam = 2. - Uninstalling foo. - Installing foo. - recipe v2 - -We'll get output that includes lines that tell us what versions -buildout chose a for us, like:: - - zc.buildout.easy_install.picked: spam = 2 - -This allows us to discover versions that are picked dynamically, so -that we can fix them in a versions section. - -If we run the buildout with the versions section: - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout 1.0.0. - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = 0.6 - Installing 'spam'. - We have the distribution that satisfies 'spam==1'. - Uninstalling foo. - Installing foo. - recipe v1 - -We won't get output for the spam distribution, which we didn't pick, -but we will get output for setuptools, which we didn't specify -versions for. - -You can request buildout to generate an error if it picks any -versions: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... versions = release-1 - ... allow-picked-versions = false - ... - ... [release-1] - ... spam = 1 - ... eggs = 2.2 - ... - ... [foo] - ... recipe = spam - ... ''' % join('recipe', 'dist')) diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/rmtree.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/rmtree.py deleted file mode 100644 index a4995f2..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/rmtree.py +++ /dev/null @@ -1,66 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## - - -import shutil -import os -import doctest - -def rmtree (path): - """ - A variant of shutil.rmtree which tries hard to be successful - On windows shutil.rmtree aborts when it tries to delete a - read only file. - This tries to chmod the file to writeable and retries before giving up. - - >>> from tempfile import mkdtemp - - Let's make a directory ... - - >>> d = mkdtemp() - - and make sure it is actually there - - >>> os.path.isdir (d) - 1 - - Now create a file ... - - >>> foo = os.path.join (d, 'foo') - >>> open (foo, 'w').write ('huhu') - - and make it unwriteable - - >>> os.chmod (foo, 0400) - - rmtree should be able to remove it: - - >>> rmtree (d) - - and now the directory is gone - - >>> os.path.isdir (d) - 0 - """ - def retry_writeable (func, path, exc): - os.chmod (path, 0600) - func (path) - - shutil.rmtree (path, onerror = retry_writeable) - -def test_suite(): - return doctest.DocTestSuite() - -if "__main__" == __name__: - doctest.testmod() diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/runsetup.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/runsetup.txt deleted file mode 100644 index 469e623..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/runsetup.txt +++ /dev/null @@ -1,42 +0,0 @@ -Running setup scripts -===================== - -Buildouts are often used to work on packages that will be distributed -as eggs. During development, we use develop eggs. When you've -completed a development cycle, you'll need to run your setup script to -generate a distribution and, perhaps, uploaded it to the Python -package index. If your script uses setuptools, you'll need setuptools -in your Python path, which may be an issue if you haven't installed -setuptools into your Python installation. - -The buildout setup command is helpful in a situation like this. It -can be used to run a setup script and it does so with the setuptools -egg in the Python path and with setuptools already imported. The fact -that setuptools is imported means that you can use setuptools-based -commands, like bdist_egg even with packages that don't use setuptools. -To illustrate this, we'll create a package in a sample buildout: - - >>> mkdir('hello') - >>> write('hello', 'hello.py', 'print "Hello World!"') - >>> write('hello', 'README', 'This is hello') - >>> write('hello', 'setup.py', - ... """ - ... from distutils.core import setup - ... setup(name="hello", - ... version="1.0", - ... py_modules=["hello"], - ... author="Bob", - ... author_email="bob@foo.com", - ... ) - ... """) - -We can use the buildout command to generate the hello egg: - - >>> print system(buildout +' setup hello -q bdist_egg'), - Running setup script 'hello/setup.py'. - zip_safe flag not set; analyzing archive contents... - -The hello directory now has a hello egg in it's dist directory: - - >>> ls('hello', 'dist') - - hello-1.0-py2.4.egg diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/setup.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/setup.txt deleted file mode 100644 index ff850fc..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/setup.txt +++ /dev/null @@ -1,51 +0,0 @@ -Using zc.buildout to run setup scripts -====================================== - -zc buildout has a convenience command for running setup scripts. Why? -There are two reasons. If a setup script doesn't import setuptools, -you can't use any setuptools-provided commands, like bdist_egg. When -buildout runs a setup script, it arranges to import setuptools before -running the script so setuptools-provided commands are available. - -If you use a squeaky-clean Python to do your development, the setup -script that would import setuptools because setuptools isn't in the -path. Because buildout requires setuptools and knows where it has -installed a setuptools egg, it adds the setuptools egg to the Python -path before running the script. To run a setup script, use the -buildout setup command, passing the name of a script or a directory -containing a setup script and arguments to the script. Let's look at -an example: - - >>> mkdir('test') - >>> cd('test') - >>> write('setup.py', - ... ''' - ... from distutils.core import setup - ... setup(name='sample') - ... ''') - -We've created a super simple (stupid) setup script. Note that it -doesn't import setuptools. Let's try running it to create an egg. -We'll use the buildout script from our sample buildout: - - >>> print system(buildout+' setup'), - ... # doctest: +NORMALIZE_WHITESPACE - Error: The setup command requires the path to a setup script or - directory containing a setup script, and its arguments. - -Oops, we forgot to give the name of the setup script: - - >>> print system(buildout+' setup setup.py bdist_egg'), - ... # doctest: +ELLIPSIS - Running setup script 'setup.py'. - ... - - >>> ls('dist') - - sample-0.0.0-py2.5.egg - -Note that we can specify a directory name. This is often shorter and -preferred by the lazy :) - - >>> print system(buildout+' setup . bdist_egg'), # doctest: +ELLIPSIS - Running setup script './setup.py'. - ... diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.py deleted file mode 100644 index 768684c..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.py +++ /dev/null @@ -1,616 +0,0 @@ -############################################################################# -# -# Copyright (c) 2004-2009 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -"""Various test-support utility functions - -$Id: testing.py 116197 2010-09-04 00:02:53Z gary $ -""" - -import BaseHTTPServer -import errno -import logging -import os -import pkg_resources -import random -import re -import shutil -import socket -import subprocess -import sys -import tempfile -import textwrap -import threading -import time -import urllib2 - -import zc.buildout.buildout -import zc.buildout.easy_install -from zc.buildout.rmtree import rmtree - -fsync = getattr(os, 'fsync', lambda fileno: None) -is_win32 = sys.platform == 'win32' - -setuptools_location = pkg_resources.working_set.find( - pkg_resources.Requirement.parse('setuptools')).location - -def cat(dir, *names): - path = os.path.join(dir, *names) - if (not os.path.exists(path) - and is_win32 - and os.path.exists(path+'-script.py') - ): - path = path+'-script.py' - print open(path).read(), - -def ls(dir, *subs): - if subs: - dir = os.path.join(dir, *subs) - names = os.listdir(dir) - names.sort() - for name in names: - if os.path.isdir(os.path.join(dir, name)): - print 'd ', - elif os.path.islink(os.path.join(dir, name)): - print 'l ', - else: - print '- ', - print name - -def mkdir(*path): - os.mkdir(os.path.join(*path)) - -def remove(*path): - path = os.path.join(*path) - if os.path.isdir(path): - shutil.rmtree(path) - else: - os.remove(path) - -def rmdir(*path): - shutil.rmtree(os.path.join(*path)) - -def write(dir, *args): - path = os.path.join(dir, *(args[:-1])) - f = open(path, 'w') - f.write(args[-1]) - f.flush() - fsync(f.fileno()) - f.close() - -## FIXME - check for other platforms -MUST_CLOSE_FDS = not sys.platform.startswith('win') - -def system(command, input=''): - env = dict(os.environ) - env['COLUMNS'] = '80' - p = subprocess.Popen(command, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - close_fds=MUST_CLOSE_FDS, - env=env, - ) - i, o, e = (p.stdin, p.stdout, p.stderr) - if input: - i.write(input) - i.close() - result = o.read() + e.read() - o.close() - e.close() - return result - -def call_py(interpreter, cmd, flags=None): - if sys.platform == 'win32': - args = ['"%s"' % arg for arg in (interpreter, flags, cmd) if arg] - args.insert(-1, '"-c"') - return system('"%s"' % ' '.join(args)) - else: - cmd = repr(cmd) - return system( - ' '.join(arg for arg in (interpreter, flags, '-c', cmd) if arg)) - -def get(url): - return urllib2.urlopen(url).read() - -def _runsetup(setup, executable, *args): - if os.path.isdir(setup): - setup = os.path.join(setup, 'setup.py') - d = os.path.dirname(setup) - - args = [zc.buildout.easy_install._safe_arg(arg) - for arg in args] - args.insert(0, '-q') - env = dict(os.environ) - if executable == sys.executable: - env['PYTHONPATH'] = setuptools_location - # else pass an executable that has setuptools! See testselectingpython.py. - args.append(env) - - here = os.getcwd() - try: - os.chdir(d) - os.spawnle(os.P_WAIT, executable, - zc.buildout.easy_install._safe_arg(executable), - setup, *args) - if os.path.exists('build'): - rmtree('build') - finally: - os.chdir(here) - -def sdist(setup, dest): - _runsetup(setup, sys.executable, 'sdist', '-d', dest, '--formats=zip') - -def bdist_egg(setup, executable, dest): - _runsetup(setup, executable, 'bdist_egg', '-d', dest) - -def sys_install(setup, dest): - _runsetup(setup, sys.executable, 'install', '--install-purelib', dest, - '--record', os.path.join(dest, '__added_files__'), - '--single-version-externally-managed') - -def find_python(version): - e = os.environ.get('PYTHON%s' % version) - if e is not None: - return e - if is_win32: - e = '\Python%s%s\python.exe' % tuple(version.split('.')) - if os.path.exists(e): - return e - else: - cmd = 'python%s -c "import sys; print sys.executable"' % version - p = subprocess.Popen(cmd, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - close_fds=MUST_CLOSE_FDS) - i, o = (p.stdin, p.stdout) - i.close() - e = o.read().strip() - o.close() - if os.path.exists(e): - return e - cmd = 'python -c "import sys; print \'%s.%s\' % sys.version_info[:2]"' - p = subprocess.Popen(cmd, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - close_fds=MUST_CLOSE_FDS) - i, o = (p.stdin, p.stdout) - i.close() - e = o.read().strip() - o.close() - if e == version: - cmd = 'python -c "import sys; print sys.executable"' - p = subprocess.Popen(cmd, - shell=True, - stdin=subprocess.PIPE, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT, - close_fds=MUST_CLOSE_FDS) - i, o = (p.stdin, p.stdout) - i.close() - e = o.read().strip() - o.close() - if os.path.exists(e): - return e - - raise ValueError( - "Couldn't figure out the executable for Python %(version)s.\n" - "Set the environment variable PYTHON%(version)s to the location\n" - "of the Python %(version)s executable before running the tests." - % {'version': version}) - -def wait_until(label, func, *args, **kw): - if 'timeout' in kw: - kw = dict(kw) - timeout = kw.pop('timeout') - else: - timeout = 30 - deadline = time.time()+timeout - while time.time() < deadline: - if func(*args, **kw): - return - time.sleep(0.01) - raise ValueError('Timed out waiting for: '+label) - -def get_installer_values(): - """Get the current values for the easy_install module. - - This is necessary because instantiating a Buildout will force the - Buildout's values on the installer. - - Returns a dict of names-values suitable for set_installer_values.""" - names = ('default_versions', 'download_cache', 'install_from_cache', - 'prefer_final', 'include_site_packages', - 'allowed_eggs_from_site_packages', 'use_dependency_links', - 'allow_picked_versions', 'always_unzip' - ) - values = {} - for name in names: - values[name] = getattr(zc.buildout.easy_install, name)() - return values - -def set_installer_values(values): - """Set the given values on the installer.""" - for name, value in values.items(): - getattr(zc.buildout.easy_install, name)(value) - -def make_buildout(executable=None): - """Make a buildout that uses this version of zc.buildout.""" - # Create a basic buildout.cfg to avoid a warning from buildout. - open('buildout.cfg', 'w').write( - "[buildout]\nparts =\n" - ) - # Get state of installer defaults so we can reinstate them (instantiating - # a Buildout will force the Buildout's defaults on the installer). - installer_values = get_installer_values() - # Use the buildout bootstrap command to create a buildout - config = [ - ('buildout', 'log-level', 'WARNING'), - # trick bootstrap into putting the buildout develop egg - # in the eggs dir. - ('buildout', 'develop-eggs-directory', 'eggs'), - ] - if executable is not None: - config.append(('buildout', 'executable', executable)) - zc.buildout.buildout.Buildout( - 'buildout.cfg', config, - user_defaults=False, - ).bootstrap([]) - # Create the develop-eggs dir, which didn't get created the usual - # way due to the trick above: - os.mkdir('develop-eggs') - # Reinstate the default values of the installer. - set_installer_values(installer_values) - -def buildoutSetUp(test): - - test.globs['__tear_downs'] = __tear_downs = [] - test.globs['register_teardown'] = register_teardown = __tear_downs.append - - installer_values = get_installer_values() - register_teardown( - lambda: set_installer_values(installer_values) - ) - - here = os.getcwd() - register_teardown(lambda: os.chdir(here)) - - handlers_before_set_up = logging.getLogger().handlers[:] - def restore_root_logger_handlers(): - root_logger = logging.getLogger() - for handler in root_logger.handlers[:]: - root_logger.removeHandler(handler) - for handler in handlers_before_set_up: - root_logger.addHandler(handler) - register_teardown(restore_root_logger_handlers) - - base = tempfile.mkdtemp('buildoutSetUp') - base = os.path.realpath(base) - register_teardown(lambda base=base: rmtree(base)) - - old_home = os.environ.get('HOME') - os.environ['HOME'] = os.path.join(base, 'bbbBadHome') - def restore_home(): - if old_home is None: - del os.environ['HOME'] - else: - os.environ['HOME'] = old_home - register_teardown(restore_home) - - base = os.path.join(base, '_TEST_') - os.mkdir(base) - - tmp = tempfile.mkdtemp('buildouttests') - register_teardown(lambda: rmtree(tmp)) - - zc.buildout.easy_install.default_index_url = 'file://'+tmp - os.environ['buildout-testing-index-url'] = ( - zc.buildout.easy_install.default_index_url) - os.environ.pop('PYTHONPATH', None) - - def tmpdir(name): - path = os.path.join(base, name) - mkdir(path) - return path - - sample = tmpdir('sample-buildout') - - os.chdir(sample) - make_buildout() - - def start_server(path): - port, thread = _start_server(path, name=path) - url = 'http://localhost:%s/' % port - register_teardown(lambda: stop_server(url, thread)) - return url - - def make_py(initialization=''): - """Returns paths to new executable and to its site-packages. - """ - buildout = tmpdir('executable_buildout') - site_packages_dir = os.path.join(buildout, 'site-packages') - mkdir(site_packages_dir) - old_wd = os.getcwd() - os.chdir(buildout) - make_buildout() - # Normally we don't process .pth files in extra-paths. We want to - # in this case so that we can test with setuptools system installs - # (--single-version-externally-managed), which use .pth files. - initialization = ( - ('import sys\n' - 'import site\n' - 'known_paths = set(sys.path)\n' - 'site_packages_dir = %r\n' - 'site.addsitedir(site_packages_dir, known_paths)\n' - ) % (site_packages_dir,)) + initialization - initialization = '\n'.join( - ' ' + line for line in initialization.split('\n')) - install_develop( - 'zc.recipe.egg', os.path.join(buildout, 'develop-eggs')) - install_develop( - 'z3c.recipe.scripts', os.path.join(buildout, 'develop-eggs')) - write('buildout.cfg', textwrap.dedent('''\ - [buildout] - parts = py - include-site-packages = false - exec-sitecustomize = false - - [py] - recipe = z3c.recipe.scripts - interpreter = py - initialization = - %(initialization)s - extra-paths = %(site-packages)s - eggs = setuptools - ''') % { - 'initialization': initialization, - 'site-packages': site_packages_dir}) - system(os.path.join(buildout, 'bin', 'buildout')) - os.chdir(old_wd) - return ( - os.path.join(buildout, 'bin', 'py'), site_packages_dir) - - test.globs.update(dict( - sample_buildout = sample, - ls = ls, - cat = cat, - mkdir = mkdir, - rmdir = rmdir, - remove = remove, - tmpdir = tmpdir, - write = write, - system = system, - call_py = call_py, - get = get, - cd = (lambda *path: os.chdir(os.path.join(*path))), - join = os.path.join, - sdist = sdist, - bdist_egg = bdist_egg, - start_server = start_server, - buildout = os.path.join(sample, 'bin', 'buildout'), - wait_until = wait_until, - make_py = make_py - )) - -def buildoutTearDown(test): - for f in test.globs['__tear_downs']: - f() - -class Server(BaseHTTPServer.HTTPServer): - - def __init__(self, tree, *args): - BaseHTTPServer.HTTPServer.__init__(self, *args) - self.tree = os.path.abspath(tree) - - __run = True - def serve_forever(self): - while self.__run: - self.handle_request() - - def handle_error(self, *_): - self.__run = False - -class Handler(BaseHTTPServer.BaseHTTPRequestHandler): - - Server.__log = False - - def __init__(self, request, address, server): - self.__server = server - self.tree = server.tree - BaseHTTPServer.BaseHTTPRequestHandler.__init__( - self, request, address, server) - - def do_GET(self): - if '__stop__' in self.path: - raise SystemExit - - if self.path == '/enable_server_logging': - self.__server.__log = True - self.send_response(200) - return - - if self.path == '/disable_server_logging': - self.__server.__log = False - self.send_response(200) - return - - path = os.path.abspath(os.path.join(self.tree, *self.path.split('/'))) - if not ( - ((path == self.tree) or path.startswith(self.tree+os.path.sep)) - and - os.path.exists(path) - ): - self.send_response(404, 'Not Found') - #self.send_response(200) - out = '<html><body>Not Found</body></html>' - #out = '\n'.join(self.tree, self.path, path) - self.send_header('Content-Length', str(len(out))) - self.send_header('Content-Type', 'text/html') - self.end_headers() - self.wfile.write(out) - return - - self.send_response(200) - if os.path.isdir(path): - out = ['<html><body>\n'] - names = os.listdir(path) - names.sort() - for name in names: - if os.path.isdir(os.path.join(path, name)): - name += '/' - out.append('<a href="%s">%s</a><br>\n' % (name, name)) - out.append('</body></html>\n') - out = ''.join(out) - self.send_header('Content-Length', str(len(out))) - self.send_header('Content-Type', 'text/html') - else: - out = open(path, 'rb').read() - self.send_header('Content-Length', len(out)) - if path.endswith('.egg'): - self.send_header('Content-Type', 'application/zip') - elif path.endswith('.gz'): - self.send_header('Content-Type', 'application/x-gzip') - elif path.endswith('.zip'): - self.send_header('Content-Type', 'application/x-gzip') - else: - self.send_header('Content-Type', 'text/html') - self.end_headers() - - self.wfile.write(out) - - def log_request(self, code): - if self.__server.__log: - print '%s %s %s' % (self.command, code, self.path) - -def _run(tree, port): - server_address = ('localhost', port) - httpd = Server(tree, server_address, Handler) - httpd.serve_forever() - -def get_port(): - for i in range(10): - port = random.randrange(20000, 30000) - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - try: - s.connect(('localhost', port)) - except socket.error: - return port - finally: - s.close() - raise RuntimeError, "Can't find port" - -def _start_server(tree, name=''): - port = get_port() - thread = threading.Thread(target=_run, args=(tree, port), name=name) - thread.setDaemon(True) - thread.start() - wait(port, up=True) - return port, thread - -def start_server(tree): - return _start_server(tree)[0] - -def stop_server(url, thread=None): - try: - urllib2.urlopen(url+'__stop__') - except Exception: - pass - if thread is not None: - thread.join() # wait for thread to stop - -def wait(port, up): - addr = 'localhost', port - for i in range(120): - time.sleep(0.25) - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect(addr) - s.close() - if up: - break - except socket.error, e: - if e[0] not in (errno.ECONNREFUSED, errno.ECONNRESET): - raise - s.close() - if not up: - break - else: - if up: - raise - else: - raise SystemError("Couln't stop server") - -def install(project, destination): - if not isinstance(destination, basestring): - destination = os.path.join(destination.globs['sample_buildout'], - 'eggs') - - dist = pkg_resources.working_set.find( - pkg_resources.Requirement.parse(project)) - if dist.location.endswith('.egg'): - destination = os.path.join(destination, - os.path.basename(dist.location), - ) - if os.path.isdir(dist.location): - shutil.copytree(dist.location, destination) - else: - shutil.copyfile(dist.location, destination) - else: - # copy link - open(os.path.join(destination, project+'.egg-link'), 'w' - ).write(dist.location) - -def install_develop(project, destination): - if not isinstance(destination, basestring): - destination = os.path.join(destination.globs['sample_buildout'], - 'develop-eggs') - - dist = pkg_resources.working_set.find( - pkg_resources.Requirement.parse(project)) - open(os.path.join(destination, project+'.egg-link'), 'w' - ).write(dist.location) - -def _normalize_path(match): - path = match.group(1) - if os.path.sep == '\\': - path = path.replace('\\\\', '/') - if path.startswith('\\'): - path = path[1:] - return '/' + path.replace(os.path.sep, '/') - -if sys.platform == 'win32': - sep = r'[\\/]' # Windows uses both sometimes. -else: - sep = re.escape(os.path.sep) -normalize_path = ( - re.compile( - r'''[^'" \t\n\r!]+%(sep)s_[Tt][Ee][Ss][Tt]_%(sep)s([^"' \t\n\r]+)''' - % dict(sep=sep)), - _normalize_path, - ) - -normalize_endings = re.compile('\r\n'), '\n' - -normalize_script = ( - re.compile('(\n?)- ([a-zA-Z_.-]+)-script.py\n- \\2.exe\n'), - '\\1- \\2\n') - -normalize_egg_py = ( - re.compile('-py\d[.]\d(-\S+)?.egg'), - '-pyN.N.egg', - ) diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.txt deleted file mode 100644 index 64cb1bf..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing.txt +++ /dev/null @@ -1,181 +0,0 @@ -Testing Support -=============== - -The zc.buildout.testing module provides an API that can be used when -writing recipe tests. This API is documented below. Many examples of -using this API can be found in the zc.buildout, zc.recipe.egg, and -zc.recipe.testrunner tests. - -zc.buildout.testing.buildoutSetUp(test) ---------------------------------------- - -The buildoutSetup function can be used as a doctest setup function. -It creates a sample buildout that can be used by tests, changing the -current working directory to the sample_buildout. It also adds a -number of names to the test namespace: - -``sample_buildout`` - This is the name of a buildout with a basic configuration. - -``buildout`` - This is the path of the buildout script in the sample buildout. - -``ls(*path)`` - List the contents of a directory. The directory path is provided as one or - more strings, to be joined with os.path.join. - -``cat(*path)`` - Display the contents of a file. The file path is provided as one or - more strings, to be joined with os.path.join. - - On Windows, if the file doesn't exist, the function will try - adding a '-script.py' suffix. This helps to work around a - difference in script generation on windows. - -``mkdir(*path)`` - Create a directory. The directory path is provided as one or - more strings, to be joined with os.path.join. - -``rmdir(*path)`` - Remove a directory. The directory path is provided as one or - more strings, to be joined with os.path.join. - -``remove(*path)`` - Remove a directory or file. The path is provided as one or - more strings, to be joined with os.path.join. - -``tmpdir(name)`` - Create a temporary directory with the given name. The directory - will be automatically removed at the end of the test. The path of - the created directory is returned. - - Further, if the the normalize_path normlaizing substitution (see - below) is used, then any paths starting with this path will be - normalized to:: - - /name/restofpath - - No two temporary directories can be created with the same name. A - directory created with tmpdir can be removed with rmdir and recreated. - - Note that the sample_buildout directory is created by calling this - function. - -``write(*path_and_contents)`` - Create a file. The file path is provided as one or more strings, - to be joined with os.path.join. The last argument is the file contents. - -``system(command, input='')`` - Execute a system command with the given input passed to the - command's standard input. The output (error and regular output) - from the command is returned. - -``get(url)`` - Get a web page. - -``cd(*path)`` - Change to the given directory. The directory path is provided as one or - more strings, to be joined with os.path.join. - - The directory will be reset at the end of the test. - -``join(*path)`` - A convenient reference to os.path.join. - -``register_teardown(func)`` - Register a tear-down function. The function will be called with - no arguments at the end of the test. - -``start_server(path)`` - Start a web server on the given path. The server will be shut - down at the end of the test. The server URL is returned. - - You can cause the server to start and stop logging it's output - using: - - >>> get(server_url+'enable_server_logging') - - and: - - >>> get(server_url+'disable_server_logging') - - This can be useful to see how buildout is interacting with a - server. - - -``sdist(setup, dest)`` - Create a source distribution by running the given setup file and - placing the result in the given destination directory. If the - setup argument is a directory, the thge setup.py file in that - directory is used. - -``bdist_egg(setup, executable, dest)`` - Create an egg by running the given setup file with the given - Python executable and placing the result in the given destination - directory. If the setup argument is a directory, then the - setup.py file in that directory is used. - -``find_python(version)`` - Find a Python executable for the given version, where version is a - string like "2.4". - - This function uses the following strategy to find a Python of the - given version: - - - Look for an environment variable of the form PYTHON%(version)s. - - - On windows, look for \Pythonm%(version)s\python - - - on Unix, try running python%(version)s or just python to get the - executable - -``zc.buildout.testing.buildoutTearDown(test)`` ----------------------------------------------- - -Tear down everything set up by zc.buildout.testing.buildoutSetUp. Any -functions passed to register_teardown are called as well. - -``install(project, destination)`` ---------------------------------- - -Install eggs for a given project into a destination. If the -destination is a test object, then the eggs directory of the -sample buildout (sample_buildout) defined by the test will be used. -Tests will use this to install the distributions for the packages -being tested (and their dependencies) into a sample buildout. The egg -to be used should already be loaded, by importing one of the modules -provided, before calling this function. - -``install_develop(project, destination)`` ------------------------------------------ - -Like install, but a develop egg is installed even if the current egg -if not a develop egg. - -``Output normalization`` ------------------------- - -Recipe tests often generate output that is dependent on temporary file -locations, operating system conventions or Python versions. To deal -with these dependencies, we often use -zope.testing.renormalizing.RENormalizing to normalize test output. -zope.testing.renormalizing.RENormalizing takes pairs of regular -expressions and substitutions. The zc.buildout.testing module provides -a few helpful variables that define regular-expression/substitution -pairs that you can pass to zope.testing.renormalizing.RENormalizing. - - -``normalize_path`` - Converts tests paths, based on directories created with tmpdir(), - to simple paths. - -``normalize_script`` - On Unix-like systems, scripts are implemented in single files - without suffixes. On windows, scripts are implemented with 2 - files, a -script.py file and a .exe file. This normalization - converts directory listings of Windows scripts to the form - generated on UNix-like systems. - -``normalize_egg_py`` - Normalize Python version and platform indicators, if specified, in - egg names. diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing_bugfix.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing_bugfix.txt deleted file mode 100644 index 3bd13ee..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testing_bugfix.txt +++ /dev/null @@ -1,39 +0,0 @@ -Bug fixes in zc.buildout.testing -================================ - -Logging handler which did not get deleted ------------------------------------------ - -The buildout testing set up runs a buildout which adds a -``logging.StreamHandler`` to the root logger. But tear down did not -remove it. This can disturb other tests of packages reusing -zc.buildout.testing. - -The handers before calling set up are: - - >>> import logging - >>> len(logging.getLogger().handlers) - 1 - >>> logging.getLogger().handlers # doctest: +ELLIPSIS - [<zope...testrunner.logsupport.NullHandler instance at ...>] - -After calling it, a ``logging.StreamHandler`` was added: - - >>> import zc.buildout.testing - >>> import doctest - >>> test = doctest.DocTestParser().get_doctest( - ... '>>> x', {}, 'foo', 'foo.py', 0) - >>> zc.buildout.testing.buildoutSetUp(test) - >>> len(logging.getLogger().handlers) - 2 - >>> logging.getLogger().handlers # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - [<zope...testrunner.logsupport.NullHandler instance at ...>, - <logging.StreamHandler instance at ...>] - -But tear down removes the new logging handler: - - >>> zc.buildout.testing.buildoutTearDown(test) - >>> len(logging.getLogger().handlers) - 1 - >>> logging.getLogger().handlers # doctest: +ELLIPSIS - [<zope...testrunner.logsupport.NullHandler instance at ...>] diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testrecipes.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testrecipes.py deleted file mode 100644 index f0eb9d7..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testrecipes.py +++ /dev/null @@ -1,16 +0,0 @@ - -class Debug: - - def __init__(self, buildout, name, options): - self.buildout = buildout - self.name = name - self.options = options - - def install(self): - items = self.options.items() - items.sort() - for option, value in items: - print " %s=%r" % (option, value) - return () - - update = install diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/tests.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/tests.py deleted file mode 100644 index bf8a715..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/tests.py +++ /dev/null @@ -1,4190 +0,0 @@ -############################################################################## -# -# Copyright (c) 2004-2009 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -import doctest -from zope.testing import renormalizing -import os -import pkg_resources -import re -import shutil -import sys -import tempfile -import unittest -import zc.buildout.easy_install -import zc.buildout.testing -import zc.buildout.testselectingpython -import zipfile - -os_path_sep = os.path.sep -if os_path_sep == '\\': - os_path_sep *= 2 - - -def develop_w_non_setuptools_setup_scripts(): - """ -We should be able to deal with setup scripts that aren't setuptools based. - - >>> mkdir('foo') - >>> write('foo', 'setup.py', - ... ''' - ... from distutils.core import setup - ... setup(name="foo") - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = foo - ... parts = - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - - >>> ls('develop-eggs') - - foo.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - - """ - -def develop_verbose(): - """ -We should be able to deal with setup scripts that aren't setuptools based. - - >>> mkdir('foo') - >>> write('foo', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name="foo") - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = foo - ... parts = - ... ''') - - >>> print system(join('bin', 'buildout')+' -vv'), # doctest: +ELLIPSIS - Installing... - Develop: '/sample-buildout/foo' - ... - Installed /sample-buildout/foo - ... - - >>> ls('develop-eggs') - - foo.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - - >>> print system(join('bin', 'buildout')+' -vvv'), # doctest: +ELLIPSIS - Installing... - Develop: '/sample-buildout/foo' - in: '/sample-buildout/foo' - ... -q develop -mxN -d /sample-buildout/develop-eggs/... - - - """ - -def buildout_error_handling(): - r"""Buildout error handling - -Asking for a section that doesn't exist, yields a missing section error: - - >>> import os - >>> os.chdir(sample_buildout) - >>> import zc.buildout.buildout - >>> buildout = zc.buildout.buildout.Buildout('buildout.cfg', []) - >>> buildout['eek'] - Traceback (most recent call last): - ... - MissingSection: The referenced section, 'eek', was not defined. - -Asking for an option that doesn't exist, a MissingOption error is raised: - - >>> buildout['buildout']['eek'] - Traceback (most recent call last): - ... - MissingOption: Missing option: buildout:eek - -It is an error to create a variable-reference cycle: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... parts = - ... x = ${buildout:y} - ... y = ${buildout:z} - ... z = ${buildout:x} - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - While: - Initializing. - Getting section buildout. - Initializing section buildout. - Getting option buildout:y. - Getting option buildout:z. - Getting option buildout:x. - Getting option buildout:y. - Error: Circular reference in substitutions. - -It is an error to use funny characters in variable refereces: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = data_dir debug - ... x = ${bui$ldout:y} - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Initializing. - Getting section buildout. - Initializing section buildout. - Getting option buildout:x. - Error: The section name in substitution, ${bui$ldout:y}, - has invalid characters. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = data_dir debug - ... x = ${buildout:y{z} - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Initializing. - Getting section buildout. - Initializing section buildout. - Getting option buildout:x. - Error: The option name in substitution, ${buildout:y{z}, - has invalid characters. - -and too have too many or too few colons: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = data_dir debug - ... x = ${parts} - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Initializing. - Getting section buildout. - Initializing section buildout. - Getting option buildout:x. - Error: The substitution, ${parts}, - doesn't contain a colon. - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = data_dir debug - ... x = ${buildout:y:z} - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Initializing. - Getting section buildout. - Initializing section buildout. - Getting option buildout:x. - Error: The substitution, ${buildout:y:z}, - has too many colons. - -Al parts have to have a section: - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Installing. - Getting section x. - Error: The referenced section, 'x', was not defined. - -and all parts have to have a specified recipe: - - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... - ... [x] - ... foo = 1 - ... ''') - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')), - While: - Installing. - Error: Missing option: x:recipe - -""" - -make_dist_that_requires_setup_py_template = """ -from setuptools import setup -setup(name=%r, version=%r, - install_requires=%r, - ) -""" - -def make_dist_that_requires(dest, name, requires=[], version=1, egg=''): - os.mkdir(os.path.join(dest, name)) - open(os.path.join(dest, name, 'setup.py'), 'w').write( - make_dist_that_requires_setup_py_template - % (name, version, requires) - ) - -def show_who_requires_when_there_is_a_conflict(): - """ -It's a pain when we require eggs that have requirements that are -incompatible. We want the error we get to tell us what is missing. - -Let's make a few develop distros, some of which have incompatible -requirements. - - >>> make_dist_that_requires(sample_buildout, 'sampley', - ... ['demoneeded ==1.0']) - >>> make_dist_that_requires(sample_buildout, 'samplez', - ... ['demoneeded ==1.1']) - -Now, let's create a buildout that requires y and z: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... develop = sampley samplez - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = sampley - ... samplez - ... ''' % globals()) - - >>> print system(buildout), - Develop: '/sample-buildout/sampley' - Develop: '/sample-buildout/samplez' - Installing eggs. - Getting distribution for 'demoneeded==1.1'. - Got demoneeded 1.1. - While: - Installing eggs. - Error: There is a version conflict. - We already have: demoneeded 1.1 - but sampley 1 requires 'demoneeded==1.0'. - -Here, we see that sampley required an older version of demoneeded. What -if we hadn't required sampley ourselves: - - >>> make_dist_that_requires(sample_buildout, 'samplea', ['sampleb']) - >>> make_dist_that_requires(sample_buildout, 'sampleb', - ... ['sampley', 'samplea']) - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... develop = sampley samplez samplea sampleb - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = samplea - ... samplez - ... ''' % globals()) - -If we use the verbose switch, we can see where requirements are coming from: - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout 1.0.0 - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = 0.6 - Develop: '/sample-buildout/sampley' - Develop: '/sample-buildout/samplez' - Develop: '/sample-buildout/samplea' - Develop: '/sample-buildout/sampleb' - ...Installing eggs. - Installing 'samplea', 'samplez'. - We have a develop egg: samplea 1 - We have a develop egg: samplez 1 - Getting required 'demoneeded==1.1' - required by samplez 1. - We have the distribution that satisfies 'demoneeded==1.1'. - Getting required 'sampleb' - required by samplea 1. - We have a develop egg: sampleb 1 - Getting required 'sampley' - required by sampleb 1. - We have a develop egg: sampley 1 - While: - Installing eggs. - Error: There is a version conflict. - We already have: demoneeded 1.1 - but sampley 1 requires 'demoneeded==1.0'. - """ - -def show_who_requires_missing_distributions(): - """ - -When working with a lot of eggs, which require eggs recursively, it can -be hard to tell why we're requiring things we can't find. Fortunately, -buildout will tell us who's asking for something that we can't find. - - >>> make_dist_that_requires(sample_buildout, 'sampley', ['demoneeded']) - >>> make_dist_that_requires(sample_buildout, 'samplea', ['sampleb']) - >>> make_dist_that_requires(sample_buildout, 'sampleb', - ... ['sampley', 'samplea']) - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... develop = sampley samplea sampleb - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = samplea - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/sampley' - Develop: '/sample-buildout/samplea' - Develop: '/sample-buildout/sampleb' - Installing eggs. - Couldn't find index page for 'demoneeded' (maybe misspelled?) - Getting distribution for 'demoneeded'. - While: - Installing eggs. - Getting distribution for 'demoneeded'. - Error: Couldn't find a distribution for 'demoneeded'. - """ - -def show_eggs_from_site_packages(): - """ -Sometimes you want to know what eggs are coming from site-packages. This -might be for a diagnostic, or so that you can get a starting value for the -allowed-eggs-from-site-packages option. The -v flag will also include this -information. - -Our "py_path" has the "demoneeded," "demo" -packages available. We'll ask for "bigdemo," which will get both of them. - -Here's our set up. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... prefer-final = true - ... find-links = %(link_server)s - ... - ... [primed_python] - ... executable = %(py_path)s - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... python = primed_python - ... eggs = bigdemo - ... ''' % globals()) - -Now here is the output. The lines that begin with "Egg from site-packages:" -indicate the eggs from site-packages that have been selected. You'll see -we have two: demo 0.3 and demoneeded 1.1. - - >>> print system(buildout+" -v"), - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout V - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = V - Installing 'zc.recipe.egg'. - We have a develop egg: zc.recipe.egg V - Installing eggs. - Installing 'bigdemo'. - We have no distributions for bigdemo that satisfies 'bigdemo'. - Getting distribution for 'bigdemo'. - Got bigdemo 0.1. - Picked: bigdemo = 0.1 - Getting required 'demo' - required by bigdemo 0.1. - We have the best distribution that satisfies 'demo'. - Egg from site-packages: demo 0.3 - Getting required 'demoneeded' - required by demo 0.3. - We have the best distribution that satisfies 'demoneeded'. - Egg from site-packages: demoneeded 1.1 - """ - -def test_comparing_saved_options_with_funny_characters(): - """ -If an option has newlines, extra/odd spaces or a %, we need to make sure -the comparison with the saved value works correctly. - - >>> mkdir(sample_buildout, 'recipes') - >>> write(sample_buildout, 'recipes', 'debug.py', - ... ''' - ... class Debug: - ... def __init__(self, buildout, name, options): - ... options['debug'] = \"\"\" <zodb> - ... - ... <filestorage> - ... path foo - ... </filestorage> - ... - ... </zodb> - ... \"\"\" - ... options['debug1'] = \"\"\" - ... <zodb> - ... - ... <filestorage> - ... path foo - ... </filestorage> - ... - ... </zodb> - ... \"\"\" - ... options['debug2'] = ' x ' - ... options['debug3'] = '42' - ... options['format'] = '%3d' - ... - ... def install(self): - ... open('t', 'w').write('t') - ... return 't' - ... - ... update = install - ... ''') - - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup( - ... name = "recipes", - ... entry_points = {'zc.buildout': ['default = debug:Debug']}, - ... ) - ... ''') - - >>> write(sample_buildout, 'recipes', 'README.txt', " ") - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = debug - ... - ... [debug] - ... recipe = recipes - ... ''') - - >>> os.chdir(sample_buildout) - >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing debug. - -If we run the buildout again, we shoudn't get a message about -uninstalling anything because the configuration hasn't changed. - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Updating debug. -""" - -def finding_eggs_as_local_directories(): - r""" -It is possible to set up find-links so that we could install from -a local directory that may contained unzipped eggs. - - >>> src = tmpdir('src') - >>> write(src, 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='demo', py_modules=[''], - ... zip_safe=False, version='1.0', author='bob', url='bob', - ... author_email='bob') - ... ''') - - >>> write(src, 't.py', '#\n') - >>> write(src, 'README.txt', '') - >>> _ = system(join('bin', 'buildout')+' setup ' + src + ' bdist_egg') - -Install it so it gets unzipped: - - >>> d1 = tmpdir('d1') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], d1, links=[join(src, 'dist')], - ... ) - - >>> ls(d1) - d demo-1.0-py2.4.egg - -Then try to install it again: - - >>> d2 = tmpdir('d2') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], d2, links=[d1], - ... ) - - >>> ls(d2) - d demo-1.0-py2.4.egg - - """ - -def make_sure__get_version_works_with_2_digit_python_versions(): - """ - -This is a test of an internal function used by higher-level machinery. - -We'll start by creating a faux 'python' that executable that prints a -2-digit version. This is a bit of a pain to do portably. :( - - >>> mkdir('demo') - >>> write('demo', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='demo', - ... entry_points = {'console_scripts': ['demo = demo:main']}, - ... ) - ... ''') - >>> write('demo', 'demo.py', - ... ''' - ... def main(): - ... print 'Python 2.5' - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = demo - ... parts = - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/demo' - - >>> import zc.buildout.easy_install - >>> ws = zc.buildout.easy_install.working_set( - ... ['demo'], sys.executable, ['develop-eggs']) - >>> bool(zc.buildout.easy_install.scripts( - ... ['demo'], ws, sys.executable, 'bin')) - True - - >>> print system(join('bin', 'demo')), - Python 2.5 - -Now, finally, let's test _get_version: - - >>> zc.buildout.easy_install._get_version(join('bin', 'demo')) - '2.5' - - """ - -def create_sections_on_command_line(): - """ - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = - ... x = ${foo:bar} - ... ''') - - >>> print system(buildout + ' foo:bar=1 -vv'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - ... - [foo] - bar = 1 - ... - - """ - -def test_help(): - """ - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout')+' -h'), - ... # doctest: +ELLIPSIS - Usage: buildout [options] [assignments] [command [command arguments]] - <BLANKLINE> - Options: - <BLANKLINE> - -h, --help - ... - - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout') - ... +' --help'), - ... # doctest: +ELLIPSIS - Usage: buildout [options] [assignments] [command [command arguments]] - <BLANKLINE> - Options: - <BLANKLINE> - -h, --help - ... - """ - -def test_bootstrap_with_extension(): - """ -We had a problem running a bootstrap with an extension. Let's make -sure it is fixed. Basically, we don't load extensions when -bootstrapping. - - >>> d = tmpdir('sample-bootstrap') - - >>> write(d, 'buildout.cfg', - ... ''' - ... [buildout] - ... extensions = some_awsome_extension - ... parts = - ... ''') - - >>> os.chdir(d) - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout') - ... + ' bootstrap'), - Creating directory '/sample-bootstrap/bin'. - Creating directory '/sample-bootstrap/parts'. - Creating directory '/sample-bootstrap/eggs'. - Creating directory '/sample-bootstrap/develop-eggs'. - Generated script '/sample-bootstrap/bin/buildout'. - """ - - -def bug_92891_bootstrap_crashes_with_egg_recipe_in_buildout_section(): - """ - >>> d = tmpdir('sample-bootstrap') - - >>> write(d, 'buildout.cfg', - ... ''' - ... [buildout] - ... parts = buildout - ... eggs-directory = eggs - ... - ... [buildout] - ... recipe = zc.recipe.egg - ... eggs = zc.buildout - ... scripts = buildout=buildout - ... ''') - - >>> os.chdir(d) - >>> print system(os.path.join(sample_buildout, 'bin', 'buildout') - ... + ' bootstrap'), - Creating directory '/sample-bootstrap/bin'. - Creating directory '/sample-bootstrap/parts'. - Creating directory '/sample-bootstrap/eggs'. - Creating directory '/sample-bootstrap/develop-eggs'. - Generated script '/sample-bootstrap/bin/buildout'. - - >>> print system(os.path.join('bin', 'buildout')), - Unused options for buildout: 'scripts' 'eggs'. - - """ - -def removing_eggs_from_develop_section_causes_egg_link_to_be_removed(): - ''' - >>> cd(sample_buildout) - -Create a develop egg: - - >>> mkdir('foo') - >>> write('foo', 'setup.py', - ... """ - ... from setuptools import setup - ... setup(name='foox') - ... """) - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = foo - ... parts = - ... """) - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - - >>> ls('develop-eggs') - - foox.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - -Create another: - - >>> mkdir('bar') - >>> write('bar', 'setup.py', - ... """ - ... from setuptools import setup - ... setup(name='fooy') - ... """) - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = foo bar - ... parts = - ... """) - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - Develop: '/sample-buildout/bar' - - >>> ls('develop-eggs') - - foox.egg-link - - fooy.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - -Remove one: - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = bar - ... parts = - ... """) - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/bar' - -It is gone - - >>> ls('develop-eggs') - - fooy.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - -Remove the other: - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... parts = - ... """) - >>> print system(join('bin', 'buildout')), - -All gone - - >>> ls('develop-eggs') - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - ''' - - -def add_setuptools_to_dependencies_when_namespace_packages(): - ''' -Often, a package depends on setuptools soley by virtue of using -namespace packages. In this situation, package authors often forget to -declare setuptools as a dependency. This is a mistake, but, -unfortunately, a common one that we need to work around. If an egg -uses namespace packages and does not include setuptools as a depenency, -we will still include setuptools in the working set. If we see this for -a devlop egg, we will also generate a warning. - - >>> mkdir('foo') - >>> mkdir('foo', 'src') - >>> mkdir('foo', 'src', 'stuff') - >>> write('foo', 'src', 'stuff', '__init__.py', - ... """__import__('pkg_resources').declare_namespace(__name__) - ... """) - >>> mkdir('foo', 'src', 'stuff', 'foox') - >>> write('foo', 'src', 'stuff', 'foox', '__init__.py', '') - >>> write('foo', 'setup.py', - ... """ - ... from setuptools import setup - ... setup(name='foox', - ... namespace_packages = ['stuff'], - ... package_dir = {'': 'src'}, - ... packages = ['stuff', 'stuff.foox'], - ... ) - ... """) - >>> write('foo', 'README.txt', '') - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = foo - ... parts = - ... """) - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - -Now, if we generate a working set using the egg link, we will get a warning -and we will get setuptools included in the working set. - - >>> import logging, zope.testing.loggingsupport - >>> handler = zope.testing.loggingsupport.InstalledHandler( - ... 'zc.buildout.easy_install', level=logging.WARNING) - >>> logging.getLogger('zc.buildout.easy_install').propagate = False - - >>> [dist.project_name - ... for dist in zc.buildout.easy_install.working_set( - ... ['foox'], sys.executable, - ... [join(sample_buildout, 'eggs'), - ... join(sample_buildout, 'develop-eggs'), - ... ])] - ['foox', 'setuptools'] - - >>> print handler - zc.buildout.easy_install WARNING - Develop distribution: foox 0.0.0 - uses namespace packages but the distribution does not require setuptools. - - >>> handler.clear() - -On the other hand, if we have a regular egg, rather than a develop egg: - - >>> os.remove(join('develop-eggs', 'foox.egg-link')) - - >>> _ = system(join('bin', 'buildout') + ' setup foo bdist_egg -d' - ... + join(sample_buildout, 'eggs')) - - >>> ls('develop-eggs') - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - - >>> print 'START ->'; ls('eggs') # doctest: +ELLIPSIS - START... - - foox-0.0.0-py2.4.egg - ... - -We do not get a warning, but we do get setuptools included in the working set: - - >>> [dist.project_name - ... for dist in zc.buildout.easy_install.working_set( - ... ['foox'], sys.executable, - ... [join(sample_buildout, 'eggs'), - ... join(sample_buildout, 'develop-eggs'), - ... ])] - ['foox', 'setuptools'] - - >>> print handler, - -We get the same behavior if the it is a depedency that uses a -namespace package. - - - >>> mkdir('bar') - >>> write('bar', 'setup.py', - ... """ - ... from setuptools import setup - ... setup(name='bar', install_requires = ['foox']) - ... """) - >>> write('bar', 'README.txt', '') - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = foo bar - ... parts = - ... """) - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - Develop: '/sample-buildout/bar' - - >>> [dist.project_name - ... for dist in zc.buildout.easy_install.working_set( - ... ['bar'], sys.executable, - ... [join(sample_buildout, 'eggs'), - ... join(sample_buildout, 'develop-eggs'), - ... ])] - ['bar', 'foox', 'setuptools'] - - >>> print handler, - zc.buildout.easy_install WARNING - Develop distribution: foox 0.0.0 - uses namespace packages but the distribution does not require setuptools. - - - >>> logging.getLogger('zc.buildout.easy_install').propagate = True - >>> handler.uninstall() - - ''' - -def develop_preserves_existing_setup_cfg(): - """ - -See "Handling custom build options for extensions in develop eggs" in -easy_install.txt. This will be very similar except that we'll have an -existing setup.cfg: - - >>> write(extdemo, "setup.cfg", - ... ''' - ... # sampe cfg file - ... - ... [foo] - ... bar = 1 - ... - ... [build_ext] - ... define = X,Y - ... ''') - - >>> mkdir('include') - >>> write('include', 'extdemo.h', - ... ''' - ... #define EXTDEMO 42 - ... ''') - - >>> dest = tmpdir('dest') - >>> zc.buildout.easy_install.develop( - ... extdemo, dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}) - '/dest/extdemo.egg-link' - - >>> ls(dest) - - extdemo.egg-link - - >>> cat(extdemo, "setup.cfg") - <BLANKLINE> - # sampe cfg file - <BLANKLINE> - [foo] - bar = 1 - <BLANKLINE> - [build_ext] - define = X,Y - -""" - -def uninstall_recipes_used_for_removal(): - """ -Uninstall recipes need to be called when a part is removed too: - - >>> mkdir("recipes") - >>> write("recipes", "setup.py", - ... ''' - ... from setuptools import setup - ... setup(name='recipes', - ... entry_points={ - ... 'zc.buildout': ["demo=demo:Install"], - ... 'zc.buildout.uninstall': ["demo=demo:uninstall"], - ... }) - ... ''') - - >>> write("recipes", "demo.py", - ... ''' - ... class Install: - ... def __init__(*args): pass - ... def install(self): - ... print 'installing' - ... return () - ... def uninstall(name, options): print 'uninstalling' - ... ''') - - >>> write('buildout.cfg', ''' - ... [buildout] - ... develop = recipes - ... parts = demo - ... [demo] - ... recipe = recipes:demo - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/recipes' - Installing demo. - installing - - - >>> write('buildout.cfg', ''' - ... [buildout] - ... develop = recipes - ... parts = demo - ... [demo] - ... recipe = recipes:demo - ... x = 1 - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/recipes' - Uninstalling demo. - Running uninstall recipe. - uninstalling - Installing demo. - installing - - - >>> write('buildout.cfg', ''' - ... [buildout] - ... develop = recipes - ... parts = - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/recipes' - Uninstalling demo. - Running uninstall recipe. - uninstalling - -""" - -def extensions_installed_as_eggs_work_in_offline_mode(): - ''' - >>> mkdir('demo') - - >>> write('demo', 'demo.py', - ... """ - ... def ext(buildout): - ... print 'ext', list(buildout) - ... """) - - >>> write('demo', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup( - ... name = "demo", - ... py_modules=['demo'], - ... entry_points = {'zc.buildout.extension': ['ext = demo:ext']}, - ... ) - ... """) - - >>> bdist_egg(join(sample_buildout, "demo"), sys.executable, - ... join(sample_buildout, "eggs")) - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... extensions = demo - ... parts = - ... offline = true - ... """) - - >>> print system(join(sample_buildout, 'bin', 'buildout')), - ext ['buildout'] - - - ''' - -def changes_in_svn_or_CVS_dont_affect_sig(): - """ - -If we have a develop recipe, it's signature shouldn't be affected to -changes in .svn or CVS directories. - - >>> mkdir('recipe') - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='recipe', - ... entry_points={'zc.buildout': ['default=foo:Foo']}) - ... ''') - >>> write('recipe', 'foo.py', - ... ''' - ... class Foo: - ... def __init__(*args): pass - ... def install(*args): return () - ... update = install - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipe - ... parts = foo - ... - ... [foo] - ... recipe = recipe - ... ''') - - - >>> print system(join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/recipe' - Installing foo. - - >>> mkdir('recipe', '.svn') - >>> mkdir('recipe', 'CVS') - >>> print system(join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/recipe' - Updating foo. - - >>> write('recipe', '.svn', 'x', '1') - >>> write('recipe', 'CVS', 'x', '1') - - >>> print system(join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/recipe' - Updating foo. - - """ - -if hasattr(os, 'symlink'): - def bug_250537_broken_symlink_doesnt_affect_sig(): - """ -If we have a develop recipe, it's signature shouldn't be affected by -broken symlinks, and better yet, computing the hash should not break -because of the missing target file. - - >>> mkdir('recipe') - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='recipe', - ... entry_points={'zc.buildout': ['default=foo:Foo']}) - ... ''') - >>> write('recipe', 'foo.py', - ... ''' - ... class Foo: - ... def __init__(*args): pass - ... def install(*args): return () - ... update = install - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipe - ... parts = foo - ... - ... [foo] - ... recipe = recipe - ... ''') - - - >>> print system(join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/recipe' - Installing foo. - - >>> write('recipe', 'some-file', '1') - >>> os.symlink(join('recipe', 'some-file'), - ... join('recipe', 'another-file')) - >>> ls('recipe') - l another-file - - foo.py - - foo.pyc - d recipe.egg-info - - setup.py - - some-file - - >>> remove('recipe', 'some-file') - - >>> print system(join(sample_buildout, 'bin', 'buildout')), - Develop: '/sample-buildout/recipe' - Updating foo. - - """ - -def o_option_sets_offline(): - """ - >>> print system(join(sample_buildout, 'bin', 'buildout')+' -vvo'), - ... # doctest: +ELLIPSIS - <BLANKLINE> - ... - offline = true - ... - """ - -def recipe_upgrade(): - """ - -The buildout will upgrade recipes in newest (and non-offline) mode. - -Let's create a recipe egg - - >>> mkdir('recipe') - >>> write('recipe', 'recipe.py', - ... ''' - ... class Recipe: - ... def __init__(*a): pass - ... def install(self): - ... print 'recipe v1' - ... return () - ... update = install - ... ''') - - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='recipe', version='1', py_modules=['recipe'], - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - >>> write('recipe', 'README', '') - - >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'recipe/setup.py'. - ... - - >>> rmdir('recipe', 'build') - -And update our buildout to use it. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... - ... [foo] - ... recipe = recipe - ... ''' % join('recipe', 'dist')) - - >>> print system(buildout), - Getting distribution for 'recipe'. - Got recipe 1. - Installing foo. - recipe v1 - -Now, if we update the recipe egg: - - >>> write('recipe', 'recipe.py', - ... ''' - ... class Recipe: - ... def __init__(*a): pass - ... def install(self): - ... print 'recipe v2' - ... return () - ... update = install - ... ''') - - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='recipe', version='2', py_modules=['recipe'], - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - - >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'recipe/setup.py'. - ... - -We won't get the update if we specify -N: - - >>> print system(buildout+' -N'), - Updating foo. - recipe v1 - -or if we use -o: - - >>> print system(buildout+' -o'), - Updating foo. - recipe v1 - -But we will if we use neither of these: - - >>> print system(buildout), - Getting distribution for 'recipe'. - Got recipe 2. - Uninstalling foo. - Installing foo. - recipe v2 - -We can also select a particular recipe version: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... - ... [foo] - ... recipe = recipe ==1 - ... ''' % join('recipe', 'dist')) - - >>> print system(buildout), - Uninstalling foo. - Installing foo. - recipe v1 - - """ - -def update_adds_to_uninstall_list(): - """ - -Paths returned by the update method are added to the list of paths to -uninstall - - >>> mkdir('recipe') - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='recipe', - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - >>> write('recipe', 'recipe.py', - ... ''' - ... import os - ... class Recipe: - ... def __init__(*_): pass - ... def install(self): - ... r = ('a', 'b', 'c') - ... for p in r: os.mkdir(p) - ... return r - ... def update(self): - ... r = ('c', 'd', 'e') - ... for p in r: - ... if not os.path.exists(p): - ... os.mkdir(p) - ... return r - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipe - ... parts = foo - ... - ... [foo] - ... recipe = recipe - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipe' - Installing foo. - - >>> print system(buildout), - Develop: '/sample-buildout/recipe' - Updating foo. - - >>> cat('.installed.cfg') # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE - [buildout] - ... - [foo] - __buildout_installed__ = a - b - c - d - e - __buildout_signature__ = ... - -""" - -def log_when_there_are_not_local_distros(): - """ - >>> from zope.testing.loggingsupport import InstalledHandler - >>> handler = InstalledHandler('zc.buildout.easy_install') - >>> import logging - >>> logger = logging.getLogger('zc.buildout.easy_install') - >>> old_propogate = logger.propagate - >>> logger.propagate = False - - >>> dest = tmpdir('sample-install') - >>> import zc.buildout.easy_install - >>> ws = zc.buildout.easy_install.install( - ... ['demo==0.2'], dest, - ... links=[link_server], index=link_server+'index/') - - >>> print handler # doctest: +ELLIPSIS - zc.buildout.easy_install DEBUG - Installing 'demo==0.2'. - zc.buildout.easy_install DEBUG - We have no distributions for demo that satisfies 'demo==0.2'. - ... - - >>> handler.uninstall() - >>> logger.propagate = old_propogate - - """ - -def internal_errors(): - """Internal errors are clearly marked and don't generate tracebacks: - - >>> mkdir(sample_buildout, 'recipes') - - >>> write(sample_buildout, 'recipes', 'mkdir.py', - ... ''' - ... class Mkdir: - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... options['path'] = os.path.join( - ... buildout['buildout']['directory'], - ... options['path'], - ... ) - ... ''') - - >>> write(sample_buildout, 'recipes', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name = "recipes", - ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']}, - ... ) - ... ''') - - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = data-dir - ... - ... [data-dir] - ... recipe = recipes:mkdir - ... ''') - - >>> print system(buildout), # doctest: +ELLIPSIS - Develop: '/sample-buildout/recipes' - While: - Installing. - Getting section data-dir. - Initializing part data-dir. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - NameError: global name 'os' is not defined - """ - -def whine_about_unused_options(): - ''' - - >>> write('foo.py', - ... """ - ... class Foo: - ... - ... def __init__(self, buildout, name, options): - ... self.name, self.options = name, options - ... options['x'] - ... - ... def install(self): - ... self.options['y'] - ... return () - ... """) - - >>> write('setup.py', - ... """ - ... from setuptools import setup - ... setup(name = "foo", - ... entry_points = {'zc.buildout': ['default = foo:Foo']}, - ... ) - ... """) - - >>> write('buildout.cfg', - ... """ - ... [buildout] - ... develop = . - ... parts = foo - ... a = 1 - ... - ... [foo] - ... recipe = foo - ... x = 1 - ... y = 1 - ... z = 1 - ... """) - - >>> print system(buildout), - Develop: '/sample-buildout/.' - Unused options for buildout: 'a'. - Installing foo. - Unused options for foo: 'z'. - ''' - -def abnormal_exit(): - """ -People sometimes hit control-c while running a builout. We need to make -sure that the installed database Isn't corrupted. To test this, we'll create -some evil recipes that exit uncleanly: - - >>> mkdir('recipes') - >>> write('recipes', 'recipes.py', - ... ''' - ... import os - ... - ... class Clean: - ... def __init__(*_): pass - ... def install(_): return () - ... def update(_): pass - ... - ... class EvilInstall(Clean): - ... def install(_): os._exit(1) - ... - ... class EvilUpdate(Clean): - ... def update(_): os._exit(1) - ... ''') - - >>> write('recipes', 'setup.py', - ... ''' - ... import setuptools - ... setuptools.setup(name='recipes', - ... entry_points = { - ... 'zc.buildout': [ - ... 'clean = recipes:Clean', - ... 'evil_install = recipes:EvilInstall', - ... 'evil_update = recipes:EvilUpdate', - ... 'evil_uninstall = recipes:Clean', - ... ], - ... }, - ... ) - ... ''') - -Now let's look at 3 cases: - -1. We exit during installation after installing some other parts: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = p1 p2 p3 p4 - ... - ... [p1] - ... recipe = recipes:clean - ... - ... [p2] - ... recipe = recipes:clean - ... - ... [p3] - ... recipe = recipes:evil_install - ... - ... [p4] - ... recipe = recipes:clean - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing p1. - Installing p2. - Installing p3. - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Updating p1. - Updating p2. - Installing p3. - - >>> print system(buildout+' buildout:parts='), - Develop: '/sample-buildout/recipes' - Uninstalling p2. - Uninstalling p1. - -2. We exit while updating: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = p1 p2 p3 p4 - ... - ... [p1] - ... recipe = recipes:clean - ... - ... [p2] - ... recipe = recipes:clean - ... - ... [p3] - ... recipe = recipes:evil_update - ... - ... [p4] - ... recipe = recipes:clean - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing p1. - Installing p2. - Installing p3. - Installing p4. - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Updating p1. - Updating p2. - Updating p3. - - >>> print system(buildout+' buildout:parts='), - Develop: '/sample-buildout/recipes' - Uninstalling p2. - Uninstalling p1. - Uninstalling p4. - Uninstalling p3. - -3. We exit while installing or updating after uninstalling: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = p1 p2 p3 p4 - ... - ... [p1] - ... recipe = recipes:evil_update - ... - ... [p2] - ... recipe = recipes:clean - ... - ... [p3] - ... recipe = recipes:clean - ... - ... [p4] - ... recipe = recipes:clean - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Installing p1. - Installing p2. - Installing p3. - Installing p4. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = p1 p2 p3 p4 - ... - ... [p1] - ... recipe = recipes:evil_update - ... - ... [p2] - ... recipe = recipes:clean - ... - ... [p3] - ... recipe = recipes:clean - ... - ... [p4] - ... recipe = recipes:clean - ... x = 1 - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling p4. - Updating p1. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = p1 p2 p3 p4 - ... - ... [p1] - ... recipe = recipes:clean - ... - ... [p2] - ... recipe = recipes:clean - ... - ... [p3] - ... recipe = recipes:clean - ... - ... [p4] - ... recipe = recipes:clean - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/recipes' - Uninstalling p1. - Installing p1. - Updating p2. - Updating p3. - Installing p4. - - """ - -def install_source_dist_with_bad_py(): - """ - - >>> mkdir('badegg') - >>> mkdir('badegg', 'badegg') - >>> write('badegg', 'badegg', '__init__.py', '#\\n') - >>> mkdir('badegg', 'badegg', 'scripts') - >>> write('badegg', 'badegg', 'scripts', '__init__.py', '#\\n') - >>> write('badegg', 'badegg', 'scripts', 'one.py', - ... ''' - ... return 1 - ... ''') - - >>> write('badegg', 'setup.py', - ... ''' - ... from setuptools import setup, find_packages - ... setup( - ... name='badegg', - ... version='1', - ... packages = find_packages('.'), - ... zip_safe=False) - ... ''') - - >>> print system(buildout+' setup badegg sdist'), # doctest: +ELLIPSIS - Running setup script 'badegg/setup.py'. - ... - - >>> dist = join('badegg', 'dist') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs bo - ... find-links = %(dist)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = badegg - ... - ... [bo] - ... recipe = zc.recipe.egg - ... eggs = zc.buildout - ... scripts = buildout=bo - ... ''' % globals()) - - >>> print system(buildout);print 'X' # doctest: +ELLIPSIS - Installing eggs. - Getting distribution for 'badegg'. - Got badegg 1. - Installing bo. - ... - SyntaxError: ...'return' outside function... - ... - SyntaxError: ...'return' outside function... - ... - - >>> ls('eggs') # doctest: +ELLIPSIS - d badegg-1-py2.4.egg - ... - - >>> ls('bin') - - bo - - buildout - """ - -def version_requirements_in_build_honored(): - ''' - - >>> update_extdemo() - >>> dest = tmpdir('sample-install') - >>> mkdir('include') - >>> write('include', 'extdemo.h', - ... """ - ... #define EXTDEMO 42 - ... """) - - >>> zc.buildout.easy_install.build( - ... 'extdemo ==1.4', dest, - ... {'include-dirs': os.path.join(sample_buildout, 'include')}, - ... links=[link_server], index=link_server+'index/', - ... newest=False) - ['/sample-install/extdemo-1.4-py2.4-linux-i686.egg'] - - ''' - -def bug_105081_Specific_egg_versions_are_ignored_when_newer_eggs_are_around(): - """ - Buildout might ignore a specific egg requirement for a recipe: - - - Have a newer version of an egg in your eggs directory - - Use 'recipe==olderversion' in your buildout.cfg to request an - older version - - Buildout will go and fetch the older version, but it will *use* - the newer version when installing a part with this recipe. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... find-links = %(sample_eggs)s - ... - ... [x] - ... recipe = zc.recipe.egg - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout), - Installing x. - Getting distribution for 'demo'. - Got demo 0.4c1. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - Generated script '/sample-buildout/bin/demo'. - - >>> print system(join('bin', 'demo')), - 4 2 - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... find-links = %(sample_eggs)s - ... - ... [x] - ... recipe = zc.recipe.egg - ... eggs = demo ==0.1 - ... ''' % globals()) - - >>> print system(buildout), - Uninstalling x. - Installing x. - Getting distribution for 'demo==0.1'. - Got demo 0.1. - Generated script '/sample-buildout/bin/demo'. - - >>> print system(join('bin', 'demo')), - 1 2 - """ - -def versions_section_ignored_for_dependency_in_favor_of_site_packages(): - r""" -This is a test for a bugfix. - -The error showed itself when at least two dependencies were in a shared -location like site-packages, and the first one met the "versions" setting. The -first dependency would be added, but subsequent dependencies from the same -location (e.g., site-packages) would use the version of the package found in -the shared location, ignoring the version setting. - -We begin with a Python that has demoneeded version 1.1 installed and a -demo version 0.3, all in a site-packages-like shared directory. We need -to create this. ``eggrecipedemo.main()`` shows the number after the dot -(that is, ``X`` in ``1.X``), for the demo package and the demoneeded -package, so this demonstrates that our Python does in fact have demo -version 0.3 and demoneeded version 1.1. - - >>> py_path = make_py_with_system_install(make_py, sample_eggs) - >>> print call_py( - ... py_path, - ... "import tellmy.version; print tellmy.version.__version__"), - 1.1 - -Now here's a setup that would expose the bug, using the -zc.buildout.easy_install API. - - >>> example_dest = tmpdir('example_dest') - >>> workingset = zc.buildout.easy_install.install( - ... ['tellmy.version'], example_dest, links=[sample_eggs], - ... executable=py_path, - ... index=None, - ... versions={'tellmy.version': '1.0'}) - >>> for dist in workingset: - ... res = str(dist) - ... if res.startswith('tellmy.version'): - ... print res - ... break - tellmy.version 1.0 - -Before the bugfix, the desired tellmy.version distribution would have -been blocked the one in site-packages. -""" - -def handle_namespace_package_in_both_site_packages_and_buildout_eggs(): - r""" -If you have the same namespace package in both site-packages and in -buildout, we need to be very careful that faux-Python-executables and -scripts generated by easy_install.sitepackage_safe_scripts correctly -combine the two. We show this with the local recipe that uses the -function, z3c.recipe.scripts. - -To demonstrate this, we will create three packages: tellmy.version 1.0, -tellmy.version 1.1, and tellmy.fortune 1.0. tellmy.version 1.1 is installed. - - >>> py_path = make_py_with_system_install(make_py, sample_eggs) - >>> print call_py( - ... py_path, - ... "import tellmy.version; print tellmy.version.__version__") - 1.1 - <BLANKLINE> - -Now we will create a buildout that creates a script and a faux-Python script. -We want to see that both can successfully import the specified versions of -tellmy.version and tellmy.fortune. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... - ... [primed_python] - ... executable = %(py_path)s - ... - ... [eggs] - ... recipe = z3c.recipe.scripts - ... python = primed_python - ... interpreter = py - ... include-site-packages = true - ... eggs = tellmy.version == 1.0 - ... tellmy.fortune == 1.0 - ... demo - ... script-initialization = - ... import tellmy.version - ... print tellmy.version.__version__ - ... import tellmy.fortune - ... print tellmy.fortune.__version__ - ... ''' % globals()) - - >>> print system(buildout) - Installing eggs. - Getting distribution for 'tellmy.version==1.0'. - Got tellmy.version 1.0. - Getting distribution for 'tellmy.fortune==1.0'. - Got tellmy.fortune 1.0. - Getting distribution for 'demo'. - Got demo 0.4c1. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - Generated script '/sample-buildout/bin/demo'. - Generated interpreter '/sample-buildout/bin/py'. - <BLANKLINE> - -Finally, we are ready to see if it worked. Prior to the bug fix that -this tests, the results of both calls below was the following:: - - 1.1 - Traceback (most recent call last): - ... - ImportError: No module named fortune - <BLANKLINE> - -In other words, we got the site-packages version of tellmy.version, and -we could not import tellmy.fortune at all. The following are the correct -results for the interpreter and for the script. - - >>> print call_py( - ... join('bin', 'py'), - ... "import tellmy.version; " + - ... "print tellmy.version.__version__; " + - ... "import tellmy.fortune; " + - ... "print tellmy.fortune.__version__") # doctest: +ELLIPSIS - 1.0 - 1.0... - - >>> print system(join('bin', 'demo')) - 1.0 - 1.0 - 4 2 - <BLANKLINE> - """ - -def handle_sys_path_version_hack(): - r""" -This is a test for a bugfix. - -If you use a Python that has a different version of one of your -dependencies, and the new package tries to do sys.path tricks in the -setup.py to get a __version__, and it uses namespace packages, the older -package will be loaded first, making the setup version the wrong number. -While very arguably packages simply shouldn't do this, some do, and we -don't want buildout to fall over when they do. - -To demonstrate this, we will need to create a distribution that has one of -these unpleasant tricks, and a Python that has an older version installed. - - >>> py_path, site_packages_path = make_py() - >>> for version in ('1.0', '1.1'): - ... tmp = tempfile.mkdtemp() - ... try: - ... write(tmp, 'README.txt', '') - ... mkdir(tmp, 'src') - ... mkdir(tmp, 'src', 'tellmy') - ... write(tmp, 'src', 'tellmy', '__init__.py', - ... "__import__(" - ... "'pkg_resources').declare_namespace(__name__)\n") - ... mkdir(tmp, 'src', 'tellmy', 'version') - ... write(tmp, 'src', 'tellmy', 'version', - ... '__init__.py', '__version__=%r\n' % version) - ... write( - ... tmp, 'setup.py', - ... "from setuptools import setup\n" - ... "import sys\n" - ... "sys.path.insert(0, 'src')\n" - ... "from tellmy.version import __version__\n" - ... "setup(\n" - ... " name='tellmy.version',\n" - ... " package_dir = {'': 'src'},\n" - ... " packages = ['tellmy', 'tellmy.version'],\n" - ... " install_requires = ['setuptools'],\n" - ... " namespace_packages=['tellmy'],\n" - ... " zip_safe=True, version=__version__,\n" - ... " author='bob', url='bob', author_email='bob')\n" - ... ) - ... zc.buildout.testing.sdist(tmp, sample_eggs) - ... if version == '1.0': - ... # We install the 1.0 version in site packages the way a - ... # system packaging system (debs, rpms) would do it. - ... zc.buildout.testing.sys_install(tmp, site_packages_path) - ... finally: - ... shutil.rmtree(tmp) - >>> print call_py( - ... py_path, - ... "import tellmy.version; print tellmy.version.__version__") - 1.0 - <BLANKLINE> - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(sample_eggs)s - ... - ... [primed_python] - ... executable = %(py_path)s - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... python = primed_python - ... eggs = tellmy.version == 1.1 - ... ''' % globals()) - -Before the bugfix, running this buildout would generate this error: - - Installing eggs. - Getting distribution for 'tellmy.version==1.1'. - Installing tellmy.version 1.1 - Caused installation of a distribution: - tellmy.version 1.0 - with a different version. - Got None. - While: - Installing eggs. - Error: There is a version conflict. - We already have: tellmy.version 1.0 - <BLANKLINE> - -You can see the copiously commented fix for this in easy_install.py (see -zc.buildout.easy_install.Installer._call_easy_install and particularly -the comment leading up to zc.buildout.easy_install._easy_install_cmd). -Now the install works correctly, as seen here. - - >>> print system(buildout) - Installing eggs. - Getting distribution for 'tellmy.version==1.1'. - Got tellmy.version 1.1. - <BLANKLINE> - - """ - -def isolated_include_site_packages(): - """ - -This is an isolated test of the include_site_packages functionality, passing -the argument directly to install, overriding a default. - -Our "py_path" has the "demoneeded" and "demo" packages available. We'll -simply be asking for "demoneeded" here. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - >>> zc.buildout.easy_install.include_site_packages(False) - True - - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, include_site_packages=True) - >>> [dist.project_name for dist in workingset] - ['demoneeded'] - -That worked fine. Let's try again with site packages not allowed (and -reversing the default). - - >>> zc.buildout.easy_install.include_site_packages(True) - False - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, include_site_packages=False) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - -That's a failure, as expected. - -Now we explore an important edge case. - -Some system Pythons include setuptools (and other Python packages) in their -site-packages (or equivalent) using a .egg-info directory. The pkg_resources -module (from setuptools) considers a package installed using .egg-info to be a -develop egg. - -zc.buildout.buildout.Buildout.bootstrap will make setuptools and zc.buildout -available to the buildout via the eggs directory, for normal eggs; or the -develop-eggs directory, for develop-eggs. - -If setuptools or zc.buildout is found in site-packages and considered by -pkg_resources to be a develop egg, then the bootstrap code will use a .egg-link -in the local develop-eggs, pointing to site-packages, in its entirety. Because -develop-eggs must always be available for searching for distributions, this -indirectly brings site-packages back into the search path for distributions. - -Because of this, we have to take special care that we still exclude -site-packages even in this case. See the comments about site packages in the -Installer._satisfied and Installer._obtain methods for the implementation -(as of this writing). - -In this demonstration, we insert a link to the "demoneeded" distribution -in our develop-eggs, which would bring the package back in, except for -the special care we have taken to exclude it. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> mkdir(example_dest, 'develop-eggs') - >>> write(example_dest, 'develop-eggs', 'demoneeded.egg-link', - ... site_packages_path) - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], - ... path=[join(example_dest, 'develop-eggs')], - ... executable=py_path, - ... index=None, include_site_packages=False) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - -The MissingDistribution error shows that buildout correctly excluded the -"site-packages" source even though it was indirectly included in the path -via a .egg-link file. - - """ - -def include_site_packages_bug_623590(): - """ -As mentioned in isolated_include_site_packages, some system Pythons -include various Python packages in their site-packages (or equivalent) -using a .egg-info directory. The pkg_resources module (from setuptools) -considers a package installed using .egg-info to be a develop egg - -We generally prefer develop eggs when we are selecting dependencies, because -we expect them to be eggs that buildout has been told to develop. However, -we should not consider these site-packages eggs as develop eggs--they should -not have automatic precedence over eggs available elsewhere. - -We have specific code to handle this case, as identified in bug 623590. -See zc.buildout.easy_install.Installer._satisfied, as of this writing, -for the pertinent code. Here's the test for the bugfix. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - >>> zc.buildout.easy_install.include_site_packages(False) - True - - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demo'], example_dest, links=[sample_eggs], executable=py_path, - ... index=None, include_site_packages=True, prefer_final=False) - >>> [(dist.project_name, dist.version) for dist in workingset] - [('demo', '0.4c1'), ('demoneeded', '1.2c1')] -""" - -def allowed_eggs_from_site_packages(): - """ -Sometimes you need or want to control what eggs from site-packages are used. -The allowed-eggs-from-site-packages option allows you to specify a whitelist of -project names that may be included from site-packages. You can use globs to -specify the value. It defaults to a single value of '*', indicating that any -package may come from site-packages. - -This option interacts with include-site-packages in the following ways. - -If include-site-packages is true, then allowed-eggs-from-site-packages filters -what eggs from site-packages may be chosen. If allowed-eggs-from-site-packages -is an empty list, then no eggs from site-packages are chosen, but site-packages -will still be included at the end of path lists. - -If include-site-packages is false, allowed-eggs-from-site-packages is -irrelevant. - -This test shows the interaction with the zc.buildout.easy_install API. Another -test below (allow_site_package_eggs_option) shows using it with a buildout.cfg. - -Our "py_path" has the "demoneeded" and "demo" packages available. We'll -simply be asking for "demoneeded" here. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, - ... allowed_eggs_from_site_packages=['demoneeded', 'other']) - >>> [dist.project_name for dist in workingset] - ['demoneeded'] - -That worked fine. It would work fine for a glob too. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, - ... allowed_eggs_from_site_packages=['?emon*', 'other']) - >>> [dist.project_name for dist in workingset] - ['demoneeded'] - -But now let's try again with 'demoneeded' not allowed. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, - ... allowed_eggs_from_site_packages=['demo']) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - -Here's the same, but with an empty list. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, - ... allowed_eggs_from_site_packages=[]) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - -Of course, this doesn't stop us from getting a package from elsewhere. Here, -we add a link server. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, executable=py_path, - ... links=[link_server], index=link_server+'index/', - ... allowed_eggs_from_site_packages=['other']) - >>> [dist.project_name for dist in workingset] - ['demoneeded'] - >>> [dist.location for dist in workingset] - ['/site-packages-example-install/demoneeded-1.1-py2.6.egg'] - -Finally, here's an example of an interaction: we say that it is OK to -allow the "demoneeded" egg to come from site-packages, but we don't -include-site-packages. - - >>> zc.buildout.easy_install.clear_index_cache() - >>> rmdir(example_dest) - >>> example_dest = tmpdir('site-packages-example-install') - >>> workingset = zc.buildout.easy_install.install( - ... ['demoneeded'], example_dest, links=[], executable=py_path, - ... index=None, include_site_packages=False, - ... allowed_eggs_from_site_packages=['demoneeded']) - Traceback (most recent call last): - ... - MissingDistribution: Couldn't find a distribution for 'demoneeded'. - - """ - -def allowed_eggs_from_site_packages_dependencies_bugfix(): - """ -If you specify that a package with a dependency may come from site-packages, -that doesn't mean that the dependency may come from site-packages. This -is a test for a bug fix to verify that this is true. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - >>> interpreter_dir = tmpdir('interpreter') - >>> interpreter_parts_dir = os.path.join( - ... interpreter_dir, 'parts', 'interpreter') - >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin') - >>> mkdir(interpreter_bin_dir) - >>> mkdir(interpreter_dir, 'eggs') - >>> mkdir(interpreter_dir, 'parts') - >>> mkdir(interpreter_parts_dir) - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], join(interpreter_dir, 'eggs'), executable=py_path, - ... links=[link_server], index=link_server+'index/', - ... allowed_eggs_from_site_packages=['demo']) - >>> [dist.project_name for dist in ws] - ['demo', 'demoneeded'] - >>> from pprint import pprint - >>> pprint([dist.location for dist in ws]) - ['/executable_buildout/site-packages', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'] - - """ - -def allowed_eggs_from_site_packages_bug_592524(): - """ -When we use allowed_eggs_from_site_packages, we need to make sure that the -site-packages paths are not inserted with the normal egg paths. They already -included at the end, and including them along with the normal egg paths will -possibly mask subsequent egg paths. This affects interpreters and scripts -generated by sitepackage_safe_scripts. - -Our "py_path" has the "demoneeded" and "demo" packages available. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - >>> interpreter_dir = tmpdir('interpreter') - >>> interpreter_parts_dir = os.path.join( - ... interpreter_dir, 'parts', 'interpreter') - >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin') - >>> mkdir(interpreter_bin_dir) - >>> mkdir(interpreter_dir, 'eggs') - >>> mkdir(interpreter_dir, 'parts') - >>> mkdir(interpreter_parts_dir) - >>> ws = zc.buildout.easy_install.install( - ... ['demo', 'other'], join(interpreter_dir, 'eggs'), executable=py_path, - ... links=[link_server], index=link_server+'index/', - ... allowed_eggs_from_site_packages=['demo']) - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, py_path, interpreter_parts_dir, - ... interpreter='py', include_site_packages=True) - -Now we will look at the paths in the site.py we generated. Notice that the -site-packages are at the end. They were not before this bugfix. - - >>> test = 'import pprint, sys; pprint.pprint(sys.path[-4:])' - >>> print call_py(join(interpreter_bin_dir, 'py'), test) - ['/interpreter/eggs/other-1.0-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg', - '/executable_buildout/eggs/setuptools-0.0-pyN.N.egg', - '/executable_buildout/site-packages'] - <BLANKLINE> - """ - -def subprocesses_have_same_environment_by_default(): - """ -The scripts generated by sitepackage_safe_scripts set the PYTHONPATH so that, -if the environment is maintained (the default behavior), subprocesses get -the same Python packages. - -First, we set up a script and an interpreter. - - >>> interpreter_dir = tmpdir('interpreter') - >>> interpreter_parts_dir = os.path.join( - ... interpreter_dir, 'parts', 'interpreter') - >>> interpreter_bin_dir = os.path.join(interpreter_dir, 'bin') - >>> mkdir(interpreter_bin_dir) - >>> mkdir(interpreter_dir, 'eggs') - >>> mkdir(interpreter_dir, 'parts') - >>> mkdir(interpreter_parts_dir) - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], join(interpreter_dir, 'eggs'), links=[link_server], - ... index=link_server+'index/') - >>> test = ( - ... "import subprocess, sys; subprocess.call(" - ... "[sys.executable, '-c', " - ... "'import eggrecipedemo; print eggrecipedemo.x'])") - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... reqs=['demo'], interpreter='py', - ... script_initialization=test + '; sys.exit(0)') - -This works for the script. - - >>> print system(join(interpreter_bin_dir, 'demo')) - 3 - <BLANKLINE> - -This also works for the generated interpreter. - - >>> print call_py(join(interpreter_bin_dir, 'py'), test) - 3 - <BLANKLINE> - -If you have a PYTHONPATH in your environment, it will be honored, after -the buildout-generated path. - - >>> original_pythonpath = os.environ.get('PYTHONPATH') - >>> os.environ['PYTHONPATH'] = 'foo' - >>> test = ( - ... "import subprocess, sys; subprocess.call(" - ... "[sys.executable, '-c', " - ... "'import sys, pprint; pprint.pprint(sys.path)'])") - >>> generated = zc.buildout.easy_install.sitepackage_safe_scripts( - ... interpreter_bin_dir, ws, sys.executable, interpreter_parts_dir, - ... reqs=['demo'], interpreter='py', - ... script_initialization=test + '; sys.exit(0)') - -This works for the script. As you can see, /sample_buildout/foo is included -right after the "parts" directory that contains site.py and sitecustomize.py. -You can also see, actually more easily than in the other example, that we -have the desired eggs available. - - >>> print system(join(interpreter_bin_dir, 'demo')), # doctest: +ELLIPSIS - ['', - '/interpreter/parts/interpreter', - '/sample-buildout/foo', - ... - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'] - -This also works for the generated interpreter, with identical results. - - >>> print call_py(join(interpreter_bin_dir, 'py'), test), - ... # doctest: +ELLIPSIS - ['', - '/interpreter/parts/interpreter', - '/sample-buildout/foo', - ... - '/interpreter/eggs/demo-0.3-pyN.N.egg', - '/interpreter/eggs/demoneeded-1.1-pyN.N.egg'] - - >>> # Cleanup - >>> if original_pythonpath: - ... os.environ['PYTHONPATH'] = original_pythonpath - ... else: - ... del os.environ['PYTHONPATH'] - ... - - """ - -def bootstrap_makes_buildout_that_works_with_system_python(): - r""" -In order to work smoothly with a system Python, bootstrapping creates -the buildout script with -zc.buildout.easy_install.sitepackage_safe_scripts. If it did not, a -variety of problems might happen. For instance, if another version of -buildout or setuptools is installed in the site-packages than is -desired, it may cause a problem. - -A problem actually experienced in the field is when -a recipe wants a different version of a dependency that is installed in -site-packages. We will create a similar situation, and show that it is now -handled. - -First let's write a dummy recipe. - - >>> mkdir(sample_buildout, 'recipes') - >>> write(sample_buildout, 'recipes', 'dummy.py', - ... ''' - ... import logging, os, zc.buildout - ... class Dummy: - ... def __init__(self, buildout, name, options): - ... pass - ... def install(self): - ... return () - ... def update(self): - ... pass - ... ''') - >>> write(sample_buildout, 'recipes', 'setup.py', - ... ''' - ... from setuptools import setup - ... - ... setup( - ... name = "recipes", - ... entry_points = {'zc.buildout': ['dummy = dummy:Dummy']}, - ... install_requires = 'demoneeded==1.2c1', - ... ) - ... ''') - >>> write(sample_buildout, 'recipes', 'README.txt', " ") - -Now we'll try to use it with a Python that has a different version of -demoneeded installed. - - >>> py_path, site_packages_path = make_py() - >>> create_sample_sys_install(site_packages_path) - >>> rmdir('develop-eggs') - >>> from zc.buildout.testing import make_buildout - >>> make_buildout(executable=py_path) - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = recipes - ... parts = dummy - ... find-links = %(link_server)s - ... executable = %(py_path)s - ... - ... [dummy] - ... recipe = recipes:dummy - ... ''' % globals()) - -Now we actually run the buildout. Before the change, we got the following -error: - - Develop: '/sample-buildout/recipes' - While: - Installing. - Getting section dummy. - Initializing section dummy. - Installing recipe recipes. - Error: There is a version conflict. - We already have: demoneeded 1.1 - but recipes 0.0.0 requires 'demoneeded==1.2c1'. - -Now, it is handled smoothly. - - >>> print system(buildout) - Develop: '/sample-buildout/recipes' - Getting distribution for 'demoneeded==1.2c1'. - Got demoneeded 1.2c1. - Installing dummy. - <BLANKLINE> - -Here's the same story with a namespace package, which has some additional -complications behind the scenes. First, a recipe, in the "tellmy" namespace. - - >>> mkdir(sample_buildout, 'ns') - >>> mkdir(sample_buildout, 'ns', 'tellmy') - >>> write(sample_buildout, 'ns', 'tellmy', '__init__.py', - ... "__import__('pkg_resources').declare_namespace(__name__)\n") - >>> mkdir(sample_buildout, 'ns', 'tellmy', 'recipes') - >>> write(sample_buildout, 'ns', 'tellmy', 'recipes', '__init__.py', ' ') - >>> write(sample_buildout, 'ns', 'tellmy', 'recipes', 'dummy.py', - ... ''' - ... import logging, os, zc.buildout - ... class Dummy: - ... def __init__(self, buildout, name, options): - ... pass - ... def install(self): - ... return () - ... def update(self): - ... pass - ... ''') - >>> write(sample_buildout, 'ns', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup( - ... name="tellmy.recipes", - ... packages=['tellmy', 'tellmy.recipes'], - ... install_requires=['setuptools'], - ... namespace_packages=['tellmy'], - ... entry_points = {'zc.buildout': - ... ['dummy = tellmy.recipes.dummy:Dummy']}, - ... ) - ... ''') - -Now, a buildout that uses it. - - >>> create_sample_namespace_eggs(sample_eggs, site_packages_path) - >>> rmdir('develop-eggs') - >>> from zc.buildout.testing import make_buildout - >>> make_buildout(executable=py_path) - >>> write(sample_buildout, 'buildout.cfg', - ... ''' - ... [buildout] - ... develop = ns - ... recipes - ... parts = dummy - ... find-links = %(link_server)s - ... executable = %(py_path)s - ... - ... [dummy] - ... recipe = tellmy.recipes:dummy - ... ''' % globals()) - -Now we actually run the buildout. - - >>> print system(buildout) - Develop: '/sample-buildout/ns' - Develop: '/sample-buildout/recipes' - Uninstalling dummy. - Installing dummy. - <BLANKLINE> - - """ - -if sys.version_info > (2, 4): - def test_exit_codes(): - """ - >>> import subprocess - >>> def call(s): - ... p = subprocess.Popen(s, stdin=subprocess.PIPE, - ... stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - ... p.stdin.close() - ... print p.stdout.read() - ... print 'Exit:', bool(p.wait()) - - >>> call(buildout) - <BLANKLINE> - Exit: False - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... ''') - - >>> call(buildout) # doctest: +NORMALIZE_WHITESPACE - While: - Installing. - Getting section x. - Error: The referenced section, 'x', was not defined. - <BLANKLINE> - Exit: True - - >>> write('setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='zc.buildout.testexit', entry_points={ - ... 'zc.buildout': ['default = testexitrecipe:x']}) - ... ''') - - >>> write('testexitrecipe.py', - ... ''' - ... x y - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = x - ... develop = . - ... - ... [x] - ... recipe = zc.buildout.testexit - ... ''') - - >>> call(buildout) # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - Develop: '/sample-buildout/.' - While: - Installing. - Getting section x. - Initializing section x. - Loading zc.buildout recipe entry zc.buildout.testexit:default. - <BLANKLINE> - An internal error occurred due to a bug in either zc.buildout or in a - recipe being used: - Traceback (most recent call last): - ... - x y - ^ - SyntaxError: invalid syntax - <BLANKLINE> - Exit: True - """ - -def bug_59270_recipes_always_start_in_buildout_dir(): - """ - Recipes can rely on running from buildout directory - - >>> mkdir('bad_start') - >>> write('bad_recipe.py', - ... ''' - ... import os - ... class Bad: - ... def __init__(self, *_): - ... print os.getcwd() - ... def install(self): - ... print os.getcwd() - ... os.chdir('bad_start') - ... print os.getcwd() - ... return () - ... ''') - - >>> write('setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='bad.test', - ... entry_points={'zc.buildout': ['default=bad_recipe:Bad']},) - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = . - ... parts = b1 b2 - ... [b1] - ... recipe = bad.test - ... [b2] - ... recipe = bad.test - ... ''') - - >>> os.chdir('bad_start') - >>> print system(join(sample_buildout, 'bin', 'buildout') - ... +' -c '+join(sample_buildout, 'buildout.cfg')), - Develop: '/sample-buildout/.' - /sample-buildout - /sample-buildout - Installing b1. - /sample-buildout - /sample-buildout/bad_start - Installing b2. - /sample-buildout - /sample-buildout/bad_start - - """ - -def bug_61890_file_urls_dont_seem_to_work_in_find_dash_links(): - """ - - This bug arises from the fact that setuptools is overly restrictive - about file urls, requiring that file urls pointing at directories - must end in a slash. - - >>> dest = tmpdir('sample-install') - >>> import zc.buildout.easy_install - >>> sample_eggs = sample_eggs.replace(os.path.sep, '/') - >>> ws = zc.buildout.easy_install.install( - ... ['demo==0.2'], dest, - ... links=['file://'+sample_eggs], index=link_server+'index/') - - - >>> for dist in ws: - ... print dist - demo 0.2 - demoneeded 1.1 - - >>> ls(dest) - - demo-0.2-py2.4.egg - - demoneeded-1.1-py2.4.egg - - """ - -def bug_75607_buildout_should_not_run_if_it_creates_an_empty_buildout_cfg(): - """ - >>> remove('buildout.cfg') - >>> print system(buildout), - While: - Initializing. - Error: Couldn't open /sample-buildout/buildout.cfg - - - - """ - -def dealing_with_extremely_insane_dependencies(): - r""" - - There was a problem with analysis of dependencies taking a long - time, in part because the analysis would get repeated every time a - package was encountered in a dependency list. Now, we don't do - the analysis any more: - - >>> import os - >>> for i in range(5): - ... p = 'pack%s' % i - ... deps = [('pack%s' % j) for j in range(5) if j is not i] - ... if i == 4: - ... deps.append('pack5') - ... mkdir(p) - ... write(p, 'setup.py', - ... 'from setuptools import setup\n' - ... 'setup(name=%r, install_requires=%r,\n' - ... ' url="u", author="a", author_email="e")\n' - ... % (p, deps)) - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = pack0 pack1 pack2 pack3 pack4 - ... parts = pack1 - ... - ... [pack1] - ... recipe = zc.recipe.egg:eggs - ... eggs = pack0 - ... ''') - - >>> print system(buildout), - Develop: '/sample-buildout/pack0' - Develop: '/sample-buildout/pack1' - Develop: '/sample-buildout/pack2' - Develop: '/sample-buildout/pack3' - Develop: '/sample-buildout/pack4' - Installing pack1. - Couldn't find index page for 'pack5' (maybe misspelled?) - Getting distribution for 'pack5'. - While: - Installing pack1. - Getting distribution for 'pack5'. - Error: Couldn't find a distribution for 'pack5'. - - However, if we run in verbose mode, we can see why packages were included: - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - We have a develop egg: zc.buildout 1.0.0 - We have the best distribution that satisfies 'setuptools'. - Picked: setuptools = 0.6 - Develop: '/sample-buildout/pack0' - Develop: '/sample-buildout/pack1' - Develop: '/sample-buildout/pack2' - Develop: '/sample-buildout/pack3' - Develop: '/sample-buildout/pack4' - ...Installing pack1. - Installing 'pack0'. - We have a develop egg: pack0 0.0.0 - Getting required 'pack4' - required by pack0 0.0.0. - We have a develop egg: pack4 0.0.0 - Getting required 'pack3' - required by pack0 0.0.0. - required by pack4 0.0.0. - We have a develop egg: pack3 0.0.0 - Getting required 'pack2' - required by pack0 0.0.0. - required by pack3 0.0.0. - required by pack4 0.0.0. - We have a develop egg: pack2 0.0.0 - Getting required 'pack1' - required by pack0 0.0.0. - required by pack2 0.0.0. - required by pack3 0.0.0. - required by pack4 0.0.0. - We have a develop egg: pack1 0.0.0 - Getting required 'pack5' - required by pack4 0.0.0. - We have no distributions for pack5 that satisfies 'pack5'. - Couldn't find index page for 'pack5' (maybe misspelled?) - Getting distribution for 'pack5'. - While: - Installing pack1. - Getting distribution for 'pack5'. - Error: Couldn't find a distribution for 'pack5'. - """ - -def read_find_links_to_load_extensions(): - """ -We'll create a wacky buildout extension that is just another name for http: - - >>> src = tmpdir('src') - >>> write(src, 'wacky_handler.py', - ... ''' - ... import urllib2 - ... class Wacky(urllib2.HTTPHandler): - ... wacky_open = urllib2.HTTPHandler.http_open - ... def install(buildout=None): - ... urllib2.install_opener(urllib2.build_opener(Wacky)) - ... ''') - >>> write(src, 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='wackyextension', version='1', - ... py_modules=['wacky_handler'], - ... entry_points = {'zc.buildout.extension': - ... ['default = wacky_handler:install'] - ... }, - ... ) - ... ''') - >>> print system(buildout+' setup '+src+' bdist_egg'), - ... # doctest: +ELLIPSIS - Running setup ... - creating 'dist/wackyextension-1-... - -Now we'll create a buildout that uses this extension to load other packages: - - >>> wacky_server = link_server.replace('http', 'wacky') - >>> dist = 'file://' + join(src, 'dist').replace(os.path.sep, '/') - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = demo - ... extensions = wackyextension - ... find-links = %(wacky_server)s/demoneeded-1.0.zip - ... %(dist)s - ... [demo] - ... recipe = zc.recipe.egg - ... eggs = demoneeded - ... ''' % globals()) - -When we run the buildout. it will load the extension from the dist -directory and then use the wacky extension to load the demo package - - >>> print system(buildout), - Getting distribution for 'wackyextension'. - Got wackyextension 1. - Installing demo. - Getting distribution for 'demoneeded'. - Got demoneeded 1.0. - - """ - -def distributions_from_local_find_links_make_it_to_download_cache(): - """ - -If we specify a local directory in find links, distors found there -need to make it to the download cache. - - >>> mkdir('test') - >>> write('test', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='foo') - ... ''') - - >>> print system(buildout+' setup test bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'test/setup.py'. - ... - - - >>> mkdir('cache') - >>> old_cache = zc.buildout.easy_install.download_cache('cache') - >>> list(zc.buildout.easy_install.install(['foo'], 'eggs', - ... links=[join('test', 'dist')])) # doctest: +ELLIPSIS - [foo 0.0.0 ... - - >>> ls('cache') - - foo-0.0.0-py2.4.egg - - >>> _ = zc.buildout.easy_install.download_cache(old_cache) - - """ - -def create_egg(name, version, dest, install_requires=None, - dependency_links=None): - d = tempfile.mkdtemp() - if dest=='available': - extras = dict(x=['x']) - else: - extras = {} - if dependency_links: - links = 'dependency_links = %s, ' % dependency_links - else: - links = '' - if install_requires: - requires = 'install_requires = %s, ' % install_requires - else: - requires = '' - try: - open(os.path.join(d, 'setup.py'), 'w').write( - 'from setuptools import setup\n' - 'setup(name=%r, version=%r, extras_require=%r, zip_safe=True,\n' - ' %s %s py_modules=["setup"]\n)' - % (name, str(version), extras, requires, links) - ) - zc.buildout.testing.bdist_egg(d, sys.executable, os.path.abspath(dest)) - finally: - shutil.rmtree(d) - -def prefer_final_permutation(existing, available): - for d in ('existing', 'available'): - if os.path.exists(d): - shutil.rmtree(d) - os.mkdir(d) - for version in existing: - create_egg('spam', version, 'existing') - for version in available: - create_egg('spam', version, 'available') - - zc.buildout.easy_install.clear_index_cache() - [dist] = list( - zc.buildout.easy_install.install(['spam'], 'existing', ['available'], - always_unzip=True) - ) - - if dist.extras: - print 'downloaded', dist.version - else: - print 'had', dist.version - sys.path_importer_cache.clear() - -def prefer_final(): - """ -This test tests several permutations: - -Using different version numbers to work around zip importer cache problems. :( - -- With prefer final: - - - no existing and newer dev available - >>> prefer_final_permutation((), [1, '2a1']) - downloaded 1 - - - no existing and only dev available - >>> prefer_final_permutation((), ['3a1']) - downloaded 3a1 - - - final existing and only dev acailable - >>> prefer_final_permutation([4], ['5a1']) - had 4 - - - final existing and newer final available - >>> prefer_final_permutation([6], [7]) - downloaded 7 - - - final existing and same final available - >>> prefer_final_permutation([8], [8]) - had 8 - - - final existing and older final available - >>> prefer_final_permutation([10], [9]) - had 10 - - - only dev existing and final available - >>> prefer_final_permutation(['12a1'], [11]) - downloaded 11 - - - only dev existing and no final available newer dev available - >>> prefer_final_permutation(['13a1'], ['13a2']) - downloaded 13a2 - - - only dev existing and no final available older dev available - >>> prefer_final_permutation(['15a1'], ['14a1']) - had 15a1 - - - only dev existing and no final available same dev available - >>> prefer_final_permutation(['16a1'], ['16a1']) - had 16a1 - -- Without prefer final: - - >>> _ = zc.buildout.easy_install.prefer_final(False) - - - no existing and newer dev available - >>> prefer_final_permutation((), [18, '19a1']) - downloaded 19a1 - - - no existing and only dev available - >>> prefer_final_permutation((), ['20a1']) - downloaded 20a1 - - - final existing and only dev acailable - >>> prefer_final_permutation([21], ['22a1']) - downloaded 22a1 - - - final existing and newer final available - >>> prefer_final_permutation([23], [24]) - downloaded 24 - - - final existing and same final available - >>> prefer_final_permutation([25], [25]) - had 25 - - - final existing and older final available - >>> prefer_final_permutation([27], [26]) - had 27 - - - only dev existing and final available - >>> prefer_final_permutation(['29a1'], [28]) - had 29a1 - - - only dev existing and no final available newer dev available - >>> prefer_final_permutation(['30a1'], ['30a2']) - downloaded 30a2 - - - only dev existing and no final available older dev available - >>> prefer_final_permutation(['32a1'], ['31a1']) - had 32a1 - - - only dev existing and no final available same dev available - >>> prefer_final_permutation(['33a1'], ['33a1']) - had 33a1 - - >>> _ = zc.buildout.easy_install.prefer_final(True) - - """ - -def buildout_prefer_final_option(): - """ -The prefer-final buildout option can be used for override the default -preference for newer distributions. - -The default is prefer-final = false: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - ... - Picked: demo = 0.4c1 - ... - Picked: demoneeded = 1.2c1 - -Here we see that the final versions of demo and demoneeded are used. -We get the same behavior if we add prefer-final = false - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... prefer-final = false - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - ... - Picked: demo = 0.4c1 - ... - Picked: demoneeded = 1.2c1 - -If we specify prefer-final = true, we'll get the newest -distributions: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... prefer-final = true - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing 'zc.buildout', 'setuptools'. - ... - Picked: demo = 0.3 - ... - Picked: demoneeded = 1.1 - -We get an error if we specify anything but true or false: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... prefer-final = no - ... - ... [eggs] - ... recipe = zc.recipe.egg:eggs - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - While: - Initializing. - Error: Invalid value for prefer-final option: no - - """ - -def buildout_prefer_final_build_system_option(): - """ -The accept-buildout-test-releases buildout option can be used for overriding -the default preference for final distributions for recipes, buildout -extensions, and buildout itself. It is usually controlled via the bootstrap -script rather than in the configuration file, but we will test the machinery -using the file. - -Set up. This creates sdists for demorecipe 1.0 and 1.1b1, and for -demoextension 1.0 and 1.1b1. - - >>> create_sample_recipe_sdists(sample_eggs) - >>> create_sample_extension_sdists(sample_eggs) - -The default is accept-buildout-test-releases = false: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = demo - ... find-links = %(link_server)s - ... extensions = demoextension - ... - ... [demo] - ... recipe = demorecipe - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing ... - Picked: demoextension = 1.0 - ... - Picked: demorecipe = 1.0 - ... - -Here we see that the final versions of demorecipe and demoextension were used. - -We get the same behavior if we explicitly state that -accept-buildout-test-releases = false. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = demo - ... find-links = %(link_server)s - ... extensions = demoextension - ... accept-buildout-test-releases = false - ... - ... [demo] - ... recipe = demorecipe - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing ... - Picked: demoextension = 1.0 - ... - Picked: demorecipe = 1.0 - ... - -If we specify accept-buildout-test-releases = true, we'll get the newest -distributions in the build system: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = demo - ... find-links = %(link_server)s - ... extensions = demoextension - ... accept-buildout-test-releases = true - ... - ... [demo] - ... recipe = demorecipe - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - Installing ... - Picked: demoextension = 1.1b1 - ... - Picked: demorecipe = 1.1b1 - ... - -We get an error if we specify anything but true or false: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = demo - ... find-links = %(link_server)s - ... extensions = demoextension - ... accept-buildout-test-releases = no - ... - ... [demo] - ... recipe = demorecipe - ... ''' % globals()) - - >>> print system(buildout+' -v'), # doctest: +ELLIPSIS - While: - Initializing. - Error: Invalid value for accept-buildout-test-releases option: no - - """ - -def develop_with_modules(): - """ -Distribution setup scripts can import modules in the distribution directory: - - >>> mkdir('foo') - >>> write('foo', 'bar.py', - ... '''# empty - ... ''') - - >>> write('foo', 'setup.py', - ... ''' - ... import bar - ... from setuptools import setup - ... setup(name="foo") - ... ''') - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... develop = foo - ... parts = - ... ''') - - >>> print system(join('bin', 'buildout')), - Develop: '/sample-buildout/foo' - - >>> ls('develop-eggs') - - foo.egg-link - - z3c.recipe.scripts.egg-link - - zc.recipe.egg.egg-link - - """ - -def dont_pick_setuptools_if_version_is_specified_when_required_by_src_dist(): - """ -When installing a source distribution, we got setuptools without -honoring our version specification. - - >>> mkdir('dist') - >>> write('setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='foo', version='1', py_modules=['foo'], zip_safe=True) - ... ''') - >>> write('foo.py', '') - >>> _ = system(buildout+' setup . sdist') - - >>> if zc.buildout.easy_install.is_distribute: - ... distribute_version = 'distribute = %s' % ( - ... pkg_resources.working_set.find( - ... pkg_resources.Requirement.parse('distribute')).version,) - ... else: - ... distribute_version = '' - ... - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = dist - ... versions = versions - ... allow-picked-versions = false - ... - ... [versions] - ... setuptools = %s - ... foo = 1 - ... %s - ... - ... [foo] - ... recipe = zc.recipe.egg - ... eggs = foo - ... ''' % (pkg_resources.working_set.find( - ... pkg_resources.Requirement.parse('setuptools')).version, - ... distribute_version)) - - >>> print system(buildout), - Installing foo. - Getting distribution for 'foo==1'. - Got foo 1. - - """ - -def pyc_and_pyo_files_have_correct_paths(): - r""" - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... unzip = true - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = demo - ... interpreter = py - ... ''' % globals()) - - >>> _ = system(buildout) - - >>> write('t.py', - ... ''' - ... import eggrecipedemo, eggrecipedemoneeded - ... print eggrecipedemo.main.func_code.co_filename - ... print eggrecipedemoneeded.f.func_code.co_filename - ... ''') - - >>> print system(join('bin', 'py')+ ' t.py'), - /sample-buildout/eggs/demo-0.4c1-py2.4.egg/eggrecipedemo.py - /sample-buildout/eggs/demoneeded-1.2c1-py2.4.egg/eggrecipedemoneeded.py - - >>> import os - >>> for name in os.listdir('eggs'): - ... if name.startswith('demoneeded'): - ... ls('eggs', name) - d EGG-INFO - - eggrecipedemoneeded.py - - eggrecipedemoneeded.pyc - - eggrecipedemoneeded.pyo - - """ - -def dont_mess_with_standard_dirs_with_variable_refs(): - """ - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... eggs-directory = ${buildout:directory}/develop-eggs - ... parts = - ... ''' % globals()) - >>> print system(buildout), - - """ - -def expand_shell_patterns_in_develop_paths(): - """ - Sometimes we want to include a number of eggs in some directory as - develop eggs, without explicitly listing all of them in our - buildout.cfg - - >>> make_dist_that_requires(sample_buildout, 'sampley') - >>> make_dist_that_requires(sample_buildout, 'samplez') - - Now, let's create a buildout that has a shell pattern that matches - both: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... develop = sample* - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = sampley - ... samplez - ... ''' % globals()) - - We can see that both eggs were found: - - >>> print system(buildout), - Develop: '/sample-buildout/sampley' - Develop: '/sample-buildout/samplez' - Installing eggs. - - """ - -def warn_users_when_expanding_shell_patterns_yields_no_results(): - """ - Sometimes shell patterns do not match anything, so we want to warn - our users about it... - - >>> make_dist_that_requires(sample_buildout, 'samplea') - - So if we have 2 patterns, one that has a matching directory, and - another one that does not - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... develop = samplea grumble* - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = samplea - ... ''' % globals()) - - We should get one of the eggs, and a warning for the pattern that - did not match anything. - - >>> print system(buildout), - Develop: '/sample-buildout/samplea' - Couldn't develop '/sample-buildout/grumble*' (not found) - Installing eggs. - - """ - -def make_sure_versions_dont_cancel_extras(): - """ - There was a bug that caused extras in requirements to be lost. - - >>> open('setup.py', 'w').write(''' - ... from setuptools import setup - ... setup(name='extraversiondemo', version='1.0', - ... url='x', author='x', author_email='x', - ... extras_require=dict(foo=['demo']), py_modules=['t']) - ... ''') - >>> open('README', 'w').close() - >>> open('t.py', 'w').close() - - >>> sdist('.', sample_eggs) - >>> mkdir('dest') - >>> ws = zc.buildout.easy_install.install( - ... ['extraversiondemo[foo]'], 'dest', links=[sample_eggs], - ... versions = dict(extraversiondemo='1.0') - ... ) - >>> sorted(dist.key for dist in ws) - ['demo', 'demoneeded', 'extraversiondemo'] - """ - -def increment_buildout_options(): - r""" - >>> write('b1.cfg', ''' - ... [buildout] - ... parts = p1 - ... x = 1 - ... y = a - ... b - ... - ... [p1] - ... recipe = zc.buildout:debug - ... foo = ${buildout:x} ${buildout:y} - ... ''') - - >>> write('buildout.cfg', ''' - ... [buildout] - ... extends = b1.cfg - ... parts += p2 - ... x += 2 - ... y -= a - ... - ... [p2] - ... <= p1 - ... ''') - - >>> print system(buildout), - Installing p1. - foo='1\n2 b' - recipe='zc.buildout:debug' - Installing p2. - foo='1\n2 b' - recipe='zc.buildout:debug' - """ - -def increment_buildout_with_multiple_extended_files_421022(): - r""" - >>> write('foo.cfg', ''' - ... [buildout] - ... foo-option = foo - ... [other] - ... foo-option = foo - ... ''') - >>> write('bar.cfg', ''' - ... [buildout] - ... bar-option = bar - ... [other] - ... bar-option = bar - ... ''') - >>> write('buildout.cfg', ''' - ... [buildout] - ... parts = p other - ... extends = bar.cfg foo.cfg - ... bar-option += baz - ... foo-option += ham - ... - ... [other] - ... recipe = zc.buildout:debug - ... bar-option += baz - ... foo-option += ham - ... - ... [p] - ... recipe = zc.buildout:debug - ... x = ${buildout:bar-option} ${buildout:foo-option} - ... ''') - - >>> print system(buildout), - Installing p. - recipe='zc.buildout:debug' - x='bar\nbaz foo\nham' - Installing other. - bar-option='bar\nbaz' - foo-option='foo\nham' - recipe='zc.buildout:debug' - """ - -def increment_on_command_line(): - r""" - >>> write('buildout.cfg', ''' - ... [buildout] - ... parts = p1 - ... x = 1 - ... y = a - ... b - ... - ... [p1] - ... recipe = zc.buildout:debug - ... foo = ${buildout:x} ${buildout:y} - ... - ... [p2] - ... <= p1 - ... ''') - - >>> print system(buildout+' buildout:parts+=p2 p1:foo+=bar'), - Installing p1. - foo='1 a\nb\nbar' - recipe='zc.buildout:debug' - Installing p2. - foo='1 a\nb\nbar' - recipe='zc.buildout:debug' - """ - -###################################################################### - -def make_py_with_system_install(make_py, sample_eggs): - py_path, site_packages_path = make_py() - create_sample_namespace_eggs(sample_eggs, site_packages_path) - return py_path - -def create_sample_namespace_eggs(dest, site_packages_path=None): - from zc.buildout.testing import write, mkdir - for pkg, version in (('version', '1.0'), ('version', '1.1'), - ('fortune', '1.0')): - tmp = tempfile.mkdtemp() - try: - write(tmp, 'README.txt', '') - mkdir(tmp, 'src') - mkdir(tmp, 'src', 'tellmy') - write(tmp, 'src', 'tellmy', '__init__.py', - "__import__(" - "'pkg_resources').declare_namespace(__name__)\n") - mkdir(tmp, 'src', 'tellmy', pkg) - write(tmp, 'src', 'tellmy', pkg, - '__init__.py', '__version__=%r\n' % version) - write( - tmp, 'setup.py', - "from setuptools import setup\n" - "setup(\n" - " name='tellmy.%(pkg)s',\n" - " package_dir = {'': 'src'},\n" - " packages = ['tellmy', 'tellmy.%(pkg)s'],\n" - " install_requires = ['setuptools'],\n" - " namespace_packages=['tellmy'],\n" - " zip_safe=True, version=%(version)r,\n" - " author='bob', url='bob', author_email='bob')\n" - % locals() - ) - zc.buildout.testing.sdist(tmp, dest) - if (site_packages_path and pkg == 'version' and version == '1.1'): - # We install the 1.1 version in site packages the way a - # system packaging system (debs, rpms) would do it. - zc.buildout.testing.sys_install(tmp, site_packages_path) - finally: - shutil.rmtree(tmp) - -def create_sample_extension_sdists(dest): - from zc.buildout.testing import write, mkdir - name = 'demoextension' - for version in ('1.0', '1.1b1'): - tmp = tempfile.mkdtemp() - try: - write(tmp, 'README.txt', '') - write(tmp, name + '.py', - "def ext(buildout):\n" - " pass\n" - "def unload(buildout):\n" - " pass\n" - % locals()) - write(tmp, 'setup.py', - "from setuptools import setup\n" - "setup(\n" - " name = %(name)r,\n" - " py_modules = [%(name)r],\n" - " entry_points = {\n" - " 'zc.buildout.extension': " - "['ext = %(name)s:ext'],\n" - " 'zc.buildout.unloadextension': " - "['ext = %(name)s:unload'],\n" - " },\n" - " zip_safe=True, version=%(version)r,\n" - " author='bob', url='bob', author_email='bob')\n" - % locals()) - zc.buildout.testing.sdist(tmp, dest) - finally: - shutil.rmtree(tmp) - -def create_sample_recipe_sdists(dest): - from zc.buildout.testing import write, mkdir - name = 'demorecipe' - for version in ('1.0', '1.1b1'): - tmp = tempfile.mkdtemp() - try: - write(tmp, 'README.txt', '') - write(tmp, name + '.py', - "import logging, os, zc.buildout\n" - "class Demorecipe:\n" - " def __init__(self, buildout, name, options):\n" - " self.name, self.options = name, options\n" - " def install(self):\n" - " return ()\n" - " def update(self):\n" - " pass\n" - % locals()) - write(tmp, 'setup.py', - "from setuptools import setup\n" - "setup(\n" - " name = %(name)r,\n" - " py_modules = [%(name)r],\n" - " entry_points = {'zc.buildout': " - "['default = %(name)s:Demorecipe']},\n" - " zip_safe=True, version=%(version)r,\n" - " author='bob', url='bob', author_email='bob')\n" - % locals()) - zc.buildout.testing.sdist(tmp, dest) - finally: - shutil.rmtree(tmp) - -def _write_eggrecipedemoneeded(tmp, minor_version, suffix=''): - from zc.buildout.testing import write - write(tmp, 'README.txt', '') - write(tmp, 'eggrecipedemoneeded.py', - 'y=%s\ndef f():\n pass' % minor_version) - write( - tmp, 'setup.py', - "from setuptools import setup\n" - "setup(name='demoneeded', py_modules=['eggrecipedemoneeded']," - " zip_safe=True, version='1.%s%s', author='bob', url='bob', " - "author_email='bob')\n" - % (minor_version, suffix) - ) - -def _write_eggrecipedemo(tmp, minor_version, suffix=''): - from zc.buildout.testing import write - write(tmp, 'README.txt', '') - write( - tmp, 'eggrecipedemo.py', - 'import eggrecipedemoneeded\n' - 'x=%s\n' - 'def main(): print x, eggrecipedemoneeded.y\n' - % minor_version) - write( - tmp, 'setup.py', - "from setuptools import setup\n" - "setup(name='demo', py_modules=['eggrecipedemo']," - " install_requires = 'demoneeded'," - " entry_points={'console_scripts': " - "['demo = eggrecipedemo:main']}," - " zip_safe=True, version='0.%s%s')\n" % (minor_version, suffix) - ) - -def create_sample_sys_install(site_packages_path): - for creator, minor_version in ( - (_write_eggrecipedemoneeded, 1), - (_write_eggrecipedemo, 3)): - # Write the files and install in site_packages_path. - tmp = tempfile.mkdtemp() - try: - creator(tmp, minor_version) - zc.buildout.testing.sys_install(tmp, site_packages_path) - finally: - shutil.rmtree(tmp) - -def create_sample_eggs(test, executable=sys.executable): - from zc.buildout.testing import write - dest = test.globs['sample_eggs'] - tmp = tempfile.mkdtemp() - try: - for i in (0, 1, 2): - suffix = i==2 and 'c1' or '' - _write_eggrecipedemoneeded(tmp, i, suffix) - zc.buildout.testing.sdist(tmp, dest) - - write( - tmp, 'setup.py', - "from setuptools import setup\n" - "setup(name='other', zip_safe=False, version='1.0', " - "py_modules=['eggrecipedemoneeded'])\n" - ) - zc.buildout.testing.bdist_egg(tmp, executable, dest) - - os.remove(os.path.join(tmp, 'eggrecipedemoneeded.py')) - - for i in (1, 2, 3, 4): - suffix = i==4 and 'c1' or '' - _write_eggrecipedemo(tmp, i, suffix) - zc.buildout.testing.bdist_egg(tmp, executable, dest) - - write(tmp, 'eggrecipebigdemo.py', 'import eggrecipedemo') - write( - tmp, 'setup.py', - "from setuptools import setup\n" - "setup(name='bigdemo', " - " install_requires = 'demo'," - " py_modules=['eggrecipebigdemo'], " - " zip_safe=True, version='0.1')\n" - ) - zc.buildout.testing.bdist_egg(tmp, executable, dest) - - finally: - shutil.rmtree(tmp) - -extdemo_c = """ -#include <Python.h> -#include <extdemo.h> - -static PyMethodDef methods[] = {{NULL}}; - -PyMODINIT_FUNC -initextdemo(void) -{ - PyObject *m; - m = Py_InitModule3("extdemo", methods, ""); -#ifdef TWO - PyModule_AddObject(m, "val", PyInt_FromLong(2)); -#else - PyModule_AddObject(m, "val", PyInt_FromLong(EXTDEMO)); -#endif -} -""" - -extdemo_setup_py = """ -import os -from distutils.core import setup, Extension - -if os.environ.get('test-variable'): - print "Have environment test-variable:", os.environ['test-variable'] - -setup(name = "extdemo", version = "%s", url="http://www.zope.org", - author="Demo", author_email="demo@demo.com", - ext_modules = [Extension('extdemo', ['extdemo.c'])], - ) -""" - -def add_source_dist(test, version=1.4): - - if 'extdemo' not in test.globs: - test.globs['extdemo'] = test.globs['tmpdir']('extdemo') - - tmp = test.globs['extdemo'] - write = test.globs['write'] - try: - write(tmp, 'extdemo.c', extdemo_c); - write(tmp, 'setup.py', extdemo_setup_py % version); - write(tmp, 'README', ""); - write(tmp, 'MANIFEST.in', "include *.c\n"); - test.globs['sdist'](tmp, test.globs['sample_eggs']) - except: - shutil.rmtree(tmp) - -def easy_install_SetUp(test): - zc.buildout.testing.buildoutSetUp(test) - sample_eggs = test.globs['tmpdir']('sample_eggs') - test.globs['sample_eggs'] = sample_eggs - os.mkdir(os.path.join(sample_eggs, 'index')) - create_sample_eggs(test) - add_source_dist(test) - test.globs['link_server'] = test.globs['start_server']( - test.globs['sample_eggs']) - test.globs['update_extdemo'] = lambda : add_source_dist(test, 1.5) - zc.buildout.testing.install_develop('zc.recipe.egg', test) - zc.buildout.testing.install_develop('z3c.recipe.scripts', test) - -egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$' - ).match -def makeNewRelease(project, ws, dest, version='99.99'): - dist = ws.find(pkg_resources.Requirement.parse(project)) - eggname, oldver, pyver = egg_parse( - os.path.basename(dist.location) - ).groups() - dest = os.path.join(dest, "%s-%s-py%s.egg" % (eggname, version, pyver)) - if os.path.isfile(dist.location): - shutil.copy(dist.location, dest) - zip = zipfile.ZipFile(dest, 'a') - zip.writestr( - 'EGG-INFO/PKG-INFO', - zip.read('EGG-INFO/PKG-INFO').replace("Version: %s" % oldver, - "Version: %s" % version) - ) - zip.close() - else: - shutil.copytree(dist.location, dest) - info_path = os.path.join(dest, 'EGG-INFO', 'PKG-INFO') - info = open(info_path).read().replace("Version: %s" % oldver, - "Version: %s" % version) - open(info_path, 'w').write(info) - -def getWorkingSetWithBuildoutEgg(test): - sample_buildout = test.globs['sample_buildout'] - eggs = os.path.join(sample_buildout, 'eggs') - - # If the zc.buildout dist is a develop dist, convert it to a - # regular egg in the sample buildout - req = pkg_resources.Requirement.parse('zc.buildout') - dist = pkg_resources.working_set.find(req) - if dist.precedence == pkg_resources.DEVELOP_DIST: - # We have a develop egg, create a real egg for it: - here = os.getcwd() - os.chdir(os.path.dirname(dist.location)) - assert os.spawnle( - os.P_WAIT, sys.executable, - zc.buildout.easy_install._safe_arg(sys.executable), - os.path.join(os.path.dirname(dist.location), 'setup.py'), - '-q', 'bdist_egg', '-d', eggs, - dict(os.environ, - PYTHONPATH=pkg_resources.working_set.find( - pkg_resources.Requirement.parse('setuptools') - ).location, - ), - ) == 0 - os.chdir(here) - os.remove(os.path.join(eggs, 'zc.buildout.egg-link')) - - # Rebuild the buildout script - ws = pkg_resources.WorkingSet([eggs]) - ws.require('zc.buildout') - zc.buildout.easy_install.scripts( - ['zc.buildout'], ws, sys.executable, - os.path.join(sample_buildout, 'bin')) - else: - ws = pkg_resources.working_set - return ws - -def updateSetup(test): - zc.buildout.testing.buildoutSetUp(test) - new_releases = test.globs['tmpdir']('new_releases') - test.globs['new_releases'] = new_releases - ws = getWorkingSetWithBuildoutEgg(test) - # now let's make the new releases - makeNewRelease('zc.buildout', ws, new_releases) - makeNewRelease('zc.buildout', ws, new_releases, '100.0b1') - os.mkdir(os.path.join(new_releases, 'zc.buildout')) - if zc.buildout.easy_install.is_distribute: - makeNewRelease('distribute', ws, new_releases) - os.mkdir(os.path.join(new_releases, 'distribute')) - else: - makeNewRelease('setuptools', ws, new_releases) - os.mkdir(os.path.join(new_releases, 'setuptools')) - -def bootstrapSetup(test): - easy_install_SetUp(test) - sample_eggs = test.globs['sample_eggs'] - ws = getWorkingSetWithBuildoutEgg(test) - makeNewRelease('zc.buildout', ws, sample_eggs) - makeNewRelease('zc.buildout', ws, sample_eggs, '100.0b1') - os.environ['bootstrap-testing-find-links'] = test.globs['link_server'] - -normalize_bang = ( - re.compile(re.escape('#!'+ - zc.buildout.easy_install._safe_arg(sys.executable))), - '#!/usr/local/bin/python2.4', - ) - -hide_distribute_additions = (re.compile('install_dir .+\n'), '') -hide_zip_safe_message = ( - # This comes in a different place in the output in Python 2.7. It's not - # important to our tests. Hide it. - re.compile( - '((?<=\n)\n)?zip_safe flag not set; analyzing archive contents...\n'), - '') -hide_first_index_page_message = ( - # This comes in a different place in the output in Python 2.7. It's not - # important to our tests. Hide it. - re.compile( - "Couldn't find index page for '[^']+' \(maybe misspelled\?\)\n"), - '') -def test_suite(): - test_suite = [ - doctest.DocFileSuite( - 'buildout.txt', 'runsetup.txt', 'repeatable.txt', 'setup.txt', - setUp=zc.buildout.testing.buildoutSetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - zc.buildout.tests.hide_distribute_additions, - hide_zip_safe_message, - (re.compile('__buildout_signature__ = recipes-\S+'), - '__buildout_signature__ = recipes-SSSSSSSSSSS'), - (re.compile('executable = [\S ]+python\S*', re.I), - 'executable = python'), - (re.compile('[-d] (setuptools|distribute)-\S+[.]egg'), - 'setuptools.egg'), - (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'), - 'zc.buildout.egg'), - (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'), - (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'), - (re.compile('Picked: (\S+) = \S+'), - 'Picked: \\1 = V.V'), - (re.compile(r'We have a develop egg: zc.buildout (\S+)'), - 'We have a develop egg: zc.buildout X.X.'), - (re.compile(r'\\[\\]?'), '/'), - (re.compile('WindowsError'), 'OSError'), - (re.compile(r'\[Error \d+\] Cannot create a file ' - r'when that file already exists: '), - '[Errno 17] File exists: ' - ), - (re.compile('distribute'), 'setuptools'), - ]) - ), - doctest.DocFileSuite( - 'debugging.txt', - setUp=zc.buildout.testing.buildoutSetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.tests.hide_distribute_additions, - (re.compile(r'\S+buildout.py'), 'buildout.py'), - (re.compile(r'line \d+'), 'line NNN'), - (re.compile(r'py\(\d+\)'), 'py(NNN)'), - ]) - ), - - doctest.DocFileSuite( - 'update.txt', - setUp=updateSetup, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - normalize_bang, - zc.buildout.tests.hide_distribute_additions, - (re.compile('99[.]99'), 'NINETYNINE.NINETYNINE'), - (re.compile('(zc.buildout|setuptools)-\d+[.]\d+\S*' - '-py\d.\d.egg'), - '\\1.egg'), - (re.compile('distribute-\d+[.]\d+\S*' - '-py\d.\d.egg'), - 'setuptools.egg'), - (re.compile('(zc.buildout|setuptools)( version)? \d+[.]\d+\S*'), - '\\1 V.V'), - (re.compile('distribute( version)? \d+[.]\d+\S*'), - 'setuptools V.V'), - (re.compile('[-d] (setuptools|distribute)'), '- setuptools'), - (re.compile('distribute'), 'setuptools'), - (re.compile("\nUnused options for buildout: " - "'(distribute|setuptools)\-version'\."), - '') - ]) - ), - - doctest.DocFileSuite( - 'easy_install.txt', 'downloadcache.txt', 'dependencylinks.txt', - 'allowhosts.txt', 'unzip.txt', 'upgrading_distribute.txt', - setUp=easy_install_SetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - normalize_bang, - hide_first_index_page_message, - zc.buildout.tests.hide_distribute_additions, - (re.compile('extdemo[.]pyd'), 'extdemo.so'), - (re.compile('[-d] (setuptools|distribute)-\S+[.]egg'), - 'setuptools.egg'), - (re.compile(r'\\[\\]?'), '/'), - (re.compile(r'\#!\S+\bpython\S*'), '#!/usr/bin/python'), - # Normalize generate_script's Windows interpreter to UNIX: - (re.compile(r'\nimport subprocess\n'), '\n'), - (re.compile('subprocess\\.call\\(argv, env=environ\\)'), - 'os.execve(sys.executable, argv, environ)'), - (re.compile('distribute'), 'setuptools'), - # Distribute unzips eggs by default. - (re.compile('\- demoneeded'), 'd demoneeded'), - ]+(sys.version_info < (2, 5) and [ - (re.compile('.*No module named runpy.*', re.S), ''), - (re.compile('.*usage: pdb.py scriptfile .*', re.S), ''), - (re.compile('.*Error: what does not exist.*', re.S), ''), - ] or [])), - ), - - doctest.DocFileSuite( - 'download.txt', 'extends-cache.txt', - setUp=easy_install_SetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - optionflags=doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS, - checker=renormalizing.RENormalizing([ - (re.compile(' at -?0x[^>]+'), '<MEM ADDRESS>'), - (re.compile('http://localhost:[0-9]{4,5}/'), - 'http://localhost/'), - (re.compile('[0-9a-f]{32}'), '<MD5 CHECKSUM>'), - zc.buildout.testing.normalize_path, - ]), - ), - - doctest.DocTestSuite( - setUp=easy_install_SetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - zc.buildout.tests.hide_distribute_additions, - hide_first_index_page_message, - (re.compile("buildout: Running \S*setup.py"), - 'buildout: Running setup.py'), - (re.compile('(setuptools|distribute)-\S+-'), - 'setuptools.egg'), - (re.compile('zc.buildout-\S+-'), - 'zc.buildout.egg'), - (re.compile('File "\S+one.py"'), - 'File "one.py"'), - (re.compile(r'We have a develop egg: (\S+) (\S+)'), - r'We have a develop egg: \1 V'), - (re.compile('Picked: (setuptools|distribute) = \S+'), - 'Picked: setuptools = V'), - (re.compile(r'\\[\\]?'), '/'), - (re.compile( - '-q develop -mxN -d "/sample-buildout/develop-eggs'), - '-q develop -mxN -d /sample-buildout/develop-eggs' - ), - (re.compile(r'^[*]...'), '...'), - # for bug_92891_bootstrap_crashes_with_egg_recipe_in_buildout_section - (re.compile(r"Unused options for buildout: 'eggs' 'scripts'\."), - "Unused options for buildout: 'scripts' 'eggs'."), - (re.compile('distribute'), 'setuptools'), - # Distribute unzips eggs by default. - (re.compile('\- demoneeded'), 'd demoneeded'), - ]), - ), - zc.buildout.testselectingpython.test_suite(), - zc.buildout.rmtree.test_suite(), - doctest.DocFileSuite( - 'windows.txt', - setUp=zc.buildout.testing.buildoutSetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - zc.buildout.tests.hide_distribute_additions, - (re.compile('__buildout_signature__ = recipes-\S+'), - '__buildout_signature__ = recipes-SSSSSSSSSSS'), - (re.compile('[-d] setuptools-\S+[.]egg'), 'setuptools.egg'), - (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'), - 'zc.buildout.egg'), - (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'), - (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'), - (re.compile('Picked: (\S+) = \S+'), - 'Picked: \\1 = V.V'), - (re.compile(r'We have a develop egg: zc.buildout (\S+)'), - 'We have a develop egg: zc.buildout X.X.'), - (re.compile(r'\\[\\]?'), '/'), - (re.compile('WindowsError'), 'OSError'), - (re.compile(r'\[Error 17\] Cannot create a file ' - r'when that file already exists: '), - '[Errno 17] File exists: ' - ), - ]) - ), - doctest.DocFileSuite( - 'testing_bugfix.txt', - checker=renormalizing.RENormalizing([ - # Python 2.7 - (re.compile( - re.escape( - 'testrunner.logsupport.NullHandler instance at')), - 'testrunner.logsupport.NullHandler object at'), - (re.compile(re.escape('logging.StreamHandler instance at')), - 'logging.StreamHandler object at'), - ]) - ), - ] - - # adding bootstrap.txt doctest to the suite - # only if bootstrap.py is present - bootstrap_py = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.dirname(zc.buildout.__file__) - ) - ) - ), - 'bootstrap', 'bootstrap.py') - - if os.path.exists(bootstrap_py): - test_suite.append(doctest.DocFileSuite( - 'bootstrap.txt', - setUp=bootstrapSetup, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - normalize_bang, - (re.compile('Downloading.*setuptools.*egg\n'), ''), - (re.compile('options:'), 'Options:'), - (re.compile('usage:'), 'Usage:'), - ]), - )) - test_suite.append(doctest.DocFileSuite( - 'virtualenv.txt', - setUp=easy_install_SetUp, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - zc.buildout.testing.normalize_path, - zc.buildout.testing.normalize_endings, - zc.buildout.testing.normalize_script, - zc.buildout.testing.normalize_egg_py, - zc.buildout.tests.hide_distribute_additions, - (re.compile('(setuptools|distribute)-\S+-'), - 'setuptools.egg'), - (re.compile('zc.buildout-\S+-'), - 'zc.buildout.egg'), - (re.compile(re.escape('#!"/executable_buildout/bin/py"')), - '#!/executable_buildout/bin/py'), # Windows. - (re.compile(re.escape('/broken_s/')), - '/broken_S/'), # Windows. - ]), - )) - - return unittest.TestSuite(test_suite) diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testselectingpython.py b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testselectingpython.py deleted file mode 100644 index 542e253..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/testselectingpython.py +++ /dev/null @@ -1,96 +0,0 @@ -############################################################################## -# -# Copyright (c) 2006 Zope Corporation and Contributors. -# All Rights Reserved. -# -# This software is subject to the provisions of the Zope Public License, -# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. -# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED -# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS -# FOR A PARTICULAR PURPOSE. -# -############################################################################## -import os, re, subprocess, sys, textwrap, unittest, doctest -from zope.testing import renormalizing -import zc.buildout.tests -import zc.buildout.testing - -if sys.version_info[:2] == (2, 4): - other_version = "2.5" -else: - other_version = "2.4" - -__test__ = dict( - test_selecting_python_via_easy_install= - """\ - -We can specify a specific Python executable. - - >>> dest = tmpdir('sample-install') - >>> ws = zc.buildout.easy_install.install( - ... ['demo'], dest, links=[link_server], - ... index='http://www.python.org/pypi/', - ... always_unzip=True, executable=other_executable) - - >>> ls(dest) - d demo-0.3-py%(other_version)s.egg - d demoneeded-1.1-py%(other_version)s.egg - -""" % dict(other_version=other_version) - ) - -def multi_python(test): - other_executable = zc.buildout.testing.find_python(other_version) - command = textwrap.dedent('''\ - try: - import setuptools - except ImportError: - import sys - sys.exit(1) - ''') - env = dict(os.environ) - env.pop('PYTHONPATH', None) - if subprocess.call([other_executable, '-c', command], env=env): - # the other executable does not have setuptools. Get setuptools. - # We will do this using the same tools we are testing, for better or - # worse. Alternatively, we could try using bootstrap. - executable_dir = test.globs['tmpdir']('executable_dir') - executable_parts = os.path.join(executable_dir, 'parts') - test.globs['mkdir'](executable_parts) - ws = zc.buildout.easy_install.install( - ['setuptools'], executable_dir, - index='http://www.python.org/pypi/', - always_unzip=True, executable=other_executable) - zc.buildout.easy_install.sitepackage_safe_scripts( - executable_dir, ws, other_executable, executable_parts, - reqs=['setuptools'], interpreter='py') - original_executable = other_executable - other_executable = os.path.join(executable_dir, 'py') - assert not subprocess.call( - [other_executable, '-c', command], env=env), ( - 'test set up failed') - sample_eggs = test.globs['tmpdir']('sample_eggs') - os.mkdir(os.path.join(sample_eggs, 'index')) - test.globs['sample_eggs'] = sample_eggs - zc.buildout.tests.create_sample_eggs(test, executable=other_executable) - test.globs['other_executable'] = other_executable - - -def setup(test): - zc.buildout.testing.buildoutSetUp(test) - multi_python(test) - zc.buildout.tests.add_source_dist(test) - test.globs['link_server'] = test.globs['start_server']( - test.globs['sample_eggs']) - - -def test_suite(): - return doctest.DocTestSuite( - setUp=setup, - tearDown=zc.buildout.testing.buildoutTearDown, - checker=renormalizing.RENormalizing([ - (re.compile('setuptools-\S+-py%s.egg' % other_version), - 'setuptools-V-py%s.egg' % other_version), - ]), - ) diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/unzip.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/unzip.txt deleted file mode 100644 index 9f55f3f..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/unzip.txt +++ /dev/null @@ -1,54 +0,0 @@ -Always unzipping eggs -===================== - -By default, zc.buildout doesn't unzip zip-safe eggs. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = demo - ... ''' % globals()) - - >>> _ = system(buildout) - >>> ls('eggs') - - demo-0.4c1-py2.4.egg - - demoneeded-1.2c1-py2.4.egg - d setuptools-0.6c8-py2.4.egg - - zc.buildout.egg-link - -This follows the policy followed by setuptools itself. Experience shows -this policy to to be inconvenient. Zipped eggs make debugging more -difficult and often import more slowly. - -You can include an unzip option in the buildout section to change the -default unzipping policy. - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... unzip = true - ... - ... [eggs] - ... recipe = zc.recipe.egg - ... eggs = demo - ... ''' % globals()) - - - >>> import os - >>> for name in os.listdir('eggs'): - ... if name.startswith('demo'): - ... remove('eggs', name) - - >>> _ = system(buildout) - >>> ls('eggs') - d demo-0.4c1-py2.4.egg - d demoneeded-1.2c1-py2.4.egg - d setuptools-0.6c8-py2.4.egg - - zc.buildout.egg-link diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/update.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/update.txt deleted file mode 100644 index cab1610..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/update.txt +++ /dev/null @@ -1,263 +0,0 @@ -Automatic Buildout Updates -========================== - -When a buildout is run, one of the first steps performed is to check -for updates to either zc.buildout or setuptools. To demonstrate this, -we've created some "new releases" of buildout and setuptools in a -new_releases folder: - - >>> ls(new_releases) - d setuptools - - setuptools-99.99-py2.4.egg - d zc.buildout - - zc.buildout-100.0b1-pyN.N.egg - - zc.buildout-99.99-py2.4.egg - -Let's update the sample buildout.cfg to look in this area: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... find-links = %(new_releases)s - ... index = %(new_releases)s - ... parts = show-versions - ... develop = showversions - ... - ... [show-versions] - ... recipe = showversions - ... """ % dict(new_releases=new_releases)) - -We'll also include a recipe that echos the versions of setuptools and -zc.buildout used: - - >>> mkdir(sample_buildout, 'showversions') - - >>> write(sample_buildout, 'showversions', 'showversions.py', - ... """ - ... import pkg_resources - ... - ... class Recipe: - ... - ... def __init__(self, buildout, name, options): - ... pass - ... - ... def install(self): - ... for project in 'zc.buildout', 'setuptools': - ... req = pkg_resources.Requirement.parse(project) - ... print project, pkg_resources.working_set.find(req).version - ... return () - ... update = install - ... """) - - - >>> write(sample_buildout, 'showversions', 'setup.py', - ... """ - ... from setuptools import setup - ... - ... setup( - ... name = "showversions", - ... entry_points = {'zc.buildout': ['default = showversions:Recipe']}, - ... ) - ... """) - - -Now if we run the buildout, the buildout will upgrade itself to the -new versions found in new releases: - - >>> print system(buildout), - Getting distribution for 'zc.buildout'. - Got zc.buildout 99.99. - Getting distribution for 'setuptools'. - Got setuptools 99.99. - Upgraded: - zc.buildout version 99.99, - setuptools version 99.99; - restarting. - Generated script '/sample-buildout/bin/buildout'. - Develop: '/sample-buildout/showversions' - Installing show-versions. - zc.buildout 99.99 - setuptools 99.99 - -Notice that, even though we have a newer beta version of zc.buildout -available, the final "99.99" was selected. If you want to get non-final -versions, specify a specific version in your buildout's versions -section, you typically want to use the --accept-buildout-test-releases -option to the bootstrap script, which internally uses the -``accept-buildout-test-releases = true`` discussed below. - -Our buildout script's site.py has been updated to use the new eggs: - - >>> cat(sample_buildout, 'parts', 'buildout', 'site.py') - ... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - "... - def addsitepackages(known_paths): - """Add site packages, as determined by zc.buildout. - <BLANKLINE> - See original_addsitepackages, below, for the original version.""" - setuptools_path = '/sample-buildout/eggs/setuptools-99.99-pyN.N.egg' - sys.path.append(setuptools_path) - known_paths.add(os.path.normcase(setuptools_path)) - import pkg_resources - buildout_paths = [ - '/sample-buildout/eggs/zc.buildout-99.99-pyN.N.egg', - '/sample-buildout/eggs/setuptools-99.99-pyN.N.egg' - ] - for path in buildout_paths: - sitedir, sitedircase = makepath(path) - if not sitedircase in known_paths and os.path.exists(sitedir): - sys.path.append(sitedir) - known_paths.add(sitedircase) - pkg_resources.working_set.add_entry(sitedir) - sys.__egginsert = len(buildout_paths) # Support setuptools. - original_paths = [ - ... - ] - for path in original_paths: - if path == setuptools_path or path not in known_paths: - addsitedir(path, known_paths) - return known_paths - ... - -Now, let's recreate the sample buildout. If we specify constraints on -the versions of zc.buildout and setuptools (or distribute) to use, -running the buildout will install earlier versions of these packages: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... find-links = %(new_releases)s - ... index = %(new_releases)s - ... parts = show-versions - ... develop = showversions - ... zc.buildout-version = < 99 - ... setuptools-version = < 99 - ... distribute-version = < 99 - ... - ... [show-versions] - ... recipe = showversions - ... """ % dict(new_releases=new_releases)) - -Now we can see that we actually "upgrade" to an earlier version. - - >>> print system(buildout), - Upgraded: - zc.buildout version 1.0.0, - setuptools version 0.6; - restarting. - Develop: '/sample-buildout/showversions' - Updating show-versions. - zc.buildout 1.0.0 - setuptools 0.6 - -There are a number of cases, described below, in which the updates -don't happen. - -We won't upgrade in offline mode: - - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... find-links = %(new_releases)s - ... index = %(new_releases)s - ... parts = show-versions - ... develop = showversions - ... - ... [show-versions] - ... recipe = showversions - ... """ % dict(new_releases=new_releases)) - - >>> print system(buildout+' -o'), - Develop: '/sample-buildout/showversions' - Updating show-versions. - zc.buildout 1.0.0 - setuptools 0.6 - -Or in non-newest mode: - - >>> print system(buildout+' -N'), - Develop: '/sample-buildout/showversions' - Updating show-versions. - zc.buildout 1.0.0 - setuptools 0.6 - -We also won't upgrade if the buildout script being run isn't in the -buildout's bin directory. To see this we'll create a new buildout -directory: - - >>> sample_buildout2 = tmpdir('sample_buildout2') - >>> write(sample_buildout2, 'buildout.cfg', - ... """ - ... [buildout] - ... find-links = %(new_releases)s - ... index = %(new_releases)s - ... parts = - ... """ % dict(new_releases=new_releases)) - - >>> cd(sample_buildout2) - >>> print system(buildout), - Creating directory '/sample_buildout2/bin'. - Creating directory '/sample_buildout2/parts'. - Creating directory '/sample_buildout2/eggs'. - Creating directory '/sample_buildout2/develop-eggs'. - Getting distribution for 'zc.buildout'. - Got zc.buildout 99.99. - Getting distribution for 'setuptools'. - Got setuptools 99.99. - Not upgrading because not running a local buildout command. - - >>> ls('bin') - -As mentioned above, the ``accept-buildout-test-releases = true`` means that -newer non-final versions of these dependencies are preferred. Typically -users are not expected to actually manipulate this value. Instead, the -bootstrap script creates a buildout buildout script that passes in the -value as a command line override. This then results in the buildout -script being rewritten to remember the decision. - -We'll mimic this by passing the argument actually in the command line. - - >>> cd(sample_buildout) - >>> write(sample_buildout, 'buildout.cfg', - ... """ - ... [buildout] - ... find-links = %(new_releases)s - ... index = %(new_releases)s - ... parts = show-versions - ... develop = showversions - ... - ... [show-versions] - ... recipe = showversions - ... """ % dict(new_releases=new_releases)) - - >>> print system(buildout + - ... ' buildout:accept-buildout-test-releases=true'), - ... # doctest: +NORMALIZE_WHITESPACE - Getting distribution for 'zc.buildout'. - Got zc.buildout 100.0b1. - Upgraded: - zc.buildout version 100.0b1, - setuptools version 99.99; - restarting. - Generated script '/sample-buildout/bin/buildout'. - NOTE: Accepting early releases of build system packages. Rerun bootstrap - without --accept-buildout-test-releases (-t) to return to default - behavior. - Develop: '/sample-buildout/showversions' - Updating show-versions. - zc.buildout 100.0b1 - setuptools 99.99 - -The buildout script shows the change. - - >>> buildout_script = join(sample_buildout, 'bin', 'buildout') - >>> import sys - >>> if sys.platform.startswith('win'): - ... buildout_script += '-script.py' - >>> print open(buildout_script).read() # doctest: +ELLIPSIS - #... - sys.argv.insert(1, 'buildout:accept-buildout-test-releases=true') - print ('NOTE: Accepting early releases of build system packages. Rerun ' - 'bootstrap without --accept-buildout-test-releases (-t) to return to ' - 'default behavior.') - ... diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/upgrading_distribute.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/upgrading_distribute.txt deleted file mode 100644 index e45b54b..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/upgrading_distribute.txt +++ /dev/null @@ -1,56 +0,0 @@ -Installing setuptools/distribute --------------------------------- - -Some initial test setup: - - >>> import sys - >>> import zc.buildout - >>> dest = tmpdir('sample-install') - -Setuptools (0.6something) is packaged as an ``.egg``. So when installing it, -the egg is downloaded and used. Distribute is packaged as a tarball, which -makes an easy_install call necessary. In older versions of buildout, the -``_call_easy_install()`` method would call ``_get_dist()`` to get hold of the -setuptools path for calling easy_install. When an updated "distribute" was -found, this would try an install again, leading to an infinite recursion. - -The solution is to just use the setuptools location found at import time, like -happens with the buildout and setuptools location that is inserted in scripts' -paths. - -We test this corner case by patching the ``_get_dist()`` call: - - >>> def mock_get_dist(requirement, ws, always_unzip): - ... raise RuntimeError("We should not get called") - -When installing setuptools itself, we expect the "Getting dist" message not to -be printed. We call ``_call_easy_install()`` directly and get an error -because of a non-existing tarball, but that's the OK for this corner case -test: we only want to test that ``_get_dist()`` isn't getting called: - - >>> class MockDist(object): - ... def __str__(self): - ... return 'nonexisting.tgz' - ... @property - ... def project_name(self): - ... # Testing corner case: there *is* actually - ... # a newer setuptools package on pypi than we - ... # are running with, so it really installs it - ... # and compares project_name. We're past the - ... # point that we're testing, so we just raise - ... # the normally expected error. - ... raise zc.buildout.UserError( - ... "Couldn't install: nonexisting.tgz") - >>> dist = MockDist() - - >>> installer = zc.buildout.easy_install.Installer( - ... dest=dest, - ... links=[link_server], - ... index=link_server+'index/', - ... executable=sys.executable, - ... always_unzip=True) - >>> installer._get_dist = mock_get_dist - >>> installer._call_easy_install('setuptools', None, dest, dist) - Traceback (most recent call last): - ... - UserError: Couldn't install: nonexisting.tgz diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/virtualenv.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/virtualenv.txt deleted file mode 100644 index c6c127f..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/virtualenv.txt +++ /dev/null @@ -1,257 +0,0 @@ -Version 1.5.0 of buildout (and higher) provides the ability to use -buildout directly with a system Python if you use z3c.recipe.scripts or -other isolation-aware recipes that use the sitepackage_safe_scripts function. - -Some people use virtualenv to provide similar functionality. -Unfortunately, a problem with the virtualenv executable as of this -writing means that -S will not work properly with it (see -https://bugs.launchpad.net/virtualenv/+bug/572545). This breaks -buildout's approach to providing isolation. - -Because of this, if buildout detects an executable with a broken -S -option, it will revert to its pre-1.5.0 behavior. If buildout has been -asked to provide isolation, it will warn the user that isolation will -not be provided by buildout, but proceed. This should give full -backwards compatibility to virtualenv users. - -The only minor annoyance in the future may be recipes that explicitly -use the new buildout functionality to provide isolation: as described -above, the builds will proceed, but users will receive warnings that -buildout is not providing isolation itself. The warnings themselves can -be squelched when running bin/buildout with the ``-s`` option or with a -lower verbosity than usual (e.g., one or more ``-q`` options). - -For tests, then, we can examine several things. We'll focus on four. - -- Running bootstrap with an executable broken in this way will not try to do - any -S tricks. - -- Running sitepackage_safe_scripts with a virtualenv will create an - old-style script. This will affect the bin/buildout script that is - created, for instance. If the sitepackage_safe_scripts function is asked - to provide isolation under these circumstances, it will warn that isolation - will not be available, but still create the desired script. - -- Using the easy_install Installer or install or build functions and trying - to request isolation will generate a warning and then the isolation request - will be ignored as it proceeds. - -- Passing -s (or -q) to the bin/buildout script will squelch warnings. - -Testing these involves first creating a Python that exhibits the same -behavior as the problematic one we care about from virtualenv. Let's do that -first. - - >>> import os, sys - >>> from zc.buildout.easy_install import _safe_arg - >>> py_path, site_packages_path = make_py() - >>> if sys.platform == 'win32': - ... py_script_path = py_path + '-script.py' - ... else: - ... py_script_path = py_path - ... - >>> py_file = open(py_script_path) - >>> py_lines = py_file.readlines() - >>> py_file.close() - >>> py_file = open(py_script_path, 'w') - >>> extra = '''\ - ... new_argv = argv[:1] - ... for ix, val in enumerate(argv[1:]): - ... if val.startswith('--'): - ... new_argv.append(val) - ... if val.startswith('-') and len(val) > 1: - ... if 'S' in val: - ... val = val.replace('S', '') - ... environ['BROKEN_DASH_S'] = 'Y' - ... if val != '-': - ... new_argv.append(val) - ... if 'c' in val: - ... new_argv.extend(argv[ix+2:]) - ... break - ... else: - ... new_argv.extend(argv[ix+1:]) - ... argv = new_argv - ... ''' - >>> for line in py_lines: - ... py_file.write(line) - ... if line.startswith('environ = os.environ.copy()'): - ... py_file.write(extra) - ... print 'Rewritten.' - ... - Rewritten. - >>> py_file.close() - >>> sitecustomize_path = join(os.path.dirname(site_packages_path), - ... 'parts', 'py', 'sitecustomize.py') - >>> sitecustomize_file = open(sitecustomize_path, 'a') - >>> sitecustomize_file.write(''' - ... import os, sys - ... sys.executable = %r - ... if 'BROKEN_DASH_S' in os.environ: - ... class ImportHook: - ... site = None - ... - ... @classmethod - ... def find_module(klass, fullname, path=None): - ... if klass.site is None and 'site' in sys.modules: - ... # Pop site out of sys.modules. This will be a - ... # close-enough approximation of site not being - ... # loaded for our tests--it lets us provoke the - ... # right errors when the fixes are absent, and - ... # works well enough when the fixes are present. - ... klass.site = sys.modules.pop('site') - ... if fullname == 'ConfigParser': - ... raise ImportError(fullname) - ... elif fullname == 'site': - ... # Keep the site module from being processed twice. - ... return klass - ... - ... @classmethod - ... def load_module(klass, fullname): - ... if fullname == 'site': - ... return klass.site - ... raise ImportError(fullname) - ... - ... sys.meta_path.append(ImportHook) - ... ''' % (py_path,)) - >>> sitecustomize_file.close() - >>> print call_py( - ... _safe_arg(py_path), - ... "import ConfigParser") - <BLANKLINE> - >>> print 'X'; print call_py( - ... _safe_arg(py_path), - ... "import ConfigParser", - ... '-S') # doctest: +ELLIPSIS - X...Traceback (most recent call last): - ... - ImportError: No module named ConfigParser - <BLANKLINE> - >>> from zc.buildout.easy_install import _has_broken_dash_S - >>> _has_broken_dash_S(py_path) - True - -Well, that was ugly, but it seems to have done the trick. The -executable represented by py_path has the same problematic -characteristic as the virtualenv one: -S results in a Python that does -not allow the import of some packages from the standard library. We'll -test with this. - -First, let's try running bootstrap. - - >>> from os.path import dirname, join - >>> import zc.buildout - >>> bootstrap_py = join( - ... dirname( - ... dirname( - ... dirname( - ... dirname(zc.buildout.__file__) - ... ) - ... ) - ... ), - ... 'bootstrap', 'bootstrap.py') - >>> broken_S_buildout = tmpdir('broken_S') - >>> os.chdir(broken_S_buildout) - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = - ... ''') - >>> write('bootstrap.py', open(bootstrap_py).read()) - >>> print 'X'; print system( - ... _safe_arg(py_path)+' '+ - ... 'bootstrap.py'); print 'X' # doctest: +ELLIPSIS - X... - Generated script '/broken_S/bin/buildout'. - ... - -If bootstrap didn't look out for a broken -S, that would have failed. Moreover, -take a look at bin/buildout: - - >>> cat('bin', 'buildout') # doctest: +NORMALIZE_WHITESPACE - #!/executable_buildout/bin/py - <BLANKLINE> - import sys - sys.path[0:0] = [ - '/broken_S/eggs/setuptools-0.0-pyN.N.egg', - '/broken_S/eggs/zc.buildout-0.0-pyN.N.egg', - ] - <BLANKLINE> - import zc.buildout.buildout - <BLANKLINE> - if __name__ == '__main__': - zc.buildout.buildout.main() - -That's the old-style buildout script: no changes for users with this issue. - -Of course, they don't get the new features either, presumably because -they don't need or want them. This means that if they use a recipe that -tries to use a new feature, the behavior needs to degrade gracefully. - -Here's an example. We'll switch to another buildout in which it is easier to -use local dev versions of zc.buildout and z3c.recipe.scripts. - - >>> os.chdir(dirname(dirname(buildout))) - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = eggs - ... find-links = %(link_server)s - ... include-site-packages = false - ... - ... [primed_python] - ... executable = %(py_path)s - ... - ... [eggs] - ... recipe = z3c.recipe.scripts - ... python = primed_python - ... interpreter = py - ... eggs = demo - ... ''' % globals()) - - >>> print system(buildout), # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS - Installing eggs. - Getting distribution for 'demo'. - Got demo 0.4c1. - Getting distribution for 'demoneeded'. - Got demoneeded 1.2c1. - Generated script '/sample-buildout/bin/demo'. - Generated interpreter '/sample-buildout/bin/py'. - ...UserWarning: Buildout has been asked to exclude or limit site-packages - so that builds can be repeatable when using a system Python. However, - the chosen Python executable has a broken implementation of -S (see - https://bugs.launchpad.net/virtualenv/+bug/572545 for an example - problem) and this breaks buildout's ability to isolate site-packages. - If the executable already has a clean site-packages (e.g., using - virtualenv's ``--no-site-packages`` option) you may be getting - equivalent repeatability. To silence this warning, use the -s argument - to the buildout script. Alternatively, use a Python executable with a - working -S (such as a standard Python binary). - warnings.warn(BROKEN_DASH_S_WARNING) - -So, it did what we asked as best it could, but gave a big warning. If -you don't want those warnings for those particular recipes that use the -new features, you can use the "-s" option to squelch the warnings. - - >>> print system(buildout + ' -s'), - Updating eggs. - -A lower verbosity (one or more -q options) also quiets the warning. - - >>> print system(buildout + ' -q'), - -Notice that, as we saw before with bin/buildout, the generated scripts -are old-style, because the new-style feature gracefully degrades to the -previous implementation when it encounters an executable with a broken -dash-S. - - >>> print 'X'; cat('bin', 'py') # doctest: +ELLIPSIS - X... - <BLANKLINE> - import sys - <BLANKLINE> - sys.path[0:0] = [ - '/sample-buildout/eggs/demo-0.4c1-pyN.N.egg', - '/sample-buildout/eggs/demoneeded-1.2c1-pyN.N.egg', - ] - ... - diff --git a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/windows.txt b/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/windows.txt deleted file mode 100644 index 3f6b1d1..0000000 --- a/eggs/zc.buildout-1.5.2-py2.6.egg/zc/buildout/windows.txt +++ /dev/null @@ -1,66 +0,0 @@ -zc.buildout on MS-Windows -========================= - -Certain aspects of every software project are dependent on the -operating system used. -The same - of course - applies to zc.buildout. - -To test that Windows doesn't get in the way, we'll test some system -dependent aspects. -The following recipe will create a read-only file which shutil.rmtree -can't delete. - - >>> mkdir('recipe') - >>> write('recipe', 'recipe.py', - ... ''' - ... import os - ... class Recipe: - ... def __init__(self, buildout, name, options): - ... self.location = os.path.join( - ... buildout['buildout']['parts-directory'], - ... name) - ... - ... def install(self): - ... print "can't remove read only files" - ... if not os.path.exists (self.location): - ... os.makedirs (self.location) - ... - ... name = os.path.join (self.location, 'readonly.txt') - ... open (name, 'w').write ('this is a read only file') - ... os.chmod (name, 0400) - ... return () - ... - ... update = install - ... ''') - - >>> write('recipe', 'setup.py', - ... ''' - ... from setuptools import setup - ... setup(name='spam', version='1', py_modules=['recipe'], - ... entry_points={'zc.buildout': ['default = recipe:Recipe']}, - ... ) - ... ''') - - >>> write('recipe', 'README', '') - - >>> print system(buildout+' setup recipe bdist_egg'), # doctest: +ELLIPSIS - Running setup script 'recipe/setup.py'. - ... - -and we'll configure a buildout to use it: - - >>> write('buildout.cfg', - ... ''' - ... [buildout] - ... parts = foo - ... find-links = %s - ... - ... [foo] - ... recipe = spam - ... ''' % join('recipe', 'dist')) - - >>> print system(buildout), - Getting distribution for 'spam'. - Got spam 1. - Installing foo. - can't remove read only files |