[Checkins] SVN: zc.buildout/trunk/ The buildout init command now accepts distribution requirements and
Jim Fulton
jim at zope.com
Wed Sep 28 14:34:20 EST 2011
Log message for revision 122989:
The buildout init command now accepts distribution requirements and
paths to set up a custom interpreter part that has the distributions
or parts in the path. For example::
python bootstrap.py init BeautifulSoup
Changed:
U zc.buildout/trunk/CHANGES.txt
U zc.buildout/trunk/src/zc/buildout/buildout.py
U zc.buildout/trunk/src/zc/buildout/buildout.txt
U zc.buildout/trunk/src/zc/buildout/tests.py
-=-
Modified: zc.buildout/trunk/CHANGES.txt
===================================================================
--- zc.buildout/trunk/CHANGES.txt 2011-09-28 19:34:14 UTC (rev 122988)
+++ zc.buildout/trunk/CHANGES.txt 2011-09-28 19:34:20 UTC (rev 122989)
@@ -1,9 +1,15 @@
Change History
**************
-1.5.3 (unreleased)
+1.6.0 (unreleased)
==================
+- The buildout init command now accepts distribution requirements and
+ paths to set up a custom interpreter part that has the distributions
+ or parts in the path. For example::
+
+ python bootstrap.py init BeautifulSoup
+
- Introduce a cache for the expensive `buildout._dir_hash` function.
- Remove duplicate path from script's sys.path setup.
Modified: zc.buildout/trunk/src/zc/buildout/buildout.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.py 2011-09-28 19:34:14 UTC (rev 122988)
+++ zc.buildout/trunk/src/zc/buildout/buildout.py 2011-09-28 19:34:20 UTC (rev 122989)
@@ -144,7 +144,8 @@
class Buildout(UserDict.DictMixin):
def __init__(self, config_file, cloptions,
- user_defaults=True, windows_restart=False, command=None):
+ user_defaults=True, windows_restart=False,
+ command=None, args=()):
__doing__ = 'Initializing.'
@@ -159,8 +160,7 @@
base = os.path.dirname(config_file)
if not os.path.exists(config_file):
if command == 'init':
- print 'Creating %r.' % config_file
- open(config_file, 'w').write('[buildout]\nparts = \n')
+ self._init_config(config_file, args)
elif command == 'setup':
# Sigh. This model of a buildout instance
# with methods is breaking down. :(
@@ -169,6 +169,9 @@
else:
raise zc.buildout.UserError(
"Couldn't open %s" % config_file)
+ elif command == 'init':
+ raise zc.buildout.UserError(
+ "%r already exists." % config_file)
if config_file:
data['buildout']['directory'] = (os.path.dirname(config_file),
@@ -191,7 +194,8 @@
'.buildout', 'default.cfg')
if os.path.exists(user_config):
_update(data, _open(os.path.dirname(user_config), user_config,
- [], data['buildout'].copy(), override, set()))
+ [], data['buildout'].copy(), override,
+ set()))
# load configuration files
if config_file:
@@ -415,8 +419,39 @@
exec_sitecustomize=self.exec_sitecustomize,
)
- init = bootstrap
+ def _init_config(self, config_file, args):
+ print 'Creating %r.' % config_file
+ f = open(config_file, 'w')
+ sep = re.compile(r'[\\/]')
+ if args:
+ eggs = '\n '.join(a for a in args if not sep.search(a))
+ paths = '\n '.join(
+ sep.sub(os.path.sep, a) for a in args if sep.search(a))
+ f.write('[buildout]\n'
+ 'parts = py\n'
+ '\n'
+ '[py]\n'
+ 'recipe = zc.recipe.egg\n'
+ 'interpreter = py\n'
+ 'eggs =\n'
+ )
+ if eggs:
+ f.write(' %s\n' % eggs)
+ if paths:
+ f.write('extra-paths =\n %s\n' % paths)
+ for p in [a for a in args if sep.search(a)]:
+ if not os.path.exists(p):
+ os.mkdir(p)
+ else:
+ f.write('[buildout]\nparts =\n')
+ f.close()
+
+ def init(self, args):
+ self.bootstrap(())
+ if args:
+ self.install(())
+
def install(self, install_args):
__doing__ = 'Installing.'
@@ -1795,11 +1830,12 @@
_error('invalid command:', command)
else:
command = 'install'
-
+
try:
try:
buildout = Buildout(config_file, options,
- user_defaults, windows_restart, command)
+ user_defaults, windows_restart,
+ command, args)
getattr(buildout, command)(args)
except Exception, v:
_doing()
Modified: zc.buildout/trunk/src/zc/buildout/buildout.txt
===================================================================
--- zc.buildout/trunk/src/zc/buildout/buildout.txt 2011-09-28 19:34:14 UTC (rev 122988)
+++ zc.buildout/trunk/src/zc/buildout/buildout.txt 2011-09-28 19:34:20 UTC (rev 122989)
@@ -2420,8 +2420,16 @@
Creating directory '/sample-bootstrapped/develop-eggs'.
Generated script '/sample-bootstrapped/bin/buildout'.
-Note that a basic setup.cfg was created for us.
+Note that a basic setup.cfg was created for us. This is because we
+provided an 'init' argument. By default, the generated
+``setup.cfg`` is as minimal as it could be:
+ >>> cat(sample_bootstrapped, 'setup.cfg')
+ [buildout]
+ parts =
+
+We also get other buildout artifacts:
+
>>> ls(sample_bootstrapped)
d bin
d develop-eggs
@@ -2522,7 +2530,94 @@
Creating directory '/sample-bootstrapped2/develop-eggs'.
Generated script '/sample-bootstrapped2/bin/buildout'.
+Similarly, if there is a configuration file and we use the init
+command, we'll get an error that the configuration file already
+exists:
+ >>> print system(buildout
+ ... +' -c'+os.path.join(sample_bootstrapped, 'setup.cfg')
+ ... +' init'),
+ While:
+ Initializing.
+ Error: '/sample-bootstrapped/setup.cfg' already exists.
+
+Initial eggs
+------------
+
+When using the ``init`` command, you can specify distribution requirements
+or paths to use:
+
+ >>> cd(sample_bootstrapped)
+ >>> remove('setup.cfg')
+ >>> print system(buildout + ' -csetup.cfg init demo other ./src'),
+ Creating '/sample-bootstrapped/setup.cfg'.
+ Generated script '/sample-bootstrapped/bin/buildout'.
+ Getting distribution for 'zc.recipe.egg'.
+ Got zc.recipe.egg 1.3.3dev.
+ Installing py.
+ Getting distribution for 'demo'.
+ Got demo 0.4c1.
+ Getting distribution for 'other'.
+ Got other 1.0.
+ Getting distribution for 'demoneeded'.
+ Got demoneeded 1.2c1.
+ Generated script '/sample-bootstrapped/bin/demo'.
+ Generated interpreter '/sample-bootstrapped/bin/py'.
+
+This causes a ``py`` part to be included that sets up a custom python
+interpreter with the given requirements or paths:
+
+ >>> cat('setup.cfg')
+ [buildout]
+ parts = py
+ <BLANKLINE>
+ [py]
+ recipe = zc.recipe.egg
+ interpreter = py
+ eggs =
+ demo
+ other
+ extra-paths =
+ ./src
+
+Passing requirements or paths causes the the builout to be run as part
+of initialization. In the example above, we got a number of
+distributions installed and 2 scripts generated. The first, ``demo``,
+was defined by the ``demo`` project. The second, ``py`` was defined by
+the generated configuration. It's a "custom interpreter" that behaves
+like a standard Python interpeter, except that includes the specified
+eggs and extra paths in it's Python path.
+
+We specified a source directory that didn't exist. Buildout created it
+for us:
+
+ >>> ls('.')
+ - .installed.cfg
+ d bin
+ d develop-eggs
+ d eggs
+ d parts
+ - setup.cfg
+ d src
+
+ >>> uncd()
+
+.. Make sure it works if the dir is already there:
+
+ >>> cd(sample_bootstrapped)
+ >>> _ = system(buildout + ' -csetup.cfg buildout:parts=')
+ >>> remove('setup.cfg')
+ >>> print system(buildout + ' -csetup.cfg init demo other ./src'),
+ Creating '/sample-bootstrapped/setup.cfg'.
+ Installing py.
+ Generated script '/sample-bootstrapped/bin/demo'.
+ Generated interpreter '/sample-bootstrapped/bin/py'.
+
+.. cleanup
+
+ >>> _ = system(buildout + ' -csetup.cfg buildout:parts=')
+ >>> uncd()
+
Newest and Offline Modes
------------------------
Modified: zc.buildout/trunk/src/zc/buildout/tests.py
===================================================================
--- zc.buildout/trunk/src/zc/buildout/tests.py 2011-09-28 19:34:14 UTC (rev 122988)
+++ zc.buildout/trunk/src/zc/buildout/tests.py 2011-09-28 19:34:20 UTC (rev 122989)
@@ -3837,6 +3837,29 @@
zc.buildout.testing.install_develop('zc.recipe.egg', test)
zc.buildout.testing.install_develop('z3c.recipe.scripts', test)
+def buildout_txt_setup(test):
+ zc.buildout.testing.buildoutSetUp(test)
+ mkdir = test.globs['mkdir']
+ eggs = os.environ['buildout-testing-index-url'][7:]
+ test.globs['sample_eggs'] = eggs
+ create_sample_eggs(test)
+
+ for name in os.listdir(eggs):
+ if '-' in name:
+ pname = name.split('-')[0]
+ if not os.path.exists(os.path.join(eggs, pname)):
+ mkdir(eggs, pname)
+ shutil.move(os.path.join(eggs, name),
+ os.path.join(eggs, pname, name))
+
+ dist = pkg_resources.working_set.find(
+ pkg_resources.Requirement.parse('zc.recipe.egg'))
+ mkdir(eggs, 'zc.recipe.egg')
+ zc.buildout.testing.sdist(
+ os.path.dirname(dist.location),
+ os.path.join(eggs, 'zc.recipe.egg'),
+ )
+
egg_parse = re.compile('([0-9a-zA-Z_.]+)-([0-9a-zA-Z_.]+)-py(\d[.]\d).egg$'
).match
def makeNewRelease(project, ws, dest, version='99.99'):
@@ -3943,7 +3966,42 @@
def test_suite():
test_suite = [
doctest.DocFileSuite(
- 'buildout.txt', 'runsetup.txt', 'repeatable.txt', 'setup.txt',
+ 'buildout.txt',
+ setUp=buildout_txt_setup,
+ tearDown=zc.buildout.testing.buildoutTearDown,
+ checker=renormalizing.RENormalizing([
+ zc.buildout.testing.normalize_path,
+ zc.buildout.testing.normalize_endings,
+ zc.buildout.testing.normalize_script,
+ zc.buildout.testing.normalize_egg_py,
+ zc.buildout.tests.hide_distribute_additions,
+ hide_zip_safe_message,
+ (re.compile('__buildout_signature__ = recipes-\S+'),
+ '__buildout_signature__ = recipes-SSSSSSSSSSS'),
+ (re.compile('executable = [\S ]+python\S*', re.I),
+ 'executable = python'),
+ (re.compile('[-d] (setuptools|distribute)-\S+[.]egg'),
+ 'setuptools.egg'),
+ (re.compile('zc.buildout(-\S+)?[.]egg(-link)?'),
+ 'zc.buildout.egg'),
+ (re.compile('creating \S*setup.cfg'), 'creating setup.cfg'),
+ (re.compile('hello\%ssetup' % os.path.sep), 'hello/setup'),
+ (re.compile('Picked: (\S+) = \S+'),
+ 'Picked: \\1 = V.V'),
+ (re.compile(r'We have a develop egg: zc.buildout (\S+)'),
+ 'We have a develop egg: zc.buildout X.X.'),
+ (re.compile(r'\\[\\]?'), '/'),
+ (re.compile('WindowsError'), 'OSError'),
+ (re.compile(r'\[Error \d+\] Cannot create a file '
+ r'when that file already exists: '),
+ '[Errno 17] File exists: '
+ ),
+ (re.compile('distribute'), 'setuptools'),
+ (re.compile('Got zc.recipe.egg \S+'), 'Got zc.recipe.egg'),
+ ])
+ ),
+ doctest.DocFileSuite(
+ 'runsetup.txt', 'repeatable.txt', 'setup.txt',
setUp=zc.buildout.testing.buildoutSetUp,
tearDown=zc.buildout.testing.buildoutTearDown,
checker=renormalizing.RENormalizing([
More information about the checkins
mailing list