Commit bb152420 authored by Gary Poster's avatar Gary Poster

Implementation complete to my knowledge. Tests pass locally.

Need to check if tests are complete/sufficient, and test with multiple Pythons
and on Windows.

Changed zc.recipe.egg and the easy_install.scripts function into only adding
-S to scripts.

New package z3c.recipe.scripts and the easy_install.generate_scripts now
contains the more robust interpreter generation and the ability to
include site-packages.

Pertinent tests from the previous approach (from 3+ months ago) are
ported.  In the course of this port I discovered that big changes like
the ones in this checkin were needed.
parent 7794bee7
Change History
**************
1.?.? (200?-??-??)
1.?.? (201?-??-??)
==================
New Features:
- Buildout can be safely used with a system Python. Note that the Python is
always used, by default, with -S: that is, site-packages are not
included. If you would like to have access to your site-packages, see
the next bullet point.
A limitation: in no cases are distributions in your site-packages used
to satisfy buildout dependencies. The site-packages can be used in
addition to the dependencies specified in your buildout, and buildout
dependencies can override code in your site-packages, but even if your
Python's site-packages has the same exact version as specified in your
buildout configuration, buildout will still use its own copy.
- Added new function to generate scripts and interpreter. It produces
a full-featured interpreter (all command-line options supported) and the
ability to safely let scripts include site packages (see
z3c.recipe.scripts). In this case a functioning site.py also is available
(and namespace packages are handled somewhat more efficiently than standard
pkg_resources usage).
- Improve bootstrap.
* New options let you specify where to find ez_setup.py and where to find
......@@ -28,6 +47,16 @@ Bugs fixed:
This means, among other things, that ``bin/buildout -vv`` and
``bin/buildout annotate`` correctly list more of the options.
- Installing a namespace package using a Python that already has a package
in the same namespace (e.g., in the Python's site-packages) in some cases.
- 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.
1.4.1 (2009-08-27)
==================
......
......@@ -37,6 +37,11 @@ Existing recipes include:
dependencies. It installs their console-script entry points with
the needed eggs included in their paths.
`z3c.recipe.scripts <http://pypi.python.org/pypi/z3c.recipe.scripts>`_
This scripts recipe builds interpreter scripts and entry point scripts
based on eggs. These scripts have more features and flexibility than the
ones offered by zc.recipe.egg.
`zc.recipe.testrunner <http://pypi.python.org/pypi/zc.recipe.testrunner>`_
The testrunner egg creates a test runner script for one or
more eggs.
......@@ -126,7 +131,7 @@ If I need to run a previous version of zc.buildout, I use the
`--version` option of the bootstrap.py script::
$ python bootstrap.py --version 1.1.3
The `zc.buildout project <http://svn.zope.org/zc.buildout/trunk>`_
is a slightly more complex example of this type of buildout.
......
[buildout]
develop = zc.recipe.egg_ .
develop = zc.recipe.egg_ z3c.recipe.scripts_ .
parts = test oltest py
[py]
......@@ -13,6 +13,7 @@ recipe = zc.recipe.testrunner
eggs =
zc.buildout
zc.recipe.egg
z3c.recipe.scripts
# Tests that can be run wo a network
[oltest]
......@@ -20,6 +21,7 @@ recipe = zc.recipe.testrunner
eggs =
zc.buildout
zc.recipe.egg
z3c.recipe.scripts
defaults =
[
'-t',
......
This diff is collapsed.
This diff is collapsed.
......@@ -117,7 +117,12 @@ def _runsetup(setup, executable, *args):
args = [zc.buildout.easy_install._safe_arg(arg)
for arg in args]
args.insert(0, '-q')
args.append(dict(os.environ, PYTHONPATH=setuptools_location))
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:
......@@ -136,6 +141,11 @@ def sdist(setup, dest):
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:
......@@ -295,12 +305,15 @@ def buildoutSetUp(test):
' ' + 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
[py]
recipe = zc.recipe.egg:interpreter
recipe = z3c.recipe.scripts
interpreter = py
initialization =
%(initialization)s
extra-paths = %(site-packages)s
......
This diff is collapsed.
......@@ -11,7 +11,7 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
import os, re, sys, unittest
import os, re, subprocess, sys, textwrap, unittest
from zope.testing import doctest, renormalizing
import zc.buildout.tests
import zc.buildout.testing
......@@ -43,6 +43,33 @@ We can specify a specific Python executable.
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)
''')
if subprocess.call([other_executable, '-c', command],
env=os.environ):
# 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.generate_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=os.environ), (
'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
......
......@@ -85,9 +85,9 @@ Our buildout script has been updated to use the new eggs:
<BLANKLINE>
import sys
sys.path[0:0] = [
'/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
'/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
]
'/sample-buildout/eggs/zc.buildout-99.99-py2.4.egg',
'/sample-buildout/eggs/setuptools-99.99-py2.4.egg',
]
<BLANKLINE>
<BLANKLINE>
import zc.buildout.buildout
......
Change History
**************
1.0.0
=====
Initial public version.
********************************
Buildout Script Recipe
********************************
.. contents::
The script recipe installs eggs into a buildout eggs directory, exactly
like zc.recipe.egg, and then generates scripts in a buildout bin
directory with egg paths baked into them.
##############################################################################
#
# Copyright (c) 2007 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.
#
##############################################################################
"""Setup for z3c.recipe.scripts package
$Id: setup.py 106736 2009-12-18 02:33:08Z gary $
"""
version = '1.0'
import os
from setuptools import setup, find_packages
def read(*rnames):
return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
name = "z3c.recipe.scripts"
setup(
name = name,
version = version,
author = "Gary Poster",
author_email = "gary.poster@canonical.com",
description = "Recipe for installing Python scripts",
long_description = (
read('README.txt')
+ '\n' +
read('CHANGES.txt')
+ '\n' +
'Detailed Documentation\n'
'**********************\n'
+ '\n' +
read('src', 'z3c', 'recipe', 'scripts', 'README.txt')
+ '\n' +
'Download\n'
'*********\n'
),
keywords = "development build",
classifiers = [
'Development Status :: 5 - Production/Stable',
'Framework :: Buildout',
'Intended Audience :: Developers',
'License :: OSI Approved :: Zope Public License',
'Topic :: Software Development :: Build Tools',
'Topic :: Software Development :: Libraries :: Python Modules',
],
url='http://cheeseshop.python.org/pypi/z3c.recipe.scripts',
license = "ZPL 2.1",
packages = find_packages('src'),
package_dir = {'':'src'},
namespace_packages = ['z3c', 'z3c.recipe'],
install_requires = [
'zc.buildout >=1.2.0',
'zc.recipe.egg',
'setuptools'],
tests_require = ['zope.testing'],
test_suite = name+'.tests.test_suite',
entry_points = {'zc.buildout': ['default = %s:Scripts' % name,
'script = %s:Scripts' % name,
'scripts = %s:Scripts' % name,
'interpreter = %s:Interpreter' % name,
]
},
include_package_data = True,
zip_safe=False,
)
__import__('pkg_resources').declare_namespace(__name__)
__import__('pkg_resources').declare_namespace(__name__)
This diff is collapsed.
from z3c.recipe.scripts.scripts import Scripts, Interpreter
##############################################################################
#
# Copyright (c) 2009-2010 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.
#
##############################################################################
"""Install scripts from eggs.
"""
import os
import zc.buildout
import zc.buildout.easy_install
from zc.recipe.egg.egg import ScriptBase
class Base(ScriptBase):
def __init__(self, buildout, name, options):
if 'extends' in options:
options.update(buildout[options['extends']])
super(Base, self).__init__(buildout, name, options)
self.default_eggs = '' # Disables feature from zc.recipe.egg.
b_options = buildout['buildout']
options['parts-directory'] = os.path.join(
b_options['parts-directory'], self.name)
value = options.setdefault(
'add-site-packages',
b_options.get('add-site-packages', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for add-site-packages option: %s" %
(value,))
self.add_site_packages = (value == 'true')
value = options.setdefault(
'exec-sitecustomize',
b_options.get('exec-sitecustomize', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for exec-sitecustomize option: %s" %
(value,))
self.exec_sitecustomize = (value == 'true')
class Interpreter(Base):
def __init__(self, buildout, name, options):
super(Interpreter, self).__init__(buildout, name, options)
options.setdefault('name', name)
def install(self):
reqs, ws = self.working_set()
options = self.options
generated = []
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
generated.append(options['parts-directory'])
generated.extend(zc.buildout.easy_install.generate_scripts(
options['bin-directory'], ws, options['executable'],
options['parts-directory'],
interpreter=options['name'],
extra_paths=self.extra_paths,
initialization=options.get('initialization', ''),
add_site_packages=self.add_site_packages,
exec_sitecustomize=self.exec_sitecustomize,
relative_paths=self._relative_paths,
))
return generated
update = install
class Scripts(Base):
def _install(self, reqs, ws, scripts):
options = self.options
generated = []
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
generated.append(options['parts-directory'])
generated.extend(zc.buildout.easy_install.generate_scripts(
options['bin-directory'], ws, options['executable'],
options['parts-directory'], reqs=reqs, scripts=scripts,
interpreter=options.get('interpreter'),
extra_paths=self.extra_paths,
initialization=options.get('initialization', ''),
add_site_packages=self.add_site_packages,
exec_sitecustomize=self.exec_sitecustomize,
relative_paths=self._relative_paths,
script_arguments=options.get('arguments', ''),
script_initialization=options.get('script-initialization', '')
))
return generated
##############################################################################
#
# 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.
#
##############################################################################
import os, re, shutil, sys
import zc.buildout.tests
import zc.buildout.testselectingpython
import zc.buildout.testing
import unittest
from zope.testing import doctest, renormalizing
# We do not explicitly test the recipe support for the ``eggs``,
# ``find-links``, and ``index`` options because they are used for most or
# all of the examples. The README tests ``extends``,
# ``include-site-customization`` and ``name``. That leaves ``python``,
# ``extra-paths``, ``initialization``, ``relative-paths``, and
# ``include-site-packages``.
def supports_python_option():
"""
This simply shows that the ``python`` option can specify another section to
find the ``executable``. (The ``python`` option defaults to looking in the
``buildout`` section.) We do this by creating a custom Python that will have
some initialization that we can look for.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... exec-sitecustomize = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_extra_paths_option():
"""
This shows that specifying extra-paths will affect sys.path.
This recipe will not add paths that do not exist, so we create them.
>>> mkdir(sample_buildout, 'foo')
>>> mkdir(sample_buildout, 'foo', 'bar')
>>> mkdir(sample_buildout, 'spam')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... find-links = %(server)s
... index = %(server)s/index
... extra-paths =
... ${buildout:directory}/foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import sys;print 'path' + ' '.join(sys.path)"''')
... # doctest:+ELLIPSIS
path.../foo/bar /sample-buildout/spam...
"""
def interpreter_recipe_supports_initialization_option():
"""
This simply shows that the ``initialization`` option can specify code to
run on initialization.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... initialization =
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.buildout'] = 'foo bar baz shazam'
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
This also works with the exec-sitecustomize option, processing local
initialization, and then the Python's initialization. We show this with a
custom Python.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... initialization =
... import os
... os.environ['zc.recipe.egg'] = 'baLOOba'
... exec-sitecustomize = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Uninstalling py.
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.recipe.egg'] = 'baLOOba'
<BLANKLINE>
# The following is from
# /executable_buildout/parts/py/sitecustomize.py
<BLANKLINE>
import os
os.environ['zc.buildout'] = 'foo bar baz shazam'
>>> print system(join(sample_buildout, 'bin', 'py') + ' -c ' +
... '''"import os; print os.environ['zc.recipe.egg']"'''),
baLOOba
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_relative_paths_option():
"""
This shows that the relative-paths option affects the code for inserting
paths into sys.path.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = z3c.recipe.scripts:interpreter
... find-links = %(server)s
... index = %(server)s/index
... relative-paths = true
... extra-paths =
... /foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
Let's look at the site.py that was generated:
>>> import sys
>>> sys.stdout.write('#'); cat(sample_buildout, 'parts', 'py', 'site.py')
... # doctest: +NORMALIZE_WHITESPACE +ELLIPSIS
#...
def addsitepackages(known_paths):
paths = []
<BLANKLINE>
import os
<BLANKLINE>
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)
paths[0:0] = [ # eggs
'/foo/bar',
join(base, 'spam')
]...
"""
def setUp(test):
zc.buildout.tests.easy_install_SetUp(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
zc.buildout.testing.install_develop('z3c.recipe.scripts', test)
def setUpSelecting(test):
zc.buildout.testselectingpython.setup(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
zc.buildout.testing.install_develop('z3c.recipe.scripts', test)
def test_suite():
suite = unittest.TestSuite((
doctest.DocFileSuite(
'README.txt',
setUp=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.normalize_bang,
(re.compile(r'zc.buildout(-\S+)?[.]egg(-link)?'),
'zc.buildout.egg'),
(re.compile('[-d] setuptools-[^-]+-'), 'setuptools-X-'),
(re.compile(r'setuptools-[\w.]+-py'), 'setuptools-X-py'),
(re.compile(r'eggs\\\\demo'), 'eggs/demo'),
(re.compile(r'[a-zA-Z]:\\\\foo\\\\bar'), '/foo/bar'),
(re.compile(r'\#!\S+\bpython\S*'), '#!/usr/bin/python'),
])
),
doctest.DocTestSuite(
setUp=setUp,
tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_egg_py,
]),
),
))
return suite
if __name__ == '__main__':
unittest.main(defaultTest='test_suite')
This diff is collapsed.
from zc.recipe.egg.egg import Egg, Scripts, Eggs, Interpreter
from zc.recipe.egg.egg import Egg, Scripts, Eggs
from zc.recipe.egg.custom import Custom, Develop
......@@ -116,7 +116,6 @@ computed by the egg recipe by looking at .installed.cfg:
executable = /usr/local/bin/python2.3
extras = other
find-links = http://localhost:27071/
include-site-packages = false
index = http://localhost:27071/index
python = buildout
recipe = sample
......
......@@ -50,7 +50,7 @@ compiler
swig
The path to the swig executable
swig-cpp
swig-cpp
Make SWIG create C++ files (default is C)
swig-opts
......@@ -73,14 +73,14 @@ index
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
we'll just point to an empty directory on our link server. This
will make our examples run a little bit faster.
python
The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named
section.
section.
environment
The name of a section with additional environment variables. The
......@@ -150,6 +150,7 @@ eggs directory can be shared across multiple buildouts.
>>> ls(sample_buildout, 'develop-eggs')
d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
Note that no scripts or dependencies are installed. To install
......@@ -188,7 +189,7 @@ Let's define a script that uses out ext demo:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo
... entry-points = demo=demo:main
... """ % dict(server=link_server))
......@@ -231,6 +232,7 @@ We won't get an update.
>>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link
d extdemo-1.4-py2.4-unix-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
But if we run the buildout in the default on-line and newest modes, we
......@@ -248,6 +250,7 @@ version is imported:
- demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg
d extdemo-1.5-py2.4-linux-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
Controlling the version used
......@@ -270,7 +273,7 @@ We can specify a specific version using the egg option:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo ==1.4
... entry-points = demo=demo:main
... """ % dict(server=link_server))
......@@ -287,6 +290,7 @@ We can specify a specific version using the egg option:
>>> ls(sample_buildout, 'develop-eggs')
- demo.egg-link
d extdemo-1.4-py2.4-linux-i686.egg
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
......@@ -440,7 +444,7 @@ Create a clean buildout.cfg w/o the checkenv recipe, and delete the recipe:
Uninstalling extdemo.
Installing extdemo.
zip_safe flag not set; analyzing archive contents...
>>> rmdir(sample_buildout, 'recipes')
......@@ -496,7 +500,7 @@ compiler
swig
The path to the swig executable
swig-cpp
swig-cpp
Make SWIG create C++ files (default is C)
swig-opts
......@@ -506,7 +510,7 @@ python
The name of a section to get the Python executable from.
If not specified, then the buildout python option is used. The
Python executable is found in the executable option of the named
section.
section.
To illustrate this, we'll use a directory containing the extdemo
example from the earlier section:
......@@ -532,7 +536,7 @@ example from the earlier section:
...
... [demo]
... recipe = zc.recipe.egg
... eggs = demo
... eggs = demo
... extdemo
... entry-points = demo=demo:main
... """ % dict(extdemo=extdemo))
......@@ -553,6 +557,7 @@ Our develop-eggs now includes an egg link for extdemo:
>>> ls('develop-eggs')
- demo.egg-link
- extdemo.egg-link
- z3c.recipe.scripts.egg-link
- zc.recipe.egg.egg-link
and the extdemo now has a built extension:
......
......@@ -128,27 +128,16 @@ class ScriptBase(Eggs):
self._relative_paths = ''
assert relative_paths == 'false'
value = options.setdefault(
'include-site-packages',
b_options.get('include-site-packages', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for include-site-packages option: %s" %
(value,))
self.include_site_packages = (value == 'true')
class Scripts(ScriptBase):
parse_entry_point = re.compile(
'([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$'
).match
def install(self):
reqs, ws = self.working_set()
options = self.options
scripts = options.get('scripts')
if scripts or scripts is None:
if scripts or scripts is None or options.get('interpreter'):
if scripts is not None:
scripts = scripts.split()
scripts = dict([
......@@ -172,66 +161,30 @@ class Scripts(ScriptBase):
name = dist.project_name
if name != 'setuptools' and name not in reqs:
reqs.append(name)
return zc.buildout.easy_install.scripts(
reqs, ws, options['executable'],
options['bin-directory'],
scripts=scripts,
extra_paths=self.extra_paths,
interpreter=options.get('interpreter'),
initialization=options.get('initialization', ''),
arguments=options.get('arguments', ''),
relative_paths=self._relative_paths,
import_site=self.include_site_packages,
)
return self._install(reqs, ws, scripts)
return ()
update = install
def _install(self, reqs, ws, scripts):
# Subclasses implement this.
raise NotImplementedError()
class Interpreter(ScriptBase):
def __init__(self, buildout, name, options):
if 'extends' in options:
options.update(buildout[options['extends']])
super(Interpreter, self).__init__(buildout, name, options)
self.default_eggs = ''
b_options = buildout['buildout']
options['parts-directory'] = os.path.join(
b_options['parts-directory'], self.name)
value = options.setdefault(
'include-site-customization',
b_options.get('include-site-customization', 'false'))
if value not in ('true', 'false'):
raise zc.buildout.UserError(
"Invalid value for include-site-customization option: %s" %
(value,))
self.include_site_customization = (value == 'true')
options.setdefault('name', name)
class Scripts(ScriptBase):
def install(self):
reqs, ws = self.working_set()
def _install(self, reqs, ws, scripts):
options = self.options
if not os.path.exists(options['parts-directory']):
os.mkdir(options['parts-directory'])
dir_made = True
else:
dir_made = False
generated = zc.buildout.easy_install.interpreter(
options['name'], ws, options['executable'],
options['bin-directory'], options['parts-directory'],
return zc.buildout.easy_install.scripts(
reqs, ws, options['executable'],
options['bin-directory'],
scripts=scripts,
extra_paths=self.extra_paths,
interpreter=options.get('interpreter'),
initialization=options.get('initialization', ''),
relative_paths=self._relative_paths,
import_site=self.include_site_packages,
import_sitecustomize=self.include_site_customization,
arguments=options.get('arguments', ''),
relative_paths=self._relative_paths
)
if dir_made:
generated.append(options['parts-directory'])
return generated
def get_bool(options, name, default=False):
......
......@@ -29,249 +29,6 @@ def dirname(d, level=1):
return d
return dirname(os.path.dirname(d), level-1)
# We do not explicitly test the interpreter recipe support for the ``eggs``,
# ``find-links``, and ``index`` options because they are used for most or
# all of the examples. The README tests ``extends``,
# ``include-site-customization`` and ``name``. That leaves ``python``,
# ``extra-paths``, ``initialization``, ``relative-paths``, and
# ``include-site-packages``.
def interpreter_recipe_supports_python_option():
"""
This simply shows that the ``python`` option can specify another section to
find the ``executable``. (The ``python`` option defaults to looking in the
``buildout`` section.) We do this by creating a custom Python that will have
some initialization that we can look for.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = zc.recipe.egg:interpreter
... include-site-customization = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_extra_paths_option():
"""
This shows that specifying extra-paths will affect sys.path.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = zc.recipe.egg:interpreter
... find-links = %(server)s
... index = %(server)s/index
... extra-paths =
... /foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import sys;print 'path' + ' '.join(sys.path)"''')
... # doctest:+ELLIPSIS
path.../foo/bar /sample-buildout/spam...
"""
def interpreter_recipe_supports_initialization_option():
"""
This simply shows that the ``initialization`` option can specify code to
run on initialization.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = zc.recipe.egg:interpreter
... initialization =
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.buildout'] = 'foo bar baz shazam'
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
This also works with the include-site-customization option, processing local
initialization, and then the Python's initialization. We show this with a
custom Python.
>>> py_path, site_packages_path = make_py(initialization='''
... import os
... os.environ['zc.buildout'] = 'foo bar baz shazam'
... ''')
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [custom_python]
... executable = %(py_path)s
...
... [py]
... recipe = zc.recipe.egg:interpreter
... initialization =
... import os
... os.environ['zc.recipe.egg'] = 'baLOOba'
... include-site-customization = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... python = custom_python
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Uninstalling py.
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
>>> cat(sample_buildout, 'parts', 'py', 'sitecustomize.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
os.environ['zc.recipe.egg'] = 'baLOOba'
execfile('/executable_buildout/parts/py/sitecustomize.py')
>>> print system(join(sample_buildout, 'bin', 'py') + ' -c ' +
... '''"import os; print os.environ['zc.recipe.egg']"'''),
baLOOba
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import os; print os.environ['zc.buildout']"'''),
foo bar baz shazam
"""
def interpreter_recipe_supports_relative_paths_option():
"""
This shows that the relative-paths option affects the code for inserting
paths into sys.path.
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
...
... [py]
... recipe = zc.recipe.egg:interpreter
... find-links = %(server)s
... index = %(server)s/index
... relative-paths = true
... extra-paths =
... /foo/bar
... ${buildout:directory}/spam
... ''' % dict(server=link_server))
>>> print system(buildout),
Installing py.
Generated interpreter '/sample-buildout/bin/py'.
Let's look at the site.py that was generated:
>>> cat(sample_buildout, 'parts', 'py', 'site.py')
... # doctest: +NORMALIZE_WHITESPACE
<BLANKLINE>
import os
<BLANKLINE>
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)
import sys
sys.path[0:0] = [
'/foo/bar',
join(base, 'spam'),
]
import sitecustomize
"""
def interpreter_recipe_supports_include_site_packages_option():
"""
This option simply causes the executable's usual site.py to be processed.
We'll demonstrate this by using a Python that has its own extra path.
>>> py_path, site_packages_path = make_py()
>>> write(sample_buildout, 'buildout.cfg',
... '''
... [buildout]
... parts = py
... executable = %(py_path)s
...
... [py]
... recipe = zc.recipe.egg:interpreter
... include-site-packages = true
... eggs = demo<0.3
... find-links = %(server)s
... index = %(server)s/index
... ''' % dict(server=link_server, py_path=py_path))
>>> print system(buildout),
Installing py.
Getting distribution for 'demo<0.3'.
Got demo 0.2.
Getting distribution for 'demoneeded'.
Got demoneeded 1.2c1.
Generated interpreter '/sample-buildout/bin/py'.
>>> print system(join(sample_buildout, 'bin', 'py') +
... ''' -c "import sys; print (%r in sys.path) or (%r, sys.path)"''' %
... (site_packages_path, site_packages_path)),
True
"""
def setUp(test):
zc.buildout.tests.easy_install_SetUp(test)
zc.buildout.testing.install_develop('zc.recipe.egg', test)
......@@ -332,15 +89,6 @@ def test_suite():
(re.compile('extdemo[.]pyd'), 'extdemo.so')
]),
),
doctest.DocTestSuite(
setUp=setUp,
tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([
zc.buildout.testing.normalize_path,
zc.buildout.testing.normalize_endings,
zc.buildout.testing.normalize_egg_py,
]),
),
))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment