[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