[Checkins] SVN: z3c.recipe.filetemplate/branches/gary-support-system-python/ Support the new zc.buildout 1.4.0+ include-site-packages option, and more.
Gary Poster
gary.poster at canonical.com
Thu Jul 9 15:20:56 EDT 2009
Log message for revision 101775:
Support the new zc.buildout 1.4.0+ include-site-packages option, and more.
--------
Features
--------
- Support the new zc.buildout 1.4.0+ include-site-packages option.
- Use the new zc.buildout 1.4.0+ path sorting algorithm, which puts
site-package dependency paths after the other dependency paths (but before
extra paths, as before). This can reduce or eliminate problems with
packages in site-packages causing other dependencies to be masked with the
versions in site-packages.
- Support escaping "$" with "$$" in templates. This is particularly useful
for *NIX shell scripts.
- Support specifying local options in templates without braces (e.g.,
"Hello $world" is now equivalent to "Hello ${world}".
-----
Fixes
-----
- Clarify that the recipe does not support the relative-paths options.
- Make tests less susceptible to timing errors.
Changed:
_U z3c.recipe.filetemplate/branches/gary-support-system-python/
U z3c.recipe.filetemplate/branches/gary-support-system-python/CHANGES.txt
U z3c.recipe.filetemplate/branches/gary-support-system-python/buildout.cfg
U z3c.recipe.filetemplate/branches/gary-support-system-python/setup.py
U z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/README.txt
U z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/__init__.py
U z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/tests.py
-=-
Property changes on: z3c.recipe.filetemplate/branches/gary-support-system-python
___________________________________________________________________
Modified: svn:externals
- bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
+ bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap
zc.buildout svn+ssh://svn.zope.org/repos/main/zc.buildout/branches/gary-support-system-python
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/CHANGES.txt
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/CHANGES.txt 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/CHANGES.txt 2009-07-09 19:20:56 UTC (rev 101775)
@@ -9,9 +9,29 @@
Features
--------
-- None yet.
+- Support the new zc.buildout 1.4.0+ include-site-packages option.
+- Use the new zc.buildout 1.4.0+ path sorting algorithm, which puts
+ site-package dependency paths after the other dependency paths (but before
+ extra paths, as before). This can reduce or eliminate problems with
+ packages in site-packages causing other dependencies to be masked with the
+ versions in site-packages.
+- Support escaping "$" with "$$" in templates. This is particularly useful
+ for *NIX shell scripts.
+
+- Support specifying local options in templates without braces (e.g.,
+ "Hello $world" is now equivalent to "Hello ${world}".
+
+-----
+Fixes
+-----
+
+- Clarify that the recipe does not support the relative-paths options.
+
+- Make tests less susceptible to timing errors.
+
+
2.0.3 (2009-07-02)
==================
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/buildout.cfg
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/buildout.cfg 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/buildout.cfg 2009-07-09 19:20:56 UTC (rev 101775)
@@ -1,7 +1,17 @@
[buildout]
develop = .
+ zc.buildout
+ zc.buildout/zc.recipe.egg_
parts = test
+ interpreter
+include-site-packages = false
[test]
recipe = zc.recipe.testrunner
eggs = z3c.recipe.filetemplate
+
+[interpreter]
+recipe = zc.recipe.egg
+interpreter = py
+eggs = z3c.recipe.filetemplate
+
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/setup.py
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/setup.py 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/setup.py 2009-07-09 19:20:56 UTC (rev 101775)
@@ -42,8 +42,8 @@
packages=find_packages(),
namespace_packages=['z3c', 'z3c.recipe'],
install_requires=['setuptools',
- 'zc.buildout',
- 'zc.recipe.egg',
+ 'zc.buildout>=1.4.0dev',
+ 'zc.recipe.egg>=1.3.0dev',
],
zip_safe=True,
entry_points="""
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/README.txt
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/README.txt 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/README.txt 2009-07-09 19:20:56 UTC (rev 101775)
@@ -40,7 +40,7 @@
... world = Philipp
... """)
-After executing buildout, we can see that ``$world`` has indeed been
+After executing buildout, we can see that ``${world}`` has indeed been
replaced by ``Philipp``:
>>> print system(buildout)
@@ -49,6 +49,37 @@
>>> cat(sample_buildout, 'helloworld.txt')
Hello Philipp!
+If the option name does not have a space or a period in it, you do not need the
+braces in the template. Notice this example uses "$world" not "${world}" for
+the same result as before.
+
+ >>> write_and_wait(sample_buildout, 'helloworld.txt.in',
+ ... """
+ ... Hi $world!
+ ... """)
+
+ >>> print system(buildout)
+ Uninstalling message.
+ Installing message.
+
+ >>> cat(sample_buildout, 'helloworld.txt')
+ Hi Philipp!
+
+You can escape the dollar sign by repeating it, as with the Python string
+template class.
+
+ >>> write_and_wait(sample_buildout, 'helloworld.txt.in',
+ ... """
+ ... Hello $$$world! The double $${dollar-sign} escapes!
+ ... """)
+
+ >>> print system(buildout)
+ Uninstalling message.
+ Installing message.
+
+ >>> cat(sample_buildout, 'helloworld.txt')
+ Hello $Philipp! The double ${dollar-sign} escapes!
+
Note that the output file uses the same permission bits as found on the input
file.
@@ -327,14 +358,21 @@
>>> cat(sample_buildout, 'helloworld.txt') # doctest:+ELLIPSIS
Hello! Here are the paths for the demo<0.3 eggs.
OS paths:
- .../eggs/demo-0.2...egg:.../eggs/demoneeded-1.2c1...egg
+ .../eggs/demo-0.2...egg:.../eggs/demoneeded-1.2c1...egg:...
---
String paths:
- '.../eggs/demo-0.2...egg', '.../eggs/demoneeded-1.2c1...egg'
+ '.../eggs/demo-0.2...egg', '.../eggs/demoneeded-1.2c1...egg', '...'
---
Space paths:
- .../eggs/demo-0.2...egg .../eggs/demoneeded-1.2c1...egg
+ .../eggs/demo-0.2...egg .../eggs/demoneeded-1.2c1...egg ...
+Notice that included multiple paths. In fact, it includes the site packages
+and the standard library, so these are appropriate for entirely replacing
+sys.path.
+
+You can eliminate the site packages from the paths by specifying
+"include-site-packages = false" in the buildout or the specific section.
+
You can specify extra-paths as well, which will go at the end of the egg paths.
>>> write(sample_buildout, 'buildout.cfg',
@@ -359,13 +397,13 @@
>>> cat(sample_buildout, 'helloworld.txt') # doctest:+ELLIPSIS
Hello! Here are the paths for the demo<0.3 eggs.
OS paths:
- ...demo...:...demoneeded...:.../sample-buildout/foo
+ ...demo...:...demoneeded...:.../sample-buildout/foo:...
---
String paths:
- '...demo...', '...demoneeded...', '.../sample-buildout/foo'
+ '...demo...', '...demoneeded...', '.../sample-buildout/foo', '...'
---
Space paths:
- ...demo... ...demoneeded... .../sample-buildout/foo
+ ...demo... ...demoneeded... .../sample-buildout/foo ...
Defining options in Python
==========================
@@ -420,8 +458,8 @@
>>> cat(sample_buildout, 'helloworld.txt') # doctest:+ELLIPSIS
hello world!
- duplicate-os-paths: ...demo-0.2...egg:...demoneeded-1.2c1...egg
- foo-paths: ...demo-0.2...eggFOO...demoneeded-1.2c1...egg
+ duplicate-os-paths: ...demo-0.2...egg:...demoneeded-1.2c1...egg:...
+ foo-paths: ...demo-0.2...eggFOO...demoneeded-1.2c1...eggFOO...
silly-range: [0, 1, 2, 3, 4]
first-interpreted-option: duplicate-os-paths=(os.pathsep).join(paths)
message-reversed-is-egassem: egassem
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/__init__.py
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/__init__.py 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/__init__.py 2009-07-09 19:20:56 UTC (rev 101775)
@@ -22,6 +22,7 @@
import traceback
import zc.recipe.egg
import zc.buildout
+import zc.buildout.buildout
import zc.buildout.easy_install
ABS_PATH_ERROR = ('%s is an absolute path. Paths must be '
@@ -44,15 +45,21 @@
self.options.setdefault(key, value)
# set up paths for eggs, if given
if 'eggs' in self.options:
+ relative_paths = self.options.get(
+ 'relative-paths',
+ buildout['buildout'].get('relative-paths', 'false')
+ )
+ if relative_paths != 'false':
+ self._user_error(
+ 'This recipe does not support relative-paths.')
+ # Why? Because the relative path tricks rely on Python
+ # at runtime, and we're offering path values for arbitrary
+ # files (for instance, including bash files).
self.eggs = zc.recipe.egg.Scripts(buildout, name, options)
orig_distributions, ws = self.eggs.working_set()
- # we want ws, eggs.extra_paths, eggs._relative_paths
- all_paths = [
- zc.buildout.easy_install.realpath(dist.location)
- for dist in ws]
- all_paths.extend(
- zc.buildout.easy_install.realpath(path)
- for path in self.eggs.extra_paths)
+ all_paths = zc.buildout.easy_install.get_path(
+ ws, self.options['executable'], self.eggs.extra_paths,
+ self.eggs.include_site_packages)
else:
all_paths = []
paths = [path for path in all_paths if not path.endswith('.zip')]
@@ -195,17 +202,17 @@
'Destinations already exist: %s. Please make sure that '
'you really want to generate these automatically. Then '
'move them away.', ', '.join(already_exists))
+ seen = [] # we throw this away right now, but could move this up
+ # to __init__ if valuable.
for rel_path, last_mod, st_mode in self.actions:
source = os.path.join(self.source_dir, rel_path)
dest = os.path.join(self.destination_dir, rel_path[:-3])
mode=stat.S_IMODE(st_mode)
template=open(source).read()
- template=re.sub(r"\$\{([^:]+?)\}", r"${%s:\1}" % self.name,
- template)
- self._create_paths(os.path.dirname(dest))
# we process the file first so that it won't be created if there
# is a problem.
- processed = self.options._sub(template, [])
+ processed = Template(template).substitute(self, seen)
+ self._create_paths(os.path.dirname(dest))
result=open(dest, "wt")
result.write(processed)
result.close()
@@ -221,3 +228,70 @@
def update(self):
pass
+
+
+class Template:
+ # hacked from string.Template
+ pattern = re.compile(r"""
+ \$(?:
+ (?P<escaped>\$) | # Escape sequence of two delimiters.
+ (?P<named>[-a-z0-9_]+) | # Delimiter and a local option without
+ # space or period.
+ {(?P<braced_single>[-a-z0-9 ._]+)} |
+ # Delimiter and a braced local option
+ {(?P<braced_double>[-a-z0-9 ._]+:[-a-z0-9 ._]+)} |
+ # Delimiter and a braced fully
+ # qualified option (that is, with
+ # explicit section).
+ (?P<invalid>) # Other ill-formed delimiter exprs.
+ )
+ """, re.IGNORECASE | re.VERBOSE)
+
+ def __init__(self, template):
+ self.template = template
+
+ # Search for $$, $identifier, ${identifier}, and any bare $'s
+
+ def _invalid(self, mo):
+ i = mo.start('invalid')
+ lines = self.template[:i].splitlines(True)
+ if not lines:
+ colno = 1
+ lineno = 1
+ else:
+ colno = i - len(''.join(lines[:-1]))
+ lineno = len(lines)
+ raise ValueError('Invalid placeholder %r in string: line %d, col %d' %
+ (mo.group('invalid'), lineno, colno))
+
+ def _get(self, options, section, option, seen):
+ value = options.get(option, None, seen)
+ if value is None:
+ raise zc.buildout.buildout.MissingOption(
+ "Referenced option does not exist:", section, option)
+ return value
+
+ def substitute(self, recipe, seen):
+ # Helper function for .sub()
+ def convert(mo):
+ # Check the most common path first.
+ local = mo.group('named') or mo.group('braced_single')
+ if local is not None:
+ val = self._get(recipe.options, recipe.name, local, seen)
+ # We use this idiom instead of str() because the latter will
+ # fail if val is a Unicode containing non-ASCII characters.
+ return '%s' % (val,)
+ double = mo.group('braced_double')
+ if double is not None:
+ section, option = double.split(':')
+ val = self._get(
+ recipe.buildout[section], section, option, seen)
+ return '%s' % (val,)
+ if mo.group('escaped') is not None:
+ return '$'
+ if mo.group('invalid') is not None:
+ self._invalid(mo)
+ raise ValueError('Unrecognized named group in pattern',
+ self.pattern) # programmer error, AFAICT
+ return self.pattern.sub(convert, self.template)
+
Modified: z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/tests.py
===================================================================
--- z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/tests.py 2009-07-09 19:18:14 UTC (rev 101774)
+++ z3c.recipe.filetemplate/branches/gary-support-system-python/z3c/recipe/filetemplate/tests.py 2009-07-09 19:20:56 UTC (rev 101775)
@@ -12,12 +12,24 @@
#
##############################################################################
+import os
import zc.buildout.testing
import zc.buildout.tests
from zope.testing import doctest
+def write_and_wait(dir, *args):
+ path = os.path.join(dir, *(args[:-1]))
+ original = os.stat(path).st_mtime
+ while os.stat(path).st_mtime == original:
+ f = open(path, 'w')
+ f.write(args[-1])
+ f.flush()
+ os.fsync(f.fileno())
+ f.close()
+
def setUp(test):
zc.buildout.tests.easy_install_SetUp(test)
+ test.globs['write_and_wait'] = write_and_wait
zc.buildout.testing.install_develop('z3c.recipe.filetemplate', test)
def test_suite():
More information about the Checkins
mailing list