[Checkins] SVN: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/ Added support for extra paths in generated scripts.

Jim Fulton jim at zope.com
Tue Sep 5 18:55:42 EDT 2006


Log message for revision 69984:
  Added support for extra paths in generated scripts.
  
  Added an option to supply entry points directly. This is useful for
  packages that don't declare their entry points.
  
  No longer generate "py-" scripts implicitly.  Added a new option,
  interpreter, to request such scripts and specifu their names.
  
  Increased default buildout logging.
  

Changed:
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/README.txt
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/api.txt
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/custom.txt
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt
  U   zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py

-=-
Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/README.txt
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/README.txt	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/README.txt	2006-09-05 22:55:41 UTC (rev 69984)
@@ -29,6 +29,13 @@
    Python executable is found in the executable option of the named
    section. 
 
+entry-points
+   A list of entry-point identifiers of the form name=module#attrs,
+   name is a script name, module is a module name, and a attrs is a
+   (possibly dotted) name of an object wihin the module.  This option
+   is useful when working with distributions that don't declare entry
+   points, such as distributions not written to work with setuptools.
+
 scripts
    Control which scripts are generated.  The value should be a list of
    zero or more tokens.  Each token is either a name, or a name
@@ -37,6 +44,10 @@
    disabled.  If the option isn't given at all, then all scripts
    defined by the named eggs will be generated.
 
+interpreter
+   The name of a script to generate that allows access to a Python
+   interpreter that has the path set based on the eggs installed.
+
 extra-paths
    Extra paths to include in a generates script.
 
@@ -69,7 +80,7 @@
     ... index = %(server)s/index
     ... """ % dict(server=link_server))
 
-In this example, we limited ourself to revisions before 0.3. We also
+In this example, we limited ourselves to revisions before 0.3. We also
 specified where to find distributions using the find-links option.
 
 Let's run the buildout:
@@ -78,6 +89,11 @@
     >>> os.chdir(sample_buildout)
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
     >>> print system(buildout),
+    buildout: Installing demo
+    zc.buildout.easy_install: Getting new distribution for demo<0.3
+    zc.buildout.easy_install: Got demo 0.2
+    zc.buildout.easy_install: Getting new distribution for demoneeded
+    zc.buildout.easy_install: Got demoneeded 1.1
     
 Now, if we look at the buildout eggs directory:
 
@@ -93,20 +109,48 @@
 the sample buildout setup. Normally, when using the recipe, you'll get
 a regular egg installation.)
 
+Script generation
+-----------------
+
 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
-    -  py-zc.buildout
 
 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
+demo.
+
+Let's add an interpreter option:
+
+    >>> write(sample_buildout, 'buildout.cfg',
+    ... """
+    ... [buildout]
+    ... parts = demo
+    ...
+    ... [demo]
+    ... recipe = zc.recipe.egg
+    ... eggs = demo<0.3
+    ... find-links = %(server)s
+    ... index = %(server)s/index
+    ... interpreter = py-demo
+    ... """ % dict(server=link_server))
+
+    >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
+
+Now we also get a py-demo script 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 debugging and testing.
 
+    >>> ls(sample_buildout, 'bin')
+    -  buildout
+    -  demo
+    -  py-demo
+
+
 If we run the demo script, it prints out some minimal data:
 
     >>> print system(os.path.join(sample_buildout, 'bin', 'demo')),
@@ -144,6 +188,10 @@
     ... """ % dict(server=link_server))
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
+    zc.buildout.easy_install: Getting new distribution for demo
+    zc.buildout.easy_install: Got demo 0.3
 
 Then we'll get a new demo egg:
 
@@ -162,11 +210,13 @@
     >>> print system(os.path.join(sample_buildout, 'bin', 'demo')),
     3 1
 
+Controlling script generation
+-----------------------------
+
 You can control which scripts get generated using the scripts option.
 For example, to suppress scripts, use the scripts option without any
 arguments:
 
-
     >>> write(sample_buildout, 'buildout.cfg',
     ... """
     ... [buildout]
@@ -181,10 +231,11 @@
 
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
 
     >>> ls(sample_buildout, 'bin')
     -  buildout
-    -  py-zc.buildout
 
 You can also control the name used for scripts:
 
@@ -201,12 +252,16 @@
     ... """ % dict(server=link_server))
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
 
     >>> ls(sample_buildout, 'bin')
     -  buildout
     -  foo
-    -  py-zc.buildout
 
+Specifying extra script paths
+-----------------------------
+
 If we need to include extra paths in a script, we can use the
 extra-paths option:
 
@@ -226,6 +281,8 @@
     ... """ % dict(server=link_server))
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
 
 Let's look at the script that was generated:
 
@@ -237,7 +294,7 @@
       '/tmp/xyzsample-install/demo-0.3-py2.3.egg',
       '/tmp/xyzsample-install/demoneeded-1.1-py2.3.egg',
       '/foo/bar',
-      '/spam/eggs'
+      '/spam/eggs',
       ]
     <BLANKLINE>
     import eggrecipedemo
@@ -245,8 +302,54 @@
     if __name__ == '__main__':
         eggrecipedemo.main()
 
+Specifying entry points
+-----------------------
 
+Scripts can be generated for entry points declared explcitly.  We can
+declate entry points using the entry-points option:
 
+
+    >>> write(sample_buildout, 'buildout.cfg',
+    ... """
+    ... [buildout]
+    ... parts = demo
+    ...
+    ... [demo]
+    ... recipe = zc.recipe.egg
+    ... find-links = %(server)s
+    ... index = %(server)s/index
+    ... extra-paths = 
+    ...    /foo/bar
+    ...    /spam/eggs
+    ... entry-points = alt=eggrecipedemo:alt other=foo.bar:a.b.c
+    ... """ % dict(server=link_server))
+
+    >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
+
+    >>> ls(sample_buildout, 'bin')
+    -  alt
+    -  buildout
+    -  demo
+    -  other
+
+    >>> cat(sample_buildout, 'bin', 'other')
+    #!/usr/local/bin/python2.3
+    <BLANKLINE>
+    import sys
+    sys.path[0:0] = [
+      '/private/tmp/tmp88gKbfsample-buildout/eggs/demo-0.3-py2.3.egg',
+      '/private/tmp/tmp88gKbfsample-buildout/eggs/demoneeded-1.1-py2.3.egg',
+      '/foo/bar',
+      '/spam/eggs',
+      ]
+    <BLANKLINE>
+    import foo.bar
+    <BLANKLINE>
+    if __name__ == '__main__':
+        foo.bar.a.b.c()
+
 Offline mode
 ------------
 
@@ -267,3 +370,5 @@
     ... """ % dict(server=link_server))
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/api.txt
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/api.txt	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/api.txt	2006-09-05 22:55:41 UTC (rev 69984)
@@ -6,10 +6,10 @@
 recipe provides an API that other recipes can use.
 
 A recipe can reuse the egg recipe, supporting the eggs, find-links,
-index, and python options.  This is done by creating an egg recipe
-instance in a recipes's contructor.  In the recipe's install script,
-the egg-recipe instance's working_set method is used to collect the
-requested eggs and working set.
+index, extra-paths, and python options.  This is done by creating an
+egg recipe instance in a recipes's contructor.  In the recipe's
+install script, the egg-recipe instance's working_set method is used
+to collect the requested eggs and working set.
 
 To illustrate, we create a sample recipe that is a very thin layer
 around the egg recipe:
@@ -37,6 +37,7 @@
     ...         print 'Working set:'
     ...         for d in ws:
     ...             print d
+    ...         print 'extra paths:', self.egg.extra_paths
     ... """)
 
 Here we instantiated the egg recipe in the constructor, saving it in
@@ -77,7 +78,7 @@
     >>> import os
     >>> os.chdir(sample_buildout)
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
-    >>> print system(buildout),
+    >>> print system(buildout + ' -q'),
     Part: sample-part
     Egg requirements:
     demo<0.3
@@ -85,6 +86,7 @@
     demo 0.2
     other 1.0
     demoneeded 1.1
+    extra paths: []
 
 We can see that the options were augmented with additionl data
 computed by the egg recipe by looking at .installed.cfg:
@@ -108,3 +110,35 @@
     find-links = http://localhost:27071/
     index = http://localhost:27071/index
     recipe = sample
+
+If we use the extra-paths option:
+
+
+    >>> write(sample_buildout, 'buildout.cfg',
+    ... """
+    ... [buildout]
+    ... develop = sample
+    ... parts = sample-part
+    ...
+    ... [sample-part]
+    ... recipe = sample
+    ... eggs = demo<0.3
+    ... find-links = %(server)s
+    ... index = %(server)sindex
+    ... extras = other
+    ... extra-paths = /foo/bar
+    ...               /spam/eggs
+    ... """ % dict(server=link_server))
+
+Then we'll see that reflected in the extra_paths attribute in the egg
+recipe instance:
+
+    >>> print system(buildout + ' -q'),
+    Part: sample-part
+    Egg requirements:
+    demo<0.3
+    Working set:
+    demo 0.2
+    other 1.0
+    demoneeded 1.1
+    extra paths: ['/foo/bar', '/spam/eggs']

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/custom.txt
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/custom.txt	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/custom.txt	2006-09-05 22:55:41 UTC (rev 69984)
@@ -95,6 +95,7 @@
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
 
     >>> print system(buildout),
+    buildout: Installing extdemo
     zip_safe flag not set; analyzing archive contents...
 
 We got the zip_safe warning because the source distribution we used

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/egg.py	2006-09-05 22:55:41 UTC (rev 69984)
@@ -16,7 +16,7 @@
 $Id$
 """
 
-import os, re, zipfile
+import logging, os, re, zipfile
 import zc.buildout.easy_install
 
 class Egg:
@@ -87,8 +87,11 @@
 
         return orig_distributions, ws
 
+    parse_entry_point = re.compile(
+        '([^=]+)=(\w+(?:[.]\w+)*):(\w+(?:[.]\w+)*)$'
+        ).match
     def install(self):
-        distributions, ws = self.working_set()
+        reqs, ws = self.working_set()
         options = self.options
 
         scripts = options.get('scripts')
@@ -99,9 +102,20 @@
                     ('=' in s) and s.split('=', 1) or (s, s)
                     for s in scripts
                     ])
+
+            for s in options.get('entry-points', '').split():
+                parsed = self.parse_entry_point(s)
+                if not parsed:
+                    logging.getLogger(self.name).error(
+                        "Cannot parse the entry point %s.", s)
+                    raise zc.buildout.UserError("Invalid entry point")
+                reqs.append(parsed.groups())
+
             return zc.buildout.easy_install.scripts(
-                distributions, ws, options['executable'],
+                reqs, ws, options['executable'],
                 options['_b'],
                 scripts=scripts,
-                extra_paths=self.extra_paths)
+                extra_paths=self.extra_paths,
+                interpreter=options.get('interpreter'),
+                )
 

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/selecting-python.txt	2006-09-05 22:55:41 UTC (rev 69984)
@@ -46,6 +46,7 @@
     ... find-links = %(server)s
     ... index = %(server)s/index
     ... python = python2.3
+    ... interpreter = py-demo
     ... """ % dict(server=link_server, python23=python2_3_executable))
 
 Now, if we run the buildout:
@@ -54,6 +55,11 @@
     >>> os.chdir(sample_buildout)
     >>> buildout = os.path.join(sample_buildout, 'bin', 'buildout')
     >>> print system(buildout),
+    buildout: Installing demo
+    zc.buildout.easy_install: Getting new distribution for demo<0.3
+    zc.buildout.easy_install: Got demo 0.2
+    zc.buildout.easy_install: Getting new distribution for demoneeded
+    zc.buildout.easy_install: Got demoneeded 1.1
 
 we'll get the Python 2.3 eggs for demo and demoneeded:
 
@@ -78,7 +84,7 @@
     import sys
     sys.path[0:0] = [
       '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.3.egg',
-      '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.3.egg'
+      '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.3.egg',
       ]
     <BLANKLINE>
     import eggrecipedemo
@@ -97,7 +103,7 @@
     <BLANKLINE>
     sys.path[0:0] = [
       '/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.3.egg',
-      '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.3.egg'
+      '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.3.egg',
       ]
     <BLANKLINE>
     _interactive = True
@@ -135,6 +141,7 @@
     ... find-links = %(server)s
     ... index = %(server)s/index
     ... python = python2.4
+    ... interpreter = py-demo
     ...
     ... [python2.4]
     ... executable = %(python24)s
@@ -142,6 +149,12 @@
     ... """ % dict(server=link_server, python24=python2_4_executable))
 
     >>> print system(buildout),
+    buildout: Uninstalling demo
+    buildout: Installing demo
+    zc.buildout.easy_install: Getting new distribution for demo<0.3
+    zc.buildout.easy_install: Got demo 0.2
+    zc.buildout.easy_install: Getting new distribution for demoneeded
+    zc.buildout.easy_install: Got demoneeded 1.1
 
     >>> ls(sample_buildout, 'eggs')
     -  demo-0.2-py2.3.egg
@@ -162,7 +175,7 @@
     import sys
     sys.path[0:0] = [
       '/private/tmp/tmpOEtRO8sample-buildout/eggs/demo-0.2-py2.4.egg',
-      '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.4.egg'
+      '/private/tmp/tmpOEtRO8sample-buildout/eggs/demoneeded-1.1-py2.4.egg',
       ]
     <BLANKLINE>
     import eggrecipedemo
@@ -183,7 +196,7 @@
     <BLANKLINE>
     sys.path[0:0] = [
       '/tmp/tmp5zS2Afsample-buildout/eggs/demo-0.2-py2.4.egg',
-      '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.4.egg'
+      '/tmp/tmp5zS2Afsample-buildout/eggs/demoneeded-1.1-py2.4.egg',
       ]
     <BLANKLINE>
     _interactive = True

Modified: zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py
===================================================================
--- zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py	2006-09-05 21:41:15 UTC (rev 69983)
+++ zc.buildout/trunk/zc.recipe.egg_/src/zc/recipe/egg/tests.py	2006-09-05 22:55:41 UTC (rev 69984)
@@ -122,7 +122,7 @@
             setUp=setUpCustom, tearDown=zc.buildout.testing.buildoutTearDown,
             checker=renormalizing.RENormalizing([
                (re.compile("(d  ((ext)?demo(needed)?|other)"
-                           "-\d[.]\d-py)\d[.]\d(-[^. \t\n]+)?[.]egg"),
+                           "-\d[.]\d-py)\d[.]\d(-\S+)?[.]egg"),
                 '\\1V.V.egg'),
                (re.compile('extdemo.c\n.+\\extdemo.exp\n'), ''),
                ]),



More information about the Checkins mailing list