[Checkins] SVN: zc.buildout/trunk/ Allow custom python interpreters
(other than the one used to run the
Jim Fulton
cvs-admin at zope.org
Mon Jun 19 15:20:28 EDT 2006
Log message for revision 68763:
Allow custom python interpreters (other than the one used to run the
buildout) to be used.
Changed:
U zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt
U zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/selecting-python.txt
U zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py
U zc.buildout/trunk/src/zc/buildout/easy_install.py
U zc.buildout/trunk/src/zc/buildout/easy_install.txt
U zc.buildout/trunk/src/zc/buildout/egglinker.py
U zc.buildout/trunk/src/zc/buildout/egglinker.txt
U zc.buildout/trunk/src/zc/buildout/testing.py
U zc.buildout/trunk/src/zc/buildout/tests.py
-=-
Modified: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt 2006-06-19 19:20:24 UTC (rev 68763)
@@ -1,7 +1,7 @@
Installation of distributions as eggs
=====================================
-The zc.recipe.egg ewcipe can be used to install various types if
+The zc.recipe.egg recipe can be used to install various types if
distutils distributions as eggs. It takes a number of options:
distribution
@@ -14,6 +14,18 @@
find-links
A list of URLs, files, or directories to search for distributions.
+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.
+
+unzip
+ The value of this option must be either true or false. If the value
+ is true, then the installed egg will be unzipped. Note that this is
+ only effective when an egg is installed. If a zipped egg already
+ exists in the eggs directory, it will not be unzipped.
+
To illustrate this, we've created a directory with some sample eggs:
>>> ls(sample_eggs)
@@ -51,7 +63,6 @@
>>> ls(sample_buildout, 'eggs')
- demo-0.2-py2.3.egg
- demoneeded-1.0-py2.3.egg
- - zc.recipe.egg.egg-link
We see that we got an egg for demo that met the requirement, as well
as the egg for demoneeded, wich demo requires. (We also see an egg
@@ -94,7 +105,7 @@
<BLANKLINE>
The recipe gets the most recent distribution that satisfies the
-specification. For example, if we remove the restriction on demo:
+specification. For example, We remove the restriction on demo:
>>> write(sample_buildout, 'buildout.cfg',
... """
@@ -104,9 +115,11 @@
... [demo]
... recipe = zc.recipe.egg
... find-links = %s
+ ... unzip = true
... """ % sample_eggs)
-and rerun the buildout:
+We also used the unzip uption to request a directory, rather than
+a zip file.
>>> print system(runscript),
@@ -114,9 +127,8 @@
>>> ls(sample_buildout, 'eggs')
- demo-0.2-py2.3.egg
- - demo-0.3-py2.3.egg
+ d demo-0.3-py2.3.egg
- demoneeded-1.0-py2.3.egg
- - zc.recipe.egg.egg-link
Note that we removed the distribution option, and the distribution
defaulted to the part name.
@@ -150,7 +162,6 @@
You can also control the name used for scripts:
-
>>> write(sample_buildout, 'buildout.cfg',
... """
... [buildout]
@@ -167,3 +178,4 @@
>>> ls(sample_buildout, 'bin')
- buildout
- foo
+
Modified: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -16,7 +16,7 @@
$Id$
"""
-import os
+import os, zipfile
import zc.buildout.egglinker
import zc.buildout.easy_install
@@ -41,12 +41,20 @@
options['_e'] = buildout['buildout']['eggs-directory']
options['_d'] = buildout['buildout']['develop-eggs-directory']
+ assert options.get('unzip') in ('true', 'false', None)
+
+ python = options.get('python', buildout['buildout']['python'])
+ options['executable'] = buildout[python]['executable']
+
def install(self):
options = self.options
distribution = options.get('distribution', self.name)
+
zc.buildout.easy_install.install(
- distribution, options['_e'], self.links)
+ distribution, options['_e'], self.links, options['executable'],
+ always_unzip=options.get('unzip') == 'true')
+ eggss = [options['_d'], options['_e']]
scripts = options.get('scripts')
if scripts or scripts is None:
if scripts is not None:
@@ -56,6 +64,6 @@
for s in scripts
])
return zc.buildout.egglinker.scripts(
- [distribution],
- options['_b'], [options['_d'], options['_e']], scripts=scripts)
-
+ [distribution], options['_b'], eggss,
+ scripts=scripts, executable=options['executable'])
+
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/selecting-python.txt
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/selecting-python.txt 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/selecting-python.txt 2006-06-19 19:20:24 UTC (rev 68763)
@@ -0,0 +1,143 @@
+Controlling which Python to use
+-------------------------------
+
+The following assumes that your $HOME/.buildout/default.cfg has
+python2.3 and python2.4 sections that define Python 2.3 and Python 2.4
+executables.
+
+We can specify the python to use by specifying the name of a section
+to read the Python executable from. The default is the section
+defined by the python buildout option.
+
+We have a directory with some sample eggs:
+
+ >>> ls(sample_eggs)
+ - demo-0.1-py2.3.egg
+ - demo-0.1-py2.4.egg
+ - demo-0.2-py2.3.egg
+ - demo-0.2-py2.4.egg
+ - demo-0.3-py2.3.egg
+ - demo-0.3-py2.4.egg
+ - demoneeded-1.0-py2.3.egg
+ - demoneeded-1.0-py2.4.egg
+
+We have a sample buildout. Let's update it's configuration file to
+install the demo package using Python 2.3.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... parts = demo
+ ... eggs-directory = eggs
+ ...
+ ... [demo]
+ ... recipe = zc.recipe.egg
+ ... distribution = demo <0.3
+ ... find-links = %s
+ ... python = python2.3
+ ... """ % sample_eggs)
+
+In our default.cfg file in the .buildout subdirectiry of our
+directory, we have something like::
+
+ [python2.3]
+ executable = /usr/bin/python
+
+ [python2.4]
+ executable = /usr/local/bin/python2.4
+
+(Of course, the paths will vary from system to system.)
+
+Now, if we run the buildout:
+
+ >>> import os
+ >>> os.chdir(sample_buildout)
+ >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
+ >>> print system(buildout),
+
+we'll get the Python 2.3 eggs for demo and demoneeded:
+
+ >>> ls(sample_buildout, 'eggs')
+ - demo-0.2-py2.3.egg
+ - demoneeded-1.0-py2.3.egg
+
+And the generated scripts invoke Python 2.3:
+
+ >>> f = open(os.path.join(sample_buildout, 'bin', 'demo'))
+ >>> f.readline().strip() == '#!' + python2_3_executable
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.3.egg',
+ '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.0-py2.3.egg'
+ ]
+ <BLANKLINE>
+ import eggrecipedemo
+ <BLANKLINE>
+ if __name__ == '__main__':
+ eggrecipedemo.main()
+
+ >>> f = open(os.path.join(sample_buildout, 'bin', 'py_demo'))
+ >>> f.readline().strip() == '#!' + python2_3_executable + ' -i'
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/tmp/tmpOBTxDMsample-buildout/eggs/demo-0.2-py2.3.egg',
+ '/tmp/tmpOBTxDMsample-buildout/eggs/demoneeded-1.0-py2.3.egg'
+ ]
+
+If we change the Python version to 2.4, we'll use Python 2.4 eggs:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... parts = demo
+ ... eggs-directory = eggs
+ ...
+ ... [demo]
+ ... recipe = zc.recipe.egg
+ ... distribution = demo <0.3
+ ... find-links = %s
+ ... python = python2.4
+ ... """ % sample_eggs)
+
+ >>> print system(buildout),
+
+ >>> ls(sample_buildout, 'eggs')
+ - demo-0.2-py2.3.egg
+ - demo-0.2-py2.4.egg
+ - demoneeded-1.0-py2.3.egg
+ - demoneeded-1.0-py2.4.egg
+
+ >>> f = open(os.path.join(sample_buildout, 'bin', 'demo'))
+ >>> f.readline().strip() == '#!' + python2_4_executable
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.4.egg',
+ '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.0-py2.4.egg'
+ ]
+ <BLANKLINE>
+ import eggrecipedemo
+ <BLANKLINE>
+ if __name__ == '__main__':
+ eggrecipedemo.main()
+
+ >>> f = open(os.path.join(sample_buildout, 'bin', 'py_demo'))
+ >>> f.readline().strip() == '#!' + python2_4_executable + ' -i'
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/tmp/tmpOBTxDMsample-buildout/eggs/demo-0.2-py2.4.egg',
+ '/tmp/tmpOBTxDMsample-buildout/eggs/demoneeded-1.0-py2.4.egg'
+ ]
+
+
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/selecting-python.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Modified: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -26,15 +26,23 @@
def setUp(test):
zc.buildout.testing.buildoutSetUp(test)
open(os.path.join(test.globs['sample_buildout'],
- 'eggs', 'zc.recipe.egg.egg-link'),
+ 'develop-eggs', 'zc.recipe.egg.egg-link'),
'w').write(dirname(__file__, 4))
zc.buildout.testing.create_sample_eggs(test)
def tearDown(test):
shutil.rmtree(test.globs['_sample_eggs_container'])
zc.buildout.testing.buildoutTearDown(test)
+
+def setUpPython(test):
+ zc.buildout.testing.buildoutSetUp(test, clear_home=False)
+ open(os.path.join(test.globs['sample_buildout'],
+ 'develop-eggs', 'zc.recipe.egg.egg-link'),
+ 'w').write(dirname(__file__, 4))
+ zc.buildout.testing.multi_python(test)
+
def test_suite():
return unittest.TestSuite((
#doctest.DocTestSuite(),
@@ -49,7 +57,15 @@
'\\2-VVV-egg')
])
),
-
+ doctest.DocFileSuite(
+ 'selecting-python.txt',
+ setUp=setUpPython, tearDown=tearDown,
+ checker=renormalizing.RENormalizing([
+ (re.compile('\S+sample-(\w+)%s(\S+)' % os.path.sep),
+ r'/sample-\1/\2'),
+ (re.compile('\S+sample-(\w+)'), r'/sample-\1'),
+ ]),
+ ),
))
if __name__ == '__main__':
Modified: zc.buildout/trunk/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -22,11 +22,16 @@
import os, sys
-def install(spec, dest, links, python=sys.executable):
+def install(spec, dest, links, executable=sys.executable, always_unzip=False):
prefix = sys.exec_prefix + os.path.sep
path = os.pathsep.join([p for p in sys.path if not p.startswith(prefix)])
- os.spawnle(
- os.P_WAIT, python, python,
+ args = (
'-c', 'from setuptools.command.easy_install import main; main()',
- '-mqxd', dest, '-f', ' '.join(links), spec,
- dict(PYTHONPATH=path))
+ '-mqxd', dest)
+ if links:
+ args += ('-f', ' '.join(links))
+ if always_unzip:
+ args += ('-Z', )
+ args += (spec, dict(PYTHONPATH=path))
+
+ os.spawnle(os.P_WAIT, executable, executable, *args)
Modified: zc.buildout/trunk/src/zc/buildout/easy_install.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.txt 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.txt 2006-06-19 19:20:24 UTC (rev 68763)
@@ -20,9 +20,13 @@
>>> ls(sample_eggs)
- demo-0.1-py2.3.egg
+ - demo-0.1-py2.4.egg
- demo-0.2-py2.3.egg
+ - demo-0.2-py2.4.egg
- demo-0.3-py2.3.egg
+ - demo-0.3-py2.4.egg
- demoneeded-1.0-py2.3.egg
+ - demoneeded-1.0-py2.4.egg
let's make directory and install the demo egg to it:
@@ -34,3 +38,28 @@
- demo-0.3-py2.3.egg
- demoneeded-1.0-py2.3.egg
+We can specify an alternate Python executable, and we can specify
+that, when we retrieve (or create) an egg, it should be unzipped.
+
+ >>> import shutil
+ >>> shutil.rmtree(dest)
+ >>> dest = tempfile.mkdtemp()
+ >>> zc.buildout.easy_install.install(
+ ... 'demo', dest, [sample_eggs],
+ ... always_unzip=True, executable= python2_3_executable)
+
+ >>> ls(dest)
+ d demo-0.3-py2.3.egg
+ d demoneeded-1.0-py2.3.egg
+
+ >>> shutil.rmtree(dest)
+ >>> dest = tempfile.mkdtemp()
+ >>> zc.buildout.easy_install.install(
+ ... 'demo', dest, [sample_eggs],
+ ... always_unzip=True, executable= python2_4_executable)
+
+ >>> ls(dest)
+ d demo-0.3-py2.4.egg
+ d demoneeded-1.0-py2.4.egg
+
+
Modified: zc.buildout/trunk/src/zc/buildout/egglinker.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/egglinker.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/egglinker.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -25,28 +25,44 @@
# XXX need to deal with extras
import os
+import re
import sys
import pkg_resources
-def distributions(reqs, eggss):
- env = pkg_resources.Environment(eggss)
+_versions = {sys.executable: '%d.%d' % sys.version_info[:2]}
+def _get_version(executable):
+ try:
+ return _versions[executable]
+ except KeyError:
+ i, o = os.popen4(executable + ' -V')
+ 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
+
+def distributions(reqs, eggss, executable=sys.executable):
+ env = pkg_resources.Environment(eggss, python=_get_version(executable))
ws = pkg_resources.WorkingSet()
reqs = [pkg_resources.Requirement.parse(r) for r in reqs]
return ws.resolve(reqs, env=env)
-def path(reqs, eggss):
- dists = distributions(reqs, eggss)
+def path(reqs, eggss, executable=sys.executable):
+ dists = distributions(reqs, eggss, executable)
return [dist.location for dist in dists]
-def location(spec, eggss):
- env = pkg_resources.Environment(eggss)
+def location(spec, eggss, executable=sys.executable):
+ env = pkg_resources.Environment(eggss, python=_get_version(executable))
req = pkg_resources.Requirement.parse(spec)
dist = env.best_match(req, pkg_resources.WorkingSet())
return dist.location
-def scripts(reqs, dest, eggss, scripts=None):
- dists = distributions(reqs, eggss)
+def scripts(reqs, dest, eggss, scripts=None, executable=sys.executable):
+ dists = distributions(reqs, eggss, executable)
reqs = [pkg_resources.Requirement.parse(r) for r in reqs]
projects = [r.project_name for r in reqs]
path = "',\n '".join([dist.location for dist in dists])
@@ -64,7 +80,7 @@
sname = os.path.join(dest, sname)
generated.append(sname)
- _script(dist, 'console_scripts', name, path, sname)
+ _script(dist, 'console_scripts', name, path, sname, executable)
name = 'py_'+dist.project_name
if scripts is not None:
@@ -75,14 +91,14 @@
if sname is not None:
sname = os.path.join(dest, sname)
generated.append(sname)
- _pyscript(path, sname)
+ _pyscript(path, sname, executable)
return generated
-def _script(dist, group, name, path, dest):
+def _script(dist, group, name, path, dest, executable):
entry_point = dist.get_entry_info(group, name)
open(dest, 'w').write(script_template % dict(
- python = sys.executable,
+ python = executable,
path = path,
project = dist.project_name,
name = name,
@@ -109,9 +125,9 @@
'''
-def _pyscript(path, dest):
+def _pyscript(path, dest, executable):
open(dest, 'w').write(py_script_template % dict(
- python = sys.executable,
+ python = executable,
path = path,
))
try:
Modified: zc.buildout/trunk/src/zc/buildout/egglinker.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/egglinker.txt 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/egglinker.txt 2006-06-19 19:20:24 UTC (rev 68763)
@@ -17,9 +17,13 @@
>>> ls(sample_eggs)
- demo-0.1-py2.3.egg
+ - demo-0.1-py2.4.egg
- demo-0.2-py2.3.egg
+ - demo-0.2-py2.4.egg
- demo-0.3-py2.3.egg
+ - demo-0.3-py2.4.egg
- demoneeded-1.0-py2.3.egg
+ - demoneeded-1.0-py2.4.egg
The demo package depends on the demoneeded package.
@@ -66,8 +70,8 @@
<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'
+ '/tmp/xyzsample-eggs/demo-0.1-py2.3.egg',
+ '/tmp/xyzsample-eggs/demoneeded-1.0-py2.3.egg'
]
<BLANKLINE>
import eggrecipedemo
@@ -90,8 +94,8 @@
<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'
+ '/tmp/xyzsample-eggs/demo-0.1-py2.3.egg',
+ '/tmp/xyzsample-eggs/demoneeded-1.0-py2.3.egg'
]
An additional argumnet can be passed to define which scripts to install
@@ -112,8 +116,6 @@
>>> 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
@@ -124,15 +126,15 @@
>>> 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']
+ ['/tmp/xyzsample-eggs/demo-0.1-py2.3.egg',
+ '/tmp/xyzsample-eggs/demoneeded-1.0-py2.3.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'
+ '/tmp/xyzsample-eggs/demo-0.1-py2.3.egg'
The distributions function can retrieve a list of distributions found
ineg directories that match a sequence of requirements:
@@ -141,3 +143,73 @@
... zc.buildout.egglinker.distributions(['demo==0.1'], [sample_eggs])]
[('demo', '0.1'), ('demoneeded', '1.0')]
+Using a custom Python interpreter
+---------------------------------
+
+You can pass an executable argument to egglinker methods:
+
+ >>> scripts = zc.buildout.egglinker.scripts(
+ ... ['demo==0.1'], bin, [sample_eggs],
+ ... executable=python2_3_executable)
+
+ >>> f = open(os.path.join(bin, 'demo'))
+ >>> f.readline().strip() == '#!' + python2_3_executable
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/tmp/sample-eggs/dist/demo-0.1-py2.3.egg',
+ '/tmp/sample-eggs/dist/demoneeded-1.0-py2.3.egg'
+ ]
+ <BLANKLINE>
+ import eggrecipedemo
+ <BLANKLINE>
+ if __name__ == '__main__':
+ eggrecipedemo.main()
+
+ >>> zc.buildout.egglinker.path(['demo==0.1'], [sample_eggs],
+ ... python2_3_executable)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ ['/tmp/sample-eggs/dist/demo-0.1-py2.3.egg',
+ '/tmp/sample-eggs/dist/demoneeded-1.0-py2.3.egg']
+
+
+ >>> zc.buildout.egglinker.location('demo==0.1', [sample_eggs],
+ ... python2_3_executable)
+ '/tmp/sample-eggs/demo-0.1-py2.3.egg'
+
+ >>> [(d.project_name, d.version) for d in
+ ... zc.buildout.egglinker.distributions(
+ ... ['demo==0.1'], [sample_eggs], python2_3_executable)]
+ [('demo', '0.1'), ('demoneeded', '1.0')]
+
+
+ >>> scripts = zc.buildout.egglinker.scripts(
+ ... ['demo==0.1'], bin, [sample_eggs],
+ ... executable=python2_4_executable)
+
+ >>> f = open(os.path.join(bin, 'demo'))
+ >>> f.readline().strip() == '#!' + python2_4_executable
+ True
+ >>> print f.read(),
+ <BLANKLINE>
+ import sys
+ sys.path[0:0] = [
+ '/tmp/sample-eggs/dist/demo-0.1-py2.4.egg',
+ '/tmp/sample-eggs/dist/demoneeded-1.0-py2.4.egg'
+ ]
+ <BLANKLINE>
+ import eggrecipedemo
+ <BLANKLINE>
+ if __name__ == '__main__':
+ eggrecipedemo.main()
+
+ >>> zc.buildout.egglinker.path(['demo==0.1'], [sample_eggs],
+ ... python2_4_executable)
+ ... # doctest: +NORMALIZE_WHITESPACE
+ ['/tmp/sample-eggs/dist/demo-0.1-py2.4.egg',
+ '/tmp/sample-eggs/dist/demoneeded-1.0-py2.4.egg']
+
+ >>> shutil.rmtree(bin)
+
Modified: zc.buildout/trunk/src/zc/buildout/testing.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/testing.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/testing.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -11,12 +11,12 @@
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
-"""XXX short summary goes here.
+"""Various test-support utility functions
$Id$
"""
-import os, re, shutil, sys, tempfile, unittest
+import ConfigParser, os, re, shutil, sys, tempfile, unittest
from zope.testing import doctest, renormalizing
import pkg_resources
@@ -52,10 +52,11 @@
i.close()
return o.read()
-def buildoutSetUp(test):
- # we both need to make sure that HOME isn't set and be prepared
- # to restore whatever it was after the test.
- test.globs['_oldhome'] = os.environ.pop('HOME', None)
+def buildoutSetUp(test, clear_home=True):
+ if clear_home:
+ # we both need to make sure that HOME isn't set and be prepared
+ # to restore whatever it was after the test.
+ test.globs['_oldhome'] = os.environ.pop('HOME', None)
sample = tempfile.mkdtemp('sample-buildout')
for name in ('bin', 'eggs', 'develop-eggs', 'parts'):
@@ -96,7 +97,7 @@
def buildoutTearDown(test):
shutil.rmtree(test.globs['sample_buildout'])
os.chdir(test.globs['__original_wd__'])
- if test.globs['_oldhome'] is not None:
+ if test.globs.get('_oldhome') is not None:
os.environ['HOME'] = test.globs['_oldhome']
@@ -110,12 +111,12 @@
sys.exit(load_entry_point('zc.buildout', 'console_scripts', 'buildout')())
'''
-def runsetup(d):
+def runsetup(d, executable):
here = os.getcwd()
try:
os.chdir(d)
os.spawnle(
- os.P_WAIT, sys.executable, sys.executable,
+ os.P_WAIT, executable, executable,
'setup.py', '-q', 'bdist_egg',
{'PYTHONPATH': os.path.dirname(pkg_resources.__file__)},
)
@@ -123,20 +124,25 @@
finally:
os.chdir(here)
-def create_sample_eggs(test):
- sample = tempfile.mkdtemp('sample-eggs')
- test.globs['_sample_eggs_container'] = sample
- test.globs['sample_eggs'] = os.path.join(sample, 'dist')
- write(sample, 'README.txt', '')
+def create_sample_eggs(test, executable=sys.executable):
+ if '_sample_eggs_container' in test.globs:
+ sample = test.globs['_sample_eggs_container']
+ else:
+ sample = tempfile.mkdtemp('sample-eggs')
+ test.globs['_sample_eggs_container'] = sample
+ test.globs['sample_eggs'] = os.path.join(sample, 'dist')
+ write(sample, 'README.txt', '')
+
write(sample, 'eggrecipedemobeeded.py', 'y=1\n')
write(
sample, 'setup.py',
"from setuptools import setup\n"
"setup(name='demoneeded', py_modules=['eggrecipedemobeeded'],"
" zip_safe=True, version='1.0')\n"
- )
- runsetup(sample)
+ )
+ runsetup(sample, executable)
os.remove(os.path.join(sample, 'eggrecipedemobeeded.py'))
+
for i in (1, 2, 3):
write(
sample, 'eggrecipedemo.py',
@@ -152,4 +158,17 @@
" entry_points={'console_scripts': ['demo = eggrecipedemo:main']},"
" zip_safe=True, version='0.%s')\n" % i
)
- runsetup(sample)
+ runsetup(sample, executable)
+
+def multi_python(test):
+ defaults = ConfigParser.RawConfigParser()
+ defaults.readfp(open(os.path.join(os.environ['HOME'],
+ '.buildout', 'default.cfg')))
+ p23 = defaults.get('python2.3', 'executable')
+ p24 = defaults.get('python2.4', 'executable')
+ create_sample_eggs(test, executable=p23)
+ create_sample_eggs(test, executable=p24)
+ test.globs['python2_3_executable'] = p23
+ test.globs['python2_4_executable'] = p24
+
+
Modified: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py 2006-06-19 18:02:54 UTC (rev 68762)
+++ zc.buildout/trunk/src/zc/buildout/tests.py 2006-06-19 19:20:24 UTC (rev 68763)
@@ -64,8 +64,8 @@
'''
def linkerSetUp(test):
- zc.buildout.testing.buildoutSetUp(test)
- zc.buildout.testing.create_sample_eggs(test)
+ zc.buildout.testing.buildoutSetUp(test, clear_home=False)
+ zc.buildout.testing.multi_python(test)
def linkerTearDown(test):
shutil.rmtree(test.globs['_sample_eggs_container'])
@@ -75,6 +75,61 @@
shutil.rmtree(test.globs['extensions'])
shutil.rmtree(test.globs['home'])
zc.buildout.testing.buildoutTearDown(test)
+
+
+class PythonNormalizing(renormalizing.RENormalizing):
+
+ def _transform(self, want, got):
+ if '/xyzsample-eggs/' in want:
+ got = got.replace('-py2.4.egg', '-py2.3.egg')
+ firstg = got.split('\n')[0]
+ firstw = want.split('\n')[0]
+ if firstg.startswith('#!') and firstw.startswith('#!'):
+ firstg = ' '.join(firstg.split()[1:])
+ got = firstg + '\n' + '\n'.join(got.split('\n')[1:])
+ firstw = ' '.join(firstw.split()[1:])
+ want = firstw + '\n' + '\n'.join(want.split('\n')[1:])
+
+ for pattern, repl in self.patterns:
+ want = pattern.sub(repl, want)
+ got = pattern.sub(repl, got)
+
+ return want, got
+
+ def check_output(self, want, got, optionflags):
+ if got == want:
+ return True
+
+ want, got = self._transform(want, got)
+ if got == want:
+ return True
+
+ return doctest.OutputChecker.check_output(self, want, got, optionflags)
+
+ def output_difference(self, example, got, optionflags):
+
+ want = example.want
+
+ # If want is empty, use original outputter. This is useful
+ # when setting up tests for the first time. In that case, we
+ # generally use the differencer to display output, which we evaluate
+ # by hand.
+ if not want.strip():
+ return doctest.OutputChecker.output_difference(
+ self, example, got, optionflags)
+
+ # Dang, this isn't as easy to override as we might wish
+ original = want
+ want, got = self._transform(want, got)
+
+ # temporarily hack example with normalized want:
+ example.want = want
+ result = doctest.OutputChecker.output_difference(
+ self, example, got, optionflags)
+ example.want = original
+
+ return result
+
def test_suite():
return unittest.TestSuite((
@@ -86,22 +141,23 @@
(re.compile('__buildout_signature__ = recipes-\S+'),
'__buildout_signature__ = recipes-SSSSSSSSSSS'),
(re.compile('\S+sample-(\w+)%s(\S+)' % os.path.sep),
- r'/sample-\1/\3'),
- (re.compile('\S+sample-(\w+)'),
- r'/sample-\1/\3'),
- (re.compile('executable = \S+python\S*'), 'executable = python'),
+ r'/sample-\1/\2'),
+ (re.compile('\S+sample-(\w+)'), r'/sample-\1'),
+ (re.compile('executable = \S+python\S*'),
+ 'executable = python'),
])
),
+
doctest.DocFileSuite(
'egglinker.txt', 'easy_install.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('\S+%spython(\d.\d)?' % os.path.sep), 'python')
+
+ checker=PythonNormalizing([
+ (re.compile("'%(sep)s\S+sample-eggs%(sep)s(dist%(sep)s)?"
+ % dict(sep=os.path.sep)),
+ '/sample-eggs/'),
+ (re.compile("(- demo(needed)?-\d[.]\d-py)\d[.]\d[.]egg"),
+ '\\1V.V.egg'),
]),
),
doctest.DocTestSuite(
More information about the Checkins
mailing list