Commit e445e585 authored by Jim Fulton's avatar Jim Fulton

Added missing tests.

parent a2a19ac4
Custom script support
=====================
The egg-linker module provides support for creating scripts from
eggs. It provides a function similar to setup tools except that it
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.
We have a directory with some sample eggs in it:
>>> ls(sample_eggs)
- demo-0.1-py2.3.egg
- demo-0.2-py2.3.egg
- demo-0.3-py2.3.egg
- demoneeded-1.0-py2.3.egg
The demo package depends on the demoneeded package.
The egglinker module can be used to generate scripts. Let's create a
desitnation directory for it to place them in:
>>> import tempfile
>>> bin = tempfile.mkdtemp()
Now, we'll use the egg linker to generate scripts in this directory
from the demo egg:
>>> import zc.buildout.egglinker
>>> scripts = zc.buildout.egglinker.scripts(['demo==0.1'], bin,
... [sample_eggs])
the three 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. The destination directory.
3, A sequence of egg directories, which are searched for suitable
distributions.
The bin directory now contains 2 generated scripts:
>>> ls(bin)
- demo
- py_demo
The return value is a list of the scripts generated:
>>> import os
>>> scripts == [os.path.join(bin, 'demo'), os.path.join(bin, 'py_demo')]
True
The demo script run the entry point defined in the demo egg:
>>> cat(bin, 'demo')
#!/usr/local/bin/python2.3
<BLANKLINE>
import sys
sys.path[0:0] = [
'/tmp/tmpuR5-n7eggtest/dist/demo-0.1-py2.3.egg',
'/tmp/tmpuR5-n7eggtest/dist/demoneeded-1.0-py2.3.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.
The py_demo script simply run the Python interactive interpreter with
the path set:
>>> cat(bin, 'py_demo')
#!/usr/local/bin/python2.3 -i
<BLANKLINE>
import sys
sys.path[0:0] = [
'/tmp/tmpuR5-n7eggtest/dist/demo-0.1-py2.3.egg',
'/tmp/tmpuR5-n7eggtest/dist/demoneeded-1.0-py2.3.egg'
]
An additional argumnet can be passed to define which scripts to install
and to provie script names. The argument is a dictionary mapping
original script names to new script names.
>>> import shutil
>>> shutil.rmtree(bin)
>>> bin = tempfile.mkdtemp()
>>> scripts = zc.buildout.egglinker.scripts(
... ['demo==0.1'], bin, [sample_eggs],
... dict(demo='run'))
>>> scripts == [os.path.join(bin, 'run')]
True
>>> ls(bin)
- run
>>> print system(os.path.join(bin, 'run')),
1 1
>>> shutil.rmtree(bin)
Sometimes we need more control over script generation. Some
lower-level APIs are available to help us generate scripts ourselves.
These apis are a little bit higher level than those provided by
the pkg_resources from the setuptools distribution.
The path method returns a path to a set of eggs satisftying a sequence
of requirements from a sequence of egg directories:
>>> zc.buildout.egglinker.path(['demo==0.1'], [sample_eggs])
... # doctest: +NORMALIZE_WHITESPACE
['/tmp/tmpQeJjpkeggtest/dist/demo-0.1-py2.4.egg',
'/tmp/tmpQeJjpkeggtest/dist/demoneeded-1.0-py2.4.egg']
The location method returns the distribution location for an egg that
satisfies a requirement:
>>> zc.buildout.egglinker.location('demo==0.1', [sample_eggs])
'/tmp/tmpQeJjpkeggtest/dist/demo-0.1-py2.4.egg'
The distributions function can retrieve a list of distributions found
ineg directories that match a sequence of requirements:
>>> [(d.project_name, d.version) for d in
... zc.buildout.egglinker.distributions(['demo==0.1'], [sample_eggs])]
[('demo', '0.1'), ('demoneeded', '1.0')]
...@@ -16,10 +16,10 @@ ...@@ -16,10 +16,10 @@
$Id$ $Id$
""" """
import re, unittest import os, re, shutil, sys, tempfile, unittest
from zope.testing import doctest, renormalizing from zope.testing import doctest, renormalizing
import pkg_resources
from zc.buildout.testing import buildoutSetUp, buildoutTearDown import zc.buildout.testing
def buildout_error_handling(): def buildout_error_handling():
r'''Buildout error handling r'''Buildout error handling
...@@ -64,20 +64,90 @@ It is an error to create a variable-reference cycle: ...@@ -64,20 +64,90 @@ It is an error to create a variable-reference cycle:
''' '''
def runsetup(d):
here = os.getcwd()
try:
os.chdir(d)
os.spawnle(
os.P_WAIT, sys.executable, sys.executable,
'setup.py', '-q', 'bdist_egg',
{'PYTHONPATH': os.path.dirname(pkg_resources.__file__)},
)
shutil.rmtree('build')
finally:
os.chdir(here)
def dirname(d, level=1):
if level == 0:
return d
return dirname(os.path.dirname(d), level-1)
def linkerSetUp(test):
zc.buildout.testing.buildoutSetUp(test)
sample = tempfile.mkdtemp('eggtest')
test.globs['_sample_eggs_container'] = sample
test.globs['sample_eggs'] = os.path.join(sample, 'dist')
zc.buildout.testing.write(sample, 'README.txt', '')
zc.buildout.testing.write(sample, 'eggrecipedemobeeded.py', 'y=1\n')
zc.buildout.testing.write(
sample, 'setup.py',
"from setuptools import setup\n"
"setup(name='demoneeded', py_modules=['eggrecipedemobeeded'],"
" zip_safe=True, version='1.0')\n"
)
runsetup(sample)
os.remove(os.path.join(sample, 'eggrecipedemobeeded.py'))
for i in (1, 2, 3):
zc.buildout.testing.write(
sample, 'eggrecipedemo.py',
'import eggrecipedemobeeded\n'
'x=%s\n'
'def main(): print x, eggrecipedemobeeded.y\n'
% i)
zc.buildout.testing.write(
sample, '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')\n" % i
)
runsetup(sample)
def linkerTearDown(test):
shutil.rmtree(test.globs['_sample_eggs_container'])
zc.buildout.testing.buildoutTearDown(test)
def test_suite(): def test_suite():
return unittest.TestSuite(( return unittest.TestSuite((
#doctest.DocTestSuite(), #doctest.DocTestSuite(),
doctest.DocFileSuite( doctest.DocFileSuite(
'buildout.txt', 'buildout.txt',
setUp=buildoutSetUp, tearDown=buildoutTearDown, setUp=zc.buildout.testing.buildoutSetUp,
tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([ checker=renormalizing.RENormalizing([
(re.compile('__buildout_signature__ = recipes-\S+'), (re.compile('__buildout_signature__ = recipes-\S+'),
'__buildout_signature__ = recipes-SSSSSSSSSSS'), '__buildout_signature__ = recipes-SSSSSSSSSSS'),
]) ])
), ),
doctest.DocFileSuite(
'egglinker.txt',
setUp=linkerSetUp, tearDown=linkerTearDown,
checker=renormalizing.RENormalizing([
(re.compile('(\S+[/%(sep)s]| )'
'(\\w+-)[^ \t\n%(sep)s/]+.egg'
% dict(sep=os.path.sep)
),
'\\2-VVV-egg'),
(re.compile('python2.\d'), 'python2.N')
]),
),
doctest.DocTestSuite( doctest.DocTestSuite(
setUp=buildoutSetUp, tearDown=buildoutTearDown), setUp=zc.buildout.testing.buildoutSetUp,
tearDown=zc.buildout.testing.buildoutTearDown),
)) ))
if __name__ == '__main__': if __name__ == '__main__':
......
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