[Checkins] SVN: zope.kgs/trunk/ - Collected all generic KGS-related
scripts into one package.
Stephan Richter
srichter at cosmos.phy.tufts.edu
Fri Nov 16 21:31:31 EST 2007
Log message for revision 81891:
- Collected all generic KGS-related scripts into one package.
- Implemented some new features based on recent zope-dev discussions, such as a find
link.
- Made server maintainance much simpler by having a generator for all files.
- Provided features to keep history better.
Changed:
_U zope.kgs/trunk/
U zope.kgs/trunk/CHANGES.txt
U zope.kgs/trunk/buildout.cfg
U zope.kgs/trunk/setup.py
_U zope.kgs/trunk/src/
A zope.kgs/trunk/src/zope/kgs/README.txt
A zope.kgs/trunk/src/zope/kgs/buildout.cfg.in
A zope.kgs/trunk/src/zope/kgs/buildout.py
A zope.kgs/trunk/src/zope/kgs/intro.pt
A zope.kgs/trunk/src/zope/kgs/intro.py
A zope.kgs/trunk/src/zope/kgs/kgs.py
A zope.kgs/trunk/src/zope/kgs/link.py
A zope.kgs/trunk/src/zope/kgs/ppix.py
A zope.kgs/trunk/src/zope/kgs/site.py
A zope.kgs/trunk/src/zope/kgs/tests.py
A zope.kgs/trunk/src/zope/kgs/version.py
-=-
Property changes on: zope.kgs/trunk
___________________________________________________________________
Name: svn:ignore
+ .installed.cfg
bin
develop-eggs
dist
parts
python
Name: svn:externals
+
Modified: zope.kgs/trunk/CHANGES.txt
===================================================================
--- zope.kgs/trunk/CHANGES.txt 2007-11-17 01:18:45 UTC (rev 81890)
+++ zope.kgs/trunk/CHANGES.txt 2007-11-17 02:31:30 UTC (rev 81891)
@@ -7,8 +7,18 @@
- Initial version as ``zope.kgs``.
+ * A script that manages the generation of the entire site.
+
+ * Generate an intro page to the KGS.
+
+ * Generate `links.html` file which lists all controlled packages files.
+
* Features copied from ``zope.release``:
+ Parser for KGS configuration files.
+ Generate `versions.cfg` and `buildout.cfg` script.
+
+ * Features copied from ``zc.mirrorcheeseshopslashsimple``:
+
+ + Generate new index pages for the controlled packages.
Modified: zope.kgs/trunk/buildout.cfg
===================================================================
--- zope.kgs/trunk/buildout.cfg 2007-11-17 01:18:45 UTC (rev 81890)
+++ zope.kgs/trunk/buildout.cfg 2007-11-17 02:31:30 UTC (rev 81891)
@@ -1,22 +1,12 @@
[buildout]
develop = .
index = http://download.zope.org/zope3.4
-parts = test generate-buildout generate-versions
+parts = test scripts
[test]
recipe = zc.recipe.testrunner
eggs = zope.kgs [test]
-[generate-buildout]
+[scripts]
recipe = zc.recipe.egg:scripts
eggs = zope.kgs
-scripts = generate-buildout
-arguments = ('controlled-packages.cfg',
- './test/buildout.cfg')
-
-[generate-versions]
-recipe = zc.recipe.egg:scripts
-eggs = zope.kgs
-scripts = generate-versions
-arguments = ('controlled-packages.cfg',
- './test/versions.cfg')
Modified: zope.kgs/trunk/setup.py
===================================================================
--- zope.kgs/trunk/setup.py 2007-11-17 01:18:45 UTC (rev 81890)
+++ zope.kgs/trunk/setup.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -46,14 +46,20 @@
package_dir = {'': 'src'},
namespace_packages=['zope'],
extras_require = dict(
- test=['zope.testing']),
+ test=['zope.testing'],
+ ),
install_requires=[
'setuptools',
'zc.buildout',
+ 'zope.pagetemplate',
],
entry_points = dict(console_scripts=[
'generate-buildout = zope.kgs.buildout:main',
'generate-versions = zope.kgs.version:main',
+ 'generate-index = zope.kgs.ppix:main',
+ 'generate-links = zope.kgs.link:main',
+ 'generate-intro = zope.kgs.intro:main',
+ 'generate-site = zope.kgs.site:main',
]),
include_package_data = True,
zip_safe = False,
Property changes on: zope.kgs/trunk/src
___________________________________________________________________
Name: svn:ignore
+ zope.kgs.egg-info
Copied: zope.kgs/trunk/src/zope/kgs/README.txt (from rev 81726, zope.release/trunk/src/zope/release/README.txt)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/README.txt (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/README.txt 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,477 @@
+===============
+Known Good Sets
+===============
+
+This package provides a set of scripts and tools to manage Good-Known-Sets, or
+short KGSs. A KGS is a set of package distributions that are known to work
+well together. You can verify this, for example, by running all the tests of
+all the packages at once.
+
+Let me show you how a typical controlled packages configuration file looks
+like:
+
+ >>> import tempfile
+ >>> cfgFile = tempfile.mktemp('-cp.cfg')
+ >>> open(cfgFile, 'w').write('''\
+ ... [DEFAULT]
+ ... tested = true
+ ...
+ ... [KGS]
+ ... name = zope-dev
+ ... version = 1.2.0
+ ...
+ ... [packageA]
+ ... versions = 1.0.0
+ ... 1.0.1
+ ...
+ ... [packageB]
+ ... versions = 1.2.3
+ ...
+ ... [packageC]
+ ... # Do not test this package.
+ ... tested = false
+ ... versions = 4.3.1
+ ... ''')
+
+As you can see, this file uses an INI-style format. The "DEFAULT" section is
+special, as it will insert the specified options into all other sections as
+default. The "KGS" section specifies some global information about the KGS,
+such as the name of the KGS.
+
+All other sections refer to package names. Currently each package section
+supports two options. The "versions" option lists all versions that are known
+to work in the KGS. Those versions should *always* only be bug fixes to the
+first listed version. The second option, "tested", specifies whether the
+package should be part of the KGS test suite. By default, we want all packages
+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
+ ... version = 0.1.0
+ ... 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.
+
+.. [1]: This is usually due to bugs in setuptools or buildout, such as PYC
+files not containing the correct reference to their PY file.
+
+
+Generate Versions
+-----------------
+
+One of the easiest scripts, is the version generation. This script will
+generate a "versions" section that is compatible with buildout.
+
+ >>> versionsFile = tempfile.mktemp('-versions.cfg')
+
+ >>> from zope.kgs import version
+ >>> version.main((cfgFile, versionsFile))
+
+ >>> print open(versionsFile, 'r').read()
+ [versions]
+ packageA = 1.0.1
+ 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')
+
+ >>> 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
+-----------------
+
+In order to be able to test the KGS, you can also generate a full buildout
+file that will create and install a testrunner over all packages for you:
+
+ >>> buildoutFile = tempfile.mktemp('-buildout.cfg')
+
+ >>> from zope.kgs import buildout
+ >>> buildout.main((cfgFile, buildoutFile))
+
+ >>> print open(buildoutFile, 'r').read()
+ [buildout]
+ parts = test
+ versions = versions
+ <BLANKLINE>
+ [test]
+ recipe = zc.recipe.testrunner
+ eggs = packageA
+ packageB
+ <BLANKLINE>
+ [versions]
+ packageA = 1.0.1
+ packageB = 1.2.3
+ packageC = 4.3.1
+ <BLANKLINE>
+
+Let's make sure that the buildout generation also honors the extensions:
+
+ >>> buildoutFile2 = tempfile.mktemp('-buildout.cfg')
+
+ >>> 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>
+
+
+Flat Links Pages
+----------------
+
+We can also create a flat links page that can be used in the
+`dependency_links` argument in your `setup.py` file. Since this module
+accesses the original PyPI to ask for the download locations and filenames, we
+have to create a controlled packages configuration file that contains real
+packages with real version numbers:
+
+ >>> cfgFileReal = tempfile.mktemp('-cp.cfg')
+ >>> open(cfgFileReal, 'w').write('''\
+ ... [DEFAULT]
+ ... tested = true
+ ...
+ ... [KGS]
+ ... name = zope-dev
+ ... version = 3.4.0b2
+ ...
+ ... [PIL]
+ ... versions = 1.1.6
+ ...
+ ... [zope.component]
+ ... versions = 3.4.0
+ ...
+ ... [zope.interface]
+ ... versions = 3.4.0
+ ... 3.4.1
+ ... ''')
+
+Let's now create the links page:
+
+ >>> linksFile = tempfile.mktemp('-links.html')
+
+ >>> from zope.kgs import link
+ >>> link.main((cfgFileReal, linksFile))
+
+ >>> print open(linksFile, 'r').read()
+ <html>
+ <head>
+ <title>Links for the "zope-dev" KGS (version 3.4.0b2)</title>
+ </head>
+ <body>
+ <h1>Links for the "zope-dev" KGS (version 3.4.0b2)</h1>
+ <a href="http://pypi.python.org/packages/source/z/zope.component/zope.component-3.4.0.tar.gz#md5=94afb57dfe605d7235ff562d1eaa3bed">zope.component-3.4.0.tar.gz</a><br/>
+ <a href="http://pypi.python.org/packages/2.4/z/zope.component/zope.component-3.4.0-py2.4.egg#md5=c0763e94912e4a8ac1e321a068c916ba">zope.component-3.4.0-py2.4.egg</a><br/>
+ <a href="http://pypi.python.org/packages/source/z/zope.interface/zope.interface-3.4.0.tar.gz#md5=0be9fd80b7bb6bee520e56eba7d29c90">zope.interface-3.4.0.tar.gz</a><br/>
+ <a href="http://pypi.python.org/packages/2.4/z/zope.interface/zope.interface-3.4.0-py2.4-win32.egg#md5=3fa5e992271375eac597622d8e2fd5ec">zope.interface-3.4.0-py2.4-win32.egg</a><br/>
+ <a href="http://pypi.python.org/packages/source/z/zope.interface/zope.interface-3.4.1.tar.gz#md5=b085f4a774adab688e037ad32fbbf08e">zope.interface-3.4.1.tar.gz</a><br/>
+ </body>
+ </html>
+
+PPIX Support
+------------
+
+You can also use the KGS to limit the available packages in a package index
+generated ``zc.mirrorcheeseshopslashsimple``. This script also uses PyPI to
+look up distribution file, so wave to use the real configuration file again.
+
+Let's create the pages:
+
+ >>> indexDir = tempfile.mkdtemp('-ppix')
+
+ >>> from zope.kgs import ppix
+ >>> ppix.main((cfgFileReal, indexDir))
+
+The index contains one directory per package. So let's have a look:
+
+ >>> import os
+ >>> sorted(os.listdir(indexDir))
+ ['PIL', 'zope.component', 'zope.interface']
+
+Each directory contains a single "index.html" file with the download links:
+
+ >>> pkgDir = os.path.join(indexDir, 'zope.component')
+ >>> sorted(os.listdir(pkgDir))
+ ['index.html']
+
+ >>> pkgIndex = os.path.join(pkgDir, 'index.html')
+ >>> print open(pkgIndex, 'r').read()
+ <html>
+ <head>
+ <title>Links for "zope.component"</title>
+ </head>
+ <body>
+ <h1>Links for "zope.component"</h1>
+ <a href="http://pypi.python.org/packages/source/z/zope.component/zope.component-3.4.0.tar.gz#md5=94afb57dfe605d7235ff562d1eaa3bed">zope.component-3.4.0.tar.gz</a><br/>
+ <a href="http://pypi.python.org/packages/2.4/z/zope.component/zope.component-3.4.0-py2.4.egg#md5=c0763e94912e4a8ac1e321a068c916ba">zope.component-3.4.0-py2.4.egg</a><br/>
+ </body>
+ </html>
+
+PIL is an interesting case, because it does not upload its distribution files
+yet, at least not for version 1.1.6:
+
+ >>> pkgIndex = os.path.join(indexDir, 'PIL', 'index.html')
+ >>> print open(pkgIndex, 'r').read()
+ <html><head><title>Links for PIL</title></head><body><h1>Links for PIL</h1><a href='http://www.pythonware.com/products/pil' rel="homepage">1.1.6 home_page</a><br/>
+ <a href='http://effbot.org/downloads/#Imaging' rel="download">1.1.6 download_url</a><br/>
+ <a href='http://www.pythonware.com/products/pil/' rel="homepage">1.1.4 home_page</a><br/>
+ <a href='http://www.pythonware.com/products/pil/' rel="homepage">1.1.3 home_page</a><br/>
+ <a href='http://www.pythonware.com/downloads/Imaging-1.1.3.tar.gz' rel="download">1.1.3 download_url</a><br/>
+ <a href='http://www.pythonware.com/products/pil' rel="homepage">1.1.5a1 home_page</a><br/>
+ <a href='http://effbot.org/zone/pil-changes-115.htm' rel="download">1.1.5a1 download_url</a><br/>
+ <a href='http://www.pythonware.com/products/pil' rel="homepage">1.1.5a2 home_page</a><br/>
+ <a href='http://effbot.org/zone/pil-changes-115.htm' rel="download">1.1.5a2 download_url</a><br/>
+ <a href='http://www.pythonware.com/products/pil' rel="homepage">1.1.5 home_page</a><br/>
+ <a href='http://effbot.org/zone/pil-changes-115.htm' rel="download">1.1.5 download_url</a><br/>
+ </body></html>
+
+Optionally, you can also specify the `-i` option to generate an overview:
+
+ >>> ppix.main(('-i', cfgFileReal, indexDir))
+
+ >>> sorted(os.listdir(indexDir))
+ ['PIL', 'index.html', 'zope.component', 'zope.interface']
+
+Let's now look at the file:
+
+ >>> indexPage = os.path.join(indexDir, 'index.html')
+ >>> print open(indexPage, 'r').read()
+ <html>
+ <head>
+ <title>Simple Index for the "zope-dev" KGS (version 3.4.0b2)</title>
+ </head>
+ <body>
+ <h1>Simple Index for the "zope-dev" KGS (version 3.4.0b2)</h1>
+ <a href="PIL">PIL</a><br/>
+ <a href="zope.component">zope.component</a><br/>
+ <a href="zope.interface">zope.interface</a><br/>
+ </body>
+ </html>
+
+Allowing exisitng package pages to be overwritten and making the main index
+page an optional feature makes it possible to use this script for two use
+cases: (1) Merge the constraints into a PPIX index created by
+``zc.mirrorcheeseshopslashsimple``, and (2) create a standalone index which
+only provides the packages of the KGS.
+
+
+Introduction Page
+-----------------
+
+Once all the files have been created, one can generate an introduction page
+that explains how the files can be used. It also lists all the files by
+distribution. In order for this script to work, you need the following
+directory layout:
+
+ >>> kgsDir = tempfile.mkdtemp()
+
+ >>> open(os.path.join(kgsDir, 'controlled-packages.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'buildout.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'versions.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'links.cfg'), 'w').write(' ')
+
+ >>> open(os.path.join(kgsDir, 'controlled-packages-1.0.0.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'buildout-1.0.0.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'versions-1.0.0.cfg'), 'w').write(' ')
+
+ >>> open(os.path.join(kgsDir, 'controlled-packages-1.1.0.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'buildout-1.1.0.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'versions-1.1.0.cfg'), 'w').write(' ')
+ >>> open(os.path.join(kgsDir, 'links-1.1.0.cfg'), 'w').write(' ')
+
+ >>> open(os.path.join(kgsDir, 'index.html'), 'w').write(' ')
+ >>> os.mkdir(os.path.join(kgsDir, 'minimal'))
+
+Let's now generate the page:
+
+ >>> introPage = os.path.join(kgsDir, 'intro.html')
+
+ >>> from zope.kgs import intro
+ >>> intro.main((introPage,))
+
+ >>> print open(introPage, 'r').read()
+ <!DOCTYPE ...
+ <body>
+ <h1>Introduction to the KGS</h1>
+ <h2>Available Versions</h2>
+ <h3>Version 1.0.0</h3>
+ <ul>
+ <li>
+ <a href="controlled-packages-1.0.0.cfg">Controlled Packages</a>
+ </li>
+ <li>
+ <a href="versions-1.0.0.cfg">Versions</a>
+ </li>
+ <li>
+ <a href="index.html">Index</a>
+ </li>
+ <li>
+ <a href="minimal">Minimal Index</a>
+ </li>
+ </ul>
+ <h3>Version 1.1.0</h3>
+ <ul>
+ <li>
+ <a href="controlled-packages-1.1.0.cfg">Controlled Packages</a>
+ </li>
+ <li>
+ <a href="versions-1.1.0.cfg">Versions</a>
+ </li>
+ <li>
+ <a href="index.html">Index</a>
+ </li>
+ <li>
+ <a href="minimal">Minimal Index</a>
+ </li>
+ </ul>
+ ...
+ </body>
+ </html>
+
+
+The Site Generator
+------------------
+
+The easiest way to publish the KGS is via a directory published by a Web
+server. Whenever a new `controlled-packages.cfg` file is uploaded, a script is
+run that generates all the files. I usually set up a crontab job to do
+this. The site generator script acts upon a directory, in which it assumes a
+`controlled-packages.cfg` file was placed:
+
+ >>> siteDir = tempfile.mkdtemp()
+ >>> cfgFileSite = os.path.join(siteDir, 'controlled-packages.cfg')
+
+ >>> import shutil
+ >>> shutil.copy(cfgFileReal, cfgFileSite)
+
+ >>> from zope.kgs import site
+ >>> site.main((siteDir,))
+
+Let's have a look at the generated files:
+
+ >>> sorted(os.listdir(siteDir))
+ ['PIL',
+ 'buildout-3.4.0b2.cfg', 'buildout.cfg',
+ 'cf-timestamp',
+ 'controlled-packages-3.4.0b2.cfg', 'controlled-packages.cfg',
+ 'intro.html',
+ 'links-3.4.0b2.cfg', 'links.cfg',
+ 'minimal',
+ 'versions-3.4.0b2.cfg', 'versions.cfg',
+ 'zope.component', 'zope.interface']
+
+ >>> sorted(os.listdir(os.path.join(siteDir, 'minimal')))
+ ['PIL', 'index.html', 'zope.component', 'zope.interface']
+
+If you try to generate the site again without changing the controlled packages
+config file, it will simply return, because it checks the timestamp from the
+previous generation:
+
+ >>> tsPath = os.path.join(siteDir, 'cf-timestamp')
+
+ >>> beforeTimestamp = open(tsPath).read()
+ >>> site.main((siteDir,))
+ >>> afterTimestamp = open(tsPath).read()
+
+ >>> beforeTimestamp == afterTimestamp
+ True
+
+
+Basic Parser API
+----------------
+
+The ``kgs.py`` module provides a simple class that parses the KGS
+configuration file and provides all data in an object-oriented manner.
+
+ >>> from zope.kgs import kgs
+
+The class is simply instnatiated using the path to the config file:
+
+ >>> myKGS = kgs.KGS(cfgFile)
+ >>> myKGS
+ <KGS 'zope-dev'>
+
+The name and version of the KGS is available via:
+
+ >>> myKGS.name
+ 'zope-dev'
+ >>> myKGS.version
+ '1.2.0'
+
+The packages are available under `packages`:
+
+ >>> myKGS.packages
+ [<Package 'packageA'>, <Package 'packageB'>, <Package 'packageC'>]
+
+Each package is also an object:
+
+ >>> pkgA = myKGS.packages[0]
+ >>> pkgA
+ <Package 'packageA'>
+
+ >>> pkgA.name
+ 'packageA'
+ >>> pkgA.versions
+ ['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'>]
Copied: zope.kgs/trunk/src/zope/kgs/buildout.cfg.in (from rev 81726, zope.release/trunk/src/zope/release/buildout.cfg.in)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/buildout.cfg.in (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/buildout.cfg.in 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,10 @@
+[buildout]
+parts = test
+versions = versions
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = %(tested-packages)s
+
+[versions]
+%(versions)s
Copied: zope.kgs/trunk/src/zope/kgs/buildout.py (from rev 81726, zope.release/trunk/src/zope/release/buildout.py)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/buildout.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/buildout.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,73 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generate a ``buildout.cfg`` file from the controlled list of packages.
+
+Usage: generate-buildout package-cfg-path [output-cfg-path]
+
+* ``package-cfg-path``
+
+ This is the path to the controlled packages configuration file.
+
+* ``output-cfg-path``
+
+ The path of the file under which the generated buildout configuration file
+ is stored. By default it is placed in the package configuration file's
+ directory under the name 'test-buildout.cfg'.
+
+"""
+import ConfigParser
+import os
+
+from zope.kgs import kgs
+
+def getVersionsListing(packages):
+ """Create a version listing string."""
+ return '\n'.join(
+ [package.name + ' = ' + package.versions[-1]
+ for package in packages])
+
+
+def generateBuildout(packageConfigPath, outputPath):
+ """Generate a ``buildout.cfg`` from the list of controlled packages."""
+ # Load all package information from the controlled pacakge config file.
+ packages = kgs.KGS(packageConfigPath).packages
+
+ # Create the data dictionary
+ data = {
+ 'tested-packages': '\n '.join(
+ [package.name for package in packages if package.tested]),
+ 'versions': getVersionsListing(packages)
+ }
+
+ # Write a new buildout.cfg file
+ templatePath = os.path.join(os.path.dirname(__file__), 'buildout.cfg.in')
+ open(outputPath, 'w').write(open(templatePath, 'r').read() %data)
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 1:
+ print __file__.__doc__
+ sys.exit(1)
+
+ packageConfigPath = os.path.abspath(args[0])
+
+ outputPath = os.path.join(
+ os.path.dirname(packageConfigPath), 'test-buildout.cfg')
+ if len(args) == 2:
+ outputPath = args[1]
+
+ generateBuildout(packageConfigPath, outputPath)
Added: zope.kgs/trunk/src/zope/kgs/intro.pt
===================================================================
--- zope.kgs/trunk/src/zope/kgs/intro.pt (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/intro.pt 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,115 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+ <head>
+ <title>Introduction to the KGS</title>
+ </head>
+ <body>
+ <h1>Introduction to the KGS</h1>
+
+ <h2>Available Versions</h2>
+
+ <tal:block repeat="version self/versions">
+ <h3>Version <span tal:replace="version/name" /></h3>
+ <ul>
+ <li tal:repeat="feature version/features">
+ <a href="versions-1.0.0.cfg"
+ tal:attributes="href feature/url"
+ tal:content="feature/title">Versions</a>
+ </li>
+ </ul>
+ </tal:block>
+
+
+ <h2>Usage</h2>
+
+ <p>
+ This KGS was designed to work with many of the tools developed to
+ manage and install Python pacakges. The following sub-sections will
+ explain its use in more detail.
+ </p>
+
+ <h3>The Index</h3>
+
+ <p>
+ You can use the index directly. It then behaves exactely like
+ <a href="http://pypi.python.org/simple">http://pypi.python.org/simple</a>,
+ except that for the controlled packages only the good versions are
+ available. The advantage of using the KGS as an index is that you get
+ bug fixes automatically.
+ </p>
+
+ <ul>
+ <li>
+ <div>Buildout, <code>buildout.cfg</code>:</div>
+ <pre>
+ [buildout]
+ index = http://download.project.org/kgs
+ ...
+ </pre>
+ </li>
+ <li>
+ <div>Setup Tools, <code>easy_install</code></div>
+ <pre>
+ $ easy_install -i http://download.project.org/kgs mypackage
+ </pre>
+ </li>
+ </ul>
+
+ <h3>Nailed or Pinned Versions</h3>
+
+ <p>
+ When deploying an application, it is often important to nail or pin down
+ the versions of all used packages, so that it can be guaranteed that the
+ setup is identical all the time.
+ </p>
+
+ <ul>
+ <li>
+ <div>Buildout, <code>buildout.cfg</code>:</div>
+ <pre>
+ [buildout]
+ versions = versions
+ ...
+ [version]
+ zope.interface = 3.4.0
+ (copy the content here)
+ </pre>
+ or
+ <pre>
+ [buildout]
+ extend = http://download.project.org/kgs/versions-1.0.0.cfg
+ </pre>
+ </li>
+ <li>
+ <div>Setup Tools itself cannot use the <code>version.cfg</code>
+ file.</div>
+ </li>
+ </ul>
+
+ <h3>Find Links</h3>
+
+ <p>
+ The way of providing the installation tools with additional locations to
+ look for packages is via find links. Those URLs are expected to be an
+ HTML page with links to files or files directly.
+ </p>
+
+ <ul>
+ <li>
+ <div>Buildout, <code>buildout.cfg</code>:</div>
+ <pre>
+ [buildout]
+ find-links = http://download.project.org/kgs/links.html
+ ...
+ </pre>
+ </li>
+ <li>
+ <div>Setup Tools, <code>easy_install</code></div>
+ <pre>
+ $ easy_install -f http://download.project.org/kgs/links.html mypackage
+ </pre>
+ </li>
+ </ul>
+
+ </body>
+</html>
Property changes on: zope.kgs/trunk/src/zope/kgs/intro.pt
___________________________________________________________________
Name: svn:eol-style
+ native
Added: zope.kgs/trunk/src/zope/kgs/intro.py
===================================================================
--- zope.kgs/trunk/src/zope/kgs/intro.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/intro.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,79 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generate an Introduction HTML page for the KGS.
+
+Usage: %s output-intro-path
+
+* ``output-intro-path``
+
+ The path of the file under which the generated intro file is stored.
+"""
+import os
+import zope.pagetemplate.pagetemplatefile
+
+FEATURES = [
+ ('controlled-packages-%(version)s.cfg', u'Controlled Packages'),
+ ('buildout-%s.cfg', u'Buildout Configuration'),
+ ('versions-%(version)s.cfg', u'Versions'),
+ ('links-%(version)s.html', u'Package Links'),
+ ('index.html', u'Index'),
+ ('minimal', u'Minimal Index'),
+ ]
+
+TEMPLATE_PATH = os.path.join(os.path.dirname(__file__), 'intro.pt')
+
+class IntroPage(zope.pagetemplate.pagetemplatefile.PageTemplateFile):
+
+ def __init__(self, kgsDir):
+ super(IntroPage, self).__init__(TEMPLATE_PATH)
+ self.kgsDir = kgsDir
+
+ def update(self):
+ kgsFileNames = os.listdir(self.kgsDir)
+ vnums = [fn[20:-4] for fn in kgsFileNames
+ if fn.startswith('controlled-packages-')]
+ vnums.sort()
+ self.versions = []
+ for vnum in vnums:
+ features = []
+ for (templ, title) in FEATURES:
+ featureFileName = templ %{'version': vnum}
+ if featureFileName in kgsFileNames:
+ features.append({'url': featureFileName, 'title': title})
+ self.versions.append({'name': vnum, 'features': features})
+
+
+ def pt_getContext(self, args=(), options=None, **ignore):
+ rval = {'args': args,
+ 'nothing': None,
+ 'options': options,
+ 'self': self
+ }
+ rval.update(self.pt_getEngine().getBaseNames())
+ return rval
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 0:
+ print __file__.__doc__
+ sys.exit(1)
+
+ outputPath = args[0]
+
+ page = IntroPage(os.path.dirname(outputPath))
+ page.update()
+ open(outputPath, 'w').write(page())
Property changes on: zope.kgs/trunk/src/zope/kgs/intro.py
___________________________________________________________________
Name: svn:keywords
+ Id
Copied: zope.kgs/trunk/src/zope/kgs/kgs.py (from rev 81726, zope.release/trunk/src/zope/release/kgs.py)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/kgs.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/kgs.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,115 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""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):
+ self.name = name
+ self.versions = versions
+ self.tested = tested
+
+ def __repr__(self):
+ return '<%s %r>' %(self.__class__.__name__, self.name)
+
+
+class KGS(object):
+
+ name = u'noname'
+ version = u'unknown'
+ packages = ()
+
+ def __init__(self, path):
+ self.path = path
+ self._extract()
+
+ def _extract(self):
+ result = _open(os.path.dirname(self.path), self.path, [])
+ if MAIN_SECTION in result:
+ self.name = result[MAIN_SECTION].get('name', self.name)
+ self.version = result[MAIN_SECTION].get('version', self.version)
+ del result[MAIN_SECTION]
+ self.packages = []
+ sections = result.keys()
+ sections.sort()
+ for section in sections:
+ self.packages.append(
+ Package(section,
+ result[section]['versions'].split(),
+ ConfigParser.ConfigParser._boolean_states[
+ result[section]['tested']]
+ )
+ )
+
+ def __repr__(self):
+ return '<%s %r>' %(self.__class__.__name__, self.name)
+
Added: zope.kgs/trunk/src/zope/kgs/link.py
===================================================================
--- zope.kgs/trunk/src/zope/kgs/link.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/link.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,78 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generate a 'Links' HTML page that can be used as a `find-links` entry in
+setuptools.
+
+Usage: %s package-cfg-path [output-links-path]
+
+* ``package-cfg-path``
+
+ This is the path to the controlled packages configuration file.
+
+* ``output-links-path``
+
+ The path of the file under which the generated links file is stored. By
+ default it is placed in the package configuration file's directory under the
+ name 'links.html'.
+"""
+import os
+import xmlrpclib
+import zope.kgs.kgs
+
+TEMPLATE = ('<html>\n<head>\n'
+ '<title>Links for the "%(name)s" KGS (version %(version)s)</title>\n'
+ '</head>\n'
+ '<body>\n'
+ '<h1>Links for the "%(name)s" KGS (version %(version)s)</h1>\n'
+ '%(links)s\n'
+ '</body>\n'
+ '</html>')
+
+LINK_TEMPLATE = '<a href="%(url)s#md5=%(md5_digest)s">%(filename)s</a><br/>'
+
+def generateLinks(packageConfigPath, outputPath):
+ """Generate a ``buildout.cfg`` from the list of controlled packages."""
+ kgs = zope.kgs.kgs.KGS(packageConfigPath)
+ server = xmlrpclib.Server('http://cheeseshop.python.org/pypi')
+
+ # Collect all links
+ links = []
+ for package in kgs.packages:
+ for version in package.versions:
+ dist_links = server.package_urls(package.name, version)
+ for link in dist_links:
+ links.append(LINK_TEMPLATE %link)
+
+ # Write a new versions.cfg file
+ open(outputPath, 'w').write(
+ TEMPLATE %{'name': kgs.name,
+ 'version': kgs.version,
+ 'links': '\n'.join(links)})
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 1:
+ print __file__.__doc__ % sys.argv[0]
+ sys.exit(1)
+
+ packageConfigPath = os.path.abspath(args[0])
+
+ outputPath = os.path.join(
+ os.path.dirname(packageConfigPath), 'links.html')
+ if len(args) == 2:
+ outputPath = args[1]
+
+ generateLinks(packageConfigPath, outputPath)
Property changes on: zope.kgs/trunk/src/zope/kgs/link.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: zope.kgs/trunk/src/zope/kgs/ppix.py
===================================================================
--- zope.kgs/trunk/src/zope/kgs/ppix.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/ppix.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,117 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generate a 'Links' HTML page that can be used as a `find-links` entry in
+setuptools.
+
+Usage: %s [-i] package-cfg-path [output-links-path]
+
+* -i
+
+ When set, this flag causes an `index.html` file to be generated that
+ provides a link to every package's links page.
+
+* ``package-cfg-path``
+
+ This is the path to the controlled packages configuration file.
+
+* ``output-links-path``
+
+ The path of the file under which the generated links file is stored. By
+ default it is placed in the package configuration file's directory under the
+ name 'links.html'.
+"""
+import os
+import urllib
+import urllib2
+import xmlrpclib
+import zope.kgs.kgs
+
+TEMPLATE = ('<html>\n<head>\n<title>%(title)s</title>\n</head>\n'
+ '<body>\n<h1>%(title)s</h1>\n%(body)s\n</body>\n'
+ '</html>')
+
+LINK_TEMPLATE = '<a href="%(url)s#md5=%(md5_digest)s">%(filename)s</a><br/>'
+SIMPLE_LINK_TEMPLATE = '<a href="%(url)s">%(name)s</a><br/>'
+
+SIMPLE_BASE_URL = "http://cheeseshop.python.org/simple/"
+
+def generatePackagePage(package, destDir, server):
+ packagePath = os.path.join(destDir, package.name)
+ links = []
+ for version in package.versions:
+ dist_links = server.package_urls(package.name, version)
+ for link in dist_links:
+ links.append(LINK_TEMPLATE %link)
+
+ if not os.path.exists(packagePath):
+ os.mkdir(packagePath)
+
+ if links:
+ open(os.path.join(packagePath, 'index.html'), 'w').write(
+ TEMPLATE %{'title': 'Links for "%s"' %package.name,
+ 'body': '\n'.join(links)})
+ else:
+ # A small fallback, in case PyPI does not maintain the release
+ # files.
+ page = urllib2.urlopen(SIMPLE_BASE_URL + package.name + '/').read()
+ open(os.path.join(packagePath, 'index.html'), 'w').write(page)
+
+
+def generatePackagePages(packageConfigPath, destDir):
+ kgs = zope.kgs.kgs.KGS(packageConfigPath)
+ server = xmlrpclib.Server('http://cheeseshop.python.org/pypi')
+
+ for package in kgs.packages:
+ generatePackagePage(package, destDir, server)
+
+
+def generateIndexPage(packageConfigPath, destDir):
+ kgs = zope.kgs.kgs.KGS(packageConfigPath)
+ links = []
+ for pkg in kgs.packages:
+ links.append(
+ SIMPLE_LINK_TEMPLATE %{
+ 'url': urllib.quote(pkg.name), 'name': pkg.name}
+ )
+ open(os.path.join(destDir, 'index.html'), 'w').write(
+ TEMPLATE %{
+ 'title': 'Simple Index for the "%s" KGS (version %s)' %(kgs.name,
+ kgs.version),
+ 'body': '\n'.join(links)})
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 1:
+ print __file__.__doc__ % sys.argv[0]
+ sys.exit(1)
+
+ createIndex = False
+ if args[0] == '-i':
+ createIndex = True
+ args = args[1:]
+
+ packageConfigPath = os.path.abspath(args[0])
+
+ destDir = os.path.join(
+ os.path.dirname(packageConfigPath), 'links.html')
+ if len(args) == 2:
+ destDir = args[1]
+
+ generatePackagePages(packageConfigPath, destDir)
+
+ if createIndex:
+ generateIndexPage(packageConfigPath, destDir)
Property changes on: zope.kgs/trunk/src/zope/kgs/ppix.py
___________________________________________________________________
Name: svn:keywords
+ Id
Added: zope.kgs/trunk/src/zope/kgs/site.py
===================================================================
--- zope.kgs/trunk/src/zope/kgs/site.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/site.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,92 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generates a full KGS site with all bells and whistles.
+
+Usage: %s site-dir
+
+* ``site-dir``
+
+ The path to the directory where a ``controlled-packages.cfg`` file is
+ located to generate the site. The generated site is in that directory as
+ well.
+"""
+import os
+import shutil
+import time
+from zope.kgs import version, buildout, ppix, link, intro, kgs
+
+TIMESTAMP_FILENAME = 'cf-timestamp'
+
+def generateSite(siteDir):
+ kgsPath = os.path.join(siteDir, 'controlled-packages.cfg')
+ ver = kgs.KGS(kgsPath).version
+
+ timestampPath = os.path.join(siteDir, TIMESTAMP_FILENAME)
+
+ # If there have been no changes in the file since the last generation,
+ # simple do not do anything.
+ if os.path.exists(timestampPath):
+ last_update = float(open(timestampPath, 'r').read())
+ last_modified = os.stat(kgsPath)[-2]
+ if last_update > last_modified:
+ return
+
+ # Copy the KGS config file to a versioned version
+ shutil.copy(
+ kgsPath, os.path.join(siteDir, 'controlled-packages-%s.cfg' %ver))
+
+ # Create the buildout config file and version it
+ buildoutPath = os.path.join(siteDir, 'buildout.cfg')
+ buildout.generateBuildout(kgsPath, buildoutPath)
+ shutil.copy(buildoutPath, os.path.join(siteDir, 'buildout-%s.cfg' %ver))
+
+ # Create a versions config file and version it
+ versionsPath = os.path.join(siteDir, 'versions.cfg')
+ version.generateVersions(kgsPath, versionsPath)
+ shutil.copy(versionsPath, os.path.join(siteDir, 'versions-%s.cfg' %ver))
+
+ # Create a links config file and version it
+ linksPath = os.path.join(siteDir, 'links.cfg')
+ link.generateLinks(kgsPath, linksPath)
+ shutil.copy(linksPath, os.path.join(siteDir, 'links-%s.cfg' %ver))
+
+ # Update the full index (which is asummed to live in the site directory)
+ ppix.generatePackagePages(kgsPath, siteDir)
+
+ # Update the minimal index
+ midxDir = os.path.join(siteDir, 'minimal')
+ if not os.path.exists(midxDir):
+ os.mkdir(midxDir)
+ ppix.generatePackagePages(kgsPath, midxDir)
+ ppix.generateIndexPage(kgsPath, midxDir)
+
+ # Update the intro page
+ introPath = os.path.join(siteDir, 'intro.html')
+ intro.main((introPath,))
+
+ # Save the last generation date-time.
+ open(timestampPath, 'w').write(str(time.time()))
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 1:
+ print __file__.__doc__ % sys.argv[0]
+ sys.exit(1)
+
+ siteDir = os.path.abspath(args[0])
+
+ generateSite(siteDir)
Property changes on: zope.kgs/trunk/src/zope/kgs/site.py
___________________________________________________________________
Name: svn:keywords
+ Id
Copied: zope.kgs/trunk/src/zope/kgs/tests.py (from rev 81726, zope.release/trunk/src/zope/release/tests.py)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/tests.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/tests.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,29 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""zope.release tools tests
+
+$Id$
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+from zope.testing import doctest
+from zope.testing.doctestunit import DocFileSuite
+
+def test_suite():
+ return unittest.TestSuite((
+ DocFileSuite('README.txt',
+ optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+ ),
+ ))
Copied: zope.kgs/trunk/src/zope/kgs/version.py (from rev 81726, zope.release/trunk/src/zope/release/version.py)
===================================================================
--- zope.kgs/trunk/src/zope/kgs/version.py (rev 0)
+++ zope.kgs/trunk/src/zope/kgs/version.py 2007-11-17 02:31:30 UTC (rev 81891)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Generate a ``latest-versions.cfg`` file from the controlled list of
+packages.
+
+This file can
+
+Usage: generate-buildout package-cfg-path [output-cfg-path]
+
+* ``package-cfg-path``
+
+ This is the path to the controlled packages configuration file.
+
+* ``output-cfg-path``
+
+ The path of the file under which the generated buildout configuration file
+ is stored. By default it is placed in the package configuration file's
+ directory under the name 'latest-versions.cfg'.
+
+"""
+import os
+
+from zope.kgs import buildout, kgs
+
+def generateVersions(packageConfigPath, outputPath):
+ """Generate a ``buildout.cfg`` from the list of controlled packages."""
+ # Load all package information from the controlled pacakge config file.
+ packages = kgs.KGS(packageConfigPath).packages
+
+ # Write a new versions.cfg file
+ open(outputPath, 'w').write(
+ '[versions]\n' +
+ buildout.getVersionsListing(packages))
+
+
+def main(args=None):
+ if args is None:
+ args = sys.argv[1:]
+
+ if len(args) < 1:
+ print __file__.__doc__
+ sys.exit(1)
+
+ packageConfigPath = os.path.abspath(args[0])
+
+ outputPath = os.path.join(
+ os.path.dirname(packageConfigPath), 'latest-versions.cfg')
+ if len(args) == 2:
+ outputPath = args[1]
+
+ generateVersions(packageConfigPath, outputPath)
More information about the Checkins
mailing list