[Checkins] SVN: zope.release/trunk/ - Added support for a new
`extends` option that allows using other controlled
Stephan Richter
srichter at cosmos.phy.tufts.edu
Sat Nov 10 13:15:27 EST 2007
Log message for revision 81726:
- Added support for a new `extends` option that allows using other controlled
package configurations as a base.
Note: I shamelessly copied the code from buildout.
Changed:
U zope.release/trunk/CHANGES.txt
U zope.release/trunk/setup.py
U zope.release/trunk/src/zope/release/README.txt
U zope.release/trunk/src/zope/release/kgs.py
-=-
Modified: zope.release/trunk/CHANGES.txt
===================================================================
--- zope.release/trunk/CHANGES.txt 2007-11-10 17:26:27 UTC (rev 81725)
+++ zope.release/trunk/CHANGES.txt 2007-11-10 18:15:27 UTC (rev 81726)
@@ -8,11 +8,15 @@
3.4.0 (2007-11-??)
------------------
+- Added support for a new `extends` option that allows using other controlled
+ package configurations as a base.
+
- Refactored configuration file parsing into a new module that provides
object-oriented output.
- Added tests for the existing code.
+- Update package data.
3.4.0b2 (2007-11-05)
--------------------
Modified: zope.release/trunk/setup.py
===================================================================
--- zope.release/trunk/setup.py 2007-11-10 17:26:27 UTC (rev 81725)
+++ zope.release/trunk/setup.py 2007-11-10 18:15:27 UTC (rev 81726)
@@ -49,6 +49,7 @@
test=['zope.testing']),
install_requires=[
'setuptools',
+ 'zc.buildout',
],
entry_points = dict(console_scripts=[
'generate-buildout = zope.release.buildout:main',
Modified: zope.release/trunk/src/zope/release/README.txt
===================================================================
--- zope.release/trunk/src/zope/release/README.txt 2007-11-10 17:26:27 UTC (rev 81725)
+++ zope.release/trunk/src/zope/release/README.txt 2007-11-10 18:15:27 UTC (rev 81726)
@@ -45,6 +45,30 @@
to be tested, but some packages require very specific test setups that cannot
be easily reproduced _[1], so we turn off those tests.
+You can also stack controlled package configurations on top of each
+other. Base configurations can be specified using the `extends` option:
+
+ >>> import tempfile
+ >>> cfgFile2 = tempfile.mktemp('-cp.cfg')
+ >>> open(cfgFile2, 'w').write('''\
+ ... [DEFAULT]
+ ... tested = true
+ ...
+ ... [KGS]
+ ... name = grok-dev
+ ... extends = %s
+ ...
+ ... [packageA]
+ ... versions = 1.0.2
+ ...
+ ... [packageD]
+ ... versions = 2.2.3
+ ... 2.2.4
+ ... ''' %cfgFile)
+
+As you can see, you can completely override another package's version
+specification as well.
+
Generating the configuration file and managing it is actually the hard
part. Let's now see what we can do with it.
@@ -69,7 +93,21 @@
packageB = 1.2.3
packageC = 4.3.1
+Let's now ensure that the versions also work for the extended configuration:
+ >>> versionsFile2 = tempfile.mktemp('-versions.cfg')
+
+ >>> from zope.release import version
+ >>> version.main((cfgFile2, versionsFile2))
+
+ >>> print open(versionsFile2, 'r').read()
+ [versions]
+ packageA = 1.0.2
+ packageB = 1.2.3
+ packageC = 4.3.1
+ packageD = 2.2.4
+
+
Generate Buildout
-----------------
@@ -97,7 +135,32 @@
packageC = 4.3.1
<BLANKLINE>
+Let's make sure that the buildout generation also honors the extensions:
+ >>> buildoutFile2 = tempfile.mktemp('-buildout.cfg')
+
+ >>> from zope.release import buildout
+ >>> buildout.main((cfgFile2, buildoutFile2))
+
+ >>> print open(buildoutFile2, 'r').read()
+ [buildout]
+ parts = test
+ versions = versions
+ <BLANKLINE>
+ [test]
+ recipe = zc.recipe.testrunner
+ eggs = packageA
+ packageB
+ packageD
+ <BLANKLINE>
+ [versions]
+ packageA = 1.0.2
+ packageB = 1.2.3
+ packageC = 4.3.1
+ packageD = 2.2.4
+ <BLANKLINE>
+
+
Uploading Files
---------------
@@ -235,3 +298,19 @@
['1.0.0', '1.0.1']
>>> pkgA.tested
True
+
+As we have seen in the scripts above, the KGS class also supports the
+`entends` option. Thus, let's load the KGS for the config file 2:
+
+ >>> myKGS2 = kgs.KGS(cfgFile2)
+ >>> myKGS2
+ <KGS 'grok-dev'>
+
+ >>> myKGS2.name
+ 'grok-dev'
+
+ >>> myKGS2.packages
+ [<Package 'packageA'>,
+ <Package 'packageB'>,
+ <Package 'packageC'>,
+ <Package 'packageD'>]
Modified: zope.release/trunk/src/zope/release/kgs.py
===================================================================
--- zope.release/trunk/src/zope/release/kgs.py 2007-11-10 17:26:27 UTC (rev 81725)
+++ zope.release/trunk/src/zope/release/kgs.py 2007-11-10 18:15:27 UTC (rev 81726)
@@ -12,8 +12,65 @@
#
##############################################################################
"""KGS configuration file parser."""
+import os.path
+import urllib2
import ConfigParser
+from zc.buildout.buildout import _update, _isurl
+MAIN_SECTION = 'KGS'
+EXTENDS_OPTION = 'extends'
+
+def _open(base, filename, seen):
+ """Open a configuration file and return the result as a dictionary,
+
+ Recursively open other files based on options found.
+
+ Note: Shamelessly copied from zc.buildout!
+ """
+
+ if _isurl(filename):
+ fp = urllib2.urlopen(filename)
+ base = filename[:filename.rfind('/')]
+ elif _isurl(base):
+ if os.path.isabs(filename):
+ fp = open(filename)
+ base = os.path.dirname(filename)
+ else:
+ filename = base + '/' + filename
+ fp = urllib2.urlopen(filename)
+ base = filename[:filename.rfind('/')]
+ else:
+ filename = os.path.join(base, filename)
+ fp = open(filename)
+ base = os.path.dirname(filename)
+
+ if filename in seen:
+ raise ValueError("Recursive file include", seen, filename)
+
+ seen.append(filename)
+
+ result = {}
+
+ parser = ConfigParser.RawConfigParser()
+ parser.optionxform = lambda s: s
+ parser.readfp(fp)
+ extends = None
+ for section in parser.sections():
+ options = dict(parser.items(section))
+ if section == MAIN_SECTION:
+ extends = options.pop(EXTENDS_OPTION, extends)
+ result[section] = options
+
+ if extends:
+ extends = extends.split()
+ extends.reverse()
+ for fname in extends:
+ result = _update(_open(base, fname, seen), result)
+
+ seen.pop()
+ return result
+
+
class Package(object):
def __init__(self, name, versions, tested):
@@ -35,19 +92,19 @@
self._extract()
def _extract(self):
- config = ConfigParser.RawConfigParser()
- config.read(self.path)
- if config.has_section('KGS'):
- self.name = config.get('KGS', 'name')
- config.remove_section('KGS')
+ result = _open(os.path.dirname(self.path), self.path, [])
+ if MAIN_SECTION in result:
+ self.name = result[MAIN_SECTION].get('name', u'')
+ del result[MAIN_SECTION]
self.packages = []
- sections = config.sections()
+ sections = result.keys()
sections.sort()
for section in sections:
self.packages.append(
Package(section,
- config.get(section, 'versions').split(),
- config.getboolean(section, 'tested')
+ result[section]['versions'].split(),
+ ConfigParser.ConfigParser._boolean_states[
+ result[section]['tested']]
)
)
More information about the Checkins
mailing list