[Checkins] SVN: zc.buildout/trunk/ Checking in initial work. Still
need more tests and features.
Jim Fulton
jim at zope.com
Mon Jun 5 07:25:19 EDT 2006
Log message for revision 68494:
Checking in initial work. Still need more tests and features.
Changed:
A zc.buildout/trunk/README.txt
A zc.buildout/trunk/bootstrap.py
A zc.buildout/trunk/buildout.cfg
A zc.buildout/trunk/eggrecipe/
A zc.buildout/trunk/eggrecipe/README.txt
A zc.buildout/trunk/eggrecipe/setup.py
A zc.buildout/trunk/eggrecipe/src/
A zc.buildout/trunk/eggrecipe/src/zc/
A zc.buildout/trunk/eggrecipe/src/zc/__init__.py
A zc.buildout/trunk/eggrecipe/src/zc/recipe/
A zc.buildout/trunk/eggrecipe/src/zc/recipe/__init__.py
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/__init__.py
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py
A zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py
A zc.buildout/trunk/setup.py
A zc.buildout/trunk/src/
A zc.buildout/trunk/src/zc/
A zc.buildout/trunk/src/zc/__init__.py
A zc.buildout/trunk/src/zc/buildout/
A zc.buildout/trunk/src/zc/buildout/__init__.py
A zc.buildout/trunk/src/zc/buildout/build.py
A zc.buildout/trunk/src/zc/buildout/buildout.txt
A zc.buildout/trunk/src/zc/buildout/easy_install.py
A zc.buildout/trunk/src/zc/buildout/egglinker.py
A zc.buildout/trunk/src/zc/buildout/testing.py
A zc.buildout/trunk/src/zc/buildout/tests.py
A zc.buildout/trunk/testrunnerrecipe/
A zc.buildout/trunk/testrunnerrecipe/README.txt
A zc.buildout/trunk/testrunnerrecipe/setup.py
A zc.buildout/trunk/testrunnerrecipe/src/
A zc.buildout/trunk/testrunnerrecipe/src/zc/
A zc.buildout/trunk/testrunnerrecipe/src/zc/__init__.py
A zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/
A zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/__init__.py
A zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/testrunner.py
A zc.buildout/trunk/todo.txt
-=-
Added: zc.buildout/trunk/README.txt
===================================================================
--- zc.buildout/trunk/README.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/README.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,58 @@
+Zope Buildout
+=============
+
+The Zope Buildout project provides support for creating applications,
+especially Pyton applications. It provides tools for assembling
+applications from multiple parts, Python or otherwise. An application
+may actually contain multiple programs, processes, and configuration
+settings.
+
+The word "buildout" refers to a description of a set of parts and the
+software to create ans 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".
+
+I expect that, for many Zope packages, we'll arrange the package
+projects in subversion as buildouts. To work on the package, someone
+will check the project out of Subversion and build it. Building it
+will assemble all of packages and progras needed to work on it. For
+example, a buildout for a project to provide a new security policy
+will include the source of the policy and specifications to build the
+application for working on it, including:
+
+- a test runner
+
+- a web server for running the user interface
+
+- supporting packages
+
+A buildout will typically contain a copy of bootstrap.py. When
+someone checks out the project, they'll run bootstrap.py, which will
+
+- create support directories, like bin, eggs, and work, as needed,
+
+- download and install the zc.buildout and setuptools eggs,
+
+- run bin/build (created by installing zc.buildout) to build the
+ application.
+
+Buildouts are defined using configuration files. These files are
+based on the Python ConfigParser module with some variable-definition
+and substitution extensions.
+
+The detailed documentation for the various parts of bukdout can be
+found in the following files:
+
+bootstrap.txt
+ Describes how to use the bootstrapping script
+
+buildout.txt
+ Describes how to define and run buildouts. It also describes how
+ to write recipes.
+
+recipes.txt
+ Documents the few built-in recipes.
Property changes on: zc.buildout/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/bootstrap.py
===================================================================
--- zc.buildout/trunk/bootstrap.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/bootstrap.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,66 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Bootstrap a buildout
+
+$Id$
+"""
+
+import os, sys, urllib2
+
+for d in 'eggs', 'bin':
+ if not os.path.exists(d):
+ os.mkdir(d)
+
+ez = {}
+exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+ ).read() in ez
+
+ez['use_setuptools'](to_dir='eggs', download_delay=0)
+
+import setuptools.command.easy_install
+import pkg_resources
+import setuptools.package_index
+import distutils.dist
+
+os.spawnle(os.P_WAIT, sys.executable, sys.executable, 'setup.py',
+ '-q', 'develop', '-m', '-x', '-d', 'eggs',
+ {'PYTHONPATH': os.path.dirname(pkg_resources.__file__)},
+ )
+
+## easy = setuptools.command.easy_install.easy_install(
+## distutils.dist.Distribution(),
+## multi_version=True,
+## exclude_scripts=True,
+## sitepy_installed=True,
+## install_dir='eggs',
+## outputs=[],
+## quiet=True,
+## zip_ok=True,
+## args=['zc.buildout'],
+## )
+## easy.finalize_options()
+## easy.easy_install('zc.buildout')
+
+env = pkg_resources.Environment(['eggs'])
+
+ws = pkg_resources.WorkingSet()
+sys.path[0:0] = [
+ d.location
+ for d in ws.resolve([pkg_resources.Requirement.parse('zc.buildout')], env)
+ ]
+
+import zc.buildout.egglinker
+zc.buildout.egglinker.scripts(['zc.buildout'], 'bin', ['eggs'])
+
+sys.exit(os.spawnl(os.P_WAIT, 'bin/buildout', 'bin/buildout'))
Property changes on: zc.buildout/trunk/bootstrap.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/buildout.cfg
===================================================================
--- zc.buildout/trunk/buildout.cfg 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/buildout.cfg 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,8 @@
+[buildout]
+develop = eggrecipe testrunnerrecipe
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+distributions = zc.buildout zc.recipe.egg
+
Property changes on: zc.buildout/trunk/buildout.cfg
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/README.txt
===================================================================
--- zc.buildout/trunk/eggrecipe/README.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/README.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+Buildout recipe for installing Python distutils distributions as eggs
Property changes on: zc.buildout/trunk/eggrecipe/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/setup.py
===================================================================
--- zc.buildout/trunk/eggrecipe/setup.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/setup.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,19 @@
+from setuptools import setup, find_packages
+
+setup(
+ name = "zc.recipe.egg",
+ version = "0.1",
+ packages = find_packages('src'),
+ include_package_data = True,
+ package_dir = {'':'src'},
+ namespace_packages = ['zc', 'zc.recipe'],
+ install_requires = ['zc.buildout'],
+ tests_require = ['zope.testing'],
+ test_suite = 'zc.recipe.eggs.tests.test_suite',
+ author = "Jim Fulton",
+ author_email = "jim at zope.com",
+ description = "Recipe for installing Python package distributions as eggs",
+ license = "ZPL 2.1",
+ keywords = "development build",
+ entry_points = {'zc.buildout': ['default = zc.recipe.egg:Egg']},
+ )
Property changes on: zc.buildout/trunk/eggrecipe/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/__init__.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/__init__.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,94 @@
+Installation of distributions as eggs
+=====================================
+
+The zc.recipe.egg ewcipe can be used to install various types if
+distutils distributions as eggs. It takes a number of options:
+
+distribution
+ The distribution specifies the distribution requirement.
+
+ This is a requirement as defined by setuptools.
+
+find_links
+ A list of URLs, files, or directories to search for distributions.
+
+To illustrate this, we've created a directory with some sample eggs:
+
+ >>> 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
+
+We have a sample buildout. Let's update it's configuration file to
+install the demo package.
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... parts = demo
+ ...
+ ... [demo]
+ ... recipe = zc.recipe.egg
+ ... distribution = demo <0.3
+ ... find_links = %s
+ ... """ % sample_eggs)
+
+In this example, we limited ourself to revisions before 0.3. We also
+specified where to find distributions using the find_links option.
+
+Let's run the buildout:
+
+ >>> import os
+ >>> os.chdir(sample_buildout)
+ >>> runscript = os.path.join(sample_buildout, 'bin', 'buildout')
+ >>> print system(runscript),
+
+Now, if we look at the buildout eggs directory:
+
+ >>> 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
+link for the recipe. This egg link was actually created as part of
+the sample buildout setup. Normally, when using the recipe, you'll get
+a regular egg installation.)
+
+The demo egg also defined a script and we see that the script was
+installed as well:
+
+ >>> ls(sample_buildout, 'bin')
+ - buildout
+ - demo
+ - py_demo
+
+Here, in addition to the buildout script, we see the demo script,
+demo, and we see a script, py_demo, for giving us a Python prompt with
+the path for demo and any eggs it depends on included in sys.path.
+This is useful for testing.
+
+If we run the demo script, it prints out some minimal data:
+
+ >>> print system(os.path.join(sample_buildout, 'bin', 'demo')),
+ 2 1
+
+The value it prints out happens to be some values defined in the
+modules installed.
+
+We can also run the py_demo script. Here we'll just print out
+the bits if the path added to reflect the eggs:
+
+ >>> print system(os.path.join(sample_buildout, 'bin', 'py_demo'),
+ ... """for p in sys.path[:3]:
+ ... print p
+ ... """).replace('>>> ', '').replace('... ', ''),
+ ... # doctest: +ELLIPSIS
+ <BLANKLINE>
+ /usr/local/python/2.3.5/lib/python/setuptools-0.6b2-py2.3.egg
+ /tmp/tmpcy8MvGbuildout-tests/eggs/demo-0.2-py2.3.egg
+ /tmp/tmpcy8MvGbuildout-tests/eggs/demoneeded-1.0-py2.3.egg
+ <BLANKLINE>
+
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/__init__.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+from zc.recipe.egg.egg import Egg
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,50 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Install packages as eggs
+
+$Id$
+"""
+
+import zc.buildout.egglinker
+import zc.buildout.easy_install
+
+class Egg:
+
+ def __init__(self, buildout, name, options):
+ self.buildout = buildout
+ self.name = name
+ self.options = options
+
+ def install(self):
+ distribution = self.options.get('distribution', self.name)
+ links = self.options.get(
+ 'find_links',
+ self.buildout['buildout'].get('find_links'),
+ )
+ if links:
+ links = links.split()
+ else:
+ links = ()
+
+ buildout = self.buildout
+ zc.buildout.easy_install.install(
+ distribution,
+ buildout.eggs,
+ [buildout.buildout_path(link) for link in links],
+ always_copy = True,
+ )
+
+ zc.buildout.egglinker.scripts(
+ [distribution], buildout.bin, [buildout.eggs],
+ )
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/egg.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py
===================================================================
--- zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# 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, tempfile
+import pkg_resources
+import zc.buildout.testing
+
+import unittest
+from zope.testing import doctest, renormalizing
+
+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 setUp(test):
+ zc.buildout.testing.buildoutSetUp(test)
+ open(os.path.join(test.globs['sample_buildout'],
+ 'eggs', 'zc.recipe.egg.egg-link'),
+ 'w').write(dirname(__file__, 4))
+
+ 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 tearDown(test):
+ shutil.rmtree(test.globs['_sample_eggs_container'])
+ zc.buildout.testing.buildoutTearDown(test)
+
+
+def test_suite():
+ return unittest.TestSuite((
+ #doctest.DocTestSuite(),
+ doctest.DocFileSuite(
+ 'README.txt',
+ setUp=setUp, tearDown=tearDown,
+ checker=renormalizing.RENormalizing([
+ (re.compile('\S+[/%(sep)s]'
+ '(\\w+-)[^ \t\n%(sep)s/]+.egg'
+ % dict(sep=os.path.sep)
+ ),
+ '\\1-VVV-egg')
+ ])
+ ),
+
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: zc.buildout/trunk/eggrecipe/src/zc/recipe/egg/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/setup.py
===================================================================
--- zc.buildout/trunk/setup.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/setup.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,19 @@
+from setuptools import setup, find_packages
+
+setup(
+ name = "zc.buildout",
+ version = "0.1",
+ packages = ['zc.buildout'],
+ package_dir = {'':'src'},
+ namespace_packages = ['zc'],
+ include_package_data = True,
+ tests_require = ['zope.testing'],
+ test_suite = 'zc.buildout.tests.test_suite',
+ author = "Jim Fulton",
+ author_email = "jim at zope.com",
+ description = "System for managing development buildouts",
+ license = "ZPL 2.1",
+ keywords = "development build",
+ install_requires = 'setuptools',
+ entry_points = {'console_scripts': ['buildout = zc.buildout.build:main']},
+ )
Property changes on: zc.buildout/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/__init__.py
===================================================================
--- zc.buildout/trunk/src/zc/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,5 @@
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except:
+ # bootstrapping
+ pass
Property changes on: zc.buildout/trunk/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/__init__.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+#
Property changes on: zc.buildout/trunk/src/zc/buildout/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/build.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/build.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/build.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,320 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Buildout main script
+
+$Id$
+"""
+
+import md5
+import os
+import pprint
+import re
+import shutil
+import sys
+import ConfigParser
+
+import zc.buildout.easy_install
+import pkg_resources
+import zc.buildout.easy_install
+import zc.buildout.egglinker
+
+class MissingOption(KeyError):
+ """A required option was missing
+ """
+
+class Options(dict):
+
+ def __init__(self, buildout, section, data):
+ self.buildout = buildout
+ self.section = section
+ super(Options, self).__init__(data)
+
+ def __getitem__(self, option):
+ try:
+ return super(Options, self).__getitem__(option)
+ except KeyError:
+ # XXX need test
+ raise MissingOption("Missing option", self.section, option)
+
+ def copy(self):
+ return Options(self.buildout, self.section, self)
+
+class Buildout(dict):
+
+ def __init__(self):
+ self._buildout_dir = os.path.abspath(os.getcwd())
+ self._config_file = self.buildout_path('buildout.cfg')
+
+ super(Buildout, self).__init__(self._open(
+ directory = self._buildout_dir,
+ eggs_directory = 'eggs',
+ bin_directory = 'bin',
+ parts_directory = 'parts',
+ installed = '.installed.cfg',
+ ))
+
+ options = self['buildout']
+
+ links = options.get('find_links', '')
+ self._links = links and links.split() or ()
+
+ # XXX need tests for alternate directory locations
+
+ for name in ('bin', 'parts', 'eggs'):
+ d = self.buildout_path(options[name+'_directory'])
+ setattr(self, name, d)
+ if not os.path.exists(d):
+ os.mkdir(d)
+
+ _template_split = re.compile('([$]{\w+:\w+})').split
+ def _open(self, **predefined):
+ # Open configuration files
+ parser = ConfigParser.SafeConfigParser()
+ parser.add_section('buildout')
+ for k, v in predefined.iteritems():
+ parser.set('buildout', k, v)
+ parser.read(self._config_file)
+
+ data = dict([
+ (section,
+ Options(self, section,
+ [(k, v.strip()) for (k, v) in parser.items(section)])
+ )
+ for section in parser.sections()
+ ])
+
+ converted = {}
+ for section, options in data.iteritems():
+ for option, value in options.iteritems():
+ if '$' in value:
+ value = self._dosubs(section, option, value,
+ data, converted, [])
+ options[option] = value
+ converted[(section, option)] = value
+
+ # XXX need various error tests
+
+ return data
+
+ def _dosubs(self, section, option, value, data, converted, seen):
+ key = section, option
+ r = converted.get(key)
+ if r is not None:
+ return r
+ if key in seen:
+ raise ValueError('Circular references', seen, key)
+ seen.append(key)
+ value = '$$'.join([self._dosubs_esc(s, data, converted, seen)
+ for s in value.split('$$')
+ ])
+ seen.pop()
+ return value
+
+ def _dosubs_esc(self, value, data, converted, seen):
+ value = self._template_split(value)
+ subs = []
+ for s in value[1::2]:
+ s = tuple(s[2:-1].split(':'))
+ v = converted.get(s)
+ if v is None:
+ options = data.get(s[0])
+ if options is None:
+ raise KeyError("Referenced section does not exist", s[0])
+ v = options.get(s[1])
+ if v is None:
+ raise KeyError("Referenced option does not exist", *s)
+ if '$' in v:
+ v = _dosubs(s[0], s[1], v, data, converted, seen)
+ options[s[1]] = v
+ converted[s] = v
+ subs.append(v)
+ subs.append('')
+
+ return ''.join([''.join(v) for v in zip(value[::2], subs)])
+
+ # XXX test
+ def buildout_path(self, *names):
+ return os.path.join(self._buildout_dir, *names)
+
+ # XXX test
+ def distributions_path(self, specs):
+ return zc.buildout.egglinker.path(specs, [self.eggs])
+
+ def install(self):
+ self._develop()
+ new_part_options = self._gather_part_info()
+ installed_part_options = self._read_installed_part_options()
+ old_parts = installed_part_options['buildout']['parts'].split()
+ old_parts.reverse()
+
+ new_old_parts = []
+ for part in old_parts:
+ installed_options = installed_part_options[part].copy()
+ installed = installed_options.pop('__buildout_installed__')
+ if installed_options != new_part_options.get(part):
+ self._uninstall(installed)
+ del installed_part_options[part]
+ else:
+ new_old_parts.append(part)
+ new_old_parts.reverse()
+
+ new_parts = []
+ try:
+ for part in new_part_options['buildout']['parts'].split():
+ installed = self._install(part)
+ new_part_options[part]['__buildout_installed__'] = installed
+ new_parts.append(part)
+ installed_part_options[part] = new_part_options[part]
+ new_old_parts = [p for p in new_old_parts if p != part]
+ finally:
+ new_parts.extend(new_old_parts)
+ installed_part_options['buildout']['parts'] = ' '.join(new_parts)
+ self._save_installed_options(installed_part_options)
+
+ def _develop(self):
+ """Install sources by running setup.py develop on them
+ """
+ develop = self['buildout'].get('develop')
+ if develop:
+ here = os.getcwd()
+ try:
+ for setup in develop.split():
+ setup = self.buildout_path(setup)
+ if os.path.isdir(setup):
+ setup = os.path.join(setup, 'setup.py')
+
+ os.chdir(os.path.dirname(setup))
+ os.spawnle(
+ os.P_WAIT, sys.executable, sys.executable,
+ setup, '-q', 'develop', '-m', '-x',
+ '-f', ' '.join(self._links),
+ '-d', self.eggs,
+ {'PYTHONPATH':
+ os.path.dirname(pkg_resources.__file__)},
+ )
+ finally:
+ os.chdir(os.path.dirname(here))
+
+ def _gather_part_info(self):
+ """Get current part info, including part options and recipe info
+ """
+ parts = self['buildout']['parts']
+ part_info = {'buildout': {'parts': parts}}
+ recipes_requirements = []
+ pkg_resources.working_set.add_entry(self.eggs)
+
+ parts = parts and parts.split() or []
+ for part in parts:
+ options = self.get(part)
+ if options is None:
+ options = self[part] = {}
+ options = options.copy()
+ recipe, entry = self._recipe(part, options)
+ zc.buildout.easy_install.install(
+ recipe, self.eggs, self._links)
+ recipes_requirements.append(recipe)
+ part_info[part] = options
+
+ # Load up the recipe distros
+ pkg_resources.require(recipes_requirements)
+
+ base = self.eggs + os.path.sep
+ for part in parts:
+ options = part_info[part]
+ recipe, entry = self._recipe(part, options)
+ req = pkg_resources.Requirement.parse(recipe)
+ sig = _dists_sig(pkg_resources.working_set.resolve([req]), base)
+ options['__buildout_signature__'] = ' '.join(sig)
+
+ return part_info
+
+ def _recipe(self, part, options):
+ recipe = options.get('recipe', part)
+ if ':' in recipe:
+ recipe, entry = recipe.split(':')
+ else:
+ entry = 'default'
+
+ return recipe, entry
+
+ def _read_installed_part_options(self):
+ old = self._installed_path()
+ if os.path.isfile(old):
+ parser = ConfigParser.SafeConfigParser()
+ parser.read(old)
+ return dict([(section, dict(parser.items(section)))
+ for section in parser.sections()])
+ else:
+ return {'buildout': {'parts': ''}}
+
+ def _installed_path(self):
+ return self.buildout_path(self['buildout']['installed'])
+
+ def _uninstall(self, installed):
+ for f in installed.split():
+ f = self.buildout_path(f)
+ if os.path.isdir(f):
+ shutil.rmtree(f)
+ elif os.path.isfile(f):
+ os.remove(f)
+
+ def _install(self, part):
+ options = self[part]
+ recipe, entry = self._recipe(part, 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):
+ parser = ConfigParser.SafeConfigParser()
+ for section in installed_options:
+ parser.add_section(section)
+ for option, value in installed_options[section].iteritems():
+ parser.set(section, option, value)
+ parser.write(open(self._installed_path(), 'w'))
+
+def _dir_hash(dir):
+ hash = md5.new()
+ for (dirpath, dirnames, filenames) in os.walk(dir):
+ filenames[:] = [f for f in filenames
+ if not (f.endswith('pyc') or f.endswith('pyo'))
+ ]
+ 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, base):
+ result = []
+ for dist in dists:
+ location = dist.location
+ if dist.precedence == pkg_resources.DEVELOP_DIST:
+ result.append(dist.project_name + '-' + _dir_hash(location))
+ else:
+ if location.startswith(base):
+ location = location[len(base):]
+ result.append(location)
+ return result
+
+def main():
+ Buildout().install()
Property changes on: zc.buildout/trunk/src/zc/buildout/build.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/buildout.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,363 @@
+Defining Buildouts
+==================
+
+This document describes how to define buildouts using buildout
+configuation files and recipes. It doesn't describe how to bootstrap
+a buildout. To find out how to do that, see bootstrap.txt. For the
+examples we show here, we've created a sample buildout that already
+contains the mimimal software needed for a buildout.
+
+Buildouts are defined using configuration files. These are in the
+format defined by the Python ConfigParser module, with an extension
+that we'll describe later. When a buildout is run, it looks for
+the file buildout.cfg in the directory where the buidout is run. It
+will optionally look for buildout-instance.cfg. Typically, buidout.cfg
+contains information common to all instances of a buildout and is
+checked in, and buildout-instance.cfg has instance-specific information.
+
+We have a sample buildout that has already been created for us. It
+has the absolute minimum information. We have bin, eggs and parts
+directories, and a configuration file:
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ d bin
+ - buildout.cfg
+ d eggs
+ d parts
+
+The bin directory contains scripts. A minimal buildout has a build
+script and a py_zc.buildout script:
+
+ >>> ls(sample_buildout, 'bin')
+ - buildout
+
+The build script is what we run to build things out. The
+py_zc.buildout script gives us a Python prompt with the Python path
+set to that needed by the zc.buildout package.
+
+The eggs directory is initially empty. This is typically the case
+when the zc.buildout and setuptools are installed externally to the
+buildout:
+
+ >>> ls(sample_buildout, 'eggs')
+
+They can also be installed locally in a buildout, in which case they's
+show up as eggs in the eggs directory.
+
+The parts directory is initially empty:
+
+ >>> ls(sample_buildout, 'parts')
+
+The parts directory provides an area where recipies 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
+subdirectory of the parts directory with the same name as the part.
+
+The file .installed.cfg contains information about previously installed
+parts. Because this is a new buildout, this file isn't very
+interesting:
+
+ >>> cat(sample_buildout, '.installed.cfg')
+ [buildout]
+ parts =
+
+
+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
+a confguration file.
+
+A part is created by a recipe. Recipes are always installed as Python
+eggs. They can be downloaded from an package server, such as the
+Python package index, or they can be developed as part of a project.
+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 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 os
+ ...
+ ... class Mkdir:
+ ...
+ ... def __init__(self, buildout, name, options):
+ ... self.buildout = buildout
+ ... self.name = name
+ ... self.options = options
+ ...
+ ... def install(self):
+ ... path = self.buildout.buildout_path(self.options['path'])
+ ... if not os.path.isdir(path):
+ ... print 'Creating directory', os.path.basename(path)
+ ... os.mkdir(path)
+ ... return path
+ ... """)
+
+The recipe defines a constructor that takes a buildout object, a part
+name, and an options dictionary. It saves them in instance attributes.
+
+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
+buildout option from our options dictionary. If the path is relative,
+we'll interpret it relative to the buildout directory. The buildout
+buildout_path method gives us a path relative to the buildout. It
+uses os.path.join, so if we pass it an absolute path, we'll get the
+absolute path back. (If no arguments are passed to base_path, then the
+buildout directory is returned.)
+
+We made the method chatty so that we can observe what it's doing.
+
+We return the path that we installed. If the part is unistalled or
+reinstalled, then the path returned will be removed by the buildout
+machinery. A recipe install method is expected to return None, a
+string, or an iterable of strings containing paths to be removed if a
+part is uninstalled.
+
+We need to provide packaging information so that our recipe can be
+installed as an egg. We need to define a setup script for this:
+
+ >>> write(sample_buildout, 'recipes', 'setup.py',
+ ... """
+ ... from setuptools import setup
+ ...
+ ... setup(
+ ... name = "recipes",
+ ... entry_points = {'zc.buildout': ['mkdir = mkdir:Mkdir']},
+ ... )
+ ... """)
+
+Here we've defined a package containing just our module. We've also
+defined 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 default. Recipe classes must be exposed
+as entry points in the zc.buildout group. we give entry points names
+within the group. The name "default" is somewhat special because it
+allows a recipe to be referenced using a package name without naming
+an entry point.
+
+We also need a README.txt for our recipes to avoid a warning:
+
+ >>> 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 buidlout
+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.
+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
+
+Generally, when we name a part, we also create a section of the same
+name that contains part data. In this section, we'll usually 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)
+ >>> runscript = os.path.join(sample_buildout, 'bin', 'buildout')
+ >>> print system(runscript),
+ Creating directory mystuff
+
+We see that the recipe created the directory, as expected:
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ d bin
+ - buildout.cfg
+ d eggs
+ d mystuff
+ d parts
+ d recipes
+
+In addition, .installed.cfg has been updated to reflect the part we
+installed:
+
+ >>> cat(sample_buildout, '.installed.cfg')
+ [buildout]
+ parts = data_dir
+ <BLANKLINE>
+ [data_dir]
+ path = mystuff
+ recipe = recipes:mkdir
+ __buildout_signature__ = recipes-O3ypTgKOkHMqMwKvMfvHnA==
+ __buildout_installed__ = mystuff
+ <BLANKLINE>
+
+Note that the directory we installed is included in .installed.cfg.
+
+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(runscript),
+ Creating directory mydata
+
+ >>> ls(sample_buildout)
+ - .installed.cfg
+ d bin
+ - buildout.cfg
+ d eggs
+ d mydata
+ d parts
+ d recipes
+
+Variable substitutions
+----------------------
+
+Buildout configuration files support two kinds of substitutions,
+standard ConfigParser substitutions, and string-template
+substitutions. 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
+ ... """)
+
+In this example, we've used a simple base class that provides a
+boilerplate constructor. 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.
+
+Let's update our configuration to provide variable substitution
+examples:
+
+ >>> write(sample_buildout, 'buildout.cfg',
+ ... """
+ ... [buildout]
+ ... develop = recipes
+ ... parts = data_dir debug
+ ...
+ ... [debug]
+ ... recipe = recipes:debug
+ ... file1 = ${data_dir:path}/file
+ ... file2 = %(file1)s.out
+ ... file3 = %(base)s/file3
+ ...
+ ... [data_dir]
+ ... recipe = recipes:mkdir
+ ... path = mydata
+ ...
+ ... [DEFAULT]
+ ... base = var
+ ... """)
+
+In this example, we've used ConfigParser substitutions for file2 and
+file3. This type of substitution uses Python string format syntax.
+Valid names are option in the same section and options defined in the
+DEFAULT section. We used a string-template substitution for file1.
+This type of substituion uses the string.Template syntax. Names
+substited 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(runscript),
+ Creating directory mydata
+ base var
+ file1 mydata/file
+ file2 mydata/file.out
+ file3 var/file3
+ recipe recipes:debug
+
+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(runscript),
+ base var
+ file1 mydata/file
+ file2 mydata/file.out
+ file3 var/file3
+ recipe recipes:debug
+
+We can see that mydata was not recreated.
Property changes on: zc.buildout/trunk/src/zc/buildout/buildout.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/easy_install.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/easy_install.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/easy_install.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# 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.
+
+$Id$
+"""
+
+# XXX needs doctest
+
+import setuptools.command.easy_install
+import pkg_resources
+import setuptools.package_index
+import distutils.dist
+import distutils.log
+
+def install(spec, dest, links=(), **kw):
+ index = setuptools.package_index.PackageIndex()
+ index.add_find_links(links)
+ easy = setuptools.command.easy_install.easy_install(
+ distutils.dist.Distribution(),
+ multi_version=True,
+ exclude_scripts=True,
+ sitepy_installed=True,
+ install_dir=dest,
+ outputs=[],
+ verbose = 0,
+ args = [spec],
+ find_links = links,
+ **kw
+ )
+ easy.finalize_options()
+
+ old_warn = distutils.log.warn
+ distutils.log.warn = lambda *a, **k: None
+
+ easy.easy_install(spec, deps=True)
+
+ distutils.log.warn = old_warn
+
Property changes on: zc.buildout/trunk/src/zc/buildout/easy_install.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/egglinker.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/egglinker.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/egglinker.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,111 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""Egg linker -- Link eggs together to build applications
+
+Egg linker is a script that generates startup scripts for eggs that
+include an egg's working script in the generated script.
+
+The egg linker module also exports helper functions of varous kinds to
+assist in custom script generation.
+
+$Id$
+"""
+
+# XXX needs doctest
+
+import os
+import sys
+
+import pkg_resources
+
+def distributions(reqs, eggss):
+ env = pkg_resources.Environment(eggss)
+ ws = pkg_resources.WorkingSet()
+ reqs = [pkg_resources.Requirement.parse(r) for r in reqs]
+ reqs.append(pkg_resources.Requirement.parse('setuptools'))
+ return ws.resolve(reqs, env=env)
+
+def path(reqs, eggss):
+ dists = distributions(reqs, eggss)
+ return [dist.location for dist in dists]
+
+def location(spec, eggss):
+ env = pkg_resources.Environment(eggss)
+ req = pkg_resources.Requirement.parse(spec)
+ dist = env.best_match(req, pkg_resources.WorkingSet())
+ return dist.location
+
+def scripts(reqs, dest, eggss):
+ dists = distributions(reqs, eggss)
+ 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])
+
+ for dist in dists:
+ if dist.project_name in projects:
+ for name in pkg_resources.get_entry_map(dist, 'console_scripts'):
+ _script(dist, name, path, os.path.join(dest, name))
+ _pyscript(path, os.path.join(dest, 'py_'+dist.project_name))
+
+def _script(dist, name, path, dest):
+ open(dest, 'w').write(script_template % dict(
+ python = sys.executable,
+ path = path,
+ project = dist.project_name,
+ name = name,
+ ))
+ try:
+ os.chmod(dest, 0755)
+ except (AttributeError, os.error):
+ pass
+
+script_template = '''\
+#!%(python)s
+
+import sys
+sys.path[0:0] = [
+ '%(path)s'
+ ]
+
+from pkg_resources import load_entry_point
+
+sys.exit(
+ load_entry_point('%(project)s', 'console_scripts', '%(name)s')()
+)
+
+'''
+
+
+def _pyscript(path, dest):
+ open(dest, 'w').write(py_script_template % dict(
+ python = sys.executable,
+ path = path,
+ ))
+ try:
+ os.chmod(dest,0755)
+ except (AttributeError, os.error):
+ pass
+
+py_script_template = '''\
+#!%(python)s -i
+
+import sys
+sys.path[0:0] = [
+ '%(path)s'
+ ]
+'''
+
+def main():
+ import pdb; pdb.set_trace()
+
Property changes on: zc.buildout/trunk/src/zc/buildout/egglinker.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/testing.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/testing.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/testing.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,109 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""XXX short summary goes here.
+
+$Id$
+"""
+
+import os, re, shutil, sys, tempfile, unittest
+from zope.testing import doctest, renormalizing
+
+
+def cat(dir, *names):
+ path = os.path.join(dir, *names)
+ 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 ',
+ else:
+ print '- ',
+ print name
+
+def mkdir(dir, *subs):
+ if subs:
+ dir = os.path.join(dir, *subs)
+ os.mkdir(dir)
+
+def write(dir, *args):
+ open(os.path.join(dir, *(args[:-1])), 'w').write(args[-1])
+
+def system(command, input=''):
+ i, o = os.popen4(command)
+ if input:
+ i.write(input)
+ i.close()
+ return o.read()
+
+def dirname(path, n=1):
+ if n <= 0:
+ return path
+ return dirname(os.path.dirname(path), n-1)
+
+def buildoutSetUp(test):
+ sample = tempfile.mkdtemp('buildout-tests')
+ for name in ('bin', 'eggs', 'parts'):
+ os.mkdir(os.path.join(sample, name))
+
+ # make sure we can import zc.buildout and setuptools
+ import zc.buildout, setuptools
+
+ # Generate buildout script
+ dest = os.path.join(sample, 'bin', 'buildout')
+ open(dest, 'w').write(
+ script_template % dict(python=sys.executable, path=sys.path)
+ )
+ try:
+ os.chmod(dest, 0755)
+ except (AttributeError, os.error):
+ pass
+
+
+ open(os.path.join(sample, 'buildout.cfg'), 'w').write(
+ "[buildout]\nparts =\n"
+ )
+ open(os.path.join(sample, '.installed.cfg'), 'w').write(
+ "[buildout]\nparts =\n"
+ )
+
+ test.globs.update(dict(
+ __here = os.getcwd(),
+ sample_buildout = sample,
+ ls = ls,
+ cat = cat,
+ mkdir = mkdir,
+ write = write,
+ system = system,
+ __original_wd__ = os.getcwd(),
+ ))
+
+def buildoutTearDown(test):
+ shutil.rmtree(test.globs['sample_buildout'])
+ os.chdir(test.globs['__original_wd__'])
+
+
+script_template = '''\
+#!%(python)s
+
+import sys
+sys.path[0:0] = %(path)r
+
+from pkg_resources import load_entry_point
+sys.exit(load_entry_point('zc.buildout', 'console_scripts', 'buildout')())
+'''
Property changes on: zc.buildout/trunk/src/zc/buildout/testing.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/src/zc/buildout/tests.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""XXX short summary goes here.
+
+$Id$
+"""
+
+import unittest
+from zope.testing import doctest
+
+from zc.buildout.testing import buildoutSetUp, buildoutTearDown
+
+def test_suite():
+ return unittest.TestSuite((
+ #doctest.DocTestSuite(),
+ doctest.DocFileSuite(
+ 'buildout.txt',
+ setUp=buildoutSetUp, tearDown=buildoutTearDown,
+ ),
+ ))
+
+if __name__ == '__main__':
+ unittest.main(defaultTest='test_suite')
+
Property changes on: zc.buildout/trunk/src/zc/buildout/tests.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/testrunnerrecipe/README.txt
===================================================================
--- zc.buildout/trunk/testrunnerrecipe/README.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/testrunnerrecipe/README.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+Recipe for generating a custom test runner.
Property changes on: zc.buildout/trunk/testrunnerrecipe/README.txt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/testrunnerrecipe/setup.py
===================================================================
--- zc.buildout/trunk/testrunnerrecipe/setup.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/testrunnerrecipe/setup.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,20 @@
+from setuptools import setup, find_packages
+
+setup(
+ name = "zc.recipe.testrunner",
+ version = "0.1",
+ packages = find_packages('src'),
+ include_package_data = True,
+ package_dir = {'':'src'},
+ namespace_packages = ['zc', 'zc.recipe'],
+ install_requires = ['zc.buildout', 'zope.testing'],
+ dependency_links = ['http://download.zope.org/distribution/'],
+ test_suite = 'zc.recipe.testrunner.tests.test_suite',
+ author = "Jim Fulton",
+ author_email = "jim at zope.com",
+ description = "ZC Buildout recipe for creating test runners",
+ license = "ZPL 2.1",
+ keywords = "development build",
+ entry_points = {'zc.buildout':
+ ['default = zc.recipe.testrunner:TestRunner']},
+ )
Property changes on: zc.buildout/trunk/testrunnerrecipe/setup.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/testrunnerrecipe/src/zc/__init__.py
===================================================================
--- zc.buildout/trunk/testrunnerrecipe/src/zc/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/testrunnerrecipe/src/zc/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zc.buildout/trunk/testrunnerrecipe/src/zc/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/__init__.py
===================================================================
--- zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/__init__.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/__init__.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1 @@
+__import__('pkg_resources').declare_namespace(__name__)
Property changes on: zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/__init__.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/testrunner.py
===================================================================
--- zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/testrunner.py 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/testrunner.py 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,63 @@
+##############################################################################
+#
+# 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.
+#
+##############################################################################
+"""A few built-in recipes
+
+$Id$
+"""
+
+# XXX need tests
+
+import os, sys
+
+class TestRunner:
+
+ def __init__(self, buildout, name, options):
+ self.buildout = buildout
+ self.name = name
+ self.options = options
+
+ def install(self):
+ distributions = self.options['distributions'].split()
+ path = self.buildout.distributions_path(distributions+['zope.testing'])
+ locations = [self.buildout.distribution_location(distribution)
+ for distribution in distributions]
+ script = self.options.get('script', self.name)
+ script = self.buildout.buildout_path('bin', script)
+ open(script, 'w').write(tests_template % dict(
+ PYTHON=sys.executable,
+ PATH="',\n '".join(path),
+ TESTPATH="',\n '--test-path', '".join(locations),
+ ))
+ try:
+ os.chmod(script, 0755)
+ except (AttributeError, os.error):
+ pass
+
+
+tests_template = """#!%(PYTHON)s
+
+import sys
+sys.path[0:0] = [
+ '%(PATH)s',
+ ]
+
+from zope.testing import testrunner
+
+defaults = [
+ '--test-path', '%(TESTPATH)s',
+ ]
+
+sys.exit(testrunner.run(defaults))
+"""
+
Property changes on: zc.buildout/trunk/testrunnerrecipe/src/zc/recipe/testrunner.py
___________________________________________________________________
Name: svn:keywords
+ Id
Name: svn:eol-style
+ native
Added: zc.buildout/trunk/todo.txt
===================================================================
--- zc.buildout/trunk/todo.txt 2006-06-05 09:57:28 UTC (rev 68493)
+++ zc.buildout/trunk/todo.txt 2006-06-05 11:25:19 UTC (rev 68494)
@@ -0,0 +1,40 @@
+- Missing tests. See XXXs
+
+- Buildout command-line options:
+
+ --config -C specify a config files
+
+ --option -O specify options
+
+- Python discovery support
+
+ (Perhaps this is best handled by DEFAULT section.
+
+- Common recipes
+
+ - configure-make-make-install
+
+ - download, checkout
+
+ - Should ot be possible to provide multiple recipies?
+ Or should recipies be combined through inheritence (or
+ composition)?
+
+ - Python
+
+- Need to better understand the way upgrading works in setuptools.
+
+- Multiple setupfiles,
+
+ o extends, optionally-extends, extended-by, optionally-exteded-by
+
+ o instance.ini
+
+ o ~/buildout/default.ini
+
+- Offline mode
+
+- Local download cache
+
+- Logging
+
Property changes on: zc.buildout/trunk/todo.txt
___________________________________________________________________
Name: svn:eol-style
+ native
More information about the Checkins
mailing list