[Checkins] SVN: zopeorg.buildout/branches/beta.zope.org/ ADDED

Andreas Jung andreas at andreas-jung.com
Mon May 9 08:32:57 EDT 2011


Log message for revision 121636:
  ADDED
  

Changed:
  A   zopeorg.buildout/branches/beta.zope.org/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/bin/
  A   zopeorg.buildout/branches/beta.zope.org/bin/activate
  A   zopeorg.buildout/branches/beta.zope.org/bin/activate_this.py
  A   zopeorg.buildout/branches/beta.zope.org/bin/cheetah
  A   zopeorg.buildout/branches/beta.zope.org/bin/cheetah-compile
  A   zopeorg.buildout/branches/beta.zope.org/bin/easy_install
  A   zopeorg.buildout/branches/beta.zope.org/bin/easy_install-2.6
  A   zopeorg.buildout/branches/beta.zope.org/bin/paster
  A   zopeorg.buildout/branches/beta.zope.org/bin/pip
  A   zopeorg.buildout/branches/beta.zope.org/bin/python
  A   zopeorg.buildout/branches/beta.zope.org/bin/zopeskel
  A   zopeorg.buildout/branches/beta.zope.org/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/buildout.cfg
  A   zopeorg.buildout/branches/beta.zope.org/include/
  A   zopeorg.buildout/branches/beta.zope.org/include/python2.6
  A   zopeorg.buildout/branches/beta.zope.org/lib/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/UserDict.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/_abcoll.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/abc.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/codecs.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/config
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/copy_reg.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/distutils.cfg
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/encodings
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/fnmatch.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/genericpath.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/lib-dynload
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/linecache.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/locale.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/no-global-site-packages.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/ntpath.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/orig-prefix.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/os.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/posixpath.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/re.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheRegion.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheStore.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CheetahWrapper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Compiler.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Django.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/DummyTransaction.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ErrorCatchers.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/FileUtils.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Filters.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportHooks.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportManager.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/I18n.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/NameMapper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Parser.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Servlet.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SettingsManager.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SourceReader.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Template.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/TemplateCmdLineIface.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/_SkeletonPage.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/CheetahWrapper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Filters.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/NameMapper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Regressions.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/SyntaxAndOutput.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Template.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Test.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Unicode.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/unittest_local_copy.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/xmlrunner.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/CGITemplate.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReport.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReportDoc.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/RecursiveNull.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/SiteHierarchy.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Unspecified.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Indenter.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Misc.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/VerifyType.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/WebInputMixin.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlDecode.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlEncode.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/memcache.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/statprof.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Version.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.so
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockparser.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockprocessors.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/commandline.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/etree_loader.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/html4.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/inlinepatterns.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/odict.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/postprocessors.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/preprocessors.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/treeprocessors.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/convertTmplPathToModuleName.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/native_libs.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah-compile
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/entry_points.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/namespace_packages.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/requires.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/auth_tkt.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/basic.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cas.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cookie.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/digest.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/form.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/grantip.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/multi.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/open_id.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cascade.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgiapp.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgitb_catcher.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/config.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cowbell/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cowbell/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/debugapp.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/doctest_webapp.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/fsdiff.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/prints.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/profile.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/testserver.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/watchthreads.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/wdg_validate.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/errordocument.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/evalcontext.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/MochiKit.packed.js
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/debug.js
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/minus.jpg
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/plus.jpg
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/middleware.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/collector.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/errormiddleware.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/formatter.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/reporter.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/serial_number_generator.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fileapp.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fixture.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/flup_session.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/gzipper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpexceptions.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpheaders.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpserver.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/lint.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/modpython.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/pony.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/progress.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/proxy.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/recursive.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/registry.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/reloader.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/request.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/response.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/session.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/transaction.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/translogger.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/url.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlmap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlparser.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/PySourceColor.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/UserDict24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinit.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinstance.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/converters.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/dateinterval.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/datetimeutil.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/doctest24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/filemixin.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/finddata.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/findpackage.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/import_string.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/intset.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/ip4.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/killthread.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/looper.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/mimeparse.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/multidict.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/quoting.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/scgiserver.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/string24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/subprocess24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/template.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadedprint.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadinglocal.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgilib.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgiwrappers.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/entry_points.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/namespace_packages.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/requires.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/config.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/converters.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/epdesc.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/interfaces.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/loadwsgi.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/paster_templates.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/fixtypeerror.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/threadinglocal.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/finddata.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/fixture.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_basic_app.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config_middleware.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_filter.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_load_package.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/entry_points.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/namespace_packages.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/requires.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/scripts/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/scripts/paster
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/appinstall.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/bool_optparse.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cgi_server.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/checkperms.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cherrypy_server.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/copydir.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/create_distro.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/default_sysconfig.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/entrypoints.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/epdesc.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/exe.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/filemaker.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/flup_server.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/grep.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/help.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/interfaces.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/+package+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.cfg
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/pluginlib.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/request.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/templates.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/testapp.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/twisted_web2_server.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/logging_config.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/secret.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/string24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/subprocess24.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/uuid.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiserver/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiserver/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiutils_server.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/entry_points.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/requires.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_zope.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/archetype.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/base.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_namespace.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_zope.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/archetypes.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/atschema.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_namespace.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_zope.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/kss_plugin.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/localcommands.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/nested_namespace.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_buildout.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_theme.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone2_theme.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_buildout.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_portlet.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_theme.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone4_buildout.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_app.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_pas.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/recipe.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/silva_buildout.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/hosting.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/interfaces.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/kss_plugin.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/archetype.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone_pas.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/+content_class_filename+.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/messagefactory_insert.txt_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/schema_field_bridge.txt_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/+interface_name+.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/additional_imports.txt_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/README.txt_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/config.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/+content_class_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/+content_class_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/factorytool.xml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/rolemap.xml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/+types_xml_filename+.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types.xml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/+interface_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/default/browserlayer.xml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/+form_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/form.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/browser/+form_filename+.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.pt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/metadata.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/portlets.xml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/base_+portlet_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/test_+portlet_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.pt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/configure.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/meta.zcml_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metaconfigure.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metadirectives.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/anonymous_user_factory.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/authentication.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/challenge.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/credentials_reset.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/credentials_update.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/extraction.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/group_enumeration.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/groups.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/properties.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/role_assigner.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/role_enumeration.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/roles.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/update.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/user_adder.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/user_enumeration.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/user_factory.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/interface.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugin.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/__init__.py_insert
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/validation.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/nested_namespace.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_theme.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone2_theme.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_portlet.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_theme.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone4_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_app.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_pas.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/recipe.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/silva_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/config.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/factorytool.xml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/portlets.xml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/types.xml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/base.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/test_doctest.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CHANGES.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CONTRIBUTORS.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/MANIFEST.in_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/docs/HISTORY.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/tests.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/zope2.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+project+-configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/+namespace_package+.+namespace_package2+.+package+-configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.kss
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.pt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/zopeconfig.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/+package+.js_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/docs/HISTORY.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/docs/HISTORY.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/INSTALL.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.GPL
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_buildout/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_buildout/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/Install.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/config.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/import_steps.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/setuphandlers.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base_properties.props_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/generated.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/portlets.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/public.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/CONTENT.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/+package+.css.dtml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/CONTENT.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/version.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/MANIFEST.in_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/Install.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/utils.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/HISTORY.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/config.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/+package+.css.dtml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base_properties.props_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/generated.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/portlets.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/public.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/framework.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/runalltests.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testSkeleton.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testStyleInstallation.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/version.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/products/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/products/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/src/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/var/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/var/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.pt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/metadata.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/portlets.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/base.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/test_portlet.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/INSTALL.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.GPL
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/interfaces.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/main.css_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlet.pt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlets.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/+namespace_package+.+package+_various.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/viewlets.xml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/setuphandlers.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/CONTENT.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base_properties.props_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/portlets.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/public.css.dtml
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/version.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+project+-configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/MANIFEST.in_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/src/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/var/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/var/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/INSTALL.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.GPL
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/base.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/etc/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/etc/supervisord.conf_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/products/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/products/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/src/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/templates/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/templates/logrotate.conf
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/var/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/var/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/add_plugin.zpt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/icon.gif
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/install.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/interface.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugin.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CHANGES.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CONTRIBUTORS.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/INSTALL.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.GPL
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/test_docs.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/__init__.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CHANGES.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CONTRIBUTORS.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/README.txt_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/setup.py_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/products/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/products/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/src/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/var/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/var/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/bootstrap.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/buildout.cfg_tmpl
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/products/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/products/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/src/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/var/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/var/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_all.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_base.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_vars.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskel_script.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskeldocs.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/ui.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/vars.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zope2_buildout.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zopeskel_script.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/easy-install.pth
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/PKG-INFO
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/SOURCES.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/dependency_links.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/entry_points.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/not-zip-safe
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/top_level.txt
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/backwardcompat.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/basecommand.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/baseparser.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/bundle.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/completion.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/freeze.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/help.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/install.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/search.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/uninstall.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/unzip.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/zip.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/exceptions.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/index.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/locations.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/log.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/req.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/runner.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/util.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/__init__.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/bazaar.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/git.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/mercurial.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/subversion.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/venv.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools.pth
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_compile.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_constants.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_parse.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/stat.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/types.py
  A   zopeorg.buildout/branches/beta.zope.org/lib/python2.6/warnings.py
  A   zopeorg.buildout/branches/beta.zope.org/src/
  A   zopeorg.buildout/branches/beta.zope.org/src/README.txt
  A   zopeorg.buildout/branches/beta.zope.org/var/
  A   zopeorg.buildout/branches/beta.zope.org/var/README.txt

-=-
Added: zopeorg.buildout/branches/beta.zope.org/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,173 @@
+================================
+Plone 4 buildout for developers
+================================
+
+.. contents ::
+
+Introduction
+------------
+
+`Buildout <http://www.buildout.org>`_ is a tool which automatically downloads, installs and configures Python software.
+Plone developers prefer uses buildout based installation method - it makes it easy to work with source code and developing your own Plone add-ons.
+
+For production site installations please use `standard Plone installer <http://plone.org/download>`_.
+
+Prerequisitements
+-----------------
+
+What you need in order to use developer buildout with Plone 4
+
+* Experience using command line tools
+
+* Experience using a text editor to work with configuration files (``buildout.cfg``)
+
+* GCC compiler suite to build native Python extensions (Zope contains C code for optimized parts)
+
+* Python 2.6 (other versions are *not* ok for Plone 4)
+
+* Python Imaging Library installed for your Python interpreter (more below)
+
+* Python `Distribute <http://pypi.python.org/pypi/distribute>`_ installation tool, provided by your operating system
+  or installed by hand
+
+Read below from operating system specific instructions how to install these dependencies.
+
+Features
+--------
+
+This buildout provides
+
+* Zope start up scripts (one instance)
+
+* ``paster`` command for creating Plone add-ons (different from system-wide installation)
+
+* `test <http://plone.org/documentation/manual/plone-community-developer-documentation/testing-and-debugging/unit-testing>`_ command for running automatic test suites 
+
+* `i18ndude <http://pypi.python.org/pypi/i18ndude>`_  for managing text string translations in Python source code 
+
+* `omelette <http://pypi.python.org/pypi/collective.recipe.omelette>`_ buildout recipe which makes Python egg source code more browseable by using symlinks
+
+* `mr.developer <http://pypi.python.org/pypi/mr.developer>`_ command for managing source code checkouts and updates with buildout repeatable manner
+
+* `collective.developermanual <http://plone.org/documentation/manual/plone-community-developer-documentation>`_ - community managed developer manual for Plone
+  in source code form, ready for contributions
+
+Creating Plone 4 buildout installation
+------------------------------------------
+
+Install ZopeSkel template package for your system-wide Python using Distribute::
+
+ easy_install ZopeSkel
+ 
+... or upgrade existing installation::
+
+ easy_install -U ZopeSkel
+
+You probably got here by running something like (replace *myplonefoldername* with the target folder where you want to Plone to be installed)::
+
+ zopeskel plone4_buildout myplonefoldername
+
+Now, you need to run (please see remarks regarding your operating system below)::
+
+ python bootstrap.py
+
+This will create ``bin`` folder and ``bin/buildout`` script. If you any time want to change Python interpreter
+associated with buildout, or you need to update ``buildout`` script itself to newer version please rerun ``bootsrap.py``.
+
+Now you can run buildout script which will download all Python packages
+(.egg files) and create ``parts/`` and ``var/`` folder structure ::
+
+  bin/buildout
+
+If this succesfully completes you can start buildout in foreground mode (Press *CTRL+C* to terminate)::
+
+  bin/instance fg 
+
+Now you can login to your site
+
+  http://localhost:8080
+
+The default user is ``admin`` with password ``admin``. 
+After initial start-up admin password is stored in Data.fs databse file and value in ``buildout.cfg`` is ignored.
+Please follow `these instructions to change admin password <http://manage.plone.org/documentation/kb/changing-the-admin-password>`_.
+
+Next steps
+----------
+
+Creating your first add-on
+==========================
+
+Plone 4 buildout comes with ``bin/paster`` command for creating Plone add-ons.
+
+.. note ::
+
+	When working with Plone add-ons, use paster command from buildout bin folder, not the system wide paster command.
+
+Create theme (applies for Plone 4 also)::
+	
+	bin/zopeskel plone3_theme plonetheme.mythemeid
+	
+Create Archetypes based content types package::
+
+	bin/zopeskel archetype mycompanyid.content
+
+Create other Plone customizations::
+
+	bin/zopeskel plone mycompanyid.mypackageid
+
+More info
+
+* `Instructions how to use Paster command to create your own add-ons <http://collective-docs.plone.org/tutorials/paste.html>`_ 
+
+Managing source code checkouts with buildout
+=============================================
+
+`mr.developer buildout extension <http://pypi.python.org/pypi/mr.developer>`_ command which can be used with buildout to manage your source code repositories
+*mr.developer* makes source code checkout from multiple repositores a repeatable task.
+
+Operating system specific instructions 
+-------------------------------------------
+
+Ubuntu/Debian
+==============
+
+Tested for Ubuntu 10.10.
+
+Install prerequisitements::
+
+	sudo apt-get install python2.6 python-imaging wget build-essential python2.6-dev python-setuptools
+	easy_install ZopeSkel
+
+OSX
+====
+
+Install `OSX development tools (XCode) <http://developer.apple.com/>`_ from Apple.
+
+Install `Macports <http://www.macports.org/>`_.
+
+Then the following installs dependencies::
+
+	sudo port install python26 py26-pil py26-distribute wget 
+	easy_install ZopeSkel
+
+When you run ``bootstrap.py``use the following command to make sure you are using Python interpreter from Macports::
+
+	python2.6 bootstrap.py
+
+Windows
+========
+
+Microsoft Windows systems is problematic because
+it does not provide to Microsoft Visual C compiler (commercial) which is
+required to build native Python extensions.
+
+Please read
+
+* http://plone.org/documentation/kb/using-buildout-on-windows
+
+Other
+-----
+
+The orignal copy of these instructions is available at
+
+* https://svn.plone.org/svn/collective/ZopeSkel/trunk/zopeskel/templates/plone4_buildout/README.txt

Added: zopeorg.buildout/branches/beta.zope.org/bin/activate
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/activate	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/activate	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,72 @@
+# This file must be used with "source bin/activate" *from bash*
+# you cannot run it directly
+
+deactivate () {
+    # reset old environment variables
+    if [ -n "$_OLD_VIRTUAL_PATH" ] ; then
+        PATH="$_OLD_VIRTUAL_PATH"
+        export PATH
+        unset _OLD_VIRTUAL_PATH
+    fi
+    if [ -n "$_OLD_VIRTUAL_PYTHONHOME" ] ; then
+        PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
+        export PYTHONHOME
+        unset _OLD_VIRTUAL_PYTHONHOME
+    fi
+
+    # This should detect bash and zsh, which have a hash command that must
+    # be called to get it to forget past commands.  Without forgetting
+    # past commands the $PATH changes we made may not be respected
+    if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
+        hash -r
+    fi
+
+    if [ -n "$_OLD_VIRTUAL_PS1" ] ; then
+        PS1="$_OLD_VIRTUAL_PS1"
+        export PS1
+        unset _OLD_VIRTUAL_PS1
+    fi
+
+    unset VIRTUAL_ENV
+    if [ ! "$1" = "nondestructive" ] ; then
+    # Self destruct!
+        unset -f deactivate
+    fi
+}
+
+# unset irrelavent variables
+deactivate nondestructive
+
+VIRTUAL_ENV="/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org"
+export VIRTUAL_ENV
+
+_OLD_VIRTUAL_PATH="$PATH"
+PATH="$VIRTUAL_ENV/bin:$PATH"
+export PATH
+
+# unset PYTHONHOME if set
+# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
+# could use `if (set -u; : $PYTHONHOME) ;` in bash
+if [ -n "$PYTHONHOME" ] ; then
+    _OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
+    unset PYTHONHOME
+fi
+
+if [ -z "$VIRTUAL_ENV_DISABLE_PROMPT" ] ; then
+    _OLD_VIRTUAL_PS1="$PS1"
+    if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
+        # special case for Aspen magic directories
+        # see http://www.zetadev.com/software/aspen/
+        PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
+    else
+        PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
+    fi
+    export PS1
+fi
+
+# This should detect bash and zsh, which have a hash command that must
+# be called to get it to forget past commands.  Without forgetting
+# past commands the $PATH changes we made may not be respected
+if [ -n "$BASH" -o -n "$ZSH_VERSION" ] ; then
+    hash -r
+fi

Added: zopeorg.buildout/branches/beta.zope.org/bin/activate_this.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/activate_this.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/activate_this.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+"""By using execfile(this_file, dict(__file__=this_file)) you will
+activate this virtualenv environment.
+
+This can be used when you must use an existing Python interpreter, not
+the virtualenv bin/python
+"""
+
+try:
+    __file__
+except NameError:
+    raise AssertionError(
+        "You must run this like execfile('path/to/active_this.py', dict(__file__='path/to/activate_this.py'))")
+import sys
+import os
+
+base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+if sys.platform == 'win32':
+    site_packages = os.path.join(base, 'Lib', 'site-packages')
+else:
+    site_packages = os.path.join(base, 'lib', 'python%s' % sys.version[:3], 'site-packages')
+prev_sys_path = list(sys.path)
+import site
+site.addsitedir(site_packages)
+sys.real_prefix = sys.prefix
+sys.prefix = base
+# Move the added items to the front of the path:
+new_sys_path = []
+for item in list(sys.path):
+    if item not in prev_sys_path:
+        new_sys_path.append(item)
+        sys.path.remove(item)
+sys.path[:0] = new_sys_path

Added: zopeorg.buildout/branches/beta.zope.org/bin/cheetah
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/cheetah	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/cheetah	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-SCRIPT: 'Cheetah==2.2.1','cheetah'
+__requires__ = 'Cheetah==2.2.1'
+import pkg_resources
+pkg_resources.run_script('Cheetah==2.2.1', 'cheetah')


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/cheetah
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/cheetah-compile
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/cheetah-compile	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/cheetah-compile	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-SCRIPT: 'Cheetah==2.2.1','cheetah-compile'
+__requires__ = 'Cheetah==2.2.1'
+import pkg_resources
+pkg_resources.run_script('Cheetah==2.2.1', 'cheetah-compile')


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/cheetah-compile
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/easy_install
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/easy_install	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/easy_install	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==0.6c11','console_scripts','easy_install'
+__requires__ = 'setuptools==0.6c11'
+import sys
+from pkg_resources import load_entry_point
+
+sys.exit(
+   load_entry_point('setuptools==0.6c11', 'console_scripts', 'easy_install')()
+)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/easy_install
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/easy_install-2.6
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/easy_install-2.6	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/easy_install-2.6	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-ENTRY-SCRIPT: 'setuptools==0.6c11','console_scripts','easy_install-2.6'
+__requires__ = 'setuptools==0.6c11'
+import sys
+from pkg_resources import load_entry_point
+
+sys.exit(
+   load_entry_point('setuptools==0.6c11', 'console_scripts', 'easy_install-2.6')()
+)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/easy_install-2.6
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/paster
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/paster	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/paster	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-ENTRY-SCRIPT: 'PasteScript==1.7.3','console_scripts','paster'
+__requires__ = 'PasteScript==1.7.3'
+import sys
+from pkg_resources import load_entry_point
+
+sys.exit(
+   load_entry_point('PasteScript==1.7.3', 'console_scripts', 'paster')()
+)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/paster
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/pip
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/pip	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/pip	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-ENTRY-SCRIPT: 'pip==0.7.2','console_scripts','pip'
+__requires__ = 'pip==0.7.2'
+import sys
+from pkg_resources import load_entry_point
+
+sys.exit(
+   load_entry_point('pip==0.7.2', 'console_scripts', 'pip')()
+)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/pip
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bin/python
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/python
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/bin/zopeskel
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bin/zopeskel	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bin/zopeskel	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+# EASY-INSTALL-ENTRY-SCRIPT: 'ZopeSkel==2.19','console_scripts','zopeskel'
+__requires__ = 'ZopeSkel==2.19'
+import sys
+from pkg_resources import load_entry_point
+
+sys.exit(
+   load_entry_point('ZopeSkel==2.19', 'console_scripts', 'zopeskel')()
+)


Property changes on: zopeorg.buildout/branches/beta.zope.org/bin/zopeskel
___________________________________________________________________
Added: svn:executable
   + *

Added: zopeorg.buildout/branches/beta.zope.org/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,120 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os
+import shutil
+import sys
+import tempfile
+import urllib2
+from optparse import OptionParser
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+# parsing arguments
+parser = OptionParser()
+parser.add_option("-v", "--version", dest="version",
+                          help="use a specific zc.buildout version")
+parser.add_option("-d", "--distribute",
+                   action="store_true", dest="distribute", default=False,
+                   help="Use Disribute rather than Setuptools.")
+
+parser.add_option("-c", None, action="store", dest="config_file",
+                   help=("Specify the path to the buildout configuration "
+                         "file to be used."))
+
+options, args = parser.parse_args()
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args += ['-c', options.config_file]
+
+if options.version is not None:
+    VERSION = '==%s' % options.version
+else:
+    VERSION = ''
+
+# We decided to always use distribute, make sure this is the default for us
+# USE_DISTRIBUTE = options.distribute
+USE_DISTRIBUTE = True
+args = args + ['bootstrap']
+
+to_reload = False
+try:
+    import pkg_resources
+    if not hasattr(pkg_resources, '_distribute'):
+        to_reload = True
+        raise ImportError
+except ImportError:
+    ez = {}
+    if USE_DISTRIBUTE:
+        setup_url = 'http://python-distribute.org/distribute_setup.py'
+        exec urllib2.urlopen(setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
+    else:
+        ez_setup_url = 'http://peak.telecommunity.com/dist/ez_setup.py'
+        exec urllib2.urlopen(ez_setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    if to_reload:
+        reload(pkg_resources)
+    else:
+        import pkg_resources
+
+
+def quote(c):
+    if sys.platform == 'win32':
+        if ' ' in c:
+            return '"%s"' % c  # work around spawn lamosity on windows
+    return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws = pkg_resources.working_set
+
+if USE_DISTRIBUTE:
+    requirement = 'distribute'
+else:
+    requirement = 'setuptools'
+
+pythonpath = ws.find(pkg_resources.Requirement.parse(requirement)).location
+
+if is_jython:
+    import subprocess
+
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+           quote(tmpeggs), 'zc.buildout' + VERSION],
+           env=dict(os.environ,
+               PYTHONPATH=pythonpath),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote(sys.executable),
+        '-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION,
+        dict(os.environ,
+            PYTHONPATH=pythonpath),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout' + VERSION)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/buildout.cfg
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/buildout.cfg	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/buildout.cfg	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,101 @@
+# buildout.cfg file for Plone 4 development work
+# - for production installations please use http://plone.org/download
+# Each part has more information about its recipe on PyPi
+# http://pypi.python.org/pypi 
+# ... just reach by the recipe name
+[buildout]
+parts =  
+    instance
+    zopepy
+    i18ndude
+    zopeskel
+    test
+#    omelette
+
+extends = 
+    http://dist.plone.org/release/4.0.5/versions.cfg
+	
+# Add additional egg download sources here. dist.plone.org contains archives
+# of Plone packages.
+find-links =
+    http://dist.plone.org/release/4.0.5
+    http://dist.plone.org/thirdparty
+
+extensions = 
+    mr.developer
+    buildout.dumppickedversions
+    buildout.threatlevel
+
+sources = sources
+	
+versions = versions
+
+# Reference any folders where you have Python egg source code under development here 
+# e.g.: develop = src/my.package
+# If you are using the mr.developer extension and have the source code in a 
+# repository mr.developer will handle this automatically for you
+develop =
+
+
+# Create bin/instance command to manage Zope start up and shutdown
+[instance]
+recipe = plone.recipe.zope2instance
+user = admin:admin
+http-address = 8080
+debug-mode = off
+verbose-security = on
+blob-storage = var/blobstorage
+
+eggs =
+	Plone
+
+# Some pre-Plone 3.3 packages may need you to register the package name here in 
+# order their configure.zcml to be run (http://plone.org/products/plone/roadmap/247)
+# - this is never required for packages in the Products namespace (Products.*)
+zcml =
+
+
+# zopepy commands allows you to execute Python scripts using a PYTHONPATH 
+# including all the configured eggs
+[zopepy]
+recipe = zc.recipe.egg
+eggs = ${instance:eggs}
+interpreter = zopepy
+scripts = zopepy
+
+# create bin/i18ndude command
+[i18ndude]
+unzip = true
+recipe = zc.recipe.egg
+eggs = i18ndude
+
+# create bin/test command
+[test]
+recipe = zc.recipe.testrunner
+defaults = ['--auto-color', '--auto-progress']
+eggs =
+    ${instance:eggs}
+
+# create ZopeSkel command
+[zopeskel]
+unzip = true
+recipe = zc.recipe.egg
+eggs =
+    ZopeSkel
+    ${instance:eggs}
+
+# symlinks all Python source code to parts/omelette folder when buildout is run
+# windows users will need to install additional software for this part to build 
+# correctly.  See http://pypi.python.org/pypi/collective.recipe.omelette for
+# relevant details.
+# [omelette]
+# recipe = collective.recipe.omelette
+# eggs = ${instance:eggs}
+
+# Put your mr.developer managed source code repositories here, see
+# http://pypi.python.org/pypi/mr.developer for details on format for this part
+[sources]
+collective.developermanual = svn http://svn.plone.org/svn/collective/collective.developermanual
+
+# Version pindowns for new style products go here - this section extends one provided in http://dist.plone.org/release/
+[versions]

Added: zopeorg.buildout/branches/beta.zope.org/include/python2.6
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/include/python2.6	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/include/python2.6	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/include/python2.6
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/include/python2.6
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/UserDict.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/UserDict.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/UserDict.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/UserDict.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/UserDict.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/_abcoll.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/_abcoll.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/_abcoll.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/_abcoll.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/_abcoll.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/abc.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/abc.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/abc.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/abc.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/abc.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/codecs.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/codecs.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/codecs.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/codecs.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/codecs.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/config
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/config	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/config	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/config
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/config
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/copy_reg.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/copy_reg.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/copy_reg.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/copy_reg.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/copy_reg.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,87 @@
+import os
+import sys
+import warnings 
+import ConfigParser # ConfigParser is not a virtualenv module, so we can use it to find the stdlib
+
+dirname = os.path.dirname
+
+distutils_path = os.path.join(os.path.dirname(ConfigParser.__file__), 'distutils')
+if os.path.normpath(distutils_path) == os.path.dirname(os.path.normpath(__file__)):
+    warnings.warn(
+        "The virtualenv distutils package at %s appears to be in the same location as the system distutils?")
+else:
+    __path__.insert(0, distutils_path)
+    exec open(os.path.join(distutils_path, '__init__.py')).read()
+
+import dist
+import sysconfig
+
+
+## patch build_ext (distutils doesn't know how to get the libs directory
+## path on windows - it hardcodes the paths around the patched sys.prefix)
+
+if sys.platform == 'win32':
+    from distutils.command.build_ext import build_ext as old_build_ext
+    class build_ext(old_build_ext):
+        def finalize_options (self):
+            if self.library_dirs is None:
+                self.library_dirs = []
+            
+            self.library_dirs.insert(0, os.path.join(sys.real_prefix, "Libs"))
+            old_build_ext.finalize_options(self)
+            
+    from distutils.command import build_ext as build_ext_module 
+    build_ext_module.build_ext = build_ext
+
+## distutils.dist patches:
+
+old_find_config_files = dist.Distribution.find_config_files
+def find_config_files(self):
+    found = old_find_config_files(self)
+    system_distutils = os.path.join(distutils_path, 'distutils.cfg')
+    #if os.path.exists(system_distutils):
+    #    found.insert(0, system_distutils)
+        # What to call the per-user config file
+    if os.name == 'posix':
+        user_filename = ".pydistutils.cfg"
+    else:
+        user_filename = "pydistutils.cfg"
+    user_filename = os.path.join(sys.prefix, user_filename)
+    if os.path.isfile(user_filename):
+        for item in list(found):
+            if item.endswith('pydistutils.cfg'):
+                found.remove(item)
+        found.append(user_filename)
+    return found
+dist.Distribution.find_config_files = find_config_files
+
+## distutils.sysconfig patches:
+
+old_get_python_inc = sysconfig.get_python_inc
+def sysconfig_get_python_inc(plat_specific=0, prefix=None):
+    if prefix is None:
+        prefix = sys.real_prefix
+    return old_get_python_inc(plat_specific, prefix)
+sysconfig_get_python_inc.__doc__ = old_get_python_inc.__doc__
+sysconfig.get_python_inc = sysconfig_get_python_inc
+
+old_get_python_lib = sysconfig.get_python_lib
+def sysconfig_get_python_lib(plat_specific=0, standard_lib=0, prefix=None):
+    if standard_lib and prefix is None:
+        prefix = sys.real_prefix
+    return old_get_python_lib(plat_specific, standard_lib, prefix)
+sysconfig_get_python_lib.__doc__ = old_get_python_lib.__doc__
+sysconfig.get_python_lib = sysconfig_get_python_lib
+
+old_get_config_vars = sysconfig.get_config_vars
+def sysconfig_get_config_vars(*args):
+    real_vars = old_get_config_vars(*args)
+    if sys.platform == 'win32':
+        lib_dir = os.path.join(sys.real_prefix, "libs")
+        if isinstance(real_vars, dict) and 'LIBDIR' not in real_vars:
+            real_vars['LIBDIR'] = lib_dir # asked for all
+        elif isinstance(real_vars, list) and 'LIBDIR' in args:
+            real_vars = real_vars + [lib_dir] # asked for list
+    return real_vars
+sysconfig_get_config_vars.__doc__ = old_get_config_vars.__doc__
+sysconfig.get_config_vars = sysconfig_get_config_vars

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/distutils.cfg
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/distutils.cfg	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/distutils/distutils.cfg	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# This is a config file local to this virtualenv installation
+# You may include options that will be used by all distutils commands,
+# and by easy_install.  For instance:
+#
+#   [easy_install]
+#   find_links = http://mylocalsite

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/encodings
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/encodings	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/encodings	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/encodings
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/encodings
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/fnmatch.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/fnmatch.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/fnmatch.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/fnmatch.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/fnmatch.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/genericpath.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/genericpath.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/genericpath.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/genericpath.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/genericpath.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/lib-dynload
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/lib-dynload	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/lib-dynload	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/lib-dynload
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/lib-dynload
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/linecache.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/linecache.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/linecache.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/linecache.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/linecache.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/locale.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/locale.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/locale.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/locale.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/locale.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/ntpath.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/ntpath.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/ntpath.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/ntpath.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/ntpath.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/orig-prefix.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/orig-prefix.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/orig-prefix.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+/opt/python-2.6.4
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/os.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/os.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/os.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/os.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/os.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/posixpath.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/posixpath.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/posixpath.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/posixpath.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/posixpath.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/re.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/re.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/re.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/re.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/re.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheRegion.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheRegion.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheRegion.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,136 @@
+# $Id: CacheRegion.py,v 1.3 2006/01/28 04:19:30 tavis_rudd Exp $
+'''
+Cache holder classes for Cheetah:
+
+Cache regions are defined using the #cache Cheetah directive. Each
+cache region can be viewed as a dictionary (keyed by cacheRegionID)
+handling at least one cache item (the default one). It's possible to add
+cacheItems in a region by using the `varyBy` #cache directive parameter as
+in the following example::
+   #def getArticle
+      this is the article content.
+   #end def
+
+   #cache varyBy=$getArticleID()
+      $getArticle($getArticleID())
+   #end cache
+
+The code above will generate a CacheRegion and add new cacheItem for each value
+of $getArticleID().
+'''
+
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+
+import time
+import Cheetah.CacheStore
+
+class CacheItem(object):
+    '''
+    A CacheItem is a container storing:
+
+        - cacheID (string)
+        - refreshTime (timestamp or None) : last time the cache was refreshed
+        - data (string) : the content of the cache
+    '''
+    
+    def __init__(self, cacheItemID, cacheStore):
+        self._cacheItemID = cacheItemID
+        self._cacheStore = cacheStore
+        self._refreshTime = None
+        self._expiryTime = 0
+
+    def hasExpired(self):
+        return (self._expiryTime and time.time() > self._expiryTime)
+    
+    def setExpiryTime(self, time):
+        self._expiryTime = time
+
+    def getExpiryTime(self):
+        return self._expiryTime
+
+    def setData(self, data):
+        self._refreshTime = time.time()
+        self._cacheStore.set(self._cacheItemID, data, self._expiryTime)
+
+    def getRefreshTime(self):
+        return self._refreshTime
+
+    def getData(self):
+        assert self._refreshTime
+        return self._cacheStore.get(self._cacheItemID)
+
+    def renderOutput(self):
+        """Can be overridden to implement edge-caching"""
+        return self.getData() or ""
+
+    def clear(self):
+        self._cacheStore.delete(self._cacheItemID)
+        self._refreshTime = None
+
+class _CacheDataStoreWrapper(object):
+    def __init__(self, dataStore, keyPrefix):
+        self._dataStore = dataStore
+        self._keyPrefix = keyPrefix
+        
+    def get(self, key):
+        return self._dataStore.get(self._keyPrefix+key)
+
+    def delete(self, key):
+        self._dataStore.delete(self._keyPrefix+key)
+
+    def set(self, key, val, time=0):        
+        self._dataStore.set(self._keyPrefix+key, val, time=time)
+
+class CacheRegion(object):
+    '''
+    A `CacheRegion` stores some `CacheItem` instances.
+
+    This implementation stores the data in the memory of the current process.
+    If you need a more advanced data store, create a cacheStore class that works
+    with Cheetah's CacheStore protocol and provide it as the cacheStore argument
+    to __init__.  For example you could use
+    Cheetah.CacheStore.MemcachedCacheStore, a wrapper around the Python
+    memcached API (http://www.danga.com/memcached).
+    '''
+    _cacheItemClass = CacheItem
+    
+    def __init__(self, regionID, templateCacheIdPrefix='', cacheStore=None):
+        self._isNew = True
+        self._regionID = regionID
+        self._templateCacheIdPrefix = templateCacheIdPrefix
+        if not cacheStore:
+            cacheStore = Cheetah.CacheStore.MemoryCacheStore()
+        self._cacheStore = cacheStore
+        self._wrappedCacheDataStore = _CacheDataStoreWrapper(
+            cacheStore, keyPrefix=templateCacheIdPrefix+':'+regionID+':')
+        self._cacheItems = {}
+
+    def isNew(self):
+        return self._isNew
+        
+    def clear(self):
+        " drop all the caches stored in this cache region "
+        for cacheItemId in self._cacheItems.keys():
+            cacheItem = self._cacheItems[cacheItemId]
+            cacheItem.clear()
+            del self._cacheItems[cacheItemId]
+        
+    def getCacheItem(self, cacheItemID):
+        """ Lazy access to a cacheItem
+
+            Try to find a cache in the stored caches. If it doesn't
+            exist, it's created.
+            
+            Returns a `CacheItem` instance.
+        """
+        cacheItemID = md5(str(cacheItemID)).hexdigest()
+        
+        if not self._cacheItems.has_key(cacheItemID):
+            cacheItem = self._cacheItemClass(
+                cacheItemID=cacheItemID, cacheStore=self._wrappedCacheDataStore)
+            self._cacheItems[cacheItemID] = cacheItem
+            self._isNew = False
+        return self._cacheItems[cacheItemID]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheStore.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheStore.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CacheStore.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,108 @@
+'''
+Provides several CacheStore backends for Cheetah's caching framework.  The
+methods provided by these classes have the same semantics as those in the
+python-memcached API, except for their return values:
+
+set(key, val, time=0)
+  set the value unconditionally
+add(key, val, time=0)
+  set only if the server doesn't already have this key
+replace(key, val, time=0)
+  set only if the server already have this key
+get(key, val)
+  returns val or raises a KeyError
+delete(key)
+  deletes or raises a KeyError
+'''
+import time
+
+from Cheetah.Utils.memcache import Client as MemcachedClient
+
+class Error(Exception):
+    pass
+
+class AbstractCacheStore(object):
+
+    def set(self, key, val, time=None):
+        raise NotImplementedError
+
+    def add(self, key, val, time=None):
+        raise NotImplementedError
+
+    def replace(self, key, val, time=None):
+        raise NotImplementedError
+
+    def delete(self, key):
+        raise NotImplementedError
+
+    def get(self, key):
+        raise NotImplementedError
+
+class MemoryCacheStore(AbstractCacheStore):
+    def __init__(self):
+        self._data = {}
+
+    def set(self, key, val, time=0):
+        self._data[key] = (val, time)
+
+    def add(self, key, val, time=0):
+        if self._data.has_key(key):
+            raise Error('a value for key %r is already in the cache'%key)
+        self._data[key] = (val, time)
+
+    def replace(self, key, val, time=0):
+        if self._data.has_key(key):
+            raise Error('a value for key %r is already in the cache'%key)
+        self._data[key] = (val, time)
+
+    def delete(self, key):
+        del self._data[key]
+        
+    def get(self, key):
+        (val, exptime) = self._data[key]
+        if exptime and time.time() > exptime:
+            del self._data[key]
+            raise KeyError(key)
+        else:
+            return val
+
+    def clear(self):
+        self._data.clear()        
+                  
+class MemcachedCacheStore(AbstractCacheStore):
+    servers = ('127.0.0.1:11211')
+    def __init__(self, servers=None, debug=False):
+        if servers is None:
+            servers = self.servers
+            
+        self._client = MemcachedClient(servers, debug)
+
+    def set(self, key, val, time=0):
+        self._client.set(key, val, time)
+
+    def add(self, key, val, time=0):
+        res = self._client.add(key, val, time)        
+        if not res:
+            raise Error('a value for key %r is already in the cache'%key)
+        self._data[key] = (val, time)
+
+    def replace(self, key, val, time=0):
+        res = self._client.replace(key, val, time)        
+        if not res:
+            raise Error('a value for key %r is already in the cache'%key)
+        self._data[key] = (val, time)
+
+    def delete(self, key):
+        res = self._client.delete(key, time=0)        
+        if not res:
+            raise KeyError(key)
+        
+    def get(self, key):
+        val = self._client.get(key)
+        if val is None:
+            raise KeyError(key)
+        else:
+            return val
+
+    def clear(self):
+        self._client.flush_all()        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CheetahWrapper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CheetahWrapper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/CheetahWrapper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,610 @@
+#!/usr/bin/env python
+# $Id: CheetahWrapper.py,v 1.26 2007/10/02 01:22:04 tavis_rudd Exp $
+"""Cheetah command-line interface.
+
+2002-09-03 MSO: Total rewrite.
+2002-09-04 MSO: Bugfix, compile command was using wrong output ext.
+2002-11-08 MSO: Another rewrite.
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com> and Mike Orr <sluggoster at gmail.com>>
+Version: $Revision: 1.26 $
+Start Date: 2001/03/30
+Last Revision Date: $Date: 2007/10/02 01:22:04 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com> and Mike Orr <sluggoster at gmail.com>"
+__revision__ = "$Revision: 1.26 $"[11:-2]
+
+import getopt, glob, os, pprint, re, shutil, sys
+import cPickle as pickle
+from optparse import OptionParser
+
+from Cheetah.Version import Version
+from Cheetah.Template import Template, DEFAULT_COMPILER_SETTINGS
+from Cheetah.Utils.Misc import mkdirsWithPyInitFiles
+
+optionDashesRE = re.compile(  R"^-{1,2}"  )
+moduleNameRE = re.compile(  R"^[a-zA-Z_][a-zA-Z_0-9]*$"  )
+   
+def fprintfMessage(stream, format, *args):
+    if format[-1:] == '^':
+        format = format[:-1]
+    else:
+        format += '\n'
+    if args:
+        message = format % args
+    else:
+        message = format
+    stream.write(message)
+
+class Error(Exception):
+    pass
+
+
+class Bundle:
+    """Wrap the source, destination and backup paths in one neat little class.
+       Used by CheetahWrapper.getBundles().
+    """
+    def __init__(self, **kw):
+        self.__dict__.update(kw)
+
+    def __repr__(self):
+        return "<Bundle %r>" % self.__dict__
+
+
+##################################################
+## USAGE FUNCTION & MESSAGES
+
+def usage(usageMessage, errorMessage="", out=sys.stderr):
+    """Write help text, an optional error message, and abort the program.
+    """
+    out.write(WRAPPER_TOP)
+    out.write(usageMessage)
+    exitStatus = 0
+    if errorMessage:
+        out.write('\n')
+        out.write("*** USAGE ERROR ***: %s\n" % errorMessage)
+        exitStatus = 1
+    sys.exit(exitStatus)
+             
+
+WRAPPER_TOP = """\
+         __  ____________  __
+         \ \/            \/ /
+          \/    *   *     \/    CHEETAH %(Version)s Command-Line Tool
+           \      |       / 
+            \  ==----==  /      by Tavis Rudd <tavis at damnsimple.com>
+             \__________/       and Mike Orr <sluggoster at gmail.com>
+              
+""" % globals()
+
+
+HELP_PAGE1 = """\
+USAGE:
+------
+  cheetah compile [options] [FILES ...]     : Compile template definitions
+  cheetah fill [options] [FILES ...]        : Fill template definitions
+  cheetah help                              : Print this help message
+  cheetah options                           : Print options help message
+  cheetah test [options]                    : Run Cheetah's regression tests
+                                            : (same as for unittest)
+  cheetah version                           : Print Cheetah version number
+
+You may abbreviate the command to the first letter; e.g., 'h' == 'help'.
+If FILES is a single "-", read standard input and write standard output.
+Run "cheetah options" for the list of valid options.
+"""
+
+##################################################
+## CheetahWrapper CLASS
+
+class CheetahWrapper(object):
+    MAKE_BACKUPS = True
+    BACKUP_SUFFIX = ".bak"
+    _templateClass = None
+    _compilerSettings = None    
+
+    def __init__(self):
+        self.progName = None
+        self.command = None
+        self.opts = None
+        self.pathArgs = None
+        self.sourceFiles = []
+        self.searchList = []
+        self.parser = None
+
+    ##################################################
+    ## MAIN ROUTINE
+
+    def main(self, argv=None):
+        """The main program controller."""
+
+        if argv is None:
+            argv = sys.argv
+
+        # Step 1: Determine the command and arguments.
+        try:
+            self.progName = progName = os.path.basename(argv[0])
+            self.command = command = optionDashesRE.sub("", argv[1])
+            if command == 'test':
+                self.testOpts = argv[2:]
+            else:
+                self.parseOpts(argv[2:])
+        except IndexError:
+            usage(HELP_PAGE1, "not enough command-line arguments")
+
+        # Step 2: Call the command
+        meths = (self.compile, self.fill, self.help, self.options,
+            self.test, self.version)
+        for meth in meths:
+            methName = meth.__name__
+            # Or meth.im_func.func_name
+            # Or meth.func_name (Python >= 2.1 only, sometimes works on 2.0)
+            methInitial = methName[0]
+            if command in (methName, methInitial):
+                sys.argv[0] += (" " + methName)
+                # @@MO: I don't necessarily agree sys.argv[0] should be 
+                # modified.
+                meth()
+                return
+        # If none of the commands matched.
+        usage(HELP_PAGE1, "unknown command '%s'" % command)
+
+    def parseOpts(self, args):
+        C, D, W = self.chatter, self.debug, self.warn
+        self.isCompile = isCompile = self.command[0] == 'c'
+        defaultOext = isCompile and ".py" or ".html"
+        self.parser = OptionParser()
+        pao = self.parser.add_option
+        pao("--idir", action="store", dest="idir", default='', help='Input directory (defaults to current directory)')
+        pao("--odir", action="store", dest="odir", default="", help='Output directory (defaults to current directory)')
+        pao("--iext", action="store", dest="iext", default=".tmpl", help='File input extension (defaults: compile: .tmpl, fill: .tmpl)')
+        pao("--oext", action="store", dest="oext", default=defaultOext, help='File output extension (defaults: compile: .py, fill: .html)')
+        pao("-R", action="store_true", dest="recurse", default=False, help='Recurse through subdirectories looking for input files')
+        pao("--stdout", "-p", action="store_true", dest="stdout", default=False, help='Verbosely print informational messages to stdout')
+        pao("--debug", action="store_true", dest="debug", default=False, help='Print diagnostic/debug information to stderr')
+        pao("--env", action="store_true", dest="env", default=False, help='Pass the environment into the search list')
+        pao("--pickle", action="store", dest="pickle", default="", help='Unpickle FILE and pass it through in the search list')
+        pao("--flat", action="store_true", dest="flat", default=False, help='Do not build destination subdirectories')
+        pao("--nobackup", action="store_true", dest="nobackup", default=False, help='Do not make backup files when generating new ones')
+        pao("--settings", action="store", dest="compilerSettingsString", default=None, help='String of compiler settings to pass through, e.g. --settings="useNameMapper=False,useFilters=False"')
+        pao('--print-settings', action='store_true', dest='print_settings', help='Print out the list of available compiler settings')
+        pao("--templateAPIClass", action="store", dest="templateClassName", default=None, help='Name of a subclass of Cheetah.Template.Template to use for compilation, e.g. MyTemplateClass')
+        pao("--parallel", action="store", type="int", dest="parallel", default=1, help='Compile/fill templates in parallel, e.g. --parallel=4')
+        pao('--shbang', dest='shbang', default='#!/usr/bin/env python', help='Specify the shbang to place at the top of compiled templates, e.g. --shbang="#!/usr/bin/python2.6"')
+
+        self.opts, self.pathArgs = opts, files = self.parser.parse_args(args)
+        D("""\
+cheetah compile %s
+Options are
+%s
+Files are %s""", args, pprint.pformat(vars(opts)), files)
+
+
+        if opts.print_settings:
+            print 
+            print '>> Available Cheetah compiler settings:'
+            from Cheetah.Compiler import _DEFAULT_COMPILER_SETTINGS
+            listing = _DEFAULT_COMPILER_SETTINGS
+            listing.sort(key=lambda l: l[0][0].lower())
+
+            for l in listing:
+                print '\t%s (default: "%s")\t%s' % l
+            sys.exit(0)
+
+        #cleanup trailing path separators
+        seps = [sep for sep in [os.sep, os.altsep] if sep]
+        for attr in ['idir', 'odir']:
+            for sep in seps:
+                path = getattr(opts, attr, None)
+                if path and path.endswith(sep):
+                    path = path[:-len(sep)]
+                    setattr(opts, attr, path)
+                    break
+
+        self._fixExts()
+        if opts.env:
+            self.searchList.insert(0, os.environ)
+        if opts.pickle:
+            f = open(opts.pickle, 'rb')
+            unpickled = pickle.load(f)
+            f.close()
+            self.searchList.insert(0, unpickled)
+        opts.verbose = not opts.stdout
+
+    ##################################################
+    ## COMMAND METHODS
+
+    def compile(self):
+        self._compileOrFill()
+
+    def fill(self):
+        from Cheetah.ImportHooks import install
+        install()        
+        self._compileOrFill()
+
+    def help(self):
+        usage(HELP_PAGE1, "", sys.stdout)
+
+    def options(self):
+        return self.parser.print_help()
+
+    def test(self):
+        # @@MO: Ugly kludge.
+        TEST_WRITE_FILENAME = 'cheetah_test_file_creation_ability.tmp'
+        try:
+            f = open(TEST_WRITE_FILENAME, 'w')
+        except:
+            sys.exit("""\
+Cannot run the tests because you don't have write permission in the current
+directory.  The tests need to create temporary files.  Change to a directory
+you do have write permission to and re-run the tests.""")
+        else:
+            f.close()
+            os.remove(TEST_WRITE_FILENAME)
+        # @@MO: End ugly kludge.
+        from Cheetah.Tests import Test
+        import Cheetah.Tests.unittest_local_copy as unittest
+        del sys.argv[1:] # Prevent unittest from misinterpreting options.
+        sys.argv.extend(self.testOpts)
+        #unittest.main(testSuite=Test.testSuite)
+        #unittest.main(testSuite=Test.testSuite)
+        unittest.main(module=Test)
+        
+    def version(self):
+        print Version
+
+    # If you add a command, also add it to the 'meths' variable in main().
+    
+    ##################################################
+    ## LOGGING METHODS
+
+    def chatter(self, format, *args):
+        """Print a verbose message to stdout.  But don't if .opts.stdout is
+           true or .opts.verbose is false.
+        """
+        if self.opts.stdout or not self.opts.verbose:
+            return
+        fprintfMessage(sys.stdout, format, *args)
+
+
+    def debug(self, format, *args):
+        """Print a debugging message to stderr, but don't if .debug is
+           false.
+        """
+        if self.opts.debug:
+            fprintfMessage(sys.stderr, format, *args)
+    
+    def warn(self, format, *args):
+        """Always print a warning message to stderr.
+        """
+        fprintfMessage(sys.stderr, format, *args)
+
+    def error(self, format, *args):
+        """Always print a warning message to stderr and exit with an error code.        
+        """
+        fprintfMessage(sys.stderr, format, *args)
+        sys.exit(1)
+
+    ##################################################
+    ## HELPER METHODS
+
+
+    def _fixExts(self):
+        assert self.opts.oext, "oext is empty!"
+        iext, oext = self.opts.iext, self.opts.oext
+        if iext and not iext.startswith("."):
+            self.opts.iext = "." + iext
+        if oext and not oext.startswith("."):
+            self.opts.oext = "." + oext
+    
+
+
+    def _compileOrFill(self):
+        C, D, W = self.chatter, self.debug, self.warn
+        opts, files = self.opts, self.pathArgs
+        if files == ["-"]: 
+            self._compileOrFillStdin()
+            return
+        elif not files and opts.recurse:
+            which = opts.idir and "idir" or "current"
+            C("Drilling down recursively from %s directory.", which)
+            sourceFiles = []
+            dir = os.path.join(self.opts.idir, os.curdir)
+            os.path.walk(dir, self._expandSourceFilesWalk, sourceFiles)
+        elif not files:
+            usage(HELP_PAGE1, "Neither files nor -R specified!")
+        else:
+            sourceFiles = self._expandSourceFiles(files, opts.recurse, True)
+        sourceFiles = [os.path.normpath(x) for x in sourceFiles]
+        D("All source files found: %s", sourceFiles)
+        bundles = self._getBundles(sourceFiles)
+        D("All bundles: %s", pprint.pformat(bundles))
+        if self.opts.flat:
+            self._checkForCollisions(bundles)
+
+        # In parallel mode a new process is forked for each template
+        # compilation, out of a pool of size self.opts.parallel. This is not
+        # really optimal in all cases (e.g. probably wasteful for small
+        # templates), but seems to work well in real life for me.
+        #
+        # It also won't work for Windows users, but I'm not going to lose any
+        # sleep over that.
+        if self.opts.parallel > 1:
+            bad_child_exit = 0
+            pid_pool = set()
+
+            def child_wait():
+                pid, status = os.wait()
+                pid_pool.remove(pid)
+                return os.WEXITSTATUS(status)
+
+            while bundles:
+                b = bundles.pop()
+                pid = os.fork()
+                if pid:
+                    pid_pool.add(pid)
+                else:
+                    self._compileOrFillBundle(b)
+                    sys.exit(0)
+
+                if len(pid_pool) == self.opts.parallel:
+                    bad_child_exit = child_wait()
+                    if bad_child_exit:
+                        break
+
+            while pid_pool:
+                child_exit = child_wait()
+                if not bad_child_exit:
+                    bad_child_exit = child_exit
+
+            if bad_child_exit:
+                sys.exit("Child process failed, exited with code %d" % bad_child_exit)
+
+        else:
+            for b in bundles:
+                self._compileOrFillBundle(b)
+
+    def _checkForCollisions(self, bundles):
+        """Check for multiple source paths writing to the same destination
+           path.
+        """
+        C, D, W = self.chatter, self.debug, self.warn
+        isError = False
+        dstSources = {}
+        for b in bundles:
+            if dstSources.has_key(b.dst):
+                dstSources[b.dst].append(b.src)
+            else:
+                dstSources[b.dst] = [b.src]
+        keys = dstSources.keys()
+        keys.sort()
+        for dst in keys:
+            sources = dstSources[dst]
+            if len(sources) > 1:
+                isError = True
+                sources.sort()
+                fmt = "Collision: multiple source files %s map to one destination file %s"
+                W(fmt, sources, dst)
+        if isError:
+            what = self.isCompile and "Compilation" or "Filling"
+            sys.exit("%s aborted due to collisions" % what)
+                
+
+    def _expandSourceFilesWalk(self, arg, dir, files):
+        """Recursion extension for .expandSourceFiles().
+           This method is a callback for os.path.walk().
+           'arg' is a list to which successful paths will be appended.
+        """
+        iext = self.opts.iext
+        for f in files:
+            path = os.path.join(dir, f)
+            if   path.endswith(iext) and os.path.isfile(path):
+                arg.append(path)
+            elif os.path.islink(path) and os.path.isdir(path):
+                os.path.walk(path, self._expandSourceFilesWalk, arg)
+            # If is directory, do nothing; 'walk' will eventually get it.
+
+
+    def _expandSourceFiles(self, files, recurse, addIextIfMissing):
+        """Calculate source paths from 'files' by applying the 
+           command-line options.
+        """
+        C, D, W = self.chatter, self.debug, self.warn
+        idir = self.opts.idir
+        iext = self.opts.iext
+        files = [] 
+        for f in self.pathArgs:
+            oldFilesLen = len(files)
+            D("Expanding %s", f)
+            path = os.path.join(idir, f)
+            pathWithExt = path + iext # May or may not be valid.
+            if os.path.isdir(path):
+                if recurse:
+                    os.path.walk(path, self._expandSourceFilesWalk, files)
+                else:
+                    raise Error("source file '%s' is a directory" % path)
+            elif os.path.isfile(path):
+                files.append(path)
+            elif (addIextIfMissing and not path.endswith(iext) and 
+                  os.path.isfile(pathWithExt)):
+                files.append(pathWithExt)
+                # Do not recurse directories discovered by iext appending.
+            elif os.path.exists(path):
+                W("Skipping source file '%s', not a plain file.", path)
+            else:
+                W("Skipping source file '%s', not found.", path)
+            if len(files) > oldFilesLen:
+                D("  ... found %s", files[oldFilesLen:])
+        return files
+
+
+    def _getBundles(self, sourceFiles):
+        flat = self.opts.flat
+        idir = self.opts.idir
+        iext = self.opts.iext
+        nobackup = self.opts.nobackup
+        odir = self.opts.odir
+        oext = self.opts.oext
+        idirSlash = idir + os.sep
+        bundles = []
+        for src in sourceFiles:
+            # 'base' is the subdirectory plus basename.
+            base = src
+            if idir and src.startswith(idirSlash):
+                base = src[len(idirSlash):]
+            if iext and base.endswith(iext):
+                base = base[:-len(iext)]
+            basename = os.path.basename(base)
+            if flat:
+                dst = os.path.join(odir, basename + oext)
+            else:
+                dbn = basename
+                if odir and base.startswith(os.sep):
+                    odd = odir
+                    while odd != '':
+                        idx = base.find(odd)
+                        if idx == 0:
+                            dbn = base[len(odd):]
+                            if dbn[0] == '/':
+                                dbn = dbn[1:]
+                            break
+                        odd = os.path.dirname(odd)
+                        if odd == '/':
+                            break
+                    dst = os.path.join(odir, dbn + oext)
+                else:
+                    dst = os.path.join(odir, base + oext)
+            bak = dst + self.BACKUP_SUFFIX
+            b = Bundle(src=src, dst=dst, bak=bak, base=base, basename=basename)
+            bundles.append(b)
+        return bundles
+
+
+    def _getTemplateClass(self):
+        C, D, W = self.chatter, self.debug, self.warn
+        modname = None
+        if self._templateClass:
+            return self._templateClass
+
+        modname = self.opts.templateClassName
+
+        if not modname:
+            return Template
+        p = modname.rfind('.')
+        if ':' not in modname:
+            self.error('The value of option --templateAPIClass is invalid\n'
+                       'It must be in the form "module:class", '
+                       'e.g. "Cheetah.Template:Template"')
+            
+        modname, classname = modname.split(':')
+
+        C('using --templateAPIClass=%s:%s'%(modname, classname))
+        
+        if p >= 0:
+            mod = getattr(__import__(modname[:p], {}, {}, [modname[p+1:]]), modname[p+1:])
+        else:
+            mod = __import__(modname, {}, {}, [])
+
+        klass = getattr(mod, classname, None)
+        if klass:
+            self._templateClass = klass
+            return klass
+        else:
+            self.error('**Template class specified in option --templateAPIClass not found\n'
+                       '**Falling back on Cheetah.Template:Template')
+
+
+    def _getCompilerSettings(self):
+        if self._compilerSettings:
+            return self._compilerSettings
+
+        def getkws(**kws):
+            return kws
+        if self.opts.compilerSettingsString:
+            try:
+                exec 'settings = getkws(%s)'%self.opts.compilerSettingsString
+            except:                
+                self.error("There's an error in your --settings option."
+                          "It must be valid Python syntax.\n"
+                          +"    --settings='%s'\n"%self.opts.compilerSettingsString
+                          +"  %s: %s"%sys.exc_info()[:2] 
+                          )
+
+            validKeys = DEFAULT_COMPILER_SETTINGS.keys()
+            if [k for k in settings.keys() if k not in validKeys]:
+                self.error(
+                    'The --setting "%s" is not a valid compiler setting name.'%k)
+            
+            self._compilerSettings = settings
+            return settings
+        else:
+            return {}
+
+    def _compileOrFillStdin(self):
+        TemplateClass = self._getTemplateClass()
+        compilerSettings = self._getCompilerSettings()
+        if self.isCompile:
+            pysrc = TemplateClass.compile(file=sys.stdin,
+                                          compilerSettings=compilerSettings,
+                                          returnAClass=False)
+            output = pysrc
+        else:
+            output = str(TemplateClass(file=sys.stdin, compilerSettings=compilerSettings))
+        sys.stdout.write(output)
+
+    def _compileOrFillBundle(self, b):
+        C, D, W = self.chatter, self.debug, self.warn
+        TemplateClass = self._getTemplateClass()
+        compilerSettings = self._getCompilerSettings()
+        src = b.src
+        dst = b.dst
+        base = b.base
+        basename = b.basename
+        dstDir = os.path.dirname(dst)
+        what = self.isCompile and "Compiling" or "Filling"
+        C("%s %s -> %s^", what, src, dst) # No trailing newline.
+        if os.path.exists(dst) and not self.opts.nobackup:
+            bak = b.bak
+            C(" (backup %s)", bak) # On same line as previous message.
+        else:
+            bak = None
+            C("")
+        if self.isCompile:
+            if not moduleNameRE.match(basename):
+                tup = basename, src
+                raise Error("""\
+%s: base name %s contains invalid characters.  It must
+be named according to the same rules as Python modules.""" % tup)
+            pysrc = TemplateClass.compile(file=src, returnAClass=False,
+                                          moduleName=basename,
+                                          className=basename,
+                                          commandlineopts=self.opts,
+                                          compilerSettings=compilerSettings)
+            output = pysrc
+        else:
+            #output = str(TemplateClass(file=src, searchList=self.searchList))
+            tclass = TemplateClass.compile(file=src, compilerSettings=compilerSettings)
+            output = str(tclass(searchList=self.searchList))
+            
+        if bak:
+            shutil.copyfile(dst, bak)
+        if dstDir and not os.path.exists(dstDir):
+            if self.isCompile:
+                mkdirsWithPyInitFiles(dstDir)
+            else:
+                os.makedirs(dstDir)
+        if self.opts.stdout:
+            sys.stdout.write(output)
+        else:
+            f = open(dst, 'w')
+            f.write(output)
+            f.close()
+            
+
+##################################################
+## if run from the command line
+if __name__ == '__main__':  CheetahWrapper().main()
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Compiler.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Compiler.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Compiler.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2011 @@
+#!/usr/bin/env python
+'''
+    Compiler classes for Cheetah:
+    ModuleCompiler aka 'Compiler'
+    ClassCompiler
+    MethodCompiler
+
+    If you are trying to grok this code start with ModuleCompiler.__init__,
+    ModuleCompiler.compile, and ModuleCompiler.__getattr__.
+'''
+
+import sys
+import os
+import os.path
+from os.path import getmtime, exists
+import re
+import types
+import time
+import random
+import warnings
+import copy
+
+from Cheetah.Version import Version, VersionTuple
+from Cheetah.SettingsManager import SettingsManager
+from Cheetah.Utils.Indenter import indentize # an undocumented preprocessor
+from Cheetah import ErrorCatchers
+from Cheetah import NameMapper
+from Cheetah.Parser import Parser, ParseError, specialVarRE, \
+     STATIC_CACHE, REFRESH_CACHE, SET_LOCAL, SET_GLOBAL,SET_MODULE, \
+     unicodeDirectiveRE, encodingDirectiveRE,escapedNewlineRE
+
+from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
+VFFSL=valueFromFrameOrSearchList
+VFSL=valueFromSearchList
+VFN=valueForName
+currentTime=time.time
+
+class Error(Exception): pass
+
+# Settings format: (key, default, docstring)
+_DEFAULT_COMPILER_SETTINGS = [
+    ('useNameMapper', True, 'Enable NameMapper for dotted notation and searchList support'),
+    ('useSearchList', True, 'Enable the searchList, requires useNameMapper=True, if disabled, first portion of the $variable is a global, builtin, or local variable that doesn\'t need looking up in the searchList'),
+    ('allowSearchListAsMethArg', True, ''),
+    ('useAutocalling', True, 'Detect and call callable objects in searchList, requires useNameMapper=True'),
+    ('useStackFrames', True, 'Used for NameMapper.valueFromFrameOrSearchList rather than NameMapper.valueFromSearchList'),
+    ('useErrorCatcher', False, 'Turn on the #errorCatcher directive for catching NameMapper errors, etc'),
+    ('alwaysFilterNone', True, 'Filter out None prior to calling the #filter'),
+    ('useFilters', True, 'If False, pass output through str()'),
+    ('includeRawExprInFilterArgs', True, ''),
+    ('useLegacyImportMode', True, 'All #import statements are relocated to the top of the generated Python module'),
+    ('prioritizeSearchListOverSelf', False, 'When iterating the searchList, look into the searchList passed into the initializer instead of Template members first'),
+
+    ('autoAssignDummyTransactionToSelf', False, ''),
+    ('useKWsDictArgForPassingTrans', True, ''),
+
+    ('commentOffset', 1, ''),
+    ('outputRowColComments', True, ''),
+    ('includeBlockMarkers', False, 'Wrap #block\'s in a comment in the template\'s output'),
+    ('blockMarkerStart', ('\n<!-- START BLOCK: ',' -->\n'), ''),
+    ('blockMarkerEnd', ('\n<!-- END BLOCK: ',' -->\n'), ''),
+    ('defDocStrMsg', 'Autogenerated by Cheetah: The Python-Powered Template Engine', ''),
+    ('setup__str__method', False, ''),
+    ('mainMethodName', 'respond', ''),
+    ('mainMethodNameForSubclasses', 'writeBody', ''),
+    ('indentationStep', ' ' * 4, ''),
+    ('initialMethIndentLevel', 2, ''),
+    ('monitorSrcFile', False, ''),
+    ('outputMethodsBeforeAttributes', True, ''),
+    ('addTimestampsToCompilerOutput', True, ''),
+
+    ## Customizing the #extends directive
+    ('autoImportForExtendsDirective', True, ''),
+    ('handlerForExtendsDirective', None, ''),
+
+    ('disabledDirectives', [], 'List of directive keys to disable (without starting "#")'),
+    ('enabledDirectives', [], 'List of directive keys to enable (without starting "#")'),
+    ('disabledDirectiveHooks', [], 'callable(parser, directiveKey)'),
+    ('preparseDirectiveHooks', [], 'callable(parser, directiveKey)'),
+    ('postparseDirectiveHooks', [], 'callable(parser, directiveKey)'),
+    ('preparsePlaceholderHooks', [], 'callable(parser)'),
+    ('postparsePlaceholderHooks', [], 'callable(parser)'),
+    ('expressionFilterHooks', [], '''callable(parser, expr, exprType, rawExpr=None, startPos=None), exprType is the name of the directive, "psp" or "placeholder" The filters *must* return the expr or raise an expression, they can modify the expr if needed'''),
+    ('templateMetaclass', None, 'Strictly optional, only will work with new-style basecalsses as well'),
+    ('i18NFunctionName', 'self.i18n', ''),
+
+    ('cheetahVarStartToken', '$', ''),
+    ('commentStartToken', '##', ''),
+    ('multiLineCommentStartToken', '#*', ''),
+    ('multiLineCommentEndToken', '*#', ''),
+    ('gobbleWhitespaceAroundMultiLineComments', True, ''),
+    ('directiveStartToken', '#', ''),
+    ('directiveEndToken', '#', ''),
+    ('allowWhitespaceAfterDirectiveStartToken', False, ''),
+    ('PSPStartToken', '<%', ''),
+    ('PSPEndToken', '%>', ''),
+    ('EOLSlurpToken', '#', ''),
+    ('gettextTokens', ["_", "N_", "ngettext"], ''),
+    ('allowExpressionsInExtendsDirective', False, ''),
+    ('allowEmptySingleLineMethods', False, ''),
+    ('allowNestedDefScopes', True, ''),
+    ('allowPlaceholderFilterArgs', True, ''),
+]
+
+DEFAULT_COMPILER_SETTINGS = dict([(v[0], v[1]) for v in _DEFAULT_COMPILER_SETTINGS])
+
+
+
+class GenUtils:
+    """An abstract baseclass for the Compiler classes that provides methods that
+    perform generic utility functions or generate pieces of output code from
+    information passed in by the Parser baseclass.  These methods don't do any
+    parsing themselves.
+    """
+
+    def genTimeInterval(self, timeString):
+        ##@@ TR: need to add some error handling here
+        if timeString[-1] == 's':
+            interval = float(timeString[:-1])
+        elif timeString[-1] == 'm':
+            interval = float(timeString[:-1])*60
+        elif timeString[-1] == 'h':
+            interval = float(timeString[:-1])*60*60
+        elif timeString[-1] == 'd':
+            interval = float(timeString[:-1])*60*60*24
+        elif timeString[-1] == 'w':
+            interval = float(timeString[:-1])*60*60*24*7
+        else:                       # default to minutes
+            interval = float(timeString)*60
+        return interval
+
+    def genCacheInfo(self, cacheTokenParts):
+        """Decipher a placeholder cachetoken
+        """
+        cacheInfo = {}
+        if cacheTokenParts['REFRESH_CACHE']:
+            cacheInfo['type'] = REFRESH_CACHE
+            cacheInfo['interval'] = self.genTimeInterval(cacheTokenParts['interval'])
+        elif cacheTokenParts['STATIC_CACHE']:
+            cacheInfo['type'] = STATIC_CACHE
+        return cacheInfo                # is empty if no cache
+
+    def genCacheInfoFromArgList(self, argList):
+        cacheInfo = {'type':REFRESH_CACHE}
+        for key, val in argList:
+            if val[0] in '"\'':
+                val = val[1:-1]
+
+            if key == 'timer':
+                key = 'interval'
+                val = self.genTimeInterval(val)
+                
+            cacheInfo[key] = val
+        return cacheInfo
+        
+    def genCheetahVar(self, nameChunks, plain=False):
+        if nameChunks[0][0] in self.setting('gettextTokens'):
+            self.addGetTextVar(nameChunks) 
+        if self.setting('useNameMapper') and not plain:
+            return self.genNameMapperVar(nameChunks)
+        else:
+            return self.genPlainVar(nameChunks)
+
+    def addGetTextVar(self, nameChunks):
+        """Output something that gettext can recognize.
+        
+        This is a harmless side effect necessary to make gettext work when it
+        is scanning compiled templates for strings marked for translation.
+
+        @@TR: another marginally more efficient approach would be to put the
+        output in a dummy method that is never called.
+        """
+        # @@TR: this should be in the compiler not here
+        self.addChunk("if False:")
+        self.indent()
+        self.addChunk(self.genPlainVar(nameChunks[:]))
+        self.dedent()
+
+    def genPlainVar(self, nameChunks):        
+        """Generate Python code for a Cheetah $var without using NameMapper
+        (Unified Dotted Notation with the SearchList).
+        """
+        nameChunks.reverse()
+        chunk = nameChunks.pop()
+        pythonCode = chunk[0] + chunk[2]
+        while nameChunks:
+            chunk = nameChunks.pop()
+            pythonCode = (pythonCode + '.' + chunk[0] + chunk[2])
+        return pythonCode
+
+    def genNameMapperVar(self, nameChunks):
+        """Generate valid Python code for a Cheetah $var, using NameMapper
+        (Unified Dotted Notation with the SearchList).
+
+        nameChunks = list of var subcomponents represented as tuples
+          [ (name,useAC,remainderOfExpr),
+          ]
+        where:
+          name = the dotted name base
+          useAC = where NameMapper should use autocalling on namemapperPart
+          remainderOfExpr = any arglist, index, or slice
+
+        If remainderOfExpr contains a call arglist (e.g. '(1234)') then useAC
+        is False, otherwise it defaults to True. It is overridden by the global
+        setting 'useAutocalling' if this setting is False.
+
+        EXAMPLE
+        ------------------------------------------------------------------------
+        if the raw Cheetah Var is
+          $a.b.c[1].d().x.y.z
+          
+        nameChunks is the list
+          [ ('a.b.c',True,'[1]'), # A
+            ('d',False,'()'),     # B
+            ('x.y.z',True,''),    # C
+          ]
+        
+        When this method is fed the list above it returns
+          VFN(VFN(VFFSL(SL, 'a.b.c',True)[1], 'd',False)(), 'x.y.z',True)
+        which can be represented as
+          VFN(B`, name=C[0], executeCallables=(useAC and C[1]))C[2]
+        where:
+          VFN = NameMapper.valueForName
+          VFFSL = NameMapper.valueFromFrameOrSearchList
+          VFSL = NameMapper.valueFromSearchList # optionally used instead of VFFSL
+          SL = self.searchList()
+          useAC = self.setting('useAutocalling') # True in this example
+          
+          A = ('a.b.c',True,'[1]')
+          B = ('d',False,'()')
+          C = ('x.y.z',True,'')
+
+          C` = VFN( VFN( VFFSL(SL, 'a.b.c',True)[1],
+                         'd',False)(),
+                    'x.y.z',True)
+             = VFN(B`, name='x.y.z', executeCallables=True)
+             
+          B` = VFN(A`, name=B[0], executeCallables=(useAC and B[1]))B[2]
+          A` = VFFSL(SL, name=A[0], executeCallables=(useAC and A[1]))A[2]
+
+
+        Note, if the compiler setting useStackFrames=False (default is true)
+        then
+          A` = VFSL([locals()]+SL+[globals(), __builtin__], name=A[0], executeCallables=(useAC and A[1]))A[2]
+        This option allows Cheetah to be used with Psyco, which doesn't support
+        stack frame introspection.
+        """
+        defaultUseAC = self.setting('useAutocalling')
+        useSearchList = self.setting('useSearchList')
+
+        nameChunks.reverse()
+        name, useAC, remainder = nameChunks.pop()
+        
+        if not useSearchList:
+            firstDotIdx = name.find('.')
+            if firstDotIdx != -1 and firstDotIdx < len(name):
+                beforeFirstDot, afterDot = name[:firstDotIdx], name[firstDotIdx+1:]
+                pythonCode = ('VFN(' + beforeFirstDot +
+                              ',"' + afterDot +
+                              '",' + repr(defaultUseAC and useAC) + ')'
+                              + remainder)
+            else:
+                pythonCode = name+remainder
+        elif self.setting('useStackFrames'):
+            pythonCode = ('VFFSL(SL,'
+                          '"'+ name + '",'
+                          + repr(defaultUseAC and useAC) + ')'
+                          + remainder)
+        else:
+            pythonCode = ('VFSL([locals()]+SL+[globals(), __builtin__],'
+                          '"'+ name + '",'
+                          + repr(defaultUseAC and useAC) + ')'
+                          + remainder)
+        ##    
+        while nameChunks:
+            name, useAC, remainder = nameChunks.pop()
+            pythonCode = ('VFN(' + pythonCode +
+                          ',"' + name +
+                          '",' + repr(defaultUseAC and useAC) + ')'
+                          + remainder)
+        return pythonCode
+    
+##################################################
+## METHOD COMPILERS
+
+class MethodCompiler(GenUtils):
+    def __init__(self, methodName, classCompiler,
+                 initialMethodComment=None,
+                 decorators=None):
+        self._settingsManager = classCompiler
+        self._classCompiler = classCompiler
+        self._moduleCompiler = classCompiler._moduleCompiler
+        self._methodName = methodName
+        self._initialMethodComment = initialMethodComment
+        self._setupState()
+        self._decorators = decorators or []
+
+    def setting(self, key):
+        return self._settingsManager.setting(key)
+
+    def _setupState(self):
+        self._indent = self.setting('indentationStep')
+        self._indentLev = self.setting('initialMethIndentLevel')
+        self._pendingStrConstChunks = []
+        self._methodSignature = None
+        self._methodDef = None
+        self._docStringLines = []
+        self._methodBodyChunks = []
+
+        self._cacheRegionsStack = []
+        self._callRegionsStack = []
+        self._captureRegionsStack = []
+        self._filterRegionsStack = []
+
+        self._isErrorCatcherOn = False
+
+        self._hasReturnStatement = False
+        self._isGenerator = False
+        
+        
+    def cleanupState(self):
+        """Called by the containing class compiler instance
+        """
+        pass
+
+    def methodName(self):
+        return self._methodName
+
+    def setMethodName(self, name):
+        self._methodName = name
+        
+    ## methods for managing indentation
+    
+    def indentation(self):
+        return self._indent * self._indentLev
+    
+    def indent(self):
+        self._indentLev +=1
+        
+    def dedent(self):
+        if self._indentLev:
+            self._indentLev -=1
+        else:
+            raise Error('Attempt to dedent when the indentLev is 0')
+
+    ## methods for final code wrapping
+
+    def methodDef(self):
+        if self._methodDef:
+            return self._methodDef
+        else:
+            return self.wrapCode()
+
+    __str__ = methodDef
+    __unicode__ = methodDef
+    
+    def wrapCode(self):
+        self.commitStrConst()
+        methodDefChunks = (
+            self.methodSignature(),
+            '\n',
+            self.docString(),
+            self.methodBody() )
+        methodDef = ''.join(methodDefChunks)
+        self._methodDef = methodDef
+        return methodDef
+
+    def methodSignature(self):
+        return self._indent + self._methodSignature + ':'
+
+    def setMethodSignature(self, signature):
+        self._methodSignature = signature
+
+    def methodBody(self):
+        return ''.join( self._methodBodyChunks )
+
+    def docString(self):
+        if not self._docStringLines:
+            return ''
+        
+        ind = self._indent*2        
+        docStr = (ind + '"""\n' + ind +
+                  ('\n' + ind).join([ln.replace('"""',"'''") for ln in self._docStringLines]) +
+                  '\n' + ind + '"""\n')
+        return  docStr
+
+    ## methods for adding code
+    def addMethDocString(self, line):
+        self._docStringLines.append(line.replace('%','%%'))
+       
+    def addChunk(self, chunk):
+        self.commitStrConst()
+        chunk = "\n" + self.indentation() + chunk
+        self._methodBodyChunks.append(chunk)
+
+    def appendToPrevChunk(self, appendage):
+        self._methodBodyChunks[-1] = self._methodBodyChunks[-1] + appendage
+
+    def addWriteChunk(self, chunk):
+        self.addChunk('write(' + chunk + ')')
+
+    def addFilteredChunk(self, chunk, filterArgs=None, rawExpr=None, lineCol=None):
+        if filterArgs is None:
+            filterArgs = ''
+        if self.setting('includeRawExprInFilterArgs') and rawExpr:
+            filterArgs += ', rawExpr=%s'%repr(rawExpr)
+
+        if self.setting('alwaysFilterNone'):
+            if rawExpr and rawExpr.find('\n')==-1 and rawExpr.find('\r')==-1:
+                self.addChunk("_v = %s # %r"%(chunk, rawExpr))
+                if lineCol:
+                    self.appendToPrevChunk(' on line %s, col %s'%lineCol)
+            else:
+                self.addChunk("_v = %s"%chunk)
+                
+            if self.setting('useFilters'):
+                self.addChunk("if _v is not None: write(_filter(_v%s))"%filterArgs)
+            else:
+                self.addChunk("if _v is not None: write(str(_v))")
+        else:
+            if self.setting('useFilters'):
+                self.addChunk("write(_filter(%s%s))"%(chunk,filterArgs))
+            else:
+                self.addChunk("write(str(%s))"%chunk)
+
+    def _appendToPrevStrConst(self, strConst):
+        if self._pendingStrConstChunks:
+            self._pendingStrConstChunks.append(strConst)
+        else:
+            self._pendingStrConstChunks = [strConst]
+
+    def _unescapeCheetahVars(self, theString):
+        """Unescape any escaped Cheetah \$vars in the string.
+        """
+        
+        token = self.setting('cheetahVarStartToken')
+        return theString.replace('\\' + token, token)
+
+    def _unescapeDirectives(self, theString):
+        """Unescape any escaped Cheetah \$vars in the string.
+        """
+        
+        token = self.setting('directiveStartToken')
+        return theString.replace('\\' + token, token)
+        
+    def commitStrConst(self):
+        """Add the code for outputting the pending strConst without chopping off
+        any whitespace from it.
+        """
+        if self._pendingStrConstChunks:
+            strConst = self._unescapeCheetahVars(''.join(self._pendingStrConstChunks))
+            strConst = self._unescapeDirectives(strConst)
+            self._pendingStrConstChunks = []
+            if not strConst:
+                return
+            else:
+                reprstr = repr(strConst).replace('\\012','\n')
+                i = 0
+                out = []
+                if reprstr.startswith('u'):
+                    i = 1
+                    out = ['u']
+                body = escapedNewlineRE.sub('\n', reprstr[i+1:-1])
+                
+                if reprstr[i]=="'":
+                    out.append("'''")
+                    out.append(body)
+                    out.append("'''")
+                else:
+                    out.append('"""')
+                    out.append(body)
+                    out.append('"""')
+                self.addWriteChunk(''.join(out))
+
+    def handleWSBeforeDirective(self):
+        """Truncate the pending strCont to the beginning of the current line.
+        """
+        if self._pendingStrConstChunks:
+            src = self._pendingStrConstChunks[-1]
+            BOL = max(src.rfind('\n')+1, src.rfind('\r')+1, 0)
+            if BOL < len(src):
+                self._pendingStrConstChunks[-1] = src[:BOL]
+
+
+
+    def isErrorCatcherOn(self):
+        return self._isErrorCatcherOn
+    
+    def turnErrorCatcherOn(self):
+        self._isErrorCatcherOn = True
+
+    def turnErrorCatcherOff(self):
+        self._isErrorCatcherOn = False
+            
+    # @@TR: consider merging the next two methods into one
+    def addStrConst(self, strConst):
+        self._appendToPrevStrConst(strConst)
+
+    def addRawText(self, text):
+        self.addStrConst(text)
+        
+    def addMethComment(self, comm):
+        offSet = self.setting('commentOffset')
+        self.addChunk('#' + ' '*offSet + comm)
+
+    def addPlaceholder(self, expr, filterArgs, rawPlaceholder,
+                       cacheTokenParts, lineCol,
+                       silentMode=False):
+        cacheInfo = self.genCacheInfo(cacheTokenParts)
+        if cacheInfo:
+            cacheInfo['ID'] = repr(rawPlaceholder)[1:-1]
+            self.startCacheRegion(cacheInfo, lineCol, rawPlaceholder=rawPlaceholder)
+
+        if self.isErrorCatcherOn():
+            methodName = self._classCompiler.addErrorCatcherCall(
+                expr, rawCode=rawPlaceholder, lineCol=lineCol)
+            expr = 'self.' + methodName + '(localsDict=locals())' 
+
+        if silentMode:
+            self.addChunk('try:')
+            self.indent()            
+            self.addFilteredChunk(expr, filterArgs, rawPlaceholder, lineCol=lineCol)
+            self.dedent()
+            self.addChunk('except NotFound: pass')            
+        else:
+            self.addFilteredChunk(expr, filterArgs, rawPlaceholder, lineCol=lineCol)
+
+        if self.setting('outputRowColComments'):
+            self.appendToPrevChunk(' # from line %s, col %s' % lineCol + '.')
+        if cacheInfo:
+            self.endCacheRegion()
+
+    def addSilent(self, expr):
+        self.addChunk( expr )
+
+    def addEcho(self, expr, rawExpr=None):
+        self.addFilteredChunk(expr, rawExpr=rawExpr)
+        
+    def addSet(self, expr, exprComponents, setStyle):
+        if setStyle is SET_GLOBAL:
+            (LVALUE, OP, RVALUE) = (exprComponents.LVALUE,
+                                    exprComponents.OP,
+                                    exprComponents.RVALUE)
+            # we need to split the LVALUE to deal with globalSetVars
+            splitPos1 = LVALUE.find('.')
+            splitPos2 = LVALUE.find('[')
+            if splitPos1 > 0 and splitPos2==-1:
+                splitPos = splitPos1
+            elif splitPos1 > 0 and splitPos1 < max(splitPos2,0):
+                splitPos = splitPos1
+            else:
+                splitPos = splitPos2
+
+            if splitPos >0:
+                primary = LVALUE[:splitPos]
+                secondary = LVALUE[splitPos:]
+            else:
+                primary = LVALUE
+                secondary = ''            
+            LVALUE = 'self._CHEETAH__globalSetVars["' + primary + '"]' + secondary
+            expr = LVALUE + ' ' + OP + ' ' + RVALUE.strip()
+
+        if setStyle is SET_MODULE:
+            self._moduleCompiler.addModuleGlobal(expr)
+        else:
+            self.addChunk(expr)
+
+    def addInclude(self, sourceExpr, includeFrom, isRaw):
+        self.addChunk('self._handleCheetahInclude(' + sourceExpr +
+                           ', trans=trans, ' +
+                           'includeFrom="' + includeFrom + '", raw=' +
+                           repr(isRaw) + ')')
+
+    def addWhile(self, expr, lineCol=None):
+        self.addIndentingDirective(expr, lineCol=lineCol)
+        
+    def addFor(self, expr, lineCol=None):
+        self.addIndentingDirective(expr, lineCol=lineCol)
+
+    def addRepeat(self, expr, lineCol=None):
+        #the _repeatCount stuff here allows nesting of #repeat directives        
+        self._repeatCount = getattr(self, "_repeatCount", -1) + 1
+        self.addFor('for __i%s in range(%s)' % (self._repeatCount,expr), lineCol=lineCol)
+
+    def addIndentingDirective(self, expr, lineCol=None):
+        if expr and not expr[-1] == ':':
+            expr = expr  + ':'
+        self.addChunk( expr )
+        if lineCol:
+            self.appendToPrevChunk(' # generated from line %s, col %s'%lineCol )
+        self.indent()
+
+    def addReIndentingDirective(self, expr, dedent=True, lineCol=None):
+        self.commitStrConst()
+        if dedent:
+            self.dedent()
+        if not expr[-1] == ':':
+            expr = expr  + ':'
+            
+        self.addChunk( expr )
+        if lineCol:
+            self.appendToPrevChunk(' # generated from line %s, col %s'%lineCol )
+        self.indent()
+
+    def addIf(self, expr, lineCol=None):
+        """For a full #if ... #end if directive
+        """
+        self.addIndentingDirective(expr, lineCol=lineCol)
+
+    def addOneLineIf(self, expr, lineCol=None):
+        """For a full #if ... #end if directive
+        """
+        self.addIndentingDirective(expr, lineCol=lineCol)
+
+    def addTernaryExpr(self, conditionExpr, trueExpr, falseExpr, lineCol=None):
+        """For a single-lie #if ... then .... else ... directive
+        <condition> then <trueExpr> else <falseExpr>
+        """
+        self.addIndentingDirective(conditionExpr, lineCol=lineCol)            
+        self.addFilteredChunk(trueExpr)
+        self.dedent()
+        self.addIndentingDirective('else')            
+        self.addFilteredChunk(falseExpr)
+        self.dedent()
+
+    def addElse(self, expr, dedent=True, lineCol=None):
+        expr = re.sub(r'else[ \f\t]+if','elif', expr)
+        self.addReIndentingDirective(expr, dedent=dedent, lineCol=lineCol)
+
+    def addElif(self, expr, dedent=True, lineCol=None):
+        self.addElse(expr, dedent=dedent, lineCol=lineCol)
+        
+    def addUnless(self, expr, lineCol=None):
+        self.addIf('if not (' + expr + ')')
+
+    def addClosure(self, functionName, argsList, parserComment):
+        argStringChunks = []
+        for arg in argsList:
+            chunk = arg[0]
+            if not arg[1] == None:
+                chunk += '=' + arg[1]
+            argStringChunks.append(chunk)
+        signature = "def " + functionName + "(" + ','.join(argStringChunks) + "):"
+        self.addIndentingDirective(signature)
+        self.addChunk('#'+parserComment)
+
+    def addTry(self, expr, lineCol=None):
+        self.addIndentingDirective(expr, lineCol=lineCol)
+        
+    def addExcept(self, expr, dedent=True, lineCol=None):
+        self.addReIndentingDirective(expr, dedent=dedent, lineCol=lineCol)
+        
+    def addFinally(self, expr, dedent=True, lineCol=None):
+        self.addReIndentingDirective(expr, dedent=dedent, lineCol=lineCol)
+            
+    def addReturn(self, expr):
+        assert not self._isGenerator
+        self.addChunk(expr)
+        self._hasReturnStatement = True
+
+    def addYield(self, expr):
+        assert not self._hasReturnStatement
+        self._isGenerator = True
+        if expr.replace('yield','').strip():
+            self.addChunk(expr)
+        else:
+            self.addChunk('if _dummyTrans:')
+            self.indent()
+            self.addChunk('yield trans.response().getvalue()')
+            self.addChunk('trans = DummyTransaction()')
+            self.addChunk('write = trans.response().write')
+            self.dedent()
+            self.addChunk('else:')
+            self.indent()
+            self.addChunk(
+                'raise TypeError("This method cannot be called with a trans arg")')
+            self.dedent()
+            
+
+    def addPass(self, expr):
+        self.addChunk(expr)
+
+    def addDel(self, expr):
+        self.addChunk(expr)
+
+    def addAssert(self, expr):
+        self.addChunk(expr)
+
+    def addRaise(self, expr):
+        self.addChunk(expr)
+
+    def addBreak(self, expr):
+        self.addChunk(expr)
+
+    def addContinue(self, expr):
+        self.addChunk(expr)
+
+    def addPSP(self, PSP):
+        self.commitStrConst()
+        autoIndent = False
+        if PSP[0] == '=':
+            PSP = PSP[1:]
+            if PSP:
+                self.addWriteChunk('_filter(' + PSP + ')')
+            return
+                    
+        elif PSP.lower() == 'end':
+            self.dedent()
+            return
+        elif PSP[-1] == '$':
+            autoIndent = True
+            PSP = PSP[:-1]
+        elif PSP[-1] == ':':
+            autoIndent = True
+            
+        for line in PSP.splitlines():
+            self.addChunk(line)
+            
+        if autoIndent:
+            self.indent()
+    
+    def nextCacheID(self):
+        return ('_'+str(random.randrange(100, 999)) 
+                + str(random.randrange(10000, 99999)))
+        
+    def startCacheRegion(self, cacheInfo, lineCol, rawPlaceholder=None):
+
+        # @@TR: we should add some runtime logging to this
+        
+        ID = self.nextCacheID()
+        interval = cacheInfo.get('interval',None)
+        test = cacheInfo.get('test',None)
+        customID = cacheInfo.get('id',None)
+        if customID:
+            ID = customID
+        varyBy = cacheInfo.get('varyBy', repr(ID))
+        self._cacheRegionsStack.append(ID) # attrib of current methodCompiler
+
+        # @@TR: add this to a special class var as well
+        self.addChunk('')
+
+        self.addChunk('## START CACHE REGION: ID='+ID+
+                      '. line %s, col %s'%lineCol + ' in the source.')
+        
+        self.addChunk('_RECACHE_%(ID)s = False'%locals())
+        self.addChunk('_cacheRegion_%(ID)s = self.getCacheRegion(regionID='%locals()
+                      + repr(ID)
+                      + ', cacheInfo=%r'%cacheInfo
+                      + ')')
+        self.addChunk('if _cacheRegion_%(ID)s.isNew():'%locals())
+        self.indent()
+        self.addChunk('_RECACHE_%(ID)s = True'%locals())
+        self.dedent()
+        
+        self.addChunk('_cacheItem_%(ID)s = _cacheRegion_%(ID)s.getCacheItem('%locals()
+                      +varyBy+')')
+
+        self.addChunk('if _cacheItem_%(ID)s.hasExpired():'%locals())
+        self.indent()
+        self.addChunk('_RECACHE_%(ID)s = True'%locals())
+        self.dedent()
+            
+        if test:
+            self.addChunk('if ' + test + ':')
+            self.indent()
+            self.addChunk('_RECACHE_%(ID)s = True'%locals())
+            self.dedent()
+
+        self.addChunk('if (not _RECACHE_%(ID)s) and _cacheItem_%(ID)s.getRefreshTime():'%locals())
+        self.indent()
+        #self.addChunk('print "DEBUG"+"-"*50')
+        self.addChunk('try:')
+        self.indent()
+        self.addChunk('_output = _cacheItem_%(ID)s.renderOutput()'%locals())        
+        self.dedent()                
+        self.addChunk('except KeyError:')
+        self.indent()
+        self.addChunk('_RECACHE_%(ID)s = True'%locals())
+        #self.addChunk('print "DEBUG"+"*"*50')
+        self.dedent()                
+        self.addChunk('else:')
+        self.indent()
+        self.addWriteChunk('_output')
+        self.addChunk('del _output')
+        self.dedent()                
+
+        self.dedent()                
+
+        self.addChunk('if _RECACHE_%(ID)s or not _cacheItem_%(ID)s.getRefreshTime():'%locals())
+        self.indent()
+        self.addChunk('_orig_trans%(ID)s = trans'%locals())
+        self.addChunk('trans = _cacheCollector_%(ID)s = DummyTransaction()'%locals())
+        self.addChunk('write = _cacheCollector_%(ID)s.response().write'%locals())
+        if interval:
+            self.addChunk(("_cacheItem_%(ID)s.setExpiryTime(currentTime() +"%locals())
+                          + str(interval) + ")")
+        
+    def endCacheRegion(self):
+        ID = self._cacheRegionsStack.pop()
+        self.addChunk('trans = _orig_trans%(ID)s'%locals())
+        self.addChunk('write = trans.response().write')
+        self.addChunk('_cacheData = _cacheCollector_%(ID)s.response().getvalue()'%locals())
+        self.addChunk('_cacheItem_%(ID)s.setData(_cacheData)'%locals())
+        self.addWriteChunk('_cacheData')
+        self.addChunk('del _cacheData')        
+        self.addChunk('del _cacheCollector_%(ID)s'%locals())
+        self.addChunk('del _orig_trans%(ID)s'%locals())
+        self.dedent()
+        self.addChunk('## END CACHE REGION: '+ID)
+        self.addChunk('')
+
+    def nextCallRegionID(self):
+        return self.nextCacheID()
+
+    def startCallRegion(self, functionName, args, lineCol, regionTitle='CALL'):
+        class CallDetails(object):
+            pass
+        callDetails = CallDetails()
+        callDetails.ID = ID = self.nextCallRegionID()
+        callDetails.functionName = functionName
+        callDetails.args = args
+        callDetails.lineCol = lineCol
+        callDetails.usesKeywordArgs = False
+        self._callRegionsStack.append((ID, callDetails)) # attrib of current methodCompiler
+
+        self.addChunk('## START %(regionTitle)s REGION: '%locals()
+                      +ID
+                      +' of '+functionName
+                      +' at line %s, col %s'%lineCol + ' in the source.')
+        self.addChunk('_orig_trans%(ID)s = trans'%locals())
+        self.addChunk('_wasBuffering%(ID)s = self._CHEETAH__isBuffering'%locals())
+        self.addChunk('self._CHEETAH__isBuffering = True')
+        self.addChunk('trans = _callCollector%(ID)s = DummyTransaction()'%locals())
+        self.addChunk('write = _callCollector%(ID)s.response().write'%locals())
+
+    def setCallArg(self, argName, lineCol):
+        ID, callDetails = self._callRegionsStack[-1]
+        argName = str(argName)
+        if callDetails.usesKeywordArgs:
+            self._endCallArg()
+        else:
+            callDetails.usesKeywordArgs = True
+            self.addChunk('_callKws%(ID)s = {}'%locals())
+            self.addChunk('_currentCallArgname%(ID)s = %(argName)r'%locals())
+        callDetails.currentArgname = argName
+        
+    def _endCallArg(self):
+        ID, callDetails = self._callRegionsStack[-1]
+        currCallArg = callDetails.currentArgname
+        self.addChunk(('_callKws%(ID)s[%(currCallArg)r] ='
+                       ' _callCollector%(ID)s.response().getvalue()')%locals())
+        self.addChunk('del _callCollector%(ID)s'%locals())
+        self.addChunk('trans = _callCollector%(ID)s = DummyTransaction()'%locals())
+        self.addChunk('write = _callCollector%(ID)s.response().write'%locals())
+    
+    def endCallRegion(self, regionTitle='CALL'):
+        ID, callDetails = self._callRegionsStack[-1]
+        functionName, initialKwArgs, lineCol = (
+            callDetails.functionName, callDetails.args, callDetails.lineCol)
+
+        def reset(ID=ID):
+            self.addChunk('trans = _orig_trans%(ID)s'%locals())
+            self.addChunk('write = trans.response().write')
+            self.addChunk('self._CHEETAH__isBuffering = _wasBuffering%(ID)s '%locals())
+            self.addChunk('del _wasBuffering%(ID)s'%locals())
+            self.addChunk('del _orig_trans%(ID)s'%locals())
+
+        if not callDetails.usesKeywordArgs:
+            reset()
+            self.addChunk('_callArgVal%(ID)s = _callCollector%(ID)s.response().getvalue()'%locals())
+            self.addChunk('del _callCollector%(ID)s'%locals())
+            if initialKwArgs:
+                initialKwArgs = ', '+initialKwArgs           
+            self.addFilteredChunk('%(functionName)s(_callArgVal%(ID)s%(initialKwArgs)s)'%locals())
+            self.addChunk('del _callArgVal%(ID)s'%locals())
+        else:
+            if initialKwArgs:
+                initialKwArgs = initialKwArgs+', '
+            self._endCallArg()
+            reset()
+            self.addFilteredChunk('%(functionName)s(%(initialKwArgs)s**_callKws%(ID)s)'%locals())
+            self.addChunk('del _callKws%(ID)s'%locals())
+        self.addChunk('## END %(regionTitle)s REGION: '%locals()
+                      +ID
+                      +' of '+functionName
+                      +' at line %s, col %s'%lineCol + ' in the source.')        
+        self.addChunk('')
+        self._callRegionsStack.pop() # attrib of current methodCompiler
+
+    def nextCaptureRegionID(self):
+        return self.nextCacheID()
+
+    def startCaptureRegion(self, assignTo, lineCol):
+        class CaptureDetails: pass
+        captureDetails = CaptureDetails()
+        captureDetails.ID = ID = self.nextCaptureRegionID()
+        captureDetails.assignTo = assignTo
+        captureDetails.lineCol = lineCol
+        
+        self._captureRegionsStack.append((ID,captureDetails)) # attrib of current methodCompiler
+        self.addChunk('## START CAPTURE REGION: '+ID
+                      +' '+assignTo
+                      +' at line %s, col %s'%lineCol + ' in the source.')
+        self.addChunk('_orig_trans%(ID)s = trans'%locals())
+        self.addChunk('_wasBuffering%(ID)s = self._CHEETAH__isBuffering'%locals())
+        self.addChunk('self._CHEETAH__isBuffering = True')
+        self.addChunk('trans = _captureCollector%(ID)s = DummyTransaction()'%locals())
+        self.addChunk('write = _captureCollector%(ID)s.response().write'%locals())
+
+    def endCaptureRegion(self):
+        ID, captureDetails = self._captureRegionsStack.pop()
+        assignTo, lineCol = (captureDetails.assignTo, captureDetails.lineCol)
+        self.addChunk('trans = _orig_trans%(ID)s'%locals())
+        self.addChunk('write = trans.response().write')
+        self.addChunk('self._CHEETAH__isBuffering = _wasBuffering%(ID)s '%locals())
+        self.addChunk('%(assignTo)s = _captureCollector%(ID)s.response().getvalue()'%locals())
+        self.addChunk('del _orig_trans%(ID)s'%locals())
+        self.addChunk('del _captureCollector%(ID)s'%locals())
+        self.addChunk('del _wasBuffering%(ID)s'%locals())
+        
+    def setErrorCatcher(self, errorCatcherName):
+        self.turnErrorCatcherOn()        
+
+        self.addChunk('if self._CHEETAH__errorCatchers.has_key("' + errorCatcherName + '"):')
+        self.indent()
+        self.addChunk('self._CHEETAH__errorCatcher = self._CHEETAH__errorCatchers["' +
+            errorCatcherName + '"]')
+        self.dedent()
+        self.addChunk('else:')
+        self.indent()
+        self.addChunk('self._CHEETAH__errorCatcher = self._CHEETAH__errorCatchers["'
+                      + errorCatcherName + '"] = ErrorCatchers.'
+                      + errorCatcherName + '(self)'
+                      )
+        self.dedent()
+
+    def nextFilterRegionID(self):
+        return self.nextCacheID()
+
+    def setTransform(self, transformer, isKlass):
+        self.addChunk('trans = TransformerTransaction()')
+        self.addChunk('trans._response = trans.response()')
+        self.addChunk('trans._response._filter = %s' % transformer)
+        self.addChunk('write = trans._response.write')
+        
+    def setFilter(self, theFilter, isKlass):
+        class FilterDetails: 
+            pass
+        filterDetails = FilterDetails()
+        filterDetails.ID = ID = self.nextFilterRegionID()
+        filterDetails.theFilter = theFilter
+        filterDetails.isKlass = isKlass
+        self._filterRegionsStack.append((ID, filterDetails)) # attrib of current methodCompiler
+
+        self.addChunk('_orig_filter%(ID)s = _filter'%locals())
+        if isKlass:
+            self.addChunk('_filter = self._CHEETAH__currentFilter = ' + theFilter.strip() +
+                          '(self).filter')
+        else:
+            if theFilter.lower() == 'none':
+                self.addChunk('_filter = self._CHEETAH__initialFilter')
+            else:
+                # is string representing the name of a builtin filter
+                self.addChunk('filterName = ' + repr(theFilter))
+                self.addChunk('if self._CHEETAH__filters.has_key("' + theFilter + '"):')
+                self.indent()
+                self.addChunk('_filter = self._CHEETAH__currentFilter = self._CHEETAH__filters[filterName]')
+                self.dedent()
+                self.addChunk('else:')
+                self.indent()
+                self.addChunk('_filter = self._CHEETAH__currentFilter'
+                              +' = \\\n\t\t\tself._CHEETAH__filters[filterName] = '
+                              + 'getattr(self._CHEETAH__filtersLib, filterName)(self).filter')
+                self.dedent()
+                
+    def closeFilterBlock(self):
+        ID, filterDetails = self._filterRegionsStack.pop()
+        #self.addChunk('_filter = self._CHEETAH__initialFilter')
+        #self.addChunk('_filter = _orig_filter%(ID)s'%locals())
+        self.addChunk('_filter = self._CHEETAH__currentFilter = _orig_filter%(ID)s'%locals())
+
+class AutoMethodCompiler(MethodCompiler):
+
+    def _setupState(self):
+        MethodCompiler._setupState(self)
+        self._argStringList = [ ("self",None) ]
+        self._streamingEnabled = True
+        self._isClassMethod = None
+        self._isStaticMethod = None
+
+    def _useKWsDictArgForPassingTrans(self):
+        alreadyHasTransArg = [argname for argname,defval in self._argStringList
+                              if argname=='trans']
+        return (self.methodName()!='respond'
+                and not alreadyHasTransArg
+                and self.setting('useKWsDictArgForPassingTrans'))
+
+    def isClassMethod(self):
+        if self._isClassMethod is None:
+            self._isClassMethod = '@classmethod' in self._decorators
+        return self._isClassMethod
+
+    def isStaticMethod(self):
+        if self._isStaticMethod is None:
+            self._isStaticMethod = '@staticmethod' in self._decorators
+        return self._isStaticMethod
+    
+    def cleanupState(self):
+        MethodCompiler.cleanupState(self)
+        self.commitStrConst()
+        if self._cacheRegionsStack:
+            self.endCacheRegion()
+        if self._callRegionsStack:
+            self.endCallRegion()
+            
+        if self._streamingEnabled:
+            kwargsName = None
+            positionalArgsListName = None
+            for argname,defval in self._argStringList:
+                if argname.strip().startswith('**'):
+                    kwargsName = argname.strip().replace('**','')
+                    break
+                elif argname.strip().startswith('*'):
+                    positionalArgsListName = argname.strip().replace('*','')
+                    
+            if not kwargsName and self._useKWsDictArgForPassingTrans():
+                kwargsName = 'KWS'
+                self.addMethArg('**KWS', None)
+            self._kwargsName = kwargsName
+
+            if not self._useKWsDictArgForPassingTrans():
+                if not kwargsName and not positionalArgsListName:
+                    self.addMethArg('trans', 'None')       
+                else:
+                    self._streamingEnabled = False
+                
+        self._indentLev = self.setting('initialMethIndentLevel')
+        mainBodyChunks = self._methodBodyChunks
+        self._methodBodyChunks = []
+        self._addAutoSetupCode()
+        self._methodBodyChunks.extend(mainBodyChunks)
+        self._addAutoCleanupCode()
+        
+    def _addAutoSetupCode(self):
+        if self._initialMethodComment:
+            self.addChunk(self._initialMethodComment)
+            
+        if self._streamingEnabled and not self.isClassMethod() and not self.isStaticMethod():
+            if self._useKWsDictArgForPassingTrans() and self._kwargsName:
+                self.addChunk('trans = %s.get("trans")'%self._kwargsName)            
+            self.addChunk('if (not trans and not self._CHEETAH__isBuffering'
+                          ' and not callable(self.transaction)):')
+            self.indent()
+            self.addChunk('trans = self.transaction'
+                          ' # is None unless self.awake() was called')
+            self.dedent()
+            self.addChunk('if not trans:')
+            self.indent()
+            self.addChunk('trans = DummyTransaction()')
+            if self.setting('autoAssignDummyTransactionToSelf'):
+                self.addChunk('self.transaction = trans')            
+            self.addChunk('_dummyTrans = True')
+            self.dedent()
+            self.addChunk('else: _dummyTrans = False')
+        else:
+            self.addChunk('trans = DummyTransaction()')
+            self.addChunk('_dummyTrans = True')
+        self.addChunk('write = trans.response().write')
+        if self.setting('useNameMapper'):
+            argNames = [arg[0] for arg in self._argStringList]
+            allowSearchListAsMethArg = self.setting('allowSearchListAsMethArg')            
+            if allowSearchListAsMethArg and 'SL' in argNames:
+                pass
+            elif allowSearchListAsMethArg and 'searchList' in argNames:
+                self.addChunk('SL = searchList')
+            elif not self.isClassMethod() and not self.isStaticMethod():
+                self.addChunk('SL = self._CHEETAH__searchList')                
+            else:
+                self.addChunk('SL = [KWS]')
+        if self.setting('useFilters'):
+            if self.isClassMethod() or self.isStaticMethod():
+                self.addChunk('_filter = lambda x, **kwargs: unicode(x)')
+            else:
+                self.addChunk('_filter = self._CHEETAH__currentFilter')
+        self.addChunk('')
+        self.addChunk("#" *40)
+        self.addChunk('## START - generated method body')
+        self.addChunk('')
+
+    def _addAutoCleanupCode(self):
+        self.addChunk('')
+        self.addChunk("#" *40)
+        self.addChunk('## END - generated method body')
+        self.addChunk('')
+
+        if not self._isGenerator:
+            self.addStop()
+        self.addChunk('')
+        
+    def addStop(self, expr=None):
+        self.addChunk('return _dummyTrans and trans.response().getvalue() or ""')
+
+    def addMethArg(self, name, defVal=None):
+        self._argStringList.append( (name,defVal) )
+        
+    def methodSignature(self):
+        argStringChunks = []
+        for arg in self._argStringList:
+            chunk = arg[0]
+            if chunk == 'self' and self.isClassMethod():
+                chunk = 'cls'
+            if chunk == 'self' and self.isStaticMethod():
+                # Skip the "self" method for @staticmethod decorators
+                continue
+            if not arg[1] == None:
+                chunk += '=' + arg[1]
+            argStringChunks.append(chunk)
+        argString = (', ').join(argStringChunks)
+
+        output = []
+        if self._decorators:
+            output.append(''.join([self._indent + decorator + '\n'
+                                   for decorator in self._decorators]))
+        output.append(self._indent + "def "
+                      + self.methodName() + "(" +
+                      argString + "):\n\n")
+        return ''.join(output)
+
+
+##################################################
+## CLASS COMPILERS
+
+_initMethod_initCheetah = """\
+if not self._CHEETAH__instanceInitialized:
+    cheetahKWArgs = {}
+    allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
+    for k,v in KWs.items():
+        if k in allowedKWs: cheetahKWArgs[k] = v
+    self._initCheetahInstance(**cheetahKWArgs)
+""".replace('\n','\n'+' '*8)
+
+class ClassCompiler(GenUtils):
+    methodCompilerClass = AutoMethodCompiler
+    methodCompilerClassForInit = MethodCompiler
+        
+    def __init__(self, className, mainMethodName='respond',
+                 moduleCompiler=None,
+                 fileName=None,
+                 settingsManager=None):
+
+        self._settingsManager = settingsManager
+        self._fileName = fileName
+        self._className = className
+        self._moduleCompiler = moduleCompiler
+        self._mainMethodName = mainMethodName
+        self._setupState()
+        methodCompiler = self._spawnMethodCompiler(
+            mainMethodName,
+            initialMethodComment='## CHEETAH: main method generated for this template')
+
+        self._setActiveMethodCompiler(methodCompiler)
+        if fileName and self.setting('monitorSrcFile'):
+            self._addSourceFileMonitoring(fileName)
+
+    def setting(self, key):
+        return self._settingsManager.setting(key)
+
+    def __getattr__(self, name):
+        """Provide access to the methods and attributes of the MethodCompiler
+        at the top of the activeMethods stack: one-way namespace sharing
+
+        
+        WARNING: Use .setMethods to assign the attributes of the MethodCompiler
+        from the methods of this class!!! or you will be assigning to attributes
+        of this object instead."""
+        
+        if self.__dict__.has_key(name):
+            return self.__dict__[name]
+        elif hasattr(self.__class__, name):
+            return getattr(self.__class__, name)
+        elif self._activeMethodsList and hasattr(self._activeMethodsList[-1], name):
+            return getattr(self._activeMethodsList[-1], name)
+        else:
+            raise AttributeError, name
+
+    def _setupState(self):
+        self._classDef = None
+        self._decoratorsForNextMethod = []
+        self._activeMethodsList = []        # stack while parsing/generating
+        self._finishedMethodsList = []      # store by order
+        self._methodsIndex = {}      # store by name
+        self._baseClass = 'Template'
+        self._classDocStringLines = []
+        # printed after methods in the gen class def:
+        self._generatedAttribs = ['_CHEETAH__instanceInitialized = False']
+        self._generatedAttribs.append('_CHEETAH_version = __CHEETAH_version__')
+        self._generatedAttribs.append(
+            '_CHEETAH_versionTuple = __CHEETAH_versionTuple__')
+
+        if self.setting('addTimestampsToCompilerOutput'):
+            self._generatedAttribs.append('_CHEETAH_genTime = __CHEETAH_genTime__')
+            self._generatedAttribs.append('_CHEETAH_genTimestamp = __CHEETAH_genTimestamp__')
+
+        self._generatedAttribs.append('_CHEETAH_src = __CHEETAH_src__')
+        self._generatedAttribs.append(
+            '_CHEETAH_srcLastModified = __CHEETAH_srcLastModified__')
+
+        if self.setting('templateMetaclass'):
+            self._generatedAttribs.append('__metaclass__ = '+self.setting('templateMetaclass'))
+        self._initMethChunks = []        
+        self._blockMetaData = {}
+        self._errorCatcherCount = 0
+        self._placeholderToErrorCatcherMap = {}
+
+    def cleanupState(self):
+        while self._activeMethodsList:
+            methCompiler = self._popActiveMethodCompiler()
+            self._swallowMethodCompiler(methCompiler)
+        self._setupInitMethod()
+        if self._mainMethodName == 'respond':
+            if self.setting('setup__str__method'):
+                self._generatedAttribs.append('def __str__(self): return self.respond()')
+        self.addAttribute('_mainCheetahMethod_for_' + self._className +
+                           '= ' + repr(self._mainMethodName) )
+
+    def _setupInitMethod(self):
+        __init__ = self._spawnMethodCompiler('__init__',
+                                             klass=self.methodCompilerClassForInit)
+        __init__.setMethodSignature("def __init__(self, *args, **KWs)")
+        __init__.addChunk('super(%s, self).__init__(*args, **KWs)' % self._className)
+        __init__.addChunk(_initMethod_initCheetah % {'className' : self._className})
+        for chunk in self._initMethChunks:
+            __init__.addChunk(chunk)
+        __init__.cleanupState()
+        self._swallowMethodCompiler(__init__, pos=0)
+
+    def _addSourceFileMonitoring(self, fileName):
+        # @@TR: this stuff needs auditing for Cheetah 2.0       
+        # the first bit is added to init
+        self.addChunkToInit('self._filePath = ' + repr(fileName))
+        self.addChunkToInit('self._fileMtime = ' + str(getmtime(fileName)) )
+
+        # the rest is added to the main output method of the class ('mainMethod')
+        self.addChunk('if exists(self._filePath) and ' +
+                      'getmtime(self._filePath) > self._fileMtime:')
+        self.indent()
+        self.addChunk('self._compile(file=self._filePath, moduleName='+self._className + ')')
+        self.addChunk(
+            'write(getattr(self, self._mainCheetahMethod_for_' + self._className +
+            ')(trans=trans))')            
+        self.addStop()
+        self.dedent()
+    
+    def setClassName(self, name):
+        self._className = name
+
+    def className(self):
+        return self._className
+
+    def setBaseClass(self, baseClassName):
+        self._baseClass = baseClassName
+               
+    def setMainMethodName(self, methodName):
+        if methodName == self._mainMethodName:
+            return
+        ## change the name in the methodCompiler and add new reference
+        mainMethod = self._methodsIndex[self._mainMethodName]
+        mainMethod.setMethodName(methodName)
+        self._methodsIndex[methodName] = mainMethod
+
+        ## make sure that fileUpdate code still works properly:
+        chunkToChange = ('write(self.' + self._mainMethodName + '(trans=trans))')
+        chunks = mainMethod._methodBodyChunks
+        if chunkToChange in chunks:
+            for i in range(len(chunks)):
+                if chunks[i] == chunkToChange:
+                    chunks[i] = ('write(self.' + methodName + '(trans=trans))')
+        ## get rid of the old reference and update self._mainMethodName                   
+        del self._methodsIndex[self._mainMethodName]
+        self._mainMethodName = methodName
+
+    def setMainMethodArgs(self, argsList):
+        mainMethodCompiler = self._methodsIndex[self._mainMethodName]
+        for argName, defVal in argsList:
+            mainMethodCompiler.addMethArg(argName, defVal)
+        
+          
+    def _spawnMethodCompiler(self, methodName, klass=None, 
+                             initialMethodComment=None):
+        if klass is None:
+            klass = self.methodCompilerClass
+
+        decorators = self._decoratorsForNextMethod or []
+        self._decoratorsForNextMethod = []
+        methodCompiler = klass(methodName, classCompiler=self,
+                               decorators=decorators,
+                               initialMethodComment=initialMethodComment)
+        self._methodsIndex[methodName] = methodCompiler
+        return methodCompiler
+
+    def _setActiveMethodCompiler(self, methodCompiler):
+        self._activeMethodsList.append(methodCompiler)
+
+    def _getActiveMethodCompiler(self):
+        return self._activeMethodsList[-1]
+
+    def _popActiveMethodCompiler(self):
+        return self._activeMethodsList.pop()
+
+    def _swallowMethodCompiler(self, methodCompiler, pos=None):
+        methodCompiler.cleanupState()
+        if pos==None:
+            self._finishedMethodsList.append( methodCompiler )
+        else:
+            self._finishedMethodsList.insert(pos, methodCompiler)
+        return methodCompiler
+
+    def startMethodDef(self, methodName, argsList, parserComment):
+        methodCompiler = self._spawnMethodCompiler(
+            methodName, initialMethodComment=parserComment)
+        self._setActiveMethodCompiler(methodCompiler)        
+        for argName, defVal in argsList:
+            methodCompiler.addMethArg(argName, defVal)
+        
+    def _finishedMethods(self):
+        return self._finishedMethodsList
+
+    def addDecorator(self, decoratorExpr):
+        """Set the decorator to be used with the next method in the source.
+
+        See _spawnMethodCompiler() and MethodCompiler for the details of how
+        this is used.
+        """
+        self._decoratorsForNextMethod.append(decoratorExpr)
+
+    def addClassDocString(self, line):
+        self._classDocStringLines.append( line.replace('%','%%')) 
+
+    def addChunkToInit(self,chunk):
+        self._initMethChunks.append(chunk)
+
+    def addAttribute(self, attribExpr):
+        ## first test to make sure that the user hasn't used any fancy Cheetah syntax
+        #  (placeholders, directives, etc.) inside the expression 
+        if attribExpr.find('VFN(') != -1 or attribExpr.find('VFFSL(') != -1:
+            raise ParseError(self,
+                             'Invalid #attr directive.' +
+                             ' It should only contain simple Python literals.')
+        ## now add the attribute
+        self._generatedAttribs.append(attribExpr)
+
+    def addSuper(self, argsList, parserComment=None):        
+        className = self._className #self._baseClass
+        methodName = self._getActiveMethodCompiler().methodName()
+
+        argStringChunks = []
+        for arg in argsList:
+            chunk = arg[0]
+            if not arg[1] == None:
+                chunk += '=' + arg[1]
+            argStringChunks.append(chunk)
+        argString = ','.join(argStringChunks)
+
+        self.addFilteredChunk(
+            'super(%(className)s, self).%(methodName)s(%(argString)s)'%locals())
+
+    def addErrorCatcherCall(self, codeChunk, rawCode='', lineCol=''):
+        if self._placeholderToErrorCatcherMap.has_key(rawCode):
+            methodName = self._placeholderToErrorCatcherMap[rawCode]
+            if not self.setting('outputRowColComments'):
+                self._methodsIndex[methodName].addMethDocString(
+                    'plus at line %s, col %s'%lineCol)
+            return methodName
+
+        self._errorCatcherCount += 1
+        methodName = '__errorCatcher' + str(self._errorCatcherCount)
+        self._placeholderToErrorCatcherMap[rawCode] = methodName
+        
+        catcherMeth = self._spawnMethodCompiler(
+            methodName,
+            klass=MethodCompiler,
+            initialMethodComment=('## CHEETAH: Generated from ' + rawCode +
+                                  ' at line %s, col %s'%lineCol + '.')
+            )        
+        catcherMeth.setMethodSignature('def ' + methodName +
+                                       '(self, localsDict={})')
+                                        # is this use of localsDict right?
+        catcherMeth.addChunk('try:')
+        catcherMeth.indent()
+        catcherMeth.addChunk("return eval('''" + codeChunk +
+                             "''', globals(), localsDict)")
+        catcherMeth.dedent()
+        catcherMeth.addChunk('except self._CHEETAH__errorCatcher.exceptions(), e:')
+        catcherMeth.indent()        
+        catcherMeth.addChunk("return self._CHEETAH__errorCatcher.warn(exc_val=e, code= " +
+                             repr(codeChunk) + " , rawCode= " +
+                             repr(rawCode) + " , lineCol=" + str(lineCol) +")")
+        
+        catcherMeth.cleanupState()
+        
+        self._swallowMethodCompiler(catcherMeth)
+        return methodName
+
+    def closeDef(self):
+        self.commitStrConst()
+        methCompiler = self._popActiveMethodCompiler()
+        self._swallowMethodCompiler(methCompiler)
+
+    def closeBlock(self):
+        self.commitStrConst()
+        methCompiler = self._popActiveMethodCompiler()
+        methodName = methCompiler.methodName()
+        if self.setting('includeBlockMarkers'):
+            endMarker = self.setting('blockMarkerEnd')
+            methCompiler.addStrConst(endMarker[0] + methodName + endMarker[1])
+        self._swallowMethodCompiler(methCompiler)
+        
+        #metaData = self._blockMetaData[methodName] 
+        #rawDirective = metaData['raw']
+        #lineCol = metaData['lineCol']
+        
+        ## insert the code to call the block, caching if #cache directive is on
+        codeChunk = 'self.' + methodName + '(trans=trans)'
+        self.addChunk(codeChunk)
+        
+        #self.appendToPrevChunk(' # generated from ' + repr(rawDirective) )
+        #if self.setting('outputRowColComments'):
+        #    self.appendToPrevChunk(' at line %s, col %s' % lineCol + '.')
+
+
+    ## code wrapping methods
+    
+    def classDef(self):
+        if self._classDef:
+            return self._classDef
+        else:
+            return self.wrapClassDef()
+
+    __str__ = classDef
+    __unicode__ = classDef
+    
+    def wrapClassDef(self):
+        ind = self.setting('indentationStep')
+        classDefChunks = [self.classSignature(),
+                          self.classDocstring(),
+                          ]
+        def addMethods():
+            classDefChunks.extend([
+                ind + '#'*50,
+                ind + '## CHEETAH GENERATED METHODS',
+                '\n',
+                self.methodDefs(),
+                ])
+        def addAttributes():
+            classDefChunks.extend([
+                ind + '#'*50,
+                ind + '## CHEETAH GENERATED ATTRIBUTES',
+                '\n',
+                self.attributes(),
+                ])            
+        if self.setting('outputMethodsBeforeAttributes'):
+            addMethods()
+            addAttributes()
+        else:
+            addAttributes()
+            addMethods()
+            
+        classDef = '\n'.join(classDefChunks)
+        self._classDef = classDef
+        return classDef
+
+
+    def classSignature(self):
+        return "class %s(%s):" % (self.className(), self._baseClass)
+        
+    def classDocstring(self):
+        if not self._classDocStringLines:
+            return ''
+        ind = self.setting('indentationStep')
+        docStr = ('%(ind)s"""\n%(ind)s' +
+                  '\n%(ind)s'.join(self._classDocStringLines) +
+                  '\n%(ind)s"""\n'
+                  ) % {'ind':ind}
+        return  docStr
+
+    def methodDefs(self):
+        methodDefs = [methGen.methodDef() for methGen in self._finishedMethods()]
+        return '\n\n'.join(methodDefs)
+
+    def attributes(self):
+        attribs = [self.setting('indentationStep') + str(attrib)
+                      for attrib in self._generatedAttribs ]
+        return '\n\n'.join(attribs)
+  
+class AutoClassCompiler(ClassCompiler):
+    pass
+
+##################################################
+## MODULE COMPILERS
+
+class ModuleCompiler(SettingsManager, GenUtils):
+
+    parserClass = Parser
+    classCompilerClass = AutoClassCompiler
+    
+    def __init__(self, source=None, file=None,
+                 moduleName='DynamicallyCompiledCheetahTemplate',                 
+                 mainClassName=None, # string
+                 mainMethodName=None, # string
+                 baseclassName=None, # string
+                 extraImportStatements=None, # list of strings
+                 settings=None # dict
+                 ):
+        SettingsManager.__init__(self)
+        if settings:
+            self.updateSettings(settings)
+        # disable useStackFrames if the C version of NameMapper isn't compiled
+        # it's painfully slow in the Python version and bites Windows users all
+        # the time:
+        if not NameMapper.C_VERSION:
+            if not sys.platform.startswith('java'):
+                warnings.warn(
+                    "\nYou don't have the C version of NameMapper installed! "
+                    "I'm disabling Cheetah's useStackFrames option as it is "
+                    "painfully slow with the Python version of NameMapper. "
+                    "You should get a copy of Cheetah with the compiled C version of NameMapper."
+                    )
+            self.setSetting('useStackFrames', False)                    
+
+        self._compiled = False
+        self._moduleName = moduleName
+        if not mainClassName:
+            self._mainClassName = moduleName
+        else:
+            self._mainClassName = mainClassName
+        self._mainMethodNameArg = mainMethodName
+        if mainMethodName:
+            self.setSetting('mainMethodName', mainMethodName)
+        self._baseclassName = baseclassName
+        
+        self._filePath = None
+        self._fileMtime = None
+        
+        if source and file:
+            raise TypeError("Cannot compile from a source string AND file.")
+        elif isinstance(file, basestring): # it's a filename.
+            f = open(file) # Raises IOError.
+            source = f.read()
+            f.close()
+            self._filePath = file
+            self._fileMtime = os.path.getmtime(file)
+        elif hasattr(file, 'read'):
+            source = file.read()  # Can't set filename or mtime--they're not accessible.
+        elif file:
+            raise TypeError("'file' argument must be a filename string or file-like object")
+                
+        if self._filePath:
+            self._fileDirName, self._fileBaseName = os.path.split(self._filePath)
+            self._fileBaseNameRoot, self._fileBaseNameExt = os.path.splitext(self._fileBaseName)
+
+        if not isinstance(source, basestring):
+            source = unicode(source)
+            # by converting to string here we allow objects such as other Templates
+            # to be passed in
+
+        # Handle the #indent directive by converting it to other directives.
+        # (Over the long term we'll make it a real directive.)
+        if source == "":
+            warnings.warn("You supplied an empty string for the source!", )
+        
+        else:
+            unicodeMatch = unicodeDirectiveRE.search(source)
+            encodingMatch = encodingDirectiveRE.match(source)
+            if unicodeMatch:
+                if encodingMatch:
+                    raise ParseError(
+                        self, "#encoding and #unicode are mutually exclusive! "
+                        "Use one or the other.")
+                source = unicodeDirectiveRE.sub('', source)
+                if isinstance(source, str):
+                    encoding = unicodeMatch.group(1) or 'ascii'
+                    source = unicode(source, encoding)
+            elif encodingMatch:
+                encodings = encodingMatch.groups()
+                if len(encodings):
+                    encoding = encodings[0]
+                    source = source.decode(encoding)
+            else:
+                source = unicode(source)
+
+        if source.find('#indent') != -1: #@@TR: undocumented hack
+            source = indentize(source)
+
+        self._parser = self.parserClass(source, filename=self._filePath, compiler=self)
+        self._setupCompilerState()
+        
+    def __getattr__(self, name):
+        """Provide one-way access to the methods and attributes of the
+        ClassCompiler, and thereby the MethodCompilers as well.
+
+        WARNING: Use .setMethods to assign the attributes of the ClassCompiler
+        from the methods of this class!!! or you will be assigning to attributes
+        of this object instead.
+        """
+        if self.__dict__.has_key(name):
+            return self.__dict__[name]
+        elif hasattr(self.__class__, name):
+            return getattr(self.__class__, name)
+        elif self._activeClassesList and hasattr(self._activeClassesList[-1], name):
+            return getattr(self._activeClassesList[-1], name)
+        else:
+            raise AttributeError, name
+
+    def _initializeSettings(self):
+        self.updateSettings(copy.deepcopy(DEFAULT_COMPILER_SETTINGS))
+        
+    def _setupCompilerState(self):
+        self._activeClassesList = []
+        self._finishedClassesList = []      # listed by ordered 
+        self._finishedClassIndex = {}  # listed by name
+        self._moduleDef = None
+        self._moduleShBang = '#!/usr/bin/env python'
+        self._moduleEncoding = 'ascii'
+        self._moduleEncodingStr = ''
+        self._moduleHeaderLines = []
+        self._moduleDocStringLines = []
+        self._specialVars = {}
+        self._importStatements = [
+            "import sys",
+            "import os",
+            "import os.path",
+            "import __builtin__",
+            "from os.path import getmtime, exists",
+            "import time",
+            "import types",
+            "from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion",            
+            "from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple",
+            "from Cheetah.Template import Template",
+            "from Cheetah.DummyTransaction import *",
+            "from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList",
+            "from Cheetah.CacheRegion import CacheRegion",
+            "import Cheetah.Filters as Filters",
+            "import Cheetah.ErrorCatchers as ErrorCatchers",
+            ]        
+
+        self._importedVarNames = ['sys',
+                                  'os',
+                                  'os.path',
+                                  'time',
+                                  'types',
+                                  'Template',
+                                  'DummyTransaction',
+                                  'NotFound',
+                                  'Filters',
+                                  'ErrorCatchers',
+                                  'CacheRegion',
+                                  ]
+        
+        self._moduleConstants = [
+            "VFFSL=valueFromFrameOrSearchList",
+            "VFSL=valueFromSearchList",
+            "VFN=valueForName",
+            "currentTime=time.time",
+            ]
+        
+    def compile(self):
+        classCompiler = self._spawnClassCompiler(self._mainClassName)            
+        if self._baseclassName:
+            classCompiler.setBaseClass(self._baseclassName)
+        self._addActiveClassCompiler(classCompiler)
+        self._parser.parse()
+        self._swallowClassCompiler(self._popActiveClassCompiler())
+        self._compiled = True
+        self._parser.cleanup()
+        
+    def _spawnClassCompiler(self, className, klass=None):
+        if klass is None:
+            klass = self.classCompilerClass
+        classCompiler = klass(className,
+                              moduleCompiler=self,
+                              mainMethodName=self.setting('mainMethodName'),
+                              fileName=self._filePath,
+                              settingsManager=self,
+                              )
+        return classCompiler
+
+    def _addActiveClassCompiler(self, classCompiler):
+        self._activeClassesList.append(classCompiler)
+
+    def _getActiveClassCompiler(self):
+        return self._activeClassesList[-1]
+
+    def _popActiveClassCompiler(self):
+        return self._activeClassesList.pop()
+
+    def _swallowClassCompiler(self, classCompiler):
+        classCompiler.cleanupState()
+        self._finishedClassesList.append( classCompiler )
+        self._finishedClassIndex[classCompiler.className()] = classCompiler
+        return classCompiler
+
+    def _finishedClasses(self):
+        return self._finishedClassesList
+
+    def importedVarNames(self):
+        return self._importedVarNames
+    
+    def addImportedVarNames(self, varNames, raw_statement=None):
+        settings = self.settings()
+        if not varNames:
+            return 
+        if self._methodBodyChunks and raw_statement and not settings.get('useLegacyImportMode'):
+            self.addChunk(raw_statement)
+        else:
+            self._importedVarNames.extend(varNames)
+
+    ## methods for adding stuff to the module and class definitions
+
+    def setBaseClass(self, baseClassName):
+        if self._mainMethodNameArg:
+            self.setMainMethodName(self._mainMethodNameArg)
+        else:
+            self.setMainMethodName(self.setting('mainMethodNameForSubclasses'))
+       
+        if self.setting('handlerForExtendsDirective'):
+            handler = self.setting('handlerForExtendsDirective')
+            baseClassName = handler(compiler=self, baseClassName=baseClassName)
+            self._getActiveClassCompiler().setBaseClass(baseClassName)
+        elif (not self.setting('autoImportForExtendsDirective')
+            or baseClassName=='object' or baseClassName in self.importedVarNames()):
+            self._getActiveClassCompiler().setBaseClass(baseClassName)
+            # no need to import
+        else:
+            ##################################################
+            ## If the #extends directive contains a classname or modulename that isn't
+            #  in self.importedVarNames() already, we assume that we need to add
+            #  an implied 'from ModName import ClassName' where ModName == ClassName.
+            #  - This is the case in WebKit servlet modules.
+            #  - We also assume that the final . separates the classname from the
+            #    module name.  This might break if people do something really fancy 
+            #    with their dots and namespaces.
+            chunks = baseClassName.split('.')
+            if len(chunks)==1:
+                self._getActiveClassCompiler().setBaseClass(baseClassName)
+                if baseClassName not in self.importedVarNames():
+                    modName = baseClassName
+                    # we assume the class name to be the module name
+                    # and that it's not a builtin:
+                    importStatement = "from %s import %s" % (modName, baseClassName)
+                    self.addImportStatement(importStatement)
+                    self.addImportedVarNames( [baseClassName,] ) 
+            else:
+                needToAddImport = True
+                modName = chunks[0]
+                #print chunks, ':', self.importedVarNames()
+                for chunk in chunks[1:-1]:
+                    if modName in self.importedVarNames():
+                        needToAddImport = False
+                        finalBaseClassName = baseClassName.replace(modName+'.', '')
+                        self._getActiveClassCompiler().setBaseClass(finalBaseClassName)
+                        break
+                    else:
+                        modName += '.'+chunk                        
+                if needToAddImport:
+                    modName, finalClassName = '.'.join(chunks[:-1]), chunks[-1]                
+                    #if finalClassName != chunks[:-1][-1]:
+                    if finalClassName != chunks[-2]:
+                        # we assume the class name to be the module name
+                        modName = '.'.join(chunks)
+                    self._getActiveClassCompiler().setBaseClass(finalClassName)                        
+                    importStatement = "from %s import %s" % (modName, finalClassName)
+                    self.addImportStatement(importStatement)
+                    self.addImportedVarNames( [finalClassName,] ) 
+            
+    def setCompilerSetting(self, key, valueExpr):
+        self.setSetting(key, eval(valueExpr) )
+        self._parser.configureParser()
+
+    def setCompilerSettings(self, keywords, settingsStr):
+        KWs = keywords
+        merge = True
+        if 'nomerge' in KWs:
+            merge = False
+            
+        if 'reset' in KWs:
+            # @@TR: this is actually caught by the parser at the moment. 
+            # subject to change in the future
+            self._initializeSettings()
+            self._parser.configureParser()
+            return
+        elif 'python' in KWs:
+            settingsReader = self.updateSettingsFromPySrcStr
+            # this comes from SettingsManager
+        else:
+            # this comes from SettingsManager
+            settingsReader = self.updateSettingsFromConfigStr
+
+        settingsReader(settingsStr)
+        self._parser.configureParser()
+        
+    def setShBang(self, shBang):
+        self._moduleShBang = shBang
+    
+    def setModuleEncoding(self, encoding):
+        self._moduleEncoding = encoding
+
+    def getModuleEncoding(self):
+        return self._moduleEncoding
+
+    def addModuleHeader(self, line):
+        """Adds a header comment to the top of the generated module.
+        """
+        self._moduleHeaderLines.append(line)
+        
+    def addModuleDocString(self, line):        
+        """Adds a line to the generated module docstring.
+        """
+        self._moduleDocStringLines.append(line)
+
+    def addModuleGlobal(self, line):
+        """Adds a line of global module code.  It is inserted after the import
+        statements and Cheetah default module constants.
+        """
+        self._moduleConstants.append(line)
+
+    def addSpecialVar(self, basename, contents, includeUnderscores=True):
+        """Adds module __specialConstant__ to the module globals.
+        """
+        name = includeUnderscores and '__'+basename+'__' or basename
+        self._specialVars[name] = contents.strip()
+
+    def addImportStatement(self, impStatement):
+        settings = self.settings()
+        if not self._methodBodyChunks or settings.get('useLegacyImportMode'):
+            # In the case where we are importing inline in the middle of a source block
+            # we don't want to inadvertantly import the module at the top of the file either
+            self._importStatements.append(impStatement)
+
+        #@@TR 2005-01-01: there's almost certainly a cleaner way to do this!
+        importVarNames = impStatement[impStatement.find('import') + len('import'):].split(',')
+        importVarNames = [var.split()[-1] for var in importVarNames] # handles aliases
+        importVarNames = [var for var in importVarNames if not var == '*']
+        self.addImportedVarNames(importVarNames, raw_statement=impStatement) #used by #extend for auto-imports
+
+    def addAttribute(self, attribName, expr):
+        self._getActiveClassCompiler().addAttribute(attribName + ' =' + expr)
+        
+    def addComment(self, comm):
+        if re.match(r'#+$',comm):      # skip bar comments
+            return
+        
+        specialVarMatch = specialVarRE.match(comm)
+        if specialVarMatch:
+            # @@TR: this is a bit hackish and is being replaced with
+            # #set module varName = ...
+            return self.addSpecialVar(specialVarMatch.group(1),
+                                      comm[specialVarMatch.end():])
+        elif comm.startswith('doc:'):
+            addLine = self.addMethDocString
+            comm = comm[len('doc:'):].strip()
+        elif comm.startswith('doc-method:'):
+            addLine = self.addMethDocString
+            comm = comm[len('doc-method:'):].strip()
+        elif comm.startswith('doc-module:'):
+            addLine = self.addModuleDocString
+            comm = comm[len('doc-module:'):].strip()
+        elif comm.startswith('doc-class:'):
+            addLine = self.addClassDocString
+            comm = comm[len('doc-class:'):].strip()
+        elif comm.startswith('header:'):
+            addLine = self.addModuleHeader
+            comm = comm[len('header:'):].strip()
+        else:
+            addLine = self.addMethComment
+
+        for line in comm.splitlines():
+            addLine(line)
+
+    ## methods for module code wrapping
+    
+    def getModuleCode(self):
+        if not self._compiled:
+            self.compile()
+        if self._moduleDef:
+            return self._moduleDef
+        else:
+            return self.wrapModuleDef()
+        
+    __str__ = getModuleCode
+
+    def wrapModuleDef(self):
+        self.addSpecialVar('CHEETAH_docstring', self.setting('defDocStrMsg'))
+        self.addModuleGlobal('__CHEETAH_version__ = %r'%Version)
+        self.addModuleGlobal('__CHEETAH_versionTuple__ = %r'%(VersionTuple,))        
+        if self.setting('addTimestampsToCompilerOutput'):
+            self.addModuleGlobal('__CHEETAH_genTime__ = %r'%time.time())
+            self.addModuleGlobal('__CHEETAH_genTimestamp__ = %r'%self.timestamp())
+        if self._filePath:
+            timestamp = self.timestamp(self._fileMtime)
+            self.addModuleGlobal('__CHEETAH_src__ = %r'%self._filePath)
+            self.addModuleGlobal('__CHEETAH_srcLastModified__ = %r'%timestamp)
+        else:
+            self.addModuleGlobal('__CHEETAH_src__ = None')
+            self.addModuleGlobal('__CHEETAH_srcLastModified__ = None')            
+
+        moduleDef = """%(header)s
+%(docstring)s
+
+##################################################
+## DEPENDENCIES
+%(imports)s
+
+##################################################
+## MODULE CONSTANTS
+%(constants)s
+%(specialVars)s
+
+if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
+    raise AssertionError(
+      'This template was compiled with Cheetah version'
+      ' %%s. Templates compiled before version %%s must be recompiled.'%%(
+         __CHEETAH_version__, RequiredCheetahVersion))
+
+##################################################
+## CLASSES
+
+%(classes)s
+
+## END CLASS DEFINITION
+
+if not hasattr(%(mainClassName)s, '_initCheetahAttributes'):
+    templateAPIClass = getattr(%(mainClassName)s, '_CHEETAH_templateClass', Template)
+    templateAPIClass._addCheetahPlumbingCodeToClass(%(mainClassName)s)
+
+%(footer)s
+""" %   {'header':self.moduleHeader(),
+         'docstring':self.moduleDocstring(),
+         'specialVars':self.specialVars(),
+         'imports':self.importStatements(),
+         'constants':self.moduleConstants(),
+         'classes':self.classDefs(),
+         'footer':self.moduleFooter(),
+         'mainClassName':self._mainClassName,
+         }
+       
+        self._moduleDef = moduleDef
+        return moduleDef
+
+    def timestamp(self, theTime=None):
+        if not theTime:
+            theTime = time.time()
+        return time.asctime(time.localtime(theTime))
+    
+    def moduleHeader(self):
+        header = self._moduleShBang + '\n'
+        header += self._moduleEncodingStr + '\n'
+        if self._moduleHeaderLines:
+            offSet = self.setting('commentOffset')
+        
+            header += (
+                '#' + ' '*offSet + 
+                ('\n#'+ ' '*offSet).join(self._moduleHeaderLines) + '\n')
+
+        return header
+
+    def moduleDocstring(self):
+        if not self._moduleDocStringLines:
+            return ''
+        
+        return ('"""' +
+                '\n'.join(self._moduleDocStringLines) +
+                '\n"""\n')
+
+    def specialVars(self):
+        chunks = []
+        theVars = self._specialVars
+        keys = theVars.keys()
+        keys.sort()
+        for key in keys:
+            chunks.append(key + ' = ' + repr(theVars[key])  )
+        return '\n'.join(chunks)
+        
+    def importStatements(self):
+        return '\n'.join(self._importStatements)
+        
+    def moduleConstants(self):
+        return '\n'.join(self._moduleConstants)
+
+    def classDefs(self):
+        classDefs = [klass.classDef() for klass in self._finishedClasses()]
+        return '\n\n'.join(classDefs)
+
+    def moduleFooter(self):
+        return """
+# CHEETAH was developed by Tavis Rudd and Mike Orr
+# with code, advice and input from many other volunteers.
+# For more information visit http://www.CheetahTemplate.org/
+
+##################################################
+## if run from command line:
+if __name__ == '__main__':
+    from Cheetah.TemplateCmdLineIface import CmdLineIface
+    CmdLineIface(templateObj=%(className)s()).run()
+
+""" % {'className':self._mainClassName}
+
+
+##################################################
+## Make Compiler an alias for ModuleCompiler
+    
+Compiler = ModuleCompiler

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Django.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Django.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Django.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+import Cheetah.Template
+
+def render(template_file, **kwargs):
+    '''
+        Cheetah.Django.render() takes the template filename 
+        (the filename should be a file in your Django 
+        TEMPLATE_DIRS)
+
+        Any additional keyword arguments are passed into the 
+        template are propogated into the template's searchList
+    '''
+    import django.http
+    import django.template.loader
+    source, loader = django.template.loader.find_template_source(template_file)
+    t = Cheetah.Template.Template(source, searchList=[kwargs])
+    return django.http.HttpResponse(t.__str__())

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/DummyTransaction.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/DummyTransaction.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/DummyTransaction.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,96 @@
+#!/usr/bin/env python
+
+'''
+Provides dummy Transaction and Response classes is used by Cheetah in place
+of real Webware transactions when the Template obj is not used directly as a
+Webware servlet.
+
+Warning: This may be deprecated in the future, please do not rely on any 
+specific DummyTransaction or DummyResponse behavior
+'''
+
+import types
+
+class DummyResponseFailure(Exception):
+    pass
+
+class DummyResponse(object):
+    '''
+        A dummy Response class is used by Cheetah in place of real Webware
+        Response objects when the Template obj is not used directly as a Webware
+        servlet
+    ''' 
+    def __init__(self):
+        self._outputChunks = []
+
+    def flush(self):
+        pass
+        
+    def write(self, value):
+        self._outputChunks.append(value)
+
+    def writeln(self, txt):
+        write(txt)
+        write('\n')
+
+    def getvalue(self, outputChunks=None):
+        chunks = outputChunks or self._outputChunks
+        try: 
+            return ''.join(chunks)
+        except UnicodeDecodeError, ex:
+            nonunicode = [c for c in chunks if not isinstance(c, unicode)]
+            raise DummyResponseFailure('''Looks like you're trying to mix encoded strings with Unicode strings
+            (most likely utf-8 encoded ones)
+
+            This can happen if you're using the `EncodeUnicode` filter, or if you're manually
+            encoding strings as utf-8 before passing them in on the searchList (possible offenders: 
+            %s) 
+            (%s)''' % (nonunicode, ex))
+
+
+    def writelines(self, *lines):
+        ## not used
+        [self.writeln(ln) for ln in lines]
+        
+
+class DummyTransaction(object):
+    '''
+        A dummy Transaction class is used by Cheetah in place of real Webware
+        transactions when the Template obj is not used directly as a Webware
+        servlet.
+
+        It only provides a response object and method.  All other methods and
+        attributes make no sense in this context.
+    '''
+    def __init__(self, *args, **kwargs):
+        self._response = None
+
+    def response(self, resp=None):
+        if self._response is None:
+            self._response = resp or DummyResponse()
+        return self._response
+
+
+class TransformerResponse(DummyResponse):
+    def __init__(self, *args, **kwargs):
+        super(TransformerResponse, self).__init__(*args, **kwargs)
+        self._filter = None
+
+    def getvalue(self, **kwargs):
+        output = super(TransformerResponse, self).getvalue(**kwargs)
+        if self._filter:
+            _filter = self._filter
+            if isinstance(_filter, types.TypeType):
+                _filter = _filter()
+            return _filter.filter(output)
+        return output
+
+
+class TransformerTransaction(object):
+    def __init__(self, *args, **kwargs):
+        self._response = None
+    def response(self):
+        if self._response:
+            return self._response
+        return TransformerResponse()
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ErrorCatchers.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ErrorCatchers.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ErrorCatchers.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,63 @@
+#!/usr/bin/env python
+# $Id: ErrorCatchers.py,v 1.7 2005/01/03 19:59:07 tavis_rudd Exp $
+"""ErrorCatcher class for Cheetah Templates
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+Version: $Revision: 1.7 $
+Start Date: 2001/08/01
+Last Revision Date: $Date: 2005/01/03 19:59:07 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.7 $"[11:-2]
+
+import time
+from Cheetah.NameMapper import NotFound
+
+class Error(Exception):
+    pass
+
+class ErrorCatcher:
+    _exceptionsToCatch = (NotFound,)
+    
+    def __init__(self, templateObj):
+        pass
+    
+    def exceptions(self):
+        return self._exceptionsToCatch
+    
+    def warn(self, exc_val, code, rawCode, lineCol):
+        return rawCode
+## make an alias
+Echo = ErrorCatcher
+
+class BigEcho(ErrorCatcher):
+    def warn(self, exc_val, code, rawCode, lineCol):
+        return "="*15 + "&lt;" + rawCode + " could not be found&gt;" + "="*15
+
+class KeyError(ErrorCatcher):
+    def warn(self, exc_val, code, rawCode, lineCol):
+        raise KeyError("no '%s' in this Template Object's Search List" % rawCode) 
+
+class ListErrors(ErrorCatcher):
+    """Accumulate a list of errors."""
+    _timeFormat = "%c"
+    
+    def __init__(self, templateObj):
+        ErrorCatcher.__init__(self, templateObj)
+        self._errors = []
+
+    def warn(self, exc_val, code, rawCode, lineCol):
+        dict = locals().copy()
+        del dict['self']
+        dict['time'] = time.strftime(self._timeFormat,
+                                     time.localtime(time.time()))
+        self._errors.append(dict)
+        return rawCode
+    
+    def listErrors(self):
+        """Return the list of errors."""
+        return self._errors
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/FileUtils.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/FileUtils.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/FileUtils.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,374 @@
+#!/usr/bin/env python
+# $Id: FileUtils.py,v 1.12 2005/11/02 22:26:07 tavis_rudd Exp $
+"""File utitilies for Python:
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.12 $
+Start Date: 2001/09/26
+Last Revision Date: $Date: 2005/11/02 22:26:07 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.12 $"[11:-2]
+
+
+from glob import glob
+import os
+from os import listdir
+import os.path
+import re
+from types import StringType
+from tempfile import mktemp
+
+def _escapeRegexChars(txt,
+                     escapeRE=re.compile(r'([\$\^\*\+\.\?\{\}\[\]\(\)\|\\])')):
+    return escapeRE.sub(r'\\\1' , txt)
+
+def findFiles(*args, **kw):
+    """Recursively find all the files matching a glob pattern.
+
+    This function is a wrapper around the FileFinder class.  See its docstring
+    for details about the accepted arguments, etc."""
+    
+    return FileFinder(*args, **kw).files()
+            
+def replaceStrInFiles(files, theStr, repl):
+
+    """Replace all instances of 'theStr' with 'repl' for each file in the 'files'
+    list. Returns a dictionary with data about the matches found.
+
+    This is like string.replace() on a multi-file basis.
+
+    This function is a wrapper around the FindAndReplace class. See its
+    docstring for more details."""
+    
+    pattern = _escapeRegexChars(theStr)
+    return FindAndReplace(files, pattern, repl).results()
+
+def replaceRegexInFiles(files, pattern, repl):
+
+    """Replace all instances of regex 'pattern' with 'repl' for each file in the
+    'files' list. Returns a dictionary with data about the matches found.
+
+    This is like re.sub on a multi-file basis.
+
+    This function is a wrapper around the FindAndReplace class. See its
+    docstring for more details."""
+
+    return FindAndReplace(files, pattern, repl).results()
+
+
+##################################################
+## CLASSES
+
+class FileFinder:
+    
+    """Traverses a directory tree and finds all files in it that match one of
+    the specified glob patterns."""
+    
+    def __init__(self, rootPath,
+                 globPatterns=('*',),
+                 ignoreBasenames=('CVS','.svn'),
+                 ignoreDirs=(),
+                 ):
+        
+        self._rootPath = rootPath
+        self._globPatterns = globPatterns
+        self._ignoreBasenames = ignoreBasenames
+        self._ignoreDirs = ignoreDirs
+        self._files = []
+        
+        self.walkDirTree(rootPath)
+            
+    def walkDirTree(self, dir='.',
+                    
+                    listdir=os.listdir,
+                    isdir=os.path.isdir,
+                    join=os.path.join,
+                    ):
+
+        """Recursively walk through a directory tree and find matching files."""
+        processDir = self.processDir
+        filterDir = self.filterDir
+        
+        pendingDirs = [dir]
+        addDir = pendingDirs.append
+        getDir = pendingDirs.pop
+        
+        while pendingDirs:
+            dir = getDir()
+            ##  process this dir
+            processDir(dir)
+            
+            ## and add sub-dirs 
+            for baseName in listdir(dir):
+                fullPath = join(dir, baseName)
+                if isdir(fullPath):
+                    if filterDir(baseName, fullPath):
+                        addDir( fullPath )
+
+    def filterDir(self, baseName, fullPath):
+        
+        """A hook for filtering out certain dirs. """
+        
+        return not (baseName in self._ignoreBasenames or 
+                    fullPath in self._ignoreDirs)
+    
+    def processDir(self, dir, glob=glob):
+        extend = self._files.extend
+        for pattern in self._globPatterns:
+            extend( glob(os.path.join(dir, pattern)) )
+    
+    def files(self):
+        return self._files
+
+class _GenSubberFunc:
+
+    """Converts a 'sub' string in the form that one feeds to re.sub (backrefs,
+    groups, etc.) into a function that can be used to do the substitutions in
+    the FindAndReplace class."""
+    
+    backrefRE = re.compile(r'\\([1-9][0-9]*)')
+    groupRE = re.compile(r'\\g<([a-zA-Z_][a-zA-Z_]*)>')
+    
+    def __init__(self, replaceStr):
+        self._src = replaceStr
+        self._pos = 0
+        self._codeChunks = []
+        self.parse()
+
+    def src(self):
+        return self._src
+        
+    def pos(self):
+        return self._pos
+    
+    def setPos(self, pos):
+        self._pos = pos
+
+    def atEnd(self):
+        return self._pos >= len(self._src)
+
+    def advance(self, offset=1):
+        self._pos += offset
+
+    def readTo(self, to, start=None):
+        if start == None:
+            start = self._pos
+        self._pos = to
+        if self.atEnd():
+            return self._src[start:]
+        else:
+            return self._src[start:to]
+
+    ## match and get methods
+        
+    def matchBackref(self):
+        return self.backrefRE.match(self.src(), self.pos())
+
+    def getBackref(self):
+        m = self.matchBackref()
+        self.setPos(m.end())
+        return m.group(1)
+        
+    def matchGroup(self):
+        return self.groupRE.match(self.src(), self.pos())
+
+    def getGroup(self):
+        m = self.matchGroup()
+        self.setPos(m.end())
+        return m.group(1)
+
+    ## main parse loop and the eat methods
+    
+    def parse(self):
+        while not self.atEnd():
+            if self.matchBackref():
+                self.eatBackref()
+            elif self.matchGroup():
+                self.eatGroup()
+            else:
+                self.eatStrConst()
+                
+    def eatStrConst(self):
+        startPos = self.pos()
+        while not self.atEnd():
+            if self.matchBackref() or self.matchGroup():
+                break
+            else:
+                self.advance()
+        strConst = self.readTo(self.pos(), start=startPos)
+        self.addChunk(repr(strConst))
+    
+    def eatBackref(self):
+        self.addChunk( 'm.group(' + self.getBackref() + ')' )
+
+    def eatGroup(self):
+        self.addChunk( 'm.group("' + self.getGroup() + '")' )
+    
+    def addChunk(self, chunk):
+        self._codeChunks.append(chunk)
+
+    ## code wrapping methods
+
+    def codeBody(self):
+        return ', '.join(self._codeChunks)
+
+    def code(self):
+        return "def subber(m):\n\treturn ''.join([%s])\n" % (self.codeBody())
+    
+    def subberFunc(self):
+        exec self.code()
+        return subber
+
+
+class FindAndReplace:
+    
+    """Find and replace all instances of 'patternOrRE' with 'replacement' for
+    each file in the 'files' list. This is a multi-file version of re.sub().
+
+    'patternOrRE' can be a raw regex pattern or
+    a regex object as generated by the re module. 'replacement' can be any
+    string that would work with patternOrRE.sub(replacement, fileContents).
+    """
+    
+    def __init__(self, files, patternOrRE, replacement,
+                 recordResults=True):
+
+        
+        if type(patternOrRE) == StringType:
+            self._regex = re.compile(patternOrRE)
+        else:
+            self._regex = patternOrRE
+        if type(replacement) == StringType:
+            self._subber = _GenSubberFunc(replacement).subberFunc()
+        else:
+            self._subber = replacement
+
+        self._pattern = pattern = self._regex.pattern
+        self._files = files
+        self._results = {}
+        self._recordResults = recordResults
+
+        ## see if we should use pgrep to do the file matching
+        self._usePgrep = False
+        if (os.popen3('pgrep')[2].read()).startswith('Usage:'):
+            ## now check to make sure pgrep understands the pattern
+            tmpFile = mktemp()
+            open(tmpFile, 'w').write('#')
+            if not (os.popen3('pgrep "' + pattern + '" ' + tmpFile)[2].read()):
+                # it didn't print an error msg so we're ok
+                self._usePgrep = True
+            os.remove(tmpFile)
+
+        self._run()
+
+    def results(self):
+        return self._results
+    
+    def _run(self):
+        regex = self._regex
+        subber = self._subDispatcher
+        usePgrep = self._usePgrep
+        pattern = self._pattern
+        for file in self._files:
+            if not os.path.isfile(file):
+                continue # skip dirs etc.
+            
+            self._currFile = file
+            found = False
+            if locals().has_key('orig'):
+                del orig
+            if self._usePgrep:
+                if os.popen('pgrep "' + pattern + '" ' + file ).read():
+                    found = True
+            else:
+                orig = open(file).read()
+                if regex.search(orig):
+                    found = True
+            if found:
+                if not locals().has_key('orig'):
+                    orig = open(file).read()
+                new = regex.sub(subber, orig)
+                open(file, 'w').write(new)
+
+    def _subDispatcher(self, match):
+        if self._recordResults:
+            if not self._results.has_key(self._currFile):
+                res = self._results[self._currFile] = {}
+                res['count'] = 0
+                res['matches'] = []
+            else:
+                res = self._results[self._currFile]
+            res['count'] += 1
+            res['matches'].append({'contents':match.group(),
+                                   'start':match.start(),
+                                   'end':match.end(),
+                                   }
+                                   )
+        return self._subber(match)
+
+
+class SourceFileStats:
+
+    """
+    """
+    
+    _fileStats = None
+    
+    def __init__(self, files):
+        self._fileStats = stats = {}
+        for file in files:
+            stats[file] = self.getFileStats(file)
+
+    def rawStats(self):
+        return self._fileStats
+
+    def summary(self):
+        codeLines = 0
+        blankLines = 0
+        commentLines = 0
+        totalLines = 0
+        for fileStats in self.rawStats().values():
+            codeLines += fileStats['codeLines']
+            blankLines += fileStats['blankLines']
+            commentLines += fileStats['commentLines']
+            totalLines += fileStats['totalLines']
+            
+        stats = {'codeLines':codeLines,
+                 'blankLines':blankLines,
+                 'commentLines':commentLines,
+                 'totalLines':totalLines,
+                 }
+        return stats
+        
+    def printStats(self):
+        pass
+
+    def getFileStats(self, fileName):
+        codeLines = 0
+        blankLines = 0
+        commentLines = 0 
+        commentLineRe = re.compile(r'\s#.*$')
+        blankLineRe = re.compile('\s$')
+        lines = open(fileName).read().splitlines()
+        totalLines = len(lines)
+        
+        for line in lines:
+            if commentLineRe.match(line):
+                commentLines += 1
+            elif blankLineRe.match(line):
+                blankLines += 1
+            else:
+                codeLines += 1
+
+        stats = {'codeLines':codeLines,
+                 'blankLines':blankLines,
+                 'commentLines':commentLines,
+                 'totalLines':totalLines,
+                 }
+        
+        return stats

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Filters.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Filters.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Filters.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,241 @@
+#!/usr/bin/env python
+'''
+    Filters for the #filter directive as well as #transform
+    
+    #filter results in output filters Cheetah's $placeholders .
+    #transform results in a filter on the entirety of the output
+'''
+import sys
+import Cheetah.contrib
+
+# Additional entities WebSafe knows how to transform.  No need to include
+# '<', '>' or '&' since those will have been done already.
+webSafeEntities = {' ': '&nbsp;', '"': '&quot;'}
+
+class Filter(object):
+    """A baseclass for the Cheetah Filters."""
+    
+    def __init__(self, template=None):
+        """Setup a reference to the template that is using the filter instance.
+        This reference isn't used by any of the standard filters, but is
+        available to Filter subclasses, should they need it.
+        
+        Subclasses should call this method.
+        """
+        self.template = template
+        
+    def filter(self, val,
+               #encoding='utf8',
+               encoding=None,
+               str=str, 
+               **kw):
+        """Pass Unicode strings through unmolested, unless an encoding is specified.
+        """
+        if isinstance(val, unicode):
+            if encoding:
+                filtered = val.encode(encoding)
+            else:
+                filtered = val
+        elif val is None:
+            filtered = ''
+        else:
+            try:
+                filtered = str(val)
+            except UnicodeEncodeError:
+                filtered = unicode(val)
+        return filtered
+
+RawOrEncodedUnicode = Filter
+
+
+class EncodeUnicode(Filter):
+    def filter(self, val,
+               encoding='utf8',
+               str=str,
+               **kw):
+        """Encode Unicode strings, by default in UTF-8.
+
+        >>> import Cheetah.Template
+        >>> t = Cheetah.Template.Template('''
+        ... $myvar
+        ... ${myvar, encoding='utf16'}
+        ... ''', searchList=[{'myvar': u'Asni\xe8res'}],
+        ... filter='EncodeUnicode')
+        >>> print t
+        """
+        if isinstance(val, unicode):
+            return val.encode(encoding)
+        if val is None:
+            return ''
+        return str(val)
+
+
+class Markdown(EncodeUnicode):
+    '''
+        Markdown will change regular strings to Markdown
+            (http://daringfireball.net/projects/markdown/)
+
+        Such that:
+            My Header
+            =========
+        Becaomes:
+            <h1>My Header</h1>
+
+        and so on.
+
+        Markdown is meant to be used with the #transform 
+        tag, as it's usefulness with #filter is marginal at
+        best
+    '''
+    def filter(self,  value, **kwargs):
+        # This is a bit of a hack to allow outright embedding of the markdown module
+        try:
+            markdown_path = '/'.join(Cheetah.contrib.__file__.split('/')[:-1])
+            sys.path.append(markdown_path)
+            from Cheetah.contrib import markdown
+            sys.path.pop()
+        except:
+            print '>>> Exception raised importing the "markdown" module'
+            print '>>> Are you sure you have the ElementTree module installed?'
+            print '          http://effbot.org/downloads/#elementtree'
+            raise
+
+        encoded = super(Markdown, self).filter(value, **kwargs)
+        return markdown.markdown(encoded)
+
+class CodeHighlighter(EncodeUnicode):
+    '''
+        The CodeHighlighter filter depends on the "pygments" module which you can 
+        download and install from: http://pygments.org
+
+        What the CodeHighlighter assumes the string that it's receiving is source
+        code and uses pygments.lexers.guess_lexer() to try to guess which parser
+        to use when highlighting it. 
+
+        CodeHighlighter will return the HTML and CSS to render the code block, syntax 
+        highlighted, in a browser
+
+        NOTE: I had an issue installing pygments on Linux/amd64/Python 2.6 dealing with
+        importing of pygments.lexers, I was able to correct the failure by adding:
+            raise ImportError
+        to line 39 of pygments/plugin.py (since importing pkg_resources was causing issues)
+    '''
+    def filter(self, source, **kwargs):
+        encoded = super(CodeHighlighter, self).filter(source, **kwargs)
+        try:
+            from pygments import highlight
+            from pygments import lexers
+            from pygments import formatters
+        except ImportError, ex:
+            print '<%s> - Failed to import pygments! (%s)' % (self.__class__.__name__, ex)
+            print '-- You may need to install it from: http://pygments.org'
+            return encoded
+
+        lexer = None
+        try:
+            lexer = lexers.guess_lexer(source)
+        except lexers.ClassNotFound:
+            lexer = lexers.PythonLexer()
+
+        formatter = formatters.HtmlFormatter(cssclass='code_highlighter')
+        encoded = highlight(encoded, lexer, formatter)
+        css = formatter.get_style_defs('.code_highlighter')
+        return '''<style type="text/css"><!--
+                %(css)s
+            --></style>%(source)s''' % {'css' : css, 'source' : encoded}
+
+
+
+class MaxLen(Filter):
+    def filter(self, val, **kw):
+        """Replace None with '' and cut off at maxlen."""
+        
+        output = super(MaxLen, self).filter(val, **kw)
+        if kw.has_key('maxlen') and len(output) > kw['maxlen']:
+            return output[:kw['maxlen']]
+        return output
+
+class WebSafe(Filter):
+    """Escape HTML entities in $placeholders.
+    """
+    def filter(self, val, **kw):
+        s = super(WebSafe, self).filter(val, **kw)
+        # These substitutions are copied from cgi.escape().
+        s = s.replace("&", "&amp;") # Must be done first!
+        s = s.replace("<", "&lt;")
+        s = s.replace(">", "&gt;")
+        # Process the additional transformations if any.
+        if kw.has_key('also'):
+            also = kw['also']
+            entities = webSafeEntities   # Global variable.
+            for k in also:
+                if k in entities:
+                    v = entities[k]
+                else:
+                    v = "&#%s;" % ord(k)
+                s = s.replace(k, v)
+        return s
+
+
+class Strip(Filter):
+    """Strip leading/trailing whitespace but preserve newlines.
+
+    This filter goes through the value line by line, removing leading and
+    trailing whitespace on each line.  It does not strip newlines, so every
+    input line corresponds to one output line, with its trailing newline intact.
+
+    We do not use val.split('\n') because that would squeeze out consecutive
+    blank lines.  Instead, we search for each newline individually.  This
+    makes us unable to use the fast C .split method, but it makes the filter
+    much more widely useful.
+
+    This filter is intended to be usable both with the #filter directive and
+    with the proposed #sed directive (which has not been ratified yet.)
+    """
+    def filter(self, val, **kw):
+        s = super(Strip, self).filter(val, **kw)
+        result = []
+        start = 0   # The current line will be s[start:end].
+        while 1: # Loop through each line.
+            end = s.find('\n', start)  # Find next newline.
+            if end == -1:  # If no more newlines.
+                break
+            chunk = s[start:end].strip()
+            result.append(chunk)
+            result.append('\n')
+            start = end + 1
+        # Write the unfinished portion after the last newline, if any.
+        chunk = s[start:].strip()
+        result.append(chunk)
+        return "".join(result)
+
+class StripSqueeze(Filter):
+    """Canonicalizes every chunk of whitespace to a single space.
+
+    Strips leading/trailing whitespace.  Removes all newlines, so multi-line
+    input is joined into one ling line with NO trailing newline.
+    """
+    def filter(self, val, **kw):
+        s = super(StripSqueeze, self).filter(val, **kw)
+        s = s.split()
+        return " ".join(s)
+    
+##################################################
+## MAIN ROUTINE -- testing
+    
+def test():
+    s1 = "abc <=> &"
+    s2 = "   asdf  \n\t  1  2    3\n"
+    print "WebSafe INPUT:", `s1`
+    print "      WebSafe:", `WebSafe().filter(s1)`
+    
+    print
+    print " Strip INPUT:", `s2`
+    print "       Strip:", `Strip().filter(s2)`
+    print "StripSqueeze:", `StripSqueeze().filter(s2)`
+
+    print "Unicode:", `EncodeUnicode().filter(u'aoeu12345\u1234')`
+    
+if __name__ == "__main__":  test()
+    
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportHooks.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportHooks.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportHooks.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# $Id: ImportHooks.py,v 1.27 2007/11/16 18:28:47 tavis_rudd Exp $
+
+"""Provides some import hooks to allow Cheetah's .tmpl files to be imported
+directly like Python .py modules.
+
+To use these:
+  import Cheetah.ImportHooks
+  Cheetah.ImportHooks.install()
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.27 $
+Start Date: 2001/03/30
+Last Revision Date: $Date: 2007/11/16 18:28:47 $
+""" 
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.27 $"[11:-2]
+
+import sys
+import os.path
+import types
+import __builtin__
+import new
+import imp
+from threading import RLock
+import string
+import traceback
+from Cheetah import ImportManager
+from Cheetah.ImportManager import DirOwner
+from Cheetah.Compiler import Compiler
+from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
+
+_installed = False
+
+##################################################
+## HELPER FUNCS
+
+_cacheDir = []
+def setCacheDir(cacheDir):
+    global _cacheDir
+    _cacheDir.append(cacheDir)
+    
+##################################################
+## CLASSES
+
+class CheetahDirOwner(DirOwner):
+    _lock = RLock()
+    _acquireLock = _lock.acquire
+    _releaseLock = _lock.release
+
+    templateFileExtensions = ('.tmpl',)
+
+    def getmod(self, name):
+        self._acquireLock()
+        try:        
+            mod = DirOwner.getmod(self, name)
+            if mod:
+                return mod
+
+            for ext in self.templateFileExtensions:
+                tmplPath =  os.path.join(self.path, name + ext)
+                if os.path.exists(tmplPath):
+                    try:
+                        return self._compile(name, tmplPath)
+                    except:
+                        # @@TR: log the error
+                        exc_txt = traceback.format_exc()
+                        exc_txt ='  '+('  \n'.join(exc_txt.splitlines()))
+                        raise ImportError(
+                            'Error while compiling Cheetah module'
+                        ' %(name)s, original traceback follows:\n%(exc_txt)s'%locals())
+            ##
+            return None
+
+        finally:
+            self._releaseLock()          
+
+    def _compile(self, name, tmplPath):
+        ## @@ consider adding an ImportError raiser here
+        code = str(Compiler(file=tmplPath, moduleName=name,
+                            mainClassName=name))
+        if _cacheDir:
+            __file__ = os.path.join(_cacheDir[0],
+                                    convertTmplPathToModuleName(tmplPath)) + '.py'
+            try:
+                open(__file__, 'w').write(code)
+            except OSError:
+                ## @@ TR: need to add some error code here
+                traceback.print_exc(file=sys.stderr)
+                __file__ = tmplPath
+        else:
+            __file__ = tmplPath
+        co = compile(code+'\n', __file__, 'exec')
+
+        mod = imp.new_module(name)
+        mod.__file__ = co.co_filename
+        if _cacheDir:
+            mod.__orig_file__ = tmplPath # @@TR: this is used in the WebKit
+                                         # filemonitoring code
+        mod.__co__ = co
+        return mod
+        
+
+##################################################
+## FUNCTIONS
+
+def install(templateFileExtensions=('.tmpl',)):
+    """Install the Cheetah Import Hooks"""
+
+    global _installed
+    if not _installed:
+        CheetahDirOwner.templateFileExtensions = templateFileExtensions
+        import __builtin__
+        if type(__builtin__.__import__) == types.BuiltinFunctionType:
+            global __oldimport__
+            __oldimport__ = __builtin__.__import__
+            ImportManager._globalOwnerTypes.insert(0, CheetahDirOwner)
+            #ImportManager._globalOwnerTypes.append(CheetahDirOwner)            
+            global _manager
+            _manager=ImportManager.ImportManager()
+            _manager.setThreaded()
+            _manager.install()
+        
+def uninstall():
+    """Uninstall the Cheetah Import Hooks"""    
+    global _installed
+    if not _installed:
+        import __builtin__
+        if type(__builtin__.__import__) == types.MethodType:
+            __builtin__.__import__ = __oldimport__
+            global _manager
+            del _manager
+
+if __name__ == '__main__':
+    install()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportManager.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportManager.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/ImportManager.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,566 @@
+#!/usr/bin/env python
+# $Id: ImportManager.py,v 1.6 2007/04/03 01:56:24 tavis_rudd Exp $
+
+"""Provides an emulator/replacement for Python's standard import system.
+
+@@TR: Be warned that Import Hooks are in the deepest, darkest corner of Python's
+jungle.  If you need to start hacking with this, be prepared to get lost for a
+while. Also note, this module predates the newstyle import hooks in Python 2.3
+http://www.python.org/peps/pep-0302.html.  
+
+
+This is a hacked/documented version of Gordon McMillan's iu.py. I have:
+
+  - made it a little less terse
+
+  - added docstrings and explanatations
+
+  - standardized the variable naming scheme
+
+  - reorganized the code layout to enhance readability
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>  based on Gordon McMillan's iu.py
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.6 $
+Start Date: 2001/03/30
+Last Revision Date: $Date: 2007/04/03 01:56:24 $
+""" 
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.6 $"[11:-2]
+
+##################################################
+## DEPENDENCIES
+
+import sys
+import imp
+import marshal
+
+##################################################
+## CONSTANTS & GLOBALS
+
+try:
+    True,False
+except NameError:
+    True, False = (1==1),(1==0)
+
+_installed = False
+
+STRINGTYPE = type('')
+
+# _globalOwnerTypes is defined at the bottom of this file
+
+_os_stat = _os_path_join = _os_getcwd = _os_path_dirname = None
+
+##################################################
+## FUNCTIONS
+
+def _os_bootstrap():
+    """Set up 'os' module replacement functions for use during import bootstrap."""
+
+    names = sys.builtin_module_names
+
+    join = dirname = None
+    if 'posix' in names:
+        sep = '/'
+        from posix import stat, getcwd
+    elif 'nt' in names:
+        sep = '\\'
+        from nt import stat, getcwd
+    elif 'dos' in names:
+        sep = '\\'
+        from dos import stat, getcwd
+    elif 'os2' in names:
+        sep = '\\'
+        from os2 import stat, getcwd
+    elif 'mac' in names:
+        from mac import stat, getcwd
+        def join(a, b):
+            if a == '':
+                return b
+            if ':' not in a:
+                a = ':' + a
+            if a[-1:] != ':':
+                a = a + ':'
+            return a + b
+    else:
+        raise ImportError, 'no os specific module found'
+
+    if join is None:
+        def join(a, b, sep=sep):
+            if a == '':
+                return b
+            lastchar = a[-1:]
+            if lastchar == '/' or lastchar == sep:
+                return a + b
+            return a + sep + b
+
+    if dirname is None:
+        def dirname(a, sep=sep):
+            for i in range(len(a)-1, -1, -1):
+                c = a[i]
+                if c == '/' or c == sep:
+                    return a[:i]
+            return ''
+    
+    global _os_stat
+    _os_stat = stat
+
+    global _os_path_join
+    _os_path_join = join
+
+    global _os_path_dirname
+    _os_path_dirname = dirname
+    
+    global _os_getcwd
+    _os_getcwd = getcwd
+    
+_os_bootstrap()
+
+def packageName(s):
+    for i in range(len(s)-1, -1, -1):
+        if s[i] == '.':
+            break
+    else:
+        return ''
+    return s[:i]
+
+def nameSplit(s):
+    rslt = []
+    i = j = 0
+    for j in range(len(s)):
+        if s[j] == '.':
+            rslt.append(s[i:j])
+            i = j+1
+    if i < len(s):
+        rslt.append(s[i:])
+    return rslt
+
+def getPathExt(fnm):
+    for i in range(len(fnm)-1, -1, -1):
+        if fnm[i] == '.':
+            return fnm[i:]
+    return ''
+
+def pathIsDir(pathname):
+    "Local replacement for os.path.isdir()."
+    try:
+        s = _os_stat(pathname)
+    except OSError:
+        return None
+    return (s[0] & 0170000) == 0040000
+
+def getDescr(fnm):
+    ext = getPathExt(fnm)
+    for (suffix, mode, typ) in imp.get_suffixes():
+        if suffix == ext:
+            return (suffix, mode, typ)
+
+##################################################
+## CLASSES
+
+class Owner:
+    
+    """An Owner does imports from a particular piece of turf That is, there's
+    an Owner for each thing on sys.path There are owners for directories and
+    .pyz files.  There could be owners for zip files, or even URLs.  A
+    shadowpath (a dictionary mapping the names in sys.path to their owners) is
+    used so that sys.path (or a package's __path__) is still a bunch of strings,
+    """
+    
+    def __init__(self, path):
+        self.path = path
+
+    def __str__(self):
+        return self.path
+    
+    def getmod(self, nm):
+        return None
+    
+class DirOwner(Owner):
+    
+    def __init__(self, path):
+        if path == '':
+            path = _os_getcwd()
+        if not pathIsDir(path):
+            raise ValueError, "%s is not a directory" % path
+        Owner.__init__(self, path)
+        
+    def getmod(self, nm,
+               getsuffixes=imp.get_suffixes, loadco=marshal.loads, newmod=imp.new_module):
+        
+        pth =  _os_path_join(self.path, nm)
+
+        possibles = [(pth, 0, None)]
+        if pathIsDir(pth):
+            possibles.insert(0, (_os_path_join(pth, '__init__'), 1, pth))
+        py = pyc = None
+        for pth, ispkg, pkgpth in possibles:
+            for ext, mode, typ in getsuffixes():
+                attempt = pth+ext
+                try:
+                    st = _os_stat(attempt)
+                except:
+                    pass
+                else:
+                    if typ == imp.C_EXTENSION:
+                        fp = open(attempt, 'rb')
+                        mod = imp.load_module(nm, fp, attempt, (ext, mode, typ))
+                        mod.__file__ = attempt
+                        return mod
+                    elif typ == imp.PY_SOURCE:
+                        py = (attempt, st)
+                    else:
+                        pyc = (attempt, st)
+            if py or pyc:
+                break
+        if py is None and pyc is None:
+            return None
+        while 1:
+            if pyc is None or py and pyc[1][8] < py[1][8]:
+                try:
+                    co = compile(open(py[0], 'r').read()+'\n', py[0], 'exec')
+                    break
+                except SyntaxError, e:
+                    print "Invalid syntax in %s" % py[0]
+                    print e.args
+                    raise
+            elif pyc:
+                stuff = open(pyc[0], 'rb').read()
+                try:
+                    co = loadco(stuff[8:])
+                    break
+                except (ValueError, EOFError):
+                    pyc = None
+            else:
+                return None
+        mod = newmod(nm)
+        mod.__file__ = co.co_filename
+        if ispkg:
+            mod.__path__ = [pkgpth]
+            subimporter = PathImportDirector(mod.__path__)
+            mod.__importsub__ = subimporter.getmod
+        mod.__co__ = co
+        return mod
+
+
+class ImportDirector(Owner):
+    """ImportDirectors live on the metapath There's one for builtins, one for
+    frozen modules, and one for sys.path Windows gets one for modules gotten
+    from the Registry Mac would have them for PY_RESOURCE modules etc.  A
+    generalization of Owner - their concept of 'turf' is broader"""
+
+    pass
+
+class BuiltinImportDirector(ImportDirector):
+    """Directs imports of builtin modules"""
+    def __init__(self):
+        self.path = 'Builtins'
+
+    def getmod(self, nm, isbuiltin=imp.is_builtin):
+        if isbuiltin(nm):
+            mod = imp.load_module(nm, None, nm, ('','',imp.C_BUILTIN))
+            return mod
+        return None
+
+class FrozenImportDirector(ImportDirector):
+    """Directs imports of frozen modules"""
+    
+    def __init__(self):
+        self.path = 'FrozenModules'
+
+    def getmod(self, nm,
+               isFrozen=imp.is_frozen, loadMod=imp.load_module):
+        if isFrozen(nm):
+            mod = loadMod(nm, None, nm, ('','',imp.PY_FROZEN))
+            if hasattr(mod, '__path__'):
+                mod.__importsub__ = lambda name, pname=nm, owner=self: owner.getmod(pname+'.'+name)
+            return mod
+        return None
+
+
+class RegistryImportDirector(ImportDirector):
+    """Directs imports of modules stored in the Windows Registry"""
+
+    def __init__(self):
+        self.path = "WindowsRegistry"
+        self.map = {}
+        try:
+            import win32api
+            ## import win32con
+        except ImportError:
+            pass
+        else:
+            HKEY_CURRENT_USER = -2147483647
+            HKEY_LOCAL_MACHINE = -2147483646
+            KEY_ALL_ACCESS = 983103
+            subkey = r"Software\Python\PythonCore\%s\Modules" % sys.winver
+            for root in (HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE):
+                try:
+                    hkey = win32api.RegOpenKeyEx(root, subkey, 0, KEY_ALL_ACCESS)
+                except:
+                    pass
+                else:
+                    numsubkeys, numvalues, lastmodified = win32api.RegQueryInfoKey(hkey)
+                    for i in range(numsubkeys):
+                        subkeyname = win32api.RegEnumKey(hkey, i)
+                        hskey = win32api.RegOpenKeyEx(hkey, subkeyname, 0, KEY_ALL_ACCESS)
+                        val = win32api.RegQueryValueEx(hskey, '')
+                        desc = getDescr(val[0])
+                        self.map[subkeyname] = (val[0], desc)
+                        hskey.Close()
+                    hkey.Close()
+                    break
+                
+    def getmod(self, nm):
+        stuff = self.map.get(nm)
+        if stuff:
+            fnm, desc = stuff
+            fp = open(fnm, 'rb')
+            mod = imp.load_module(nm, fp, fnm, desc)
+            mod.__file__ = fnm
+            return mod
+        return None
+    
+class PathImportDirector(ImportDirector):
+    """Directs imports of modules stored on the filesystem."""
+
+    def __init__(self, pathlist=None, importers=None, ownertypes=None):
+        if pathlist is None:
+            self.path = sys.path
+        else:
+            self.path = pathlist
+        if ownertypes == None:
+            self._ownertypes = _globalOwnerTypes
+        else:
+            self._ownertypes = ownertypes
+        if importers:
+            self._shadowPath = importers
+        else:
+            self._shadowPath = {}
+        self._inMakeOwner = False
+        self._building = {}
+        
+    def getmod(self, nm):
+        mod = None
+        for thing in self.path:
+            if type(thing) is STRINGTYPE:
+                owner = self._shadowPath.get(thing, -1)
+                if owner == -1:
+                    owner = self._shadowPath[thing] = self._makeOwner(thing)
+                if owner:
+                    mod = owner.getmod(nm)
+            else:
+                mod = thing.getmod(nm)
+            if mod:
+                break
+        return mod
+    
+    def _makeOwner(self, path):
+        if self._building.get(path):
+            return None
+        self._building[path] = 1
+        owner = None
+        for klass in self._ownertypes:
+            try:
+                # this may cause an import, which may cause recursion
+                # hence the protection
+                owner = klass(path)
+            except:
+                pass
+            else:
+                break
+        del self._building[path]
+        return owner
+
+#=================ImportManager============================#
+# The one-and-only ImportManager
+# ie, the builtin import
+
+UNTRIED = -1
+
+class ImportManager:
+    # really the equivalent of builtin import
+    def __init__(self):
+        self.metapath = [
+            BuiltinImportDirector(),
+            FrozenImportDirector(),
+            RegistryImportDirector(),
+            PathImportDirector()
+        ]
+        self.threaded = 0
+        self.rlock = None
+        self.locker = None
+        self.setThreaded()
+        
+    def setThreaded(self):
+        thread = sys.modules.get('thread', None)
+        if thread and not self.threaded:
+            self.threaded = 1
+            self.rlock = thread.allocate_lock()
+            self._get_ident = thread.get_ident
+            
+    def install(self):
+        import __builtin__
+        __builtin__.__import__ = self.importHook
+        __builtin__.reload = self.reloadHook
+        
+    def importHook(self, name, globals=None, locals=None, fromlist=None, level=-1):
+        '''
+            NOTE: Currently importHook will accept the keyword-argument "level" 
+            but it will *NOT* use it (currently). Details about the "level" keyword
+            argument can be found here: http://www.python.org/doc/2.5.2/lib/built-in-funcs.html
+        '''
+        # first see if we could be importing a relative name
+        #print "importHook(%s, %s, locals, %s)" % (name, globals['__name__'], fromlist)
+        _sys_modules_get = sys.modules.get
+        contexts = [None]
+        if globals:
+            importernm = globals.get('__name__', '')
+            if importernm:
+                if hasattr(_sys_modules_get(importernm), '__path__'):
+                    contexts.insert(0,importernm)
+                else:
+                    pkgnm = packageName(importernm)
+                    if pkgnm:
+                        contexts.insert(0,pkgnm)
+        # so contexts is [pkgnm, None] or just [None]
+        # now break the name being imported up so we get:
+        # a.b.c -> [a, b, c]
+        nmparts = nameSplit(name)
+        _self_doimport = self.doimport
+        threaded = self.threaded
+        for context in contexts:
+            ctx = context
+            for i in range(len(nmparts)):
+                nm = nmparts[i]
+                #print " importHook trying %s in %s" % (nm, ctx)
+                if ctx:
+                    fqname = ctx + '.' + nm
+                else:
+                    fqname = nm
+                if threaded:
+                    self._acquire()
+                mod = _sys_modules_get(fqname, UNTRIED)
+                if mod is UNTRIED:
+                    mod = _self_doimport(nm, ctx, fqname)
+                if threaded:
+                    self._release()
+                if mod:
+                    ctx = fqname
+                else:
+                    break
+            else:
+                # no break, point i beyond end
+                i = i + 1
+            if i:
+                break
+            
+        if i<len(nmparts):
+            if ctx and hasattr(sys.modules[ctx], nmparts[i]):
+                #print "importHook done with %s %s %s (case 1)" % (name, globals['__name__'], fromlist)
+                return sys.modules[nmparts[0]]
+            del sys.modules[fqname]
+            raise ImportError, "No module named %s" % fqname
+        if fromlist is None: 
+            #print "importHook done with %s %s %s (case 2)" % (name, globals['__name__'], fromlist)
+            if context:
+                return sys.modules[context+'.'+nmparts[0]]
+            return sys.modules[nmparts[0]]
+        bottommod = sys.modules[ctx]
+        if hasattr(bottommod, '__path__'):
+            fromlist = list(fromlist)
+            i = 0
+            while i < len(fromlist):
+                nm = fromlist[i]
+                if nm == '*':
+                    fromlist[i:i+1] = list(getattr(bottommod, '__all__', []))
+                    if i >= len(fromlist):
+                        break
+                    nm = fromlist[i]
+                i = i + 1
+                if not hasattr(bottommod, nm):
+                    if self.threaded:
+                        self._acquire()
+                    mod = self.doimport(nm, ctx, ctx+'.'+nm)
+                    if self.threaded:
+                        self._release()
+                    if not mod:
+                        raise ImportError, "%s not found in %s" % (nm, ctx)
+        #print "importHook done with %s %s %s (case 3)" % (name, globals['__name__'], fromlist)
+        return bottommod
+    
+    def doimport(self, nm, parentnm, fqname):
+        # Not that nm is NEVER a dotted name at this point
+        #print "doimport(%s, %s, %s)" % (nm, parentnm, fqname)
+        if parentnm:
+            parent = sys.modules[parentnm]
+            if hasattr(parent, '__path__'):
+                importfunc = getattr(parent, '__importsub__', None)
+                if not importfunc:
+                    subimporter = PathImportDirector(parent.__path__)
+                    importfunc = parent.__importsub__ = subimporter.getmod
+                mod = importfunc(nm)
+                if mod:
+                    setattr(parent, nm, mod)
+            else:
+                #print "..parent not a package"
+                return None
+        else:
+            # now we're dealing with an absolute import
+            for director in self.metapath:
+                mod = director.getmod(nm)
+                if mod:
+                    break
+        if mod:
+            mod.__name__ = fqname
+            sys.modules[fqname] = mod
+            if hasattr(mod, '__co__'):
+                co = mod.__co__
+                del mod.__co__
+                exec co in mod.__dict__
+            if fqname == 'thread' and not self.threaded:
+##                print "thread detected!"
+                self.setThreaded()
+        else:
+            sys.modules[fqname] = None
+        #print "..found %s" % mod
+        return mod
+    
+    def reloadHook(self, mod):
+        fqnm = mod.__name__
+        nm = nameSplit(fqnm)[-1]
+        parentnm = packageName(fqnm)
+        newmod = self.doimport(nm, parentnm, fqnm)
+        mod.__dict__.update(newmod.__dict__)
+##        return newmod
+        
+    def _acquire(self):
+        if self.rlock.locked():
+            if self.locker == self._get_ident():
+                self.lockcount = self.lockcount + 1
+##                print "_acquire incrementing lockcount to", self.lockcount
+                return
+        self.rlock.acquire()
+        self.locker = self._get_ident()
+        self.lockcount = 0
+##        print "_acquire first time!"
+        
+    def _release(self):
+        if self.lockcount:
+            self.lockcount = self.lockcount - 1
+##            print "_release decrementing lockcount to", self.lockcount
+        else:
+            self.rlock.release()
+##            print "_release releasing lock!"
+
+
+##################################################
+## MORE CONSTANTS & GLOBALS
+
+_globalOwnerTypes = [
+    DirOwner,
+    Owner,
+]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/I18n.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/I18n.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/I18n.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,67 @@
+import gettext
+_ = gettext.gettext
+class I18n(object):
+    def __init__(self, parser):
+        pass
+
+## junk I'm playing with to test the macro framework 
+#    def parseArgs(self, parser, startPos):
+#        parser.getWhiteSpace()
+#        args = parser.getExpression(useNameMapper=False,
+#                                    pyTokensToBreakAt=[':']).strip()
+#        return args
+#
+#    def convertArgStrToDict(self, args, parser=None, startPos=None):
+#        def getArgs(*pargs, **kws):
+#            return pargs, kws
+#        exec 'positionalArgs, kwArgs = getArgs(%(args)s)'%locals()
+#        return kwArgs
+
+    def __call__(self,
+                 src, # aka message,
+                 plural=None,
+                 n=None, # should be a string representing the name of the
+                          # '$var' rather than $var itself                   
+                 id=None,
+                 domain=None,
+                 source=None,
+                 target=None,
+                 comment=None,
+
+                 # args that are automatically supplied by the parser when the
+                 # macro is called:
+                 parser=None,
+                 macros=None,
+                 isShortForm=False,
+                 EOLCharsInShortForm=None,
+                 startPos=None,
+                 endPos=None,
+             ):
+        """This is just a stub at this time.
+
+	   plural = the plural form of the message
+	   n = a sized argument to distinguish between single and plural forms           
+
+      	   id = msgid in the translation catalog
+	   domain = translation domain
+	   source = source lang
+	   target = a specific target lang
+	   comment = a comment to the translation team
+
+        See the following for some ideas
+        http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport
+
+        Other notes:
+        - There is no need to replicate the i18n:name attribute from plone / PTL,
+          as cheetah placeholders serve the same purpose
+    
+    
+       """
+        
+        #print macros['i18n']
+        src = _(src)
+        if isShortForm and endPos<len(parser):
+            return src+EOLCharsInShortForm
+        else:
+            return src
+        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Macros/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/NameMapper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/NameMapper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/NameMapper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,375 @@
+#!/usr/bin/env python
+# $Id: NameMapper.py,v 1.32 2007/12/10 19:20:09 tavis_rudd Exp $
+
+"""This module supports Cheetah's optional NameMapper syntax.
+
+Overview
+================================================================================
+
+NameMapper provides a simple syntax for accessing Python data structures,
+functions, and methods from Cheetah. It's called NameMapper because it 'maps'
+simple 'names' in Cheetah templates to possibly more complex syntax in Python.
+
+Its purpose is to make working with Cheetah easy for non-programmers.
+Specifically, non-programmers using Cheetah should NOT need to be taught (a)
+what the difference is between an object and a dictionary, (b) what functions
+and methods are, and (c) what 'self' is.  A further aim (d) is to buffer the
+code in Cheetah templates from changes in the implementation of the Python data
+structures behind them.
+
+Consider this scenario:
+
+You are building a customer information system. The designers with you want to
+use information from your system on the client's website --AND-- they want to
+understand the display code and so they can maintian it themselves.
+
+You write a UI class with a 'customers' method that returns a dictionary of all
+the customer objects.  Each customer object has an 'address' method that returns
+the a dictionary with information about the customer's address.  The designers
+want to be able to access that information.
+
+Using PSP, the display code for the website would look something like the
+following, assuming your servlet subclasses the class you created for managing
+customer information:
+
+  <%= self.customer()[ID].address()['city'] %>   (42 chars)
+
+Using Cheetah's NameMapper syntax it could be any of the following:
+
+   $self.customers()[$ID].address()['city']       (39 chars)
+   --OR--                                         
+   $customers()[$ID].address()['city']           
+   --OR--                                         
+   $customers()[$ID].address().city              
+   --OR--                                         
+   $customers()[$ID].address.city                
+   --OR--                                         
+   $customers()[$ID].address.city
+   --OR--
+   $customers[$ID].address.city                   (27 chars)                   
+   
+   
+Which of these would you prefer to explain to the designers, who have no
+programming experience?  The last form is 15 characters shorter than the PSP
+and, conceptually, is far more accessible. With PHP or ASP, the code would be
+even messier than the PSP
+
+This is a rather extreme example and, of course, you could also just implement
+'$getCustomer($ID).city' and obey the Law of Demeter (search Google for more on that).
+But good object orientated design isn't the point here.
+
+Details
+================================================================================
+The parenthesized letters below correspond to the aims in the second paragraph.
+
+DICTIONARY ACCESS (a)
+---------------------
+
+NameMapper allows access to items in a dictionary using the same dotted notation
+used to access object attributes in Python.  This aspect of NameMapper is known
+as 'Unified Dotted Notation'.
+
+For example, with Cheetah it is possible to write:
+   $customers()['kerr'].address()  --OR--  $customers().kerr.address()
+where the second form is in NameMapper syntax.
+
+This only works with dictionary keys that are also valid python identifiers:
+  regex = '[a-zA-Z_][a-zA-Z_0-9]*'
+
+
+AUTOCALLING (b,d)
+-----------------
+
+NameMapper automatically detects functions and methods in Cheetah $vars and calls
+them if the parentheses have been left off.  
+
+For example if 'a' is an object, 'b' is a method
+  $a.b
+is equivalent to
+  $a.b()
+
+If b returns a dictionary, then following variations are possible
+  $a.b.c  --OR--  $a.b().c  --OR--  $a.b()['c']
+where 'c' is a key in the dictionary that a.b() returns.
+
+Further notes:
+* NameMapper autocalls the function or method without any arguments.  Thus
+autocalling can only be used with functions or methods that either have no
+arguments or have default values for all arguments.
+
+* NameMapper only autocalls functions and methods.  Classes and callable object instances
+will not be autocalled.  
+
+* Autocalling can be disabled using Cheetah's 'useAutocalling' setting.
+
+LEAVING OUT 'self' (c,d)
+------------------------
+
+NameMapper makes it possible to access the attributes of a servlet in Cheetah
+without needing to include 'self' in the variable names.  See the NAMESPACE
+CASCADING section below for details.
+
+NAMESPACE CASCADING (d)
+--------------------
+...
+
+Implementation details
+================================================================================
+
+* NameMapper's search order is dictionary keys then object attributes
+
+* NameMapper.NotFound is raised if a value can't be found for a name.
+
+Performance and the C version
+================================================================================
+
+Cheetah comes with both a C version and a Python version of NameMapper.  The C
+version is significantly faster and the exception tracebacks are much easier to
+read.  It's still slower than standard Python syntax, but you won't notice the
+difference in realistic usage scenarios.
+
+Cheetah uses the optimized C version (_namemapper.c) if it has
+been compiled or falls back to the Python version if not.
+
+Meta-Data
+================================================================================
+Authors: Tavis Rudd <tavis at damnsimple.com>,
+         Chuck Esterbrook <echuck at mindspring.com>
+Version: $Revision: 1.32 $
+Start Date: 2001/04/03
+Last Revision Date: $Date: 2007/12/10 19:20:09 $
+"""
+from __future__ import generators
+__author__ = "Tavis Rudd <tavis at damnsimple.com>," +\
+             "\nChuck Esterbrook <echuck at mindspring.com>"
+__revision__ = "$Revision: 1.32 $"[11:-2]
+import types
+from types import StringType, InstanceType, ClassType, TypeType
+from pprint import pformat
+import inspect
+import pdb
+
+_INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS = False
+_ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS = True
+__all__ = ['NotFound',
+           'hasKey',
+           'valueForKey',
+           'valueForName',
+           'valueFromSearchList',
+           'valueFromFrameOrSearchList',
+           'valueFromFrame',
+           ]
+
+
+## N.B. An attempt is made at the end of this module to import C versions of
+## these functions.  If _namemapper.c has been compiled succesfully and the
+## import goes smoothly, the Python versions defined here will be replaced with
+## the C versions.
+
+class NotFound(LookupError):
+    pass
+
+def _raiseNotFoundException(key, namespace):
+    excString = "cannot find '%s'"%key
+    if _INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS:
+        excString += ' in the namespace %s'%pformat(namespace)
+    raise NotFound(excString)
+
+def _wrapNotFoundException(exc, fullName, namespace):
+    if not _ALLOW_WRAPPING_OF_NOTFOUND_EXCEPTIONS:
+        raise 
+    else:
+        excStr = exc.args[0]
+        if excStr.find('while searching')==-1: # only wrap once!
+            excStr +=" while searching for '%s'"%fullName
+            if _INCLUDE_NAMESPACE_REPR_IN_NOTFOUND_EXCEPTIONS:
+                excStr += ' in the namespace %s'%pformat(namespace)
+            exc.args = (excStr,)
+        raise
+
+def _isInstanceOrClass(obj):
+    if type(obj) in (InstanceType, ClassType):
+        # oldstyle
+        return True
+
+    if hasattr(obj, "__class__"):
+        # newstyle
+        if hasattr(obj, 'mro'):
+            # type/class
+            return True
+        elif (hasattr(obj, 'im_func') or hasattr(obj, 'func_code') or hasattr(obj, '__self__')):
+            # method, func, or builtin func
+            return False
+        elif hasattr(obj, '__init__'):
+            # instance
+            return True
+    return False
+    
+def hasKey(obj, key):
+    """Determine if 'obj' has 'key' """
+    if hasattr(obj,'has_key') and obj.has_key(key):
+        return True
+    elif hasattr(obj, key):
+        return True
+    else:
+        return False
+
+def valueForKey(obj, key):
+    if hasattr(obj, 'has_key') and obj.has_key(key):
+        return obj[key]
+    elif hasattr(obj, key):
+        return getattr(obj, key)
+    else:
+        _raiseNotFoundException(key, obj)
+
+def _valueForName(obj, name, executeCallables=False):
+    nameChunks=name.split('.')
+    for i in range(len(nameChunks)):
+        key = nameChunks[i]
+        if hasattr(obj, 'has_key') and obj.has_key(key):
+            nextObj = obj[key]
+        else:
+            try:
+                nextObj = getattr(obj, key)
+            except AttributeError:
+                _raiseNotFoundException(key, obj)
+        
+        if executeCallables and callable(nextObj) and not _isInstanceOrClass(nextObj):
+            obj = nextObj()
+        else:
+            obj = nextObj
+    return obj
+
+def valueForName(obj, name, executeCallables=False):
+    try:
+        return _valueForName(obj, name, executeCallables)
+    except NotFound, e:
+        _wrapNotFoundException(e, fullName=name, namespace=obj)
+
+def valueFromSearchList(searchList, name, executeCallables=False):
+    key = name.split('.')[0]
+    for namespace in searchList:
+        if hasKey(namespace, key):
+            return _valueForName(namespace, name,
+                                executeCallables=executeCallables)
+    _raiseNotFoundException(key, searchList)
+
+def _namespaces(callerFrame, searchList=None):
+    yield callerFrame.f_locals
+    if searchList:
+        for namespace in searchList:
+            yield namespace
+    yield callerFrame.f_globals
+    yield __builtins__
+
+def valueFromFrameOrSearchList(searchList, name, executeCallables=False,
+                               frame=None):
+    def __valueForName():
+        try:
+            return _valueForName(namespace, name, executeCallables=executeCallables)
+        except NotFound, e:
+            _wrapNotFoundException(e, fullName=name, namespace=searchList)
+    try:
+        if not frame:
+            frame = inspect.stack()[1][0]
+        key = name.split('.')[0]
+        for namespace in _namespaces(frame, searchList):
+            if hasKey(namespace, key):
+                return __valueForName()
+        _raiseNotFoundException(key, searchList)
+    finally:
+        del frame
+
+def valueFromFrame(name, executeCallables=False, frame=None):
+    # @@TR consider implementing the C version the same way
+    # at the moment it provides a seperate but mirror implementation
+    # to valueFromFrameOrSearchList
+    try: 
+        if not frame:
+            frame = inspect.stack()[1][0]
+        return valueFromFrameOrSearchList(searchList=None,
+                                          name=name,
+                                          executeCallables=executeCallables,
+                                          frame=frame)
+    finally:
+        del frame
+
+def hasName(obj, name):
+    #Not in the C version
+    """Determine if 'obj' has the 'name' """
+    key = name.split('.')[0]
+    if not hasKey(obj, key):
+        return False
+    try:
+        valueForName(obj, name)
+        return True
+    except NotFound:
+        return False
+try:
+    from _namemapper import NotFound, valueForKey, valueForName, \
+         valueFromSearchList, valueFromFrameOrSearchList, valueFromFrame
+    # it is possible with Jython or Windows, for example, that _namemapper.c hasn't been compiled
+    C_VERSION = True
+except:
+    C_VERSION = False
+
+##################################################
+## CLASSES
+
+class Mixin:
+    """@@ document me"""
+    def valueForName(self, name):
+        return valueForName(self, name)
+
+    def valueForKey(self, key):
+        return valueForKey(self, key)
+
+##################################################
+## if run from the command line ##
+
+def example():
+    class A(Mixin):
+        classVar = 'classVar val'
+        def method(self,arg='method 1 default arg'):
+            return arg
+
+        def method2(self, arg='meth 2 default arg'):
+            return {'item1':arg}
+
+        def method3(self, arg='meth 3 default'):
+            return arg
+
+    class B(A):
+        classBvar = 'classBvar val'
+
+    a = A()
+    a.one = 'valueForOne'
+    def function(whichOne='default'):
+        values = {
+            'default': 'default output',
+            'one': 'output option one',
+            'two': 'output option two'
+            }
+        return values[whichOne]
+
+    a.dic = {
+        'func': function,
+        'method': a.method3,
+        'item': 'itemval',
+        'subDict': {'nestedMethod':a.method3}
+        }
+    b = 'this is local b'
+
+    print valueForKey(a.dic,'subDict')
+    print valueForName(a, 'dic.item')
+    print valueForName(vars(), 'b')
+    print valueForName(__builtins__, 'dir')()
+    print valueForName(vars(), 'a.classVar')
+    print valueForName(vars(), 'a.dic.func', executeCallables=True)
+    print valueForName(vars(), 'a.method2.item1', executeCallables=True)
+
+if __name__ == '__main__':
+    example()
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Parser.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Parser.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Parser.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2626 @@
+#!/usr/bin/env python
+# $Id: Parser.py,v 1.137 2008/03/10 05:25:13 tavis_rudd Exp $
+"""Parser classes for Cheetah's Compiler
+
+Classes:
+  ParseError( Exception )
+  _LowLevelParser( Cheetah.SourceReader.SourceReader ), basically a lexer
+  _HighLevelParser( _LowLevelParser )
+  Parser === _HighLevelParser (an alias)
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+Version: $Revision: 1.137 $
+Start Date: 2001/08/01
+Last Revision Date: $Date: 2008/03/10 05:25:13 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.137 $"[11:-2]
+
+import os
+import sys
+import re
+from re import DOTALL, MULTILINE
+from types import StringType, ListType, TupleType, ClassType, TypeType
+import time
+from tokenize import pseudoprog
+import inspect
+import new
+import traceback
+
+from Cheetah.SourceReader import SourceReader
+from Cheetah import Filters
+from Cheetah import ErrorCatchers
+from Cheetah.Unspecified import Unspecified
+from Cheetah.Macros.I18n import I18n
+
+# re tools
+_regexCache = {}
+def cachedRegex(pattern):
+    if pattern not in _regexCache:
+        _regexCache[pattern] = re.compile(pattern)
+    return _regexCache[pattern]
+
+def escapeRegexChars(txt,
+                     escapeRE=re.compile(r'([\$\^\*\+\.\?\{\}\[\]\(\)\|\\])')):
+    
+    """Return a txt with all special regular expressions chars escaped."""
+    
+    return escapeRE.sub(r'\\\1' , txt)
+
+def group(*choices): return '(' + '|'.join(choices) + ')'
+def nongroup(*choices): return '(?:' + '|'.join(choices) + ')'
+def namedGroup(name, *choices): return '(P:<' + name +'>' + '|'.join(choices) + ')'
+def any(*choices): return apply(group, choices) + '*'
+def maybe(*choices): return apply(group, choices) + '?'
+
+##################################################
+## CONSTANTS & GLOBALS ##
+
+NO_CACHE = 0
+STATIC_CACHE = 1
+REFRESH_CACHE = 2
+
+SET_LOCAL = 0
+SET_GLOBAL = 1
+SET_MODULE = 2
+
+##################################################
+## Tokens for the parser ##
+
+#generic
+identchars = "abcdefghijklmnopqrstuvwxyz" \
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ_"
+namechars = identchars + "0123456789"
+
+#operators
+powerOp = '**'
+unaryArithOps = ('+', '-', '~')
+binaryArithOps = ('+', '-', '/', '//','%')
+shiftOps = ('>>','<<')
+bitwiseOps = ('&','|','^')
+assignOp = '='
+augAssignOps = ('+=','-=','/=','*=', '**=','^=','%=',
+          '>>=','<<=','&=','|=', )
+assignmentOps = (assignOp,) + augAssignOps
+
+compOps = ('<','>','==','!=','<=','>=', '<>', 'is', 'in',)
+booleanOps = ('and','or','not')
+operators = (powerOp,) + unaryArithOps + binaryArithOps \
+            + shiftOps + bitwiseOps + assignmentOps \
+            + compOps + booleanOps
+
+delimeters = ('(',')','{','}','[',']',
+              ',','.',':',';','=','`') + augAssignOps
+
+
+keywords = ('and',       'del',       'for',       'is',        'raise',
+            'assert',    'elif',      'from',      'lambda',    'return',
+            'break',     'else',      'global',    'not',       'try',   
+            'class',     'except',    'if',        'or',        'while',
+            'continue',  'exec',      'import',    'pass',
+            'def',       'finally',   'in',        'print',
+            )
+
+single3 = "'''"
+double3 = '"""'
+
+tripleQuotedStringStarts =  ("'''", '"""', 
+                             "r'''", 'r"""', "R'''", 'R"""',
+                             "u'''", 'u"""', "U'''", 'U"""',
+                             "ur'''", 'ur"""', "Ur'''", 'Ur"""',
+                             "uR'''", 'uR"""', "UR'''", 'UR"""')
+
+tripleQuotedStringPairs = {"'''": single3, '"""': double3,
+                           "r'''": single3, 'r"""': double3,
+                           "u'''": single3, 'u"""': double3,
+                           "ur'''": single3, 'ur"""': double3,
+                           "R'''": single3, 'R"""': double3,
+                           "U'''": single3, 'U"""': double3,
+                           "uR'''": single3, 'uR"""': double3,
+                           "Ur'''": single3, 'Ur"""': double3,
+                           "UR'''": single3, 'UR"""': double3,
+                           }
+
+closurePairs= {')':'(',']':'[','}':'{'}
+closurePairsRev= {'(':')','[':']','{':'}'}
+
+##################################################
+## Regex chunks for the parser ##
+
+tripleQuotedStringREs = {}
+def makeTripleQuoteRe(start, end):
+    start = escapeRegexChars(start)
+    end = escapeRegexChars(end)
+    return re.compile(r'(?:' + start + r').*?' + r'(?:' + end + r')', re.DOTALL)
+
+for start, end in tripleQuotedStringPairs.items():
+    tripleQuotedStringREs[start] = makeTripleQuoteRe(start, end)
+
+WS = r'[ \f\t]*'  
+EOL = r'\r\n|\n|\r'
+EOLZ = EOL + r'|\Z'
+escCharLookBehind = nongroup(r'(?<=\A)',r'(?<!\\)')
+nameCharLookAhead = r'(?=[A-Za-z_])'
+identRE=re.compile(r'[a-zA-Z_][a-zA-Z_0-9]*')
+EOLre=re.compile(r'(?:\r\n|\r|\n)')
+
+specialVarRE=re.compile(r'([a-zA-z_]+)@') # for matching specialVar comments
+# e.g. ##author@ Tavis Rudd
+
+unicodeDirectiveRE = re.compile(
+    r'(?:^|\r\n|\r|\n)\s*#\s{0,5}unicode[:\s]*([-\w.]*)\s*(?:\r\n|\r|\n)', re.MULTILINE)
+encodingDirectiveRE = re.compile(
+    r'(?:^|\r\n|\r|\n)\s*#\s{0,5}encoding[:\s]*([-\w.]*)\s*(?:\r\n|\r|\n)', re.MULTILINE)
+
+escapedNewlineRE = re.compile(r'(?<!\\)\\n')
+
+directiveNamesAndParsers = {
+    # importing and inheritance
+    'import':None,
+    'from':None,
+    'extends': 'eatExtends',
+    'implements': 'eatImplements',
+    'super': 'eatSuper',
+
+    # output, filtering, and caching
+    'slurp': 'eatSlurp',
+    'raw': 'eatRaw',
+    'include': 'eatInclude',
+    'cache': 'eatCache',
+    'filter': 'eatFilter',
+    'echo': None,
+    'silent': None,
+    'transform' : 'eatTransform',
+    
+    'call': 'eatCall',
+    'arg': 'eatCallArg',
+    
+    'capture': 'eatCapture',
+    
+    # declaration, assignment, and deletion
+    'attr': 'eatAttr',
+    'def': 'eatDef',
+    'block': 'eatBlock',
+    '@': 'eatDecorator',
+    'defmacro': 'eatDefMacro',
+    
+    'closure': 'eatClosure',
+    
+    'set': 'eatSet',
+    'del': None,
+    
+    # flow control
+    'if': 'eatIf',
+    'while': None,
+    'for': None,
+    'else': None,
+    'elif': None,
+    'pass': None,
+    'break': None,
+    'continue': None,
+    'stop': None,
+    'return': None,
+    'yield': None,
+    
+    # little wrappers
+    'repeat': None,
+    'unless': None,
+    
+    # error handling
+    'assert': None,
+    'raise': None,
+    'try': None,
+    'except': None,
+    'finally': None,
+    'errorCatcher': 'eatErrorCatcher',
+    
+    # intructions to the parser and compiler
+    'breakpoint': 'eatBreakPoint',
+    'compiler': 'eatCompiler',
+    'compiler-settings': 'eatCompilerSettings',
+    
+    # misc
+    'shBang': 'eatShbang',
+    'encoding': 'eatEncoding',
+    
+    'end': 'eatEndDirective',
+    }
+
+endDirectiveNamesAndHandlers = {
+    'def': 'handleEndDef',      # has short-form
+    'block': None,              # has short-form
+    'closure': None,            # has short-form
+    'cache': None,              # has short-form
+    'call': None,               # has short-form
+    'capture': None,            # has short-form
+    'filter': None,
+    'errorCatcher':None,            
+    'while': None,              # has short-form
+    'for': None,                # has short-form
+    'if': None,                 # has short-form
+    'try': None,                # has short-form
+    'repeat': None,             # has short-form
+    'unless': None,             # has short-form
+    }
+
+##################################################
+## CLASSES ##
+
+# @@TR: SyntaxError doesn't call exception.__str__ for some reason!
+#class ParseError(SyntaxError):
+class ParseError(ValueError):
+    def __init__(self, stream, msg='Invalid Syntax', extMsg='', lineno=None, col=None):
+        self.stream = stream
+        if stream.pos() >= len(stream):
+            stream.setPos(len(stream) -1)
+        self.msg = msg
+        self.extMsg = extMsg
+        self.lineno = lineno
+        self.col = col
+        
+    def __str__(self):
+        return self.report()
+
+    def report(self):
+        stream = self.stream
+        if stream.filename():
+            f = " in file %s" % stream.filename()
+        else:
+            f = ''
+        report = ''
+        if self.lineno:
+            lineno = self.lineno
+            row, col, line = (lineno, (self.col or 0),
+                              self.stream.splitlines()[lineno-1])
+        else:
+            row, col, line = self.stream.getRowColLine()
+
+        ## get the surrounding lines
+        lines = stream.splitlines()
+        prevLines = []                  # (rowNum, content)
+        for i in range(1,4):
+            if row-1-i <=0:
+                break
+            prevLines.append( (row-i,lines[row-1-i]) )
+
+        nextLines = []                  # (rowNum, content)
+        for i in range(1,4):
+            if not row-1+i < len(lines):
+                break
+            nextLines.append( (row+i,lines[row-1+i]) )
+        nextLines.reverse()
+        
+        ## print the main message
+        report += "\n\n%s\n" %self.msg
+        report += "Line %i, column %i%s\n\n" % (row, col, f)
+        report += 'Line|Cheetah Code\n'
+        report += '----|-------------------------------------------------------------\n'
+        while prevLines:
+            lineInfo = prevLines.pop()
+            report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
+        report += "%(row)-4d|%(line)s\n"% {'row':row, 'line':line}
+        report += ' '*5 +' '*(col-1) + "^\n"
+        
+        while nextLines:
+            lineInfo = nextLines.pop()
+            report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
+        ## add the extra msg
+        if self.extMsg:
+            report += self.extMsg + '\n'
+            
+        return report
+
+class ForbiddenSyntax(ParseError): pass
+class ForbiddenExpression(ForbiddenSyntax): pass
+class ForbiddenDirective(ForbiddenSyntax): pass
+
+class CheetahVariable:
+    def __init__(self, nameChunks, useNameMapper=True, cacheToken=None,
+                 rawSource=None):
+        self.nameChunks = nameChunks
+        self.useNameMapper = useNameMapper
+        self.cacheToken = cacheToken
+        self.rawSource = rawSource
+        
+class Placeholder(CheetahVariable): pass
+
+class ArgList:
+    """Used by _LowLevelParser.getArgList()"""
+
+    def __init__(self):
+        self.argNames = []
+        self.defVals = []
+        self.i = 0
+
+    def addArgName(self, name):
+        self.argNames.append( name )
+        self.defVals.append( None )
+
+    def next(self):
+        self.i += 1
+
+    def addToDefVal(self, token):
+        i = self.i
+        if self.defVals[i] == None:
+            self.defVals[i] = ''
+        self.defVals[i] += token
+    
+    def merge(self):
+        defVals = self.defVals
+        for i in range(len(defVals)):
+            if type(defVals[i]) == StringType:
+                defVals[i] = defVals[i].strip()
+                
+        return map(None, [i.strip() for i in self.argNames], defVals)
+    
+    def __str__(self):
+        return str(self.merge())
+    
+class _LowLevelParser(SourceReader):
+    """This class implements the methods to match or extract ('get*') the basic
+    elements of Cheetah's grammar.  It does NOT handle any code generation or
+    state management.
+    """
+
+    _settingsManager = None
+
+    def setSettingsManager(self, settingsManager):
+        self._settingsManager = settingsManager
+        
+    def setting(self, key, default=Unspecified):
+        if default is Unspecified:
+            return self._settingsManager.setting(key)
+        else:
+            return self._settingsManager.setting(key, default=default)
+        
+    def setSetting(self, key, val):
+        self._settingsManager.setSetting(key, val)
+
+    def settings(self):
+        return self._settingsManager.settings()
+        
+    def updateSettings(self, settings):
+        self._settingsManager.updateSettings(settings)
+
+    def _initializeSettings(self): 
+        self._settingsManager._initializeSettings()
+    
+    def configureParser(self):
+        """Is called by the Compiler instance after the parser has had a
+        settingsManager assigned with self.setSettingsManager() 
+        """
+        self._makeCheetahVarREs()
+        self._makeCommentREs()
+        self._makeDirectiveREs()
+        self._makePspREs()
+        self._possibleNonStrConstantChars = (
+            self.setting('commentStartToken')[0] +
+            self.setting('multiLineCommentStartToken')[0] + 
+            self.setting('cheetahVarStartToken')[0] +
+            self.setting('directiveStartToken')[0] +
+            self.setting('PSPStartToken')[0])
+        self._nonStrConstMatchers = [
+            self.matchCommentStartToken,
+            self.matchMultiLineCommentStartToken,
+            self.matchVariablePlaceholderStart,
+            self.matchExpressionPlaceholderStart,
+            self.matchDirective,
+            self.matchPSPStartToken,
+            self.matchEOLSlurpToken,
+            ]
+
+    ## regex setup ##
+
+    def _makeCheetahVarREs(self):
+        
+        """Setup the regexs for Cheetah $var parsing."""
+
+        num = r'[0-9\.]+'
+        interval =   (r'(?P<interval>' + 
+                      num + r's|' +
+                      num + r'm|' +
+                      num + r'h|' +
+                      num + r'd|' +
+                      num + r'w|' +
+                      num + ')' 
+                      )
+    
+        cacheToken = (r'(?:' +
+                      r'(?P<REFRESH_CACHE>\*' + interval + '\*)'+
+                      '|' +
+                      r'(?P<STATIC_CACHE>\*)' +
+                      '|' +                      
+                      r'(?P<NO_CACHE>)' +
+                      ')')
+        self.cacheTokenRE = cachedRegex(cacheToken)
+
+        silentPlaceholderToken = (r'(?:' +
+                                  r'(?P<SILENT>' +escapeRegexChars('!')+')'+
+                                  '|' +
+                                  r'(?P<NOT_SILENT>)' +
+                                  ')')
+        self.silentPlaceholderTokenRE = cachedRegex(silentPlaceholderToken)
+        
+        self.cheetahVarStartRE = cachedRegex(
+            escCharLookBehind +
+            r'(?P<startToken>'+escapeRegexChars(self.setting('cheetahVarStartToken'))+')'+
+            r'(?P<silenceToken>'+silentPlaceholderToken+')'+
+            r'(?P<cacheToken>'+cacheToken+')'+
+            r'(?P<enclosure>|(?:(?:\{|\(|\[)[ \t\f]*))' + # allow WS after enclosure
+            r'(?=[A-Za-z_])')
+        validCharsLookAhead = r'(?=[A-Za-z_\*!\{\(\[])'
+        self.cheetahVarStartToken = self.setting('cheetahVarStartToken')
+        self.cheetahVarStartTokenRE = cachedRegex(
+            escCharLookBehind +
+            escapeRegexChars(self.setting('cheetahVarStartToken'))
+            +validCharsLookAhead
+            )
+
+        self.cheetahVarInExpressionStartTokenRE = cachedRegex(
+            escapeRegexChars(self.setting('cheetahVarStartToken'))
+            +r'(?=[A-Za-z_])'
+            )
+
+        self.expressionPlaceholderStartRE = cachedRegex(
+            escCharLookBehind +
+            r'(?P<startToken>' + escapeRegexChars(self.setting('cheetahVarStartToken')) + ')' +
+            r'(?P<cacheToken>' + cacheToken + ')' +
+            #r'\[[ \t\f]*'
+            r'(?:\{|\(|\[)[ \t\f]*'
+            + r'(?=[^\)\}\]])'
+            )
+
+        if self.setting('EOLSlurpToken'):
+            self.EOLSlurpRE = cachedRegex(
+                escapeRegexChars(self.setting('EOLSlurpToken'))
+                + r'[ \t\f]*'
+                + r'(?:'+EOL+')'
+                )
+        else:
+            self.EOLSlurpRE = None
+
+
+    def _makeCommentREs(self):
+        """Construct the regex bits that are used in comment parsing."""
+        startTokenEsc = escapeRegexChars(self.setting('commentStartToken'))
+        self.commentStartTokenRE = cachedRegex(escCharLookBehind + startTokenEsc)
+        del startTokenEsc
+        
+        startTokenEsc = escapeRegexChars(
+            self.setting('multiLineCommentStartToken'))
+        endTokenEsc = escapeRegexChars(
+            self.setting('multiLineCommentEndToken'))
+        self.multiLineCommentTokenStartRE = cachedRegex(escCharLookBehind +
+                                                       startTokenEsc)
+        self.multiLineCommentEndTokenRE = cachedRegex(escCharLookBehind +
+                                                     endTokenEsc)
+        
+    def _makeDirectiveREs(self):
+        """Construct the regexs that are used in directive parsing."""
+        startToken = self.setting('directiveStartToken')
+        endToken = self.setting('directiveEndToken')
+        startTokenEsc = escapeRegexChars(startToken)
+        endTokenEsc = escapeRegexChars(endToken)
+        validSecondCharsLookAhead = r'(?=[A-Za-z_@])'
+        reParts = [escCharLookBehind, startTokenEsc]
+        if self.setting('allowWhitespaceAfterDirectiveStartToken'):
+            reParts.append('[ \t]*')
+        reParts.append(validSecondCharsLookAhead)
+        self.directiveStartTokenRE = cachedRegex(''.join(reParts))
+        self.directiveEndTokenRE = cachedRegex(escCharLookBehind + endTokenEsc)
+
+    def _makePspREs(self):
+        """Setup the regexs for PSP parsing."""
+        startToken = self.setting('PSPStartToken')
+        startTokenEsc = escapeRegexChars(startToken)
+        self.PSPStartTokenRE = cachedRegex(escCharLookBehind + startTokenEsc)
+        endToken = self.setting('PSPEndToken')
+        endTokenEsc = escapeRegexChars(endToken)
+        self.PSPEndTokenRE = cachedRegex(escCharLookBehind + endTokenEsc)
+
+
+    def isLineClearToStartToken(self, pos=None):
+        return self.isLineClearToPos(pos)
+
+    def matchTopLevelToken(self):
+        """Returns the first match found from the following methods:
+            self.matchCommentStartToken
+            self.matchMultiLineCommentStartToken
+            self.matchVariablePlaceholderStart
+            self.matchExpressionPlaceholderStart
+            self.matchDirective
+            self.matchPSPStartToken
+            self.matchEOLSlurpToken
+
+        Returns None if no match.
+        """
+        match = None
+        if self.peek() in self._possibleNonStrConstantChars:
+            for matcher in self._nonStrConstMatchers:
+                match = matcher()
+                if match:
+                    break
+        return match
+
+    def matchPyToken(self):
+        match = pseudoprog.match(self.src(), self.pos())
+        
+        if match and match.group() in tripleQuotedStringStarts:
+            TQSmatch = tripleQuotedStringREs[match.group()].match(self.src(), self.pos())
+            if TQSmatch:
+                return TQSmatch
+        return match
+        
+    def getPyToken(self):
+        match = self.matchPyToken()
+        if match is None:
+            raise ParseError(self)
+        elif match.group() in tripleQuotedStringStarts:
+            raise ParseError(self, msg='Malformed triple-quoted string')
+        return self.readTo(match.end())
+
+    def matchEOLSlurpToken(self):
+        if self.EOLSlurpRE:
+            return self.EOLSlurpRE.match(self.src(), self.pos())
+
+    def getEOLSlurpToken(self):
+        match = self.matchEOLSlurpToken()
+        if not match:
+            raise ParseError(self, msg='Invalid EOL slurp token')
+        return self.readTo(match.end())
+
+    def matchCommentStartToken(self):
+        return self.commentStartTokenRE.match(self.src(), self.pos())
+    
+    def getCommentStartToken(self):
+        match = self.matchCommentStartToken()
+        if not match:
+            raise ParseError(self, msg='Invalid single-line comment start token')
+        return self.readTo(match.end())
+
+    def matchMultiLineCommentStartToken(self):
+        return self.multiLineCommentTokenStartRE.match(self.src(), self.pos())
+    
+    def getMultiLineCommentStartToken(self):
+        match = self.matchMultiLineCommentStartToken()
+        if not match:
+            raise ParseError(self, msg='Invalid multi-line comment start token')
+        return self.readTo(match.end())
+
+    def matchMultiLineCommentEndToken(self):
+        return self.multiLineCommentEndTokenRE.match(self.src(), self.pos())
+    
+    def getMultiLineCommentEndToken(self):
+        match = self.matchMultiLineCommentEndToken()
+        if not match:
+            raise ParseError(self, msg='Invalid multi-line comment end token')
+        return self.readTo(match.end())
+    
+    def getDottedName(self):
+        srcLen = len(self)
+        nameChunks = []
+        
+        if not self.peek() in identchars:
+            raise ParseError(self)
+    
+        while self.pos() < srcLen:
+            c = self.peek()
+            if c in namechars:
+                nameChunk = self.getIdentifier()
+                nameChunks.append(nameChunk)
+            elif c == '.':
+                if self.pos()+1 <srcLen and self.peek(1) in identchars:
+                    nameChunks.append(self.getc())
+                else:
+                    break
+            else:
+                break
+
+        return ''.join(nameChunks)
+
+    def matchIdentifier(self):
+        return identRE.match(self.src(), self.pos())
+    
+    def getIdentifier(self):
+        match = self.matchIdentifier()
+        if not match:
+            raise ParseError(self, msg='Invalid identifier')
+        return self.readTo(match.end())
+
+    def matchOperator(self):
+        match = self.matchPyToken()
+        if match and match.group() not in operators:
+            match = None
+        return match
+
+    def getOperator(self):
+        match = self.matchOperator()
+        if not match:
+            raise ParseError(self, msg='Expected operator')
+        return self.readTo( match.end() )
+
+    def matchAssignmentOperator(self):
+        match = self.matchPyToken()
+        if match and match.group() not in assignmentOps:
+            match = None
+        return match
+        
+    def getAssignmentOperator(self):
+        match = self.matchAssignmentOperator()
+        if not match:
+            raise ParseError(self, msg='Expected assignment operator')
+        return self.readTo( match.end() )
+
+    def matchDirective(self):
+        """Returns False or the name of the directive matched.
+        """
+        startPos = self.pos()
+        if not self.matchDirectiveStartToken():
+            return False
+        self.getDirectiveStartToken()
+        directiveName = self.matchDirectiveName()
+        self.setPos(startPos)
+        return directiveName
+
+    def matchDirectiveName(self, directiveNameChars=identchars+'0123456789-@'):
+        startPos = self.pos()
+        possibleMatches = self._directiveNamesAndParsers.keys()
+        name = ''
+        match = None
+
+        while not self.atEnd():
+            c = self.getc()
+            if not c in directiveNameChars:
+                break
+            name += c
+            if name == '@':
+                if not self.atEnd() and self.peek() in identchars:
+                    match = '@'
+                break
+            possibleMatches = [dn for dn in possibleMatches if dn.startswith(name)]
+            if not possibleMatches:
+                break
+            elif (name in possibleMatches and (self.atEnd() or self.peek() not in directiveNameChars)):
+                match = name
+                break
+
+        self.setPos(startPos)
+        return match
+        
+    def matchDirectiveStartToken(self):
+        return self.directiveStartTokenRE.match(self.src(), self.pos())
+    
+    def getDirectiveStartToken(self):
+        match = self.matchDirectiveStartToken()
+        if not match:
+            raise ParseError(self, msg='Invalid directive start token')
+        return self.readTo(match.end())
+
+    def matchDirectiveEndToken(self):
+        return self.directiveEndTokenRE.match(self.src(), self.pos())
+    
+    def getDirectiveEndToken(self):
+        match = self.matchDirectiveEndToken()
+        if not match:
+            raise ParseError(self, msg='Invalid directive end token')
+        return self.readTo(match.end())
+
+        
+    def matchColonForSingleLineShortFormDirective(self):
+        if not self.atEnd() and self.peek()==':':
+            restOfLine = self[self.pos()+1:self.findEOL()]
+            restOfLine = restOfLine.strip()
+            if not restOfLine:
+                return False
+            elif self.commentStartTokenRE.match(restOfLine):
+                return False
+            else: # non-whitespace, non-commment chars found
+                return True
+        return False        
+
+    def matchPSPStartToken(self):
+        return self.PSPStartTokenRE.match(self.src(), self.pos())
+
+    def matchPSPEndToken(self):
+        return self.PSPEndTokenRE.match(self.src(), self.pos())
+
+    def getPSPStartToken(self):
+        match = self.matchPSPStartToken()
+        if not match:
+            raise ParseError(self, msg='Invalid psp start token')
+        return self.readTo(match.end())
+
+    def getPSPEndToken(self):
+        match = self.matchPSPEndToken()
+        if not match:
+            raise ParseError(self, msg='Invalid psp end token')
+        return self.readTo(match.end())
+
+    def matchCheetahVarStart(self):
+        """includes the enclosure and cache token"""
+        return self.cheetahVarStartRE.match(self.src(), self.pos())
+
+    def matchCheetahVarStartToken(self):
+        """includes the enclosure and cache token"""
+        return self.cheetahVarStartTokenRE.match(self.src(), self.pos())
+
+    def matchCheetahVarInExpressionStartToken(self):
+        """no enclosures or cache tokens allowed"""
+        return self.cheetahVarInExpressionStartTokenRE.match(self.src(), self.pos())
+
+    def matchVariablePlaceholderStart(self):
+        """includes the enclosure and cache token"""
+        return self.cheetahVarStartRE.match(self.src(), self.pos())
+
+    def matchExpressionPlaceholderStart(self):
+        """includes the enclosure and cache token"""
+        return self.expressionPlaceholderStartRE.match(self.src(), self.pos())        
+
+    def getCheetahVarStartToken(self):
+        """just the start token, not the enclosure or cache token"""
+        match = self.matchCheetahVarStartToken()
+        if not match:
+            raise ParseError(self, msg='Expected Cheetah $var start token')            
+        return self.readTo( match.end() )
+
+
+    def getCacheToken(self):
+        try:
+            token = self.cacheTokenRE.match(self.src(), self.pos())
+            self.setPos( token.end() )
+            return token.group()
+        except:
+            raise ParseError(self, msg='Expected cache token')
+
+    def getSilentPlaceholderToken(self):
+        try:
+            token = self.silentPlaceholderTokenRE.match(self.src(), self.pos())
+            self.setPos( token.end() )
+            return token.group()
+        except:
+            raise ParseError(self, msg='Expected silent placeholder token')
+
+
+
+    def getTargetVarsList(self):
+        varnames = []
+        while not self.atEnd():
+            if self.peek() in ' \t\f':
+                self.getWhiteSpace()
+            elif self.peek() in '\r\n':
+                break
+            elif self.startswith(','):
+                self.advance()
+            elif self.startswith('in ') or self.startswith('in\t'):
+                break
+            #elif self.matchCheetahVarStart():
+            elif self.matchCheetahVarInExpressionStartToken():
+                self.getCheetahVarStartToken()
+                self.getSilentPlaceholderToken()
+                self.getCacheToken()
+                varnames.append( self.getDottedName() )
+            elif self.matchIdentifier():
+                varnames.append( self.getDottedName() )
+            else:
+                break
+        return varnames
+        
+    def getCheetahVar(self, plain=False, skipStartToken=False):
+        """This is called when parsing inside expressions. Cache tokens are only
+        valid in placeholders so this method discards any cache tokens found.
+        """
+        if not skipStartToken:
+            self.getCheetahVarStartToken()
+        self.getSilentPlaceholderToken()
+        self.getCacheToken()
+        return self.getCheetahVarBody(plain=plain)
+            
+    def getCheetahVarBody(self, plain=False):
+        # @@TR: this should be in the compiler
+        return self._compiler.genCheetahVar(self.getCheetahVarNameChunks(), plain=plain)
+        
+    def getCheetahVarNameChunks(self):
+        
+        """
+        nameChunks = list of Cheetah $var subcomponents represented as tuples
+          [ (namemapperPart,autoCall,restOfName),
+          ]
+        where:
+          namemapperPart = the dottedName base
+          autocall = where NameMapper should use autocalling on namemapperPart
+          restOfName = any arglist, index, or slice
+
+        If restOfName contains a call arglist (e.g. '(1234)') then autocall is
+        False, otherwise it defaults to True.
+
+        EXAMPLE
+        ------------------------------------------------------------------------
+
+        if the raw CheetahVar is
+          $a.b.c[1].d().x.y.z
+          
+        nameChunks is the list
+          [ ('a.b.c',True,'[1]'),
+            ('d',False,'()'),     
+            ('x.y.z',True,''),   
+          ]
+
+        """
+
+        chunks = []
+        while self.pos() < len(self):
+            rest = ''
+            autoCall = True
+            if not self.peek() in identchars + '.':
+                break
+            elif self.peek() == '.':
+                
+                if self.pos()+1 < len(self) and self.peek(1) in identchars:
+                    self.advance()  # discard the period as it isn't needed with NameMapper
+                else:
+                    break
+                
+            dottedName = self.getDottedName()
+            if not self.atEnd() and self.peek() in '([':
+                if self.peek() == '(':
+                    rest = self.getCallArgString()
+                else:
+                    rest = self.getExpression(enclosed=True)
+                
+                period = max(dottedName.rfind('.'), 0)
+                if period:
+                    chunks.append( (dottedName[:period], autoCall, '') )
+                    dottedName = dottedName[period+1:]
+                if rest and rest[0]=='(':
+                    autoCall = False
+            chunks.append( (dottedName, autoCall, rest) )
+
+        return chunks
+    
+
+    def getCallArgString(self,
+                         enclosures=[],  # list of tuples (char, pos), where char is ({ or [ 
+                         useNameMapper=Unspecified):
+
+        """ Get a method/function call argument string. 
+
+        This method understands *arg, and **kw
+        """
+
+        # @@TR: this settings mangling should be removed
+        if useNameMapper is not Unspecified:
+            useNameMapper_orig = self.setting('useNameMapper')
+            self.setSetting('useNameMapper', useNameMapper)
+        
+        if enclosures:
+            pass
+        else:
+            if not self.peek() == '(':
+                raise ParseError(self, msg="Expected '('")
+            startPos = self.pos()
+            self.getc()
+            enclosures = [('(', startPos),
+                          ]
+        
+        argStringBits = ['(']
+        addBit = argStringBits.append
+
+        while 1:
+            if self.atEnd():
+                open = enclosures[-1][0]
+                close = closurePairsRev[open]
+                self.setPos(enclosures[-1][1])
+                raise ParseError(
+                    self, msg="EOF was reached before a matching '" + close +
+                    "' was found for the '" + open + "'")
+
+            c = self.peek()
+            if c in ")}]": # get the ending enclosure and break                
+                if not enclosures:
+                    raise ParseError(self)
+                c = self.getc()
+                open = closurePairs[c]
+                if enclosures[-1][0] == open:
+                    enclosures.pop()
+                    addBit(')')  
+                    break
+                else:
+                    raise ParseError(self)
+            elif c in " \t\f\r\n":
+                addBit(self.getc())
+            elif self.matchCheetahVarInExpressionStartToken():
+                startPos = self.pos()
+                codeFor1stToken = self.getCheetahVar()
+                WS = self.getWhiteSpace()
+                if not self.atEnd() and self.peek() == '=':
+                    nextToken = self.getPyToken()
+                    if nextToken == '=':
+                        endPos = self.pos()
+                        self.setPos(startPos)
+                        codeFor1stToken = self.getCheetahVar(plain=True)
+                        self.setPos(endPos)
+                        
+                    ## finally
+                    addBit( codeFor1stToken + WS + nextToken )
+                else:
+                    addBit( codeFor1stToken + WS)
+            elif self.matchCheetahVarStart():
+                # it has syntax that is only valid at the top level
+                self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()
+            else:
+                beforeTokenPos = self.pos()
+                token = self.getPyToken()
+                if token in ('{','(','['):
+                    self.rev()
+                    token = self.getExpression(enclosed=True)
+                token = self.transformToken(token, beforeTokenPos)
+                addBit(token)
+
+        if useNameMapper is not Unspecified:
+            self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
+
+        return ''.join(argStringBits)
+    
+    def getDefArgList(self, exitPos=None, useNameMapper=False):
+
+        """ Get an argument list. Can be used for method/function definition
+        argument lists or for #directive argument lists. Returns a list of
+        tuples in the form (argName, defVal=None) with one tuple for each arg
+        name.
+
+        These defVals are always strings, so (argName, defVal=None) is safe even
+        with a case like (arg1, arg2=None, arg3=1234*2), which would be returned as
+        [('arg1', None),
+         ('arg2', 'None'),
+         ('arg3', '1234*2'),         
+        ]
+
+        This method understands *arg, and **kw
+
+        """
+
+        if self.peek() == '(':
+            self.advance()
+        else:
+            exitPos = self.findEOL()  # it's a directive so break at the EOL
+        argList = ArgList()
+        onDefVal = False
+
+        # @@TR: this settings mangling should be removed
+        useNameMapper_orig = self.setting('useNameMapper')
+        self.setSetting('useNameMapper', useNameMapper)
+
+        while 1:
+            if self.atEnd():
+                raise ParseError(
+                    self, msg="EOF was reached before a matching ')'"+
+                    " was found for the '('")
+
+            if self.pos() == exitPos:
+                break
+
+            c = self.peek()
+            if c == ")" or self.matchDirectiveEndToken():
+                break
+            elif c == ":":
+                break            
+            elif c in " \t\f\r\n":
+                if onDefVal:
+                    argList.addToDefVal(c)
+                self.advance()
+            elif c == '=':
+                onDefVal = True
+                self.advance()
+            elif c == ",":
+                argList.next()
+                onDefVal = False
+                self.advance()
+            elif self.startswith(self.cheetahVarStartToken) and not onDefVal:
+                self.advance(len(self.cheetahVarStartToken))
+            elif self.matchIdentifier() and not onDefVal:
+                argList.addArgName( self.getIdentifier() )
+            elif onDefVal:
+                if self.matchCheetahVarInExpressionStartToken():
+                    token = self.getCheetahVar()
+                elif self.matchCheetahVarStart():
+                    # it has syntax that is only valid at the top level                    
+                    self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()
+                else:
+                    beforeTokenPos = self.pos()
+                    token = self.getPyToken()
+                    if token in ('{','(','['):
+                        self.rev()
+                        token = self.getExpression(enclosed=True)
+                    token = self.transformToken(token, beforeTokenPos)
+                argList.addToDefVal(token)
+            elif c == '*' and not onDefVal:
+                varName = self.getc()
+                if self.peek() == '*':
+                    varName += self.getc()
+                if not self.matchIdentifier():
+                    raise ParseError(self)
+                varName += self.getIdentifier()
+                argList.addArgName(varName)
+            else:
+                raise ParseError(self)
+
+                
+        self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
+        return argList.merge()
+    
+    def getExpressionParts(self,
+                           enclosed=False, 
+                           enclosures=None, # list of tuples (char, pos), where char is ({ or [ 
+                           pyTokensToBreakAt=None, # only works if not enclosed
+                           useNameMapper=Unspecified,
+                           ):
+
+        """ Get a Cheetah expression that includes $CheetahVars and break at
+        directive end tokens, the end of an enclosure, or at a specified
+        pyToken.
+        """
+
+        if useNameMapper is not Unspecified:
+            useNameMapper_orig = self.setting('useNameMapper')
+            self.setSetting('useNameMapper', useNameMapper)
+
+        if enclosures is None:
+            enclosures = []
+        
+        srcLen = len(self)
+        exprBits = []
+        while 1:
+            if self.atEnd():
+                if enclosures:
+                    open = enclosures[-1][0]
+                    close = closurePairsRev[open]
+                    self.setPos(enclosures[-1][1])
+                    raise ParseError(
+                        self, msg="EOF was reached before a matching '" + close +
+                        "' was found for the '" + open + "'")
+                else:
+                    break
+
+            c = self.peek()
+            if c in "{([":
+                exprBits.append(c)
+                enclosures.append( (c, self.pos()) )
+                self.advance()                
+            elif enclosed and not enclosures:
+                break                
+            elif c in "])}":
+                if not enclosures:
+                    raise ParseError(self)
+                open = closurePairs[c]
+                if enclosures[-1][0] == open:
+                    enclosures.pop()
+                    exprBits.append(c)
+                else:
+                    open = enclosures[-1][0]
+                    close = closurePairsRev[open]
+                    row, col = self.getRowCol()
+                    self.setPos(enclosures[-1][1])
+                    raise ParseError(
+                        self, msg= "A '" + c + "' was found at line " + str(row) +
+                        ", col " + str(col) +
+                        " before a matching '" + close +
+                        "' was found\nfor the '" + open + "'")
+                self.advance()
+                                
+            elif c in " \f\t":
+                exprBits.append(self.getWhiteSpace())            
+            elif self.matchDirectiveEndToken() and not enclosures:
+                break            
+            elif c == "\\" and self.pos()+1 < srcLen:
+                eolMatch = EOLre.match(self.src(), self.pos()+1)
+                if not eolMatch:
+                    self.advance()
+                    raise ParseError(self, msg='Line ending expected')
+                self.setPos( eolMatch.end() )
+            elif c in '\r\n':
+                if enclosures:
+                    self.advance()                    
+                else:
+                    break                    
+            elif self.matchCheetahVarInExpressionStartToken():
+                expr = self.getCheetahVar()
+                exprBits.append(expr)
+            elif self.matchCheetahVarStart():
+                # it has syntax that is only valid at the top level                
+                self._raiseErrorAboutInvalidCheetahVarSyntaxInExpr()                    
+            else:                
+                beforeTokenPos = self.pos()
+                token = self.getPyToken()
+                if (not enclosures 
+                    and pyTokensToBreakAt
+                    and token in pyTokensToBreakAt):
+                    
+                    self.setPos(beforeTokenPos)
+                    break
+
+                token = self.transformToken(token, beforeTokenPos)
+                        
+                exprBits.append(token)                    
+                if identRE.match(token):
+                    if token == 'for':
+                        expr = self.getExpression(useNameMapper=False, pyTokensToBreakAt=['in'])
+                        exprBits.append(expr)
+                    else:
+                        exprBits.append(self.getWhiteSpace())
+                        if not self.atEnd() and self.peek() == '(':
+                            exprBits.append(self.getCallArgString())                    
+        ##
+        if useNameMapper is not Unspecified:                            
+            self.setSetting('useNameMapper', useNameMapper_orig) # @@TR: see comment above
+        return exprBits
+
+    def getExpression(self,
+                      enclosed=False, 
+                      enclosures=None, # list of tuples (char, pos), where # char is ({ or [
+                      pyTokensToBreakAt=None,
+                      useNameMapper=Unspecified,
+                      ):
+        """Returns the output of self.getExpressionParts() as a concatenated
+        string rather than as a list.
+        """
+        return ''.join(self.getExpressionParts(
+            enclosed=enclosed, enclosures=enclosures,
+            pyTokensToBreakAt=pyTokensToBreakAt,
+            useNameMapper=useNameMapper))
+
+
+    def transformToken(self, token, beforeTokenPos):
+        """Takes a token from the expression being parsed and performs and
+        special transformations required by Cheetah.
+
+        At the moment only Cheetah's c'$placeholder strings' are transformed.
+        """
+        if token=='c' and not self.atEnd() and self.peek() in '\'"':
+            nextToken = self.getPyToken()
+            token = nextToken.upper()
+            theStr = eval(token)
+            endPos = self.pos()
+            if not theStr:
+                return
+            
+            if token.startswith(single3) or token.startswith(double3):
+                startPosIdx = 3
+            else:
+                startPosIdx = 1
+            #print 'CHEETAH STRING', nextToken, theStr, startPosIdx
+            self.setPos(beforeTokenPos+startPosIdx+1)
+            outputExprs = []
+            strConst = ''
+            while self.pos() < (endPos-startPosIdx):
+                if self.matchCheetahVarStart() or self.matchExpressionPlaceholderStart():
+                    if strConst:
+                        outputExprs.append(repr(strConst))
+                        strConst = ''
+                    placeholderExpr = self.getPlaceholder()
+                    outputExprs.append('str('+placeholderExpr+')')
+                else:
+                    strConst += self.getc()
+            self.setPos(endPos)
+            if strConst:
+                outputExprs.append(repr(strConst))
+            #if not self.atEnd() and self.matches('.join('):
+            #    print 'DEBUG***'
+            token = "''.join(["+','.join(outputExprs)+"])"
+        return token
+
+    def _raiseErrorAboutInvalidCheetahVarSyntaxInExpr(self):
+        match = self.matchCheetahVarStart()
+        groupdict = match.groupdict()
+        if groupdict.get('cacheToken'):
+            raise ParseError(
+                self,
+                msg='Cache tokens are not valid inside expressions. '
+                'Use them in top-level $placeholders only.')                    
+        elif groupdict.get('enclosure'):                    
+            raise ParseError(
+                self,
+                msg='Long-form placeholders - ${}, $(), $[], etc. are not valid inside expressions. '
+                'Use them in top-level $placeholders only.')
+        else:
+            raise ParseError(
+                self,
+                msg='This form of $placeholder syntax is not valid here.')
+        
+
+    def getPlaceholder(self, allowCacheTokens=False, plain=False, returnEverything=False):
+        # filtered 
+        for callback in self.setting('preparsePlaceholderHooks'):
+            callback(parser=self)
+
+        startPos = self.pos()
+        lineCol = self.getRowCol(startPos)
+        startToken = self.getCheetahVarStartToken()
+        silentPlaceholderToken = self.getSilentPlaceholderToken()
+        if silentPlaceholderToken:
+            isSilentPlaceholder = True
+        else:
+            isSilentPlaceholder = False
+            
+        
+        if allowCacheTokens:
+            cacheToken = self.getCacheToken()
+            cacheTokenParts = self.cacheTokenRE.match(cacheToken).groupdict()        
+        else:
+            cacheTokenParts = {}
+
+        if self.peek() in '({[':         
+            pos = self.pos()
+            enclosureOpenChar = self.getc()
+            enclosures = [ (enclosureOpenChar, pos) ]
+            self.getWhiteSpace()
+        else:
+            enclosures = []
+
+        filterArgs = None
+        if self.matchIdentifier(): 
+            nameChunks = self.getCheetahVarNameChunks()
+            expr = self._compiler.genCheetahVar(nameChunks[:], plain=plain)
+            restOfExpr = None
+            if enclosures:
+                WS = self.getWhiteSpace()
+                expr += WS
+                if self.setting('allowPlaceholderFilterArgs') and self.peek()==',':
+                    filterArgs = self.getCallArgString(enclosures=enclosures)[1:-1]
+                else:
+                    if self.peek()==closurePairsRev[enclosureOpenChar]:
+                        self.getc()
+                    else:
+                        restOfExpr = self.getExpression(enclosed=True, enclosures=enclosures)
+                        if restOfExpr[-1] == closurePairsRev[enclosureOpenChar]:
+                            restOfExpr = restOfExpr[:-1]
+                        expr += restOfExpr
+            rawPlaceholder = self[startPos: self.pos()]
+        else:
+            expr = self.getExpression(enclosed=True, enclosures=enclosures)
+            if expr[-1] == closurePairsRev[enclosureOpenChar]:
+                expr = expr[:-1]
+            rawPlaceholder=self[startPos: self.pos()]
+            
+        expr = self._applyExpressionFilters(expr,'placeholder',
+                                            rawExpr=rawPlaceholder,startPos=startPos)
+        for callback in self.setting('postparsePlaceholderHooks'):
+            callback(parser=self)
+
+        if returnEverything:
+            return (expr, rawPlaceholder, lineCol, cacheTokenParts,
+                    filterArgs, isSilentPlaceholder)
+        else:
+            return expr
+        
+
+class _HighLevelParser(_LowLevelParser):
+    """This class is a StateMachine for parsing Cheetah source and
+    sending state dependent code generation commands to
+    Cheetah.Compiler.Compiler.
+    """
+    def __init__(self, src, filename=None, breakPoint=None, compiler=None):
+        _LowLevelParser.__init__(self, src, filename=filename, breakPoint=breakPoint)
+        self.setSettingsManager(compiler)
+        self._compiler = compiler
+        self.setupState()
+        self.configureParser()
+
+    def setupState(self):
+        self._macros = {}        
+        self._macroDetails = {}
+        self._openDirectivesStack = []
+
+    def cleanup(self):
+        """Cleanup to remove any possible reference cycles
+        """
+        self._macros.clear()
+        for macroname, macroDetails in self._macroDetails.items():
+            macroDetails.template.shutdown()
+            del macroDetails.template
+        self._macroDetails.clear()
+
+    def configureParser(self):
+        _LowLevelParser.configureParser(self)
+        self._initDirectives()
+    
+    def _initDirectives(self):
+        def normalizeParserVal(val):
+            if isinstance(val, (str,unicode)):
+                handler = getattr(self, val)
+            elif type(val) in (ClassType, TypeType):
+                handler = val(self)
+            elif callable(val):
+                handler = val
+            elif val is None:
+                handler = val
+            else:
+                raise Exception('Invalid parser/handler value %r for %s'%(val, name))
+            return handler
+        
+        normalizeHandlerVal = normalizeParserVal
+
+        _directiveNamesAndParsers = directiveNamesAndParsers.copy()
+        customNamesAndParsers = self.setting('directiveNamesAndParsers',{})
+        _directiveNamesAndParsers.update(customNamesAndParsers)
+
+        _endDirectiveNamesAndHandlers = endDirectiveNamesAndHandlers.copy()
+        customNamesAndHandlers = self.setting('endDirectiveNamesAndHandlers',{})
+        _endDirectiveNamesAndHandlers.update(customNamesAndHandlers)        
+        
+        self._directiveNamesAndParsers = {}
+        for name, val in _directiveNamesAndParsers.items():
+            if val in (False, 0):
+                continue
+            self._directiveNamesAndParsers[name] = normalizeParserVal(val)
+
+        self._endDirectiveNamesAndHandlers = {}        
+        for name, val in _endDirectiveNamesAndHandlers.items():
+            if val in (False, 0):
+                continue
+            self._endDirectiveNamesAndHandlers[name] = normalizeHandlerVal(val)
+        
+        self._closeableDirectives = ['def','block','closure','defmacro',
+                                     'call',
+                                     'capture',
+                                     'cache',
+                                     'filter',
+                                     'if','unless',
+                                     'for','while','repeat',
+                                     'try',
+                                     ]
+        for directiveName in self.setting('closeableDirectives',[]):
+            self._closeableDirectives.append(directiveName)
+
+
+
+        macroDirectives = self.setting('macroDirectives',{})
+        macroDirectives['i18n'] = I18n
+
+
+        for macroName, callback in macroDirectives.items():
+            if type(callback) in (ClassType, TypeType):
+                callback = callback(parser=self)
+            assert callback                
+            self._macros[macroName] = callback
+            self._directiveNamesAndParsers[macroName] = self.eatMacroCall
+            
+    def _applyExpressionFilters(self, expr, exprType, rawExpr=None, startPos=None):
+        """Pipes cheetah expressions through a set of optional filter hooks.
+
+        The filters are functions which may modify the expressions or raise
+        a ForbiddenExpression exception if the expression is not allowed.  They
+        are defined in the compiler setting 'expressionFilterHooks'.
+
+        Some intended use cases:
+
+         - to implement 'restricted execution' safeguards in cases where you
+           can't trust the author of the template.
+
+         - to enforce style guidelines  
+           
+        filter call signature:  (parser, expr, exprType, rawExpr=None, startPos=None)
+         - parser is the Cheetah parser  
+         - expr is the expression to filter.  In some cases the parser will have
+           already modified it from the original source code form.  For example,
+           placeholders will have been translated into namemapper calls.  If you
+           need to work with the original source, see rawExpr.        
+         - exprType is the name of the directive, 'psp', or 'placeholder'. All
+           lowercase.  @@TR: These will eventually be replaced with a set of
+           constants.
+         - rawExpr is the original source string that Cheetah parsed.  This
+           might be None in some cases.
+         - startPos is the character position in the source string/file
+           where the parser started parsing the current expression.
+
+        @@TR: I realize this use of the term 'expression' is a bit wonky as many
+         of the 'expressions' are actually statements, but I haven't thought of
+         a better name yet.  Suggestions?
+        """
+        for callback in self.setting('expressionFilterHooks'):
+            expr = callback(parser=self, expr=expr,  exprType=exprType,
+                            rawExpr=rawExpr, startPos=startPos)
+        return expr
+
+    def _filterDisabledDirectives(self, directiveName):
+        directiveName = directiveName.lower()
+        if (directiveName in self.setting('disabledDirectives')
+            or (self.setting('enabledDirectives')
+                and directiveName not in self.setting('enabledDirectives'))):
+            for callback in self.setting('disabledDirectiveHooks'):
+                callback(parser=self, directiveName=directiveName)
+            raise ForbiddenDirective(self, msg='This %r directive is disabled'%directiveName)
+        
+    ## main parse loop
+
+    def parse(self, breakPoint=None, assertEmptyStack=True):
+        if breakPoint:
+            origBP = self.breakPoint()
+            self.setBreakPoint(breakPoint)
+            assertEmptyStack = False
+
+        while not self.atEnd():
+            if self.matchCommentStartToken():
+                self.eatComment()
+            elif self.matchMultiLineCommentStartToken():
+                self.eatMultiLineComment()
+            elif self.matchVariablePlaceholderStart():
+                self.eatPlaceholder()
+            elif self.matchExpressionPlaceholderStart():
+                self.eatPlaceholder()
+            elif self.matchDirective():
+                self.eatDirective()
+            elif self.matchPSPStartToken():
+                self.eatPSP()
+            elif self.matchEOLSlurpToken():
+                self.eatEOLSlurpToken()
+            else:
+                self.eatPlainText()
+        if assertEmptyStack:
+            self.assertEmptyOpenDirectivesStack()
+        if breakPoint:
+            self.setBreakPoint(origBP)
+            
+    ## non-directive eat methods    
+                
+    def eatPlainText(self):
+        startPos = self.pos()
+        match = None
+        while not self.atEnd():
+            match = self.matchTopLevelToken()
+            if match:
+                break
+            else:
+                self.advance()
+        strConst = self.readTo(self.pos(), start=startPos)
+        self._compiler.addStrConst(strConst)
+        return match
+
+    def eatComment(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        if isLineClearToStartToken:
+            self._compiler.handleWSBeforeDirective()
+        self.getCommentStartToken()            
+        comm = self.readToEOL(gobble=isLineClearToStartToken)
+        self._compiler.addComment(comm)
+
+    def eatMultiLineComment(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+
+        self.getMultiLineCommentStartToken()
+        endPos = startPos = self.pos()
+        level = 1
+        while 1:
+            endPos = self.pos()
+            if self.atEnd():
+                break
+            if self.matchMultiLineCommentStartToken():
+                self.getMultiLineCommentStartToken()
+                level += 1
+            elif self.matchMultiLineCommentEndToken():
+                self.getMultiLineCommentEndToken()
+                level -= 1
+            if not level:
+                break
+            self.advance()
+        comm = self.readTo(endPos, start=startPos)
+
+        if not self.atEnd():
+            self.getMultiLineCommentEndToken()
+
+        if (not self.atEnd()) and self.setting('gobbleWhitespaceAroundMultiLineComments'):
+            restOfLine = self[self.pos():self.findEOL()]
+            if not restOfLine.strip(): # WS only to EOL
+                self.readToEOL(gobble=isLineClearToStartToken)
+
+            if isLineClearToStartToken and (self.atEnd() or self.pos() > endOfFirstLine):
+                self._compiler.handleWSBeforeDirective()
+        
+        self._compiler.addComment(comm)
+
+    def eatPlaceholder(self):
+        (expr, rawPlaceholder,
+         lineCol, cacheTokenParts,
+         filterArgs, isSilentPlaceholder) = self.getPlaceholder(
+            allowCacheTokens=True, returnEverything=True)
+        
+        self._compiler.addPlaceholder(
+            expr,
+            filterArgs=filterArgs,
+            rawPlaceholder=rawPlaceholder,
+            cacheTokenParts=cacheTokenParts,
+            lineCol=lineCol,
+            silentMode=isSilentPlaceholder)
+        return
+        
+    def eatPSP(self):
+        # filtered
+        self._filterDisabledDirectives(directiveName='psp')
+        self.getPSPStartToken()
+        endToken = self.setting('PSPEndToken')
+        startPos = self.pos()            
+        while not self.atEnd():
+            if self.peek() == endToken[0]:
+                if self.matchPSPEndToken():
+                    break
+            self.advance()
+        pspString = self.readTo(self.pos(), start=startPos).strip()
+        pspString = self._applyExpressionFilters(pspString, 'psp', startPos=startPos)
+        self._compiler.addPSP(pspString)
+        self.getPSPEndToken()
+
+    ## generic directive eat methods
+    _simpleIndentingDirectives = '''
+    else elif for while repeat unless try except finally'''.split()
+    _simpleExprDirectives = '''
+    pass continue stop return yield break
+    del assert raise
+    silent echo    
+    import from'''.split()
+    _directiveHandlerNames = {'import':'addImportStatement',
+                              'from':'addImportStatement', }
+    def eatDirective(self):
+        directiveName = self.matchDirective()
+        self._filterDisabledDirectives(directiveName)
+
+        for callback in self.setting('preparseDirectiveHooks'):
+            callback(parser=self, directiveName=directiveName)
+
+        # subclasses can override the default behaviours here by providing an
+        # eater method in self._directiveNamesAndParsers[directiveName]
+        directiveParser = self._directiveNamesAndParsers.get(directiveName)
+        if directiveParser:
+            directiveParser()
+        elif directiveName in self._simpleIndentingDirectives:
+            handlerName = self._directiveHandlerNames.get(directiveName)
+            if not handlerName:
+                handlerName = 'add'+directiveName.capitalize()
+            handler = getattr(self._compiler, handlerName)
+            self.eatSimpleIndentingDirective(directiveName, callback=handler)
+        elif directiveName in self._simpleExprDirectives:
+            handlerName = self._directiveHandlerNames.get(directiveName)
+            if not handlerName:
+                handlerName = 'add'+directiveName.capitalize()
+            handler = getattr(self._compiler, handlerName)
+            if directiveName in ('silent', 'echo'):
+                includeDirectiveNameInExpr = False
+            else:
+                includeDirectiveNameInExpr = True
+            expr = self.eatSimpleExprDirective(
+                directiveName,
+                includeDirectiveNameInExpr=includeDirectiveNameInExpr)
+            handler(expr)
+        ##    
+        for callback in self.setting('postparseDirectiveHooks'):
+            callback(parser=self, directiveName=directiveName)
+
+    def _eatRestOfDirectiveTag(self, isLineClearToStartToken, endOfFirstLinePos):
+        foundComment = False
+        if self.matchCommentStartToken():
+            pos = self.pos()
+            self.advance()
+            if not self.matchDirective():
+                self.setPos(pos)
+                foundComment = True
+                self.eatComment() # this won't gobble the EOL
+            else:
+                self.setPos(pos)
+            
+        if not foundComment and self.matchDirectiveEndToken():
+                self.getDirectiveEndToken()
+        elif isLineClearToStartToken and (not self.atEnd()) and self.peek() in '\r\n':
+            # still gobble the EOL if a comment was found. 
+            self.readToEOL(gobble=True)
+            
+        if isLineClearToStartToken and (self.atEnd() or self.pos() > endOfFirstLinePos):
+            self._compiler.handleWSBeforeDirective()
+
+    def _eatToThisEndDirective(self, directiveName):
+        finalPos = endRawPos = startPos = self.pos()
+        directiveChar = self.setting('directiveStartToken')[0]
+        isLineClearToStartToken = False
+        while not self.atEnd():
+            if self.peek() == directiveChar:
+                if self.matchDirective() == 'end':
+                    endRawPos = self.pos()
+                    self.getDirectiveStartToken()
+                    self.advance(len('end'))
+                    self.getWhiteSpace()
+                    if self.startswith(directiveName):
+                        if self.isLineClearToStartToken(endRawPos):
+                            isLineClearToStartToken = True
+                            endRawPos = self.findBOL(endRawPos)
+                        self.advance(len(directiveName)) # to end of directiveName
+                        self.getWhiteSpace()
+                        finalPos = self.pos()
+                        break
+            self.advance()
+            finalPos = endRawPos = self.pos()
+
+        textEaten = self.readTo(endRawPos, start=startPos)
+        self.setPos(finalPos)
+        
+        endOfFirstLinePos = self.findEOL()
+        
+        if self.matchDirectiveEndToken():
+            self.getDirectiveEndToken()
+        elif isLineClearToStartToken and (not self.atEnd()) and self.peek() in '\r\n':
+            self.readToEOL(gobble=True)
+            
+        if isLineClearToStartToken and self.pos() > endOfFirstLinePos:
+            self._compiler.handleWSBeforeDirective()
+        return textEaten
+
+
+    def eatSimpleExprDirective(self, directiveName, includeDirectiveNameInExpr=True):
+        # filtered 
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        if not includeDirectiveNameInExpr:
+            self.advance(len(directiveName))
+        startPos = self.pos()
+        expr = self.getExpression().strip()
+        directiveName = expr.split()[0]
+        expr = self._applyExpressionFilters(expr, directiveName, startPos=startPos)
+        if directiveName in self._closeableDirectives:
+            self.pushToOpenDirectivesStack(directiveName)
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+        return expr
+
+    def eatSimpleIndentingDirective(self, directiveName, callback,
+                                    includeDirectiveNameInExpr=False):
+        # filtered 
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        lineCol = self.getRowCol()
+        self.getDirectiveStartToken()
+        if directiveName not in 'else elif for while try except finally'.split():
+            self.advance(len(directiveName))
+        startPos = self.pos()
+
+        self.getWhiteSpace()
+
+        expr = self.getExpression(pyTokensToBreakAt=[':'])
+        expr = self._applyExpressionFilters(expr, directiveName, startPos=startPos)
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            if directiveName in 'else elif except finally'.split():
+                callback(expr, dedent=False, lineCol=lineCol)
+            else:
+                callback(expr, lineCol=lineCol)
+                
+            self.getWhiteSpace(max=1)
+            self.parse(breakPoint=self.findEOL(gobble=True))
+            self._compiler.commitStrConst()
+            self._compiler.dedent()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            if directiveName in self._closeableDirectives:
+                self.pushToOpenDirectivesStack(directiveName)
+            callback(expr, lineCol=lineCol)
+
+    def eatEndDirective(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        self.getDirectiveStartToken()
+        self.advance(3)                 # to end of 'end'
+        self.getWhiteSpace()
+        pos = self.pos()
+        directiveName = False
+        for key in self._endDirectiveNamesAndHandlers.keys():
+            if self.find(key, pos) == pos:
+                directiveName = key
+                break
+        if not directiveName:
+            raise ParseError(self, msg='Invalid end directive')
+        
+        endOfFirstLinePos = self.findEOL()
+        self.getExpression() # eat in any extra comment-like crap
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)            
+        if directiveName in self._closeableDirectives:
+            self.popFromOpenDirectivesStack(directiveName)
+
+        # subclasses can override the default behaviours here by providing an
+        # end-directive handler in self._endDirectiveNamesAndHandlers[directiveName]
+        if self._endDirectiveNamesAndHandlers.get(directiveName):
+            handler = self._endDirectiveNamesAndHandlers[directiveName]
+            handler()
+        elif directiveName in 'block capture cache call filter errorCatcher'.split():
+            if key == 'block':
+                self._compiler.closeBlock()
+            elif key == 'capture':
+                self._compiler.endCaptureRegion()
+            elif key == 'cache':
+                self._compiler.endCacheRegion()
+            elif key == 'call':
+                self._compiler.endCallRegion()
+            elif key == 'filter':
+                self._compiler.closeFilterBlock()
+            elif key == 'errorCatcher':
+                self._compiler.turnErrorCatcherOff()
+        elif directiveName in 'while for if try repeat unless'.split():
+            self._compiler.commitStrConst()
+            self._compiler.dedent()
+        elif directiveName=='closure':
+            self._compiler.commitStrConst()
+            self._compiler.dedent()
+            # @@TR: temporary hack of useSearchList
+            self.setSetting('useSearchList', self._useSearchList_orig)            
+
+    ## specific directive eat methods
+    
+    def eatBreakPoint(self):
+        """Tells the parser to stop parsing at this point and completely ignore
+        everything else.
+
+        This is a debugging tool.
+        """
+        self.setBreakPoint(self.pos())
+
+    def eatShbang(self):
+        # filtered 
+        self.getDirectiveStartToken()
+        self.advance(len('shBang'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        shBang = self.readToEOL()
+        shBang = self._applyExpressionFilters(shBang, 'shbang', startPos=startPos)
+        self._compiler.setShBang(shBang.strip())
+
+    def eatEncoding(self):
+        # filtered 
+        self.getDirectiveStartToken()
+        self.advance(len('encoding'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        encoding = self.readToEOL()
+        encoding = self._applyExpressionFilters(encoding, 'encoding', startPos=startPos)               
+        self._compiler.setModuleEncoding(encoding.strip())
+        
+    def eatCompiler(self):
+        # filtered 
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        startPos = self.pos()
+        self.getDirectiveStartToken()
+        self.advance(len('compiler'))   # to end of 'compiler'
+        self.getWhiteSpace()
+
+        startPos = self.pos()
+        settingName = self.getIdentifier()
+
+        if settingName.lower() == 'reset':
+            self.getExpression() # gobble whitespace & junk
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+            self._initializeSettings()
+            self.configureParser()
+            return
+        
+        self.getWhiteSpace()
+        if self.peek() == '=':
+            self.advance()
+        else:
+            raise ParseError(self)
+        valueExpr = self.getExpression()
+        endPos = self.pos()
+
+        # @@TR: it's unlikely that anyone apply filters would have left this
+        # directive enabled:
+        # @@TR: fix up filtering, regardless
+        self._applyExpressionFilters('%s=%r'%(settingName, valueExpr),
+                                     'compiler', startPos=startPos)
+        
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+        try:
+            self._compiler.setCompilerSetting(settingName, valueExpr)
+        except:
+            out = sys.stderr
+            print >> out, 'An error occurred while processing the following #compiler directive.'
+            print >> out, '-'*80
+            print >> out, self[startPos:endPos]
+            print >> out, '-'*80
+            print >> out, 'Please check the syntax of these settings.'
+            print >> out, 'A full Python exception traceback follows.'
+            raise
+
+
+    def eatCompilerSettings(self):
+        # filtered         
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('compiler-settings'))   # to end of 'settings'
+        
+        keywords = self.getTargetVarsList()
+        self.getExpression()            # gobble any garbage
+            
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+
+        if 'reset' in keywords:
+            self._compiler._initializeSettings()
+            self.configureParser()
+            # @@TR: this implies a single-line #compiler-settings directive, and
+            # thus we should parse forward for an end directive.
+            # Subject to change in the future
+            return 
+        startPos = self.pos()
+        settingsStr = self._eatToThisEndDirective('compiler-settings')            
+        settingsStr = self._applyExpressionFilters(settingsStr, 'compilerSettings', 
+                                                   startPos=startPos)
+        try:
+            self._compiler.setCompilerSettings(keywords=keywords, settingsStr=settingsStr)
+        except:
+            out = sys.stderr
+            print >> out, 'An error occurred while processing the following compiler settings.'
+            print >> out, '-'*80
+            print >> out, settingsStr.strip()
+            print >> out, '-'*80
+            print >> out, 'Please check the syntax of these settings.'
+            print >> out, 'A full Python exception traceback follows.'
+            raise
+
+    def eatAttr(self):
+        # filtered         
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        startPos = self.pos()
+        self.getDirectiveStartToken()
+        self.advance(len('attr'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        if self.matchCheetahVarStart():
+            self.getCheetahVarStartToken()
+        attribName = self.getIdentifier()
+        self.getWhiteSpace()
+        self.getAssignmentOperator()
+        expr = self.getExpression()
+        expr = self._applyExpressionFilters(expr, 'attr', startPos=startPos)
+        self._compiler.addAttribute(attribName, expr)
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+
+    def eatDecorator(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        startPos = self.pos()
+        self.getDirectiveStartToken()
+        #self.advance() # eat @
+        startPos = self.pos()
+        decoratorExpr = self.getExpression()
+        decoratorExpr = self._applyExpressionFilters(decoratorExpr, 'decorator', startPos=startPos)
+        self._compiler.addDecorator(decoratorExpr)
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+        self.getWhiteSpace()
+
+        directiveName = self.matchDirective()
+        if not directiveName or directiveName not in ('def', 'block', 'closure', '@'):
+            raise ParseError(
+                self, msg='Expected #def, #block, #closure or another @decorator')
+        self.eatDirective()
+        
+    def eatDef(self):
+        # filtered         
+        self._eatDefOrBlock('def')
+
+    def eatBlock(self):
+        # filtered
+        startPos = self.pos()
+        methodName, rawSignature = self._eatDefOrBlock('block')
+        self._compiler._blockMetaData[methodName] = {
+            'raw':rawSignature,
+            'lineCol':self.getRowCol(startPos),
+            }
+
+    def eatClosure(self):
+        # filtered         
+        self._eatDefOrBlock('closure')
+        
+    def _eatDefOrBlock(self, directiveName):
+        # filtered 
+        assert directiveName in ('def','block','closure')
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        startPos = self.pos()
+        self.getDirectiveStartToken()
+        self.advance(len(directiveName))
+        self.getWhiteSpace()
+        if self.matchCheetahVarStart():
+            self.getCheetahVarStartToken()
+        methodName = self.getIdentifier()
+        self.getWhiteSpace()
+        if self.peek() == '(':
+            argsList = self.getDefArgList()
+            self.advance()              # past the closing ')'
+            if argsList and argsList[0][0] == 'self':
+                del argsList[0]
+        else:
+            argsList=[]
+
+        def includeBlockMarkers():
+            if self.setting('includeBlockMarkers'):
+                startMarker = self.setting('blockMarkerStart')
+                self._compiler.addStrConst(startMarker[0] + methodName + startMarker[1])
+
+        # @@TR: fix up filtering
+        self._applyExpressionFilters(self[startPos:self.pos()], 'def', startPos=startPos)
+
+        if self.matchColonForSingleLineShortFormDirective():
+            isNestedDef = (self.setting('allowNestedDefScopes')
+                           and [name for name in self._openDirectivesStack if name=='def'])
+            self.getc()
+            rawSignature = self[startPos:endOfFirstLinePos]
+            self._eatSingleLineDef(directiveName=directiveName,
+                                   methodName=methodName,
+                                   argsList=argsList,
+                                   startPos=startPos,
+                                   endPos=endOfFirstLinePos)
+            if directiveName == 'def' and not isNestedDef:
+                #@@TR: must come before _eatRestOfDirectiveTag ... for some reason
+                self._compiler.closeDef()
+            elif directiveName == 'block':
+                includeBlockMarkers()
+                self._compiler.closeBlock()
+            elif directiveName == 'closure' or isNestedDef:
+                self._compiler.dedent()
+                
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+        else:
+            if self.peek()==':':
+                self.getc()            
+            self.pushToOpenDirectivesStack(directiveName)
+            rawSignature = self[startPos:self.pos()]
+            self._eatMultiLineDef(directiveName=directiveName,
+                                  methodName=methodName,
+                                  argsList=argsList,
+                                  startPos=startPos,
+                                  isLineClearToStartToken=isLineClearToStartToken)
+            if directiveName == 'block':
+                includeBlockMarkers()
+
+        return methodName, rawSignature
+
+    def _eatMultiLineDef(self, directiveName, methodName, argsList, startPos,
+                         isLineClearToStartToken=False):
+        # filtered in calling method
+        self.getExpression()            # slurp up any garbage left at the end
+        signature = self[startPos:self.pos()]
+        endOfFirstLinePos = self.findEOL()
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+        signature = ' '.join([line.strip() for line in signature.splitlines()]) 
+        parserComment = ('## CHEETAH: generated from ' + signature + 
+                         ' at line %s, col %s' % self.getRowCol(startPos)
+                         + '.')
+
+        isNestedDef = (self.setting('allowNestedDefScopes')
+                       and len([name for name in self._openDirectivesStack if name=='def'])>1)
+        if directiveName=='block' or (directiveName=='def' and not isNestedDef):
+            self._compiler.startMethodDef(methodName, argsList, parserComment)
+        else: #closure
+            self._useSearchList_orig = self.setting('useSearchList')
+            self.setSetting('useSearchList', False)
+            self._compiler.addClosure(methodName, argsList, parserComment)
+
+        return methodName
+
+    def _eatSingleLineDef(self, directiveName, methodName, argsList, startPos, endPos):
+        # filtered in calling method        
+        fullSignature = self[startPos:endPos]
+        parserComment = ('## Generated from ' + fullSignature + 
+                         ' at line %s, col %s' % self.getRowCol(startPos)
+                         + '.')
+        isNestedDef = (self.setting('allowNestedDefScopes')
+                       and [name for name in self._openDirectivesStack if name=='def'])
+        if directiveName=='block' or (directiveName=='def' and not isNestedDef):
+            self._compiler.startMethodDef(methodName, argsList, parserComment)
+        else: #closure
+            # @@TR: temporary hack of useSearchList
+            useSearchList_orig = self.setting('useSearchList')
+            self.setSetting('useSearchList', False)            
+            self._compiler.addClosure(methodName, argsList, parserComment)            
+
+        self.getWhiteSpace(max=1)
+        self.parse(breakPoint=endPos)        
+        if directiveName=='closure' or isNestedDef: # @@TR: temporary hack of useSearchList
+            self.setSetting('useSearchList', useSearchList_orig)
+    
+    def eatExtends(self):
+        # filtered
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('extends'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        if self.setting('allowExpressionsInExtendsDirective'):
+            baseName = self.getExpression()
+        else:
+            baseName = self.getDottedName()
+                       
+        baseName = self._applyExpressionFilters(baseName, 'extends', startPos=startPos)
+        self._compiler.setBaseClass(baseName) # in compiler
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+            
+    def eatImplements(self):
+        # filtered
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('implements'))
+        self.getWhiteSpace()       
+        startPos = self.pos()
+        methodName = self.getIdentifier()
+        if not self.atEnd() and self.peek() == '(':
+            argsList = self.getDefArgList()
+            self.advance()              # past the closing ')'
+            if argsList and argsList[0][0] == 'self':
+                del argsList[0]
+        else:
+            argsList=[]
+
+        # @@TR: need to split up filtering of the methodname and the args
+        #methodName = self._applyExpressionFilters(methodName, 'implements', startPos=startPos)
+        self._applyExpressionFilters(self[startPos:self.pos()], 'implements', startPos=startPos)
+
+        self._compiler.setMainMethodName(methodName)
+        self._compiler.setMainMethodArgs(argsList)
+            
+        self.getExpression()  # throw away and unwanted crap that got added in
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+
+    def eatSuper(self):
+        # filtered
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('super'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        if not self.atEnd() and self.peek() == '(':
+            argsList = self.getDefArgList()
+            self.advance()              # past the closing ')'
+            if argsList and argsList[0][0] == 'self':
+                del argsList[0]
+        else:
+            argsList=[]
+
+        self._applyExpressionFilters(self[startPos:self.pos()], 'super', startPos=startPos)
+
+        #parserComment = ('## CHEETAH: generated from ' + signature + 
+        #                 ' at line %s, col %s' % self.getRowCol(startPos)
+        #                 + '.')
+
+        self.getExpression()  # throw away and unwanted crap that got added in
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+        self._compiler.addSuper(argsList)
+
+    def eatSet(self):
+        # filtered
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(3)
+        self.getWhiteSpace()
+        style = SET_LOCAL
+        if self.startswith('local'):
+            self.getIdentifier()
+            self.getWhiteSpace()
+        elif self.startswith('global'):
+            self.getIdentifier()
+            self.getWhiteSpace()
+            style = SET_GLOBAL
+        elif self.startswith('module'):
+            self.getIdentifier()
+            self.getWhiteSpace()
+            style = SET_MODULE
+
+        startsWithDollar = self.matchCheetahVarStart()
+        startPos = self.pos()
+        LVALUE = self.getExpression(pyTokensToBreakAt=assignmentOps, useNameMapper=False).strip()
+        OP = self.getAssignmentOperator()
+        RVALUE = self.getExpression()        
+        expr = LVALUE + ' ' + OP + ' ' + RVALUE.strip()
+        
+        expr = self._applyExpressionFilters(expr, 'set', startPos=startPos)
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)
+
+        class Components: pass # used for 'set global'
+        exprComponents = Components()
+        exprComponents.LVALUE = LVALUE
+        exprComponents.OP = OP
+        exprComponents.RVALUE = RVALUE
+        self._compiler.addSet(expr, exprComponents, style)
+    
+    def eatSlurp(self):
+        if self.isLineClearToStartToken():
+            self._compiler.handleWSBeforeDirective()
+        self._compiler.commitStrConst()
+        self.readToEOL(gobble=True)
+
+    def eatEOLSlurpToken(self):
+        if self.isLineClearToStartToken():
+            self._compiler.handleWSBeforeDirective()
+        self._compiler.commitStrConst()
+        self.readToEOL(gobble=True)        
+
+    def eatRaw(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('raw'))
+        self.getWhiteSpace()
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self.getWhiteSpace(max=1)
+            rawBlock = self.readToEOL(gobble=False)
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            rawBlock = self._eatToThisEndDirective('raw')
+        self._compiler.addRawText(rawBlock)
+    
+    def eatInclude(self):
+        # filtered
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('include'))
+
+        self.getWhiteSpace()
+        includeFrom = 'file'
+        isRaw = False
+        if self.startswith('raw'):
+            self.advance(3)
+            isRaw=True
+            
+        self.getWhiteSpace()            
+        if self.startswith('source'):
+            self.advance(len('source'))
+            includeFrom = 'str'
+            self.getWhiteSpace()
+            if not self.peek() == '=':
+                raise ParseError(self)
+            self.advance()
+        startPos = self.pos()
+        sourceExpr = self.getExpression()
+        sourceExpr = self._applyExpressionFilters(sourceExpr, 'include', startPos=startPos)        
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+        self._compiler.addInclude(sourceExpr, includeFrom, isRaw)
+
+    
+    def eatDefMacro(self):
+        # @@TR: not filtered yet
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('defmacro'))
+
+        self.getWhiteSpace()
+        if self.matchCheetahVarStart():
+            self.getCheetahVarStartToken()
+        macroName = self.getIdentifier()
+        self.getWhiteSpace()
+        if self.peek() == '(':
+            argsList = self.getDefArgList(useNameMapper=False)
+            self.advance()              # past the closing ')'
+            if argsList and argsList[0][0] == 'self':
+                del argsList[0]
+        else:
+            argsList=[]
+
+        assert not self._directiveNamesAndParsers.has_key(macroName)
+        argsList.insert(0, ('src',None))
+        argsList.append(('parser','None'))
+        argsList.append(('macros','None'))
+        argsList.append(('compilerSettings','None'))
+        argsList.append(('isShortForm','None'))
+        argsList.append(('EOLCharsInShortForm','None'))        
+        argsList.append(('startPos','None'))
+        argsList.append(('endPos','None'))
+        
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self.getWhiteSpace(max=1)
+            macroSrc = self.readToEOL(gobble=False)
+            self.readToEOL(gobble=True)
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            macroSrc = self._eatToThisEndDirective('defmacro')
+
+        #print argsList
+        normalizedMacroSrc = ''.join(
+            ['%def callMacro('+','.join([defv and '%s=%s'%(n,defv) or n
+                                         for n,defv in argsList])
+             +')\n',
+             macroSrc,
+             '%end def'])
+
+        
+        from Cheetah.Template import Template
+        templateAPIClass = self.setting('templateAPIClassForDefMacro', default=Template)
+        compilerSettings = self.setting('compilerSettingsForDefMacro', default={})
+        searchListForMacros = self.setting('searchListForDefMacro', default=[])
+        searchListForMacros = list(searchListForMacros) # copy to avoid mutation bugs
+        searchListForMacros.append({'macros':self._macros,
+                                    'parser':self,
+                                    'compilerSettings':self.settings(),                                    
+                                    })
+        
+        templateAPIClass._updateSettingsWithPreprocessTokens(
+            compilerSettings, placeholderToken='@', directiveToken='%')
+        macroTemplateClass = templateAPIClass.compile(source=normalizedMacroSrc,
+                                                      compilerSettings=compilerSettings)
+        #print normalizedMacroSrc
+        #t = macroTemplateClass()
+        #print t.callMacro('src')
+        #print t.generatedClassCode()
+        
+        class MacroDetails: pass
+        macroDetails = MacroDetails()
+        macroDetails.macroSrc = macroSrc
+        macroDetails.argsList = argsList
+        macroDetails.template = macroTemplateClass(searchList=searchListForMacros)
+
+        self._macroDetails[macroName] = macroDetails
+        self._macros[macroName] = macroDetails.template.callMacro
+        self._directiveNamesAndParsers[macroName] = self.eatMacroCall
+
+    def eatMacroCall(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        startPos = self.pos()
+        self.getDirectiveStartToken()
+        macroName = self.getIdentifier()
+        macro = self._macros[macroName]
+        if hasattr(macro, 'parse'):
+            return macro.parse(parser=self, startPos=startPos)
+        
+        if hasattr(macro, 'parseArgs'):
+            args = macro.parseArgs(parser=self, startPos=startPos)
+        else:
+            self.getWhiteSpace()
+            args = self.getExpression(useNameMapper=False,
+                                      pyTokensToBreakAt=[':']).strip()
+
+        if self.matchColonForSingleLineShortFormDirective():
+            isShortForm = True
+            self.advance() # skip over :
+            self.getWhiteSpace(max=1)
+            srcBlock = self.readToEOL(gobble=False)
+            EOLCharsInShortForm = self.readToEOL(gobble=True)
+            #self.readToEOL(gobble=False)
+        else:
+            isShortForm = False
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            srcBlock = self._eatToThisEndDirective(macroName)
+
+
+        if hasattr(macro, 'convertArgStrToDict'):
+            kwArgs = macro.convertArgStrToDict(args, parser=self, startPos=startPos)
+        else:
+            def getArgs(*pargs, **kws):
+                return pargs, kws
+            exec 'positionalArgs, kwArgs = getArgs(%(args)s)'%locals()
+
+        assert not kwArgs.has_key('src')
+        kwArgs['src'] = srcBlock
+
+        if type(macro)==new.instancemethod:
+            co = macro.im_func.func_code
+        elif (hasattr(macro, '__call__')
+              and hasattr(macro.__call__, 'im_func')):
+            co = macro.__call__.im_func.func_code
+        else:
+            co = macro.func_code
+        availableKwArgs = inspect.getargs(co)[0]
+        
+        if 'parser' in availableKwArgs:
+            kwArgs['parser'] = self
+        if 'macros' in availableKwArgs:
+            kwArgs['macros'] = self._macros
+        if 'compilerSettings' in availableKwArgs:
+            kwArgs['compilerSettings'] = self.settings()
+        if 'isShortForm' in availableKwArgs:
+            kwArgs['isShortForm'] = isShortForm
+        if isShortForm and 'EOLCharsInShortForm' in availableKwArgs:
+            kwArgs['EOLCharsInShortForm'] = EOLCharsInShortForm
+
+        if 'startPos' in availableKwArgs:
+            kwArgs['startPos'] = startPos
+        if 'endPos' in availableKwArgs:
+            kwArgs['endPos'] = self.pos()
+
+        srcFromMacroOutput = macro(**kwArgs)
+
+        origParseSrc = self._src
+        origBreakPoint = self.breakPoint()
+        origPos = self.pos()
+        # add a comment to the output about the macro src that is being parsed
+        # or add a comment prefix to all the comments added by the compiler
+        self._src = srcFromMacroOutput
+        self.setPos(0)
+        self.setBreakPoint(len(srcFromMacroOutput))
+        
+        self.parse(assertEmptyStack=False)
+
+        self._src = origParseSrc
+        self.setBreakPoint(origBreakPoint)
+        self.setPos(origPos)                
+
+
+        #self._compiler.addRawText('end')
+        
+    def eatCache(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        lineCol = self.getRowCol()
+        self.getDirectiveStartToken()
+        self.advance(len('cache'))
+
+        startPos = self.pos()
+        argList = self.getDefArgList(useNameMapper=True)
+        argList = self._applyExpressionFilters(argList, 'cache', startPos=startPos)
+
+        def startCache():
+            cacheInfo = self._compiler.genCacheInfoFromArgList(argList)
+            self._compiler.startCacheRegion(cacheInfo, lineCol)
+
+        if self.matchColonForSingleLineShortFormDirective():            
+            self.advance() # skip over :
+            self.getWhiteSpace(max=1)
+            startCache()
+            self.parse(breakPoint=self.findEOL(gobble=True))
+            self._compiler.endCacheRegion()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()            
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            self.pushToOpenDirectivesStack('cache')
+            startCache()        
+
+    def eatCall(self):
+        # @@TR: need to enable single line version of this
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        lineCol = self.getRowCol()
+        self.getDirectiveStartToken()
+        self.advance(len('call'))
+        startPos = self.pos()
+        
+        useAutocallingOrig = self.setting('useAutocalling')
+        self.setSetting('useAutocalling', False)
+        self.getWhiteSpace()
+        if self.matchCheetahVarStart():
+            functionName = self.getCheetahVar()
+        else:
+            functionName = self.getCheetahVar(plain=True, skipStartToken=True)
+        self.setSetting('useAutocalling', useAutocallingOrig)
+        # @@TR: fix up filtering
+        self._applyExpressionFilters(self[startPos:self.pos()], 'call', startPos=startPos)
+
+        self.getWhiteSpace()
+        args = self.getExpression(pyTokensToBreakAt=[':']).strip()
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self._compiler.startCallRegion(functionName, args, lineCol)
+            self.getWhiteSpace(max=1)
+            self.parse(breakPoint=self.findEOL(gobble=False))
+            self._compiler.endCallRegion()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self.pushToOpenDirectivesStack("call")            
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            self._compiler.startCallRegion(functionName, args, lineCol)
+
+    def eatCallArg(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        lineCol = self.getRowCol()
+        self.getDirectiveStartToken()
+
+        self.advance(len('arg'))
+        startPos = self.pos()
+        self.getWhiteSpace()
+        argName = self.getIdentifier()
+        self.getWhiteSpace()
+        argName = self._applyExpressionFilters(argName, 'arg', startPos=startPos)
+        self._compiler.setCallArg(argName, lineCol)
+        if self.peek() == ':':
+            self.getc()
+        else:        
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+
+    def eatFilter(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+
+        self.getDirectiveStartToken()
+        self.advance(len('filter'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        if self.matchCheetahVarStart():
+            isKlass = True
+            theFilter = self.getExpression(pyTokensToBreakAt=[':'])
+        else:
+            isKlass = False
+            theFilter = self.getIdentifier()
+            self.getWhiteSpace()
+        theFilter = self._applyExpressionFilters(theFilter, 'filter', startPos=startPos)            
+
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self.getWhiteSpace(max=1)            
+            self._compiler.setFilter(theFilter, isKlass)
+            self.parse(breakPoint=self.findEOL(gobble=False))
+            self._compiler.closeFilterBlock()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self.pushToOpenDirectivesStack("filter")
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            self._compiler.setFilter(theFilter, isKlass)        
+
+    def eatTransform(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+
+        self.getDirectiveStartToken()
+        self.advance(len('transform'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        if self.matchCheetahVarStart():
+            isKlass = True
+            transformer = self.getExpression(pyTokensToBreakAt=[':'])
+        else:
+            isKlass = False
+            transformer = self.getIdentifier()
+            self.getWhiteSpace()
+        transformer = self._applyExpressionFilters(transformer, 'transform', startPos=startPos)
+
+        if self.peek()==':':
+            self.advance()
+        self.getWhiteSpace()
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+        self._compiler.setTransform(transformer, isKlass)
+
+        
+    def eatErrorCatcher(self):
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        self.getDirectiveStartToken()
+        self.advance(len('errorCatcher'))
+        self.getWhiteSpace()
+        startPos = self.pos()
+        errorCatcherName = self.getIdentifier()
+        errorCatcherName = self._applyExpressionFilters(
+            errorCatcherName, 'errorcatcher', startPos=startPos)
+        self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)        
+        self._compiler.setErrorCatcher(errorCatcherName)
+
+    def eatCapture(self):
+        # @@TR:  this could be refactored to use the code in eatSimpleIndentingDirective
+        # filtered 
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLinePos = self.findEOL()
+        lineCol = self.getRowCol()
+
+        self.getDirectiveStartToken()
+        self.advance(len('capture'))        
+        startPos = self.pos()
+        self.getWhiteSpace()
+
+        expr = self.getExpression(pyTokensToBreakAt=[':'])
+        expr = self._applyExpressionFilters(expr, 'capture', startPos=startPos)
+        if self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self._compiler.startCaptureRegion(assignTo=expr, lineCol=lineCol)
+            self.getWhiteSpace(max=1)
+            self.parse(breakPoint=self.findEOL(gobble=False))
+            self._compiler.endCaptureRegion()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLinePos)
+            self.pushToOpenDirectivesStack("capture")
+            self._compiler.startCaptureRegion(assignTo=expr, lineCol=lineCol)
+        
+
+    def eatIf(self):
+        # filtered 
+        isLineClearToStartToken = self.isLineClearToStartToken()
+        endOfFirstLine = self.findEOL()
+        lineCol = self.getRowCol()
+        self.getDirectiveStartToken()
+        startPos = self.pos()
+        
+        expressionParts = self.getExpressionParts(pyTokensToBreakAt=[':'])
+        expr = ''.join(expressionParts).strip()
+        expr = self._applyExpressionFilters(expr, 'if', startPos=startPos)
+
+        isTernaryExpr = ('then' in expressionParts and 'else' in expressionParts)
+        if isTernaryExpr:
+            conditionExpr = []
+            trueExpr = []
+            falseExpr = []
+            currentExpr = conditionExpr
+            for part in expressionParts:
+                if part.strip()=='then':
+                    currentExpr = trueExpr
+                elif part.strip()=='else':
+                    currentExpr = falseExpr
+                else:
+                    currentExpr.append(part)
+                    
+            conditionExpr = ''.join(conditionExpr)
+            trueExpr = ''.join(trueExpr)
+            falseExpr = ''.join(falseExpr)
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)            
+            self._compiler.addTernaryExpr(conditionExpr, trueExpr, falseExpr, lineCol=lineCol)
+        elif self.matchColonForSingleLineShortFormDirective():
+            self.advance() # skip over :
+            self._compiler.addIf(expr, lineCol=lineCol)
+            self.getWhiteSpace(max=1)
+            self.parse(breakPoint=self.findEOL(gobble=True))            
+            self._compiler.commitStrConst()            
+            self._compiler.dedent()
+        else:
+            if self.peek()==':':
+                self.advance()
+            self.getWhiteSpace()                
+            self._eatRestOfDirectiveTag(isLineClearToStartToken, endOfFirstLine)            
+            self.pushToOpenDirectivesStack('if')
+            self._compiler.addIf(expr, lineCol=lineCol)
+
+    ## end directive handlers
+    def handleEndDef(self):
+        isNestedDef = (self.setting('allowNestedDefScopes')
+                       and [name for name in self._openDirectivesStack if name=='def'])
+        if not isNestedDef:
+            self._compiler.closeDef()
+        else:
+            # @@TR: temporary hack of useSearchList
+            self.setSetting('useSearchList', self._useSearchList_orig)                    
+            self._compiler.commitStrConst()
+            self._compiler.dedent()
+    ###
+
+    def pushToOpenDirectivesStack(self, directiveName):
+        assert directiveName in self._closeableDirectives
+        self._openDirectivesStack.append(directiveName)
+
+    def popFromOpenDirectivesStack(self, directiveName):
+        if not self._openDirectivesStack:
+            raise ParseError(self, msg="#end found, but nothing to end")
+        
+        if self._openDirectivesStack[-1] == directiveName:
+            del self._openDirectivesStack[-1]
+        else:
+            raise ParseError(self, msg="#end %s found, expected #end %s" %(
+                directiveName, self._openDirectivesStack[-1]))
+
+    def assertEmptyOpenDirectivesStack(self):
+        if self._openDirectivesStack:
+            errorMsg = (
+                "Some #directives are missing their corresponding #end ___ tag: %s" %(
+                ', '.join(self._openDirectivesStack)))
+            raise ParseError(self, msg=errorMsg)
+
+##################################################
+## Make an alias to export   
+Parser = _HighLevelParser

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Servlet.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Servlet.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Servlet.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,113 @@
+#!/usr/bin/env python
+'''
+Provides an abstract Servlet baseclass for Cheetah's Template class
+'''
+
+import sys
+import os.path
+
+isWebwareInstalled = False
+try:
+    try:
+        from ds.appserver.Servlet import Servlet as BaseServlet
+    except:
+        from WebKit.Servlet import Servlet as BaseServlet
+    isWebwareInstalled = True
+
+    if not issubclass(BaseServlet, object):
+        class NewStyleBaseServlet(BaseServlet, object):
+            pass
+        BaseServlet = NewStyleBaseServlet
+except:
+    class BaseServlet(object): 
+        _reusable = 1
+        _threadSafe = 0
+    
+        def awake(self, transaction):
+            pass
+            
+        def sleep(self, transaction):
+            pass
+
+        def shutdown(self):
+            pass
+
+##################################################
+## CLASSES
+
+class Servlet(BaseServlet):
+    
+    """This class is an abstract baseclass for Cheetah.Template.Template.
+
+    It wraps WebKit.Servlet and provides a few extra convenience methods that
+    are also found in WebKit.Page.  It doesn't do any of the HTTP method
+    resolution that is done in WebKit.HTTPServlet
+    """
+    
+    transaction = None
+    application = None
+    request = None
+    session = None
+    
+    def __init__(self, *args, **kwargs):
+        super(Servlet, self).__init__(*args, **kwargs)
+       
+        # this default will be changed by the .awake() method
+        self._CHEETAH__isControlledByWebKit = False 
+        
+    ## methods called by Webware during the request-response
+        
+    def awake(self, transaction):
+        super(Servlet, self).awake(transaction)
+        
+        # a hack to signify that the servlet is being run directly from WebKit
+        self._CHEETAH__isControlledByWebKit = True
+        
+        self.transaction = transaction        
+        #self.application = transaction.application
+        self.response = response = transaction.response
+        self.request = transaction.request
+
+        # Temporary hack to accomodate bug in
+        # WebKit.Servlet.Servlet.serverSidePath: it uses 
+        # self._request even though this attribute does not exist.
+        # This attribute WILL disappear in the future.
+        self._request = transaction.request()
+
+        
+        self.session = transaction.session
+        self.write = response().write
+        #self.writeln = response.writeln
+        
+    def respond(self, trans=None):
+        raise NotImplementedError("""\
+couldn't find the template's main method.  If you are using #extends
+without #implements, try adding '#implements respond' to your template
+definition.""")
+
+    def sleep(self, transaction):
+        super(Servlet, self).sleep(transaction)
+        self.session = None
+        self.request  = None
+        self._request  = None        
+        self.response = None
+        self.transaction = None
+
+    def shutdown(self):
+        pass
+
+    def serverSidePath(self, path=None,
+                       normpath=os.path.normpath,
+                       abspath=os.path.abspath
+                       ):
+        
+        if self._CHEETAH__isControlledByWebKit:
+            return super(Servlet, self).serverSidePath(path)
+        elif path:
+            return normpath(abspath(path.replace("\\",'/')))
+        elif hasattr(self, '_filePath') and self._filePath:
+            return normpath(abspath(self._filePath))
+        else:
+            return None
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SettingsManager.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SettingsManager.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SettingsManager.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,320 @@
+"""Provides a mixin/base class for collecting and managing application settings
+
+Meta-Data
+==========
+Author: Tavis Rudd <tavis at damnsimple.com>
+Version: $Revision: 1.30 $
+Start Date: 2001/05/30
+Last Revision Date: $Date: 2008/02/14 03:03:16 $
+"""
+
+# $Id: SettingsManager.py,v 1.30 2008/02/14 03:03:16 tavis_rudd Exp $
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.30 $"[11:-2]
+
+import sys
+import os.path
+import copy as copyModule
+from ConfigParser import ConfigParser 
+import re
+from tokenize import Intnumber, Floatnumber, Number
+from types import *
+import types
+import new
+import time
+from StringIO import StringIO # not cStringIO because of unicode support
+import imp                 # used by SettingsManager.updateSettingsFromPySrcFile()
+
+##################################################
+## CONSTANTS & GLOBALS ##
+
+try:
+    True,False
+except NameError:
+    True, False = (1==1),(1==0)
+
+numberRE = re.compile(Number)
+complexNumberRE = re.compile('[\(]*' +Number + r'[ \t]*\+[ \t]*' + Number + '[\)]*')
+
+convertableToStrTypes = (StringType, IntType, FloatType,
+                         LongType, ComplexType, NoneType,
+                         UnicodeType)
+
+##################################################
+## FUNCTIONS ##
+
+def mergeNestedDictionaries(dict1, dict2, copy=False, deepcopy=False):
+    """Recursively merge the values of dict2 into dict1.
+
+    This little function is very handy for selectively overriding settings in a
+    settings dictionary that has a nested structure.
+    """
+
+    if copy:
+        dict1 = copyModule.copy(dict1)
+    elif deepcopy:
+        dict1 = copyModule.deepcopy(dict1)
+        
+    for key,val in dict2.items():
+        if dict1.has_key(key) and type(val) == types.DictType and \
+           type(dict1[key]) == types.DictType:
+            
+            dict1[key] = mergeNestedDictionaries(dict1[key], val)
+        else:
+            dict1[key] = val
+    return dict1
+    
+def stringIsNumber(S):
+    """Return True if theString represents a Python number, False otherwise.
+    This also works for complex numbers and numbers with +/- in front."""
+
+    S = S.strip()
+    
+    if S[0] in '-+' and len(S) > 1:
+        S = S[1:].strip()
+    
+    match = complexNumberRE.match(S)
+    if not match:
+        match = numberRE.match(S)
+    if not match or (match.end() != len(S)):
+        return False
+    else:
+        return True
+        
+def convStringToNum(theString):
+    """Convert a string representation of a Python number to the Python version"""
+    
+    if not stringIsNumber(theString):
+        raise Error(theString + ' cannot be converted to a Python number')
+    return eval(theString, {}, {})
+
+
+##################################################
+## CLASSES ##
+
+class Error(Exception):
+    pass
+
+class NoDefault:
+    pass
+
+class ConfigParserCaseSensitive(ConfigParser):
+    """A case sensitive version of the standard Python ConfigParser."""
+    
+    def optionxform(self, optionstr):
+        """Don't change the case as is done in the default implemenation."""
+        return optionstr
+
+class _SettingsCollector:
+    """An abstract base class that provides the methods SettingsManager uses to
+    collect settings from config files and strings.
+
+    This class only collects settings it doesn't modify the _settings dictionary
+    of SettingsManager instances in any way.
+    """
+
+    _ConfigParserClass = ConfigParserCaseSensitive 
+
+    def __init__(self):
+        pass
+
+    def readSettingsFromModule(self, mod, ignoreUnderscored=True):
+        """Returns all settings from a Python module.
+        """
+        S = {}
+        attrs = vars(mod)
+        for k, v in attrs.items():
+            if (ignoreUnderscored and k.startswith('_')):
+                continue
+            else:
+                S[k] = v
+        return S
+        
+    def readSettingsFromPySrcStr(self, theString):
+        """Return a dictionary of the settings in a Python src string."""
+
+        globalsDict = {'True':(1==1),
+                       'False':(0==1),
+                       }
+        newSettings = {'self':self}
+        exec (theString+os.linesep) in globalsDict, newSettings        
+        del newSettings['self']
+        module = new.module('temp_settings_module')
+        module.__dict__.update(newSettings)
+        return self.readSettingsFromModule(module)
+
+    def readSettingsFromConfigFileObj(self, inFile, convert=True):
+        """Return the settings from a config file that uses the syntax accepted by
+        Python's standard ConfigParser module (like Windows .ini files).
+
+        NOTE:
+        this method maintains case unlike the ConfigParser module, unless this
+        class was initialized with the 'caseSensitive' keyword set to False.
+
+        All setting values are initially parsed as strings. However, If the
+        'convert' arg is True this method will do the following value
+        conversions:
+        
+        * all Python numeric literals will be coverted from string to number
+        
+        * The string 'None' will be converted to the Python value None
+        
+        * The string 'True' will be converted to a Python truth value
+        
+        * The string 'False' will be converted to a Python false value
+        
+        * Any string starting with 'python:' will be treated as a Python literal
+          or expression that needs to be eval'd. This approach is useful for
+          declaring lists and dictionaries.
+
+        If a config section titled 'Globals' is present the options defined
+        under it will be treated as top-level settings.        
+        """
+        
+        p = self._ConfigParserClass()
+        p.readfp(inFile)
+        sects = p.sections()
+        newSettings = {}
+
+        sects = p.sections()
+        newSettings = {}
+        
+        for s in sects:
+            newSettings[s] = {}
+            for o in p.options(s):
+                if o != '__name__':
+                    newSettings[s][o] = p.get(s,o)
+
+        ## loop through new settings -> deal with global settings, numbers,
+        ## booleans and None ++ also deal with 'importSettings' commands
+
+        for sect, subDict in newSettings.items():
+            for key, val in subDict.items():
+                if convert:
+                    if val.lower().startswith('python:'):
+                        subDict[key] = eval(val[7:],{},{})
+                    if val.lower() == 'none':
+                        subDict[key] = None
+                    if val.lower() == 'true':
+                        subDict[key] = True
+                    if val.lower() == 'false':
+                        subDict[key] = False
+                    if stringIsNumber(val):
+                        subDict[key] = convStringToNum(val)
+                        
+                ## now deal with any 'importSettings' commands
+                if key.lower() == 'importsettings':
+                    if val.find(';') < 0:
+                        importedSettings = self.readSettingsFromPySrcFile(val)
+                    else:
+                        path = val.split(';')[0]
+                        rest = ''.join(val.split(';')[1:]).strip()
+                        parentDict = self.readSettingsFromPySrcFile(path)
+                        importedSettings = eval('parentDict["' + rest + '"]')
+                        
+                    subDict.update(mergeNestedDictionaries(subDict,
+                                                           importedSettings))
+                        
+            if sect.lower() == 'globals':
+                newSettings.update(newSettings[sect])
+                del newSettings[sect]
+                
+        return newSettings
+
+
+class SettingsManager(_SettingsCollector):
+    """A mixin class that provides facilities for managing application settings.
+    
+    SettingsManager is designed to work well with nested settings dictionaries
+    of any depth.
+    """
+
+    def __init__(self):
+        """MUST BE CALLED BY SUBCLASSES"""
+        _SettingsCollector.__init__(self)
+        self._settings = {}
+        self._initializeSettings()
+
+    def _defaultSettings(self):
+        return {}
+    
+    def _initializeSettings(self):
+        """A hook that allows for complex setting initialization sequences that
+        involve references to 'self' or other settings.  For example:
+              self._settings['myCalcVal'] = self._settings['someVal'] * 15        
+        This method should be called by the class' __init__() method when needed.       
+        The dummy implementation should be reimplemented by subclasses.
+        """
+        
+        pass 
+
+    ## core post startup methods
+
+    def setting(self, name, default=NoDefault):
+        """Get a setting from self._settings, with or without a default value."""
+        
+        if default is NoDefault:
+            return self._settings[name]
+        else:
+            return self._settings.get(name, default)
+
+
+    def hasSetting(self, key):
+        """True/False"""
+        return key in self._settings
+
+    def setSetting(self, name, value):
+        """Set a setting in self._settings."""
+        self._settings[name] = value
+
+    def settings(self):
+        """Return a reference to the settings dictionary"""
+        return self._settings
+        
+    def copySettings(self):
+        """Returns a shallow copy of the settings dictionary"""
+        return copyModule.copy(self._settings)
+
+    def deepcopySettings(self):
+        """Returns a deep copy of the settings dictionary"""
+        return copyModule.deepcopy(self._settings)
+    
+    def updateSettings(self, newSettings, merge=True):
+        """Update the settings with a selective merge or a complete overwrite."""
+        
+        if merge:
+            mergeNestedDictionaries(self._settings, newSettings)
+        else:
+            self._settings.update(newSettings)
+
+
+    ## source specific update methods
+
+    def updateSettingsFromPySrcStr(self, theString, merge=True):
+        """Update the settings from a code in a Python src string."""
+        
+        newSettings = self.readSettingsFromPySrcStr(theString)
+        self.updateSettings(newSettings,
+                            merge=newSettings.get('mergeSettings',merge) )
+        
+    
+    def updateSettingsFromConfigFileObj(self, inFile, convert=True, merge=True):
+        """See the docstring for .updateSettingsFromConfigFile()
+
+        The caller of this method is responsible for closing the inFile file
+        object."""
+
+        newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
+        self.updateSettings(newSettings,
+                            merge=newSettings.get('mergeSettings',merge))
+
+    def updateSettingsFromConfigStr(self, configStr, convert=True, merge=True):
+        """See the docstring for .updateSettingsFromConfigFile()
+        """
+
+        configStr = '[globals]\n' + configStr
+        inFile = StringIO(configStr)
+        newSettings = self.readSettingsFromConfigFileObj(inFile, convert=convert)
+        self.updateSettings(newSettings,
+                            merge=newSettings.get('mergeSettings',merge))
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SourceReader.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SourceReader.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/SourceReader.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,304 @@
+#!/usr/bin/env python
+# $Id: SourceReader.py,v 1.15 2007/04/03 01:57:42 tavis_rudd Exp $
+"""SourceReader class for Cheetah's Parser and CodeGenerator
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.15 $
+Start Date: 2001/09/19
+Last Revision Date: $Date: 2007/04/03 01:57:42 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.15 $"[11:-2]
+
+import re
+import sys
+
+EOLre = re.compile(r'[ \f\t]*(?:\r\n|\r|\n)')
+EOLZre = re.compile(r'(?:\r\n|\r|\n|\Z)')
+ENCODINGsearch = re.compile("coding[=:]\s*([-\w.]+)").search
+
+class Error(Exception):
+    pass
+                                
+class SourceReader:
+    def __init__(self, src, filename=None, breakPoint=None, encoding=None):
+
+        ## @@TR 2005-01-17: the following comes from a patch Terrel Shumway
+        ## contributed to add unicode support to the reading of Cheetah source
+        ## files with dynamically compiled templates. All the existing unit
+        ## tests pass but, it needs more testing and some test cases of its
+        ## own. My instinct is to move this up into the code that passes in the
+        ## src string rather than leaving it here.  As implemented here it
+        ## forces all src strings to unicode, which IMO is not what we want.
+        #  if encoding is None:
+        #      # peek at the encoding in the first two lines
+        #      m = EOLZre.search(src)
+        #      pos = m.end()
+        #      if pos<len(src):
+        #          m = EOLZre.search(src,pos)
+        #          pos = m.end()
+        #      m = ENCODINGsearch(src,0,pos)
+        #      if m:
+        #          encoding = m.group(1)
+        #      else:
+        #          encoding  = sys.getfilesystemencoding()
+        #  self._encoding = encoding
+        #  if type(src) is not unicode:
+        #      src = src.decode(encoding)
+        ## end of Terrel's patch
+
+        self._src = src
+        self._filename = filename
+
+        self._srcLen = len(src)
+        if breakPoint == None:
+            self._breakPoint = self._srcLen
+        else:
+            self.setBreakPoint(breakPoint)
+        self._pos = 0
+        self._bookmarks = {}
+        self._posTobookmarkMap = {}
+
+        ## collect some meta-information
+        self._EOLs = []
+        pos = 0
+        while pos < len(self):
+            EOLmatch = EOLZre.search(src, pos)
+            self._EOLs.append(EOLmatch.start())
+            pos = EOLmatch.end()
+            
+        self._BOLs = []
+        for pos in self._EOLs:
+            BOLpos = self.findBOL(pos)
+            self._BOLs.append(BOLpos)
+        
+    def src(self):
+        return self._src
+
+    def filename(self):
+        return self._filename
+
+    def __len__(self):
+        return self._breakPoint
+    
+    def __getitem__(self, i):
+        self.checkPos(i)
+        return self._src[i]
+    
+    def __getslice__(self, i, j):
+        i = max(i, 0); j = max(j, 0)
+        return self._src[i:j]
+
+    def splitlines(self):
+        if not hasattr(self, '_srcLines'):                
+            self._srcLines = self._src.splitlines()
+        return self._srcLines
+
+    def lineNum(self, pos=None):
+        if pos == None:
+            pos = self._pos
+            
+        for i in range(len(self._BOLs)):
+            if pos >= self._BOLs[i] and pos <= self._EOLs[i]:
+                return i
+            
+    def getRowCol(self, pos=None):
+        if pos == None:
+            pos = self._pos
+        lineNum = self.lineNum(pos)
+        BOL, EOL = self._BOLs[lineNum], self._EOLs[lineNum]
+        return lineNum+1, pos-BOL+1
+            
+    def getRowColLine(self, pos=None):
+        if pos == None:
+            pos = self._pos
+        row, col = self.getRowCol(pos)    
+        return row, col, self.splitlines()[row-1]
+
+    def getLine(self, pos):
+        if pos == None:
+            pos = self._pos
+        lineNum = self.lineNum(pos)
+        return self.splitlines()[lineNum]
+        
+    def pos(self):
+        return self._pos
+    
+    def setPos(self, pos):
+        self.checkPos(pos)
+        self._pos = pos
+
+
+    def validPos(self, pos):
+        return pos <= self._breakPoint and pos >=0 
+                    
+    def checkPos(self, pos):
+        if not pos <= self._breakPoint:
+            raise Error("pos (" + str(pos) + ") is invalid: beyond the stream's end (" +
+                        str(self._breakPoint-1) + ")" )
+        elif not pos >=0:
+            raise Error("pos (" + str(pos) + ") is invalid: less than 0" )
+
+    def breakPoint(self):
+        return self._breakPoint
+    
+    def setBreakPoint(self, pos):
+        if pos > self._srcLen:
+            raise Error("New breakpoint (" + str(pos) +
+                        ") is invalid: beyond the end of stream's source string (" +
+                        str(self._srcLen) + ")" )
+        elif not pos >= 0:
+            raise Error("New breakpoint (" + str(pos) + ") is invalid: less than 0" )        
+        
+        self._breakPoint = pos
+
+    def setBookmark(self, name):
+        self._bookmarks[name] = self._pos
+        self._posTobookmarkMap[self._pos] = name
+
+    def hasBookmark(self, name):
+        return self._bookmarks.has_key(name)
+    
+    def gotoBookmark(self, name):
+        if not self.hasBookmark(name):
+            raise Error("Invalid bookmark (" + name + ") is invalid: does not exist")
+        pos = self._bookmarks[name]
+        if not self.validPos(pos):
+            raise Error("Invalid bookmark (" + name + ', '+
+                        str(pos) + ") is invalid: pos is out of range" )        
+        self._pos = pos
+
+    def atEnd(self):
+        return self._pos >= self._breakPoint
+
+    def atStart(self):
+        return self._pos == 0
+                          
+    def peek(self, offset=0):
+        self.checkPos(self._pos+offset)
+        pos = self._pos + offset
+        return self._src[pos]
+
+    def getc(self):
+        pos = self._pos
+        if self.validPos(pos+1):
+            self._pos += 1
+        return self._src[pos]
+
+    def ungetc(self, c=None):
+        if not self.atStart():
+            raise Error('Already at beginning of stream')
+
+        self._pos -= 1
+        if not c==None:
+            self._src[self._pos] = c
+
+    def advance(self, offset=1):
+        self.checkPos(self._pos + offset)
+        self._pos += offset
+
+    def rev(self, offset=1):
+        self.checkPos(self._pos - offset)
+        self._pos -= offset
+               
+    def read(self, offset):
+        self.checkPos(self._pos + offset)
+        start = self._pos
+        self._pos += offset
+        return self._src[start:self._pos]
+
+    def readTo(self, to, start=None):
+        self.checkPos(to)
+        if start == None:
+            start = self._pos
+        self._pos = to
+        return self._src[start:to]
+
+        
+    def readToEOL(self, start=None, gobble=True):
+        EOLmatch = EOLZre.search(self.src(), self.pos())
+        if gobble:
+            pos = EOLmatch.end()
+        else:
+            pos = EOLmatch.start()
+        return self.readTo(to=pos, start=start)
+    
+
+    def find(self, it, pos=None):
+        if pos == None:
+            pos = self._pos
+        return self._src.find(it, pos )
+
+    def startswith(self, it, pos=None):
+        if self.find(it, pos) == self.pos():
+            return True
+        else:
+            return False
+                    
+    def rfind(self, it, pos):
+        if pos == None:
+            pos = self._pos
+        return self._src.rfind(it, pos)
+        
+    def findBOL(self, pos=None):
+        if pos == None:
+            pos = self._pos
+        src = self.src()
+        return max(src.rfind('\n',0,pos)+1, src.rfind('\r',0,pos)+1, 0)
+        
+    def findEOL(self, pos=None, gobble=False):
+        if pos == None:
+            pos = self._pos
+
+        match = EOLZre.search(self.src(), pos)
+        if gobble:
+            return match.end()
+        else:
+            return match.start()
+    
+    def isLineClearToPos(self, pos=None):
+        if pos == None:
+            pos = self.pos()
+        self.checkPos(pos)            
+        src = self.src()
+        BOL = self.findBOL()
+        return BOL == pos or src[BOL:pos].isspace()
+
+    def matches(self, strOrRE):
+        if isinstance(strOrRE, (str, unicode)):
+            return self.startswith(strOrRE, pos=self.pos())
+        else: # assume an re object
+            return strOrRE.match(self.src(), self.pos())
+
+    def matchWhiteSpace(self, WSchars=' \f\t'):
+        return (not self.atEnd()) and  self.peek() in WSchars
+
+    def getWhiteSpace(self, max=None, WSchars=' \f\t'):
+        if not self.matchWhiteSpace(WSchars):
+            return ''
+        start = self.pos()
+        breakPoint = self.breakPoint()
+        if max is not None:
+            breakPoint = min(breakPoint, self.pos()+max)
+        while self.pos() < breakPoint:
+            self.advance()
+            if not self.matchWhiteSpace(WSchars):
+                break
+        return self.src()[start:self.pos()]
+
+    def matchNonWhiteSpace(self, WSchars=' \f\t\n\r'):
+        return self.atEnd() or not self.peek() in WSchars
+
+    def getNonWhiteSpace(self, WSchars=' \f\t\n\r'):
+        if not self.matchNonWhiteSpace(WSchars):
+            return ''
+        start = self.pos()
+        while self.pos() < self.breakPoint():
+            self.advance()
+            if not self.matchNonWhiteSpace(WSchars):
+                break
+        return self.src()[start:self.pos()]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Template.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Template.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Template.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1899 @@
+#!/usr/bin/env python
+'''
+Provides the core API for Cheetah.
+
+See the docstring in the Template class and the Users' Guide for more information
+'''
+
+################################################################################
+## DEPENDENCIES
+import sys                        # used in the error handling code
+import re                         # used to define the internal delims regex
+import new                        # used to bind methods and create dummy modules
+import string
+import os.path
+import time                       # used in the cache refresh code
+from random import randrange
+import imp
+import inspect
+import StringIO
+import traceback
+import pprint
+import cgi                # Used by .webInput() if the template is a CGI script.
+import types 
+from types import StringType, ClassType
+try:
+    from types import StringTypes
+except ImportError:
+    StringTypes = (types.StringType,types.UnicodeType)
+try:
+    from types import BooleanType
+    boolTypeAvailable = True
+except ImportError:
+    boolTypeAvailable = False
+    
+try:
+    from threading import Lock
+except ImportError:
+    class Lock:
+        def acquire(self):
+            pass
+        def release(self): 
+            pass
+
+try:
+    x = set()
+except NameError:
+    # Python 2.3 compatibility
+    from sets import Set as set
+
+from Cheetah.Version import convertVersionStringToTuple, MinCompatibleVersionTuple
+from Cheetah.Version import MinCompatibleVersion
+# Base classes for Template
+from Cheetah.Servlet import Servlet                 
+# More intra-package imports ...
+from Cheetah.Parser import ParseError, SourceReader
+from Cheetah.Compiler import Compiler, DEFAULT_COMPILER_SETTINGS
+from Cheetah import ErrorCatchers              # for placeholder tags
+from Cheetah import Filters                    # the output filters
+from Cheetah.convertTmplPathToModuleName import convertTmplPathToModuleName
+from Cheetah.Utils import VerifyType             # Used in Template.__init__
+from Cheetah.Utils.Misc import checkKeywords     # Used in Template.__init__
+from Cheetah.Utils.Indenter import Indenter      # Used in Template.__init__ and for
+                                                 # placeholders
+from Cheetah.NameMapper import NotFound, valueFromSearchList
+from Cheetah.CacheStore import MemoryCacheStore, MemcachedCacheStore
+from Cheetah.CacheRegion import CacheRegion
+from Cheetah.Utils.WebInputMixin import _Converter, _lookup, NonNumericInputError
+
+from Cheetah.Unspecified import Unspecified
+
+# Decide whether to use the file modification time in file's cache key 
+__checkFileMtime = True
+def checkFileMtime(value):
+    globals()['__checkFileMtime'] = value
+
+class Error(Exception):
+    pass
+class PreprocessError(Error):
+    pass
+
+def hashList(l):
+    hashedList = []
+    for v in l:
+        if isinstance(v, dict):
+            v = hashDict(v)
+        elif isinstance(v, list):
+            v = hashList(v)
+        hashedList.append(v)
+    return hash(tuple(hashedList))
+
+def hashDict(d):
+    items = d.items()
+    items.sort()
+    hashedList = []
+    for k, v in items:
+        if isinstance(v, dict):
+            v = hashDict(v)
+        elif isinstance(v, list):
+            v = hashList(v)
+        hashedList.append((k,v))
+    return hash(tuple(hashedList))
+
+################################################################################
+## MODULE GLOBALS AND CONSTANTS
+
+def _genUniqueModuleName(baseModuleName):
+    """The calling code is responsible for concurrency locking.
+    """
+    if baseModuleName not in sys.modules:
+        finalName = baseModuleName
+    else:
+        finalName = ('cheetah_%s_%s_%s'%(baseModuleName,
+                                         str(time.time()).replace('.','_'),
+                                         str(randrange(10000, 99999))))
+    return finalName
+
+# Cache of a cgi.FieldStorage() instance, maintained by .webInput().
+# This is only relavent to templates used as CGI scripts.
+_formUsedByWebInput = None
+
+# used in Template.compile()
+def valOrDefault(val, default):                
+    if val is not Unspecified:
+        return val
+    return default
+
+def updateLinecache(filename, src):
+    import linecache
+    size = len(src)
+    mtime = time.time()
+    lines = src.splitlines()
+    fullname = filename
+    linecache.cache[filename] = size, mtime, lines, fullname
+
+class CompileCacheItem(object):
+    pass
+
+class TemplatePreprocessor(object):
+    '''
+    This is used with the preprocessors argument to Template.compile().
+
+    See the docstring for Template.compile
+
+    ** Preprocessors are an advanced topic **
+    '''
+    
+    def __init__(self, settings):
+        self._settings = settings
+
+    def preprocess(self, source, file):
+        """Create an intermediate template and return the source code
+        it outputs                
+        """
+        settings = self._settings
+        if not source: # @@TR: this needs improving
+            if isinstance(file, (str, unicode)): # it's a filename.
+                f = open(file)
+                source = f.read()
+                f.close()
+            elif hasattr(file, 'read'):
+                source = file.read()
+            file = None        
+
+        templateAPIClass = settings.templateAPIClass
+        possibleKwArgs = [
+            arg for arg in
+            inspect.getargs(templateAPIClass.compile.im_func.func_code)[0]
+            if arg not in ('klass', 'source', 'file',)]
+
+        compileKwArgs = {}
+        for arg in possibleKwArgs:
+            if hasattr(settings, arg):
+                compileKwArgs[arg] = getattr(settings, arg)
+
+        tmplClass = templateAPIClass.compile(source=source, file=file, **compileKwArgs)
+        tmplInstance = tmplClass(**settings.templateInitArgs)
+        outputSource = settings.outputTransformer(tmplInstance)
+        outputFile = None
+        return outputSource, outputFile
+        
+class Template(Servlet):
+    '''
+    This class provides a) methods used by templates at runtime and b)
+    methods for compiling Cheetah source code into template classes.
+
+    This documentation assumes you already know Python and the basics of object
+    oriented programming.  If you don't know Python, see the sections of the
+    Cheetah Users' Guide for non-programmers.  It also assumes you have read
+    about Cheetah's syntax in the Users' Guide.
+
+    The following explains how to use Cheetah from within Python programs or via
+    the interpreter. If you statically compile your templates on the command
+    line using the 'cheetah' script, this is not relevant to you. Statically
+    compiled Cheetah template modules/classes (e.g. myTemplate.py:
+    MyTemplateClasss) are just like any other Python module or class. Also note,
+    most Python web frameworks (Webware, Aquarium, mod_python, Turbogears,
+    CherryPy, Quixote, etc.) provide plugins that handle Cheetah compilation for
+    you.
+
+    There are several possible usage patterns:          
+       1) tclass = Template.compile(src)
+          t1 = tclass() # or tclass(namespaces=[namespace,...])
+          t2 = tclass() # or tclass(namespaces=[namespace2,...])
+          outputStr = str(t1) # or outputStr = t1.aMethodYouDefined()
+
+          Template.compile provides a rich and very flexible API via its
+          optional arguments so there are many possible variations of this
+          pattern.  One example is:
+            tclass = Template.compile('hello $name from $caller', baseclass=dict)
+            print tclass(name='world', caller='me')
+          See the Template.compile() docstring for more details.  
+
+       2) tmplInstance = Template(src)
+             # or Template(src, namespaces=[namespace,...])
+          outputStr = str(tmplInstance) # or outputStr = tmplInstance.aMethodYouDefined(...args...)
+
+    Notes on the usage patterns:
+    
+       usage pattern 1)       
+          This is the most flexible, but it is slightly more verbose unless you
+          write a wrapper function to hide the plumbing.  Under the hood, all
+          other usage patterns are based on this approach.  Templates compiled
+          this way can #extend (subclass) any Python baseclass: old-style or
+          new-style (based on object or a builtin type).
+
+       usage pattern 2)
+          This was Cheetah's original usage pattern.  It returns an instance,
+          but you can still access the generated class via
+          tmplInstance.__class__.  If you want to use several different
+          namespace 'searchLists' with a single template source definition,
+          you're better off with Template.compile (1).
+
+          Limitations (use pattern 1 instead):
+           - Templates compiled this way can only #extend subclasses of the
+             new-style 'object' baseclass.  Cheetah.Template is a subclass of
+             'object'.  You also can not #extend dict, list, or other builtin
+             types.  
+           - If your template baseclass' __init__ constructor expects args there
+             is currently no way to pass them in.
+
+    If you need to subclass a dynamically compiled Cheetah class, do something like this:
+        from Cheetah.Template import Template
+        T1 = Template.compile('$meth1 #def meth1: this is meth1 in T1')
+        T2 = Template.compile('#implements meth1\nthis is meth1 redefined in T2', baseclass=T1)
+        print T1, T1()
+        print T2, T2()
+
+
+    Note about class and instance attribute names:
+      Attributes used by Cheetah have a special prefix to avoid confusion with
+      the attributes of the templates themselves or those of template
+      baseclasses.
+      
+      Class attributes which are used in class methods look like this:
+          klass._CHEETAH_useCompilationCache (_CHEETAH_xxx)
+
+      Instance attributes look like this:
+          klass._CHEETAH__globalSetVars (_CHEETAH__xxx with 2 underscores)
+    '''
+
+    # this is used by ._addCheetahPlumbingCodeToClass()
+    _CHEETAH_requiredCheetahMethods = (
+         '_initCheetahInstance',
+         'searchList',
+         'errorCatcher',
+         'getVar',
+         'varExists',
+         'getFileContents',
+         'i18n',
+         'runAsMainProgram',
+         'respond',
+         'shutdown',
+         'webInput',
+         'serverSidePath',
+         'generatedClassCode',
+         'generatedModuleCode',
+
+         '_getCacheStore',
+         '_getCacheStoreIdPrefix',
+         '_createCacheRegion',
+         'getCacheRegion',
+         'getCacheRegions',
+         'refreshCache',
+         
+         '_handleCheetahInclude',
+         '_getTemplateAPIClassForIncludeDirectiveCompilation',
+         )
+    _CHEETAH_requiredCheetahClassMethods = ('subclass',) 
+    _CHEETAH_requiredCheetahClassAttributes = ('cacheRegionClass','cacheStore',
+                                               'cacheStoreIdPrefix','cacheStoreClass')
+
+    ## the following are used by .compile(). Most are documented in its docstring.
+    _CHEETAH_cacheModuleFilesForTracebacks = False
+    _CHEETAH_cacheDirForModuleFiles = None # change to a dirname
+
+    _CHEETAH_compileCache = dict() # cache store for compiled code and classes
+    # To do something other than simple in-memory caching you can create an
+    # alternative cache store. It just needs to support the basics of Python's
+    # mapping/dict protocol. E.g.:
+    #   class AdvCachingTemplate(Template):
+    #       _CHEETAH_compileCache = MemoryOrFileCache()
+    _CHEETAH_compileLock = Lock() # used to prevent race conditions
+    _CHEETAH_defaultMainMethodName = None
+    _CHEETAH_compilerSettings = None
+    _CHEETAH_compilerClass = Compiler
+    _CHEETAH_cacheCompilationResults = True
+    _CHEETAH_useCompilationCache = True
+    _CHEETAH_keepRefToGeneratedCode = True
+    _CHEETAH_defaultBaseclassForTemplates = None
+    _CHEETAH_defaultClassNameForTemplates = None
+    # defaults to DEFAULT_COMPILER_SETTINGS['mainMethodName']:
+    _CHEETAH_defaultMainMethodNameForTemplates = None 
+    _CHEETAH_defaultModuleNameForTemplates = 'DynamicallyCompiledCheetahTemplate'
+    _CHEETAH_defaultModuleGlobalsForTemplates = None
+    _CHEETAH_preprocessors = None
+    _CHEETAH_defaultPreprocessorClass = TemplatePreprocessor    
+    
+    ## The following attributes are used by instance methods:
+    _CHEETAH_generatedModuleCode = None
+    NonNumericInputError = NonNumericInputError
+    _CHEETAH_cacheRegionClass = CacheRegion
+    _CHEETAH_cacheStoreClass = MemoryCacheStore
+    #_CHEETAH_cacheStoreClass = MemcachedCacheStore
+    _CHEETAH_cacheStore = None  
+    _CHEETAH_cacheStoreIdPrefix = None  
+
+    def _getCompilerClass(klass, source=None, file=None):
+        return klass._CHEETAH_compilerClass
+    _getCompilerClass = classmethod(_getCompilerClass)
+
+    def _getCompilerSettings(klass, source=None, file=None):
+        return klass._CHEETAH_compilerSettings
+    _getCompilerSettings = classmethod(_getCompilerSettings)
+    
+    def compile(klass, source=None, file=None,
+                returnAClass=True,
+                
+                compilerSettings=Unspecified,
+                compilerClass=Unspecified,
+                moduleName=None,
+                className=Unspecified,
+                mainMethodName=Unspecified,
+                baseclass=Unspecified,
+                moduleGlobals=Unspecified,
+                cacheCompilationResults=Unspecified,
+                useCache=Unspecified,
+                preprocessors=Unspecified,
+                cacheModuleFilesForTracebacks=Unspecified,
+                cacheDirForModuleFiles=Unspecified,
+                commandlineopts=None,
+                keepRefToGeneratedCode=Unspecified,                
+                ):
+        
+        """
+        The core API for compiling Cheetah source code into template classes.
+
+        This class method compiles Cheetah source code and returns a python
+        class.  You then create template instances using that class.  All
+        Cheetah's other compilation API's use this method under the hood.
+
+        Internally, this method a) parses the Cheetah source code and generates
+        Python code defining a module with a single class in it, b) dynamically
+        creates a module object with a unique name, c) execs the generated code
+        in that module's namespace then inserts the module into sys.modules, and
+        d) returns a reference to the generated class.  If you want to get the
+        generated python source code instead, pass the argument
+        returnAClass=False.
+
+        It caches generated code and classes.  See the descriptions of the
+        arguments'cacheCompilationResults' and 'useCache' for details. This
+        doesn't mean that templates will automatically recompile themselves when
+        the source file changes. Rather, if you call Template.compile(src) or
+        Template.compile(file=path) repeatedly it will attempt to return a
+        cached class definition instead of recompiling.
+
+        Hooks are provided template source preprocessing.  See the notes on the
+        'preprocessors' arg.
+
+        If you are an advanced user and need to customize the way Cheetah parses
+        source code or outputs Python code, you should check out the
+        compilerSettings argument.
+
+        Arguments:
+          You must provide either a 'source' or 'file' arg, but not both:
+            - source (string or None)
+            - file (string path, file-like object, or None)
+
+          The rest of the arguments are strictly optional. All but the first
+          have defaults in attributes of the Template class which can be
+          overridden in subclasses of this class.  Working with most of these is
+          an advanced topic.
+          
+            - returnAClass=True            
+              If false, return the generated module code rather than a class.
+
+            - compilerSettings (a dict)
+              Default: Template._CHEETAH_compilerSettings=None
+            
+              a dictionary of settings to override those defined in
+              DEFAULT_COMPILER_SETTINGS. These can also be overridden in your
+              template source code with the #compiler or #compiler-settings
+              directives.
+                  
+            - compilerClass (a class)
+              Default: Template._CHEETAH_compilerClass=Cheetah.Compiler.Compiler
+            
+              a subclass of Cheetah.Compiler.Compiler. Mucking with this is a
+              very advanced topic.
+                  
+            - moduleName (a string)
+              Default:
+                  Template._CHEETAH_defaultModuleNameForTemplates
+                  ='DynamicallyCompiledCheetahTemplate'
+            
+              What to name the generated Python module.  If the provided value is
+              None and a file arg was given, the moduleName is created from the
+              file path.  In all cases if the moduleName provided is already in
+              sys.modules it is passed through a filter that generates a unique
+              variant of the name.
+
+
+            - className (a string)
+              Default: Template._CHEETAH_defaultClassNameForTemplates=None
+              
+              What to name the generated Python class.  If the provided value is
+              None, the moduleName is use as the class name.
+
+            - mainMethodName (a string)
+              Default:
+                  Template._CHEETAH_defaultMainMethodNameForTemplates
+                  =None (and thus DEFAULT_COMPILER_SETTINGS['mainMethodName']) 
+            
+              What to name the main output generating method in the compiled
+              template class.  
+
+            - baseclass (a string or a class)
+              Default: Template._CHEETAH_defaultBaseclassForTemplates=None
+
+              Specifies the baseclass for the template without manually
+              including an #extends directive in the source. The #extends
+              directive trumps this arg.
+
+              If the provided value is a string you must make sure that a class
+              reference by that name is available to your template, either by
+              using an #import directive or by providing it in the arg
+              'moduleGlobals'.  
+
+              If the provided value is a class, Cheetah will handle all the
+              details for you.
+
+            - moduleGlobals (a dict)
+              Default: Template._CHEETAH_defaultModuleGlobalsForTemplates=None
+
+              A dict of vars that will be added to the global namespace of the
+              module the generated code is executed in, prior to the execution
+              of that code.  This should be Python values, not code strings!
+              
+            - cacheCompilationResults (True/False)
+              Default: Template._CHEETAH_cacheCompilationResults=True
+
+              Tells Cheetah to cache the generated code and classes so that they
+              can be reused if Template.compile() is called multiple times with
+              the same source and options.
+                           
+            - useCache (True/False)
+              Default: Template._CHEETAH_useCompilationCache=True
+
+              Should the compilation cache be used?  If True and a previous
+              compilation created a cached template class with the same source
+              code, compiler settings and other options, the cached template
+              class will be returned.
+
+            - cacheModuleFilesForTracebacks (True/False)
+              Default: Template._CHEETAH_cacheModuleFilesForTracebacks=False
+
+              In earlier versions of Cheetah tracebacks from exceptions that
+              were raised inside dynamically compiled Cheetah templates were
+              opaque because Python didn't have access to a python source file
+              to use in the traceback:
+        
+                File "xxxx.py", line 192, in getTextiledContent
+                  content = str(template(searchList=searchList))
+                File "cheetah_yyyy.py", line 202, in __str__
+                File "cheetah_yyyy.py", line 187, in respond
+                File "cheetah_yyyy.py", line 139, in writeBody
+               ZeroDivisionError: integer division or modulo by zero
+        
+              It is now possible to keep those files in a cache dir and allow
+              Python to include the actual source lines in tracebacks and makes
+              them much easier to understand:
+        
+               File "xxxx.py", line 192, in getTextiledContent
+                 content = str(template(searchList=searchList))
+               File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 202, in __str__
+                 def __str__(self): return self.respond()
+               File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 187, in respond
+                 self.writeBody(trans=trans)
+               File "/tmp/CheetahCacheDir/cheetah_yyyy.py", line 139, in writeBody
+                 __v = 0/0 # $(0/0)
+              ZeroDivisionError: integer division or modulo by zero
+            
+            - cacheDirForModuleFiles (a string representing a dir path)
+              Default: Template._CHEETAH_cacheDirForModuleFiles=None
+
+              See notes on cacheModuleFilesForTracebacks.
+
+            - preprocessors
+              Default: Template._CHEETAH_preprocessors=None
+
+              ** THIS IS A VERY ADVANCED TOPIC **
+              
+              These are used to transform the source code prior to compilation.
+              They provide a way to use Cheetah as a code generator for Cheetah
+              code. In other words, you use one Cheetah template to output the
+              source code for another Cheetah template.
+              
+              The major expected use cases are:
+                  
+                a) 'compile-time caching' aka 'partial template binding',
+                   wherein an intermediate Cheetah template is used to output
+                   the source for the final Cheetah template. The intermediate
+                   template is a mix of a modified Cheetah syntax (the
+                   'preprocess syntax') and standard Cheetah syntax.  The
+                   preprocessor syntax is executed at compile time and outputs
+                   Cheetah code which is then compiled in turn. This approach
+                   allows one to completely soft-code all the elements in the
+                   template which are subject to change yet have it compile to
+                   extremely efficient Python code with everything but the
+                   elements that must be variable at runtime (per browser
+                   request, etc.) compiled as static strings.  Examples of this
+                   usage pattern will be added to the Cheetah Users' Guide.
+
+                   The'preprocess syntax' is just Cheetah's standard one with
+                   alternatives for the $ and # tokens:
+                    
+                    e.g. '@' and '%' for code like this
+                     @aPreprocessVar $aRuntimeVar
+                     %if aCompileTimeCondition then yyy else zzz
+                     %% preprocessor comment
+                     
+                     #if aRunTimeCondition then aaa else bbb
+                     ## normal comment
+                     $aRuntimeVar
+                                     
+                b) adding #import and #extends directives dynamically based on
+                   the source
+                
+              If preprocessors are provided, Cheetah pipes the source code
+              through each one in the order provided.  Each preprocessor should
+              accept the args (source, file) and should return a tuple (source,
+              file).
+
+              The argument value should be a list, but a single non-list value
+              is acceptable and will automatically be converted into a list.
+              Each item in the list will be passed through
+              Template._normalizePreprocessor().  The items should either match
+              one of the following forms:
+              
+                - an object with a .preprocess(source, file) method
+                - a callable with the following signature:
+                    source, file = f(source, file)
+                
+                or one of the forms below:
+                
+                - a single string denoting the 2 'tokens' for the preprocess
+                  syntax.  The tokens should be in the order (placeholderToken,
+                  directiveToken) and should separated with a space:
+                     e.g. '@ %'
+                     klass = Template.compile(src, preprocessors='@ %')
+                     # or 
+                     klass = Template.compile(src, preprocessors=['@ %'])
+                     
+                - a dict with the following keys or an object with the
+                  following attributes (all are optional, but nothing will
+                  happen if you don't provide at least one):
+                   - tokens: same as the single string described above. You can
+                     also provide a tuple of 2 strings.
+                   - searchList: the searchList used for preprocess $placeholders
+                   - compilerSettings: used in the compilation of the intermediate
+                     template                
+                   - templateAPIClass: an optional subclass of `Template`
+                   - outputTransformer: a simple hook for passing in a callable
+                     which can do further transformations of the preprocessor
+                     output, or do something else like debug logging. The
+                     default is str().
+                   + any keyword arguments to Template.compile which you want to
+                     provide for the compilation of the intermediate template.
+                     
+                   klass = Template.compile(src,
+                          preprocessors=[ dict(tokens='@ %', searchList=[...]) ] )
+            
+        """
+        ##################################################           
+        ## normalize and validate args 
+        try:
+            vt = VerifyType.VerifyType
+            vtc = VerifyType.VerifyTypeClass
+            N = types.NoneType; S = types.StringType; U = types.UnicodeType
+            D = types.DictType; F = types.FileType
+            C = types.ClassType;  M = types.ModuleType
+            I = types.IntType
+
+            if boolTypeAvailable:         
+                B = types.BooleanType
+            
+            vt(source, 'source', [N,S,U], 'string or None')
+            vt(file, 'file',[N,S,U,F], 'string, file-like object, or None')
+
+            baseclass = valOrDefault(baseclass, klass._CHEETAH_defaultBaseclassForTemplates)
+            if isinstance(baseclass, Template):
+                baseclass = baseclass.__class__
+            vt(baseclass, 'baseclass', [N,S,C,type], 'string, class or None')
+
+            cacheCompilationResults = valOrDefault(
+                cacheCompilationResults, klass._CHEETAH_cacheCompilationResults)
+            if boolTypeAvailable:         
+                vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
+
+            useCache = valOrDefault(useCache, klass._CHEETAH_useCompilationCache)
+            if boolTypeAvailable:         
+                vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
+
+            compilerSettings = valOrDefault(
+                compilerSettings, klass._getCompilerSettings(source, file) or {})
+            vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
+
+            compilerClass = valOrDefault(compilerClass, klass._getCompilerClass(source, file))
+            preprocessors = valOrDefault(preprocessors, klass._CHEETAH_preprocessors)
+
+            keepRefToGeneratedCode = valOrDefault(
+                keepRefToGeneratedCode, klass._CHEETAH_keepRefToGeneratedCode)
+            if boolTypeAvailable:         
+                vt(cacheCompilationResults, 'cacheCompilationResults', [I,B], 'boolean')
+        
+            vt(moduleName, 'moduleName', [N,S], 'string or None')
+            __orig_file__ = None
+            if not moduleName:
+                if file and type(file) in StringTypes:
+                    moduleName = convertTmplPathToModuleName(file)
+                    __orig_file__ = file
+                else:
+                    moduleName = klass._CHEETAH_defaultModuleNameForTemplates
+        
+            className = valOrDefault(
+                className, klass._CHEETAH_defaultClassNameForTemplates)
+            vt(className, 'className', [N,S], 'string or None')
+            className = className or moduleName
+
+            mainMethodName = valOrDefault(
+                mainMethodName, klass._CHEETAH_defaultMainMethodNameForTemplates)
+            vt(mainMethodName, 'mainMethodName', [N,S], 'string or None')
+
+            moduleGlobals = valOrDefault(
+                moduleGlobals, klass._CHEETAH_defaultModuleGlobalsForTemplates)
+
+            cacheModuleFilesForTracebacks = valOrDefault(
+                cacheModuleFilesForTracebacks, klass._CHEETAH_cacheModuleFilesForTracebacks)
+            if boolTypeAvailable:
+                vt(cacheModuleFilesForTracebacks, 'cacheModuleFilesForTracebacks', [I,B], 'boolean')
+            
+            cacheDirForModuleFiles = valOrDefault(
+                cacheDirForModuleFiles, klass._CHEETAH_cacheDirForModuleFiles)
+            vt(cacheDirForModuleFiles, 'cacheDirForModuleFiles', [N,S], 'string or None')
+
+        except TypeError, reason:
+            raise TypeError(reason)
+
+        ##################################################           
+        ## handle any preprocessors
+        if preprocessors:
+            origSrc = source
+            source, file = klass._preprocessSource(source, file, preprocessors)
+
+        ##################################################                       
+        ## compilation, using cache if requested/possible
+        baseclassValue = None
+        baseclassName = None
+        if baseclass:
+            if type(baseclass) in StringTypes:
+                baseclassName = baseclass
+            elif type(baseclass) in (ClassType, type):
+                # @@TR: should soft-code this
+                baseclassName = 'CHEETAH_dynamicallyAssignedBaseClass_'+baseclass.__name__
+                baseclassValue = baseclass
+
+
+        cacheHash = None
+        cacheItem = None
+        if source or isinstance(file, basestring):
+            compilerSettingsHash = None
+            if compilerSettings:
+                compilerSettingsHash = hashDict(compilerSettings)
+
+            moduleGlobalsHash = None
+            if moduleGlobals:
+                moduleGlobalsHash = hashDict(moduleGlobals)
+
+            fileHash = None
+            if file:
+                fileHash = str(hash(file))
+                if globals()['__checkFileMtime']:
+                    fileHash += str(os.path.getmtime(file))
+                
+            try:
+                # @@TR: find some way to create a cacheHash that is consistent
+                # between process restarts.  It would allow for caching the
+                # compiled module on disk and thereby reduce the startup time
+                # for applications that use a lot of dynamically compiled
+                # templates.                
+                cacheHash = ''.join([str(v) for v in
+                                     [hash(source),
+                                      fileHash,
+                                      className,
+                                      moduleName,
+                                      mainMethodName,
+                                      hash(compilerClass),
+                                      hash(baseclass),
+                                      compilerSettingsHash,
+                                      moduleGlobalsHash,
+                                      hash(cacheDirForModuleFiles),
+                                      ]])
+            except:
+                #@@TR: should add some logging to this
+                pass
+        outputEncoding = 'ascii'
+        if useCache and cacheHash and cacheHash in klass._CHEETAH_compileCache:
+            cacheItem = klass._CHEETAH_compileCache[cacheHash]
+            generatedModuleCode = cacheItem.code
+        else:
+            compiler = compilerClass(source, file,
+                                     moduleName=moduleName,
+                                     mainClassName=className,
+                                     baseclassName=baseclassName,
+                                     mainMethodName=mainMethodName,
+                                     settings=(compilerSettings or {}))
+            if commandlineopts:
+                compiler.setShBang(commandlineopts.shbang)
+            compiler.compile()
+            generatedModuleCode = compiler.getModuleCode()
+            outputEncoding = compiler.getModuleEncoding()
+
+        if not returnAClass:
+            # This is a bit of a hackish solution to make sure we're setting the proper 
+            # encoding on generated code that is destined to be written to a file
+            if not outputEncoding == 'ascii':
+                generatedModuleCode = generatedModuleCode.split('\n')
+                generatedModuleCode.insert(1, '# -*- coding: %s -*-' % outputEncoding)
+                generatedModuleCode = '\n'.join(generatedModuleCode)
+            return generatedModuleCode.encode(outputEncoding)
+        else:
+            if cacheItem:
+                cacheItem.lastCheckoutTime = time.time()
+                return cacheItem.klass
+
+            try:
+                klass._CHEETAH_compileLock.acquire()
+                uniqueModuleName = _genUniqueModuleName(moduleName)
+                __file__ = uniqueModuleName+'.py' # relative file path with no dir part
+
+                if cacheModuleFilesForTracebacks:
+                    if not os.path.exists(cacheDirForModuleFiles):
+                        raise Exception('%s does not exist'%cacheDirForModuleFiles)
+
+                    __file__ = os.path.join(cacheDirForModuleFiles, __file__)
+                    # @@TR: might want to assert that it doesn't already exist
+                    open(__file__, 'w').write(generatedModuleCode)
+                    # @@TR: should probably restrict the perms, etc.
+
+                mod = new.module(str(uniqueModuleName))
+                if moduleGlobals:
+                    for k, v in moduleGlobals.items():
+                        setattr(mod, k, v)
+                mod.__file__ = __file__
+                if __orig_file__ and os.path.exists(__orig_file__):
+                    # this is used in the WebKit filemonitoring code
+                    mod.__orig_file__ = __orig_file__
+
+                if baseclass and baseclassValue:
+                    setattr(mod, baseclassName, baseclassValue)
+                ##
+                try:
+                    co = compile(generatedModuleCode.encode(outputEncoding), __file__, 'exec')
+                    exec co in mod.__dict__
+                except SyntaxError, e:
+                    try:
+                        parseError = genParserErrorFromPythonException(
+                            source, file, generatedModuleCode, exception=e)
+                    except:
+                        updateLinecache(__file__, generatedModuleCode)
+                        e.generatedModuleCode = generatedModuleCode
+                        raise e
+                    else:
+                        raise parseError
+                except Exception, e:
+                    updateLinecache(__file__, generatedModuleCode)
+                    e.generatedModuleCode = generatedModuleCode
+                    raise
+                ##
+                sys.modules[uniqueModuleName] = mod
+            finally:
+                klass._CHEETAH_compileLock.release()
+
+            templateClass = getattr(mod, className)
+
+            if (cacheCompilationResults
+                and cacheHash
+                and cacheHash not in klass._CHEETAH_compileCache):
+                
+                cacheItem = CompileCacheItem()
+                cacheItem.cacheTime = cacheItem.lastCheckoutTime = time.time()
+                cacheItem.code = generatedModuleCode
+                cacheItem.klass = templateClass
+                templateClass._CHEETAH_isInCompilationCache = True
+                klass._CHEETAH_compileCache[cacheHash] = cacheItem
+            else:
+                templateClass._CHEETAH_isInCompilationCache = False
+
+            if keepRefToGeneratedCode or cacheCompilationResults:
+                templateClass._CHEETAH_generatedModuleCode = generatedModuleCode                
+     
+            return templateClass
+    compile = classmethod(compile)
+
+    def subclass(klass, *args, **kws):
+        """Takes the same args as the .compile() classmethod and returns a
+        template that is a subclass of the template this method is called from.
+
+          T1 = Template.compile(' foo - $meth1 - bar\n#def meth1: this is T1.meth1')
+          T2 = T1.subclass('#implements meth1\n this is T2.meth1')
+        """
+        kws['baseclass'] = klass
+        if isinstance(klass, Template):
+            templateAPIClass = klass
+        else:
+            templateAPIClass = Template
+        return templateAPIClass.compile(*args, **kws)
+    subclass = classmethod(subclass)
+
+    def _preprocessSource(klass, source, file, preprocessors):
+        """Iterates through the .compile() classmethod's preprocessors argument
+        and pipes the source code through each each preprocessor.
+
+        It returns the tuple (source, file) which is then used by
+        Template.compile to finish the compilation.
+        """
+        if not isinstance(preprocessors, (list, tuple)):
+            preprocessors = [preprocessors]
+        for preprocessor in preprocessors:
+            preprocessor = klass._normalizePreprocessorArg(preprocessor)
+            source, file = preprocessor.preprocess(source, file)
+        return source, file
+    _preprocessSource = classmethod(_preprocessSource)
+
+    def _normalizePreprocessorArg(klass, arg):
+        """Used to convert the items in the .compile() classmethod's
+        preprocessors argument into real source preprocessors.  This permits the
+        use of several shortcut forms for defining preprocessors.
+        """
+        
+        if hasattr(arg, 'preprocess'):
+            return arg
+        elif callable(arg):
+            class WrapperPreprocessor:
+                def preprocess(self, source, file):
+                    return arg(source, file)
+            return WrapperPreprocessor()
+        else:
+            class Settings(object):
+                placeholderToken = None
+                directiveToken = None
+            settings = Settings()
+            if isinstance(arg, str) or isinstance(arg, (list, tuple)):
+                settings.tokens = arg
+            elif isinstance(arg, dict):
+                for k, v in arg.items():
+                    setattr(settings, k, v)   
+            else:
+                settings = arg
+
+            settings = klass._normalizePreprocessorSettings(settings)
+            return klass._CHEETAH_defaultPreprocessorClass(settings)
+
+    _normalizePreprocessorArg = classmethod(_normalizePreprocessorArg)
+        
+    def _normalizePreprocessorSettings(klass, settings):
+        settings.keepRefToGeneratedCode = True
+
+        def normalizeSearchList(searchList):
+            if not isinstance(searchList, (list, tuple)):
+                searchList = [searchList]
+            return searchList            
+
+        def normalizeTokens(tokens):
+            if isinstance(tokens, str):
+                return tokens.split() # space delimited string e.g.'@ %'
+            elif isinstance(tokens, (list, tuple)):
+                return tokens
+            else:
+                raise PreprocessError('invalid tokens argument: %r'%tokens)
+
+        if hasattr(settings, 'tokens'):
+            (settings.placeholderToken,
+             settings.directiveToken) = normalizeTokens(settings.tokens)
+            
+        if (not getattr(settings,'compilerSettings', None)
+            and not getattr(settings, 'placeholderToken', None) ):
+            
+            raise TypeError(
+                'Preprocessor requires either a "tokens" or a "compilerSettings" arg.'
+                ' Neither was provided.')
+
+        if not hasattr(settings, 'templateInitArgs'):
+            settings.templateInitArgs = {}
+        if 'searchList' not in settings.templateInitArgs:
+            if not hasattr(settings, 'searchList') and hasattr(settings, 'namespaces'):
+                settings.searchList = settings.namespaces
+            elif not hasattr(settings, 'searchList'):
+                settings.searchList = []
+            settings.templateInitArgs['searchList'] = settings.searchList
+        settings.templateInitArgs['searchList'] = (
+            normalizeSearchList(settings.templateInitArgs['searchList']))
+            
+        if not hasattr(settings, 'outputTransformer'):
+            settings.outputTransformer = unicode
+
+        if not hasattr(settings, 'templateAPIClass'):
+            class PreprocessTemplateAPIClass(klass): pass
+            settings.templateAPIClass = PreprocessTemplateAPIClass
+
+        if not hasattr(settings, 'compilerSettings'):
+            settings.compilerSettings = {}
+
+        klass._updateSettingsWithPreprocessTokens(
+            compilerSettings=settings.compilerSettings,
+            placeholderToken=settings.placeholderToken,
+            directiveToken=settings.directiveToken
+            )                            
+        return settings
+    _normalizePreprocessorSettings = classmethod(_normalizePreprocessorSettings)
+
+    def _updateSettingsWithPreprocessTokens(
+        klass, compilerSettings, placeholderToken, directiveToken):
+        
+        if (placeholderToken and 'cheetahVarStartToken' not in compilerSettings):
+            compilerSettings['cheetahVarStartToken'] = placeholderToken
+        if directiveToken:
+            if 'directiveStartToken' not in compilerSettings:
+                compilerSettings['directiveStartToken'] = directiveToken
+            if 'directiveEndToken' not in compilerSettings:
+                compilerSettings['directiveEndToken'] = directiveToken
+            if 'commentStartToken' not in compilerSettings:
+                compilerSettings['commentStartToken'] = directiveToken*2
+            if 'multiLineCommentStartToken' not in compilerSettings:
+                compilerSettings['multiLineCommentStartToken'] = (
+                    directiveToken+'*')
+            if 'multiLineCommentEndToken' not in compilerSettings:
+                compilerSettings['multiLineCommentEndToken'] = (
+                    '*'+directiveToken)
+            if 'EOLSlurpToken' not in compilerSettings:
+                compilerSettings['EOLSlurpToken'] = directiveToken
+    _updateSettingsWithPreprocessTokens = classmethod(_updateSettingsWithPreprocessTokens)
+
+    def _addCheetahPlumbingCodeToClass(klass, concreteTemplateClass):
+        """If concreteTemplateClass is not a subclass of Cheetah.Template, add
+        the required cheetah methods and attributes to it.
+
+        This is called on each new template class after it has been compiled.
+        If concreteTemplateClass is not a subclass of Cheetah.Template but
+        already has method with the same name as one of the required cheetah
+        methods, this will skip that method.
+        """
+        for methodname in klass._CHEETAH_requiredCheetahMethods:
+            if not hasattr(concreteTemplateClass, methodname):
+                method = getattr(Template, methodname)
+                newMethod = new.instancemethod(method.im_func, None, concreteTemplateClass)
+                #print methodname, method
+                setattr(concreteTemplateClass, methodname, newMethod)
+
+        for classMethName in klass._CHEETAH_requiredCheetahClassMethods:
+            if not hasattr(concreteTemplateClass, classMethName):
+                meth = getattr(klass, classMethName)
+                setattr(concreteTemplateClass, classMethName, classmethod(meth.im_func))
+            
+        for attrname in klass._CHEETAH_requiredCheetahClassAttributes:
+            attrname = '_CHEETAH_'+attrname
+            if not hasattr(concreteTemplateClass, attrname):
+                attrVal = getattr(klass, attrname)
+                setattr(concreteTemplateClass, attrname, attrVal)
+
+        if (not hasattr(concreteTemplateClass, '__str__')
+            or concreteTemplateClass.__str__ is object.__str__):
+            
+            mainMethNameAttr = '_mainCheetahMethod_for_'+concreteTemplateClass.__name__
+            mainMethName = getattr(concreteTemplateClass,mainMethNameAttr, None)
+            if mainMethName:
+                def __str__(self): 
+                    return getattr(self, mainMethName)()
+            elif (hasattr(concreteTemplateClass, 'respond')
+                  and concreteTemplateClass.respond!=Servlet.respond):
+                def __str__(self):
+                    return self.respond()
+            else:
+                def __str__(self):
+                    if hasattr(self, mainMethNameAttr):
+                        return getattr(self,mainMethNameAttr)()
+                    elif hasattr(self, 'respond'):
+                        return self.respond()
+                    else:
+                        return super(self.__class__, self).__str__()
+                    
+            __str__ = new.instancemethod(__str__, None, concreteTemplateClass)
+            setattr(concreteTemplateClass, '__str__', __str__)
+                
+    _addCheetahPlumbingCodeToClass = classmethod(_addCheetahPlumbingCodeToClass)
+
+    ## end classmethods ##
+
+    def __init__(self, source=None,
+
+                 namespaces=None, searchList=None,
+                 # use either or.  They are aliases for the same thing.
+                 
+                 file=None,
+                 filter='RawOrEncodedUnicode', # which filter from Cheetah.Filters
+                 filtersLib=Filters,
+                 errorCatcher=None,
+                 
+                 compilerSettings=Unspecified, # control the behaviour of the compiler
+                 _globalSetVars=None, # used internally for #include'd templates
+                 _preBuiltSearchList=None # used internally for #include'd templates
+                 ):        
+        """a) compiles a new template OR b) instantiates an existing template.
+
+        Read this docstring carefully as there are two distinct usage patterns.
+        You should also read this class' main docstring.
+        
+        a) to compile a new template:
+             t = Template(source=aSourceString)
+                 # or 
+             t = Template(file='some/path')
+                 # or 
+             t = Template(file=someFileObject)
+                 # or
+             namespaces = [{'foo':'bar'}]               
+             t = Template(source=aSourceString, namespaces=namespaces)
+                 # or 
+             t = Template(file='some/path', namespaces=namespaces)
+  
+             print t
+             
+        b) to create an instance of an existing, precompiled template class:
+             ## i) first you need a reference to a compiled template class:
+             tclass = Template.compile(source=src) # or just Template.compile(src)
+                 # or 
+             tclass = Template.compile(file='some/path')
+                 # or 
+             tclass = Template.compile(file=someFileObject)
+                 # or 
+             # if you used the command line compiler or have Cheetah's ImportHooks
+             # installed your template class is also available via Python's
+             # standard import mechanism:
+             from ACompileTemplate import AcompiledTemplate as tclass
+             
+             ## ii) then you create an instance
+             t = tclass(namespaces=namespaces)
+                 # or 
+             t = tclass(namespaces=namespaces, filter='RawOrEncodedUnicode')
+             print t
+
+        Arguments:
+          for usage pattern a)           
+            If you are compiling a new template, you must provide either a
+            'source' or 'file' arg, but not both:          
+              - source (string or None)
+              - file (string path, file-like object, or None)
+
+            Optional args (see below for more) :
+              - compilerSettings
+               Default: Template._CHEETAH_compilerSettings=None
+               
+               a dictionary of settings to override those defined in
+               DEFAULT_COMPILER_SETTINGS.  See
+               Cheetah.Template.DEFAULT_COMPILER_SETTINGS and the Users' Guide
+               for details.
+
+            You can pass the source arg in as a positional arg with this usage
+            pattern.  Use keywords for all other args.           
+
+          for usage pattern b)
+            Do not use positional args with this usage pattern, unless your
+            template subclasses something other than Cheetah.Template and you
+            want to pass positional args to that baseclass.  E.g.:
+              dictTemplate = Template.compile('hello $name from $caller', baseclass=dict)
+              tmplvars = dict(name='world', caller='me')
+              print dictTemplate(tmplvars)
+            This usage requires all Cheetah args to be passed in as keyword args.
+
+          optional args for both usage patterns:
+
+            - namespaces (aka 'searchList')
+              Default: None
+              
+              an optional list of namespaces (dictionaries, objects, modules,
+              etc.) which Cheetah will search through to find the variables
+              referenced in $placeholders.
+
+              If you provide a single namespace instead of a list, Cheetah will
+              automatically convert it into a list.
+                
+              NOTE: Cheetah does NOT force you to use the namespaces search list
+              and related features.  It's on by default, but you can turn if off
+              using the compiler settings useSearchList=False or
+              useNameMapper=False.
+                
+             - filter
+               Default: 'EncodeUnicode'
+               
+               Which filter should be used for output filtering. This should
+               either be a string which is the name of a filter in the
+               'filtersLib' or a subclass of Cheetah.Filters.Filter. . See the
+               Users' Guide for more details.
+
+             - filtersLib
+               Default: Cheetah.Filters
+               
+               A module containing subclasses of Cheetah.Filters.Filter. See the
+               Users' Guide for more details. 
+
+             - errorCatcher
+               Default: None
+
+               This is a debugging tool. See the Users' Guide for more details.
+               Do not use this or the #errorCatcher diretive with live
+               production systems.
+
+          Do NOT mess with the args _globalSetVars or _preBuiltSearchList!
+
+        """
+        
+        ##################################################           
+        ## Verify argument keywords and types
+
+        S = types.StringType; U = types.UnicodeType
+        L = types.ListType;   T = types.TupleType
+        D = types.DictType;   F = types.FileType
+        C = types.ClassType;  M = types.ModuleType
+        N = types.NoneType
+        vt = VerifyType.VerifyType
+        vtc = VerifyType.VerifyTypeClass
+        try:
+            vt(source, 'source', [N,S,U], 'string or None')
+            vt(file, 'file', [N,S,U,F], 'string, file open for reading, or None')
+            vtc(filter, 'filter', [S,C,type], 'string or class', 
+                Filters.Filter,
+                '(if class, must be subclass of Cheetah.Filters.Filter)')
+            vt(filtersLib, 'filtersLib', [S,M], 'string or module',
+                '(if module, must contain subclasses of Cheetah.Filters.Filter)')
+            vtc(errorCatcher, 'errorCatcher', [N,S,C,type], 'string, class or None',
+               ErrorCatchers.ErrorCatcher,
+               '(if class, must be subclass of Cheetah.ErrorCatchers.ErrorCatcher)')
+            if compilerSettings is not Unspecified:
+                vt(compilerSettings, 'compilerSettings', [D], 'dictionary')
+
+        except TypeError, reason:
+            # Re-raise the exception here so that the traceback will end in
+            # this function rather than in some utility function.
+            raise TypeError(reason)
+        
+        if source is not None and file is not None:
+            raise TypeError("you must supply either a source string or the" + 
+                            " 'file' keyword argument, but not both")
+                    
+        ##################################################           
+        ## Do superclass initialization.
+        super(Template, self).__init__()
+
+        ##################################################           
+        ## Do required version check
+        if not hasattr(self, '_CHEETAH_versionTuple'):
+            try:
+                mod = sys.modules[self.__class__.__module__]
+                compiledVersion = mod.__CHEETAH_version__
+                compiledVersionTuple = convertVersionStringToTuple(compiledVersion)
+                if compiledVersionTuple < MinCompatibleVersionTuple:
+                    raise AssertionError(
+                     'This template was compiled with Cheetah version'
+                     ' %s. Templates compiled before version %s must be recompiled.'%(
+                        compiledVersion, MinCompatibleVersion))                    
+            except AssertionError:
+                raise 
+            except:
+                pass
+        
+        ##################################################           
+        ## Setup instance state attributes used during the life of template
+        ## post-compile
+        reserved_searchlist = dir(self)
+        if searchList:
+            for namespace in searchList:
+                if isinstance(namespace, dict):
+                    intersection = set(reserved_searchlist) & set(namespace.keys())
+                    warn = False
+                    if intersection:
+                        warn = True
+                    if isinstance(compilerSettings, dict) and compilerSettings.get('prioritizeSearchListOverSelf'):
+                        warn = False
+                    if warn:
+                        print
+                        print ''' *** WARNING *** '''
+                        print ''' The following keys are members of the Template class and will result in NameMapper collisions! '''
+                        print '''  > %s ''' % ', '.join(list(intersection))
+                        print 
+                        print ''' Please change the key's name or use the compiler setting "prioritizeSearchListOverSelf=True" to prevent the NameMapper from using '''
+                        print ''' the Template member in place of your searchList variable '''
+                        print ''' *************** '''
+                        print 
+
+        self._initCheetahInstance(
+            searchList=searchList, namespaces=namespaces,
+            filter=filter, filtersLib=filtersLib,
+            errorCatcher=errorCatcher,
+            _globalSetVars=_globalSetVars,
+            compilerSettings=compilerSettings,
+            _preBuiltSearchList=_preBuiltSearchList)
+        
+        ##################################################
+        ## Now, compile if we're meant to
+        if (source is not None) or (file is not None):
+            self._compile(source, file, compilerSettings=compilerSettings)
+
+    def generatedModuleCode(self):
+        """Return the module code the compiler generated, or None if no
+        compilation took place.
+        """
+        
+        return self._CHEETAH_generatedModuleCode
+    
+    def generatedClassCode(self):        
+        """Return the class code the compiler generated, or None if no
+        compilation took place.
+        """
+        
+        return self._CHEETAH_generatedModuleCode[
+                    self._CHEETAH_generatedModuleCode.find('\nclass '):
+                    self._CHEETAH_generatedModuleCode.find('\n## END CLASS DEFINITION')]
+    
+    def searchList(self):
+        """Return a reference to the searchlist
+        """
+        return self._CHEETAH__searchList
+
+    def errorCatcher(self):
+        """Return a reference to the current errorCatcher
+        """
+        return self._CHEETAH__errorCatcher
+
+    ## cache methods ##
+    def _getCacheStore(self):
+        if not self._CHEETAH__cacheStore:
+            if self._CHEETAH_cacheStore is not None:
+                self._CHEETAH__cacheStore = self._CHEETAH_cacheStore
+            else:
+                # @@TR: might want to provide a way to provide init args
+                self._CHEETAH__cacheStore = self._CHEETAH_cacheStoreClass()
+
+        return self._CHEETAH__cacheStore
+
+    def _getCacheStoreIdPrefix(self):
+        if self._CHEETAH_cacheStoreIdPrefix is not None:            
+            return self._CHEETAH_cacheStoreIdPrefix
+        else:
+            return str(id(self))
+    
+    def _createCacheRegion(self, regionID):
+        return self._CHEETAH_cacheRegionClass(
+            regionID=regionID,
+            templateCacheIdPrefix=self._getCacheStoreIdPrefix(),
+            cacheStore=self._getCacheStore())
+
+    def getCacheRegion(self, regionID, cacheInfo=None, create=True):
+        cacheRegion = self._CHEETAH__cacheRegions.get(regionID)
+        if not cacheRegion and create:
+            cacheRegion = self._createCacheRegion(regionID)
+            self._CHEETAH__cacheRegions[regionID] = cacheRegion
+        return cacheRegion        
+    
+    def getCacheRegions(self):
+        """Returns a dictionary of the 'cache regions' initialized in a
+        template.
+
+        Each #cache directive block or $*cachedPlaceholder is a separate 'cache
+        region'.        
+        """
+        # returns a copy to prevent users mucking it up
+        return self._CHEETAH__cacheRegions.copy()
+
+    def refreshCache(self, cacheRegionId=None, cacheItemId=None):        
+        """Refresh a cache region or a specific cache item within a region.
+        """
+        
+        if not cacheRegionId:
+            for key, cregion in self.getCacheRegions():
+                cregion.clear()
+        else:
+            cregion = self._CHEETAH__cacheRegions.get(cacheRegionId)
+            if not cregion:
+                return
+            if not cacheItemId: # clear the desired region and all its cacheItems
+                cregion.clear()
+            else: # clear one specific cache of a specific region
+                cache = cregion.getCacheItem(cacheItemId)
+                if cache:
+                    cache.clear()
+                    
+    ## end cache methods ##
+                    
+    def shutdown(self):
+        """Break reference cycles before discarding a servlet.
+        """
+        try:
+            Servlet.shutdown(self)
+        except:
+            pass
+        self._CHEETAH__searchList = None
+        self.__dict__ = {}
+            
+    ## utility functions ##   
+
+    def getVar(self, varName, default=Unspecified, autoCall=True):        
+        """Get a variable from the searchList.  If the variable can't be found
+        in the searchList, it returns the default value if one was given, or
+        raises NameMapper.NotFound.
+        """
+        
+        try:
+            return valueFromSearchList(self.searchList(), varName.replace('$',''), autoCall)
+        except NotFound:
+            if default is not Unspecified:
+                return default
+            else:
+                raise
+    
+    def varExists(self, varName, autoCall=True):
+        """Test if a variable name exists in the searchList.
+        """
+        try:
+            valueFromSearchList(self.searchList(), varName.replace('$',''), autoCall)
+            return True
+        except NotFound:
+            return False
+
+
+    hasVar = varExists
+
+
+    def i18n(self, message,
+             plural=None,
+             n=None,
+                   
+             id=None,
+             domain=None,
+             source=None,
+             target=None,
+             comment=None
+             ):
+        """This is just a stub at this time.
+
+	   plural = the plural form of the message
+	   n = a sized argument to distinguish between single and plural forms           
+
+      	   id = msgid in the translation catalog
+	   domain = translation domain
+	   source = source lang
+	   target = a specific target lang
+	   comment = a comment to the translation team
+
+        See the following for some ideas
+        http://www.zope.org/DevHome/Wikis/DevSite/Projects/ComponentArchitecture/ZPTInternationalizationSupport
+
+        Other notes:
+        - There is no need to replicate the i18n:name attribute from plone / PTL,
+          as cheetah placeholders serve the same purpose
+    
+    
+       """
+
+        return message
+
+    def getFileContents(self, path):
+        """A hook for getting the contents of a file.  The default
+        implementation just uses the Python open() function to load local files.
+        This method could be reimplemented to allow reading of remote files via
+        various protocols, as PHP allows with its 'URL fopen wrapper'
+        """
+        
+        fp = open(path,'r')
+        output = fp.read()
+        fp.close()
+        return output
+    
+    def runAsMainProgram(self):        
+        """Allows the Template to function as a standalone command-line program
+        for static page generation.
+
+        Type 'python yourtemplate.py --help to see what it's capabable of.
+        """
+
+        from TemplateCmdLineIface import CmdLineIface
+        CmdLineIface(templateObj=self).run()
+        
+    ##################################################
+    ## internal methods -- not to be called by end-users
+
+    def _initCheetahInstance(self,
+                             searchList=None,
+                             namespaces=None,
+                             filter='RawOrEncodedUnicode', # which filter from Cheetah.Filters
+                             filtersLib=Filters,
+                             errorCatcher=None,
+                             _globalSetVars=None,
+                             compilerSettings=None,
+                             _preBuiltSearchList=None):
+        """Sets up the instance attributes that cheetah templates use at
+        run-time.
+
+        This is automatically called by the __init__ method of compiled
+        templates.
+
+        Note that the names of instance attributes used by Cheetah are prefixed
+        with '_CHEETAH__' (2 underscores), where class attributes are prefixed
+        with '_CHEETAH_' (1 underscore).
+        """
+        if getattr(self, '_CHEETAH__instanceInitialized', False):
+            return
+
+        if namespaces is not None: 
+            assert searchList is None, (
+                'Provide "namespaces" or "searchList", not both!')
+            searchList = namespaces
+        if searchList is not None and not isinstance(searchList, (list, tuple)):
+            searchList = [searchList]
+
+        self._CHEETAH__globalSetVars = {}
+        if _globalSetVars is not None:
+            # this is intended to be used internally by Nested Templates in #include's
+            self._CHEETAH__globalSetVars = _globalSetVars
+            
+        if _preBuiltSearchList is not None:
+            # happens with nested Template obj creation from #include's
+            self._CHEETAH__searchList = list(_preBuiltSearchList)
+            self._CHEETAH__searchList.append(self)
+        else:
+            # create our own searchList
+            self._CHEETAH__searchList = [self._CHEETAH__globalSetVars, self]
+            if searchList is not None:
+                if isinstance(compilerSettings, dict) and compilerSettings.get('prioritizeSearchListOverSelf'):
+                    self._CHEETAH__searchList = searchList + self._CHEETAH__searchList
+                else:
+                    self._CHEETAH__searchList.extend(list(searchList))
+        self._CHEETAH__cheetahIncludes = {}
+        self._CHEETAH__cacheRegions = {}
+        self._CHEETAH__indenter = Indenter()
+
+        # @@TR: consider allowing simple callables as the filter argument
+        self._CHEETAH__filtersLib = filtersLib
+        self._CHEETAH__filters = {}
+        if type(filter) in StringTypes:
+            filterName = filter
+            klass = getattr(self._CHEETAH__filtersLib, filterName)
+        else:
+            klass = filter
+            filterName = klass.__name__            
+        self._CHEETAH__currentFilter = self._CHEETAH__filters[filterName] = klass(self).filter
+        self._CHEETAH__initialFilter = self._CHEETAH__currentFilter
+
+        self._CHEETAH__errorCatchers = {}
+        if errorCatcher:
+            if type(errorCatcher) in StringTypes:
+                errorCatcherClass = getattr(ErrorCatchers, errorCatcher)
+            elif type(errorCatcher) == ClassType:
+                errorCatcherClass = errorCatcher
+
+            self._CHEETAH__errorCatcher = ec = errorCatcherClass(self)
+            self._CHEETAH__errorCatchers[errorCatcher.__class__.__name__] = ec
+                                 
+        else:
+            self._CHEETAH__errorCatcher = None
+        self._CHEETAH__initErrorCatcher = self._CHEETAH__errorCatcher        
+
+        if not hasattr(self, 'transaction'):
+            self.transaction = None
+        self._CHEETAH__instanceInitialized = True
+        self._CHEETAH__isBuffering = False
+        self._CHEETAH__isControlledByWebKit = False 
+
+        self._CHEETAH__cacheStore = None
+        if self._CHEETAH_cacheStore is not None:
+            self._CHEETAH__cacheStore = self._CHEETAH_cacheStore
+        
+    def _compile(self, source=None, file=None, compilerSettings=Unspecified,
+                 moduleName=None, mainMethodName=None):
+        """Compile the template. This method is automatically called by
+        Template.__init__ it is provided with 'file' or 'source' args.
+
+        USERS SHOULD *NEVER* CALL THIS METHOD THEMSELVES.  Use Template.compile
+        instead.
+        """
+        if compilerSettings is Unspecified:
+            compilerSettings = self._getCompilerSettings(source, file) or {}        
+        mainMethodName = mainMethodName or self._CHEETAH_defaultMainMethodName
+        self._fileMtime = None
+        self._fileDirName = None
+        self._fileBaseName = None
+        if file and type(file) in StringTypes:
+            file = self.serverSidePath(file)
+            self._fileMtime = os.path.getmtime(file)
+            self._fileDirName, self._fileBaseName = os.path.split(file)
+        self._filePath = file
+        templateClass = self.compile(source, file,
+                                      moduleName=moduleName,
+                                      mainMethodName=mainMethodName,
+                                      compilerSettings=compilerSettings,
+                                      keepRefToGeneratedCode=True)
+        self.__class__ = templateClass
+        # must initialize it so instance attributes are accessible
+        templateClass.__init__(self,
+                               #_globalSetVars=self._CHEETAH__globalSetVars,
+                               #_preBuiltSearchList=self._CHEETAH__searchList
+                               )                               
+        if not hasattr(self, 'transaction'):
+            self.transaction = None
+
+    def _handleCheetahInclude(self, srcArg, trans=None, includeFrom='file', raw=False):        
+        """Called at runtime to handle #include directives.
+        """
+        _includeID = srcArg            
+        if not self._CHEETAH__cheetahIncludes.has_key(_includeID):
+            if not raw:
+                if includeFrom == 'file':
+                    source = None
+                    if type(srcArg) in StringTypes:
+                        if hasattr(self, 'serverSidePath'):
+                            file = path = self.serverSidePath(srcArg)
+                        else:
+                            file = path = os.path.normpath(srcArg)
+                    else:
+                        file = srcArg ## a file-like object
+                else:
+                    source = srcArg
+                    file = None
+                # @@TR: might want to provide some syntax for specifying the
+                # Template class to be used for compilation so compilerSettings
+                # can be changed.
+                compiler = self._getTemplateAPIClassForIncludeDirectiveCompilation(source, file)
+                nestedTemplateClass = compiler.compile(source=source,file=file)
+                nestedTemplate = nestedTemplateClass(_preBuiltSearchList=self.searchList(),
+                                                     _globalSetVars=self._CHEETAH__globalSetVars)
+                # Set the inner template filters to the initial filter of the
+                # outer template:
+                # this is the only really safe way to use
+                # filter='WebSafe'.
+                nestedTemplate._CHEETAH__initialFilter = self._CHEETAH__initialFilter
+                nestedTemplate._CHEETAH__currentFilter = self._CHEETAH__initialFilter   
+                self._CHEETAH__cheetahIncludes[_includeID] = nestedTemplate
+            else:
+                if includeFrom == 'file':
+                    path = self.serverSidePath(srcArg)
+                    self._CHEETAH__cheetahIncludes[_includeID] = self.getFileContents(path)
+                else:
+                    self._CHEETAH__cheetahIncludes[_includeID] = srcArg
+        ##
+        if not raw:
+            self._CHEETAH__cheetahIncludes[_includeID].respond(trans)
+        else:
+            trans.response().write(self._CHEETAH__cheetahIncludes[_includeID])
+
+    def _getTemplateAPIClassForIncludeDirectiveCompilation(self, source, file):
+        """Returns the subclass of Template which should be used to compile
+        #include directives.
+
+        This abstraction allows different compiler settings to be used in the
+        included template than were used in the parent.
+        """
+        if issubclass(self.__class__, Template):
+            return self.__class__
+        else:
+            return Template
+
+    ## functions for using templates as CGI scripts
+    def webInput(self, names, namesMulti=(), default='', src='f',
+        defaultInt=0, defaultFloat=0.00, badInt=0, badFloat=0.00, debug=False):
+        """Method for importing web transaction variables in bulk.
+
+        This works for GET/POST fields both in Webware servlets and in CGI
+        scripts, and for cookies and session variables in Webware servlets.  If
+        you try to read a cookie or session variable in a CGI script, you'll get
+        a RuntimeError.  'In a CGI script' here means 'not running as a Webware
+        servlet'.  If the CGI environment is not properly set up, Cheetah will
+        act like there's no input.
+
+        The public method provided is:
+
+          def webInput(self, names, namesMulti=(), default='', src='f',
+            defaultInt=0, defaultFloat=0.00, badInt=0, badFloat=0.00, debug=False):
+
+        This method places the specified GET/POST fields, cookies or session
+        variables into a dictionary, which is both returned and put at the
+        beginning of the searchList.  It handles:
+            
+            * single vs multiple values
+            * conversion to integer or float for specified names
+            * default values/exceptions for missing or bad values
+            * printing a snapshot of all values retrieved for debugging        
+
+        All the 'default*' and 'bad*' arguments have 'use or raise' behavior,
+        meaning that if they're a subclass of Exception, they're raised.  If
+        they're anything else, that value is substituted for the missing/bad
+        value.
+
+
+        The simplest usage is:
+
+            #silent $webInput(['choice'])
+            $choice
+
+            dic = self.webInput(['choice'])
+            write(dic['choice'])
+
+        Both these examples retrieves the GET/POST field 'choice' and print it.
+        If you leave off the'#silent', all the values would be printed too.  But
+        a better way to preview the values is
+
+            #silent $webInput(['name'], $debug=1)
+
+        because this pretty-prints all the values inside HTML <PRE> tags.
+
+        ** KLUDGE: 'debug' is supposed to insert into the template output, but it
+        wasn't working so I changed it to a'print' statement.  So the debugging
+        output will appear wherever standard output is pointed, whether at the
+        terminal, in a Webware log file, or whatever. ***
+
+        Since we didn't specify any coversions, the value is a string.  It's a
+        'single' value because we specified it in 'names' rather than
+        'namesMulti'. Single values work like this:
+        
+            * If one value is found, take it.
+            * If several values are found, choose one arbitrarily and ignore the rest.
+            * If no values are found, use or raise the appropriate 'default*' value.
+
+        Multi values work like this:
+            * If one value is found, put it in a list.
+            * If several values are found, leave them in a list.
+            * If no values are found, use the empty list ([]).  The 'default*' 
+              arguments are *not* consulted in this case.
+
+        Example: assume 'days' came from a set of checkboxes or a multiple combo
+        box on a form, and the user  chose'Monday', 'Tuesday' and 'Thursday'.
+
+            #silent $webInput([], ['days'])
+            The days you chose are: #slurp
+            #for $day in $days
+            $day #slurp
+            #end for
+
+            dic = self.webInput([], ['days'])
+            write('The days you chose are: ')
+            for day in dic['days']:
+                write(day + ' ')
+
+        Both these examples print:  'The days you chose are: Monday Tuesday Thursday'.
+
+        By default, missing strings are replaced by '' and missing/bad numbers
+        by zero.  (A'bad number' means the converter raised an exception for
+        it, usually because of non-numeric characters in the value.)  This
+        mimics Perl/PHP behavior, and simplifies coding for many applications
+        where missing/bad values *should* be blank/zero.  In those relatively
+        few cases where you must distinguish between empty-string/zero on the
+        one hand and missing/bad on the other, change the appropriate
+        'default*' and 'bad*' arguments to something like: 
+
+            * None
+            * another constant value
+            * $NonNumericInputError/self.NonNumericInputError
+            * $ValueError/ValueError
+            
+        (NonNumericInputError is defined in this class and is useful for
+        distinguishing between bad input vs a TypeError/ValueError thrown for
+        some other rason.)
+
+        Here's an example using multiple values to schedule newspaper
+        deliveries.  'checkboxes' comes from a form with checkboxes for all the
+        days of the week.  The days the user previously chose are preselected.
+        The user checks/unchecks boxes as desired and presses Submit.  The value
+        of 'checkboxes' is a list of checkboxes that were checked when Submit
+        was pressed.  Our task now is to turn on the days the user checked, turn
+        off the days he unchecked, and leave on or off the days he didn't
+        change.
+
+            dic = self.webInput([], ['dayCheckboxes'])
+            wantedDays = dic['dayCheckboxes'] # The days the user checked.
+            for day, on in self.getAllValues():
+                if   not on and wantedDays.has_key(day):
+                    self.TurnOn(day)
+                    # ... Set a flag or insert a database record ...
+                elif on and not wantedDays.has_key(day):
+                    self.TurnOff(day)
+                    # ... Unset a flag or delete a database record ...
+
+        'source' allows you to look up the variables from a number of different
+        sources:
+            'f'   fields (CGI GET/POST parameters)
+            'c'   cookies
+            's'   session variables
+            'v'   'values', meaning fields or cookies
+
+        In many forms, you're dealing only with strings, which is why the
+        'default' argument is third and the numeric arguments are banished to
+        the end.  But sometimes you want automatic number conversion, so that
+        you can do numeric comparisions in your templates without having to
+        write a bunch of conversion/exception handling code.  Example:
+
+            #silent $webInput(['name', 'height:int'])
+            $name is $height cm tall.
+            #if $height >= 300
+            Wow, you're tall!
+            #else
+            Pshaw, you're short.
+            #end if
+
+            dic = self.webInput(['name', 'height:int'])
+            name = dic[name]
+            height = dic[height]
+            write('%s is %s cm tall.' % (name, height))
+            if height > 300:
+                write('Wow, you're tall!')
+            else:
+                write('Pshaw, you're short.')
+
+        To convert a value to a number, suffix ':int' or ':float' to the name.
+        The method will search first for a 'height:int' variable and then for a
+        'height' variable.  (It will be called 'height' in the final
+        dictionary.)  If a numeric conversion fails, use or raise 'badInt' or
+        'badFloat'.  Missing values work the same way as for strings, except the
+        default is 'defaultInt' or 'defaultFloat' instead of 'default'.
+
+        If a name represents an uploaded file, the entire file will be read into
+        memory.  For more sophistocated file-upload handling, leave that name
+        out of the list and do your own handling, or wait for
+        Cheetah.Utils.UploadFileMixin.
+
+        This only in a subclass that also inherits from Webware's Servlet or
+        HTTPServlet.  Otherwise you'll get an AttributeError on 'self.request'.
+
+        EXCEPTIONS: ValueError if 'source' is not one of the stated characters.
+        TypeError if a conversion suffix is not ':int' or ':float'.
+
+        FUTURE EXPANSION: a future version of this method may allow source
+        cascading; e.g., 'vs' would look first in 'values' and then in session
+        variables.
+
+        Meta-Data
+        ================================================================================
+        Author: Mike Orr <iron at mso.oz.net>
+        License: This software is released for unlimited distribution under the
+                 terms of the MIT license.  See the LICENSE file.
+        Version: $Revision: 1.186 $
+        Start Date: 2002/03/17
+        Last Revision Date: $Date: 2008/03/10 04:48:11 $
+        """ 
+        src = src.lower()
+        isCgi = not self._CHEETAH__isControlledByWebKit
+        if   isCgi and src in ('f', 'v'):
+            global _formUsedByWebInput
+            if _formUsedByWebInput is None:
+                _formUsedByWebInput = cgi.FieldStorage()
+            source, func = 'field',   _formUsedByWebInput.getvalue
+        elif isCgi and src == 'c':
+            raise RuntimeError("can't get cookies from a CGI script")
+        elif isCgi and src == 's':
+            raise RuntimeError("can't get session variables from a CGI script")
+        elif isCgi and src == 'v':
+            source, func = 'value',   self.request().value
+        elif isCgi and src == 's':
+            source, func = 'session', self.request().session().value
+        elif src == 'f':
+            source, func = 'field',   self.request().field
+        elif src == 'c':
+            source, func = 'cookie',  self.request().cookie
+        elif src == 'v':
+            source, func = 'value',   self.request().value
+        elif src == 's':
+            source, func = 'session', self.request().session().value
+        else:
+            raise TypeError("arg 'src' invalid")
+        sources = source + 's'
+        converters = {
+            ''     : _Converter('string', None, default,      default ),
+            'int'  : _Converter('int',     int, defaultInt,   badInt  ),
+            'float': _Converter('float', float, defaultFloat, badFloat),  }
+        #pprint.pprint(locals());  return {}
+        dic = {} # Destination.
+        for name in names:
+            k, v = _lookup(name, func, False, converters)
+            dic[k] = v
+        for name in namesMulti:
+            k, v = _lookup(name, func, True, converters)
+            dic[k] = v
+        # At this point, 'dic' contains all the keys/values we want to keep.
+        # We could split the method into a superclass
+        # method for Webware/WebwareExperimental and a subclass for Cheetah.
+        # The superclass would merely 'return dic'.  The subclass would
+        # 'dic = super(ThisClass, self).webInput(names, namesMulti, ...)'
+        # and then the code below.
+        if debug:
+           print "<PRE>\n" + pprint.pformat(dic) + "\n</PRE>\n\n"
+        self.searchList().insert(0, dic)
+        return dic
+
+T = Template   # Short and sweet for debugging at the >>> prompt.
+
+
+def genParserErrorFromPythonException(source, file, generatedPyCode, exception):
+
+    #print dir(exception)
+    
+    filename = isinstance(file, (str, unicode)) and file or None
+
+    sio = StringIO.StringIO()
+    traceback.print_exc(1, sio)
+    formatedExc = sio.getvalue()
+    
+    if hasattr(exception, 'lineno'):
+        pyLineno = exception.lineno
+    else:
+        pyLineno = int(re.search('[ \t]*File.*line (\d+)', formatedExc).group(1))
+       
+    lines = generatedPyCode.splitlines()
+    
+    prevLines = []                  # (i, content)
+    for i in range(1,4):
+        if pyLineno-i <=0:
+            break
+        prevLines.append( (pyLineno+1-i,lines[pyLineno-i]) )
+    
+    nextLines = []                  # (i, content)
+    for i in range(1,4):
+        if not pyLineno+i < len(lines):
+            break
+        nextLines.append( (pyLineno+i,lines[pyLineno+i]) )
+    nextLines.reverse()
+    report = 'Line|Python Code\n'
+    report += '----|-------------------------------------------------------------\n'
+    while prevLines:
+        lineInfo = prevLines.pop()
+        report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
+
+    if hasattr(exception, 'offset'):
+        report += ' '*(3+(exception.offset or 0)) + '^\n'
+    
+    while nextLines:
+        lineInfo = nextLines.pop()
+        report += "%(row)-4d|%(line)s\n"% {'row':lineInfo[0], 'line':lineInfo[1]}
+    
+    
+    message = [
+        "Error in the Python code which Cheetah generated for this template:",
+        '='*80,
+        '',
+        str(exception),
+        '',                            
+        report,
+        '='*80,
+        ]
+    cheetahPosMatch = re.search('line (\d+), col (\d+)', formatedExc)
+    if cheetahPosMatch:
+        lineno = int(cheetahPosMatch.group(1))
+        col = int(cheetahPosMatch.group(2))
+        #if hasattr(exception, 'offset'):
+        #    col = exception.offset
+        message.append('\nHere is the corresponding Cheetah code:\n')
+    else:
+        lineno = None
+        col = None
+        cheetahPosMatch = re.search('line (\d+), col (\d+)',
+                                    '\n'.join(lines[max(pyLineno-2, 0):]))
+        if cheetahPosMatch:
+            lineno = int(cheetahPosMatch.group(1))
+            col = int(cheetahPosMatch.group(2))
+            message.append('\nHere is the corresponding Cheetah code.')
+            message.append('** I had to guess the line & column numbers,'
+                           ' so they are probably incorrect:\n')
+
+    
+    message = '\n'.join(message)
+    reader = SourceReader(source, filename=filename)
+    return ParseError(reader, message, lineno=lineno,col=col)
+    
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/TemplateCmdLineIface.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/TemplateCmdLineIface.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/TemplateCmdLineIface.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# $Id: TemplateCmdLineIface.py,v 1.13 2006/01/10 20:34:35 tavis_rudd Exp $
+
+"""Provides a command line interface to compiled Cheetah template modules.
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>
+Version: $Revision: 1.13 $
+Start Date: 2001/12/06
+Last Revision Date: $Date: 2006/01/10 20:34:35 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.13 $"[11:-2]
+
+import sys
+import os
+import getopt
+import os.path
+try:
+    from cPickle import load
+except ImportError:
+    from pickle import load
+
+from Cheetah.Version import Version
+
+class Error(Exception):
+    pass
+
+class CmdLineIface:
+    """A command line interface to compiled Cheetah template modules."""
+
+    def __init__(self, templateObj,
+                 scriptName=os.path.basename(sys.argv[0]),
+                 cmdLineArgs=sys.argv[1:]):
+
+        self._template = templateObj
+        self._scriptName = scriptName
+        self._cmdLineArgs = cmdLineArgs
+
+    def run(self):
+        """The main program controller."""
+        
+        self._processCmdLineArgs()
+        print self._template
+        
+    def _processCmdLineArgs(self):
+        try:
+            self._opts, self._args = getopt.getopt(
+                self._cmdLineArgs, 'h', ['help',
+                                            'env',
+                                            'pickle=',
+                                            ])
+
+        except getopt.GetoptError, v:
+            # print help information and exit:
+            print v
+            print self.usage()
+            sys.exit(2)
+        
+        for o, a in self._opts:
+            if o in ('-h','--help'):
+                print self.usage()
+                sys.exit()
+            if o == '--env':
+                self._template.searchList().insert(0, os.environ)
+            if o == '--pickle':
+                if a == '-':
+                    unpickled = load(sys.stdin)
+                    self._template.searchList().insert(0, unpickled)
+                else:
+                    f = open(a)
+                    unpickled = load(f)
+                    f.close()
+                    self._template.searchList().insert(0, unpickled)
+
+    def usage(self):
+        return """Cheetah %(Version)s template module command-line interface
+
+Usage
+-----
+  %(scriptName)s [OPTION]
+
+Options
+-------
+  -h, --help                 Print this help information
+  
+  --env                      Use shell ENVIRONMENT variables to fill the
+                             $placeholders in the template.
+                             
+  --pickle <file>            Use a variables from a dictionary stored in Python
+                             pickle file to fill $placeholders in the template.
+                             If <file> is - stdin is used: 
+                             '%(scriptName)s --pickle -'
+
+Description
+-----------
+
+This interface allows you to execute a Cheetah template from the command line
+and collect the output.  It can prepend the shell ENVIRONMENT or a pickled
+Python dictionary to the template's $placeholder searchList, overriding the
+defaults for the $placeholders.
+
+""" % {'scriptName':self._scriptName,
+       'Version':Version,
+       }
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,273 @@
+#!/usr/bin/env python
+
+
+"""A Skeleton HTML page template, that provides basic structure and utility methods.
+"""
+
+
+##################################################
+## DEPENDENCIES
+import sys
+import os
+import os.path
+from os.path import getmtime, exists
+import time
+import types
+import __builtin__
+from Cheetah.Version import MinCompatibleVersion as RequiredCheetahVersion
+from Cheetah.Version import MinCompatibleVersionTuple as RequiredCheetahVersionTuple
+from Cheetah.Template import Template
+from Cheetah.DummyTransaction import DummyTransaction
+from Cheetah.NameMapper import NotFound, valueForName, valueFromSearchList, valueFromFrameOrSearchList
+from Cheetah.CacheRegion import CacheRegion
+import Cheetah.Filters as Filters
+import Cheetah.ErrorCatchers as ErrorCatchers
+from Cheetah.Templates._SkeletonPage import _SkeletonPage
+
+##################################################
+## MODULE CONSTANTS
+try:
+    True, False
+except NameError:
+    True, False = (1==1), (1==0)
+VFFSL=valueFromFrameOrSearchList
+VFSL=valueFromSearchList
+VFN=valueForName
+currentTime=time.time
+__CHEETAH_version__ = '2.0rc6'
+__CHEETAH_versionTuple__ = (2, 0, 0, 'candidate', 6)
+__CHEETAH_genTime__ = 1139107954.3640411
+__CHEETAH_genTimestamp__ = 'Sat Feb  4 18:52:34 2006'
+__CHEETAH_src__ = 'src/Templates/SkeletonPage.tmpl'
+__CHEETAH_srcLastModified__ = 'Mon Oct  7 11:37:30 2002'
+__CHEETAH_docstring__ = 'Autogenerated by CHEETAH: The Python-Powered Template Engine'
+
+if __CHEETAH_versionTuple__ < RequiredCheetahVersionTuple:
+    raise AssertionError(
+      'This template was compiled with Cheetah version'
+      ' %s. Templates compiled before version %s must be recompiled.'%(
+         __CHEETAH_version__, RequiredCheetahVersion))
+
+##################################################
+## CLASSES
+
+class SkeletonPage(_SkeletonPage):
+
+    ##################################################
+    ## CHEETAH GENERATED METHODS
+
+
+    def __init__(self, *args, **KWs):
+
+        _SkeletonPage.__init__(self, *args, **KWs)
+        if not self._CHEETAH__instanceInitialized:
+            cheetahKWArgs = {}
+            allowedKWs = 'searchList namespaces filter filtersLib errorCatcher'.split()
+            for k,v in KWs.items():
+                if k in allowedKWs: cheetahKWArgs[k] = v
+            self._initCheetahInstance(**cheetahKWArgs)
+        
+
+    def writeHeadTag(self, **KWS):
+
+
+
+        ## CHEETAH: generated from #block writeHeadTag at line 22, col 1.
+        trans = KWS.get("trans")
+        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
+            trans = self.transaction # is None unless self.awake() was called
+        if not trans:
+            trans = DummyTransaction()
+            _dummyTrans = True
+        else: _dummyTrans = False
+        write = trans.response().write
+        SL = self._CHEETAH__searchList
+        _filter = self._CHEETAH__currentFilter
+        
+        ########################################
+        ## START - generated method body
+        
+        write('<head>\n<title>')
+        _v = VFFSL(SL,"title",True) # '$title' on line 24, col 8
+        if _v is not None: write(_filter(_v, rawExpr='$title')) # from line 24, col 8.
+        write('</title>\n')
+        _v = VFFSL(SL,"metaTags",True) # '$metaTags' on line 25, col 1
+        if _v is not None: write(_filter(_v, rawExpr='$metaTags')) # from line 25, col 1.
+        write(' \n')
+        _v = VFFSL(SL,"stylesheetTags",True) # '$stylesheetTags' on line 26, col 1
+        if _v is not None: write(_filter(_v, rawExpr='$stylesheetTags')) # from line 26, col 1.
+        write(' \n')
+        _v = VFFSL(SL,"javascriptTags",True) # '$javascriptTags' on line 27, col 1
+        if _v is not None: write(_filter(_v, rawExpr='$javascriptTags')) # from line 27, col 1.
+        write('\n</head>\n')
+        
+        ########################################
+        ## END - generated method body
+        
+        return _dummyTrans and trans.response().getvalue() or ""
+        
+
+    def writeBody(self, **KWS):
+
+
+
+        ## CHEETAH: generated from #block writeBody at line 36, col 1.
+        trans = KWS.get("trans")
+        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
+            trans = self.transaction # is None unless self.awake() was called
+        if not trans:
+            trans = DummyTransaction()
+            _dummyTrans = True
+        else: _dummyTrans = False
+        write = trans.response().write
+        SL = self._CHEETAH__searchList
+        _filter = self._CHEETAH__currentFilter
+        
+        ########################################
+        ## START - generated method body
+        
+        write('This skeleton page has no flesh. Its body needs to be implemented.\n')
+        
+        ########################################
+        ## END - generated method body
+        
+        return _dummyTrans and trans.response().getvalue() or ""
+        
+
+    def respond(self, trans=None):
+
+
+
+        ## CHEETAH: main method generated for this template
+        if (not trans and not self._CHEETAH__isBuffering and not callable(self.transaction)):
+            trans = self.transaction # is None unless self.awake() was called
+        if not trans:
+            trans = DummyTransaction()
+            _dummyTrans = True
+        else: _dummyTrans = False
+        write = trans.response().write
+        SL = self._CHEETAH__searchList
+        _filter = self._CHEETAH__currentFilter
+        
+        ########################################
+        ## START - generated method body
+        
+        
+        ## START CACHE REGION: ID=header. line 6, col 1 in the source.
+        _RECACHE_header = False
+        _cacheRegion_header = self.getCacheRegion(regionID='header', cacheInfo={'type': 2, 'id': 'header'})
+        if _cacheRegion_header.isNew():
+            _RECACHE_header = True
+        _cacheItem_header = _cacheRegion_header.getCacheItem('header')
+        if _cacheItem_header.hasExpired():
+            _RECACHE_header = True
+        if (not _RECACHE_header) and _cacheItem_header.getRefreshTime():
+            try:
+                _output = _cacheItem_header.renderOutput()
+            except KeyError:
+                _RECACHE_header = True
+            else:
+                write(_output)
+                del _output
+        if _RECACHE_header or not _cacheItem_header.getRefreshTime():
+            _orig_transheader = trans
+            trans = _cacheCollector_header = DummyTransaction()
+            write = _cacheCollector_header.response().write
+            _v = VFFSL(SL,"docType",True) # '$docType' on line 7, col 1
+            if _v is not None: write(_filter(_v, rawExpr='$docType')) # from line 7, col 1.
+            write('\n')
+            _v = VFFSL(SL,"htmlTag",True) # '$htmlTag' on line 8, col 1
+            if _v is not None: write(_filter(_v, rawExpr='$htmlTag')) # from line 8, col 1.
+            write('''
+<!-- This document was autogenerated by Cheetah(http://CheetahTemplate.org). 
+Do not edit it directly!
+
+Copyright ''')
+            _v = VFFSL(SL,"currentYr",True) # '$currentYr' on line 12, col 11
+            if _v is not None: write(_filter(_v, rawExpr='$currentYr')) # from line 12, col 11.
+            write(' - ')
+            _v = VFFSL(SL,"siteCopyrightName",True) # '$siteCopyrightName' on line 12, col 24
+            if _v is not None: write(_filter(_v, rawExpr='$siteCopyrightName')) # from line 12, col 24.
+            write(' - All Rights Reserved.\nFeel free to copy any javascript or html you like on this site,\nprovided you remove all links and/or references to ')
+            _v = VFFSL(SL,"siteDomainName",True) # '$siteDomainName' on line 14, col 52
+            if _v is not None: write(_filter(_v, rawExpr='$siteDomainName')) # from line 14, col 52.
+            write('''
+However, please do not copy any content or images without permission.
+
+''')
+            _v = VFFSL(SL,"siteCredits",True) # '$siteCredits' on line 17, col 1
+            if _v is not None: write(_filter(_v, rawExpr='$siteCredits')) # from line 17, col 1.
+            write('''
+
+-->
+
+
+''')
+            self.writeHeadTag(trans=trans)
+            write('\n')
+            trans = _orig_transheader
+            write = trans.response().write
+            _cacheData = _cacheCollector_header.response().getvalue()
+            _cacheItem_header.setData(_cacheData)
+            write(_cacheData)
+            del _cacheData
+            del _cacheCollector_header
+            del _orig_transheader
+        ## END CACHE REGION: header
+        
+        write('\n')
+        _v = VFFSL(SL,"bodyTag",True) # '$bodyTag' on line 34, col 1
+        if _v is not None: write(_filter(_v, rawExpr='$bodyTag')) # from line 34, col 1.
+        write('\n\n')
+        self.writeBody(trans=trans)
+        write('''
+</body>
+</html>
+
+
+
+''')
+        
+        ########################################
+        ## END - generated method body
+        
+        return _dummyTrans and trans.response().getvalue() or ""
+        
+    ##################################################
+    ## CHEETAH GENERATED ATTRIBUTES
+
+
+    _CHEETAH__instanceInitialized = False
+
+    _CHEETAH_version = __CHEETAH_version__
+
+    _CHEETAH_versionTuple = __CHEETAH_versionTuple__
+
+    _CHEETAH_genTime = __CHEETAH_genTime__
+
+    _CHEETAH_genTimestamp = __CHEETAH_genTimestamp__
+
+    _CHEETAH_src = __CHEETAH_src__
+
+    _CHEETAH_srcLastModified = __CHEETAH_srcLastModified__
+
+    _mainCheetahMethod_for_SkeletonPage= 'respond'
+
+## END CLASS DEFINITION
+
+if not hasattr(SkeletonPage, '_initCheetahAttributes'):
+    templateAPIClass = getattr(SkeletonPage, '_CHEETAH_templateClass', Template)
+    templateAPIClass._addCheetahPlumbingCodeToClass(SkeletonPage)
+
+
+# CHEETAH was developed by Tavis Rudd and Mike Orr
+# with code, advice and input from many other volunteers.
+# For more information visit http://www.CheetahTemplate.org/
+
+##################################################
+## if run from command line:
+if __name__ == '__main__':
+    from Cheetah.TemplateCmdLineIface import CmdLineIface
+    CmdLineIface(templateObj=SkeletonPage()).run()
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/SkeletonPage.tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+##doc-module: A Skeleton HTML page template, that provides basic structure and utility methods.
+################################################################################
+#extends Cheetah.Templates._SkeletonPage
+#implements respond
+################################################################################
+#cache id='header'
+$docType
+$htmlTag
+<!-- This document was autogenerated by Cheetah(http://CheetahTemplate.org). 
+Do not edit it directly!
+
+Copyright $currentYr - $siteCopyrightName - All Rights Reserved.
+Feel free to copy any javascript or html you like on this site,
+provided you remove all links and/or references to $siteDomainName
+However, please do not copy any content or images without permission.
+
+$siteCredits
+
+-->
+
+
+#block writeHeadTag
+<head>
+<title>$title</title>
+$metaTags 
+$stylesheetTags 
+$javascriptTags
+</head>
+#end block writeHeadTag
+
+#end cache header
+#################
+
+$bodyTag
+
+#block writeBody
+This skeleton page has no flesh. Its body needs to be implemented.
+#end block writeBody
+
+</body>
+</html>
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/_SkeletonPage.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/_SkeletonPage.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/_SkeletonPage.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,216 @@
+#!/usr/bin/env python
+# $Id: _SkeletonPage.py,v 1.13 2002/10/01 17:52:02 tavis_rudd Exp $
+"""A baseclass for the SkeletonPage template
+
+Meta-Data
+==========
+Author: Tavis Rudd <tavis at damnsimple.com>,
+Version: $Revision: 1.13 $
+Start Date: 2001/04/05
+Last Revision Date: $Date: 2002/10/01 17:52:02 $
+"""
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.13 $"[11:-2]
+
+##################################################
+## DEPENDENCIES ##
+
+import time, types, os, sys
+
+# intra-package imports ...
+from Cheetah.Template import Template
+
+
+##################################################
+## GLOBALS AND CONSTANTS ##
+
+True = (1==1)
+False = (0==1)
+
+##################################################
+## CLASSES ##
+        
+class _SkeletonPage(Template):
+    """A baseclass for the SkeletonPage template"""
+
+    docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" ' + \
+              '"http://www.w3.org/TR/html4/loose.dtd">'
+    
+    # docType = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ' + \
+    #'"http://www.w3.org/TR/xhtml1l/DTD/transitional.dtd">'
+        
+    title = ''
+    siteDomainName = 'www.example.com'
+    siteCredits = 'Designed & Implemented by Tavis Rudd'
+    siteCopyrightName = "Tavis Rudd"
+    htmlTag = '<html>'
+    
+    def __init__(self, *args, **KWs):
+        Template.__init__(self, *args, **KWs)
+        self._metaTags = {'HTTP-EQUIV':{'keywords':'Cheetah',
+                                        'Content-Type':'text/html; charset=iso-8859-1',
+                                        }, 
+                    'NAME':{'generator':'Cheetah: The Python-Powered Template Engine'}
+                    }
+        # metaTags = {'HTTP_EQUIV':{'test':1234}, 'NAME':{'test':1234,'test2':1234} }
+        self._stylesheets = {}
+        # stylesheets = {'.cssClassName':'stylesheetCode'}
+        self._stylesheetsOrder = []
+        # stylesheetsOrder = ['.cssClassName',]
+        self._stylesheetLibs = {}
+        # stylesheetLibs = {'libName':'libSrcPath'}
+        self._javascriptLibs = {}
+        self._javascriptTags = {}
+        # self._javascriptLibs = {'libName':'libSrcPath'}
+        self._bodyTagAttribs = {}
+
+    def metaTags(self):
+        """Return a formatted vesion of the self._metaTags dictionary, using the
+        formatMetaTags function from Cheetah.Macros.HTML"""
+        
+        return self.formatMetaTags(self._metaTags)
+    
+    def stylesheetTags(self):
+        """Return a formatted version of the self._stylesheetLibs and
+        self._stylesheets dictionaries.  The keys in self._stylesheets must
+        be listed in the order that they should appear in the list
+        self._stylesheetsOrder, to ensure that the style rules are defined in
+        the correct order."""
+        
+        stylesheetTagsTxt = ''
+        for title, src in self._stylesheetLibs.items():
+            stylesheetTagsTxt += '<link rel="stylesheet" type="text/css" href="' + str(src) + '" />\n'
+
+        if not self._stylesheetsOrder:
+            return stylesheetTagsTxt
+        
+        stylesheetTagsTxt += '<style type="text/css"><!--\n'
+        for identifier in self._stylesheetsOrder:
+            if not self._stylesheets.has_key(identifier):
+                warning = '# the identifier ' + identifier + \
+                          'was in stylesheetsOrder, but not in stylesheets'
+                print warning
+                stylesheetTagsTxt += warning
+                continue
+                    
+            attribsDict = self._stylesheets[identifier]
+            cssCode = ''
+            attribCode = ''
+            for k, v in attribsDict.items():
+                attribCode += str(k) + ': ' + str(v) + '; '
+            attribCode = attribCode[:-2] # get rid of the last semicolon
+                
+            cssCode = '\n' + identifier + ' {' +  attribCode + '}'
+            stylesheetTagsTxt += cssCode
+            
+        stylesheetTagsTxt += '\n//--></style>\n'
+
+        return stylesheetTagsTxt
+
+    def javascriptTags(self):
+        """Return a formatted version of the javascriptTags and
+        javascriptLibs dictionaries.  Each value in javascriptTags
+        should be a either a code string to include, or a list containing the
+        JavaScript version number and the code string. The keys can be anything.
+        The same applies for javascriptLibs, but the string should be the
+        SRC filename rather than a code string."""
+        
+        javascriptTagsTxt = []
+        for key, details in self._javascriptTags.items():
+            if type(details) not in (types.ListType, types.TupleType):
+                details = ['',details]
+                
+            javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
+                                  '" type="text/javascript"><!--\n',
+                                  str(details[0]), '\n//--></script>\n']
+
+
+        for key, details in self._javascriptLibs.items():
+            if type(details) not in (types.ListType, types.TupleType):
+                details = ['',details]
+
+            javascriptTagsTxt += ['<script language="JavaScript', str(details[0]),
+                                  '" type="text/javascript" src="',
+                                  str(details[1]), '" />\n']
+        return ''.join(javascriptTagsTxt)
+    
+    def bodyTag(self):
+        """Create a body tag from the entries in the dict bodyTagAttribs."""
+        return self.formHTMLTag('body', self._bodyTagAttribs)
+
+
+    def imgTag(self, src, alt='', width=None, height=None, border=0):
+        
+        """Dynamically generate an image tag.  Cheetah will try to convert the
+        src argument to a WebKit serverSidePath relative to the servlet's
+        location. If width and height aren't specified they are calculated using
+        PIL or ImageMagick if available."""
+        
+        src = self.normalizePath(src)
+        
+
+        if not width or not height:
+            try:                    # see if the dimensions can be calc'd with PIL
+                import Image
+                im = Image.open(src)
+                calcWidth, calcHeight = im.size
+                del im
+                if not width: width = calcWidth
+                if not height: height = calcHeight
+
+            except:
+                try:                # try imageMagick instead
+                    calcWidth, calcHeight = os.popen(
+                        'identify -format "%w,%h" ' + src).read().split(',')
+                    if not width: width = calcWidth
+                    if not height: height = calcHeight
+        
+                except:
+                    pass
+                
+        if width and height:
+            return ''.join(['<img src="', src, '" width="', str(width), '" height="', str(height),
+                           '" alt="', alt, '" border="', str(border), '" />'])
+        elif width:
+            return ''.join(['<img src="', src, '" width="', str(width),
+                           '" alt="', alt, '" border="', str(border), '" />'])
+        elif height:
+            return ''.join(['<img src="', src, '" height="', str(height),
+                           '" alt="', alt, '" border="', str(border), '" />'])
+        else:
+            return ''.join(['<img src="', src, '" alt="', alt, '" border="', str(border),'" />'])
+
+
+    def currentYr(self):
+        """Return a string representing the current yr."""
+        return time.strftime("%Y",time.localtime(time.time()))
+    
+    def currentDate(self, formatString="%b %d, %Y"):
+        """Return a string representing the current localtime."""
+        return time.strftime(formatString,time.localtime(time.time()))
+    
+    def spacer(self, width=1,height=1):
+        return '<img src="spacer.gif" width="%s" height="%s" alt="" />'% (str(width), str(height))
+    
+    def formHTMLTag(self, tagName, attributes={}):
+        """returns a string containing an HTML <tag> """
+        tagTxt = ['<', tagName.lower()]
+        for name, val in attributes.items():
+            tagTxt += [' ', name.lower(), '="', str(val),'"']
+        tagTxt.append('>')
+        return ''.join(tagTxt)
+    
+    def formatMetaTags(self, metaTags):
+        """format a dict of metaTag definitions into an HTML version"""
+        metaTagsTxt = []
+        if metaTags.has_key('HTTP-EQUIV'):
+            for http_equiv, contents in metaTags['HTTP-EQUIV'].items():
+                metaTagsTxt += ['<meta http-equiv="', str(http_equiv), '" content="',
+                                str(contents), '" />\n']
+                
+        if metaTags.has_key('NAME'):
+            for name, contents in metaTags['NAME'].items():
+                metaTagsTxt += ['<meta name="', str(name), '" content="', str(contents),
+                                '" />\n']
+        return ''.join(metaTagsTxt)
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Templates/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#!/usr/bin/env python

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/CheetahWrapper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/CheetahWrapper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/CheetahWrapper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,550 @@
+#!/usr/bin/env python
+'''
+Tests for the 'cheetah' command.
+
+Besides unittest usage, recognizes the following command-line options:
+    --list CheetahWrapper.py
+        List all scenarios that are tested.  The argument is the path
+        of this script.
+     --nodelete
+        Don't delete scratch directory at end.
+     --output
+        Show the output of each subcommand.  (Normally suppressed.)
+'''
+import commands, os, shutil, sys, tempfile
+import unittest_local_copy as unittest
+
+import re                                     # Used by listTests.
+from optparse import OptionParser
+from Cheetah.CheetahWrapper import CheetahWrapper  # Used by NoBackup.
+
+
+DELETE = True # True to clean up after ourselves, False for debugging.
+OUTPUT = False # Normally False, True for debugging.
+
+BACKUP_SUFFIX = CheetahWrapper.BACKUP_SUFFIX
+
+def warn(msg):
+    sys.stderr.write(msg + '\n')
+
+class CFBase(unittest.TestCase):
+    """Base class for "cheetah compile" and "cheetah fill" unit tests.
+    """
+    srcDir = '' # Nonblank to create source directory.
+    subdirs = ('child', 'child/grandkid') # Delete in reverse order.
+    srcFiles = ('a.tmpl', 'child/a.tmpl', 'child/grandkid/a.tmpl')
+    expectError = False # Used by --list option.
+
+    def inform(self, message):
+        if self.verbose:
+            print message
+
+    def setUp(self):
+        """Create the top-level directories, subdirectories and .tmpl
+           files.
+        """
+        I = self.inform
+        # Step 1: Create the scratch directory and chdir into it.
+        self.scratchDir = scratchDir = tempfile.mktemp() 
+        os.mkdir(scratchDir)
+        self.origCwd = os.getcwd()
+        os.chdir(scratchDir)
+        if self.srcDir:
+            os.mkdir(self.srcDir)
+        # Step 2: Create source subdirectories.
+        for dir in self.subdirs:
+            os.mkdir(dir)
+        # Step 3: Create the .tmpl files, each in its proper directory.
+        for fil in self.srcFiles:
+            f = open(fil, 'w')
+            f.write("Hello, world!\n")
+            f.close()
+            
+
+    def tearDown(self):
+        os.chdir(self.origCwd)
+        if DELETE:
+            shutil.rmtree(self.scratchDir, True) # Ignore errors.
+            if os.path.exists(self.scratchDir):
+                warn("Warning: unable to delete scratch directory %s")
+        else:
+            warn("Warning: not deleting scratch directory %s" % self.scratchDir)
+
+
+    def _checkDestFileHelper(self, path, expected, 
+        allowSurroundingText, errmsg):
+        """Low-level helper to check a destination file.
+
+           in : path, string, the destination path.
+                expected, string, the expected contents.
+                allowSurroundingtext, bool, allow the result to contain
+                  additional text around the 'expected' substring?
+                errmsg, string, the error message.  It may contain the
+                  following "%"-operator keys: path, expected, result.
+           out: None
+        """
+        path = os.path.abspath(path)
+        exists = os.path.exists(path)
+        msg = "destination file missing: %s" % path
+        self.failUnless(exists, msg)
+        f = open(path, 'r')
+        result = f.read()
+        f.close()
+        if allowSurroundingText:
+            success = result.find(expected) != -1
+        else:
+            success = result == expected
+        msg = errmsg % locals()
+        self.failUnless(success, msg)
+
+
+    def checkCompile(self, path):
+        # Raw string to prevent "\n" from being converted to a newline.
+        #expected = R"write('Hello, world!\n')"
+        expected = "Hello, world!" # might output a u'' string
+        errmsg = """\
+destination file %(path)s doesn't contain expected substring:
+%(expected)r"""
+        self._checkDestFileHelper(path, expected, True, errmsg)
+
+
+    def checkFill(self, path):
+        expected = "Hello, world!\n"
+        errmsg = """\
+destination file %(path)s contains wrong result.
+Expected %(expected)r
+Found %(result)r"""
+        self._checkDestFileHelper(path, expected, False, errmsg)
+
+
+    def checkSubdirPyInit(self, path):
+        """Verify a destination subdirectory exists and contains an
+           __init__.py file.
+        """
+        exists = os.path.exists(path)
+        msg = "destination subdirectory %s misssing" % path
+        self.failUnless(exists, msg)
+        initPath = os.path.join(path, "__init__.py")
+        exists = os.path.exists(initPath)
+        msg = "destination init file missing: %s" % initPath
+        self.failUnless(exists, msg)
+
+
+    def checkNoBackup(self, path):
+        """Verify 'path' does not exist.  (To check --nobackup.)
+        """
+        exists = os.path.exists(path)
+        msg = "backup file exists in spite of --nobackup: %s" % path
+        self.failIf(exists, msg)
+
+    
+    def go(self, cmd, expectedStatus=0, expectedOutputSubstring=None):
+        """Run a "cheetah compile" or "cheetah fill" subcommand.
+
+           in : cmd, string, the command to run.
+                expectedStatus, int, subcommand's expected output status.
+                  0 if the subcommand is expected to succeed, 1-255 otherwise.
+                expectedOutputSubstring, string, substring which much appear
+                  in the standard output or standard error.  None to skip this
+                  test.
+           out: None.
+        """
+        # Use commands.getstatusoutput instead of os.system so
+        # that we can mimic ">/dev/null 2>/dev/null" even on 
+        # non-Unix platforms.
+        exit, output = commands.getstatusoutput(cmd)
+        status, signal = divmod(exit, 256)
+        if OUTPUT:
+            if output.endswith("\n"):
+                output = output[:-1]
+            print
+            print "SUBCOMMAND:", cmd
+            print output
+            print
+        msg = "subcommand killed by signal %d: %s" % (signal, cmd)
+        self.failUnlessEqual(signal, 0, msg)
+        msg = "subcommand exit status %d: %s" % (status, cmd)
+        if status!=expectedStatus:
+            print output
+        self.failUnlessEqual(status, expectedStatus, msg)
+        if expectedOutputSubstring is not None:
+            msg = "substring %r not found in subcommand output: %s" % \
+                (expectedOutputSubstring, cmd)
+            substringTest = output.find(expectedOutputSubstring) != -1
+            self.failUnless(substringTest, msg)
+
+
+    def goExpectError(self, cmd):
+        """Run a subcommand and expect it to fail.
+
+           in : cmd, string, the command to run.
+           out: None.
+        """
+        # Use commands.getstatusoutput instead of os.system so
+        # that we can mimic ">/dev/null 2>/dev/null" even on 
+        # non-Unix platforms.
+        exit, output = commands.getstatusoutput(cmd)
+        status, signal = divmod(exit, 256)
+        msg = "subcommand killed by signal %s: %s" % (signal, cmd)
+        self.failUnlessEqual(signal, 0, msg) # Signal must be 0.
+        msg = "subcommand exit status %s: %s" % (status, cmd)
+        self.failIfEqual(status, 0, msg) # Status must *not* be 0.
+        if OUTPUT:
+            if output.endswith("\n"):
+                output = output[:-1]
+            print
+            print "SUBCOMMAND:", cmd
+            print output
+            print
+
+
+class CFIdirBase(CFBase):
+    """Subclass for tests with --idir.
+    """
+    srcDir = 'SRC'
+    subdirs = ('SRC/child', 'SRC/child/grandkid') # Delete in reverse order.
+    srcFiles = ('SRC/a.tmpl', 'SRC/child/a.tmpl', 'SRC/child/grandkid/a.tmpl')
+
+
+
+##################################################
+## TEST CASE CLASSES
+
+class OneFile(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile a.tmpl")
+        self.checkCompile("a.py")
+
+    def testFill(self):
+        self.go("cheetah fill a.tmpl")
+        self.checkFill("a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt a.tmpl")
+        self.checkFill("a.txt")
+
+
+class OneFileNoExtension(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile a")
+        self.checkCompile("a.py")
+
+    def testFill(self):
+        self.go("cheetah fill a")
+        self.checkFill("a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt a")
+        self.checkFill("a.txt")
+
+
+class SplatTmpl(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile *.tmpl")
+        self.checkCompile("a.py")
+
+    def testFill(self):
+        self.go("cheetah fill *.tmpl")
+        self.checkFill("a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt *.tmpl")
+        self.checkFill("a.txt")
+
+class ThreeFilesWithSubdirectories(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile a.tmpl child/a.tmpl child/grandkid/a.tmpl")
+        self.checkCompile("a.py")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill a.tmpl child/a.tmpl child/grandkid/a.tmpl")
+        self.checkFill("a.html")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt a.tmpl child/a.tmpl child/grandkid/a.tmpl")
+        self.checkFill("a.txt")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class ThreeFilesWithSubdirectoriesNoExtension(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile a child/a child/grandkid/a")
+        self.checkCompile("a.py")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill a child/a child/grandkid/a")
+        self.checkFill("a.html")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt a child/a child/grandkid/a")
+        self.checkFill("a.txt")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class SplatTmplWithSubdirectories(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile *.tmpl child/*.tmpl child/grandkid/*.tmpl")
+        self.checkCompile("a.py")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill *.tmpl child/*.tmpl child/grandkid/*.tmpl")
+        self.checkFill("a.html")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill --oext txt *.tmpl child/*.tmpl child/grandkid/*.tmpl")
+        self.checkFill("a.txt")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class OneFileWithOdir(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile --odir DEST a.tmpl")
+        self.checkSubdirPyInit("DEST")
+        self.checkCompile("DEST/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill --odir DEST a.tmpl")
+        self.checkFill("DEST/a.html")
+
+    def testText(self):
+        self.go("cheetah fill --odir DEST --oext txt a.tmpl")
+        self.checkFill("DEST/a.txt")
+
+
+class VarietyWithOdir(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
+        self.checkSubdirPyInit("DEST")
+        self.checkSubdirPyInit("DEST/child")
+        self.checkSubdirPyInit("DEST/child/grandkid")
+        self.checkCompile("DEST/a.py")
+        self.checkCompile("DEST/child/a.py")
+        self.checkCompile("DEST/child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill --odir DEST a.tmpl child/a child/grandkid/*.tmpl")
+        self.checkFill("DEST/a.html")
+        self.checkFill("DEST/child/a.html")
+        self.checkFill("DEST/child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill --odir DEST --oext txt a.tmpl child/a child/grandkid/*.tmpl")
+        self.checkFill("DEST/a.txt")
+        self.checkFill("DEST/child/a.txt")
+        self.checkFill("DEST/child/grandkid/a.txt")
+
+
+class RecurseExplicit(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile -R child")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill -R child")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill -R --oext txt child")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class RecurseImplicit(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile -R")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill -R")
+        self.checkFill("a.html")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill -R --oext txt")
+        self.checkFill("a.txt")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class RecurseExplicitWIthOdir(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile -R --odir DEST child")
+        self.checkSubdirPyInit("DEST/child")
+        self.checkSubdirPyInit("DEST/child/grandkid")
+        self.checkCompile("DEST/child/a.py")
+        self.checkCompile("DEST/child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill -R --odir DEST child")
+        self.checkFill("DEST/child/a.html")
+        self.checkFill("DEST/child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill -R --odir DEST --oext txt child")
+        self.checkFill("DEST/child/a.txt")
+        self.checkFill("DEST/child/grandkid/a.txt")
+
+
+class Flat(CFBase):
+    def testCompile(self):
+        self.go("cheetah compile --flat child/a.tmpl")
+        self.checkCompile("a.py")
+
+    def testFill(self):
+        self.go("cheetah fill --flat child/a.tmpl")
+        self.checkFill("a.html")
+
+    def testText(self):
+        self.go("cheetah fill --flat --oext txt child/a.tmpl")
+        self.checkFill("a.txt")
+
+
+class FlatRecurseCollision(CFBase):
+    expectError = True
+
+    def testCompile(self):
+        self.goExpectError("cheetah compile -R --flat")
+
+    def testFill(self):
+        self.goExpectError("cheetah fill -R --flat")
+
+    def testText(self):
+        self.goExpectError("cheetah fill -R --flat")
+
+
+class IdirRecurse(CFIdirBase):
+    def testCompile(self):
+        self.go("cheetah compile -R --idir SRC child")
+        self.checkSubdirPyInit("child")
+        self.checkSubdirPyInit("child/grandkid")
+        self.checkCompile("child/a.py")
+        self.checkCompile("child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill -R --idir SRC child")
+        self.checkFill("child/a.html")
+        self.checkFill("child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill -R --idir SRC --oext txt child")
+        self.checkFill("child/a.txt")
+        self.checkFill("child/grandkid/a.txt")
+
+
+class IdirOdirRecurse(CFIdirBase):
+    def testCompile(self):
+        self.go("cheetah compile -R --idir SRC --odir DEST child")
+        self.checkSubdirPyInit("DEST/child")
+        self.checkSubdirPyInit("DEST/child/grandkid")
+        self.checkCompile("DEST/child/a.py")
+        self.checkCompile("DEST/child/grandkid/a.py")
+
+    def testFill(self):
+        self.go("cheetah fill -R --idir SRC --odir DEST child")
+        self.checkFill("DEST/child/a.html")
+        self.checkFill("DEST/child/grandkid/a.html")
+
+    def testText(self):
+        self.go("cheetah fill -R --idir SRC --odir DEST --oext txt child")
+        self.checkFill("DEST/child/a.txt")
+        self.checkFill("DEST/child/grandkid/a.txt")
+
+
+class IdirFlatRecurseCollision(CFIdirBase):
+    expectError = True
+
+    def testCompile(self):
+        self.goExpectError("cheetah compile -R --flat --idir SRC")
+
+    def testFill(self):
+        self.goExpectError("cheetah fill -R --flat --idir SRC")
+
+    def testText(self):
+        self.goExpectError("cheetah fill -R --flat --idir SRC --oext txt")
+
+
+class NoBackup(CFBase):
+    """Run the command twice each time and verify a backup file is 
+       *not* created.
+    """
+    def testCompile(self):
+        self.go("cheetah compile --nobackup a.tmpl")
+        self.go("cheetah compile --nobackup a.tmpl")
+        self.checkNoBackup("a.py" + BACKUP_SUFFIX)
+
+    def testFill(self):
+        self.go("cheetah fill --nobackup a.tmpl")
+        self.go("cheetah fill --nobackup a.tmpl")
+        self.checkNoBackup("a.html" + BACKUP_SUFFIX)
+
+    def testText(self):
+        self.go("cheetah fill --nobackup --oext txt a.tmpl")
+        self.go("cheetah fill --nobackup --oext txt a.tmpl")
+        self.checkNoBackup("a.txt" + BACKUP_SUFFIX)
+
+def listTests(cheetahWrapperFile):
+    """cheetahWrapperFile, string, path of this script.
+
+       XXX TODO: don't print test where expectError is true.
+    """
+    rx = re.compile( R'self\.go\("(.*?)"\)' )
+    f = open(cheetahWrapperFile)
+    while 1:
+        lin = f.readline()
+        if not lin:
+            break
+        m = rx.search(lin)
+        if m:
+            print m.group(1)
+    f.close()
+
+def main():
+    global DELETE, OUTPUT
+    parser = OptionParser()
+    parser.add_option("--list", action="store", dest="listTests")
+    parser.add_option("--nodelete", action="store_true")
+    parser.add_option("--output", action="store_true")
+    # The following options are passed to unittest.
+    parser.add_option("-e", "--explain", action="store_true")
+    parser.add_option("-v", "--verbose", action="store_true")
+    parser.add_option("-q", "--quiet", action="store_true")
+    opts, files = parser.parse_args()
+    if opts.nodelete:
+        DELETE = False
+    if opts.output:
+        OUTPUT = True
+    if opts.listTests:
+        listTests(opts.listTests)
+    else:
+        # Eliminate script-specific command-line arguments to prevent
+        # errors in unittest.
+        del sys.argv[1:]
+        for opt in ("explain", "verbose", "quiet"):
+            if getattr(opts, opt):
+                sys.argv.append("--" + opt)
+        sys.argv.extend(files)
+        unittest.main()
+        
+if __name__ == '__main__':
+    main()
+
+# vim: sw=4 ts=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Filters.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Filters.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Filters.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,68 @@
+#!/usr/bin/env python
+
+import sys
+
+import Cheetah.Template
+import Cheetah.Filters
+
+import unittest_local_copy as unittest 
+
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
+class BasicMarkdownFilterTest(unittest.TestCase):
+    '''
+        Test that our markdown filter works
+    '''
+    def test_BasicHeader(self):
+        template = '''  
+#from Cheetah.Filters import Markdown
+#transform Markdown
+$foo
+
+Header
+======
+        '''
+        expected = '''<p>bar</p>
+<h1>Header</h1>'''
+        try:
+            template = Cheetah.Template.Template(template, searchList=[{'foo' : 'bar'}])
+            template = str(template)
+            assert template == expected
+        except Exception, ex:
+            if ex.__class__.__name__ == 'MarkdownException' and majorVer == 2 and minorVer < 5:
+                print '>>> NOTE: Support for the Markdown filter will be broken for you. Markdown says: %s' % ex
+                return
+            raise
+
+
+class BasicCodeHighlighterFilterTest(unittest.TestCase):
+    '''
+        Test that our code highlighter filter works
+    '''
+    def test_Python(self):
+        template = '''  
+#from Cheetah.Filters import CodeHighlighter
+#transform CodeHighlighter
+
+def foo(self):
+    return '$foo'
+        '''
+        template = Cheetah.Template.Template(template, searchList=[{'foo' : 'bar'}])
+        template = str(template)
+        assert template, (template, 'We should have some content here...')
+
+    def test_Html(self):
+        template = '''  
+#from Cheetah.Filters import CodeHighlighter
+#transform CodeHighlighter
+
+<html><head></head><body>$foo</body></html>
+        '''
+        template = Cheetah.Template.Template(template, searchList=[{'foo' : 'bar'}])
+        template = str(template)
+        assert template, (template, 'We should have some content here...')
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/NameMapper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/NameMapper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/NameMapper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,539 @@
+#!/usr/bin/env python
+# $Id: NameMapper.py,v 1.11 2006/01/15 20:45:22 tavis_rudd Exp $
+"""NameMapper Tests
+
+Meta-Data
+================================================================================
+Author: Tavis Rudd <tavis at damnsimple.com>,
+Version: $Revision: 1.11 $
+Start Date: 2001/10/01
+Last Revision Date: $Date: 2006/01/15 20:45:22 $
+"""
+from __future__ import generators
+__author__ = "Tavis Rudd <tavis at damnsimple.com>"
+__revision__ = "$Revision: 1.11 $"[11:-2]
+import sys
+import types
+import os
+import os.path
+
+import unittest_local_copy as unittest
+from Cheetah.NameMapper import NotFound, valueForKey, \
+     valueForName, valueFromSearchList, valueFromFrame, valueFromFrameOrSearchList
+
+
+##################################################
+## TEST DATA FOR USE IN THE TEMPLATES ##
+
+class DummyClass:
+    classVar1 = 123
+
+    def __init__(self):
+        self.instanceVar1 = 123
+        
+    def __str__(self):
+        return 'object'
+
+    def meth(self, arg="arff"):
+        return str(arg)
+
+    def meth1(self, arg="doo"):
+        return arg
+
+    def meth2(self, arg1="a1", arg2="a2"):
+        raise ValueError
+
+    def meth3(self):
+        """Tests a bug that Jeff Johnson reported on Oct 1, 2001"""
+        
+        x = 'A string'
+        try:
+            for i in [1,2,3,4]:
+                if x == 2:	
+                    pass
+                
+                if x == 'xx':
+                    pass
+            return x
+        except:
+            raise
+
+
+def dummyFunc(arg="Scooby"):
+    return arg
+
+def funcThatRaises():
+    raise ValueError
+
+                 
+testNamespace = {
+    'aStr':'blarg',
+    'anInt':1,
+    'aFloat':1.5,
+    'aDict': {'one':'item1',
+              'two':'item2',
+              'nestedDict':{'one':'nestedItem1',
+                            'two':'nestedItem2',
+                            'funcThatRaises':funcThatRaises,
+                            'aClass': DummyClass,
+                            },
+              'nestedFunc':dummyFunc,
+              },
+    'aClass': DummyClass,    
+    'aFunc': dummyFunc,
+    'anObj': DummyClass(),
+    'aMeth': DummyClass().meth1,
+    'none' : None,  
+    'emptyString':'',
+    'funcThatRaises':funcThatRaises,
+    }
+    
+autoCallResults = {'aFunc':'Scooby',
+                   'aMeth':'doo',
+                   }
+
+results = testNamespace.copy()
+results.update({'anObj.meth1':'doo',
+                'aDict.one':'item1',
+                'aDict.nestedDict':testNamespace['aDict']['nestedDict'],
+                'aDict.nestedDict.one':'nestedItem1',
+                'aDict.nestedDict.aClass':DummyClass,
+                'aDict.nestedFunc':'Scooby',
+                'aClass.classVar1':123,
+                'anObj.instanceVar1':123,
+                'anObj.meth3':'A string',
+                })
+
+for k in testNamespace.keys():
+    # put them in the globals for the valueFromFrame tests
+    exec '%s = testNamespace[k]'%k
+
+##################################################
+## TEST BASE CLASSES
+
+class NameMapperTest(unittest.TestCase):
+    failureException = (NotFound,AssertionError)
+    _testNamespace = testNamespace
+    _results = results
+    
+    def namespace(self):
+        return self._testNamespace
+
+    def VFN(self, name, autocall=True):
+        return valueForName(self.namespace(), name, autocall)
+
+    def VFS(self, searchList, name, autocall=True):
+        return valueFromSearchList(searchList, name, autocall)
+
+    
+    # alias to be overriden later
+    get = VFN
+
+    def check(self, name):
+        got = self.get(name)
+        if autoCallResults.has_key(name):
+            expected = autoCallResults[name]
+        else:
+            expected = self._results[name]
+        assert got == expected
+        
+
+##################################################
+## TEST CASE CLASSES
+
+class VFN(NameMapperTest):
+
+    def test1(self):
+        """string in dict lookup"""
+        self.check('aStr')
+
+    def test2(self):
+        """string in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aStr')
+            
+    def test3(self):
+        """int in dict lookup"""
+        self.check('anInt')
+
+    def test4(self):
+        """int in dict lookup in a loop"""
+        for i in range(10):
+            self.check('anInt')
+
+    def test5(self):
+        """float in dict lookup"""
+        self.check('aFloat')
+
+    def test6(self):
+        """float in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aFloat')
+          
+    def test7(self):
+        """class in dict lookup"""
+        self.check('aClass')
+
+    def test8(self):
+        """class in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aClass')
+            
+    def test9(self):
+        """aFunc in dict lookup"""
+        self.check('aFunc')
+
+    def test10(self):
+        """aFunc in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aFunc')
+
+    def test11(self):
+        """aMeth in dict lookup"""
+        self.check('aMeth')
+
+    def test12(self):
+        """aMeth in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aMeth')
+
+    def test13(self):
+        """aMeth in dict lookup"""
+        self.check('aMeth')
+
+    def test14(self):
+        """aMeth in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aMeth')
+
+    def test15(self):
+        """anObj in dict lookup"""
+        self.check('anObj')
+
+    def test16(self):
+        """anObj in dict lookup in a loop"""
+        for i in range(10):
+            self.check('anObj')
+
+    def test17(self):
+        """aDict in dict lookup"""
+        self.check('aDict')
+
+    def test18(self):
+        """aDict in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict')
+
+    def test17(self):
+        """aDict in dict lookup"""
+        self.check('aDict')
+
+    def test18(self):
+        """aDict in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict')
+
+    def test19(self):
+        """aClass.classVar1 in dict lookup"""
+        self.check('aClass.classVar1')
+
+    def test20(self):
+        """aClass.classVar1 in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aClass.classVar1')
+
+
+    def test23(self):
+        """anObj.instanceVar1 in dict lookup"""
+        self.check('anObj.instanceVar1')
+
+    def test24(self):
+        """anObj.instanceVar1 in dict lookup in a loop"""
+        for i in range(10):
+            self.check('anObj.instanceVar1')
+
+    ## tests 22, 25, and 26 removed when the underscored lookup was removed
+
+    def test27(self):
+        """anObj.meth1 in dict lookup"""
+        self.check('anObj.meth1')
+
+    def test28(self):
+        """anObj.meth1 in dict lookup in a loop"""
+        for i in range(10):
+            self.check('anObj.meth1')
+
+    def test29(self):
+        """aDict.one in dict lookup"""
+        self.check('aDict.one')
+
+    def test30(self):
+        """aDict.one in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict.one')
+
+    def test31(self):
+        """aDict.nestedDict in dict lookup"""
+        self.check('aDict.nestedDict')
+
+    def test32(self):
+        """aDict.nestedDict in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict.nestedDict')
+            
+    def test33(self):
+        """aDict.nestedDict.one in dict lookup"""
+        self.check('aDict.nestedDict.one')
+
+    def test34(self):
+        """aDict.nestedDict.one in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict.nestedDict.one')
+            
+    def test35(self):
+        """aDict.nestedFunc in dict lookup"""
+        self.check('aDict.nestedFunc')
+
+    def test36(self):
+        """aDict.nestedFunc in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict.nestedFunc')
+
+    def test37(self):
+        """aDict.nestedFunc in dict lookup - without autocalling"""
+        assert self.get('aDict.nestedFunc', False) == dummyFunc
+
+    def test38(self):
+        """aDict.nestedFunc in dict lookup in a loop - without autocalling"""
+        for i in range(10):
+            assert self.get('aDict.nestedFunc', False) == dummyFunc
+
+    def test39(self):
+        """aMeth in dict lookup - without autocalling"""
+        assert self.get('aMeth', False) == self.namespace()['aMeth']
+
+    def test40(self):
+        """aMeth in dict lookup in a loop - without autocalling"""
+        for i in range(10):
+            assert self.get('aMeth', False) == self.namespace()['aMeth']
+
+    def test41(self):
+        """anObj.meth3 in dict lookup"""
+        self.check('anObj.meth3')
+
+    def test42(self):
+        """aMeth in dict lookup in a loop"""
+        for i in range(10):
+            self.check('anObj.meth3')
+
+    def test43(self):
+        """NotFound test"""
+
+        def test(self=self):
+            self.get('anObj.methX')    
+        self.assertRaises(NotFound,test)
+        
+    def test44(self):
+        """NotFound test in a loop"""
+        def test(self=self):
+            self.get('anObj.methX')    
+
+        for i in range(10):
+            self.assertRaises(NotFound,test)
+            
+    def test45(self):
+        """Other exception from meth test"""
+
+        def test(self=self):
+            self.get('anObj.meth2')    
+        self.assertRaises(ValueError, test)
+        
+    def test46(self):
+        """Other exception from meth test in a loop"""
+        def test(self=self):
+            self.get('anObj.meth2')    
+
+        for i in range(10):
+            self.assertRaises(ValueError,test)
+
+    def test47(self):
+        """None in dict lookup"""
+        self.check('none')
+
+    def test48(self):
+        """None in dict lookup in a loop"""
+        for i in range(10):
+            self.check('none')
+            
+    def test49(self):
+        """EmptyString in dict lookup"""
+        self.check('emptyString')
+
+    def test50(self):
+        """EmptyString in dict lookup in a loop"""
+        for i in range(10):
+            self.check('emptyString')
+
+    def test51(self):
+        """Other exception from func test"""
+
+        def test(self=self):
+            self.get('funcThatRaises')    
+        self.assertRaises(ValueError, test)
+        
+    def test52(self):
+        """Other exception from func test in a loop"""
+        def test(self=self):
+            self.get('funcThatRaises')    
+
+        for i in range(10):
+            self.assertRaises(ValueError,test)
+
+
+    def test53(self):
+        """Other exception from func test"""
+
+        def test(self=self):
+            self.get('aDict.nestedDict.funcThatRaises')    
+        self.assertRaises(ValueError, test)
+        
+    def test54(self):
+        """Other exception from func test in a loop"""
+        def test(self=self):
+            self.get('aDict.nestedDict.funcThatRaises')    
+
+        for i in range(10):
+            self.assertRaises(ValueError,test)
+
+    def test55(self):
+        """aDict.nestedDict.aClass in dict lookup"""
+        self.check('aDict.nestedDict.aClass')
+
+    def test56(self):
+        """aDict.nestedDict.aClass in dict lookup in a loop"""
+        for i in range(10):
+            self.check('aDict.nestedDict.aClass')
+
+    def test57(self):
+        """aDict.nestedDict.aClass in dict lookup - without autocalling"""
+        assert self.get('aDict.nestedDict.aClass', False) == DummyClass
+
+    def test58(self):
+        """aDict.nestedDict.aClass in dict lookup in a loop - without autocalling"""
+        for i in range(10):
+            assert self.get('aDict.nestedDict.aClass', False) == DummyClass
+
+    def test59(self):
+        """Other exception from func test -- but without autocalling shouldn't raise"""
+
+        self.get('aDict.nestedDict.funcThatRaises', False)    
+        
+    def test60(self):
+        """Other exception from func test in a loop -- but without autocalling shouldn't raise"""
+
+        for i in range(10):
+            self.get('aDict.nestedDict.funcThatRaises', False)    
+
+class VFS(VFN):
+    _searchListLength = 1
+    
+    def searchList(self):
+        lng = self._searchListLength
+        if lng == 1:
+            return [self.namespace()]
+        elif lng == 2:
+            return [self.namespace(),{'dummy':1234}]
+        elif lng == 3:
+            # a tuple for kicks
+            return ({'dummy':1234}, self.namespace(),{'dummy':1234})
+        elif lng == 4:
+            # a generator for more kicks
+            return self.searchListGenerator()
+
+    def searchListGenerator(self):
+        class Test:
+            pass
+        for i in [Test(),{'dummy':1234}, self.namespace(),{'dummy':1234}]:
+            yield i
+  
+    def get(self, name, autocall=True):
+        return self.VFS(self.searchList(), name, autocall)
+        
+class VFS_2namespaces(VFS):
+    _searchListLength = 2
+    
+class VFS_3namespaces(VFS):
+    _searchListLength = 3
+
+class VFS_4namespaces(VFS):
+    _searchListLength = 4
+    
+class VFF(VFN): 
+    def get(self, name, autocall=True):
+        ns = self._testNamespace
+        aStr = ns['aStr'] 
+        aFloat = ns['aFloat']
+        none = 'some'
+        return valueFromFrame(name, autocall)
+
+    def setUp(self):
+        """Mod some of the data
+        """
+        self._testNamespace = ns = self._testNamespace.copy()
+        self._results = res = self._results.copy()
+        ns['aStr'] = res['aStr'] = 'BLARG'
+        ns['aFloat'] = res['aFloat'] = 0.1234
+        res['none'] = 'some'
+        res['True'] = True
+        res['False'] = False
+        res['None'] = None
+        res['eval'] = eval
+
+    def test_VFF_1(self):
+        """Builtins"""
+        self.check('True')
+        self.check('None')
+        self.check('False')
+        assert self.get('eval', False)==eval
+        assert self.get('range', False)==range
+
+class VFFSL(VFS):
+    _searchListLength = 1
+
+    def setUp(self):
+        """Mod some of the data
+        """
+        self._testNamespace = ns = self._testNamespace.copy()
+        self._results = res = self._results.copy()
+        ns['aStr'] = res['aStr'] = 'BLARG'
+        ns['aFloat'] = res['aFloat'] = 0.1234
+        res['none'] = 'some'
+        
+        del ns['anInt'] # will be picked up by globals
+        
+    def VFFSL(self, searchList, name, autocall=True):
+        anInt = 1
+        none = 'some'
+        return valueFromFrameOrSearchList(searchList, name, autocall)
+    
+    def get(self, name, autocall=True):
+        return self.VFFSL(self.searchList(), name, autocall)
+
+class VFFSL_2(VFFSL):
+    _searchListLength = 2
+
+class VFFSL_3(VFFSL):
+    _searchListLength = 3
+
+class VFFSL_4(VFFSL):
+    _searchListLength = 4
+
+if sys.platform.startswith('java'):
+    del VFF, VFFSL, VFFSL_2, VFFSL_3, VFFSL_4
+
+
+##################################################
+## if run from the command line ##
+        
+if __name__ == '__main__':
+    unittest.main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Regressions.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Regressions.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Regressions.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,248 @@
+#!/usr/bin/env python
+
+import Cheetah.NameMapper 
+import Cheetah.Template
+
+import pdb
+import sys
+
+import unittest_local_copy as unittest # This is just stupid
+
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
+def isPython23():
+    ''' Python 2.3 is still supported by Cheetah, but doesn't support decorators '''
+    return majorVer == 2 and minorVer < 4
+
+class GetAttrException(Exception):
+    pass
+
+class CustomGetAttrClass(object):
+    def __getattr__(self, name):
+        raise GetAttrException('FAIL, %s' % name)
+
+class GetAttrTest(unittest.TestCase):
+    '''
+        Test for an issue occurring when __getatttr__() raises an exception
+        causing NameMapper to raise a NotFound exception
+    '''
+    def test_ValidException(self):
+        o = CustomGetAttrClass()
+        try:
+            print o.attr
+        except GetAttrException, e:
+            # expected
+            return
+        except:
+            self.fail('Invalid exception raised: %s' % e)
+        self.fail('Should have had an exception raised')
+
+    def test_NotFoundException(self):
+        template = '''
+            #def raiseme()
+                $obj.attr
+            #end def'''
+
+        template = Cheetah.Template.Template.compile(template, compilerSettings={}, keepRefToGeneratedCode=True)
+        template = template(searchList=[{'obj' : CustomGetAttrClass()}])
+        assert template, 'We should have a valid template object by now'
+
+        self.failUnlessRaises(GetAttrException, template.raiseme)
+
+
+class InlineImportTest(unittest.TestCase):
+    def test_FromFooImportThing(self):
+        '''
+            Verify that a bug introduced in v2.1.0 where an inline:
+                #from module import class
+            would result in the following code being generated:
+                import class
+        '''
+        template = '''
+            #def myfunction()
+                #if True
+                    #from os import path
+                    #return 17
+                    Hello!
+                #end if
+            #end def
+        '''
+        template = Cheetah.Template.Template.compile(template, compilerSettings={'useLegacyImportMode' : False}, keepRefToGeneratedCode=True)
+        template = template(searchList=[{}])
+
+        assert template, 'We should have a valid template object by now'
+
+        rc = template.myfunction()
+        assert rc == 17, (template, 'Didn\'t get a proper return value')
+
+    def test_ImportFailModule(self):
+        template = '''
+            #try
+                #import invalidmodule
+            #except
+                #set invalidmodule = dict(FOO='BAR!')
+            #end try
+
+            $invalidmodule.FOO
+        '''
+        template = Cheetah.Template.Template.compile(template, compilerSettings={'useLegacyImportMode' : False}, keepRefToGeneratedCode=True)
+        template = template(searchList=[{}])
+
+        assert template, 'We should have a valid template object by now'
+        assert str(template), 'We weren\'t able to properly generate the result from the template'
+
+    def test_ProperImportOfBadModule(self):
+        template = '''
+            #from invalid import fail
+                
+            This should totally $fail
+        '''
+        self.failUnlessRaises(ImportError, Cheetah.Template.Template.compile, template, compilerSettings={'useLegacyImportMode' : False}, keepRefToGeneratedCode=True)
+
+    def test_AutoImporting(self):
+        template = '''
+            #extends FakeyTemplate
+
+            Boo!
+        '''
+        self.failUnlessRaises(ImportError, Cheetah.Template.Template.compile, template)
+
+    def test_StuffBeforeImport_Legacy(self):
+        template = '''
+###
+### I like comments before import
+###
+#extends Foo
+Bar
+'''
+        self.failUnlessRaises(ImportError, Cheetah.Template.Template.compile, template, compilerSettings={'useLegacyImportMode' : True}, keepRefToGeneratedCode=True)
+
+
+class Mantis_Issue_11_Regression_Test(unittest.TestCase):
+    ''' 
+        Test case for bug outlined in Mantis issue #11:
+            
+        Output:
+        Traceback (most recent call last):
+          File "test.py", line 12, in <module>
+            t.respond()
+          File "DynamicallyCompiledCheetahTemplate.py", line 86, in respond
+          File "/usr/lib64/python2.6/cgi.py", line 1035, in escape
+            s = s.replace("&", "&") # Must be done first! 
+    '''
+    def test_FailingBehavior(self):
+        import cgi
+        template = Cheetah.Template.Template("$escape($request)", searchList=[{'escape' : cgi.escape, 'request' : 'foobar'}])
+        assert template
+        self.failUnlessRaises(AttributeError, template.respond)
+
+
+    def test_FailingBehaviorWithSetting(self):
+        import cgi
+        template = Cheetah.Template.Template("$escape($request)", 
+                searchList=[{'escape' : cgi.escape, 'request' : 'foobar'}], 
+                compilerSettings={'prioritizeSearchListOverSelf' : True})
+        assert template
+        assert template.respond()
+
+class Mantis_Issue_21_Regression_Test(unittest.TestCase):
+    ''' 
+        Test case for bug outlined in issue #21
+
+        Effectively @staticmethod and @classmethod
+        decorated methods in templates don't 
+        properly define the _filter local, which breaks
+        when using the NameMapper
+    '''
+    def runTest(self):
+        if isPython23():
+            return
+        template = '''
+            #@staticmethod
+            #def testMethod()
+                This is my $output
+            #end def
+        '''
+        template = Cheetah.Template.Template.compile(template)
+        assert template
+        assert template.testMethod(output='bug') # raises a NameError: global name '_filter' is not defined
+
+
+class Mantis_Issue_22_Regression_Test(unittest.TestCase):
+    ''' 
+        Test case for bug outlined in issue #22
+
+        When using @staticmethod and @classmethod
+        in conjunction with the #filter directive
+        the generated code for the #filter is reliant
+        on the `self` local, breaking the function
+    '''
+    def test_NoneFilter(self):
+        # XXX: Disabling this test for now
+        return
+        if isPython23():
+            return
+        template = '''
+            #@staticmethod
+            #def testMethod()
+                #filter None
+                    This is my $output
+                #end filter
+            #end def
+        '''
+        template = Cheetah.Template.Template.compile(template)
+        assert template
+        assert template.testMethod(output='bug')
+
+    def test_DefinedFilter(self):
+        # XXX: Disabling this test for now
+        return
+        if isPython23():
+            return
+        template = '''
+            #@staticmethod
+            #def testMethod()
+                #filter Filter
+                    This is my $output
+                #end filter
+            #end def
+        '''
+        # The generated code for the template's testMethod() should look something
+        # like this in the 'error' case:
+        '''
+        @staticmethod
+        def testMethod(**KWS):
+            ## CHEETAH: generated from #def testMethod() at line 3, col 13.
+            trans = DummyTransaction()
+            _dummyTrans = True
+            write = trans.response().write
+            SL = [KWS]
+            _filter = lambda x, **kwargs: unicode(x)
+
+            ########################################
+            ## START - generated method body
+
+            _orig_filter_18517345 = _filter
+            filterName = u'Filter'
+            if self._CHEETAH__filters.has_key("Filter"):
+                _filter = self._CHEETAH__currentFilter = self._CHEETAH__filters[filterName]
+            else:
+                _filter = self._CHEETAH__currentFilter = \
+                            self._CHEETAH__filters[filterName] = getattr(self._CHEETAH__filtersLib, filterName)(self).filter
+            write(u'                    This is my ')
+            _v = VFFSL(SL,"output",True) # u'$output' on line 5, col 32
+            if _v is not None: write(_filter(_v, rawExpr=u'$output')) # from line 5, col 32.
+
+            ########################################
+            ## END - generated method body
+
+            return _dummyTrans and trans.response().getvalue() or ""
+        '''
+        template = Cheetah.Template.Template.compile(template)
+        assert template
+        assert template.testMethod(output='bug')
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/SyntaxAndOutput.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/SyntaxAndOutput.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/SyntaxAndOutput.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3227 @@
+#!/usr/bin/env python
+# -*- coding: latin-1 -*-
+
+'''
+Syntax and Output tests.
+
+TODO
+- #finally
+- #filter
+- #errorCatcher
+- #echo
+- #silent
+'''
+
+
+##################################################
+## DEPENDENCIES ##
+
+import sys
+import types
+import re
+from copy import deepcopy
+import os
+import os.path
+import new
+import pdb
+import warnings
+
+from Cheetah.NameMapper import NotFound
+from Cheetah.NameMapper import C_VERSION as NameMapper_C_VERSION
+from Cheetah.Template import Template
+from Cheetah.Parser import ParseError
+from Cheetah.Compiler import Compiler, DEFAULT_COMPILER_SETTINGS
+import unittest_local_copy as unittest
+
+class Unspecified(object):
+    pass
+
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
+def testdecorator(func):
+    return func
+
+class DummyClass:
+    _called = False
+    def __str__(self):
+        return 'object'
+
+    def meth(self, arg="arff"):
+        return str(arg)
+
+    def meth1(self, arg="doo"):
+        return arg
+
+    def meth2(self, arg1="a1", arg2="a2"):
+        return str(arg1) + str(arg2)
+
+    def methWithPercentSignDefaultArg(self, arg1="110%"):
+        return str(arg1)
+
+    def callIt(self, arg=1234):
+        self._called = True
+        self._callArg = arg
+        
+
+def dummyFunc(arg="Scooby"):
+    return arg
+
+defaultTestNameSpace = {
+    'aStr':'blarg',
+    'anInt':1,
+    'aFloat':1.5,
+    'aList': ['item0','item1','item2'],
+    'aDict': {'one':'item1',
+              'two':'item2',
+              'nestedDict':{1:'nestedItem1',
+                          'two':'nestedItem2'
+                          },
+              'nestedFunc':dummyFunc,
+              },
+    'aFunc': dummyFunc,
+    'anObj': DummyClass(),
+    'aMeth': DummyClass().meth1,
+    'aStrToBeIncluded': "$aStr $anInt",
+    'none' : None,  
+    'emptyString':'',
+    'numOne':1,
+    'numTwo':2,
+    'zero':0,
+    'tenDigits': 1234567890,
+    'webSafeTest': 'abc <=> &',
+    'strip1': '  \t   strippable whitespace   \t\t  \n',
+    'strip2': '  \t   strippable whitespace   \t\t  ',
+    'strip3': '  \t   strippable whitespace   \t\t\n1 2  3\n',
+    
+    'blockToBeParsed':"""$numOne $numTwo""",
+    'includeBlock2':"""$numOne $numTwo $aSetVar""",
+    
+    'includeFileName':'parseTest.txt',
+    'listOfLambdas':[lambda x: x, lambda x: x, lambda x: x,],
+    'list': [
+    	{'index': 0, 'numOne': 1, 'numTwo': 2},
+    	{'index': 1, 'numOne': 1, 'numTwo': 2},
+        ],
+    'nameList': [('john', 'doe'), ('jane', 'smith')],
+    'letterList': ['a', 'b', 'c'],
+    '_': lambda x: 'Translated: ' + x,
+    'unicodeData':u'aoeu12345\u1234',
+    }
+
+
+##################################################
+## TEST BASE CLASSES
+
+class OutputTest(unittest.TestCase):
+    report = '''
+Template output mismatch: 
+
+    Input Template =
+%(template)s%(end)s
+
+    Expected Output =
+%(expected)s%(end)s
+
+    Actual Output =
+%(actual)s%(end)s'''
+
+    convertEOLs = True
+    _EOLreplacement = None
+    _debugEOLReplacement = False
+
+    DEBUGLEV = 0
+    _searchList = [defaultTestNameSpace]
+
+    _useNewStyleCompilation = True
+    #_useNewStyleCompilation = False
+
+    _extraCompileKwArgs = None
+
+    def searchList(self):
+        return self._searchList
+
+    def verify(self, input, expectedOutput,
+               inputEncoding=None,
+               outputEncoding=None,
+               convertEOLs=Unspecified):
+        if self._EOLreplacement:
+            if convertEOLs is Unspecified:
+                convertEOLs = self.convertEOLs
+            if convertEOLs:
+                input = input.replace('\n', self._EOLreplacement)
+                expectedOutput = expectedOutput.replace('\n', self._EOLreplacement)
+
+        self._input = input
+        if self._useNewStyleCompilation:
+            extraKwArgs = self._extraCompileKwArgs or {}
+            
+            templateClass = Template.compile(
+                source=input,
+                compilerSettings=self._getCompilerSettings(),
+                keepRefToGeneratedCode=True,
+                **extraKwArgs
+                )
+            moduleCode = templateClass._CHEETAH_generatedModuleCode
+            self.template = templateObj = templateClass(searchList=self.searchList())
+        else:
+            self.template = templateObj = Template(
+                input,
+                searchList=self.searchList(),
+                compilerSettings=self._getCompilerSettings(),
+                )
+            moduleCode = templateObj._CHEETAH_generatedModuleCode
+        if self.DEBUGLEV >= 1:
+            print moduleCode
+        try:
+            output = templateObj.respond() # rather than __str__, because of unicode
+            assert output==expectedOutput, self._outputMismatchReport(output, expectedOutput)
+        finally:
+            templateObj.shutdown()
+
+    def _getCompilerSettings(self):
+        return {}
+            
+    def _outputMismatchReport(self, output, expectedOutput):
+        if self._debugEOLReplacement and self._EOLreplacement:
+            EOLrepl = self._EOLreplacement
+            marker = '*EOL*'
+            return self.report % {'template': self._input.replace(EOLrepl,marker),
+                                  'expected': expectedOutput.replace(EOLrepl,marker),
+                                  'actual': output.replace(EOLrepl,marker),
+                                  'end': '(end)'}
+        else:
+            return self.report % {'template': self._input,
+                                  'expected': expectedOutput,
+                                  'actual': output,
+                                  'end': '(end)'}
+        
+    def genClassCode(self):
+        if hasattr(self, 'template'):
+            return self.template.generatedClassCode()
+
+    def genModuleCode(self):
+        if hasattr(self, 'template'):
+            return self.template.generatedModuleCode()
+
+##################################################
+## TEST CASE CLASSES
+
+class EmptyTemplate(OutputTest):
+    convertEOLs = False
+    def test1(self):
+        """an empty string for the template"""
+        
+        warnings.filterwarnings('error',
+                                'You supplied an empty string for the source!',
+                                UserWarning)
+        try:
+            self.verify("", "")
+        except UserWarning:
+            pass
+        else:
+            self.fail("Should warn about empty source strings.")
+        
+        try:
+            self.verify("#implements foo", "")
+        except NotImplementedError:
+            pass
+        else:
+            self.fail("This should barf about respond() not being implemented.")
+
+        self.verify("#implements respond", "")
+
+        self.verify("#implements respond(foo=1234)", "")
+
+
+class Backslashes(OutputTest):
+    convertEOLs = False
+
+    def setUp(self):
+        fp = open('backslashes.txt','w')
+        fp.write(r'\ #LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
+        fp.flush()
+        fp.close
+    
+    def tearDown(self):
+        if os.path.exists('backslashes.txt'):
+            os.remove('backslashes.txt')
+        
+    def test1(self):
+        """ a single \\ using rawstrings"""
+        self.verify(r"\ ",
+                    r"\ ")
+
+    def test2(self):
+        """ a single \\ using rawstrings and lots of lines"""
+        self.verify(r"\ " + "\n\n\n\n\n\n\n\n\n",
+                    r"\ " + "\n\n\n\n\n\n\n\n\n")
+
+    def test3(self):
+        """ a single \\ without using rawstrings"""
+        self.verify("\ \ ",
+                    "\ \ ")
+
+    def test4(self):
+        """ single line from an apache conf file"""
+        self.verify(r'#LogFormat "%h %l %u %t \"%r\" %>s %b"',
+                    r'#LogFormat "%h %l %u %t \"%r\" %>s %b"')
+
+    def test5(self):
+        """ single line from an apache conf file with many NEWLINES
+
+        The NEWLINES are used to make sure that MethodCompiler.commitStrConst()
+        is handling long and short strings in the same fashion.  It uses
+        triple-quotes for strings with lots of \\n in them and repr(theStr) for
+        shorter strings with only a few newlines."""
+        
+        self.verify(r'#LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n',
+                    r'#LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
+
+    def test6(self):
+        """ test backslash handling in an included file"""
+        self.verify(r'#include "backslashes.txt"',
+                    r'\ #LogFormat "%h %l %u %t \"%r\" %>s %b"' + '\n\n\n\n\n\n\n')
+
+    def test7(self):
+        """ a single \\ without using rawstrings plus many NEWLINES"""
+        self.verify("\ \ " + "\n\n\n\n\n\n\n\n\n",
+                    "\ \ " + "\n\n\n\n\n\n\n\n\n")
+
+    def test8(self):
+        """ single line from an apache conf file with single quotes and many NEWLINES 
+        """
+        
+        self.verify(r"""#LogFormat '%h %l %u %t \"%r\" %>s %b'""" + '\n\n\n\n\n\n\n',
+                    r"""#LogFormat '%h %l %u %t \"%r\" %>s %b'""" + '\n\n\n\n\n\n\n')
+        
+class NonTokens(OutputTest):
+    def test1(self):
+        """dollar signs not in Cheetah $vars"""
+        self.verify("$ $$ $5 $. $ test",
+                    "$ $$ $5 $. $ test")
+
+    def test2(self):
+        """hash not in #directives"""
+        self.verify("# \# #5 ",
+                    "# # #5 ")
+
+    def test3(self):
+        """escapted comments"""
+        self.verify("  \##escaped comment  ",
+                    "  ##escaped comment  ")
+
+    def test4(self):
+        """escapted multi-line comments"""
+        self.verify("  \#*escaped comment \n*#  ",
+                    "  #*escaped comment \n*#  ")
+
+    def test5(self):
+        """1 dollar sign"""
+        self.verify("$",
+                    "$")
+    def _X_test6(self):
+        """1 dollar sign followed by hash"""
+        self.verify("\n$#\n",
+                    "\n$#\n")
+
+    def test6(self):
+        """1 dollar sign followed by EOL Slurp Token"""
+        if DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']:
+            self.verify("\n$%s\n"%DEFAULT_COMPILER_SETTINGS['EOLSlurpToken'],
+                        "\n$")
+        else:
+            self.verify("\n$#\n",
+                        "\n$#\n")
+            
+class Comments_SingleLine(OutputTest):
+    def test1(self):
+        """## followed by WS"""
+        self.verify("##    ",
+                    "")
+
+    def test2(self):
+        """## followed by NEWLINE"""
+        self.verify("##\n",
+                    "")
+
+    def test3(self):
+        """## followed by text then NEWLINE"""
+        self.verify("## oeuao aoe uaoe \n",
+                    "")
+    def test4(self):
+        """## gobbles leading WS"""
+        self.verify("    ## oeuao aoe uaoe \n",
+                    "")
+
+    def test5(self):
+        """## followed by text then NEWLINE, + leading WS"""
+        self.verify("    ## oeuao aoe uaoe \n",
+                    "")
+
+    def test6(self):
+        """## followed by EOF"""
+        self.verify("##",
+                    "")
+        
+    def test7(self):
+        """## followed by EOF with leading WS"""
+        self.verify("    ##",
+                    "")
+        
+    def test8(self):
+        """## gobble line
+        with text on previous and following lines"""
+        self.verify("line1\n   ## aoeu 1234   \nline2",
+                    "line1\nline2")
+
+    def test9(self):
+        """## don't gobble line
+        with text on previous and following lines"""
+        self.verify("line1\n 12 ## aoeu 1234   \nline2",
+                    "line1\n 12 \nline2")
+
+    def test10(self):
+        """## containing $placeholders
+        """
+        self.verify("##$a$b $c($d)",
+                    "")
+
+    def test11(self):
+        """## containing #for directive
+        """
+        self.verify("##for $i in range(15)",
+                    "")
+
+
+class Comments_MultiLine_NoGobble(OutputTest):
+    """
+    Multiline comments used to not gobble whitespace.  They do now, but this can
+    be turned off with a compilerSetting    
+    """
+
+    def _getCompilerSettings(self):
+        return {'gobbleWhitespaceAroundMultiLineComments':False}
+
+    def test1(self):
+        """#* *# followed by WS
+        Shouldn't gobble WS
+        """
+        self.verify("#* blarg *#   ",
+                    "   ")
+        
+    def test2(self):
+        """#* *# preceded and followed by WS
+        Shouldn't gobble WS
+        """
+        self.verify("   #* blarg *#   ",
+                    "      ")
+        
+    def test3(self):
+        """#* *# followed by WS, with NEWLINE
+        Shouldn't gobble WS
+        """
+        self.verify("#* \nblarg\n *#   ",
+                    "   ")
+        
+    def test4(self):
+        """#* *# preceded and followed by WS, with NEWLINE
+        Shouldn't gobble WS
+        """
+        self.verify("   #* \nblarg\n *#   ",
+                    "      ")
+
+class Comments_MultiLine(OutputTest):
+    """
+    Note: Multiline comments don't gobble whitespace!
+    """
+    
+    def test1(self):
+        """#* *# followed by WS
+        Should gobble WS
+        """
+        self.verify("#* blarg *#   ",
+                    "")
+        
+    def test2(self):
+        """#* *# preceded and followed by WS
+        Should gobble WS
+        """
+        self.verify("   #* blarg *#   ",
+                    "")
+        
+    def test3(self):
+        """#* *# followed by WS, with NEWLINE
+        Shouldn't gobble WS
+        """
+        self.verify("#* \nblarg\n *#   ",
+                    "")
+        
+    def test4(self):
+        """#* *# preceded and followed by WS, with NEWLINE
+        Shouldn't gobble WS
+        """
+        self.verify("   #* \nblarg\n *#   ",
+                    "")
+
+    def test5(self):
+        """#* *# containing nothing 
+        """
+        self.verify("#**#",
+                    "")
+        
+    def test6(self):
+        """#* *# containing only NEWLINES
+        """
+        self.verify("  #*\n\n\n\n\n\n\n\n*#  ",
+                    "")
+
+    def test7(self):
+        """#* *# containing $placeholders
+        """
+        self.verify("#* $var $var(1234*$c) *#",
+                    "")
+        
+    def test8(self):
+        """#* *# containing #for directive
+        """
+        self.verify("#* #for $i in range(15) *#",
+                    "")
+
+    def test9(self):
+        """ text around #* *# containing #for directive
+        """
+        self.verify("foo\nfoo bar #* #for $i in range(15) *# foo\n",
+                    "foo\nfoo bar  foo\n")
+
+    def test9(self):
+        """ text around #* *# containing #for directive and trailing whitespace
+        which should be gobbled
+        """
+        self.verify("foo\nfoo bar #* #for $i in range(15) *#   \ntest",
+                    "foo\nfoo bar \ntest")
+
+    def test10(self):
+        """ text around #* *# containing #for directive and newlines: trailing whitespace
+        which should be gobbled.
+        """
+        self.verify("foo\nfoo bar #* \n\n#for $i in range(15) \n\n*#   \ntest",
+                    "foo\nfoo bar \ntest")
+
+class Placeholders(OutputTest):
+    def test1(self):
+        """1 placeholder"""
+        self.verify("$aStr", "blarg")
+        
+    def test2(self):
+        """2 placeholders"""
+        self.verify("$aStr $anInt", "blarg 1")
+
+    def test3(self):
+        """2 placeholders, back-to-back"""
+        self.verify("$aStr$anInt", "blarg1")
+
+    def test4(self):
+        """1 placeholder enclosed in ()"""
+        self.verify("$(aStr)", "blarg")
+        
+    def test5(self):
+        """1 placeholder enclosed in {}"""
+        self.verify("${aStr}", "blarg")
+
+    def test6(self):
+        """1 placeholder enclosed in []"""
+        self.verify("$[aStr]", "blarg")
+
+    def test7(self):
+        """1 placeholder enclosed in () + WS
+
+        Test to make sure that $(<WS><identifier>.. matches
+        """
+        self.verify("$( aStr   )", "blarg")
+
+    def test8(self):
+        """1 placeholder enclosed in {} + WS"""
+        self.verify("${ aStr   }", "blarg")
+
+    def test9(self):
+        """1 placeholder enclosed in [] + WS"""
+        self.verify("$[ aStr   ]", "blarg")
+
+    def test10(self):
+        """1 placeholder enclosed in () + WS + * cache
+
+        Test to make sure that $*(<WS><identifier>.. matches
+        """
+        self.verify("$*( aStr   )", "blarg")
+
+    def test11(self):
+        """1 placeholder enclosed in {} + WS + *cache"""
+        self.verify("$*{ aStr   }", "blarg")
+
+    def test12(self):
+        """1 placeholder enclosed in [] + WS + *cache"""
+        self.verify("$*[ aStr   ]", "blarg")
+
+    def test13(self):
+        """1 placeholder enclosed in {} + WS + *<int>*cache"""
+        self.verify("$*5*{ aStr   }", "blarg")
+
+    def test14(self):
+        """1 placeholder enclosed in [] + WS + *<int>*cache"""
+        self.verify("$*5*[ aStr   ]", "blarg")
+
+    def test15(self):
+        """1 placeholder enclosed in {} + WS + *<float>*cache"""
+        self.verify("$*0.5d*{ aStr   }", "blarg")
+
+    def test16(self):
+        """1 placeholder enclosed in [] + WS + *<float>*cache"""
+        self.verify("$*.5*[ aStr   ]", "blarg")
+
+    def test17(self):
+        """1 placeholder + *<int>*cache"""
+        self.verify("$*5*aStr", "blarg")
+
+    def test18(self):
+        """1 placeholder *<float>*cache"""
+        self.verify("$*0.5h*aStr", "blarg")
+
+    def test19(self):
+        """1 placeholder surrounded by single quotes and multiple newlines"""
+        self.verify("""'\n\n\n\n'$aStr'\n\n\n\n'""",
+                    """'\n\n\n\n'blarg'\n\n\n\n'""")
+
+    def test20(self):
+        """silent mode $!placeholders """
+        self.verify("$!aStr$!nonExistant$!*nonExistant$!{nonExistant}", "blarg")
+
+        try:
+            self.verify("$!aStr$nonExistant",
+            "blarg")
+        except NotFound:
+            pass
+        else:
+            self.fail('should raise NotFound exception')
+
+    def test21(self):
+        """Make sure that $*caching is actually working"""
+        namesStr = 'You Me Them Everyone'
+        names = namesStr.split()
+
+        tmpl = Template.compile('#for name in $names: $name ', baseclass=dict)
+        assert str(tmpl({'names':names})).strip()==namesStr
+
+        tmpl = tmpl.subclass('#for name in $names: $*name ')
+        assert str(tmpl({'names':names}))=='You '*len(names)
+
+        tmpl = tmpl.subclass('#for name in $names: $*1*name ')
+        assert str(tmpl({'names':names}))=='You '*len(names)
+
+        tmpl = tmpl.subclass('#for name in $names: $*1*(name) ')
+        assert str(tmpl({'names':names}))=='You '*len(names)
+
+        if versionTuple > (2,2):
+            tmpl = tmpl.subclass('#for name in $names: $*1*(name) ')
+            assert str(tmpl(names=names))=='You '*len(names)
+
+class Placeholders_Vals(OutputTest):
+    convertEOLs = False
+    def test1(self):
+        """string"""
+        self.verify("$aStr", "blarg")
+
+    def test2(self):
+        """string - with whitespace"""
+        self.verify(" $aStr ", " blarg ")
+
+    def test3(self):
+        """empty string - with whitespace"""
+        self.verify("$emptyString", "")
+
+    def test4(self):
+        """int"""
+        self.verify("$anInt", "1")
+
+    def test5(self):
+        """float"""
+        self.verify("$aFloat", "1.5")
+
+    def test6(self):
+        """list"""
+        self.verify("$aList", "['item0', 'item1', 'item2']")
+
+    def test7(self):
+        """None
+
+        The default output filter is ReplaceNone.
+        """
+        self.verify("$none", "")
+
+    def test8(self):
+        """True, False
+        """
+        self.verify("$True $False", "%s %s"%(repr(True), repr(False)))
+
+    def test9(self):
+        """$_
+        """
+        self.verify("$_('foo')", "Translated: foo")
+
+class PlaceholderStrings(OutputTest):
+    def test1(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("$str(c'$aStr')", "blarg")
+
+    def test2(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("$str(c'$aStr.upper')", "BLARG")
+
+    def test3(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("$str(c'$(aStr.upper.replace(c\"A$str()\",\"\"))')", "BLRG")
+
+    def test4(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("#echo $str(c'$(aStr.upper)')", "BLARG")
+
+    def test5(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("#if 1 then $str(c'$(aStr.upper)') else 0", "BLARG")
+
+    def test6(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("#if 1\n$str(c'$(aStr.upper)')#slurp\n#else\n0#end if", "BLARG")
+
+    def test7(self):
+        """some c'text $placeholder text' strings"""
+        self.verify("#def foo(arg=c'$(\"BLARG\")')\n"
+                    "$arg#slurp\n"
+                    "#end def\n"
+                    "$foo()$foo(c'$anInt')#slurp",
+                    
+                    "BLARG1")
+
+
+
+class UnicodeStrings(OutputTest):
+    def test1(self):
+        """unicode data in placeholder
+        """
+        #self.verify(u"$unicodeData", defaultTestNameSpace['unicodeData'], outputEncoding='utf8')
+        self.verify(u"$unicodeData", defaultTestNameSpace['unicodeData'])
+
+    def test2(self):
+        """unicode data in body
+        """
+        self.verify(u"aoeu12345\u1234", u"aoeu12345\u1234")
+        #self.verify(u"#encoding utf8#aoeu12345\u1234", u"aoeu12345\u1234")
+
+class EncodingDirective(OutputTest):
+    def test1(self):
+        """basic #encoding """
+        self.verify("#encoding utf-8\n1234",
+                    "1234")
+
+    def test2(self):
+        """basic #encoding """
+        self.verify("#encoding ascii\n1234",
+                    "1234")
+
+    def test3(self):
+        """basic #encoding """
+        self.verify("#encoding utf-8\n\xe1\x88\xb4",
+                    u'\u1234', outputEncoding='utf8')
+
+    def test4(self):
+        """basic #encoding """
+        self.verify("#encoding latin-1\n\xe1\x88\xb4",
+                    u"\xe1\x88\xb4")
+
+    def test5(self):
+        """basic #encoding """
+        self.verify("#encoding latin-1\nAndr\202",
+                    u'Andr\202')
+
+class UnicodeDirective(OutputTest):
+    def test1(self):
+        """basic #unicode """
+        self.verify("#unicode utf-8\n1234",
+                    u"1234")
+        
+        self.verify("#unicode ascii\n1234",
+                    u"1234")
+
+        self.verify("#unicode latin-1\n1234",
+                    u"1234")
+
+        self.verify("#unicode latin-1\n1234ü",
+                    u"1234ü")
+        self.verify("#unicode: latin-1\n1234ü",
+                    u"1234ü")
+        self.verify("#  unicode  : latin-1\n1234ü",
+                    u"1234ü")
+
+        self.verify(u"#unicode latin-1\n1234ü",
+                    u"1234ü")
+
+        self.verify("#encoding latin-1\n1234ü",
+                    u"1234ü")
+
+class Placeholders_Esc(OutputTest):
+    convertEOLs = False
+    def test1(self):
+        """1 escaped placeholder"""
+        self.verify("\$var",
+                    "$var")
+    
+    def test2(self):
+        """2 escaped placeholders"""
+        self.verify("\$var \$_",
+                    "$var $_")
+
+    def test3(self):
+        """2 escaped placeholders - back to back"""
+        self.verify("\$var\$_",
+                    "$var$_")
+
+    def test4(self):
+        """2 escaped placeholders - nested"""
+        self.verify("\$var(\$_)",
+                    "$var($_)")
+
+    def test5(self):
+        """2 escaped placeholders - nested and enclosed"""
+        self.verify("\$(var(\$_)",
+                    "$(var($_)")
+
+
+class Placeholders_Calls(OutputTest):
+    def test1(self):
+        """func placeholder - no ()"""
+        self.verify("$aFunc",
+                    "Scooby")
+
+    def test2(self):
+        """func placeholder - with ()"""
+        self.verify("$aFunc()",
+                    "Scooby")
+
+    def test3(self):
+        r"""func placeholder - with (\n\n)"""
+        self.verify("$aFunc(\n\n)",
+                    "Scooby", convertEOLs=False)
+
+    def test4(self):
+        r"""func placeholder - with (\n\n) and $() enclosure"""
+        self.verify("$(aFunc(\n\n))",
+                    "Scooby", convertEOLs=False)
+
+    def test5(self):
+        r"""func placeholder - with (\n\n) and ${} enclosure"""
+        self.verify("${aFunc(\n\n)}",
+                    "Scooby", convertEOLs=False)
+        
+    def test6(self):
+        """func placeholder - with (int)"""
+        self.verify("$aFunc(1234)",
+                    "1234")
+
+    def test7(self):
+        r"""func placeholder - with (\nint\n)"""
+        self.verify("$aFunc(\n1234\n)",
+                    "1234", convertEOLs=False)
+    def test8(self):
+        """func placeholder - with (string)"""
+        self.verify("$aFunc('aoeu')",
+                    "aoeu")
+        
+    def test9(self):
+        """func placeholder - with ('''string''')"""
+        self.verify("$aFunc('''aoeu''')",
+                    "aoeu")
+    def test10(self):
+        r"""func placeholder - with ('''\nstring\n''')"""
+        self.verify("$aFunc('''\naoeu\n''')",
+                    "\naoeu\n")
+
+    def test11(self):
+        r"""func placeholder - with ('''\nstring'\n''')"""
+        self.verify("$aFunc('''\naoeu'\n''')",
+                    "\naoeu'\n")
+
+    def test12(self):
+        r'''func placeholder - with ("""\nstring\n""")'''
+        self.verify('$aFunc("""\naoeu\n""")',
+                    "\naoeu\n")
+
+    def test13(self):
+        """func placeholder - with (string*int)"""
+        self.verify("$aFunc('aoeu'*2)",
+                    "aoeuaoeu")
+
+    def test14(self):
+        """func placeholder - with (int*int)"""
+        self.verify("$aFunc(2*2)",
+                    "4")
+
+    def test15(self):
+        """func placeholder - with (int*float)"""
+        self.verify("$aFunc(2*2.0)",
+                    "4.0")
+
+    def test16(self):
+        r"""func placeholder - with (int\n*\nfloat)"""
+        self.verify("$aFunc(2\n*\n2.0)",
+                    "4.0", convertEOLs=False)
+
+    def test17(self):
+        """func placeholder - with ($arg=float)"""
+        self.verify("$aFunc($arg=4.0)",
+                    "4.0")
+
+    def test18(self):
+        """func placeholder - with (arg=float)"""
+        self.verify("$aFunc(arg=4.0)",
+                    "4.0")
+
+    def test19(self):
+        """deeply nested argstring, no enclosure"""
+        self.verify("$aFunc($arg=$aMeth($arg=$aFunc(1)))",
+                    "1")
+
+    def test20(self):
+        """deeply nested argstring, no enclosure + with WS"""
+        self.verify("$aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) )",
+                    "1")
+    def test21(self):
+        """deeply nested argstring, () enclosure + with WS"""
+        self.verify("$(aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
+                    "1")
+        
+    def test22(self):
+        """deeply nested argstring, {} enclosure + with WS"""
+        self.verify("${aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) ) }",
+                    "1")
+
+    def test23(self):
+        """deeply nested argstring, [] enclosure + with WS"""
+        self.verify("$[aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) ) ]",
+                    "1")
+
+    def test24(self):
+        """deeply nested argstring, () enclosure + *cache"""
+        self.verify("$*(aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
+                    "1")
+    def test25(self):
+        """deeply nested argstring, () enclosure + *15*cache"""
+        self.verify("$*15*(aFunc(  $arg = $aMeth( $arg = $aFunc( 1 ) ) ) )",
+                    "1")
+
+    def test26(self):
+        """a function call with the Python None kw."""
+        self.verify("$aFunc(None)",
+                    "")
+
+class NameMapper(OutputTest):
+    def test1(self):
+        """autocalling"""
+        self.verify("$aFunc! $aFunc().",
+                    "Scooby! Scooby.")
+
+    def test2(self):
+        """nested autocalling"""
+        self.verify("$aFunc($aFunc).",
+                    "Scooby.")
+
+    def test3(self):
+        """list subscription"""
+        self.verify("$aList[0]",
+                    "item0")
+
+    def test4(self):
+        """list slicing"""
+        self.verify("$aList[:2]",
+                    "['item0', 'item1']")
+        
+    def test5(self):
+        """list slicing and subcription combined"""
+        self.verify("$aList[:2][0]",
+                    "item0")
+
+    def test6(self):
+        """dictionary access - NameMapper style"""
+        self.verify("$aDict.one",
+                    "item1")
+        
+    def test7(self):
+        """dictionary access - Python style"""
+        self.verify("$aDict['one']",
+                    "item1")
+
+    def test8(self):
+        """dictionary access combined with autocalled string method"""
+        self.verify("$aDict.one.upper",
+                    "ITEM1")
+
+    def test9(self):
+        """dictionary access combined with string method"""
+        self.verify("$aDict.one.upper()",
+                    "ITEM1")
+
+    def test10(self):
+        """nested dictionary access - NameMapper style"""
+        self.verify("$aDict.nestedDict.two",
+                    "nestedItem2")
+        
+    def test11(self):
+        """nested dictionary access - Python style"""
+        self.verify("$aDict['nestedDict']['two']",
+                    "nestedItem2")
+
+    def test12(self):
+        """nested dictionary access - alternating style"""
+        self.verify("$aDict['nestedDict'].two",
+                    "nestedItem2")
+
+    def test13(self):
+        """nested dictionary access using method - alternating style"""
+        self.verify("$aDict.get('nestedDict').two",
+                    "nestedItem2")
+
+    def test14(self):
+        """nested dictionary access - NameMapper style - followed by method"""
+        self.verify("$aDict.nestedDict.two.upper",
+                    "NESTEDITEM2")
+
+    def test15(self):
+        """nested dictionary access - alternating style - followed by method"""
+        self.verify("$aDict['nestedDict'].two.upper",
+                    "NESTEDITEM2")
+
+    def test16(self):
+        """nested dictionary access - NameMapper style - followed by method, then slice"""
+        self.verify("$aDict.nestedDict.two.upper[:4]",
+                    "NEST")
+
+    def test17(self):
+        """nested dictionary access - Python style using a soft-coded key"""
+        self.verify("$aDict[$anObj.meth('nestedDict')].two",
+                    "nestedItem2")
+
+    def test18(self):
+        """object method access"""
+        self.verify("$anObj.meth1",
+                    "doo")
+
+    def test19(self):
+        """object method access, followed by complex slice"""
+        self.verify("$anObj.meth1[0: ((4/4*2)*2)/$anObj.meth1(2) ]",
+                    "do")
+
+    def test20(self):
+        """object method access, followed by a very complex slice
+        If it can pass this one, it's safe to say it works!!"""
+        self.verify("$( anObj.meth1[0:\n (\n(4/4*2)*2)/$anObj.meth1(2)\n ] )",
+                    "do")
+
+    def test21(self):
+        """object method access with % in the default arg for the meth.
+
+        This tests a bug that Jeff Johnson found and submitted a patch to SF
+        for."""
+        
+        self.verify("$anObj.methWithPercentSignDefaultArg",
+                    "110%")
+
+
+#class NameMapperDict(OutputTest):
+#
+#    _searchList = [{"update": "Yabba dabba doo!"}]
+#
+#    def test1(self):
+#        if NameMapper_C_VERSION:
+#            return # This feature is not in the C version yet.
+#        self.verify("$update", "Yabba dabba doo!")
+#
+
+class CacheDirective(OutputTest):
+    
+    def test1(self):
+        r"""simple #cache """
+        self.verify("#cache:$anInt",
+                    "1")
+
+    def test2(self):
+        r"""simple #cache + WS"""
+        self.verify("  #cache  \n$anInt#end cache",
+                    "1")
+
+    def test3(self):
+        r"""simple #cache ... #end cache"""
+        self.verify("""#cache id='cache1', timer=150m
+$anInt
+#end cache
+$aStr""",
+                    "1\nblarg")
+        
+    def test4(self):
+        r"""2 #cache ... #end cache blocks"""
+        self.verify("""#slurp
+#def foo
+#cache ID='cache1', timer=150m
+$anInt
+#end cache
+#cache id='cache2', timer=15s
+ #for $i in range(5)
+$i#slurp
+ #end for
+#end cache
+$aStr#slurp
+#end def
+$foo$foo$foo$foo$foo""",
+                    "1\n01234blarg"*5)
+
+
+    def test5(self):
+        r"""nested #cache blocks"""
+        self.verify("""#slurp
+#def foo      
+#cache ID='cache1', timer=150m
+$anInt
+#cache id='cache2', timer=15s
+ #for $i in range(5)
+$i#slurp
+ #end for
+$*(6)#slurp
+#end cache
+#end cache
+$aStr#slurp
+#end def
+$foo$foo$foo$foo$foo""",
+                    "1\n012346blarg"*5)
+        
+    def test6(self):
+        r"""Make sure that partial directives don't match"""
+        self.verify("#cache_foo",
+                    "#cache_foo")
+        self.verify("#cached",
+                    "#cached")
+
+class CallDirective(OutputTest):
+    
+    def test1(self):
+        r"""simple #call """
+        self.verify("#call int\n$anInt#end call",
+                    "1")
+        # single line version
+        self.verify("#call int: $anInt",
+                    "1")
+        self.verify("#call int: 10\n$aStr",
+                    "10\nblarg")
+
+    def test2(self):
+        r"""simple #call + WS"""
+        self.verify("#call int\n$anInt  #end call",
+                    "1")
+
+    def test3(self):
+        r"""a longer #call"""
+        self.verify('''\
+#def meth(arg)
+$arg.upper()#slurp
+#end def
+#call $meth
+$(1234+1) foo#slurp
+#end call''',
+        "1235 FOO")
+
+    def test4(self):
+        r"""#call with keyword #args"""
+        self.verify('''\
+#def meth(arg1, arg2)
+$arg1.upper() - $arg2.lower()#slurp
+#end def
+#call self.meth
+#arg arg1
+$(1234+1) foo#slurp
+#arg arg2
+UPPER#slurp
+#end call''',
+        "1235 FOO - upper")
+
+    def test5(self):
+        r"""#call with single-line keyword #args """
+        self.verify('''\
+#def meth(arg1, arg2)
+$arg1.upper() - $arg2.lower()#slurp
+#end def
+#call self.meth
+#arg arg1:$(1234+1) foo#slurp
+#arg arg2:UPPER#slurp
+#end call''',
+        "1235 FOO - upper")
+        
+    def test6(self):
+        """#call with python kwargs and cheetah output for the 1s positional
+        arg"""
+        
+        self.verify('''\
+#def meth(arg1, arg2)
+$arg1.upper() - $arg2.lower()#slurp
+#end def
+#call self.meth arg2="UPPER"
+$(1234+1) foo#slurp
+#end call''',
+        "1235 FOO - upper")
+
+    def test7(self):
+        """#call with python kwargs and #args"""
+        self.verify('''\
+#def meth(arg1, arg2, arg3)
+$arg1.upper() - $arg2.lower() - $arg3#slurp
+#end def
+#call self.meth arg2="UPPER", arg3=999
+#arg arg1:$(1234+1) foo#slurp
+#end call''',
+        "1235 FOO - upper - 999")
+        
+    def test8(self):
+        """#call with python kwargs and #args, and using a function to get the
+        function that will be called"""
+        self.verify('''\
+#def meth(arg1, arg2, arg3)
+$arg1.upper() - $arg2.lower() - $arg3#slurp
+#end def
+#call getattr(self, "meth") arg2="UPPER", arg3=999
+#arg arg1:$(1234+1) foo#slurp
+#end call''',
+        "1235 FOO - upper - 999")
+
+    def test9(self):
+        """nested #call directives"""
+        self.verify('''\
+#def meth(arg1)
+$arg1#slurp
+#end def
+#def meth2(x,y)
+$x$y#slurp
+#end def
+##
+#call self.meth
+1#slurp
+#call self.meth
+2#slurp
+#call self.meth
+3#slurp
+#end call 3
+#set two = 2
+#call self.meth2 y=c"$(10/$two)"
+#arg x
+4#slurp
+#end call 4
+#end call 2
+#end call 1''',
+        "12345")
+
+
+
+class I18nDirective(OutputTest):   
+    def test1(self):
+        r"""simple #call """
+        self.verify("#i18n \n$anInt#end i18n",
+                    "1")
+        
+        # single line version
+        self.verify("#i18n: $anInt",
+                    "1")
+        self.verify("#i18n: 10\n$aStr",
+                    "10\nblarg")
+
+
+class CaptureDirective(OutputTest):
+    def test1(self):
+        r"""simple #capture"""
+        self.verify('''\
+#capture cap1
+$(1234+1) foo#slurp
+#end capture
+$cap1#slurp
+''',
+        "1235 foo")
+
+
+    def test2(self):
+        r"""slightly more complex #capture"""
+        self.verify('''\
+#def meth(arg)
+$arg.upper()#slurp
+#end def
+#capture cap1
+$(1234+1) $anInt $meth("foo")#slurp
+#end capture
+$cap1#slurp
+''',
+        "1235 1 FOO")
+
+
+class SlurpDirective(OutputTest):
+    def test1(self):
+        r"""#slurp with 1 \n """
+        self.verify("#slurp\n",
+                    "")
+
+    def test2(self):
+        r"""#slurp with 1 \n, leading whitespace
+        Should gobble"""
+        self.verify("       #slurp\n",
+                    "")
+        
+    def test3(self):
+        r"""#slurp with 1 \n, leading content
+        Shouldn't gobble"""
+        self.verify(" 1234 #slurp\n",
+                    " 1234 ")
+        
+    def test4(self):
+        r"""#slurp with WS then \n, leading content
+        Shouldn't gobble"""
+        self.verify(" 1234 #slurp    \n",
+                    " 1234 ")
+
+    def test5(self):
+        r"""#slurp with garbage chars then \n, leading content
+        Should eat the garbage"""
+        self.verify(" 1234 #slurp garbage   \n",
+                    " 1234 ")
+
+
+
+class EOLSlurpToken(OutputTest):
+    _EOLSlurpToken = DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']
+    def test1(self):
+        r"""#slurp with 1 \n """
+        self.verify("%s\n"%self._EOLSlurpToken,
+                    "")
+
+    def test2(self):
+        r"""#slurp with 1 \n, leading whitespace
+        Should gobble"""
+        self.verify("       %s\n"%self._EOLSlurpToken,
+                    "")
+    def test3(self):
+        r"""#slurp with 1 \n, leading content
+        Shouldn't gobble"""
+        self.verify(" 1234 %s\n"%self._EOLSlurpToken,
+                    " 1234 ")
+        
+    def test4(self):
+        r"""#slurp with WS then \n, leading content
+        Shouldn't gobble"""
+        self.verify(" 1234 %s    \n"%self._EOLSlurpToken,
+                    " 1234 ")
+
+    def test5(self):
+        r"""#slurp with garbage chars then \n, leading content
+        Should NOT eat the garbage"""
+        self.verify(" 1234 %s garbage   \n"%self._EOLSlurpToken,
+                    " 1234 %s garbage   \n"%self._EOLSlurpToken)
+
+if not DEFAULT_COMPILER_SETTINGS['EOLSlurpToken']:
+    del EOLSlurpToken
+
+class RawDirective(OutputTest):
+    def test1(self):
+        """#raw till EOF"""
+        self.verify("#raw\n$aFunc().\n\n",
+                    "$aFunc().\n\n")
+
+    def test2(self):
+        """#raw till #end raw"""
+        self.verify("#raw\n$aFunc().\n#end raw\n$anInt",
+                    "$aFunc().\n1")
+        
+    def test3(self):
+        """#raw till #end raw gobble WS"""
+        self.verify("  #raw  \n$aFunc().\n   #end raw  \n$anInt",
+                    "$aFunc().\n1")
+
+    def test4(self):
+        """#raw till #end raw using explicit directive closure
+        Shouldn't gobble"""
+        self.verify("  #raw  #\n$aFunc().\n   #end raw  #\n$anInt",
+                    "  \n$aFunc().\n\n1")
+
+    def test5(self):
+        """single-line short form #raw: """
+        self.verify("#raw: $aFunc().\n\n",
+                    "$aFunc().\n\n")
+
+        self.verify("#raw: $aFunc().\n$anInt",
+                    "$aFunc().\n1")
+
+class BreakpointDirective(OutputTest):
+    def test1(self):
+        """#breakpoint part way through source code"""
+        self.verify("$aFunc(2).\n#breakpoint\n$anInt",
+                    "2.\n")
+
+    def test2(self):
+        """#breakpoint at BOF"""
+        self.verify("#breakpoint\n$anInt",
+                    "")
+
+    def test3(self):
+        """#breakpoint at EOF"""
+        self.verify("$anInt\n#breakpoint",
+                    "1\n")
+
+
+class StopDirective(OutputTest):
+    def test1(self):
+        """#stop part way through source code"""
+        self.verify("$aFunc(2).\n#stop\n$anInt",
+                    "2.\n")
+
+    def test2(self):
+        """#stop at BOF"""
+        self.verify("#stop\n$anInt",
+                    "")
+
+    def test3(self):
+        """#stop at EOF"""
+        self.verify("$anInt\n#stop",
+                    "1\n")
+
+    def test4(self):
+        """#stop in pos test block"""
+        self.verify("""$anInt
+#if 1
+inside the if block
+#stop
+#end if
+blarg""",
+        "1\ninside the if block\n")
+
+    def test5(self):
+        """#stop in neg test block"""
+        self.verify("""$anInt
+#if 0
+inside the if block
+#stop
+#end if
+blarg""",
+        "1\nblarg")
+
+
+class ReturnDirective(OutputTest):
+    
+    def test1(self):
+        """#return'ing an int """
+        self.verify("""1
+$str($test-6)
+3
+#def test
+#if 1
+#return (3   *2)  \
+  + 2 
+#else
+aoeuoaeu
+#end if
+#end def
+""",
+                    "1\n2\n3\n")
+
+    def test2(self):
+        """#return'ing an string """
+        self.verify("""1
+$str($test[1])
+3
+#def test
+#if 1
+#return '123'
+#else
+aoeuoaeu
+#end if
+#end def
+""",
+                    "1\n2\n3\n")
+
+    def test3(self):
+        """#return'ing an string AND streaming other output via the transaction"""
+        self.verify("""1
+$str($test(trans=trans)[1])
+3
+#def test
+1.5
+#if 1
+#return '123'
+#else
+aoeuoaeu
+#end if
+#end def
+""",
+                    "1\n1.5\n2\n3\n")
+
+
+class YieldDirective(OutputTest):
+    convertEOLs = False
+    def test1(self):
+        """simple #yield """
+        
+        src1 = """#for i in range(10)\n#yield i\n#end for"""
+        src2 = """#for i in range(10)\n$i#slurp\n#yield\n#end for"""
+        src3 = ("#def iterator\n"
+               "#for i in range(10)\n#yield i\n#end for\n"
+               "#end def\n"
+               "#for i in $iterator\n$i#end for"
+               )
+
+
+        for src in (src1,src2,src3):
+            klass = Template.compile(src, keepRefToGeneratedCode=True)
+            #print klass._CHEETAH_generatedModuleCode
+            iter = klass().respond()
+            output = [str(i) for i in iter]
+            assert ''.join(output)=='0123456789'
+            #print ''.join(output)
+
+        # @@TR: need to expand this to cover error conditions etc.
+
+if versionTuple < (2,3):
+    del YieldDirective
+        
+class ForDirective(OutputTest):
+
+    def test1(self):
+        """#for loop with one local var"""
+        self.verify("#for $i in range(5)\n$i\n#end for",
+                    "0\n1\n2\n3\n4\n")
+
+        self.verify("#for $i in range(5):\n$i\n#end for",
+                    "0\n1\n2\n3\n4\n")
+
+        self.verify("#for $i in range(5): ##comment\n$i\n#end for",
+                    "0\n1\n2\n3\n4\n")
+
+        self.verify("#for $i in range(5) ##comment\n$i\n#end for",
+                    "0\n1\n2\n3\n4\n")
+
+
+    def test2(self):
+        """#for loop with WS in loop"""
+        self.verify("#for $i in range(5)\n$i \n#end for",
+                    "0 \n1 \n2 \n3 \n4 \n")
+        
+    def test3(self):
+        """#for loop gobble WS"""
+        self.verify("   #for $i in range(5)   \n$i \n   #end for   ",
+                    "0 \n1 \n2 \n3 \n4 \n")
+
+    def test4(self):
+        """#for loop over list"""
+        self.verify("#for $i, $j in [(0,1),(2,3)]\n$i,$j\n#end for",
+                    "0,1\n2,3\n")
+        
+    def test5(self):
+        """#for loop over list, with #slurp"""
+        self.verify("#for $i, $j in [(0,1),(2,3)]\n$i,$j#slurp\n#end for",
+                    "0,12,3")
+
+    def test6(self):
+        """#for loop with explicit closures"""
+        self.verify("#for $i in range(5)#$i#end for#",
+                    "01234")
+
+    def test7(self):
+        """#for loop with explicit closures and WS"""
+        self.verify("  #for $i in range(5)#$i#end for#  ",
+                    "  01234  ")
+
+    def test8(self):
+        """#for loop using another $var"""
+        self.verify("  #for $i in range($aFunc(5))#$i#end for#  ",
+                    "  01234  ")
+
+    def test9(self):
+        """test methods in for loops"""
+        self.verify("#for $func in $listOfLambdas\n$func($anInt)\n#end for",
+                    "1\n1\n1\n")
+
+
+    def test10(self):
+        """#for loop over list, using methods of the items"""
+        self.verify("#for i, j in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+        self.verify("#for $i, $j in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+
+    def test11(self):
+        """#for loop over list, using ($i,$j) style target list"""
+        self.verify("#for (i, j) in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+        self.verify("#for ($i, $j) in [('aa','bb'),('cc','dd')]\n$i.upper,$j.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+
+    def test12(self):
+        """#for loop over list, using i, (j,k) style target list"""
+        self.verify("#for i, (j, k) in enumerate([('aa','bb'),('cc','dd')])\n$j.upper,$k.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+        self.verify("#for $i, ($j, $k) in enumerate([('aa','bb'),('cc','dd')])\n$j.upper,$k.upper\n#end for",
+                    "AA,BB\nCC,DD\n")
+
+    def test13(self):
+        """single line #for"""
+        self.verify("#for $i in range($aFunc(5)): $i",
+                    "01234")
+
+    def test14(self):
+        """single line #for with 1 extra leading space"""
+        self.verify("#for $i in range($aFunc(5)):  $i",
+                    " 0 1 2 3 4")
+
+    def test15(self):
+        """2 times single line #for"""
+        self.verify("#for $i in range($aFunc(5)): $i#slurp\n"*2,
+                    "01234"*2)
+
+    def test16(self):
+        """false single line #for """
+        self.verify("#for $i in range(5): \n$i\n#end for",
+                    "0\n1\n2\n3\n4\n")
+
+if versionTuple < (2,3):
+    del ForDirective.test12
+
+class RepeatDirective(OutputTest):
+
+    def test1(self):
+        """basic #repeat"""
+        self.verify("#repeat 3\n1\n#end repeat",
+                    "1\n1\n1\n")
+        self.verify("#repeat 3: \n1\n#end repeat",
+                    "1\n1\n1\n")
+
+        self.verify("#repeat 3 ##comment\n1\n#end repeat",
+                    "1\n1\n1\n")
+
+        self.verify("#repeat 3: ##comment\n1\n#end repeat",
+                    "1\n1\n1\n")
+
+    def test2(self):
+        """#repeat with numeric expression"""
+        self.verify("#repeat 3*3/3\n1\n#end repeat",
+                    "1\n1\n1\n")
+    
+    def test3(self):
+        """#repeat with placeholder"""
+        self.verify("#repeat $numTwo\n1\n#end repeat",
+                    "1\n1\n")
+    
+    def test4(self):
+        """#repeat with placeholder * num"""
+        self.verify("#repeat $numTwo*1\n1\n#end repeat",
+                    "1\n1\n")
+        
+    def test5(self):
+        """#repeat with placeholder and WS"""
+        self.verify("   #repeat $numTwo   \n1\n   #end repeat   ",
+                    "1\n1\n")
+
+    def test6(self):
+        """single-line #repeat"""
+        self.verify("#repeat $numTwo: 1",
+                    "11")
+        self.verify("#repeat $numTwo: 1\n"*2,
+                    "1\n1\n"*2)
+
+        #false single-line
+        self.verify("#repeat 3:  \n1\n#end repeat",
+                    "1\n1\n1\n")
+
+
+class AttrDirective(OutputTest):
+
+    def test1(self):
+        """#attr with int"""
+        self.verify("#attr $test = 1234\n$test",
+                    "1234")
+
+    def test2(self):
+        """#attr with string"""
+        self.verify("#attr $test = 'blarg'\n$test",
+                    "blarg")
+
+    def test3(self):
+        """#attr with expression"""
+        self.verify("#attr $test = 'blarg'.upper()*2\n$test",
+                    "BLARGBLARG")
+
+    def test4(self):
+        """#attr with string + WS
+        Should gobble"""
+        self.verify("     #attr $test = 'blarg'   \n$test",
+                    "blarg")
+
+    def test5(self):
+        """#attr with string + WS + leading text
+        Shouldn't gobble"""
+        self.verify("  --   #attr $test = 'blarg'   \n$test",
+                    "  --   \nblarg")
+
+
+class DefDirective(OutputTest):
+
+    def test1(self):
+        """#def without argstring"""
+        self.verify("#def testMeth\n1234\n#end def\n$testMeth",
+                    "1234\n")
+
+        self.verify("#def testMeth ## comment\n1234\n#end def\n$testMeth",
+                    "1234\n")
+
+        self.verify("#def testMeth: ## comment\n1234\n#end def\n$testMeth",
+                    "1234\n")
+
+    def test2(self):
+        """#def without argstring, gobble WS"""
+        self.verify("   #def testMeth  \n1234\n    #end def   \n$testMeth",
+                    "1234\n")
+
+    def test3(self):
+        """#def with argstring, gobble WS"""
+        self.verify("  #def testMeth($a=999)   \n1234-$a\n  #end def\n$testMeth",
+                    "1234-999\n")
+
+    def test4(self):
+        """#def with argstring, gobble WS, string used in call"""
+        self.verify("  #def testMeth($a=999)   \n1234-$a\n  #end def\n$testMeth('ABC')",
+                    "1234-ABC\n")
+
+    def test5(self):
+        """#def with argstring, gobble WS, list used in call"""
+        self.verify("  #def testMeth($a=999)   \n1234-$a\n  #end def\n$testMeth([1,2,3])",
+                    "1234-[1, 2, 3]\n")
+
+    def test6(self):
+        """#def with 2 args, gobble WS, list used in call"""
+        self.verify("  #def testMeth($a, $b='default')   \n1234-$a$b\n  #end def\n$testMeth([1,2,3])",
+                    "1234-[1, 2, 3]default\n")
+
+    def test7(self):
+        """#def with *args, gobble WS"""
+        self.verify("  #def testMeth($*args)   \n1234-$args\n  #end def\n$testMeth",
+                    "1234-()\n")
+
+    def test8(self):
+        """#def with **KWs, gobble WS"""
+        self.verify("  #def testMeth($**KWs)   \n1234-$KWs\n  #end def\n$testMeth",
+                    "1234-{}\n")
+
+    def test9(self):
+        """#def with *args + **KWs, gobble WS"""
+        self.verify("  #def testMeth($*args, $**KWs)   \n1234-$args-$KWs\n  #end def\n$testMeth",
+                    "1234-()-{}\n")
+
+    def test10(self):
+        """#def with *args + **KWs, gobble WS"""
+        self.verify(
+            "  #def testMeth($*args, $**KWs)   \n1234-$args-$KWs.a\n  #end def\n$testMeth(1,2, a=1)",
+            "1234-(1, 2)-1\n")
+
+
+    def test11(self):
+        """single line #def with extra WS"""
+        self.verify(
+            "#def testMeth: aoeuaoeu\n- $testMeth -",
+            "- aoeuaoeu -")
+
+    def test12(self):
+        """single line #def with extra WS and nested $placeholders"""
+        self.verify(
+            "#def testMeth: $anInt $aFunc(1234)\n- $testMeth -",
+            "- 1 1234 -")
+
+    def test13(self):
+        """single line #def escaped $placeholders"""
+        self.verify(
+            "#def testMeth: \$aFunc(\$anInt)\n- $testMeth -",
+            "- $aFunc($anInt) -")
+
+    def test14(self):
+        """single line #def 1 escaped $placeholders"""
+        self.verify(
+            "#def testMeth: \$aFunc($anInt)\n- $testMeth -",
+            "- $aFunc(1) -")
+
+    def test15(self):
+        """single line #def 1 escaped $placeholders + more WS"""
+        self.verify(
+            "#def testMeth    : \$aFunc($anInt)\n- $testMeth -",
+            "- $aFunc(1) -")
+
+    def test16(self):
+        """multiline #def with $ on methodName"""
+        self.verify("#def $testMeth\n1234\n#end def\n$testMeth",
+                    "1234\n")
+
+    def test17(self):
+        """single line #def with $ on methodName"""
+        self.verify("#def $testMeth:1234\n$testMeth",
+                    "1234")
+
+    def test18(self):
+        """single line #def with an argument"""
+        self.verify("#def $testMeth($arg=1234):$arg\n$testMeth",
+                    "1234")
+
+    def test19(self):
+        """#def that extends over two lines with arguments"""
+        self.verify("#def $testMeth($arg=1234,\n"
+                    +"  $arg2=5678)\n"
+                    +"$arg $arg2\n"
+                    +"#end def\n"
+                    +"$testMeth",
+                    "1234 5678\n")
+
+class DecoratorDirective(OutputTest):
+    def test1(self):
+        """single line #def with decorator"""
+
+        self.verify("#@ blah", "#@ blah")
+        self.verify("#@23 blah", "#@23 blah")
+        self.verify("#@@TR: comment", "#@@TR: comment")
+
+        self.verify("#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
+                    +"#@testdecorator"
+                    +"\n#def $testMeth():1234\n$testMeth",
+                    
+                    "1234")
+
+        self.verify("#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
+                    +"#@testdecorator"
+                    +"\n#block $testMeth():1234",
+                    
+                    "1234")
+
+        try:
+            self.verify(
+                "#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
+                +"#@testdecorator\n sdf"
+                +"\n#def $testMeth():1234\n$testMeth",                        
+
+                "1234")
+        except ParseError:
+            pass
+        else:
+            self.fail('should raise a ParseError')
+
+    def test2(self):
+        """#def with multiple decorators"""
+        self.verify("#from Cheetah.Tests.SyntaxAndOutput import testdecorator\n"
+                    +"#@testdecorator\n"
+                    +"#@testdecorator\n"
+                    +"#def testMeth\n"
+                    +"1234\n"
+                    "#end def\n"
+                    "$testMeth",
+                    "1234\n")
+
+if versionTuple < (2,4):
+    del DecoratorDirective
+
+class BlockDirective(OutputTest):
+
+    def test1(self):
+        """#block without argstring"""
+        self.verify("#block testBlock\n1234\n#end block",
+                    "1234\n")
+
+        self.verify("#block testBlock ##comment\n1234\n#end block",
+                    "1234\n")
+
+    def test2(self):
+        """#block without argstring, gobble WS"""
+        self.verify("  #block testBlock   \n1234\n  #end block  ",
+                    "1234\n")
+
+    def test3(self):
+        """#block with argstring, gobble WS
+
+        Because blocks can be reused in multiple parts of the template arguments
+        (!!with defaults!!) can be given."""
+        
+        self.verify("  #block testBlock($a=999)   \n1234-$a\n  #end block  ",
+                    "1234-999\n")
+
+    def test4(self):
+        """#block with 2 args, gobble WS"""
+        self.verify("  #block testBlock($a=999, $b=444)   \n1234-$a$b\n  #end block  ",
+                    "1234-999444\n")
+
+
+    def test5(self):
+        """#block with 2 nested blocks
+
+        Blocks can be nested to any depth and the name of the block is optional
+        for the #end block part: #end block OR #end block [name] """
+        
+        self.verify("""#block testBlock
+this is a test block
+#block outerNest
+outer
+#block innerNest
+inner
+#end block innerNest
+#end block outerNest
+---
+#end block testBlock
+""",
+                    "this is a test block\nouter\ninner\n---\n")
+
+
+    def test6(self):
+        """single line #block """
+        self.verify(
+            "#block testMeth: This is my block",
+            "This is my block")
+
+    def test7(self):
+        """single line #block with WS"""
+        self.verify(
+            "#block testMeth: This is my block",
+            "This is my block")
+
+    def test8(self):
+        """single line #block 1 escaped $placeholders"""
+        self.verify(
+            "#block testMeth: \$aFunc($anInt)",
+            "$aFunc(1)")
+
+    def test9(self):
+        """single line #block 1 escaped $placeholders + WS"""
+        self.verify(
+            "#block testMeth: \$aFunc( $anInt )",
+            "$aFunc( 1 )")
+
+    def test10(self):
+        """single line #block 1 escaped $placeholders + more WS"""
+        self.verify(
+            "#block testMeth  : \$aFunc( $anInt )",
+            "$aFunc( 1 )")
+
+    def test11(self):
+        """multiline #block $ on argstring"""
+        self.verify("#block $testBlock\n1234\n#end block",
+                    "1234\n")
+
+    def test12(self):
+        """single line #block with $ on methodName """
+        self.verify(
+            "#block $testMeth: This is my block",
+            "This is my block")
+
+    def test13(self):
+        """single line #block with an arg """
+        self.verify(
+            "#block $testMeth($arg='This is my block'): $arg",
+            "This is my block")
+
+    def test14(self):
+        """single line #block with None for content"""
+        self.verify(
+            """#block $testMeth: $None\ntest $testMeth-""",
+            "test -")
+
+    def test15(self):
+        """single line #block with nothing for content"""
+        self.verify(
+            """#block $testMeth: \nfoo\n#end block\ntest $testMeth-""",
+            "foo\ntest foo\n-")
+
+class IncludeDirective(OutputTest):
+
+    def setUp(self):
+        fp = open('parseTest.txt','w')
+        fp.write("$numOne $numTwo")
+        fp.flush()
+        fp.close
+
+    def tearDown(self):
+        if os.path.exists('parseTest.txt'):
+            os.remove('parseTest.txt')
+
+    def test1(self):
+        """#include raw of source $emptyString"""
+        self.verify("#include raw source=$emptyString",
+                    "")
+
+    def test2(self):
+        """#include raw of source $blockToBeParsed"""
+        self.verify("#include raw source=$blockToBeParsed",
+                    "$numOne $numTwo")
+
+    def test3(self):
+        """#include raw of 'parseTest.txt'"""
+        self.verify("#include raw 'parseTest.txt'",
+                    "$numOne $numTwo")
+
+    def test4(self):
+        """#include raw of $includeFileName"""
+        self.verify("#include raw $includeFileName",
+                    "$numOne $numTwo")
+
+    def test5(self):
+        """#include raw of $includeFileName, with WS"""
+        self.verify("       #include raw $includeFileName      ",
+                    "$numOne $numTwo")
+
+    def test6(self):
+        """#include raw of source= , with WS"""
+        self.verify("       #include raw source='This is my $Source '*2      ",
+                    "This is my $Source This is my $Source ")
+
+    def test7(self):
+        """#include of $blockToBeParsed"""
+        self.verify("#include source=$blockToBeParsed",
+                    "1 2")
+        
+    def test8(self):
+        """#include of $blockToBeParsed, with WS"""
+        self.verify("   #include source=$blockToBeParsed   ",
+                    "1 2")
+
+    def test9(self):
+        """#include of 'parseTest.txt', with WS"""
+        self.verify("   #include source=$blockToBeParsed   ",
+                    "1 2")
+
+    def test10(self):
+        """#include of "parseTest.txt", with WS"""
+        self.verify("   #include source=$blockToBeParsed   ",
+                    "1 2")
+        
+    def test11(self):
+        """#include of 'parseTest.txt', with WS and surrounding text"""
+        self.verify("aoeu\n  #include source=$blockToBeParsed  \naoeu",
+                    "aoeu\n1 2aoeu")
+
+    def test12(self):
+        """#include of 'parseTest.txt', with WS and explicit closure"""
+        self.verify("  #include source=$blockToBeParsed#  ",
+                    "  1 2  ")
+
+
+class SilentDirective(OutputTest):
+
+    def test1(self):
+        """simple #silent"""
+        self.verify("#silent $aFunc",
+                    "")
+
+    def test2(self):
+        """simple #silent"""
+        self.verify("#silent $anObj.callIt\n$anObj.callArg",
+                    "1234")
+
+        self.verify("#silent $anObj.callIt ##comment\n$anObj.callArg",
+                    "1234")
+
+    def test3(self):
+        """simple #silent"""
+        self.verify("#silent $anObj.callIt(99)\n$anObj.callArg",
+                    "99")
+
+class SetDirective(OutputTest):
+
+    def test1(self):
+        """simple #set"""
+        self.verify("#set $testVar = 'blarg'\n$testVar",
+                    "blarg")
+        self.verify("#set testVar = 'blarg'\n$testVar",
+                    "blarg")
+
+
+        self.verify("#set testVar = 'blarg'##comment\n$testVar",
+                    "blarg")
+
+    def test2(self):
+        """simple #set with no WS between operands"""
+        self.verify("#set       $testVar='blarg'",
+                    "")
+    def test3(self):
+        """#set + use of var"""
+        self.verify("#set $testVar = 'blarg'\n$testVar",
+                    "blarg")
+        
+    def test4(self):
+        """#set + use in an #include"""
+        self.verify("#set global $aSetVar = 1234\n#include source=$includeBlock2",
+                    "1 2 1234")
+
+    def test5(self):
+        """#set with a dictionary"""
+        self.verify(     """#set $testDict = {'one':'one1','two':'two2','three':'three3'}
+$testDict.one
+$testDict.two""",
+                         "one1\ntwo2")
+
+    def test6(self):
+        """#set with string, then used in #if block"""
+    
+        self.verify("""#set $test='a string'\n#if $test#blarg#end if""",
+                    "blarg")
+
+    def test7(self):
+        """simple #set, gobble WS"""
+        self.verify("   #set $testVar = 'blarg'   ",
+                    "")
+
+    def test8(self):
+        """simple #set, don't gobble WS"""
+        self.verify("  #set $testVar = 'blarg'#---",
+                    "  ---")
+
+    def test9(self):
+        """simple #set with a list"""
+        self.verify("   #set $testVar = [1, 2, 3]  \n$testVar",
+                    "[1, 2, 3]")
+
+    def test10(self):
+        """simple #set global with a list"""
+        self.verify("   #set global $testVar = [1, 2, 3]  \n$testVar",
+                    "[1, 2, 3]")
+
+    def test11(self):
+        """simple #set global with a list and *cache
+
+        Caching only works with global #set vars.  Local vars are not accesible
+        to the cache namespace.
+        """
+        
+        self.verify("   #set global $testVar = [1, 2, 3]  \n$*testVar",
+                    "[1, 2, 3]")
+
+    def test12(self):
+        """simple #set global with a list and *<int>*cache"""
+        self.verify("   #set global $testVar = [1, 2, 3]  \n$*5*testVar",
+                    "[1, 2, 3]")
+
+    def test13(self):
+        """simple #set with a list and *<float>*cache"""
+        self.verify("   #set global $testVar = [1, 2, 3]  \n$*.5*testVar",
+                    "[1, 2, 3]")
+
+    def test14(self):
+        """simple #set without NameMapper on"""
+        self.verify("""#compiler useNameMapper = 0\n#set $testVar = 1 \n$testVar""",
+                    "1")
+
+    def test15(self):
+        """simple #set without $"""
+        self.verify("""#set testVar = 1 \n$testVar""",
+                    "1")
+
+    def test16(self):
+        """simple #set global without $"""
+        self.verify("""#set global testVar = 1 \n$testVar""",
+                    "1")
+
+    def test17(self):
+        """simple #set module without $"""
+        self.verify("""#set module __foo__ = 'bar'\n$__foo__""",
+                    "bar")
+
+    def test18(self):
+        """#set with i,j=list style assignment"""
+        self.verify("""#set i,j = [1,2]\n$i$j""",
+                    "12")
+        self.verify("""#set $i,$j = [1,2]\n$i$j""",
+                    "12")
+
+    def test19(self):
+        """#set with (i,j)=list style assignment"""
+        self.verify("""#set (i,j) = [1,2]\n$i$j""",
+                    "12")
+        self.verify("""#set ($i,$j) = [1,2]\n$i$j""",
+                    "12")
+
+    def test20(self):
+        """#set with i, (j,k)=list style assignment"""
+        self.verify("""#set i, (j,k) = [1,(2,3)]\n$i$j$k""",
+                    "123")
+        self.verify("""#set $i, ($j,$k) = [1,(2,3)]\n$i$j$k""",
+                    "123")
+
+
+class IfDirective(OutputTest):
+
+    def test1(self):
+        """simple #if block"""
+        self.verify("#if 1\n$aStr\n#end if\n",
+                    "blarg\n")
+
+        self.verify("#if 1:\n$aStr\n#end if\n",
+                    "blarg\n")
+
+        self.verify("#if 1:   \n$aStr\n#end if\n",
+                    "blarg\n")
+
+        self.verify("#if 1: ##comment \n$aStr\n#end if\n",
+                        "blarg\n")
+
+        self.verify("#if 1 ##comment \n$aStr\n#end if\n",
+                        "blarg\n")
+
+        self.verify("#if 1##for i in range(10)#$i#end for##end if",
+                    '0123456789')
+
+        self.verify("#if 1: #for i in range(10)#$i#end for",
+                    '0123456789')
+
+        self.verify("#if 1: #for i in range(10):$i",
+                    '0123456789')
+
+    def test2(self):
+        """simple #if block, with WS"""
+        self.verify("   #if 1\n$aStr\n  #end if  \n",
+                    "blarg\n")
+    def test3(self):
+        """simple #if block, with WS and explicit closures"""
+        self.verify("   #if 1#\n$aStr\n  #end if #--\n",
+                    "   \nblarg\n  --\n")
+
+    def test4(self):
+        """#if block using $numOne"""
+        self.verify("#if $numOne\n$aStr\n#end if\n",
+                    "blarg\n")
+
+    def test5(self):
+        """#if block using $zero"""
+        self.verify("#if $zero\n$aStr\n#end if\n",
+                    "")
+    def test6(self):
+        """#if block using $emptyString"""
+        self.verify("#if $emptyString\n$aStr\n#end if\n",
+                    "")
+    def test7(self):
+        """#if ... #else ... block using a $emptyString"""
+        self.verify("#if $emptyString\n$anInt\n#else\n$anInt - $anInt\n#end if",
+                    "1 - 1\n")
+        
+    def test8(self):
+        """#if ... #elif ... #else ... block using a $emptyString"""
+        self.verify("#if $emptyString\n$c\n#elif $numOne\n$numOne\n#else\n$c - $c\n#end if",
+                    "1\n")
+
+    def test9(self):
+        """#if 'not' test, with #slurp"""
+        self.verify("#if not $emptyString\n$aStr#slurp\n#end if\n",
+                    "blarg")
+
+    def test10(self):
+        """#if block using $*emptyString
+
+        This should barf
+        """
+        try:
+            self.verify("#if $*emptyString\n$aStr\n#end if\n",
+                        "")
+        except ParseError:
+            pass
+        else:
+            self.fail('This should barf')
+
+    def test11(self):
+        """#if block using invalid top-level $(placeholder) syntax - should barf"""
+
+        for badSyntax in ("#if $*5*emptyString\n$aStr\n#end if\n",
+                          "#if ${emptyString}\n$aStr\n#end if\n",
+                          "#if $(emptyString)\n$aStr\n#end if\n",
+                          "#if $[emptyString]\n$aStr\n#end if\n",
+                          "#if $!emptyString\n$aStr\n#end if\n",
+                          ):
+            try:
+                self.verify(badSyntax, "")
+            except ParseError:
+                pass
+            else:
+                self.fail('This should barf')
+            
+    def test12(self):
+        """#if ... #else if ... #else ... block using a $emptyString
+        Same as test 8 but using else if instead of elif"""
+        self.verify("#if $emptyString\n$c\n#else if $numOne\n$numOne\n#else\n$c - $c\n#end if",
+                    "1\n")
+
+
+    def test13(self):
+        """#if# ... #else # ... block using a $emptyString with """
+        self.verify("#if $emptyString# $anInt#else#$anInt - $anInt#end if",
+                    "1 - 1")
+
+    def test14(self):
+        """single-line #if: simple"""
+        self.verify("#if $emptyString then 'true' else 'false'",
+                    "false")
+
+    def test15(self):
+        """single-line #if: more complex"""
+        self.verify("#if $anInt then 'true' else 'false'",
+                    "true")
+
+    def test16(self):
+        """single-line #if: with the words 'else' and 'then' in the output """
+        self.verify("#if ($anInt and not $emptyString==''' else ''') then $str('then') else 'else'",
+                    "then")
+
+    def test17(self):
+        """single-line #if:  """
+        self.verify("#if 1: foo\n#if 0: bar\n#if 1: foo",
+                    "foo\nfoo")
+
+
+        self.verify("#if 1: foo\n#if 0: bar\n#if 1: foo",
+                    "foo\nfoo")
+
+    def test18(self):
+        """single-line #if: \n#else: """
+        self.verify("#if 1: foo\n#elif 0: bar",
+                    "foo\n")
+
+        self.verify("#if 1: foo\n#elif 0: bar\n#else: blarg\n",
+                    "foo\n")
+
+        self.verify("#if 0: foo\n#elif 0: bar\n#else: blarg\n",
+                    "blarg\n")
+
+class UnlessDirective(OutputTest):
+    
+    def test1(self):
+        """#unless 1"""
+        self.verify("#unless 1\n 1234 \n#end unless",
+                    "")
+
+        self.verify("#unless 1:\n 1234 \n#end unless",
+                    "")
+
+        self.verify("#unless 1: ##comment\n 1234 \n#end unless",
+                    "")
+
+        self.verify("#unless 1 ##comment\n 1234 \n#end unless",
+                    "")
+
+
+    def test2(self):
+        """#unless 0"""
+        self.verify("#unless 0\n 1234 \n#end unless",
+                    " 1234 \n")
+
+    def test3(self):
+        """#unless $none"""
+        self.verify("#unless $none\n 1234 \n#end unless",
+                    " 1234 \n")
+
+    def test4(self):
+        """#unless $numTwo"""
+        self.verify("#unless $numTwo\n 1234 \n#end unless",
+                    "")
+
+    def test5(self):
+        """#unless $numTwo with WS"""
+        self.verify("   #unless $numTwo   \n 1234 \n    #end unless   ",
+                    "")
+
+    def test6(self):
+        """single-line #unless"""
+        self.verify("#unless 1: 1234", "")
+        self.verify("#unless 0: 1234", "1234")
+        self.verify("#unless 0: 1234\n"*2, "1234\n"*2)
+        
+class PSP(OutputTest):
+    
+    def test1(self):
+        """simple <%= [int] %>"""
+        self.verify("<%= 1234 %>",  "1234")
+
+    def test2(self):
+        """simple <%= [string] %>"""
+        self.verify("<%= 'blarg' %>", "blarg")
+
+    def test3(self):
+        """simple <%= None %>"""
+        self.verify("<%= None %>", "")
+    def test4(self):
+        """simple <%= [string] %> + $anInt"""
+        self.verify("<%= 'blarg' %>$anInt", "blarg1")
+
+    def test5(self):
+        """simple <%= [EXPR] %> + $anInt"""
+        self.verify("<%= ('blarg'*2).upper() %>$anInt", "BLARGBLARG1")
+
+    def test6(self):
+        """for loop in <%%>"""
+        self.verify("<% for i in range(5):%>1<%end%>", "11111")
+
+    def test7(self):
+        """for loop in <%%> and using <%=i%>"""
+        self.verify("<% for i in range(5):%><%=i%><%end%>", "01234")
+
+    def test8(self):
+        """for loop in <% $%> and using <%=i%>"""
+        self.verify("""<% for i in range(5):
+    i=i*2$%><%=i%><%end%>""", "02468")
+
+    def test9(self):
+        """for loop in <% $%> and using <%=i%> plus extra text"""
+        self.verify("""<% for i in range(5):
+    i=i*2$%><%=i%>-<%end%>""", "0-2-4-6-8-")
+
+
+class WhileDirective(OutputTest):
+    def test1(self):
+        """simple #while with a counter"""
+        self.verify("#set $i = 0\n#while $i < 5\n$i#slurp\n#set $i += 1\n#end while",
+                    "01234")
+
+class ContinueDirective(OutputTest):
+    def test1(self):
+        """#continue with a #while"""
+        self.verify("""#set $i = 0
+#while $i < 5
+#if $i == 3
+  #set $i += 1        
+  #continue
+#end if
+$i#slurp
+#set $i += 1
+#end while""",
+        "0124")
+
+    def test2(self):
+        """#continue with a #for"""
+        self.verify("""#for $i in range(5)
+#if $i == 3
+  #continue
+#end if
+$i#slurp
+#end for""",
+        "0124")
+
+class BreakDirective(OutputTest):
+    def test1(self):
+        """#break with a #while"""
+        self.verify("""#set $i = 0
+#while $i < 5
+#if $i == 3
+  #break
+#end if
+$i#slurp
+#set $i += 1
+#end while""",
+        "012")
+
+    def test2(self):
+        """#break with a #for"""
+        self.verify("""#for $i in range(5)
+#if $i == 3
+  #break
+#end if
+$i#slurp
+#end for""",
+        "012")
+
+
+class TryDirective(OutputTest):
+
+    def test1(self):
+        """simple #try 
+        """
+        self.verify("#try\n1234\n#except\nblarg\n#end try",
+                    "1234\n")
+
+    def test2(self):
+        """#try / #except with #raise
+        """
+        self.verify("#try\n#raise ValueError\n#except\nblarg\n#end try",
+                    "blarg\n")
+        
+    def test3(self):
+        """#try / #except with #raise + WS
+
+        Should gobble
+        """
+        self.verify("  #try  \n  #raise ValueError \n  #except \nblarg\n  #end try",
+                    "blarg\n")
+
+
+    def test4(self):
+        """#try / #except with #raise + WS and leading text
+        
+        Shouldn't gobble
+        """
+        self.verify("--#try  \n  #raise ValueError \n  #except \nblarg\n  #end try#--",
+                    "--\nblarg\n  --")
+
+    def test5(self):
+        """nested #try / #except with #raise
+        """
+        self.verify(
+"""#try
+  #raise ValueError
+#except
+  #try
+   #raise ValueError
+  #except
+blarg
+  #end try
+#end try""",
+                    "blarg\n")
+
+class PassDirective(OutputTest):
+    def test1(self):
+        """#pass in a #try / #except block
+        """
+        self.verify("#try\n#raise ValueError\n#except\n#pass\n#end try",
+                    "")
+
+    def test2(self):
+        """#pass in a #try / #except block + WS
+        """
+        self.verify("  #try  \n  #raise ValueError  \n  #except  \n   #pass   \n   #end try",
+                    "")
+
+
+class AssertDirective(OutputTest):
+    def test1(self):
+        """simple #assert 
+        """
+        self.verify("#set $x = 1234\n#assert $x == 1234",
+                    "")
+
+    def test2(self):
+        """simple #assert that fails
+        """
+        def test(self=self):
+            self.verify("#set $x = 1234\n#assert $x == 999",
+                        ""),
+        self.failUnlessRaises(AssertionError, test)
+        
+    def test3(self):
+        """simple #assert with WS
+        """
+        self.verify("#set $x = 1234\n   #assert $x == 1234   ",
+                    "")
+
+
+class RaiseDirective(OutputTest):
+    def test1(self):
+        """simple #raise ValueError
+
+        Should raise ValueError
+        """
+        def test(self=self):
+            self.verify("#raise ValueError",
+                        ""),
+        self.failUnlessRaises(ValueError, test)
+                              
+    def test2(self):
+        """#raise ValueError in #if block
+
+        Should raise ValueError
+        """
+        def test(self=self):
+            self.verify("#if 1\n#raise ValueError\n#end if\n",
+                        "")
+        self.failUnlessRaises(ValueError, test)
+
+
+    def test3(self):
+        """#raise ValueError in #if block
+
+        Shouldn't raise ValueError
+        """
+        self.verify("#if 0\n#raise ValueError\n#else\nblarg#end if\n",
+                    "blarg\n")
+
+
+
+class ImportDirective(OutputTest):
+    def test1(self):
+        """#import math
+        """
+        self.verify("#import math",
+                    "")
+
+    def test2(self):
+        """#import math + WS
+
+        Should gobble
+        """
+        self.verify("    #import math    ",
+                    "")
+
+    def test3(self):
+        """#import math + WS + leading text
+        
+        Shouldn't gobble
+        """
+        self.verify("  --  #import math    ",
+                    "  --  ")
+        
+    def test4(self):
+        """#from math import syn
+        """
+        self.verify("#from math import cos",
+                    "")
+
+    def test5(self):
+        """#from math import cos  + WS
+        Should gobble
+        """
+        self.verify("    #from math import cos  ",
+                    "")
+
+    def test6(self):
+        """#from math import cos  + WS + leading text
+        Shouldn't gobble
+        """
+        self.verify("  --  #from math import cos  ",
+                    "  --  ")
+
+    def test7(self):
+        """#from math import cos -- use it
+        """
+        self.verify("#from math import cos\n$cos(0)",
+                    "1.0")
+
+    def test8(self):
+        """#from math import cos,tan,sin -- and use them
+        """
+        self.verify("#from math import cos, tan, sin\n$cos(0)-$tan(0)-$sin(0)",
+                    "1.0-0.0-0.0")
+
+    def test9(self):
+        """#import os.path -- use it
+        """
+        
+        self.verify("#import os.path\n$os.path.exists('.')",
+                    repr(True))
+
+    def test10(self):
+        """#import os.path -- use it with NameMapper turned off
+        """
+        self.verify("""##
+#compiler-settings
+useNameMapper=False
+#end compiler-settings
+#import os.path
+$os.path.exists('.')""",
+                    repr(True))
+
+    def test11(self):
+        """#from math import *
+        """
+        
+        self.verify("#from math import *\n$pow(1,2) $log10(10)",
+                    "1.0 1.0")
+
+class CompilerDirective(OutputTest):
+    def test1(self):
+        """overriding the commentStartToken
+        """
+        self.verify("""$anInt##comment
+#compiler commentStartToken = '//'
+$anInt//comment
+""",
+                    "1\n1\n")
+
+    def test2(self):
+        """overriding and resetting the commentStartToken
+        """
+        self.verify("""$anInt##comment
+#compiler commentStartToken = '//'
+$anInt//comment
+#compiler reset
+$anInt//comment
+""",
+                    "1\n1\n1//comment\n")
+
+
+class CompilerSettingsDirective(OutputTest):
+    
+    def test1(self):
+        """overriding the cheetahVarStartToken
+        """
+        self.verify("""$anInt
+#compiler-settings
+cheetahVarStartToken = @
+#end compiler-settings
+ at anInt
+#compiler-settings reset
+$anInt
+""",
+                    "1\n1\n1\n")
+
+    def test2(self):
+        """overriding the directiveStartToken
+        """
+        self.verify("""#set $x = 1234
+$x
+#compiler-settings
+directiveStartToken = @
+#end compiler-settings
+ at set $x = 1234
+$x
+""",
+                    "1234\n1234\n")
+
+    def test3(self):
+        """overriding the commentStartToken
+        """
+        self.verify("""$anInt##comment
+#compiler-settings
+commentStartToken = //
+#end compiler-settings
+$anInt//comment
+""",
+                    "1\n1\n")
+
+if sys.platform.startswith('java'):
+    del CompilerDirective
+    del CompilerSettingsDirective
+
+class ExtendsDirective(OutputTest):
+
+    def test1(self):
+        """#extends Cheetah.Templates._SkeletonPage"""
+        self.verify("""#from Cheetah.Templates._SkeletonPage import _SkeletonPage
+#extends _SkeletonPage
+#implements respond
+$spacer()
+""",
+                    '<img src="spacer.gif" width="1" height="1" alt="" />\n')
+
+
+        self.verify("""#from Cheetah.Templates._SkeletonPage import _SkeletonPage
+#extends _SkeletonPage
+#implements respond(foo=1234)
+$spacer()$foo
+""",
+                    '<img src="spacer.gif" width="1" height="1" alt="" />1234\n')
+
+    def test2(self):
+        """#extends Cheetah.Templates.SkeletonPage without #import"""
+        self.verify("""#extends Cheetah.Templates.SkeletonPage
+#implements respond
+$spacer()
+""",
+                    '<img src="spacer.gif" width="1" height="1" alt="" />\n')
+
+    def test3(self):
+        """#extends Cheetah.Templates.SkeletonPage.SkeletonPage without #import"""
+        self.verify("""#extends Cheetah.Templates.SkeletonPage.SkeletonPage
+#implements respond
+$spacer()
+""",
+                    '<img src="spacer.gif" width="1" height="1" alt="" />\n')
+
+    def test4(self):
+        """#extends with globals and searchList test"""
+        self.verify("""#extends Cheetah.Templates.SkeletonPage
+#set global g="Hello"
+#implements respond
+$g $numOne
+""",
+                    'Hello 1\n')
+
+
+class SuperDirective(OutputTest):
+    def test1(self):
+        tmpl1 = Template.compile('''$foo $bar(99)
+        #def foo: this is base foo
+        #def bar(arg): super-$arg''')
+
+        tmpl2 = tmpl1.subclass('''
+        #implements dummy
+        #def foo
+          #super
+          This is child foo
+          #super(trans=trans)
+          $bar(1234)
+        #end def
+        #def bar(arg): #super($arg)
+        ''')
+        expected = ('this is base foo          '
+                    'This is child foo\nthis is base foo          '
+                    'super-1234\n super-99')
+        assert str(tmpl2()).strip()==expected
+
+
+class ImportantExampleCases(OutputTest):
+    def test1(self):
+        """how to make a comma-delimited list"""
+        self.verify("""#set $sep = ''
+#for $letter in $letterList
+$sep$letter#slurp
+#set $sep = ', '
+#end for
+""",
+                    "a, b, c")
+
+class FilterDirective(OutputTest):
+    convertEOLs=False
+
+    def _getCompilerSettings(self):
+        return {'useFilterArgsInPlaceholders':True}
+    
+    def test1(self):
+        """#filter Filter
+        """
+        self.verify("#filter Filter\n$none#end filter",
+                    "")
+
+        self.verify("#filter Filter: $none",
+                    "")
+
+    def test2(self):
+        """#filter ReplaceNone with WS
+        """
+        self.verify("#filter Filter  \n$none#end filter",
+                    "")
+
+    def test3(self):
+        """#filter MaxLen -- maxlen of 5"""
+
+        self.verify("#filter MaxLen  \n${tenDigits, $maxlen=5}#end filter",
+                    "12345")
+
+    def test4(self):
+        """#filter MaxLen -- no maxlen
+        """
+        self.verify("#filter MaxLen  \n${tenDigits}#end filter",
+                    "1234567890")
+
+    def test5(self):
+        """#filter WebSafe -- basic usage
+        """
+        self.verify("#filter WebSafe  \n$webSafeTest#end filter",
+                    "abc &lt;=&gt; &amp;")
+
+    def test6(self):
+        """#filter WebSafe -- also space
+        """
+        self.verify("#filter WebSafe  \n${webSafeTest, $also=' '}#end filter",
+                    "abc&nbsp;&lt;=&gt;&nbsp;&amp;")
+        
+    def test7(self):
+        """#filter WebSafe -- also space, without $ on the args
+        """
+        self.verify("#filter WebSafe  \n${webSafeTest, also=' '}#end filter",
+                    "abc&nbsp;&lt;=&gt;&nbsp;&amp;")
+
+    def test8(self):
+        """#filter Strip -- trailing newline
+        """
+        self.verify("#filter Strip\n$strip1#end filter",
+                    "strippable whitespace\n")
+
+    def test9(self):
+        """#filter Strip -- no trailing newine
+        """
+        self.verify("#filter Strip\n$strip2#end filter",
+                    "strippable whitespace")
+
+    def test10(self):
+        """#filter Strip -- multi-line
+        """
+        self.verify("#filter Strip\n$strip3#end filter",
+                    "strippable whitespace\n1 2  3\n")
+
+    def test11(self):
+        """#filter StripSqueeze -- canonicalize all whitespace to ' '
+        """
+        self.verify("#filter StripSqueeze\n$strip3#end filter",
+                    "strippable whitespace 1 2 3")
+
+
+class EchoDirective(OutputTest):
+    def test1(self):
+        """#echo 1234
+        """
+        self.verify("#echo 1234",
+                    "1234")
+
+class SilentDirective(OutputTest):
+    def test1(self):
+        """#silent 1234
+        """
+        self.verify("#silent 1234",
+                    "")
+
+class ErrorCatcherDirective(OutputTest):
+    pass
+
+
+class VarExists(OutputTest):               # Template.varExists()
+    
+    def test1(self):
+        """$varExists('$anInt')
+        """
+        self.verify("$varExists('$anInt')",
+                    repr(True))
+
+    def test2(self):
+        """$varExists('anInt')
+        """
+        self.verify("$varExists('anInt')",
+                    repr(True))
+
+    def test3(self):
+        """$varExists('$anInt')
+        """
+        self.verify("$varExists('$bogus')",
+                    repr(False))
+
+    def test4(self):
+        """$varExists('$anInt') combined with #if false
+        """
+        self.verify("#if $varExists('$bogus')\n1234\n#else\n999\n#end if",
+                    "999\n")
+
+    def test5(self):
+        """$varExists('$anInt') combined with #if true
+        """
+        self.verify("#if $varExists('$anInt')\n1234\n#else\n999#end if",
+                    "1234\n")
+
+class GetVar(OutputTest):               # Template.getVar()
+    def test1(self):
+        """$getVar('$anInt')
+        """
+        self.verify("$getVar('$anInt')",
+                    "1")
+
+    def test2(self):
+        """$getVar('anInt')
+        """
+        self.verify("$getVar('anInt')",
+                    "1")
+
+    def test3(self):
+        """$self.getVar('anInt')
+        """
+        self.verify("$self.getVar('anInt')",
+                    "1")
+        
+    def test4(self):
+        """$getVar('bogus', 1234)
+        """
+        self.verify("$getVar('bogus',  1234)",
+                    "1234")
+        
+    def test5(self):
+        """$getVar('$bogus', 1234)
+        """
+        self.verify("$getVar('$bogus',  1234)",
+                    "1234")
+
+
+class MiscComplexSyntax(OutputTest):
+    def test1(self):
+        """Complex use of {},[] and () in a #set expression
+        ----
+        #set $c = {'A':0}[{}.get('a', {'a' : 'A'}['a'])]
+        $c
+        """
+        self.verify("#set $c = {'A':0}[{}.get('a', {'a' : 'A'}['a'])]\n$c",
+                    "0")
+
+
+class CGI(OutputTest):
+    """CGI scripts with(out) the CGI environment and with(out) GET variables.
+    """
+    convertEOLs=False
+    
+    def _beginCGI(self):  
+        os.environ['REQUEST_METHOD'] = "GET"
+    def _endCGI(self):  
+        try:
+            del os.environ['REQUEST_METHOD']
+        except KeyError:
+            pass
+    _guaranteeNoCGI = _endCGI
+
+
+    def test1(self):
+        """A regular template."""
+        self._guaranteeNoCGI()
+        source = "#extends Cheetah.Tools.CGITemplate\n" + \
+                 "#implements respond\n" + \
+                 "$cgiHeaders#slurp\n" + \
+                 "Hello, world!" 
+        self.verify(source, "Hello, world!")
+
+
+    def test2(self):
+        """A CGI script."""
+        self._beginCGI()
+        source = "#extends Cheetah.Tools.CGITemplate\n" + \
+                 "#implements respond\n" + \
+                 "$cgiHeaders#slurp\n" + \
+                 "Hello, world!" 
+        self.verify(source, "Content-type: text/html\n\nHello, world!")
+        self._endCGI()
+
+
+    def test3(self):
+        """A (pseudo) Webware servlet.
+           
+           This uses the Python syntax escape to set
+           self._CHEETAH__isControlledByWebKit.           
+           We could instead do '#silent self._CHEETAH__isControlledByWebKit = True',
+           taking advantage of the fact that it will compile unchanged as long
+           as there's no '$' in the statement.  (It won't compile with an '$'
+           because that would convert to a function call, and you can't assign
+           to a function call.)  Because this isn't really being called from
+           Webware, we'd better not use any Webware services!  Likewise, we'd
+           better not call $cgiImport() because it would be misled.
+        """
+        self._beginCGI()
+        source = "#extends Cheetah.Tools.CGITemplate\n" + \
+                 "#implements respond\n" + \
+                 "<% self._CHEETAH__isControlledByWebKit = True %>#slurp\n" + \
+                 "$cgiHeaders#slurp\n" + \
+                 "Hello, world!"
+        self.verify(source, "Hello, world!")
+        self._endCGI()
+
+
+    def test4(self):
+        """A CGI script with a GET variable."""
+        self._beginCGI()
+        os.environ['QUERY_STRING'] = "cgiWhat=world"
+        source = "#extends Cheetah.Tools.CGITemplate\n" + \
+                 "#implements respond\n" + \
+                 "$cgiHeaders#slurp\n" + \
+                 "#silent $webInput(['cgiWhat'])##slurp\n" + \
+                 "Hello, $cgiWhat!"
+        self.verify(source, 
+                    "Content-type: text/html\n\nHello, world!")
+        del os.environ['QUERY_STRING']
+        self._endCGI()
+
+
+
+class WhitespaceAfterDirectiveTokens(OutputTest):
+    def _getCompilerSettings(self):
+        return {'allowWhitespaceAfterDirectiveStartToken':True}
+
+    def test1(self):
+        self.verify("# for i in range(10): $i",
+                    "0123456789")
+        self.verify("# for i in range(10)\n$i# end for",
+                    "0123456789")
+        self.verify("# for i in range(10)#$i#end for",
+                    "0123456789")
+
+
+
+class DefmacroDirective(OutputTest):
+    def _getCompilerSettings(self):
+        def aMacro(src):
+            return '$aStr'
+        
+        return {'macroDirectives':{'aMacro':aMacro
+                                   }}
+
+    def test1(self):
+        self.verify("""\
+#defmacro inc: #set @src +=1
+#set i = 1
+#inc: $i
+$i""",
+                    "2")
+
+
+
+        self.verify("""\
+#defmacro test
+#for i in range(10): @src
+#end defmacro
+#test: $i-foo#slurp
+#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo012")
+
+        self.verify("""\
+#defmacro test
+#for i in range(10): @src
+#end defmacro
+#test: $i-foo
+#for i in range(3): $i""",
+  "0-foo\n1-foo\n2-foo\n3-foo\n4-foo\n5-foo\n6-foo\n7-foo\n8-foo\n9-foo\n012")
+
+
+        self.verify("""\
+#defmacro test: #for i in range(10): @src
+#test: $i-foo#slurp
+-#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
+
+        self.verify("""\
+#defmacro test##for i in range(10): @src#end defmacro##slurp
+#test: $i-foo#slurp
+-#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
+
+        self.verify("""\
+#defmacro testFoo: nothing
+#defmacro test(foo=1234): #for i in range(10): @src
+#test foo=234: $i-foo#slurp
+-#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
+
+        self.verify("""\
+#defmacro testFoo: nothing
+#defmacro test(foo=1234): #for i in range(10): @src at foo
+#test foo='-foo'#$i#end test#-#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
+
+        self.verify("""\
+#defmacro testFoo: nothing
+#defmacro test(foo=1234): #for i in range(10): @src.strip()@foo
+#test foo='-foo': $i
+-#for i in range(3): $i""",
+                    "0-foo1-foo2-foo3-foo4-foo5-foo6-foo7-foo8-foo9-foo-012")
+
+    def test2(self):
+        self.verify("#aMacro: foo",
+                    "blarg")
+        self.verify("#defmacro nested: @macros.aMacro(@src)\n#nested: foo",
+                    "blarg")
+
+
+class Indenter(OutputTest):
+    convertEOLs=False
+    
+    source = """
+public class X
+{
+    #for $method in $methods
+        $getMethod($method)
+        
+    #end for
+}
+//end of class
+
+#def getMethod($method)
+    #indent ++
+    public $getType($method) ${method.Name}($getParams($method.Params));
+    #indent --
+#end def
+
+#def getParams($params)
+    #indent off
+
+    #for $counter in $range($len($params))
+        #if $counter == len($params) - 1
+                       $params[$counter]#slurp
+        #else:
+                       $params[$counter], 
+        #end if
+    #end for
+    #indent on
+#end def
+
+#def getType($method)
+    #indent push
+    #indent=0
+    #if $method.Type == "VT_VOID"
+        void#slurp
+    #elif $method.Type == "VT_INT"
+        int#slurp
+    #elif $method.Type == "VT_VARIANT"
+        Object#slurp
+    #end if
+    #indent pop
+#end def
+"""
+
+    control = """
+public class X
+{
+    public void Foo(
+                       _input, 
+                       _output);
+
+
+    public int Bar(
+                       _str1, 
+                       str2, 
+                       _str3);
+
+
+    public Object Add(
+                       value1, 
+                       value);
+
+
+}
+//end of class
+
+
+
+"""
+    def _getCompilerSettings(self):
+        return {'useFilterArgsInPlaceholders':True}
+
+    def searchList(self):    # Inside Indenter class.
+        class Method:
+            def __init__(self, _name, _type, *_params):
+                self.Name = _name
+                self.Type = _type
+                self.Params = _params
+        methods = [Method("Foo", "VT_VOID", "_input", "_output"),
+                   Method("Bar", "VT_INT", "_str1", "str2", "_str3"),
+                   Method("Add", "VT_VARIANT", "value1", "value")]
+        return [{"methods": methods}]
+
+    def test1(self):    # Inside Indenter class.
+        self.verify(self.source, self.control)
+
+
+##################################################
+## CREATE CONVERTED EOL VERSIONS OF THE TEST CASES
+
+if OutputTest._useNewStyleCompilation and versionTuple >= (2,3):
+    extraCompileKwArgsForDiffBaseclass = {'baseclass':dict}
+else:
+    extraCompileKwArgsForDiffBaseclass = {'baseclass':object}
+    
+
+for klass in [var for var in globals().values()
+              if type(var) == types.ClassType and issubclass(var, unittest.TestCase)]:
+    name = klass.__name__        
+    if hasattr(klass,'convertEOLs') and klass.convertEOLs:
+        win32Src = r"class %(name)s_Win32EOL(%(name)s): _EOLreplacement = '\r\n'"%locals()
+        macSrc = r"class %(name)s_MacEOL(%(name)s): _EOLreplacement = '\r'"%locals()
+        #print win32Src
+        #print macSrc
+        exec win32Src+'\n'
+        exec macSrc+'\n'
+
+    if versionTuple >= (2,3):
+        src = r"class %(name)s_DiffBaseClass(%(name)s): "%locals()
+        src += " _extraCompileKwArgs = extraCompileKwArgsForDiffBaseclass"
+        exec src+'\n'
+
+    del name
+    del klass
+
+##################################################
+## if run from the command line ##
+        
+if __name__ == '__main__':
+    unittest.main()
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Template.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Template.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Template.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,336 @@
+#!/usr/bin/env python
+
+import pdb
+import sys
+import types
+import os
+import os.path
+import tempfile
+import shutil
+import unittest_local_copy as unittest
+from Cheetah.Template import Template
+
+majorVer, minorVer = sys.version_info[0], sys.version_info[1]
+versionTuple = (majorVer, minorVer)
+
+class TemplateTest(unittest.TestCase):
+    pass
+
+class ClassMethods_compile(TemplateTest):
+    """I am using the same Cheetah source for each test to root out clashes
+    caused by the compile caching in Template.compile().
+    """
+    
+    def test_basicUsage(self):
+        klass = Template.compile(source='$foo')
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+
+    def test_baseclassArg(self):
+        klass = Template.compile(source='$foo', baseclass=dict)
+        t = klass({'foo':1234})
+        assert str(t)=='1234'
+
+        klass2 = Template.compile(source='$foo', baseclass=klass)
+        t = klass2({'foo':1234})
+        assert str(t)=='1234'
+
+        klass3 = Template.compile(source='#implements dummy\n$bar', baseclass=klass2)
+        t = klass3({'foo':1234})
+        assert str(t)=='1234'
+
+        klass4 = Template.compile(source='$foo', baseclass='dict')
+        t = klass4({'foo':1234})
+        assert str(t)=='1234'
+
+    def test_moduleFileCaching(self):
+        if versionTuple < (2,3):
+            return
+        tmpDir = tempfile.mkdtemp()
+        try:
+            #print tmpDir
+            assert os.path.exists(tmpDir)
+            klass = Template.compile(source='$foo',
+                                     cacheModuleFilesForTracebacks=True,
+                                     cacheDirForModuleFiles=tmpDir)
+            mod = sys.modules[klass.__module__]
+            #print mod.__file__
+            assert os.path.exists(mod.__file__)
+            assert os.path.dirname(mod.__file__)==tmpDir
+        finally:
+            shutil.rmtree(tmpDir, True)
+
+    def test_classNameArg(self):
+        klass = Template.compile(source='$foo', className='foo123')
+        assert klass.__name__=='foo123'
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+
+    def test_moduleNameArg(self):
+        klass = Template.compile(source='$foo', moduleName='foo99')
+        mod = sys.modules['foo99']
+        assert klass.__name__=='foo99'
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+
+
+        klass = Template.compile(source='$foo',
+                                 moduleName='foo1',
+                                 className='foo2')
+        mod = sys.modules['foo1']
+        assert klass.__name__=='foo2'
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+
+
+    def test_mainMethodNameArg(self):
+        klass = Template.compile(source='$foo',
+                                 className='foo123',
+                                 mainMethodName='testMeth')
+        assert klass.__name__=='foo123'
+        t = klass(namespaces={'foo':1234})
+        #print t.generatedClassCode()
+        assert str(t)=='1234'
+        assert t.testMeth()=='1234'
+
+        klass = Template.compile(source='$foo',
+                                 moduleName='fooXXX',                                 
+                                 className='foo123',
+                                 mainMethodName='testMeth',
+                                 baseclass=dict)
+        assert klass.__name__=='foo123'
+        t = klass({'foo':1234})
+        #print t.generatedClassCode()
+        assert str(t)=='1234'
+        assert t.testMeth()=='1234'
+
+
+
+    def test_moduleGlobalsArg(self):
+        klass = Template.compile(source='$foo',
+                                 moduleGlobals={'foo':1234})
+        t = klass()
+        assert str(t)=='1234'
+
+        klass2 = Template.compile(source='$foo', baseclass='Test1',
+                                  moduleGlobals={'Test1':dict})
+        t = klass2({'foo':1234})
+        assert str(t)=='1234'
+
+        klass3 = Template.compile(source='$foo', baseclass='Test1',
+                                  moduleGlobals={'Test1':dict, 'foo':1234})
+        t = klass3()
+        assert str(t)=='1234'
+
+
+    def test_keepRefToGeneratedCodeArg(self):
+        klass = Template.compile(source='$foo',
+                                 className='unique58',
+                                 cacheCompilationResults=False,
+                                 keepRefToGeneratedCode=False)
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        assert not t.generatedModuleCode()
+
+
+        klass2 = Template.compile(source='$foo',
+                                 className='unique58',
+                                 keepRefToGeneratedCode=True)
+        t = klass2(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        assert t.generatedModuleCode()
+
+        klass3 = Template.compile(source='$foo',
+                                 className='unique58',
+                                 keepRefToGeneratedCode=False)
+        t = klass3(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        # still there as this class came from the cache
+        assert t.generatedModuleCode() 
+
+
+    def test_compilationCache(self):
+        klass = Template.compile(source='$foo',
+                                 className='unique111',
+                                 cacheCompilationResults=False)
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        assert not klass._CHEETAH_isInCompilationCache
+
+
+        # this time it will place it in the cache
+        klass = Template.compile(source='$foo',
+                                 className='unique111',
+                                 cacheCompilationResults=True)
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        assert klass._CHEETAH_isInCompilationCache
+
+        # by default it will be in the cache
+        klass = Template.compile(source='$foo',
+                                 className='unique999099')
+        t = klass(namespaces={'foo':1234})
+        assert str(t)=='1234'
+        assert klass._CHEETAH_isInCompilationCache
+
+
+class ClassMethods_subclass(TemplateTest):
+
+    def test_basicUsage(self):
+        klass = Template.compile(source='$foo', baseclass=dict)
+        t = klass({'foo':1234})
+        assert str(t)=='1234'
+
+        klass2 = klass.subclass(source='$foo')
+        t = klass2({'foo':1234})
+        assert str(t)=='1234'
+
+        klass3 = klass2.subclass(source='#implements dummy\n$bar')
+        t = klass3({'foo':1234})
+        assert str(t)=='1234'
+        
+
+class Preprocessors(TemplateTest):
+
+    def test_basicUsage1(self):
+        src='''\
+        %set foo = @a
+        $(@foo*10)
+        @a'''
+        src = '\n'.join([ln.strip() for ln in src.splitlines()])
+        preprocessors = {'tokens':'@ %',
+                         'namespaces':{'a':99}
+                         }
+        klass = Template.compile(src, preprocessors=preprocessors)
+        assert str(klass())=='990\n99'
+
+    def test_normalizePreprocessorArgVariants(self):
+        src='%set foo = 12\n%%comment\n$(@foo*10)'
+
+        class Settings1: tokens = '@ %' 
+        Settings1 = Settings1()
+            
+        from Cheetah.Template import TemplatePreprocessor
+        settings = Template._normalizePreprocessorSettings(Settings1)
+        preprocObj = TemplatePreprocessor(settings)
+
+        def preprocFunc(source, file):
+            return '$(12*10)', None
+
+        class TemplateSubclass(Template):
+            pass
+
+        compilerSettings = {'cheetahVarStartToken':'@',
+                            'directiveStartToken':'%',
+                            'commentStartToken':'%%',
+                            }
+        
+        for arg in ['@ %',
+                    {'tokens':'@ %'},
+                    {'compilerSettings':compilerSettings},
+                    {'compilerSettings':compilerSettings,
+                     'templateInitArgs':{}},
+                    {'tokens':'@ %',
+                     'templateAPIClass':TemplateSubclass},
+                    Settings1,
+                    preprocObj,
+                    preprocFunc,                    
+                    ]:
+            
+            klass = Template.compile(src, preprocessors=arg)
+            assert str(klass())=='120'
+
+
+    def test_complexUsage(self):
+        src='''\
+        %set foo = @a
+        %def func1: #def func(arg): $arg("***")
+        %% comment
+        $(@foo*10)
+        @func1
+        $func(lambda x:c"--$x-- at a")'''
+        src = '\n'.join([ln.strip() for ln in src.splitlines()])
+
+        
+        for arg in [{'tokens':'@ %', 'namespaces':{'a':99} },
+                    {'tokens':'@ %', 'namespaces':{'a':99} },
+                    ]:
+            klass = Template.compile(src, preprocessors=arg)
+            t = klass()
+            assert str(t)=='990\n--***--99'
+
+
+
+    def test_i18n(self):
+        src='''\
+        %i18n: This is a $string that needs translation
+        %i18n id="foo", domain="root": This is a $string that needs translation
+        '''
+        src = '\n'.join([ln.strip() for ln in src.splitlines()])
+        klass = Template.compile(src, preprocessors='@ %', baseclass=dict)
+        t = klass({'string':'bit of text'})
+        #print str(t), repr(str(t))
+        assert str(t)==('This is a bit of text that needs translation\n'*2)[:-1]
+
+
+class TryExceptImportTest(TemplateTest):
+    def test_FailCase(self):
+        ''' Test situation where an inline #import statement will get relocated '''
+        source = '''
+            #def myFunction()
+                Ahoy!
+                #try
+                    #import sys
+                #except ImportError
+                    $print "This will never happen!"
+                #end try
+            #end def
+            '''
+        # This should raise an IndentationError (if the bug exists)
+        klass = Template.compile(source=source, compilerSettings={'useLegacyImportMode' : False})
+        t = klass(namespaces={'foo' : 1234})
+
+class ClassMethodSupport(TemplateTest):
+    def test_BasicDecorator(self):
+        if sys.version_info[0] == 2 and sys.version_info[1] == 3:
+                print 'This version of Python doesn\'t support decorators, skipping tests'
+                return
+        template = '''
+            #@classmethod
+            #def myClassMethod()
+                #return '$foo = %s' % $foo
+            #end def
+        '''
+        template = Template.compile(source=template)
+        try:
+            rc = template.myClassMethod(foo='bar')
+            assert rc == '$foo = bar', (rc, 'Template class method didn\'t return what I expected')
+        except AttributeError, ex:
+            self.fail(ex)
+
+class StaticMethodSupport(TemplateTest):
+    def test_BasicDecorator(self):
+        if sys.version_info[0] == 2 and sys.version_info[1] == 3:
+                print 'This version of Python doesn\'t support decorators, skipping tests'
+                return
+        template = '''
+            #@staticmethod
+            #def myStaticMethod()
+                #return '$foo = %s' % $foo
+            #end def
+        '''
+        template = Template.compile(source=template)
+        try:
+            rc = template.myStaticMethod(foo='bar')
+            assert rc == '$foo = bar', (rc, 'Template class method didn\'t return what I expected')
+        except AttributeError, ex:
+            self.fail(ex)
+
+
+
+
+##################################################
+## if run from the command line ##
+        
+if __name__ == '__main__':
+    unittest.main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Test.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Test.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Test.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+'''
+Core module of Cheetah's Unit-testing framework
+
+TODO
+================================================================================
+# combo tests
+# negative test cases for expected exceptions
+# black-box vs clear-box testing
+# do some tests that run the Template for long enough to check that the refresh code works
+'''
+
+import sys
+import unittest_local_copy as unittest
+
+
+
+import SyntaxAndOutput
+import NameMapper
+import Template
+import CheetahWrapper
+import Regressions
+import Unicode
+
+suites = [
+   unittest.findTestCases(SyntaxAndOutput),
+   unittest.findTestCases(NameMapper),
+   unittest.findTestCases(Template),
+   unittest.findTestCases(Regressions),
+   unittest.findTestCases(Unicode),
+]
+
+if not sys.platform.startswith('java'):
+    suites.append(unittest.findTestCases(CheetahWrapper))
+
+if __name__ == '__main__':
+    runner = unittest.TextTestRunner()
+    if 'xml' in sys.argv:
+        import xmlrunner
+        runner = xmlrunner.XMLTestRunner(filename='Cheetah-Tests.xml')
+    
+    results = runner.run(unittest.TestSuite(suites))	
+
+		
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Unicode.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Unicode.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/Unicode.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,164 @@
+#!/usr/bin/env python
+# -*- encoding: utf8 -*-
+
+from Cheetah.Template import Template
+from Cheetah import CheetahWrapper
+from Cheetah import DummyTransaction
+import imp
+import os
+import pdb
+import random
+import sys
+import tempfile
+import unittest_local_copy as unittest # This is stupid
+
+class CommandLineTest(unittest.TestCase):
+    def createAndCompile(self, source):
+        sourcefile = '-'
+        while sourcefile.find('-') != -1:
+            sourcefile = tempfile.mktemp()
+        
+        fd = open('%s.tmpl' % sourcefile, 'w')
+        fd.write(source)
+        fd.close()
+
+        wrap = CheetahWrapper.CheetahWrapper()
+        wrap.main(['cheetah', 'compile', '--nobackup', sourcefile])
+        module_name = os.path.basename(sourcefile)
+        module = loadModule(module_name, ['/tmp'])
+        template = getattr(module, module_name)
+        return template
+
+class JBQ_UTF8_Test1(unittest.TestCase):
+    def runTest(self):
+        t = Template.compile(source="""Main file with |$v|
+
+        $other""")
+
+        otherT = Template.compile(source="Other template with |$v|")
+        other = otherT()
+        t.other = other
+
+        t.v = u'Unicode String'
+        t.other.v = u'Unicode String'
+
+        assert unicode(t())
+
+class JBQ_UTF8_Test2(unittest.TestCase):
+    def runTest(self):
+        t = Template.compile(source="""Main file with |$v|
+
+        $other""")
+
+        otherT = Template.compile(source="Other template with |$v|")
+        other = otherT()
+        t.other = other
+
+        t.v = u'Unicode String with eacute é'
+        t.other.v = u'Unicode String'
+
+        assert unicode(t())
+
+
+class JBQ_UTF8_Test3(unittest.TestCase):
+    def runTest(self):
+        t = Template.compile(source="""Main file with |$v|
+
+        $other""")
+
+        otherT = Template.compile(source="Other template with |$v|")
+        other = otherT()
+        t.other = other
+
+        t.v = u'Unicode String with eacute é'
+        t.other.v = u'Unicode String and an eacute é'
+
+        assert unicode(t())
+
+class JBQ_UTF8_Test4(unittest.TestCase):
+    def runTest(self):
+        t = Template.compile(source="""#encoding utf-8
+        Main file with |$v| and eacute in the template é""")
+
+        t.v = 'Unicode String'
+
+        assert unicode(t())
+
+class JBQ_UTF8_Test5(unittest.TestCase):
+    def runTest(self):
+        t = Template.compile(source="""#encoding utf-8
+        Main file with |$v| and eacute in the template é""")
+
+        t.v = u'Unicode String'
+
+        assert unicode(t())
+
+def loadModule(moduleName, path=None):
+    if path:
+        assert isinstance(path, list)
+    try:
+        mod = sys.modules[moduleName]
+    except KeyError:
+        fp = None
+
+        try:
+            fp, pathname, description = imp.find_module(moduleName, path)
+            mod = imp.load_module(moduleName, fp, pathname, description)
+        finally:
+            if fp:
+                fp.close()
+    return mod
+
+class JBQ_UTF8_Test6(unittest.TestCase):
+    def runTest(self):
+        source = """#encoding utf-8
+        #set $someUnicodeString = u"Bébé"
+        Main file with |$v| and eacute in the template é"""
+        t = Template.compile(source=source)
+
+        t.v = u'Unicode String'
+
+        assert unicode(t())
+
+class JBQ_UTF8_Test7(CommandLineTest):
+    def runTest(self):
+        source = """#encoding utf-8
+        #set $someUnicodeString = u"Bébé"
+        Main file with |$v| and eacute in the template é"""
+
+        template = self.createAndCompile(source)
+        template.v = u'Unicode String'
+
+        assert unicode(template())
+
+class Unicode_in_SearchList_Test(CommandLineTest):
+    def test_BasicASCII(self):
+        source = '''This is $adjective'''
+
+        template = self.createAndCompile(source)
+        assert template and issubclass(template, Template)
+        template = template(searchList=[{'adjective' : u'neat'}])
+        assert template.respond()
+
+    def test_Thai(self):
+        # The string is something in Thai
+        source = '''This is $foo $adjective'''
+        template = self.createAndCompile(source)
+        assert template and issubclass(template, Template)
+        template = template(searchList=[{'foo' : 'bar', 
+            'adjective' : u'\u0e22\u0e34\u0e19\u0e14\u0e35\u0e15\u0e49\u0e2d\u0e19\u0e23\u0e31\u0e1a'}])
+        assert template.respond()
+
+    def test_ErrorReporting(self):
+        utf8 = '\xe0\xb8\xa2\xe0\xb8\xb4\xe0\xb8\x99\xe0\xb8\x94\xe0\xb8\xb5\xe0\xb8\x95\xe0\xb9\x89\xe0\xb8\xad\xe0\xb8\x99\xe0\xb8\xa3\xe0\xb8\xb1\xe0\xb8\x9a'
+
+        source = '''This is $adjective'''
+        template = self.createAndCompile(source)
+        assert template and issubclass(template, Template)
+        template = template(searchList=[{'adjective' : utf8}])
+        self.failUnlessRaises(DummyTransaction.DummyResponseFailure, template.respond)
+
+
+
+if __name__ == '__main__':
+    unittest.main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/unittest_local_copy.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/unittest_local_copy.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/unittest_local_copy.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,978 @@
+#!/usr/bin/env python
+""" This is a hacked version of PyUnit that extends its reporting capabilities
+with optional meta data on the test cases.  It also makes it possible to
+separate the standard and error output streams in TextTestRunner.
+
+It's a hack rather than a set of subclasses because a) Steve had used double
+underscore private attributes for some things I needed access to, and b) the
+changes affected so many classes that it was easier just to hack it.
+
+The changes are in the following places:
+TestCase:
+   - minor refactoring of  __init__ and __call__ internals
+   - added some attributes and methods for storing and retrieving meta data
+
+_TextTestResult
+   - refactored the stream handling
+   - incorporated all the output code from TextTestRunner
+   - made the output of FAIL and ERROR information more flexible and
+     incorporated the new meta data from TestCase
+   - added a flag called 'explain' to __init__ that controls whether the new '
+     explanation'   meta data from TestCase is printed along with tracebacks
+   
+TextTestRunner
+   - delegated all output to _TextTestResult
+   - added 'err' and 'explain' to the __init__ signature to match the changes
+     in _TextTestResult
+   
+TestProgram
+   - added -e and --explain as flags on the command line
+
+-- Tavis Rudd <tavis at redonions.net> (Sept 28th, 2001)
+
+- _TestTextResult.printErrorList(): print blank line after each traceback
+
+-- Mike Orr <mso at oz.net> (Nov 11, 2002)
+
+TestCase methods copied from unittest in Python 2.3:
+  - .assertAlmostEqual(first, second, places=7, msg=None): to N decimal places.
+  - .failIfAlmostEqual(first, second, places=7, msg=None)
+
+-- Mike Orr (Jan 5, 2004)
+
+
+Below is the original docstring for unittest.
+---------------------------------------------------------------------------
+Python unit testing framework, based on Erich Gamma's JUnit and Kent Beck's
+Smalltalk testing framework.
+
+This module contains the core framework classes that form the basis of
+specific test cases and suites (TestCase, TestSuite etc.), and also a
+text-based utility class for running the tests and reporting the results
+(TextTestRunner).
+
+Simple usage:
+
+    import unittest
+
+    class IntegerArithmenticTestCase(unittest.TestCase):
+        def testAdd(self):  ## test method names begin 'test*'
+            self.assertEquals((1 + 2), 3)
+            self.assertEquals(0 + 1, 1)
+        def testMultiply(self);
+            self.assertEquals((0 * 10), 0)
+            self.assertEquals((5 * 8), 40)
+
+    if __name__ == '__main__':
+        unittest.main()
+
+Further information is available in the bundled documentation, and from
+
+  http://pyunit.sourceforge.net/
+
+Copyright (c) 1999, 2000, 2001 Steve Purcell
+This module is free software, and you may redistribute it and/or modify
+it under the same terms as Python itself, so long as this copyright message
+and disclaimer are retained in their original form.
+
+IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
+SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF
+THIS CODE, EVEN IF THE AUTHOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGE.
+
+THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE.  THE CODE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS,
+AND THERE IS NO OBLIGATION WHATSOEVER TO PROVIDE MAINTENANCE,
+SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+"""
+
+__author__ = "Steve Purcell"
+__email__ = "stephen_purcell at yahoo dot com"
+__revision__ = "$Revision: 1.11 $"[11:-2]
+
+
+##################################################
+## DEPENDENCIES ##
+
+import os
+import re
+import string
+import sys
+import time
+import traceback
+import types
+import pprint
+
+##################################################
+## CONSTANTS & GLOBALS
+
+try:
+    True,False
+except NameError:
+    True, False = (1==1),(1==0)
+
+##############################################################################
+# Test framework core
+##############################################################################
+
+
+class TestResult:
+    """Holder for test result information.
+
+    Test results are automatically managed by the TestCase and TestSuite
+    classes, and do not need to be explicitly manipulated by writers of tests.
+
+    Each instance holds the total number of tests run, and collections of
+    failures and errors that occurred among those test runs. The collections
+    contain tuples of (testcase, exceptioninfo), where exceptioninfo is a
+    tuple of values as returned by sys.exc_info().
+    """
+    def __init__(self):
+        self.failures = []
+        self.errors = []
+        self.testsRun = 0
+        self.shouldStop = 0
+
+    def startTest(self, test):
+        "Called when the given test is about to be run"
+        self.testsRun = self.testsRun + 1
+
+    def stopTest(self, test):
+        "Called when the given test has been run"
+        pass
+
+    def addError(self, test, err):
+        "Called when an error has occurred"
+        self.errors.append((test, err))
+
+    def addFailure(self, test, err):
+        "Called when a failure has occurred"
+        self.failures.append((test, err))
+
+    def addSuccess(self, test):
+        "Called when a test has completed successfully"
+        pass
+
+    def wasSuccessful(self):
+        "Tells whether or not this result was a success"
+        return len(self.failures) == len(self.errors) == 0
+
+    def stop(self):
+        "Indicates that the tests should be aborted"
+        self.shouldStop = 1
+
+    def __repr__(self):
+        return "<%s run=%i errors=%i failures=%i>" % \
+               (self.__class__, self.testsRun, len(self.errors),
+                len(self.failures))
+        
+class TestCase:
+    """A class whose instances are single test cases.
+
+    By default, the test code itself should be placed in a method named
+    'runTest'.
+
+    If the fixture may be used for many test cases, create as
+    many test methods as are needed. When instantiating such a TestCase
+    subclass, specify in the constructor arguments the name of the test method
+    that the instance is to execute.
+
+    Test authors should subclass TestCase for their own tests. Construction
+    and deconstruction of the test's environment ('fixture') can be
+    implemented by overriding the 'setUp' and 'tearDown' methods respectively.
+
+    If it is necessary to override the __init__ method, the base class
+    __init__ method must always be called. It is important that subclasses
+    should not change the signature of their __init__ method, since instances
+    of the classes are instantiated automatically by parts of the framework
+    in order to be run.
+    """
+
+    # This attribute determines which exception will be raised when
+    # the instance's assertion methods fail; test methods raising this
+    # exception will be deemed to have 'failed' rather than 'errored'
+
+    failureException = AssertionError
+
+    # the name of the fixture.  Used for displaying meta data about the test
+    name = None
+    
+    def __init__(self, methodName='runTest'):
+        """Create an instance of the class that will use the named test
+        method when executed. Raises a ValueError if the instance does
+        not have a method with the specified name.
+        """
+        self._testMethodName = methodName
+        self._setupTestMethod()
+        self._setupMetaData()
+
+    def _setupTestMethod(self):
+        try:
+            self._testMethod = getattr(self, self._testMethodName)
+        except AttributeError:
+            raise ValueError, "no such test method in %s: %s" % \
+                  (self.__class__, self._testMethodName)
+        
+    ## meta data methods
+        
+    def _setupMetaData(self):
+        """Setup the default meta data for the test case:
+
+        - id: self.__class__.__name__ + testMethodName OR self.name + testMethodName
+        - description: 1st line of Class docstring + 1st line of method docstring
+        - explanation: rest of Class docstring + rest of method docstring
+        
+        """
+
+        
+        testDoc = self._testMethod.__doc__ or '\n'
+        testDocLines = testDoc.splitlines()
+        
+        testDescription = testDocLines[0].strip() 
+        if len(testDocLines) > 1:
+            testExplanation = '\n'.join(
+                [ln.strip() for ln in testDocLines[1:]]
+                ).strip()
+        else:
+            testExplanation = ''
+            
+        fixtureDoc = self.__doc__ or '\n'
+        fixtureDocLines = fixtureDoc.splitlines()
+        fixtureDescription = fixtureDocLines[0].strip()
+        if len(fixtureDocLines) > 1:
+            fixtureExplanation = '\n'.join(
+                [ln.strip() for ln in fixtureDocLines[1:]]
+                ).strip()
+        else:
+            fixtureExplanation = ''
+        
+        if not self.name:
+            self.name = self.__class__
+        self._id = "%s.%s" % (self.name, self._testMethodName)
+        
+        if not fixtureDescription:
+            self._description = testDescription
+        else:
+            self._description = fixtureDescription + ', ' + testDescription
+
+        if not fixtureExplanation:
+            self._explanation = testExplanation
+        else:
+            self._explanation = ['Fixture Explanation:',
+                                 '--------------------',
+                                 fixtureExplanation,
+                                 '',
+                                 'Test Explanation:',
+                                 '-----------------',
+                                 testExplanation
+                                 ]
+            self._explanation = '\n'.join(self._explanation)
+
+    def id(self):
+        return self._id
+
+    def setId(self, id):
+        self._id = id
+
+    def describe(self):
+        """Returns a one-line description of the test, or None if no
+        description has been provided.
+
+        The default implementation of this method returns the first line of
+        the specified test method's docstring.
+        """
+        return self._description
+
+    shortDescription = describe
+    
+    def setDescription(self, descr):
+        self._description = descr
+    
+    def explain(self):
+        return self._explanation
+
+    def setExplanation(self, expln):
+        self._explanation = expln
+
+    ## core methods
+
+    def setUp(self):
+        "Hook method for setting up the test fixture before exercising it."
+        pass
+    
+    def run(self, result=None):
+        return self(result)
+        
+    def tearDown(self):
+        "Hook method for deconstructing the test fixture after testing it."
+        pass
+
+    def debug(self):
+        """Run the test without collecting errors in a TestResult"""
+        self.setUp()
+        self._testMethod()
+        self.tearDown()
+
+    ## internal methods
+
+    def defaultTestResult(self):
+        return TestResult()
+    
+    def __call__(self, result=None):
+        if result is None:
+            result = self.defaultTestResult()
+        
+        result.startTest(self)
+        try:
+            try:
+                self.setUp()
+            except:
+                result.addError(self, self.__exc_info())
+                return
+            
+            ok = 0
+            try:
+                self._testMethod()
+                ok = 1
+            except self.failureException, e:
+                result.addFailure(self, self.__exc_info())
+            except:
+                result.addError(self, self.__exc_info())
+            try:
+                self.tearDown()
+            except:
+                result.addError(self, self.__exc_info())
+                ok = 0
+            if ok:
+                result.addSuccess(self)
+        finally:
+            result.stopTest(self)
+            
+        return result
+        
+    def countTestCases(self):
+        return 1
+       
+    def __str__(self):
+        return "%s (%s)" % (self._testMethodName, self.__class__)
+
+    def __repr__(self):
+        return "<%s testMethod=%s>" % \
+               (self.__class__, self._testMethodName)
+
+    def __exc_info(self):
+        """Return a version of sys.exc_info() with the traceback frame
+           minimised; usually the top level of the traceback frame is not
+           needed.
+        """
+        exctype, excvalue, tb = sys.exc_info()
+        if sys.platform[:4] == 'java': ## tracebacks look different in Jython
+            return (exctype, excvalue, tb)
+        newtb = tb.tb_next
+        if newtb is None:
+            return (exctype, excvalue, tb)
+        return (exctype, excvalue, newtb)
+
+    ## methods for use by the test cases
+
+    def fail(self, msg=None):
+        """Fail immediately, with the given message."""
+        raise self.failureException, msg
+
+    def failIf(self, expr, msg=None):
+        "Fail the test if the expression is true."
+        if expr: raise self.failureException, msg
+
+    def failUnless(self, expr, msg=None):
+        """Fail the test unless the expression is true."""
+        if not expr: raise self.failureException, msg
+
+    def failUnlessRaises(self, excClass, callableObj, *args, **kwargs):
+        """Fail unless an exception of class excClass is thrown
+           by callableObj when invoked with arguments args and keyword
+           arguments kwargs. If a different type of exception is
+           thrown, it will not be caught, and the test case will be
+           deemed to have suffered an error, exactly as for an
+           unexpected exception.
+        """
+        try:
+            apply(callableObj, args, kwargs)
+        except excClass:
+            return
+        else:
+            if hasattr(excClass,'__name__'): excName = excClass.__name__
+            else: excName = str(excClass)
+            raise self.failureException, excName
+
+    def failUnlessEqual(self, first, second, msg=None):
+        """Fail if the two objects are unequal as determined by the '!='
+           operator.
+        """
+        if first != second:
+            raise self.failureException, (msg or '%s != %s' % (first, second))
+
+    def failIfEqual(self, first, second, msg=None):
+        """Fail if the two objects are equal as determined by the '=='
+           operator.
+        """
+        if first == second:
+            raise self.failureException, (msg or '%s == %s' % (first, second))
+
+    def failUnlessAlmostEqual(self, first, second, places=7, msg=None):
+        """Fail if the two objects are unequal as determined by their
+           difference rounded to the given number of decimal places
+           (default 7) and comparing to zero.
+
+           Note that decimal places (from zero) is usually not the same
+           as significant digits (measured from the most signficant digit).
+        """
+        if round(second-first, places) != 0:
+            raise self.failureException, \
+                  (msg or '%s != %s within %s places' % (`first`, `second`, `places` ))
+
+    def failIfAlmostEqual(self, first, second, places=7, msg=None):
+        """Fail if the two objects are equal as determined by their
+           difference rounded to the given number of decimal places
+           (default 7) and comparing to zero.
+
+           Note that decimal places (from zero) is usually not the same
+           as significant digits (measured from the most signficant digit).
+        """
+        if round(second-first, places) == 0:
+            raise self.failureException, \
+                  (msg or '%s == %s within %s places' % (`first`, `second`, `places`))
+
+    ## aliases
+
+    assertEqual = assertEquals = failUnlessEqual
+
+    assertNotEqual = assertNotEquals = failIfEqual
+
+    assertAlmostEqual = assertAlmostEquals = failUnlessAlmostEqual
+
+    assertNotAlmostEqual = assertNotAlmostEquals = failIfAlmostEqual
+
+    assertRaises = failUnlessRaises
+
+    assert_ = failUnless
+
+
+class FunctionTestCase(TestCase):
+    """A test case that wraps a test function.
+
+    This is useful for slipping pre-existing test functions into the
+    PyUnit framework. Optionally, set-up and tidy-up functions can be
+    supplied. As with TestCase, the tidy-up ('tearDown') function will
+    always be called if the set-up ('setUp') function ran successfully.
+    """
+
+    def __init__(self, testFunc, setUp=None, tearDown=None,
+                 description=None):
+        TestCase.__init__(self)
+        self.__setUpFunc = setUp
+        self.__tearDownFunc = tearDown
+        self.__testFunc = testFunc
+        self.__description = description
+
+    def setUp(self):
+        if self.__setUpFunc is not None:
+            self.__setUpFunc()
+
+    def tearDown(self):
+        if self.__tearDownFunc is not None:
+            self.__tearDownFunc()
+
+    def runTest(self):
+        self.__testFunc()
+
+    def id(self):
+        return self.__testFunc.__name__
+
+    def __str__(self):
+        return "%s (%s)" % (self.__class__, self.__testFunc.__name__)
+
+    def __repr__(self):
+        return "<%s testFunc=%s>" % (self.__class__, self.__testFunc)
+
+
+    def describe(self):
+        if self.__description is not None: return self.__description
+        doc = self.__testFunc.__doc__
+        return doc and string.strip(string.split(doc, "\n")[0]) or None
+    
+    ## aliases
+    shortDescription = describe
+
+class TestSuite:
+    """A test suite is a composite test consisting of a number of TestCases.
+
+    For use, create an instance of TestSuite, then add test case instances.
+    When all tests have been added, the suite can be passed to a test
+    runner, such as TextTestRunner. It will run the individual test cases
+    in the order in which they were added, aggregating the results. When
+    subclassing, do not forget to call the base class constructor.
+    """
+    def __init__(self, tests=(), suiteName=None):
+        self._tests = []
+        self._testMap = {}
+        self.suiteName = suiteName
+        self.addTests(tests)
+
+    def __repr__(self):
+        return "<%s tests=%s>" % (self.__class__, pprint.pformat(self._tests))
+
+    __str__ = __repr__
+
+    def countTestCases(self):
+        cases = 0
+        for test in self._tests:
+            cases = cases + test.countTestCases()
+        return cases
+
+    def addTest(self, test):
+        self._tests.append(test)
+        if isinstance(test, TestSuite) and test.suiteName:
+            name = test.suiteName
+        elif isinstance(test, TestCase):
+            #print test, test._testMethodName
+            name = test._testMethodName
+        else:
+            name = test.__class__.__name__
+        self._testMap[name] = test
+        
+    def addTests(self, tests):
+        for test in tests:
+            self.addTest(test)
+
+    def getTestForName(self, name):
+        return self._testMap[name]
+
+    def run(self, result):
+        return self(result)
+
+    def __call__(self, result):
+        for test in self._tests:
+            if result.shouldStop:
+                break
+            test(result)
+        return result
+
+    def debug(self):
+        """Run the tests without collecting errors in a TestResult"""
+        for test in self._tests: test.debug()
+
+
+##############################################################################
+# Text UI
+##############################################################################
+
+class StreamWrapper:
+    def __init__(self, out=sys.stdout, err=sys.stderr):
+        self._streamOut = out
+        self._streamErr = err
+
+    def write(self, txt):
+        self._streamOut.write(txt)
+        self._streamOut.flush()
+    
+    def writeln(self, *lines):
+        for line in lines:
+            self.write(line + '\n')
+        if not lines:
+            self.write('\n')
+
+    def writeErr(self, txt):
+        self._streamErr.write(txt)
+    
+    def writelnErr(self, *lines):
+        for line in lines:
+            self.writeErr(line + '\n')
+        if not lines:
+            self.writeErr('\n')
+
+
+class _TextTestResult(TestResult, StreamWrapper):
+    _separatorWidth = 70
+    _sep1 = '='
+    _sep2 = '-'
+    _errorSep1 = '*'
+    _errorSep2 = '-'
+    _errorSep3 = ''
+    
+    def __init__(self,
+                 stream=sys.stdout,
+                 errStream=sys.stderr,
+                 verbosity=1,
+                 explain=False):
+        
+        TestResult.__init__(self)
+        StreamWrapper.__init__(self, out=stream, err=errStream)        
+
+        self._verbosity = verbosity
+        self._showAll = verbosity > 1
+        self._dots = (verbosity == 1)
+        self._explain = explain
+
+    ## startup and shutdown methods
+        
+    def beginTests(self):
+        self._startTime = time.time()
+
+    def endTests(self):
+        self._stopTime = time.time()
+        self._timeTaken = float(self._stopTime - self._startTime)
+
+    def stop(self):
+        self.shouldStop = 1
+        
+    ## methods called for each test
+        
+    def startTest(self, test):
+        TestResult.startTest(self, test)
+        if self._showAll:
+            self.write("%s (%s)" %( test.id(), test.describe() ) )
+            self.write(" ... ")
+
+    def addSuccess(self, test):
+        TestResult.addSuccess(self, test)
+        if self._showAll:
+            self.writeln("ok")
+        elif self._dots:
+            self.write('.')
+
+    def addError(self, test, err):
+        TestResult.addError(self, test, err)
+        if self._showAll:
+            self.writeln("ERROR")
+        elif self._dots:
+            self.write('E')
+        if err[0] is KeyboardInterrupt:
+            self.stop()
+
+    def addFailure(self, test, err):
+        TestResult.addFailure(self, test, err)
+        if self._showAll:
+            self.writeln("FAIL")
+        elif self._dots:
+            self.write('F')
+
+    ## display methods
+
+    def summarize(self):
+        self.printErrors()
+        self.writeSep2()
+        run = self.testsRun
+        self.writeln("Ran %d test%s in %.3fs" %
+                            (run, run == 1 and "" or "s", self._timeTaken))
+        self.writeln()
+        if not self.wasSuccessful():
+            self.writeErr("FAILED (")
+            failed, errored = map(len, (self.failures, self.errors))
+            if failed:
+                self.writeErr("failures=%d" % failed)
+            if errored:
+                if failed: self.writeErr(", ")
+                self.writeErr("errors=%d" % errored)
+            self.writelnErr(")")
+        else:
+            self.writelnErr("OK")
+
+    def writeSep1(self):
+        self.writeln(self._sep1 * self._separatorWidth)
+
+    def writeSep2(self):
+        self.writeln(self._sep2 * self._separatorWidth)
+
+    def writeErrSep1(self):
+        self.writeln(self._errorSep1 * self._separatorWidth)
+
+    def writeErrSep2(self):
+        self.writeln(self._errorSep2 * self._separatorWidth)
+
+    def printErrors(self):
+        if self._dots or self._showAll:
+            self.writeln()
+        self.printErrorList('ERROR', self.errors)
+        self.printErrorList('FAIL', self.failures)
+
+    def printErrorList(self, flavour, errors):
+        for test, err in errors:
+            self.writeErrSep1()
+            self.writelnErr("%s %s (%s)" % (flavour, test.id(), test.describe() ))
+            if self._explain:
+                expln = test.explain()
+                if expln:
+                    self.writeErrSep2()
+                    self.writeErr( expln )
+                    self.writelnErr()
+
+            self.writeErrSep2()
+            for line in apply(traceback.format_exception, err):
+                for l in line.split("\n")[:-1]:
+                    self.writelnErr(l)
+            self.writelnErr("")
+
+class TextTestRunner:
+    def __init__(self, 
+                 stream=sys.stdout,
+                 errStream=sys.stderr,
+                 verbosity=1,
+                 explain=False):
+
+        self._out = stream
+        self._err = errStream
+        self._verbosity = verbosity
+        self._explain = explain
+        
+    ## main methods
+
+    def run(self, test):
+        result = self._makeResult()
+        result.beginTests()
+        test( result )
+        result.endTests()       
+        result.summarize()
+        
+        return result
+    
+    ## internal methods
+
+    def _makeResult(self):
+        return _TextTestResult(stream=self._out,
+                               errStream=self._err,
+                               verbosity=self._verbosity,
+                               explain=self._explain,
+                               )
+
+##############################################################################
+# Locating and loading tests
+##############################################################################
+
+class TestLoader:
+    """This class is responsible for loading tests according to various
+    criteria and returning them wrapped in a Test
+    """
+    testMethodPrefix = 'test'
+    sortTestMethodsUsing = cmp
+    suiteClass = TestSuite
+
+    def loadTestsFromTestCase(self, testCaseClass):
+        """Return a suite of all tests cases contained in testCaseClass"""
+        return self.suiteClass(tests=map(testCaseClass,
+                                         self.getTestCaseNames(testCaseClass)),
+                               suiteName=testCaseClass.__name__)
+
+    def loadTestsFromModule(self, module):
+        """Return a suite of all tests cases contained in the given module"""
+        tests = []
+        for name in dir(module):
+            obj = getattr(module, name)
+            if type(obj) == types.ClassType and issubclass(obj, TestCase):
+                tests.append(self.loadTestsFromTestCase(obj))
+        return self.suiteClass(tests)
+
+    def loadTestsFromName(self, name, module=None):
+        """Return a suite of all tests cases given a string specifier.
+
+        The name may resolve either to a module, a test case class, a
+        test method within a test case class, or a callable object which
+        returns a TestCase or TestSuite instance.
+
+        The method optionally resolves the names relative to a given module.
+        """
+        parts = string.split(name, '.')
+        if module is None:
+            if not parts:
+                raise ValueError, "incomplete test name: %s" % name
+            else:
+                parts_copy = parts[:]
+                while parts_copy:
+                    try:
+                        module = __import__(string.join(parts_copy,'.'))
+                        break
+                    except ImportError:
+                        del parts_copy[-1]
+                        if not parts_copy: raise
+                parts = parts[1:]
+        obj = module
+        for part in parts:
+            if isinstance(obj, TestSuite):
+                obj = obj.getTestForName(part)
+            else:
+                obj = getattr(obj, part)
+
+        if type(obj) == types.ModuleType:
+            return self.loadTestsFromModule(obj)
+        elif type(obj) == types.ClassType and issubclass(obj, TestCase):
+            return self.loadTestsFromTestCase(obj)
+        elif type(obj) == types.UnboundMethodType:
+            return obj.im_class(obj.__name__)
+        elif isinstance(obj, TestSuite):
+            return obj
+        elif isinstance(obj, TestCase):
+            return obj
+        elif callable(obj):
+            test = obj()
+            if not isinstance(test, TestCase) and \
+               not isinstance(test, TestSuite):
+                raise ValueError, \
+                      "calling %s returned %s, not a test" %(obj,test)
+            return test
+        else:
+            raise ValueError, "don't know how to make test from: %s" % obj
+
+    def loadTestsFromNames(self, names, module=None):
+        """Return a suite of all tests cases found using the given sequence
+        of string specifiers. See 'loadTestsFromName()'.
+        """
+        suites = []
+        for name in names:
+            suites.append(self.loadTestsFromName(name, module))
+        return self.suiteClass(suites)
+
+    def getTestCaseNames(self, testCaseClass):
+        """Return a sorted sequence of method names found within testCaseClass.
+        """
+        testFnNames = [fn for fn in dir(testCaseClass) if fn.startswith(self.testMethodPrefix)]
+        if hasattr(testCaseClass, 'runTest'):
+            testFnNames.append('runTest')
+        for baseclass in testCaseClass.__bases__:
+            for testFnName in self.getTestCaseNames(baseclass):
+                if testFnName not in testFnNames:  # handle overridden methods
+                    testFnNames.append(testFnName)
+        if self.sortTestMethodsUsing:
+            testFnNames.sort(self.sortTestMethodsUsing)
+        return testFnNames
+
+
+
+defaultTestLoader = TestLoader()
+
+
+##############################################################################
+# Patches for old functions: these functions should be considered obsolete
+##############################################################################
+
+def _makeLoader(prefix, sortUsing, suiteClass=None):
+    loader = TestLoader()
+    loader.sortTestMethodsUsing = sortUsing
+    loader.testMethodPrefix = prefix
+    if suiteClass: loader.suiteClass = suiteClass
+    return loader
+
+def getTestCaseNames(testCaseClass, prefix, sortUsing=cmp):
+    return _makeLoader(prefix, sortUsing).getTestCaseNames(testCaseClass)
+
+def makeSuite(testCaseClass, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
+    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromTestCase(testCaseClass)
+
+def findTestCases(module, prefix='test', sortUsing=cmp, suiteClass=TestSuite):
+    return _makeLoader(prefix, sortUsing, suiteClass).loadTestsFromModule(module)
+
+##############################################################################
+# Facilities for running tests from the command line
+##############################################################################
+
+class TestProgram:
+    """A command-line program that runs a set of tests; this is primarily
+       for making test modules conveniently executable.
+    """
+    USAGE = """\
+Usage: %(progName)s [options] [test] [...]
+
+Options:
+  -h, --help       Show this message
+  -v, --verbose    Verbose output
+  -q, --quiet      Minimal output
+  -e, --expain     Output extra test details if there is a failure or error
+  
+Examples:
+  %(progName)s                               - run default set of tests
+  %(progName)s MyTestSuite                   - run suite 'MyTestSuite'
+  %(progName)s MyTestSuite.MyTestCase        - run suite 'MyTestSuite'
+  %(progName)s MyTestCase.testSomething      - run MyTestCase.testSomething
+  %(progName)s MyTestCase                    - run all 'test*' test methods
+                                               in MyTestCase
+"""
+    def __init__(self, module='__main__', defaultTest=None,
+                 argv=None, testRunner=None, testLoader=defaultTestLoader,
+                 testSuite=None):
+        if type(module) == type(''):
+            self.module = __import__(module)
+            for part in string.split(module,'.')[1:]:
+                self.module = getattr(self.module, part)
+        else:
+            self.module = module
+        if argv is None:
+            argv = sys.argv
+        self.test = testSuite
+        self.verbosity = 1
+        self.explain = 0
+        self.defaultTest = defaultTest
+        self.testRunner = testRunner
+        self.testLoader = testLoader
+        self.progName = os.path.basename(argv[0])
+        self.parseArgs(argv)
+        self.runTests()
+
+    def usageExit(self, msg=None):
+        if msg: print msg
+        print self.USAGE % self.__dict__
+        sys.exit(2)
+
+    def parseArgs(self, argv):
+        import getopt
+        try:
+            options, args = getopt.getopt(argv[1:], 'hHvqer',
+                                  ['help','verbose','quiet','explain', 'raise'])
+            for opt, value in options:
+                if opt in ('-h','-H','--help'):
+                    self.usageExit()
+                if opt in ('-q','--quiet'):
+                    self.verbosity = 0
+                if opt in ('-v','--verbose'):
+                    self.verbosity = 2
+                if opt in ('-e','--explain'):
+                    self.explain = True
+            if len(args) == 0 and self.defaultTest is None and self.test is None:
+                self.test = self.testLoader.loadTestsFromModule(self.module)
+                return
+            if len(args) > 0:
+                self.testNames = args
+            else:
+                self.testNames = (self.defaultTest,)
+            self.createTests()
+        except getopt.error, msg:
+            self.usageExit(msg)
+
+    def createTests(self):
+        if self.test == None:
+            self.test = self.testLoader.loadTestsFromNames(self.testNames,
+                                                           self.module)
+
+    def runTests(self):
+        if self.testRunner is None:
+            self.testRunner = TextTestRunner(verbosity=self.verbosity,
+                                             explain=self.explain)
+        result = self.testRunner.run(self.test)
+        self._cleanupAfterRunningTests()
+        sys.exit(not result.wasSuccessful())
+
+    def _cleanupAfterRunningTests(self):
+        """A hook method that is called immediately prior to calling
+        sys.exit(not result.wasSuccessful()) in self.runTests().
+        """
+        pass
+
+main = TestProgram
+
+
+##############################################################################
+# Executing this module from the command line
+##############################################################################
+
+if __name__ == "__main__":
+    main(module=None)
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/xmlrunner.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/xmlrunner.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tests/xmlrunner.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,381 @@
+"""
+XML Test Runner for PyUnit
+"""
+
+# Written by Sebastian Rittau <srittau at jroger.in-berlin.de> and placed in
+# the Public Domain. With contributions by Paolo Borelli.
+
+__revision__ = "$Id: /private/python/stdlib/xmlrunner.py 16654 2007-11-12T12:46:35.368945Z srittau  $"
+
+import os.path
+import re
+import sys
+import time
+import traceback
+import unittest
+from StringIO import StringIO
+from xml.sax.saxutils import escape
+
+from StringIO import StringIO
+
+
+
+class _TestInfo(object):
+
+    """Information about a particular test.
+    
+    Used by _XMLTestResult.
+    
+    """
+
+    def __init__(self, test, time):
+        _pieces = test.id().split('.')
+        (self._class, self._method) = ('.'.join(_pieces[:-1]), _pieces[-1])
+        self._time = time
+        self._error = None
+        self._failure = None
+
+
+    def print_report(self, stream):
+        """Print information about this test case in XML format to the
+        supplied stream.
+
+        """
+        stream.write('  <testcase classname="%(class)s" name="%(method)s" time="%(time).4f">' % \
+            {
+                "class": self._class,
+                "method": self._method,
+                "time": self._time,
+            })
+        if self._failure != None:
+            self._print_error(stream, 'failure', self._failure)
+        if self._error != None:
+            self._print_error(stream, 'error', self._error)
+        stream.write('</testcase>\n')
+
+    def _print_error(self, stream, tagname, error):
+        """Print information from a failure or error to the supplied stream."""
+        text = escape(str(error[1]))
+        stream.write('\n')
+        stream.write('    <%s type="%s">%s\n' \
+            % (tagname, issubclass(error[0], Exception) and error[0].__name__ or str(error[0]), text))
+        tb_stream = StringIO()
+        traceback.print_tb(error[2], None, tb_stream)
+        stream.write(escape(tb_stream.getvalue()))
+        stream.write('    </%s>\n' % tagname)
+        stream.write('  ')
+
+# Module level functions since Python 2.3 doesn't grok decorators
+def create_success(test, time):
+    """Create a _TestInfo instance for a successful test."""
+    return _TestInfo(test, time)
+
+def create_failure(test, time, failure):
+    """Create a _TestInfo instance for a failed test."""
+    info = _TestInfo(test, time)
+    info._failure = failure
+    return info
+
+def create_error(test, time, error):
+    """Create a _TestInfo instance for an erroneous test."""
+    info = _TestInfo(test, time)
+    info._error = error
+    return info
+
+class _XMLTestResult(unittest.TestResult):
+
+    """A test result class that stores result as XML.
+
+    Used by XMLTestRunner.
+
+    """
+
+    def __init__(self, classname):
+        unittest.TestResult.__init__(self)
+        self._test_name = classname
+        self._start_time = None
+        self._tests = []
+        self._error = None
+        self._failure = None
+
+    def startTest(self, test):
+        unittest.TestResult.startTest(self, test)
+        self._error = None
+        self._failure = None
+        self._start_time = time.time()
+
+    def stopTest(self, test):
+        time_taken = time.time() - self._start_time
+        unittest.TestResult.stopTest(self, test)
+        if self._error:
+            info = create_error(test, time_taken, self._error)
+        elif self._failure:
+            info = create_failure(test, time_taken, self._failure)
+        else:
+            info = create_success(test, time_taken)
+        self._tests.append(info)
+
+    def addError(self, test, err):
+        unittest.TestResult.addError(self, test, err)
+        self._error = err
+
+    def addFailure(self, test, err):
+        unittest.TestResult.addFailure(self, test, err)
+        self._failure = err
+
+    def print_report(self, stream, time_taken, out, err):
+        """Prints the XML report to the supplied stream.
+        
+        The time the tests took to perform as well as the captured standard
+        output and standard error streams must be passed in.a
+
+        """
+        stream.write('<testsuite errors="%(e)d" failures="%(f)d" ' % \
+            { "e": len(self.errors), "f": len(self.failures) })
+        stream.write('name="%(n)s" tests="%(t)d" time="%(time).3f">\n' % \
+            {
+                "n": self._test_name,
+                "t": self.testsRun,
+                "time": time_taken,
+            })
+        for info in self._tests:
+            info.print_report(stream)
+        stream.write('  <system-out><![CDATA[%s]]></system-out>\n' % out)
+        stream.write('  <system-err><![CDATA[%s]]></system-err>\n' % err)
+        stream.write('</testsuite>\n')
+
+
+class XMLTestRunner(object):
+
+    """A test runner that stores results in XML format compatible with JUnit.
+
+    XMLTestRunner(stream=None) -> XML test runner
+
+    The XML file is written to the supplied stream. If stream is None, the
+    results are stored in a file called TEST-<module>.<class>.xml in the
+    current working directory (if not overridden with the path property),
+    where <module> and <class> are the module and class name of the test class.
+
+    """
+
+    def __init__(self, *args, **kwargs):
+        self._stream = kwargs.get('stream')
+        self._filename = kwargs.get('filename')
+        self._path = "."
+
+    def run(self, test):
+        """Run the given test case or test suite."""
+        class_ = test.__class__
+        classname = class_.__module__ + "." + class_.__name__
+        if self._stream == None:
+            filename = "TEST-%s.xml" % classname
+            if self._filename:
+                filename = self._filename
+            stream = file(os.path.join(self._path, filename), "w")
+            stream.write('<?xml version="1.0" encoding="utf-8"?>\n')
+        else:
+            stream = self._stream
+
+        result = _XMLTestResult(classname)
+        start_time = time.time()
+
+        # TODO: Python 2.5: Use the with statement
+        old_stdout = sys.stdout
+        old_stderr = sys.stderr
+        sys.stdout = StringIO()
+        sys.stderr = StringIO()
+
+        try:
+            test(result)
+            try:
+                out_s = sys.stdout.getvalue()
+            except AttributeError:
+                out_s = ""
+            try:
+                err_s = sys.stderr.getvalue()
+            except AttributeError:
+                err_s = ""
+        finally:
+            sys.stdout = old_stdout
+            sys.stderr = old_stderr
+
+        time_taken = time.time() - start_time
+        result.print_report(stream, time_taken, out_s, err_s)
+        if self._stream == None:
+            stream.close()
+
+        return result
+
+    def _set_path(self, path):
+        self._path = path
+
+    path = property(lambda self: self._path, _set_path, None,
+            """The path where the XML files are stored.
+            
+            This property is ignored when the XML file is written to a file
+            stream.""")
+
+
+class XMLTestRunnerTest(unittest.TestCase):
+    def setUp(self):
+        self._stream = StringIO()
+
+    def _try_test_run(self, test_class, expected):
+
+        """Run the test suite against the supplied test class and compare the
+        XML result against the expected XML string. Fail if the expected
+        string doesn't match the actual string. All time attribute in the
+        expected string should have the value "0.000". All error and failure
+        messages are reduced to "Foobar".
+
+        """
+
+        runner = XMLTestRunner(self._stream)
+        runner.run(unittest.makeSuite(test_class))
+
+        got = self._stream.getvalue()
+        # Replace all time="X.YYY" attributes by time="0.000" to enable a
+        # simple string comparison.
+        got = re.sub(r'time="\d+\.\d+"', 'time="0.000"', got)
+        # Likewise, replace all failure and error messages by a simple "Foobar"
+        # string.
+        got = re.sub(r'(?s)<failure (.*?)>.*?</failure>', r'<failure \1>Foobar</failure>', got)
+        got = re.sub(r'(?s)<error (.*?)>.*?</error>', r'<error \1>Foobar</error>', got)
+
+        self.assertEqual(expected, got)
+
+    def test_no_tests(self):
+        """Regression test: Check whether a test run without any tests
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            pass
+        self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="0" time="0.000">
+  <system-out><![CDATA[]]></system-out>
+  <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+    def test_success(self):
+        """Regression test: Check whether a test run with a successful test
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                pass
+        self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+  <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+  <system-out><![CDATA[]]></system-out>
+  <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+    def test_failure(self):
+        """Regression test: Check whether a test run with a failing test
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                self.assert_(False)
+        self._try_test_run(TestTest, """<testsuite errors="0" failures="1" name="unittest.TestSuite" tests="1" time="0.000">
+  <testcase classname="__main__.TestTest" name="test_foo" time="0.000">
+    <failure type="exceptions.AssertionError">Foobar</failure>
+  </testcase>
+  <system-out><![CDATA[]]></system-out>
+  <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+    def test_error(self):
+        """Regression test: Check whether a test run with a erroneous test
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                raise IndexError()
+        self._try_test_run(TestTest, """<testsuite errors="1" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+  <testcase classname="__main__.TestTest" name="test_foo" time="0.000">
+    <error type="exceptions.IndexError">Foobar</error>
+  </testcase>
+  <system-out><![CDATA[]]></system-out>
+  <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+    def test_stdout_capture(self):
+        """Regression test: Check whether a test run with output to stdout
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                print "Test"
+        self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+  <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+  <system-out><![CDATA[Test
+]]></system-out>
+  <system-err><![CDATA[]]></system-err>
+</testsuite>
+""")
+
+    def test_stderr_capture(self):
+        """Regression test: Check whether a test run with output to stderr
+        matches a previous run.
+        
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                print >>sys.stderr, "Test"
+        self._try_test_run(TestTest, """<testsuite errors="0" failures="0" name="unittest.TestSuite" tests="1" time="0.000">
+  <testcase classname="__main__.TestTest" name="test_foo" time="0.000"></testcase>
+  <system-out><![CDATA[]]></system-out>
+  <system-err><![CDATA[Test
+]]></system-err>
+</testsuite>
+""")
+
+    class NullStream(object):
+        """A file-like object that discards everything written to it."""
+        def write(self, buffer):
+            pass
+
+    def test_unittests_changing_stdout(self):
+        """Check whether the XMLTestRunner recovers gracefully from unit tests
+        that change stdout, but don't change it back properly.
+
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                sys.stdout = XMLTestRunnerTest.NullStream()
+
+        runner = XMLTestRunner(self._stream)
+        runner.run(unittest.makeSuite(TestTest))
+
+    def test_unittests_changing_stderr(self):
+        """Check whether the XMLTestRunner recovers gracefully from unit tests
+        that change stderr, but don't change it back properly.
+
+        """
+        class TestTest(unittest.TestCase):
+            def test_foo(self):
+                sys.stderr = XMLTestRunnerTest.NullStream()
+
+        runner = XMLTestRunner(self._stream)
+        runner.run(unittest.makeSuite(TestTest))
+
+
+class XMLTestProgram(unittest.TestProgram):
+    def runTests(self):
+        if self.testRunner is None:
+            self.testRunner = XMLTestRunner()
+        unittest.TestProgram.runTests(self)
+
+main = XMLTestProgram
+
+
+if __name__ == "__main__":
+    main(module=None)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/CGITemplate.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/CGITemplate.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/CGITemplate.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,78 @@
+#!/usr/bin/env python
+# $Id: CGITemplate.py,v 1.6 2006/01/29 02:09:59 tavis_rudd Exp $
+"""A subclass of Cheetah.Template for use in CGI scripts.
+
+Usage in a template:
+    #extends Cheetah.Tools.CGITemplate
+    #implements respond
+    $cgiHeaders#slurp
+
+Usage in a template inheriting a Python class:
+1. The template
+    #extends MyPythonClass
+    #implements respond
+    $cgiHeaders#slurp
+
+2. The Python class
+    from Cheetah.Tools import CGITemplate
+    class MyPythonClass(CGITemplate):
+        def cgiHeadersHook(self):
+            return "Content-Type: text/html; charset=koi8-r\n\n"
+
+To read GET/POST variables, use the .webInput method defined in
+Cheetah.Utils.WebInputMixin (available in all templates without importing
+anything), use Python's 'cgi' module, or make your own arrangements.
+
+This class inherits from Cheetah.Template to make it usable in Cheetah's
+single-inheritance model.  
+
+
+Meta-Data
+================================================================================
+Author: Mike Orr <iron at mso.oz.net>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.6 $
+Start Date: 2001/10/03
+Last Revision Date: $Date: 2006/01/29 02:09:59 $
+""" 
+__author__ = "Mike Orr <iron at mso.oz.net>"
+__revision__ = "$Revision: 1.6 $"[11:-2]
+
+import os
+from Cheetah.Template import Template
+
+class CGITemplate(Template):
+    """Methods useful in CGI scripts.
+
+       Any class that inherits this mixin must also inherit Cheetah.Servlet.
+    """
+    
+
+    def cgiHeaders(self):
+        """Outputs the CGI headers if this is a CGI script.
+
+           Usage:  $cgiHeaders#slurp
+           Override .cgiHeadersHook() if you want to customize the headers.
+        """
+        if self.isCgi():
+            return self.cgiHeadersHook()
+
+
+
+    def cgiHeadersHook(self):
+        """Override if you want to customize the CGI headers.
+        """
+        return "Content-type: text/html\n\n"
+
+
+    def isCgi(self):
+        """Is this a CGI script?
+        """
+        env = os.environ.has_key('REQUEST_METHOD') 
+        wk = self._CHEETAH__isControlledByWebKit
+        return env and not wk
+
+
+    
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReport.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReport.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReport.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,464 @@
+#!/usr/bin/env python
+"""
+@@TR: This code is pretty much unsupported.
+
+MondoReport.py -- Batching module for Python and Cheetah.
+
+Version 2001-Nov-18.  Doesn't do much practical yet, but the companion
+testMondoReport.py passes all its tests.
+-Mike Orr (Iron)
+
+TODO: BatchRecord.prev/next/prev_batches/next_batches/query, prev.query,
+next.query.
+
+How about Report: .page(), .all(), .summary()?  Or PageBreaker.
+"""
+import operator, types
+try:
+    from Cheetah.NameMapper import valueForKey as lookup_func
+except ImportError:
+    def lookup_func(obj, name):
+        if hasattr(obj, name):
+            return getattr(obj, name)
+        else:
+            return obj[name] # Raises KeyError.
+
+########## CONSTANTS ##############################
+
+True, False = (1==1), (1==0)
+numericTypes = types.IntType, types.LongType, types.FloatType
+
+########## PUBLIC GENERIC FUNCTIONS ##############################
+
+class NegativeError(ValueError):
+    pass
+
+def isNumeric(v):
+    return type(v) in numericTypes
+
+def isNonNegative(v):
+    ret = isNumeric(v)
+    if ret and v < 0:
+        raise NegativeError(v)
+
+def isNotNone(v):
+    return v is not None
+
+def Roman(n):
+    n = int(n) # Raises TypeError.
+    if n < 1:
+        raise ValueError("roman numeral for zero or negative undefined: " + n)
+    roman = ''
+    while n >= 1000:
+            n = n - 1000
+            roman = roman + 'M'
+    while n >= 500:
+            n = n - 500
+            roman = roman + 'D'
+    while n >= 100:
+            n = n - 100
+            roman = roman + 'C'
+    while n >= 50:
+            n = n - 50
+            roman = roman + 'L'
+    while n >= 10:
+            n = n - 10
+            roman = roman + 'X'
+    while n >= 5:
+            n = n - 5
+            roman = roman + 'V'
+    while n < 5 and n >= 1:
+            n = n - 1
+            roman = roman + 'I'
+    roman = roman.replace('DCCCC', 'CM')
+    roman = roman.replace('CCCC', 'CD')
+    roman = roman.replace('LXXXX', 'XC')
+    roman = roman.replace('XXXX', 'XL')
+    roman = roman.replace('VIIII', 'IX')
+    roman = roman.replace('IIII', 'IV')
+    return roman
+
+
+def sum(lis):
+    return reduce(operator.add, lis, 0)
+    
+def mean(lis):
+    """Always returns a floating-point number.
+    """
+    lis_len = len(lis)
+    if lis_len == 0:
+        return 0.00 # Avoid ZeroDivisionError (not raised for floats anyway)
+    total = float( sum(lis) )
+    return total / lis_len
+
+def median(lis):
+    lis = lis[:]
+    lis.sort()
+    return lis[int(len(lis)/2)]
+
+
+def variance(lis):
+    raise NotImplementedError()
+    
+def variance_n(lis):
+    raise NotImplementedError()
+    
+def standardDeviation(lis):
+    raise NotImplementedError()
+    
+def standardDeviation_n(lis):
+    raise NotImplementedError()
+
+
+
+class IndexFormats:
+    """Eight ways to display a subscript index.
+       ("Fifty ways to leave your lover....")
+    """
+    def __init__(self, index, item=None):
+        self._index = index
+        self._number = index + 1
+        self._item = item
+
+    def index(self):
+        return self._index
+
+    __call__ = index
+
+    def number(self):
+        return self._number
+
+    def even(self):
+        return self._number % 2 == 0
+
+    def odd(self):
+        return not self.even()
+
+    def even_i(self):
+        return self._index % 2 == 0
+
+    def odd_i(self):
+        return not self.even_i()
+
+    def letter(self):
+        return self.Letter().lower()
+
+    def Letter(self):
+        n = ord('A') + self._index
+        return chr(n)
+
+    def roman(self):
+        return self.Roman().lower()
+
+    def Roman(self):
+        return Roman(self._number)
+
+    def item(self):
+        return self._item
+
+
+
+########## PRIVATE CLASSES ##############################
+
+class ValuesGetterMixin:
+    def __init__(self, origList):
+        self._origList = origList
+
+    def _getValues(self, field=None, criteria=None):
+        if field:
+            ret = [lookup_func(elm, field) for elm in self._origList]
+        else:
+            ret = self._origList
+        if criteria:
+            ret = filter(criteria, ret)
+        return ret
+
+
+class RecordStats(IndexFormats, ValuesGetterMixin):
+    """The statistics that depend on the current record.
+    """
+    def __init__(self, origList, index):
+        record = origList[index] # Raises IndexError.
+        IndexFormats.__init__(self, index, record)
+        ValuesGetterMixin.__init__(self, origList)
+    
+    def length(self):
+        return len(self._origList)
+
+    def first(self):
+        return self._index == 0
+        
+    def last(self):
+        return self._index >= len(self._origList) - 1
+
+    def _firstOrLastValue(self, field, currentIndex, otherIndex):
+        currentValue = self._origList[currentIndex] # Raises IndexError.
+        try:
+            otherValue = self._origList[otherIndex]
+        except IndexError:
+            return True
+        if field:
+            currentValue = lookup_func(currentValue, field)
+            otherValue = lookup_func(otherValue, field)
+        return currentValue != otherValue
+
+    def firstValue(self, field=None):
+        return self._firstOrLastValue(field, self._index, self._index - 1)
+
+    def lastValue(self, field=None):
+        return self._firstOrLastValue(field, self._index, self._index + 1)
+
+    # firstPage and lastPage not implemented.  Needed?
+
+    def percentOfTotal(self, field=None, suffix='%', default='N/A', decimals=2):
+        rec = self._origList[self._index]
+        if field:
+            val = lookup_func(rec, field)
+        else:
+            val = rec
+        try:
+            lis = self._getValues(field, isNumeric)
+        except NegativeError:
+            return default
+        total = sum(lis)
+        if total == 0.00: # Avoid ZeroDivisionError.
+            return default
+        val = float(val)
+        try:
+            percent = (val / total) * 100
+        except ZeroDivisionError:
+            return default
+        if decimals == 0:
+            percent = int(percent)
+        else:
+            percent = round(percent, decimals)
+        if suffix:
+            return str(percent) + suffix # String.
+        else:
+            return percent # Numeric.
+
+    def __call__(self): # Overrides IndexFormats.__call__
+        """This instance is not callable, so we override the super method.
+        """
+        raise NotImplementedError()
+
+    def prev(self):
+        if self._index == 0:
+            return None
+        else:
+            length = self.length()
+            start = self._index - length
+            return PrevNextPage(self._origList, length, start)
+
+    def next(self):
+        if self._index + self.length() == self.length():
+            return None
+        else:
+            length = self.length()
+            start = self._index + length
+            return PrevNextPage(self._origList, length, start)
+            
+    def prevPages(self):
+        raise NotImplementedError()
+        
+    def nextPages(self):
+        raise NotImplementedError()
+
+    prev_batches = prevPages
+    next_batches = nextPages
+
+    def summary(self):
+        raise NotImplementedError()
+
+
+
+    def _prevNextHelper(self, start,end,size,orphan,sequence):
+        """Copied from Zope's DT_InSV.py's "opt" function.
+        """
+        if size < 1:
+            if start > 0 and end > 0 and end >= start:
+                size=end+1-start
+            else: size=7
+
+        if start > 0:
+
+            try: sequence[start-1]
+            except: start=len(sequence)
+            # if start > l: start=l
+
+            if end > 0:
+                if end < start: end=start
+            else:
+                end=start+size-1
+                try: sequence[end+orphan-1]
+                except: end=len(sequence)
+                # if l - end < orphan: end=l
+        elif end > 0:
+            try: sequence[end-1]
+            except: end=len(sequence)
+            # if end > l: end=l
+            start=end+1-size
+            if start - 1 < orphan: start=1
+        else:
+            start=1
+            end=start+size-1
+            try: sequence[end+orphan-1]
+            except: end=len(sequence)
+            # if l - end < orphan: end=l
+        return start,end,size
+
+
+
+class Summary(ValuesGetterMixin):
+    """The summary statistics, that don't depend on the current record.
+    """
+    def __init__(self, origList):
+        ValuesGetterMixin.__init__(self, origList)
+        
+    def sum(self, field=None):
+        lis = self._getValues(field, isNumeric)
+        return sum(lis)
+
+    total = sum
+
+    def count(self, field=None):
+        lis = self._getValues(field, isNotNone)
+        return len(lis)
+        
+    def min(self, field=None):
+        lis = self._getValues(field, isNotNone)
+        return min(lis) # Python builtin function min.
+        
+    def max(self, field=None):
+        lis = self._getValues(field, isNotNone)
+        return max(lis) # Python builtin function max.
+
+    def mean(self, field=None):
+        """Always returns a floating point number.
+        """
+        lis = self._getValues(field, isNumeric)
+        return mean(lis)
+
+    average = mean
+
+    def median(self, field=None):
+        lis = self._getValues(field, isNumeric)
+        return median(lis)
+
+    def variance(self, field=None):
+        raiseNotImplementedError()
+
+    def variance_n(self, field=None):
+        raiseNotImplementedError()
+
+    def standardDeviation(self, field=None):
+        raiseNotImplementedError()
+
+    def standardDeviation_n(self, field=None):
+        raiseNotImplementedError()
+
+
+class PrevNextPage:
+    def __init__(self, origList, size, start):
+        end = start + size
+        self.start = IndexFormats(start, origList[start])
+        self.end = IndexFormats(end, origList[end])
+        self.length = size
+        
+
+########## MAIN PUBLIC CLASS ##############################
+class MondoReport:
+    _RecordStatsClass = RecordStats
+    _SummaryClass = Summary
+
+    def __init__(self, origlist):
+        self._origList = origlist
+
+    def page(self, size, start, overlap=0, orphan=0):
+        """Returns list of ($r, $a, $b)
+        """
+        if overlap != 0:
+            raise NotImplementedError("non-zero overlap")
+        if orphan != 0:
+            raise NotImplementedError("non-zero orphan")
+        origList = self._origList
+        origList_len = len(origList)
+        start = max(0, start)
+        end = min( start + size, len(self._origList) )
+        mySlice = origList[start:end]
+        ret = []
+        for rel in range(size):
+            abs_ = start + rel
+            r = mySlice[rel]
+            a = self._RecordStatsClass(origList, abs_)
+            b = self._RecordStatsClass(mySlice, rel)
+            tup = r, a, b
+            ret.append(tup)
+        return ret
+
+
+    batch = page
+
+    def all(self):
+        origList_len = len(self._origList)
+        return self.page(origList_len, 0, 0, 0)
+    
+    
+    def summary(self):
+        return self._SummaryClass(self._origList)
+
+"""
+**********************************
+    Return a pageful of records from a sequence, with statistics.
+
+       in : origlist, list or tuple.  The entire set of records.  This is
+              usually a list of objects or a list of dictionaries.
+            page, int >= 0.  Which page to display.
+            size, int >= 1.  How many records per page.
+            widow, int >=0.  Not implemented.
+            orphan, int >=0.  Not implemented.
+            base, int >=0.  Number of first page (usually 0 or 1).
+
+       out: list of (o, b) pairs.  The records for the current page.  'o' is
+              the original element from 'origlist' unchanged.  'b' is a Batch
+              object containing meta-info about 'o'.
+       exc: IndexError if 'page' or 'size' is < 1.  If 'origlist' is empty or
+              'page' is too high, it returns an empty list rather than raising
+              an error.
+        
+        origlist_len = len(origlist)
+        start = (page + base) * size
+        end = min(start + size, origlist_len)
+        ret = []
+        # widow, orphan calculation: adjust 'start' and 'end' up and down, 
+        # Set 'widow', 'orphan', 'first_nonwidow', 'first_nonorphan' attributes.
+        for i in range(start, end):
+            o = origlist[i]
+            b = Batch(origlist, size, i)
+            tup = o, b
+            ret.append(tup)
+        return ret
+
+    def prev(self):
+        # return a PrevNextPage or None
+
+    def next(self):
+        # return a PrevNextPage or None
+
+    def prev_batches(self):
+        # return a list of SimpleBatch for the previous batches
+
+    def next_batches(self):
+        # return a list of SimpleBatch for the next batches
+
+########## PUBLIC MIXIN CLASS FOR CHEETAH TEMPLATES ##############
+class MondoReportMixin:
+    def batch(self, origList, size=None, start=0, overlap=0, orphan=0):
+        bat = MondoReport(origList)
+        return bat.batch(size, start, overlap, orphan)
+    def batchstats(self, origList):
+        bat = MondoReport(origList)
+        return bat.stats()
+"""
+
+# vim: shiftwidth=4 tabstop=4 expandtab textwidth=79

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReportDoc.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReportDoc.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/MondoReportDoc.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,391 @@
+MondoReport Documentation  
+Version 0.01 alpha 24-Nov-2001.  iron at mso.oz.net or mso at oz.net.
+Copyright (c) 2001 Mike Orr.  License: same as Python or Cheetah.
+
+* * * * *
+STATUS:  previous/next batches and query string are not implemented yet.
+Sorting not designed yet.  Considering "click on this column header to sort by
+this field" and multiple ascending/descending sort fields for a future version.
+
+Tested with Python 2.2b1.  May work with Python 2.1 or 2.0.
+
+* * * * *
+OVERVIEW
+
+MondoReport -- provide information about a list that is useful in generating
+any kind of report.  The module consists of one main public class, and some
+generic functions you may find useful in other programs.  This file contains an
+overview, syntax reference and examples.  The module is designed both for
+standalone use and for integration with the Cheetah template system
+(http://www.cheetahtemplate.org/), so the examples are in both Python and
+Cheetah.  The main uses of MondoReport are: 
+
+(A) to iterate through a list.  In this sense MR is a for-loop enhancer,
+providing information that would be verbose to calculate otherwise.
+
+(B) to separate a list into equal-size "pages" (or "batches"--the two terms are
+interchangeable) and only display the current page, plus limited information
+about the previous and next pages.
+
+(C) to extract summary statistics about a certain column ("field") in the list.
+
+* * * * *
+MAIN PUBLIC CLASS
+
+To create a MondoReport instance, supply a list to operate on.
+
+    mr = MondoReport(origList)
+
+The list may be a list of anything, but if you use the 'field' argument in any
+of the methods below, the elements must be instances or dictionaries.
+
+MondoReport assumes it's operating on an unchanging list.  Do not modify the
+list or any of its elements until you are completely finished with the
+ModoReport object and its sub-objects.  Otherwise, you may get an exception or
+incorrect results.
+
+MondoReport instances have three methods:
+
+    .page(size, start, overlap=0, orphan=0
+        sort=None, reverse=False)                => list of (r, a, b).
+
+'size' is an integer >= 1.  'start', 'overlap' and 'orphan' are integers >= 0.
+The list returned contains one triple for each record in the current page.  'r'
+is the original record.  'a' is a BatchRecord instance for the current record
+in relation to all records in the origList.  'b' is a BatchRecord instance for
+the current record in relation to all the records in that batch/page.  (There
+is a .batch method that's identical to .page.)
+
+The other options aren't implemented yet, but 'overlap' duplicates this many
+records on adjacent batches.  'orphan' moves this many records or fewer, if
+they are on a page alone, onto the neighboring page.  'sort' (string) specifies
+a field to sort the records by.  It may be suffixed by ":desc" to sort in
+descending order.  'reverse' (boolean) reverses the sort order.  If both
+":desc" and 'reverse' are specified, they will cancel each other out.  This
+sorting/reversal happens on a copy of the origList, and all objects returned
+by this method use the sorted list, except when resorting the next time.
+To do more complicated sorting, such as a hierarchy of columns, do it to the
+original list before creating the ModoReport object.
+
+    .all(sort=None, reverse=False)              => list of (r, a).
+
+Same, but the current page spans the entire origList.
+
+    .summary()                                  => Summary instance.
+
+Summary statistics for the entire origList.
+
+In Python, use .page or .all in a for loop:
+
+    from Cheetah.Tools.MondoReport import MondoReport
+    mr = MondoReport(myList)
+    for r, a, b in mr.page(20, 40):
+        # Do something with r, a and b.  The current page is the third page,
+        # with twenty records corresponding to origList[40:60].
+    if not myList:
+        # Warn the user there are no records in the list.
+
+It works the same way in Cheetah, just convert to Cheetah syntax.  This example
+assumes the template doubles as a Webware servlet, so we use the servlet's
+'$request' method to look up the CGI parameter 'start'.  The default value is 0
+for the first page.
+
+    #from Cheetah.Tools.MondoReport import MondoReport
+    #set $mr = $MondoReport($bigList)
+    #set $start = $request.field("start", 0)
+    #for $o, $a, $b in $mr.page(20, $start)
+        ... do something with $o, $a and $b ...
+    #end for
+    #unless $bigList
+        This is displayed if the original list has no elements.
+        It's equivalent to the "else" part Zope DTML's <dtml-in>.
+    #end unless
+
+* * * * *
+USING 'r' RECORDS
+
+Use 'r' just as you would the original element.  For instance:
+
+    print r.attribute     # If r is an instance.
+    print r['key']        # If r is a dictionary.
+    print r               # If r is numeric or a string.
+
+In Cheetah, you can take advantage of Universal Dotted Notation and autocalling:
+
+    $r.name        ## 'name' may be an attribute or key of 'r'.  If 'r' and/or
+                   ## 'name' is a function or method, it will be called without
+                   ## arguments.
+    $r.attribute
+    $r['key']
+    $r
+    $r().attribute()['key']()
+
+If origList is a list of name/value pairs (2-tuples or 2-lists), you may
+prefer to do this:
+
+    for (key, value), a, b in mr.page(20, 40):
+        print key, "=>", value
+    
+    #for ($key, $value), $a, $b in $mr.page(20, $start)
+        $key =&gt; $value
+    #end for
+
+* * * * *
+STATISTICS METHODS AND FIELD VALUES
+
+Certain methods below have an optional argument 'field'.  If specified, 
+MondoReport will look up that field in each affected record and use its value
+in the calculation.  MondoReport uses Cheetah's NameMapper if available,
+otherwise it uses a minimal NameMapper substitute that looks for an attribute
+or dictionary key called "field".  You'll get an exception if any record is a
+type without attributes or keys, or if one or more records is missing that
+attribute/key.
+
+If 'field' is None, MondoReport will use the entire record in its
+calculation.  This makes sense mainly if the records are a numeric type.
+
+All statistics methods filter out None values from their calculations, and
+reduce the number of records accordingly.  Most filter out non-numeric fields
+(or records).  Some raise NegativeError if a numeric field (or record) is
+negative.
+
+
+* * * * *
+BatchRecord METHODS
+
+The 'a' and 'b' objects of MondoReport.page() and MondoReport.all() provide
+these methods.
+
+    .index()
+
+The current subscript.  For 'a', this is the true subscript into origList.
+For 'b', this is relative to the current page, so the first record will be 0.
+Hint: In Cheetah, use autocalling to skip the parentheses: '$b.index'.
+
+    .number()
+
+The record's position starting from 1.  This is always '.index() + 1'.
+
+    .Letter()
+
+The letter ("A", "B", "C") corresponding to .number().  Undefined if .number()
+> 26.  The current implementation just adds the offset to 'a' and returns
+whatever character it happens to be.  
+
+To make a less dumb implementation (e.g., "Z, AA, BB" or "Z, A1, B1"):
+1) Subclass BatchRecord and override the .Letter method. 
+2) Subclass MondoReport and set the class variable .BatchRecordClass to your
+new improved class.
+
+    .letter()
+
+Same but lower case.
+
+    .Roman()
+
+The Roman numeral corresponding to .number().
+
+    .roman()
+
+Same but lower case.
+
+    .even()
+
+True if .number() is even.
+
+    .odd()
+
+True if .number() is odd.
+
+    .even_i()
+
+True if .index() is even.
+
+    .odd_i()
+
+True if .index() is odd.
+
+    .length()
+
+For 'a', number of records in origList.  For 'b', number of records on this
+page.
+
+    .item()
+
+The record itself.  You don't need this in the normal case since it's the same
+as 'r', but it's useful for previous/next batches.
+
+    .size()
+
+The 'size' argument used when this BatchRecord was created.  
+'a.size() == b.size()'.
+
+    .first()
+
+True if this is the first record.
+
+    .last()
+
+True if this is the last record.
+
+    .firstValue(field=None)
+
+True if there is no previous record, or if the previous field/record has a 
+different value.  Used for to print section headers.  For instance, if you
+are printing addresses by country, this will be true at the first occurrance
+of each country.  Or for indexes, you can have a non-printing field showing
+which letter of the alphablet this entry starts with, and then print a "B"
+header before printing the first record starting with "B".
+
+    .lastValue(field=None)
+
+True if this is the last record containing the current value in the
+field/record.
+
+    .percentOfTotal(field=None, suffix="%", default="N/A", decimals=2)
+
+Returns the percent that the current field/record is of all fields/records.
+If 'suffix' is None, returns a number; otherwise it returns a string with
+'suffix' suffixed.  If the current value is non-numeric, returns 'default'
+instead (without 'suffix').  'decimals' tells the number of decimal places to
+return; if 0, there will be no decimal point.
+
+    .prev()
+
+Returns a PrevNextBatch instance for the previous page.  If there is no
+previous page, returns None.  [Not implemented yet.]
+
+    .next()
+
+Returns a PrevNextBatch instance for the next page.  If there is no next page,
+returns None.  [Not implemented yet.]
+
+    .prevPages()
+
+Returns a list of PrevNextPage instances for every previous page, or [] if no
+previous pages.  [Not implemented yet.]
+
+    .nextPages()
+
+Returns a list of PrevNextPage instances for every next page, or [] if no next
+pages.  [Not implemented yet.]
+
+    .query(start=None, label=None, attribName="start", attribs=[])
+
+[Not implemented yet.]
+
+With no arguments, returns the HTML query string with start value removed (so
+you can append a new start value in your hyperlink).  The query string is taken
+from the 'QUERY_STRING' environmental variable, or "" if missing.  (This is
+Webware compatible.)  
+
+With 'start' (an integer >= 0), returns the query string with an updated start
+value, normally for the next or previous batch.
+
+With 'label' (a string), returns a complete HTML hyperlink:
+'<A HREF="?new_query_string">label</A>'.  You'll get a TypeError if you specify
+'label' but not 'start'.
+
+With 'attribName' (a string), uses this attribute name rather than "start".
+Useful if you have another CGI parameter "start" that's used for something
+else.
+
+With 'attribs' (a dictionary), adds these attributes to the hyperlink.
+For instance, 'attribs={"target": "_blank"}'.  Ignored unless 'label' is 
+specified too.
+
+This method assumes the start parameter is a GET variable, not a POST variable.
+
+    .summary()
+
+Returns a Summary instance.  'a.summary()' refers to all records in the
+origList, so it's the same as MondoReport.summary().  'b.summary()' refers only
+to the records on the current page.  [Not implemented yet.]
+
+* * * * *
+PrevNextPage INSTANCES
+
+[Not implemented yet.]
+
+PrevNextPage instances have the following methods:
+
+    .start()
+
+The index (true index of origList) that that page starts at.  You may also use
+'.start().index()', '.start().number()', etc.  Also
+'.start().item(field=None)'.  (Oh, so *that*'s what .item is for!)
+
+    .end()
+
+The index (true index of origList) that that page ends at.  You may also use
+'.end().index()', '.end().number()', etc.   Also
+'.end().item(field=None)'.
+
+    .length()
+
+Number of records on that page.
+
+    .query(label=None, attribName="start", attribs={}, before="", after="")
+
+[Not implemented yet.]
+
+Similar to 'a.query()' and 'b.query()', but automatically calculates the start
+value for the appropriate page.  
+
+For fancy HTML formatting, 'before' is prepended to the returned text and 
+'after' is appended.  (There was an argument 'else_' for if there is no such
+batch, but it was removed because you can't even get to this method at all in
+that case.)
+
+* * * * * *
+SUMMARY STATISTICS
+
+These methods are supported by the Summary instances returned by
+MondoReport.Summary():
+
+    .sum(field=None)
+
+Sum of all numeric values in a field, or sum of all records.
+
+    .total(field=None)
+
+Same.
+
+    .count(field=None)
+
+Number of fields/records with non-None values.
+
+    .min(field=None)
+
+Minimum value in that field/record.  Ignores None values.
+
+    .max(field=None)
+
+Maximum value in that field/record.  Ignores None values.
+
+    .mean(field=None)
+
+The mean (=average) of all numeric values in that field/record.
+
+    .average(field=None)
+
+Same.
+
+    .median(field=None)
+
+The median of all numeric values in that field/record.  This is done by sorting
+the values and taking the middle value.
+
+    .variance(field=None), .variance_n(field=None)
+    .standardDeviation(field=None), .standardDeviation_n(field=None)
+
+[Not implemented yet.]
+
+
+* * * * *
+To run the regression tests (requires unittest.py, which is standard with
+Python 2.2), run MondoReportTest.py from the command line.  The regression test
+double as usage examples.
+
+
+# vim: shiftwidth=4 tabstop=4 expandtab textwidth=79

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/RecursiveNull.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/RecursiveNull.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/RecursiveNull.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+"""
+Nothing, but in a friendly way.  Good for filling in for objects you want to
+hide.  If $form.f1 is a RecursiveNull object, then
+$form.f1.anything["you"].might("use") will resolve to the empty string.
+
+This module was contributed by Ian Bicking.
+"""
+
+class RecursiveNull(object):
+    def __getattr__(self, attr):
+        return self
+    def __getitem__(self, item):
+        return self
+    def __call__(self, *args, **kwargs):
+        return self
+    def __str__(self):
+        return ''
+    def __repr__(self):
+        return ''
+    def __nonzero__(self):
+        return 0
+    def __eq__(self, x):
+        if x:
+            return False
+        return True
+    def __ne__(self, x):
+        return x and True or False
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/SiteHierarchy.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/SiteHierarchy.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/SiteHierarchy.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+# $Id: SiteHierarchy.py,v 1.1 2001/10/11 03:25:54 tavis_rudd Exp $
+"""Create menus and crumbs from a site hierarchy.
+
+You define the site hierarchy as lists/tuples.  Each location in the hierarchy
+is a (url, description) tuple.  Each list has the base URL/text in the 0
+position, and all the children coming after it.  Any child can be a list,
+representing further depth to the hierarchy.  See the end of the file for an
+example hierarchy.
+
+Use Hierarchy(contents, currentURL), where contents is this hierarchy, and
+currentURL is the position you are currently in.  The menubar and crumbs methods
+give you the HTML output.
+
+There are methods you can override to customize the HTML output.
+
+Meta-Data
+================================================================================
+Author: Ian Bicking <ianb at colorstudy.com>
+Version: $Revision: 1.1 $
+Start Date: 2001/07/23
+Last Revision Date: $Date: 2001/10/11 03:25:54 $
+"""
+__author__ = "Ian Bicking <ianb at colorstudy.com>"
+__version__ = "$Revision: 1.1 $"[11:-2]
+
+##################################################
+## DEPENDENCIES
+import string
+try:
+	from cStringIO import StringIO
+except ImportError:
+	from StringIO import StringIO
+
+
+##################################################
+## GLOBALS & CONSTANTS
+
+True, False = (1==1), (0==1)
+
+##################################################
+## CLASSES
+
+class Hierarchy:
+	def __init__(self, hierarchy, currentURL, prefix='', menuCSSClass=None,
+				 crumbCSSClass=None):
+		"""
+		hierarchy is described above, currentURL should be somewhere in
+		the hierarchy.  prefix will be added before all of the URLs (to
+		help mitigate the problems with absolute URLs), and if given,
+		cssClass will be used for both links *and* nonlinks.
+		"""
+
+		self._contents = hierarchy
+		self._currentURL = currentURL
+		if menuCSSClass:
+			self._menuCSSClass = ' class="%s"' % menuCSSClass
+		else:
+			self._menuCSSClass = ''
+		if crumbCSSClass:
+			self._crumbCSSClass = ' class="%s"' % crumbCSSClass
+		else:
+			self._crumbCSSClass = ''
+		self._prefix=prefix
+
+	
+	## Main output methods
+	
+	def menuList(self, menuCSSClass=None):
+		"""An indented menu list"""
+		if menuCSSClass:
+			self._menuCSSClass = ' class="%s"' % menuCSSClass
+		
+		stream = StringIO()
+		for item in self._contents[1:]:
+			self._menubarRecurse(item, 0, stream)
+		return stream.getvalue()
+
+	def crumbs(self, crumbCSSClass=None):
+		"""The home>where>you>are crumbs"""
+		if crumbCSSClass:
+			self._crumbCSSClass = ' class="%s"' % crumbCSSClass
+		
+		path = []
+		pos = self._contents
+		while 1:
+			## This is not the fastest algorithm, I'm afraid.
+			## But it probably won't be for a huge hierarchy anyway.
+			foundAny = False
+			path.append(pos[0])
+			for item in pos[1:]:
+				if self._inContents(item):
+					if type(item) is type(()):
+						path.append(item)
+						break
+					else:
+						pos = item
+						foundAny = True
+						break
+			if not foundAny:
+				break
+		if len(path) == 1:
+			return self.emptyCrumb()
+		return string.join(map(lambda x, self=self: self.crumbLink(x[0], x[1]),
+							   path), self.crumbSeperator()) + \
+							   self.crumbTerminator()
+
+	## Methods to control the Aesthetics
+	#  - override these methods for your own look
+		
+	def menuLink(self, url, text, indent):
+		if url == self._currentURL or self._prefix + url == self._currentURL:
+			return '%s<B%s>%s</B> <BR>\n' % ('&nbsp;'*2*indent,
+							 self._menuCSSClass, text)
+		else:
+			return '%s<A HREF="%s%s"%s>%s</A> <BR>\n' % \
+				   ('&nbsp;'*2*indent, self._prefix, url,
+					self._menuCSSClass, text)
+		
+	def crumbLink(self, url, text):
+		if url == self._currentURL or self._prefix + url == self._currentURL:
+			return '<B%s>%s</B>' % (text, self._crumbCSSClass)
+		else:
+			return '<A HREF="%s%s"%s>%s</A>' % \
+				   (self._prefix, url, self._crumbCSSClass, text)
+		
+	def crumbSeperator(self):
+		return '&nbsp;&gt;&nbsp;'
+	
+	def crumbTerminator(self):
+		return ''
+	
+	def emptyCrumb(self):
+		"""When you are at the homepage"""
+		return ''
+				
+	## internal methods
+	
+	def _menubarRecurse(self, contents, indent, stream):
+		if type(contents) is type(()):
+			url, text = contents
+			rest = []
+		else:
+			url, text = contents[0]
+			rest = contents[1:]
+		stream.write(self.menuLink(url, text, indent))
+		if self._inContents(contents):
+			for item in rest:
+				self._menubarRecurse(item, indent+1, stream)
+
+	def _inContents(self, contents):
+		if type(contents) is type(()):
+			return self._currentURL == contents[0]
+		for item in contents:
+			if self._inContents(item):
+				return True
+		return False
+
+##################################################
+## from the command line
+
+if __name__ == '__main__':
+	hierarchy = [('/', 'home'),
+		    ('/about', 'About Us'),
+		    [('/services', 'Services'),
+		     [('/services/products', 'Products'),
+		      ('/services/products/widget', 'The Widget'),
+		      ('/services/products/wedge', 'The Wedge'),
+		      ('/services/products/thimble', 'The Thimble'),
+		      ],
+		     ('/services/prices', 'Prices'),
+		     ],
+		    ('/contact', 'Contact Us'),
+		    ]
+
+	for url in ['/', '/services', '/services/products/widget', '/contact']:
+		print '<p>', '='*50
+		print '<br> %s: <br>\n' % url
+		n = Hierarchy(hierarchy, url, menuCSSClass='menu', crumbCSSClass='crumb',
+			      prefix='/here')
+		print n.menuList()
+		print '<p>', '-'*50
+		print n.crumbs()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Tools/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+"""This package contains classes, functions, objects and packages contributed
+   by Cheetah users.  They are not used by Cheetah itself.  There is no
+   guarantee that this directory will be included in Cheetah releases, that
+   these objects will remain here forever, or that they will remain
+   backward-compatible.
+"""
+
+# vim: shiftwidth=5 tabstop=5 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Unspecified.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Unspecified.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Unspecified.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+try:
+    from ds.sys.Unspecified import Unspecified
+except ImportError:
+    class _Unspecified:
+        def __repr__(self):
+            return 'Unspecified'        
+        def __str__(self):
+            return 'Unspecified'
+    Unspecified = _Unspecified()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Indenter.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Indenter.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Indenter.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# $Id: Indenter.py,v 1.7 2006/01/08 01:09:30 tavis_rudd Exp $
+"""Indentation maker.
+@@TR: this code is unsupported and largely undocumented ...
+
+This version is based directly on code by Robert Kuzelj
+<robert_kuzelj at yahoo.com> and uses his directive syntax.  Some classes and
+attributes have been renamed.  Indentation is output via
+$self._CHEETAH__indenter.indent() to prevent '_indenter' being looked up on the
+searchList and another one being found.  The directive syntax will
+soon be changed somewhat.
+
+Meta-Data
+================================================================================
+Author: Mike Orr <iron at mso.oz.net>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.7 $
+Start Date: 2001/11/07
+Last Revision Date: $Date: 2006/01/08 01:09:30 $
+""" 
+__author__ = "Mike Orr <iron at mso.oz.net>"
+__revision__ = "$Revision: 1.7 $"[11:-2]
+
+import re
+import sys
+
+def indentize(source):
+    return IndentProcessor().process(source)
+
+class IndentProcessor:
+    """Preprocess #indent tags."""
+    LINE_SEP = '\n'
+    ARGS = "args"
+    INDENT_DIR = re.compile(r'[ \t]*#indent[ \t]*(?P<args>.*)')
+    DIRECTIVE = re.compile(r"[ \t]*#")
+    WS = "ws"
+    WHITESPACES = re.compile(r"(?P<ws>[ \t]*)")
+
+    INC = "++"
+    DEC = "--"
+    
+    SET = "="
+    CHAR = "char"
+    
+    ON = "on"
+    OFF = "off"
+
+    PUSH = "push"
+    POP = "pop"
+    
+    def process(self, _txt):
+        result = []
+
+        for line in _txt.splitlines():
+            match = self.INDENT_DIR.match(line)
+            if match:
+                #is indention directive
+                args = match.group(self.ARGS).strip()
+                if args == self.ON:
+                    line = "#silent $self._CHEETAH__indenter.on()"
+                elif args == self.OFF:
+                    line = "#silent $self._CHEETAH__indenter.off()"
+                elif args == self.INC:
+                    line = "#silent $self._CHEETAH__indenter.inc()"
+                elif args == self.DEC:
+                    line = "#silent $self._CHEETAH__indenter.dec()"
+                elif args.startswith(self.SET):
+                    level = int(args[1:])
+                    line = "#silent $self._CHEETAH__indenter.setLevel(%(level)d)" % {"level":level}
+                elif args.startswith('chars'):
+                    self.indentChars = eval(args.split('=')[1])
+                    line = "#silent $self._CHEETAH__indenter.setChars(%(level)d)" % {"level":level}
+                elif args.startswith(self.PUSH):
+                    line = "#silent $self._CHEETAH__indenter.push()"
+                elif args.startswith(self.POP):
+                    line = "#silent $self._CHEETAH__indenter.pop()"
+            else:
+                match = self.DIRECTIVE.match(line)
+                if not match:
+                    #is not another directive
+                    match = self.WHITESPACES.match(line)
+                    if match:
+                        size = len(match.group("ws").expandtabs(4))
+                        line = ("${self._CHEETAH__indenter.indent(%(size)d)}" % {"size":size}) + line.lstrip()
+                    else:
+                        line = "${self._CHEETAH__indenter.indent(0)}" + line
+            result.append(line)
+
+        return self.LINE_SEP.join(result)
+
+class Indenter:
+    """A class that keeps track of the current indentation level.
+    .indent() returns the appropriate amount of indentation.
+    """
+    def __init__(self):
+        self.On = 1
+        self.Level = 0
+        self.Chars = " "*4
+        self.LevelStack = []
+    def on(self):
+        self.On = 1
+    def off(self):
+        self.On = 0
+    def inc(self):
+        self.Level += 1
+    def dec(self):
+        """decrement can only be applied to values greater zero
+            values below zero don't make any sense at all!"""
+        if self.Level > 0:
+            self.Level -= 1
+    def push(self):
+        self.LevelStack.append(self.Level)
+    def pop(self):
+        """the levestack can not become -1. any attempt to do so
+           sets the level to 0!"""
+        if len(self.LevelStack) > 0:
+            self.Level = self.LevelStack.pop()
+        else:
+            self.Level = 0
+    def setLevel(self, _level):
+        """the leve can't be less than zero. any attempt to do so
+           sets the level automatically to zero!"""
+        if _level < 0:
+            self.Level = 0
+        else:
+            self.Level = _level
+    def setChar(self, _chars):
+        self.Chars = _chars
+    def indent(self, _default=0):
+        if self.On:
+            return self.Chars * self.Level
+        else:
+            return " " * _default
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Misc.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Misc.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/Misc.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# $Id: Misc.py,v 1.8 2005/11/02 22:26:08 tavis_rudd Exp $
+"""Miscellaneous functions/objects used by Cheetah but also useful standalone.
+
+Meta-Data
+================================================================================
+Author: Mike Orr <iron at mso.oz.net>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.8 $
+Start Date: 2001/11/07
+Last Revision Date: $Date: 2005/11/02 22:26:08 $
+""" 
+__author__ = "Mike Orr <iron at mso.oz.net>"
+__revision__ = "$Revision: 1.8 $"[11:-2]
+
+import os          # Used in mkdirsWithPyInitFile.
+import types       # Used in useOrRaise.
+import sys         # Used in die.
+
+##################################################
+## MISCELLANEOUS FUNCTIONS
+
+def die(reason):
+    sys.stderr.write(reason + '\n')
+    sys.exit(1)
+
+def useOrRaise(thing, errmsg=''):
+    """Raise 'thing' if it's a subclass of Exception.  Otherwise return it.
+
+    Called by: Cheetah.Servlet.cgiImport()
+    """
+    if type(thing) == types.ClassType and issubclass(thing, Exception):
+        raise thing(errmsg)
+    return thing
+
+
+def checkKeywords(dic, legalKeywords, what='argument'):
+    """Verify no illegal keyword arguments were passed to a function.
+
+    in : dic, dictionary (**kw in the calling routine).
+         legalKeywords, list of strings, the keywords that are allowed.
+         what, string, suffix for error message (see function source).
+    out: None.
+    exc: TypeError if 'dic' contains a key not in 'legalKeywords'.
+    called by: Cheetah.Template.__init__()
+    """
+    # XXX legalKeywords could be a set when sets get added to Python.
+    for k in dic.keys(): # Can be dic.iterkeys() if Python >= 2.2.
+        if k not in legalKeywords: 
+            raise TypeError("'%s' is not a valid %s" % (k, what))
+
+
+def removeFromList(list_, *elements):
+    """Save as list_.remove(each element) but don't raise an error if
+       element is missing.  Modifies 'list_' in place!  Returns None.
+    """
+    for elm in elements:
+        try:
+            list_.remove(elm)
+        except ValueError:
+            pass
+
+
+def mkdirsWithPyInitFiles(path):
+    """Same as os.makedirs (mkdir 'path' and all missing parent directories)
+       but also puts a Python '__init__.py' file in every directory it
+       creates.  Does nothing (without creating an '__init__.py' file) if the
+       directory already exists.  
+    """
+    dir, fil = os.path.split(path)
+    if dir and not os.path.exists(dir):
+        mkdirsWithPyInitFiles(dir)
+    if not os.path.exists(path):
+        os.mkdir(path)
+        init = os.path.join(path, "__init__.py")
+        f = open(init, 'w') # Open and close to produce empty file.
+        f.close()
+
+
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/VerifyType.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/VerifyType.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/VerifyType.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+# $Id: VerifyType.py,v 1.4 2005/11/02 22:26:08 tavis_rudd Exp $
+"""Functions to verify an argument's type
+
+Meta-Data
+================================================================================
+Author: Mike Orr <iron at mso.oz.net>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.4 $
+Start Date: 2001/11/07
+Last Revision Date: $Date: 2005/11/02 22:26:08 $
+""" 
+__author__ = "Mike Orr <iron at mso.oz.net>"
+__revision__ = "$Revision: 1.4 $"[11:-2]
+
+##################################################
+## DEPENDENCIES
+
+import types       # Used in VerifyTypeClass.
+
+##################################################
+## PRIVATE FUNCTIONS
+
+def _errmsg(argname, ltd, errmsgExtra=''):
+    """Construct an error message.
+
+    argname, string, the argument name.
+    ltd, string, description of the legal types.
+    errmsgExtra, string, text to append to error mssage.
+    Returns: string, the error message.
+    """
+    if errmsgExtra:
+        errmsgExtra = '\n' + errmsgExtra
+    return "arg '%s' must be %s%s" % (argname, ltd, errmsgExtra)
+
+
+##################################################
+## TYPE VERIFICATION FUNCTIONS
+
+def VerifyType(arg, argname, legalTypes, ltd, errmsgExtra=''):
+    """Verify the type of an argument.
+    
+    arg, any, the argument.
+    argname, string, name of the argument.
+    legalTypes, list of type objects, the allowed types.
+    ltd, string, description of legal types (for error message).
+    errmsgExtra, string, text to append to error message.
+    Returns: None.
+    Exceptions: TypeError if 'arg' is the wrong type.
+    """
+    if type(arg) not in legalTypes:
+        m = _errmsg(argname, ltd, errmsgExtra)
+        raise TypeError(m)
+
+
+def VerifyTypeClass(arg, argname, legalTypes, ltd, klass, errmsgExtra=''):
+    """Same, but if it's a class, verify it's a subclass of the right class.
+
+    arg, any, the argument.
+    argname, string, name of the argument.
+    legalTypes, list of type objects, the allowed types.
+    ltd, string, description of legal types (for error message).
+    klass, class, the parent class.
+    errmsgExtra, string, text to append to the error message.
+    Returns: None.
+    Exceptions: TypeError if 'arg' is the wrong type.
+    """
+    VerifyType(arg, argname, legalTypes, ltd, errmsgExtra)
+    # If no exception, the arg is a legal type.
+    if type(arg) == types.ClassType and not issubclass(arg, klass):
+        # Must test for "is class type" to avoid TypeError from issubclass().
+        m = _errmsg(argname, ltd, errmsgExtra)
+        raise TypeError(m)
+
+# @@MO: Commented until we determine whether it's useful.
+#def VerifyClass(arg, argname, klass, ltd):
+#    """Same, but allow *only* a subclass of the right class.
+#    """
+#    VerifyTypeClass(arg, argname, [types.ClassType], ltd, klass)
+
+# vim: shiftwidth=4 tabstop=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/WebInputMixin.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/WebInputMixin.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/WebInputMixin.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+# $Id: WebInputMixin.py,v 1.10 2006/01/06 21:56:54 tavis_rudd Exp $
+"""Provides helpers for Template.webInput(), a method for importing web
+transaction variables in bulk.  See the docstring of webInput for full details.
+
+Meta-Data
+================================================================================
+Author: Mike Orr <iron at mso.oz.net>
+License: This software is released for unlimited distribution under the
+         terms of the MIT license.  See the LICENSE file.
+Version: $Revision: 1.10 $
+Start Date: 2002/03/17
+Last Revision Date: $Date: 2006/01/06 21:56:54 $
+""" 
+__author__ = "Mike Orr <iron at mso.oz.net>"
+__revision__ = "$Revision: 1.10 $"[11:-2]
+
+from Cheetah.Utils.Misc import useOrRaise
+
+class NonNumericInputError(ValueError): pass
+
+##################################################
+## PRIVATE FUNCTIONS AND CLASSES
+
+class _Converter:
+    """A container object for info about type converters.
+    .name, string, name of this converter (for error messages).
+    .func, function, factory function.
+    .default, value to use or raise if the real value is missing.
+    .error, value to use or raise if .func() raises an exception.
+    """
+    def __init__(self, name, func, default, error):
+        self.name = name
+        self.func = func
+        self.default = default
+        self.error = error
+
+
+def _lookup(name, func, multi, converters):
+    """Look up a Webware field/cookie/value/session value.  Return
+    '(realName, value)' where 'realName' is like 'name' but with any
+    conversion suffix strips off.  Applies numeric conversion and
+    single vs multi values according to the comments in the source.
+    """
+    # Step 1 -- split off the conversion suffix from 'name'; e.g. "height:int".
+    # If there's no colon, the suffix is "".  'longName' is the name with the 
+    # suffix, 'shortName' is without.    
+    # XXX This implementation assumes "height:" means "height".
+    colon = name.find(':')
+    if colon != -1:
+        longName = name
+        shortName, ext = name[:colon], name[colon+1:]
+    else:
+        longName = shortName = name
+        ext = ''
+
+    # Step 2 -- look up the values by calling 'func'.
+    if longName != shortName:
+        values = func(longName, None) or func(shortName, None)
+    else:
+        values = func(shortName, None)
+    # 'values' is a list of strings, a string or None.
+
+    # Step 3 -- Coerce 'values' to a list of zero, one or more strings.
+    if   values is None:
+        values = []
+    elif isinstance(values, str):
+        values = [values]
+
+    # Step 4 -- Find a _Converter object or raise TypeError.
+    try:
+        converter = converters[ext]
+    except KeyError:
+        fmt = "'%s' is not a valid converter name in '%s'"
+        tup = (ext, longName)
+        raise TypeError(fmt % tup)    
+
+    # Step 5 -- if there's a converter func, run it on each element.
+    # If the converter raises an exception, use or raise 'converter.error'.
+    if converter.func is not None:
+        tmp = values[:]
+        values = []
+        for elm in tmp:
+            try:
+                elm = converter.func(elm)
+            except (TypeError, ValueError):
+                tup = converter.name, elm
+                errmsg = "%s '%s' contains invalid characters" % tup
+                elm = useOrRaise(converter.error, errmsg)
+            values.append(elm)
+    # 'values' is now a list of strings, ints or floats.
+
+    # Step 6 -- If we're supposed to return a multi value, return the list
+    # as is.  If we're supposed to return a single value and the list is
+    # empty, return or raise 'converter.default'.  Otherwise, return the
+    # first element in the list and ignore any additional values.
+    if   multi:
+        return shortName, values
+    if len(values) == 0:
+        return shortName, useOrRaise(converter.default)
+    return shortName, values[0]
+
+# vim: sw=4 ts=4 expandtab

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlDecode.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlDecode.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlDecode.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+"""This is a copy of the htmlDecode function in Webware.
+
+@@TR: It implemented more efficiently.
+
+"""
+
+from Cheetah.Utils.htmlEncode import htmlCodesReversed
+
+def htmlDecode(s, codes=htmlCodesReversed):
+    """ Returns the ASCII decoded version of the given HTML string. This does
+    NOT remove normal HTML tags like <p>. It is the inverse of htmlEncode()."""
+    for code in codes:
+        s = s.replace(code[1], code[0])
+    return s

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlEncode.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlEncode.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/htmlEncode.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+"""This is a copy of the htmlEncode function in Webware.
+
+
+@@TR: It implemented more efficiently.
+
+"""
+htmlCodes = [
+    ['&', '&amp;'],
+    ['<', '&lt;'],
+    ['>', '&gt;'],
+    ['"', '&quot;'],
+]
+htmlCodesReversed = htmlCodes[:]
+htmlCodesReversed.reverse()
+
+def htmlEncode(s, codes=htmlCodes):
+    """ Returns the HTML encoded version of the given string. This is useful to
+    display a plain ASCII text string on a web page."""
+    for code in codes:
+        s = s.replace(code[0], code[1])
+    return s

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/memcache.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/memcache.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/memcache.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,625 @@
+#!/usr/bin/env python
+
+"""
+client module for memcached (memory cache daemon)
+
+Overview
+========
+
+See U{the MemCached homepage<http://www.danga.com/memcached>} for more about memcached.
+
+Usage summary
+=============
+
+This should give you a feel for how this module operates::
+
+    import memcache
+    mc = memcache.Client(['127.0.0.1:11211'], debug=0)
+
+    mc.set("some_key", "Some value")
+    value = mc.get("some_key")
+
+    mc.set("another_key", 3)
+    mc.delete("another_key")
+    
+    mc.set("key", "1")   # note that the key used for incr/decr must be a string.
+    mc.incr("key")
+    mc.decr("key")
+
+The standard way to use memcache with a database is like this::
+
+    key = derive_key(obj)
+    obj = mc.get(key)
+    if not obj:
+        obj = backend_api.get(...)
+        mc.set(key, obj)
+
+    # we now have obj, and future passes through this code
+    # will use the object from the cache.
+
+Detailed Documentation
+======================
+
+More detailed documentation is available in the L{Client} class.
+"""
+
+import sys
+import socket
+import time
+import types
+try:
+    import cPickle as pickle
+except ImportError:
+    import pickle
+
+__author__    = "Evan Martin <martine at danga.com>"
+__version__   = "1.2_tummy5"
+__copyright__ = "Copyright (C) 2003 Danga Interactive"
+__license__   = "Python"
+
+class _Error(Exception):
+    pass
+
+class Client:
+    """
+    Object representing a pool of memcache servers.
+    
+    See L{memcache} for an overview.
+
+    In all cases where a key is used, the key can be either:
+        1. A simple hashable type (string, integer, etc.).
+        2. A tuple of C{(hashvalue, key)}.  This is useful if you want to avoid
+        making this module calculate a hash value.  You may prefer, for
+        example, to keep all of a given user's objects on the same memcache
+        server, so you could use the user's unique id as the hash value.
+
+    @group Setup: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog
+    @group Insertion: set, add, replace
+    @group Retrieval: get, get_multi
+    @group Integers: incr, decr
+    @group Removal: delete
+    @sort: __init__, set_servers, forget_dead_hosts, disconnect_all, debuglog,\
+           set, add, replace, get, get_multi, incr, decr, delete
+    """
+
+    _usePickle = False
+    _FLAG_PICKLE  = 1<<0
+    _FLAG_INTEGER = 1<<1
+    _FLAG_LONG    = 1<<2
+
+    _SERVER_RETRIES = 10  # how many times to try finding a free server.
+
+    def __init__(self, servers, debug=0):
+        """
+        Create a new Client object with the given list of servers.
+
+        @param servers: C{servers} is passed to L{set_servers}.
+        @param debug: whether to display error messages when a server can't be
+        contacted.
+        """
+        self.set_servers(servers)
+        self.debug = debug
+        self.stats = {}
+    
+    def set_servers(self, servers):
+        """
+        Set the pool of servers used by this client.
+
+        @param servers: an array of servers.
+        Servers can be passed in two forms:
+            1. Strings of the form C{"host:port"}, which implies a default weight of 1.
+            2. Tuples of the form C{("host:port", weight)}, where C{weight} is
+            an integer weight value.
+        """
+        self.servers = [_Host(s, self.debuglog) for s in servers]
+        self._init_buckets()
+
+    def get_stats(self):
+        '''Get statistics from each of the servers.  
+
+        @return: A list of tuples ( server_identifier, stats_dictionary ).
+            The dictionary contains a number of name/value pairs specifying
+            the name of the status field and the string value associated with
+            it.  The values are not converted from strings.
+        '''
+        data = []
+        for s in self.servers:
+            if not s.connect(): continue
+            name = '%s:%s (%s)' % ( s.ip, s.port, s.weight )
+            s.send_cmd('stats')
+            serverData = {}
+            data.append(( name, serverData ))
+            readline = s.readline
+            while 1:
+                line = readline()
+                if not line or line.strip() == 'END': break
+                stats = line.split(' ', 2)
+                serverData[stats[1]] = stats[2]
+
+        return(data)
+
+    def flush_all(self):
+        'Expire all data currently in the memcache servers.'
+        for s in self.servers:
+            if not s.connect(): continue
+            s.send_cmd('flush_all')
+            s.expect("OK")
+
+    def debuglog(self, str):
+        if self.debug:
+            sys.stderr.write("MemCached: %s\n" % str)
+
+    def _statlog(self, func):
+        if not self.stats.has_key(func):
+            self.stats[func] = 1
+        else:
+            self.stats[func] += 1
+
+    def forget_dead_hosts(self):
+        """
+        Reset every host in the pool to an "alive" state.
+        """
+        for s in self.servers:
+            s.dead_until = 0
+
+    def _init_buckets(self):
+        self.buckets = []
+        for server in self.servers:
+            for i in range(server.weight):
+                self.buckets.append(server)
+
+    def _get_server(self, key):
+        if type(key) == types.TupleType:
+            serverhash = key[0]
+            key = key[1]
+        else:
+            serverhash = hash(key)
+
+        for i in range(Client._SERVER_RETRIES):
+            server = self.buckets[serverhash % len(self.buckets)]
+            if server.connect():
+                #print "(using server %s)" % server,
+                return server, key
+            serverhash = hash(str(serverhash) + str(i))
+        return None, None
+
+    def disconnect_all(self):
+        for s in self.servers:
+            s.close_socket()
+    
+    def delete(self, key, time=0):
+        '''Deletes a key from the memcache.
+        
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+        self._statlog('delete')
+        if time != None:
+            cmd = "delete %s %d" % (key, time)
+        else:
+            cmd = "delete %s" % key
+
+        try:
+            server.send_cmd(cmd)
+            server.expect("DELETED")
+        except socket.error, msg:
+            server.mark_dead(msg[1])
+            return 0
+        return 1
+
+    def incr(self, key, delta=1):
+        """
+        Sends a command to the server to atomically increment the value for C{key} by
+        C{delta}, or by 1 if C{delta} is unspecified.  Returns None if C{key} doesn't
+        exist on server, otherwise it returns the new value after incrementing.
+
+        Note that the value for C{key} must already exist in the memcache, and it
+        must be the string representation of an integer.
+
+        >>> mc.set("counter", "20")  # returns 1, indicating success
+        1
+        >>> mc.incr("counter")
+        21
+        >>> mc.incr("counter")
+        22
+
+        Overflow on server is not checked.  Be aware of values approaching
+        2**32.  See L{decr}.
+
+        @param delta: Integer amount to increment by (should be zero or greater).
+        @return: New value after incrementing.
+        @rtype: int
+        """
+        return self._incrdecr("incr", key, delta)
+
+    def decr(self, key, delta=1):
+        """
+        Like L{incr}, but decrements.  Unlike L{incr}, underflow is checked and
+        new values are capped at 0.  If server value is 1, a decrement of 2
+        returns 0, not -1.
+
+        @param delta: Integer amount to decrement by (should be zero or greater).
+        @return: New value after decrementing.
+        @rtype: int
+        """
+        return self._incrdecr("decr", key, delta)
+
+    def _incrdecr(self, cmd, key, delta):
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+        self._statlog(cmd)
+        cmd = "%s %s %d" % (cmd, key, delta)
+        try:
+            server.send_cmd(cmd)
+            line = server.readline()
+            return int(line)
+        except socket.error, msg:
+            server.mark_dead(msg[1])
+            return None
+
+    def add(self, key, val, time=0):
+        '''
+        Add new key with value.
+        
+        Like L{set}, but only stores in memcache if the key doesn\'t already exist.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("add", key, val, time)
+    def replace(self, key, val, time=0):
+        '''Replace existing key with value.
+        
+        Like L{set}, but only stores in memcache if the key already exists.  
+        The opposite of L{add}.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("replace", key, val, time)
+    def set(self, key, val, time=0):
+        '''Unconditionally sets a key to a given value in the memcache.
+
+        The C{key} can optionally be an tuple, with the first element being the
+        hash value, if you want to avoid making this module calculate a hash value.
+        You may prefer, for example, to keep all of a given user's objects on the
+        same memcache server, so you could use the user's unique id as the hash
+        value.
+
+        @return: Nonzero on success.
+        @rtype: int
+        '''
+        return self._set("set", key, val, time)
+    
+    def _set(self, cmd, key, val, time):
+        server, key = self._get_server(key)
+        if not server:
+            return 0
+
+        self._statlog(cmd)
+
+        flags = 0
+        if isinstance(val, types.StringTypes):
+            pass
+        elif isinstance(val, int):
+            flags |= Client._FLAG_INTEGER
+            val = "%d" % val
+        elif isinstance(val, long):
+            flags |= Client._FLAG_LONG
+            val = "%d" % val
+        elif self._usePickle:
+            flags |= Client._FLAG_PICKLE
+            val = pickle.dumps(val, 2)
+        else:
+            pass
+        
+        fullcmd = "%s %s %d %d %d\r\n%s" % (cmd, key, flags, time, len(val), val)
+        try:
+            server.send_cmd(fullcmd)
+            server.expect("STORED")
+        except socket.error, msg:
+            server.mark_dead(msg[1])
+            return 0
+        return 1
+
+    def get(self, key):
+        '''Retrieves a key from the memcache.
+        
+        @return: The value or None.
+        '''
+        server, key = self._get_server(key)
+        if not server:
+            return None
+
+        self._statlog('get')
+
+        try:
+            server.send_cmd("get %s" % key)
+            rkey, flags, rlen, = self._expectvalue(server)
+            if not rkey:
+                return None
+            value = self._recv_value(server, flags, rlen)
+            server.expect("END")
+        except (_Error, socket.error), msg:
+            if type(msg) is types.TupleType:
+                msg = msg[1]
+            server.mark_dead(msg)
+            return None
+        return value
+
+    def get_multi(self, keys):
+        '''
+        Retrieves multiple keys from the memcache doing just one query.
+        
+        >>> success = mc.set("foo", "bar")
+        >>> success = mc.set("baz", 42)
+        >>> mc.get_multi(["foo", "baz", "foobar"]) == {"foo": "bar", "baz": 42}
+        1
+
+        This method is recommended over regular L{get} as it lowers the number of
+        total packets flying around your network, reducing total latency, since
+        your app doesn\'t have to wait for each round-trip of L{get} before sending
+        the next one.
+
+        @param keys: An array of keys.
+        @return:  A dictionary of key/value pairs that were available.
+
+        '''
+
+        self._statlog('get_multi')
+
+        server_keys = {}
+
+        # build up a list for each server of all the keys we want.
+        for key in keys:
+            server, key = self._get_server(key)
+            if not server:
+                continue
+            if not server_keys.has_key(server):
+                server_keys[server] = []
+            server_keys[server].append(key)
+
+        # send out all requests on each server before reading anything
+        dead_servers = []
+        for server in server_keys.keys():
+            try:
+                server.send_cmd("get %s" % " ".join(server_keys[server]))
+            except socket.error, msg:
+                server.mark_dead(msg[1])
+                dead_servers.append(server)
+
+        # if any servers died on the way, don't expect them to respond.
+        for server in dead_servers:
+            del server_keys[server]
+
+        retvals = {}
+        for server in server_keys.keys():
+            try:
+                line = server.readline()
+                while line and line != 'END':
+                    rkey, flags, rlen = self._expectvalue(server, line)
+                    #  Bo Yang reports that this can sometimes be None
+                    if rkey is not None:
+                        val = self._recv_value(server, flags, rlen)
+                        retvals[rkey] = val
+                    line = server.readline()
+            except (_Error, socket.error), msg:
+                server.mark_dead(msg)
+        return retvals
+
+    def _expectvalue(self, server, line=None):
+        if not line:
+            line = server.readline()
+
+        if line[:5] == 'VALUE':
+            resp, rkey, flags, len = line.split()
+            flags = int(flags)
+            rlen = int(len)
+            return (rkey, flags, rlen)
+        else:
+            return (None, None, None)
+
+    def _recv_value(self, server, flags, rlen):
+        rlen += 2 # include \r\n
+        buf = server.recv(rlen)
+        if len(buf) != rlen:
+            raise _Error("received %d bytes when expecting %d" % (len(buf), rlen))
+
+        if len(buf) == rlen:
+            buf = buf[:-2]  # strip \r\n
+
+        if flags == 0:
+            val = buf
+        elif flags & Client._FLAG_INTEGER:
+            val = int(buf)
+        elif flags & Client._FLAG_LONG:
+            val = long(buf)
+        elif self._usePickle and flags & Client._FLAG_PICKLE:
+            try:
+                val = pickle.loads(buf)
+            except:
+                self.debuglog('Pickle error...\n')
+                val = None
+        else:
+            self.debuglog("unknown flags on get: %x\n" % flags)
+
+        return val
+
+class _Host:
+    _DEAD_RETRY = 30  # number of seconds before retrying a dead server.
+
+    def __init__(self, host, debugfunc=None):
+        if isinstance(host, types.TupleType):
+            host = host[0]
+            self.weight = host[1]
+        else:
+            self.weight = 1
+
+        if host.find(":") > 0:
+            self.ip, self.port = host.split(":")
+            self.port = int(self.port)
+        else:
+            self.ip, self.port = host, 11211
+
+        if not debugfunc:
+            debugfunc = lambda x: x
+        self.debuglog = debugfunc
+
+        self.deaduntil = 0
+        self.socket = None
+    
+    def _check_dead(self):
+        if self.deaduntil and self.deaduntil > time.time():
+            return 1
+        self.deaduntil = 0
+        return 0
+
+    def connect(self):
+        if self._get_socket():
+            return 1
+        return 0
+
+    def mark_dead(self, reason):
+        self.debuglog("MemCache: %s: %s.  Marking dead." % (self, reason))
+        self.deaduntil = time.time() + _Host._DEAD_RETRY
+        self.close_socket()
+        
+    def _get_socket(self):
+        if self._check_dead():
+            return None
+        if self.socket:
+            return self.socket
+        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+        # Python 2.3-ism:  s.settimeout(1)
+        try:
+            s.connect((self.ip, self.port))
+        except socket.error, msg:
+            self.mark_dead("connect: %s" % msg[1])
+            return None
+        self.socket = s
+        return s
+    
+    def close_socket(self):
+        if self.socket:
+            self.socket.close()
+            self.socket = None
+
+    def send_cmd(self, cmd):
+        if len(cmd) > 100:
+            self.socket.sendall(cmd)
+            self.socket.sendall('\r\n')
+        else:
+            self.socket.sendall(cmd + '\r\n')
+
+    def readline(self):
+        buffers = ''
+        recv = self.socket.recv
+        while 1:
+            data = recv(1)
+            if not data:
+                self.mark_dead('Connection closed while reading from %s'
+                        % repr(self))
+                break
+            if data == '\n' and buffers and buffers[-1] == '\r':
+                return(buffers[:-1])
+            buffers = buffers + data
+        return(buffers)
+
+    def expect(self, text):
+        line = self.readline()
+        if line != text:
+            self.debuglog("while expecting '%s', got unexpected response '%s'" % (text, line))
+        return line
+    
+    def recv(self, rlen):
+        buf = ''
+        recv = self.socket.recv
+        while len(buf) < rlen:
+            buf = buf + recv(rlen - len(buf))
+        return buf
+
+    def __str__(self):
+        d = ''
+        if self.deaduntil:
+            d = " (dead until %d)" % self.deaduntil
+        return "%s:%d%s" % (self.ip, self.port, d)
+
+def _doctest():
+    import doctest, memcache
+    servers = ["127.0.0.1:11211"]
+    mc = Client(servers, debug=1)
+    globs = {"mc": mc}
+    return doctest.testmod(memcache, globs=globs)
+
+if __name__ == "__main__":
+    print "Testing docstrings..."
+    _doctest()
+    print "Running tests:"
+    print
+    #servers = ["127.0.0.1:11211", "127.0.0.1:11212"]
+    servers = ["127.0.0.1:11211"]
+    mc = Client(servers, debug=1)
+
+    def to_s(val):
+        if not isinstance(val, types.StringTypes):
+            return "%s (%s)" % (val, type(val))
+        return "%s" % val
+    def test_setget(key, val):
+        print "Testing set/get {'%s': %s} ..." % (to_s(key), to_s(val)),
+        mc.set(key, val)
+        newval = mc.get(key)
+        if newval == val:
+            print "OK"
+            return 1
+        else:
+            print "FAIL"
+            return 0
+
+    class FooStruct:
+        def __init__(self):
+            self.bar = "baz"
+        def __str__(self):
+            return "A FooStruct"
+        def __eq__(self, other):
+            if isinstance(other, FooStruct):
+                return self.bar == other.bar
+            return 0
+        
+    test_setget("a_string", "some random string")
+    test_setget("an_integer", 42)
+    if test_setget("long", long(1<<30)):
+        print "Testing delete ...",
+        if mc.delete("long"):
+            print "OK"
+        else:
+            print "FAIL"
+    print "Testing get_multi ...",
+    print mc.get_multi(["a_string", "an_integer"])
+
+    print "Testing get(unknown value) ...",
+    print to_s(mc.get("unknown_value"))
+
+    f = FooStruct()
+    test_setget("foostruct", f)
+
+    print "Testing incr ...",
+    x = mc.incr("an_integer", 1)
+    if x == 43:
+        print "OK"
+    else:
+        print "FAIL"
+
+    print "Testing decr ...",
+    x = mc.decr("an_integer", 1)
+    if x == 42:
+        print "OK"
+    else:
+        print "FAIL"
+
+
+
+# vim: ts=4 sw=4 et :

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/statprof.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/statprof.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Utils/statprof.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,304 @@
+## statprof.py
+## Copyright (C) 2004,2005 Andy Wingo <wingo at pobox dot com>
+## Copyright (C) 2001 Rob Browning <rlb at defaultvalue dot org>
+
+## This library is free software; you can redistribute it and/or
+## modify it under the terms of the GNU Lesser General Public
+## License as published by the Free Software Foundation; either
+## version 2.1 of the License, or (at your option) any later version.
+##
+## This library is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public
+## License along with this program; if not, contact:
+##
+## Free Software Foundation           Voice:  +1-617-542-5942
+## 59 Temple Place - Suite 330        Fax:    +1-617-542-2652
+## Boston, MA  02111-1307,  USA       gnu at gnu.org
+
+"""
+statprof is intended to be a fairly simple statistical profiler for
+python. It was ported directly from a statistical profiler for guile,
+also named statprof, available from guile-lib [0].
+
+[0] http://wingolog.org/software/guile-lib/statprof/
+
+To start profiling, call statprof.start():
+>>> start()
+
+Then run whatever it is that you want to profile, for example:
+>>> import test.pystone; test.pystone.pystones()
+
+Then stop the profiling and print out the results:
+>>> stop()
+>>> display()
+  %   cumulative      self          
+ time    seconds   seconds  name    
+ 26.72      1.40      0.37  pystone.py:79:Proc0
+ 13.79      0.56      0.19  pystone.py:133:Proc1
+ 13.79      0.19      0.19  pystone.py:208:Proc8
+ 10.34      0.16      0.14  pystone.py:229:Func2
+  6.90      0.10      0.10  pystone.py:45:__init__
+  4.31      0.16      0.06  pystone.py:53:copy
+    ...
+
+All of the numerical data with the exception of the calls column is
+statistically approximate. In the following column descriptions, and
+in all of statprof, "time" refers to execution time (both user and
+system), not wall clock time.
+
+% time
+    The percent of the time spent inside the procedure itself (not
+    counting children).
+
+cumulative seconds
+    The total number of seconds spent in the procedure, including
+    children.
+
+self seconds
+    The total number of seconds spent in the procedure itself (not
+    counting children).
+
+name
+    The name of the procedure.
+
+By default statprof keeps the data collected from previous runs. If you
+want to clear the collected data, call reset():
+>>> reset()
+
+reset() can also be used to change the sampling frequency. For example,
+to tell statprof to sample 50 times a second:
+>>> reset(50)
+
+This means that statprof will sample the call stack after every 1/50 of
+a second of user + system time spent running on behalf of the python
+process. When your process is idle (for example, blocking in a read(),
+as is the case at the listener), the clock does not advance. For this
+reason statprof is not currently not suitable for profiling io-bound
+operations.
+
+The profiler uses the hash of the code object itself to identify the
+procedures, so it won't confuse different procedures with the same name.
+They will show up as two different rows in the output.
+
+Right now the profiler is quite simplistic.  I cannot provide
+call-graphs or other higher level information.  What you see in the
+table is pretty much all there is. Patches are welcome :-)
+
+
+Threading
+---------
+
+Because signals only get delivered to the main thread in Python,
+statprof only profiles the main thread. However because the time
+reporting function uses per-process timers, the results can be
+significantly off if other threads' work patterns are not similar to the
+main thread's work patterns.
+
+
+Implementation notes
+--------------------
+
+The profiler works by setting the unix profiling signal ITIMER_PROF to
+go off after the interval you define in the call to reset(). When the
+signal fires, a sampling routine is run which looks at the current
+procedure that's executing, and then crawls up the stack, and for each
+frame encountered, increments that frame's code object's sample count.
+Note that if a procedure is encountered multiple times on a given stack,
+it is only counted once. After the sampling is complete, the profiler
+resets profiling timer to fire again after the appropriate interval.
+
+Meanwhile, the profiler keeps track, via os.times(), how much CPU time
+(system and user -- which is also what ITIMER_PROF tracks), has elapsed
+while code has been executing within a start()/stop() block.
+
+The profiler also tries to avoid counting or timing its own code as
+much as possible.
+"""
+
+
+from __future__ import division
+
+try:
+    import itimer
+except ImportError:
+    raise ImportError('''statprof requires the itimer python extension.
+To install it, enter the following commands from a terminal:
+
+wget http://www.cute.fi/~torppa/py-itimer/py-itimer.tar.gz
+tar zxvf py-itimer.tar.gz
+cd py-itimer
+sudo python setup.py install
+''')
+
+import signal
+import os
+
+
+__all__ = ['start', 'stop', 'reset', 'display']
+
+
+###########################################################################
+## Utils
+
+def clock():
+    times = os.times()
+    return times[0] + times[1]
+
+
+###########################################################################
+## Collection data structures
+
+class ProfileState(object):
+    def __init__(self, frequency=None):
+        self.reset(frequency)
+
+    def reset(self, frequency=None):
+        # total so far
+        self.accumulated_time = 0.0
+        # start_time when timer is active
+        self.last_start_time = None
+        # total count of sampler calls
+        self.sample_count = 0
+        # a float
+        if frequency:
+            self.sample_interval = 1.0/frequency
+        elif not hasattr(self, 'sample_interval'):
+            # default to 100 Hz
+            self.sample_interval = 1.0/100.0
+        else:
+            # leave the frequency as it was
+            pass
+        self.remaining_prof_time = None
+        # for user start/stop nesting
+        self.profile_level = 0
+        # whether to catch apply-frame
+        self.count_calls = False
+        # gc time between start() and stop()
+        self.gc_time_taken = 0
+
+    def accumulate_time(self, stop_time):
+        self.accumulated_time += stop_time - self.last_start_time
+
+state = ProfileState()
+
+## call_data := { code object: CallData }
+call_data = {}
+class CallData(object):
+    def __init__(self, code):
+        self.name = code.co_name
+        self.filename = code.co_filename
+        self.lineno = code.co_firstlineno
+        self.call_count = 0
+        self.cum_sample_count = 0
+        self.self_sample_count = 0
+        call_data[code] = self
+
+def get_call_data(code):
+    return call_data.get(code, None) or CallData(code)
+
+
+###########################################################################
+## SIGPROF handler
+
+def sample_stack_procs(frame):
+    state.sample_count += 1
+    get_call_data(frame.f_code).self_sample_count += 1
+
+    code_seen = {}
+    while frame:
+        code_seen[frame.f_code] = True
+        frame = frame.f_back
+    for code in code_seen.iterkeys():
+        get_call_data(code).cum_sample_count += 1
+
+def profile_signal_handler(signum, frame):
+    if state.profile_level > 0:
+        state.accumulate_time(clock())
+        sample_stack_procs(frame)
+        itimer.setitimer(itimer.ITIMER_PROF,
+            state.sample_interval, 0.0)
+        state.last_start_time = clock()
+
+
+###########################################################################
+## Profiling API
+
+def is_active():
+    return state.profile_level > 0
+
+def start():
+    state.profile_level += 1
+    if state.profile_level == 1:
+        state.last_start_time = clock()
+        rpt = state.remaining_prof_time
+        state.remaining_prof_time = None
+        signal.signal(signal.SIGPROF, profile_signal_handler)
+        itimer.setitimer(itimer.ITIMER_PROF,
+            rpt or state.sample_interval, 0.0)
+        state.gc_time_taken = 0 # dunno
+  
+def stop():
+    state.profile_level -= 1
+    if state.profile_level == 0:
+        state.accumulate_time(clock())
+        state.last_start_time = None
+        rpt = itimer.setitimer(itimer.ITIMER_PROF, 0.0, 0.0)
+        signal.signal(signal.SIGPROF, signal.SIG_IGN)
+        state.remaining_prof_time = rpt[0]
+        state.gc_time_taken = 0 # dunno
+    
+def reset(frequency=None):
+    assert state.profile_level == 0, "Can't reset() while statprof is running"
+    call_data.clear()
+    state.reset(frequency)
+    
+
+###########################################################################
+## Reporting API
+
+class CallStats(object):
+    def __init__(self, call_data):
+        self_samples = call_data.self_sample_count
+        cum_samples = call_data.cum_sample_count
+        nsamples = state.sample_count
+        secs_per_sample = state.accumulated_time / nsamples
+        basename = os.path.basename(call_data.filename)
+
+        self.name = '%s:%d:%s' % (basename, call_data.lineno, call_data.name)
+        self.pcnt_time_in_proc = self_samples / nsamples * 100
+        self.cum_secs_in_proc = cum_samples * secs_per_sample
+        self.self_secs_in_proc = self_samples * secs_per_sample
+        self.num_calls = None
+        self.self_secs_per_call = None
+        self.cum_secs_per_call = None
+
+    def display(self):
+        print '%6.2f %9.2f %9.2f  %s' % (self.pcnt_time_in_proc,
+                                         self.cum_secs_in_proc,
+                                         self.self_secs_in_proc,
+                                         self.name)
+
+
+def display():
+    if state.sample_count == 0:
+        print 'No samples recorded.'
+        return
+
+    l = [CallStats(x) for x in call_data.itervalues()]
+    l = [(x.self_secs_in_proc, x.cum_secs_in_proc, x) for x in l]
+    l.sort(reverse=True)
+    l = [x[2] for x in l]
+
+    print '%5.5s %10.10s   %7.7s  %-8.8s' % ('%  ', 'cumulative', 'self', '')
+    print '%5.5s  %9.9s  %8.8s  %-8.8s' % ("time", "seconds", "seconds", "name")
+
+    for x in l:
+        x.display()
+
+    print '---'
+    print 'Sample count: %d' % state.sample_count
+    print 'Total time: %f seconds' % state.accumulated_time

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Version.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Version.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/Version.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,58 @@
+Version = '2.2.1'
+VersionTuple = (2, 2, 1,'final', 0)
+
+MinCompatibleVersion = '2.0rc6'
+MinCompatibleVersionTuple = (2,0,0,'candidate',6)
+
+####
+def convertVersionStringToTuple(s):
+    versionNum = [0,0,0]
+    releaseType = 'final'
+    releaseTypeSubNum = 0
+    if s.find('a')!=-1:
+        num, releaseTypeSubNum = s.split('a')
+        releaseType = 'alpha'
+    elif s.find('b')!=-1:
+        num, releaseTypeSubNum = s.split('b')
+        releaseType = 'beta'
+    elif s.find('rc')!=-1:
+        num, releaseTypeSubNum = s.split('rc')
+        releaseType = 'candidate'
+    else:
+        num = s
+    num = num.split('.')
+    for i in range(len(num)):
+        versionNum[i] = int(num[i])        
+    if len(versionNum)<3:
+        versionNum += [0]
+    releaseTypeSubNum = int(releaseTypeSubNum)
+    
+    return tuple(versionNum+[releaseType,releaseTypeSubNum])
+
+
+if __name__ == '__main__':
+    c = convertVersionStringToTuple
+    print c('2.0a1')
+    print c('2.0b1')
+    print c('2.0rc1')
+    print c('2.0')
+    print c('2.0.2')
+
+
+    assert c('0.9.19b1') < c('0.9.19')
+    assert c('0.9b1') < c('0.9.19')
+    
+    assert c('2.0a2') > c('2.0a1')
+    assert c('2.0b1') > c('2.0a2')
+    assert c('2.0b2') > c('2.0b1')
+    assert c('2.0b2') == c('2.0b2')
+
+    assert c('2.0rc1') > c('2.0b1')
+    assert c('2.0rc2') > c('2.0rc1')
+    assert c('2.0rc2') > c('2.0b1')
+
+    assert c('2.0') > c('2.0a1')
+    assert c('2.0') > c('2.0b1')
+    assert c('2.0') > c('2.0rc1')
+    assert c('2.0.1') > c('2.0')
+    assert c('2.0rc1') > c('2.0b1')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+#!/usr/bin/env python
+
+'''
+Cheetah is an open source template engine and code generation tool.
+
+It can be used standalone or combined with other tools and frameworks. Web
+development is its principle use, but Cheetah is very flexible and is also being
+used to generate C++ game code, Java, sql, form emails and even Python code.
+
+Homepage
+    http://www.cheetahtemplate.org/
+
+Documentation
+    http://cheetahtemplate.org/learn.html
+
+Mailing list
+cheetahtemplate-discuss at lists.sourceforge.net
+Subscribe at 
+    http://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
+'''
+
+from Version import *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+def __bootstrap__():
+   global __bootstrap__, __loader__, __file__
+   import sys, pkg_resources, imp
+   __file__ = pkg_resources.resource_filename(__name__,'_namemapper.so')
+   __loader__ = None; del __bootstrap__, __loader__
+   imp.load_dynamic(__name__,__file__)
+__bootstrap__()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.so
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/_namemapper.so
___________________________________________________________________
Added: svn:executable
   + *
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,603 @@
+"""
+Python Markdown
+===============
+
+Python Markdown converts Markdown to HTML and can be used as a library or
+called from the command line.
+
+## Basic usage as a module:
+
+    import markdown
+    md = Markdown()
+    html = md.convert(your_text_string)
+
+## Basic use from the command line:
+
+    python markdown.py source.txt > destination.html
+
+Run "python markdown.py --help" to see more options.
+
+## Extensions
+
+See <http://www.freewisdom.org/projects/python-markdown/> for more
+information and instructions on how to extend the functionality of
+Python Markdown.  Read that before you try modifying this file.
+
+## Authors and License
+
+Started by [Manfred Stienstra](http://www.dwerg.net/).  Continued and
+maintained  by [Yuri Takhteyev](http://www.freewisdom.org), [Waylan
+Limberg](http://achinghead.com/) and [Artem Yunusov](http://blog.splyer.com).
+
+Contact: markdown at freewisdom.org
+
+Copyright 2007, 2008 The Python Markdown Project (v. 1.7 and later)
+Copyright 200? Django Software Foundation (OrderedDict implementation)
+Copyright 2004, 2005, 2006 Yuri Takhteyev (v. 0.2-1.6b)
+Copyright 2004 Manfred Stienstra (the original version)
+
+License: BSD (see docs/LICENSE for details).
+"""
+
+version = "2.0-rc2"
+version_info = (2,0,0, "rc2")
+
+import re
+import codecs
+import sys
+import warnings
+import logging
+from logging import DEBUG, INFO, WARN, ERROR, CRITICAL
+
+
+"""
+CONSTANTS
+=============================================================================
+"""
+
+"""
+Constants you might want to modify
+-----------------------------------------------------------------------------
+"""
+
+# default logging level for command-line use
+COMMAND_LINE_LOGGING_LEVEL = CRITICAL
+TAB_LENGTH = 4               # expand tabs to this many spaces
+ENABLE_ATTRIBUTES = True     # @id = xyz -> <... id="xyz">
+SMART_EMPHASIS = True        # this_or_that does not become this<i>or</i>that
+DEFAULT_OUTPUT_FORMAT = 'xhtml1'     # xhtml or html4 output
+HTML_REMOVED_TEXT = "[HTML_REMOVED]" # text used instead of HTML in safe mode
+BLOCK_LEVEL_ELEMENTS = re.compile("p|div|h[1-6]|blockquote|pre|table|dl|ol|ul"
+                                  "|script|noscript|form|fieldset|iframe|math"
+                                  "|ins|del|hr|hr/|style|li|dt|dd|thead|tbody"
+                                  "|tr|th|td")
+DOC_TAG = "div"     # Element used to wrap document - later removed
+
+# Placeholders
+STX = u'\u0002'  # Use STX ("Start of text") for start-of-placeholder
+ETX = u'\u0003'  # Use ETX ("End of text") for end-of-placeholder
+INLINE_PLACEHOLDER_PREFIX = STX+"klzzwxh:"
+INLINE_PLACEHOLDER = INLINE_PLACEHOLDER_PREFIX + "%s" + ETX
+AMP_SUBSTITUTE = STX+"amp"+ETX
+
+
+"""
+Constants you probably do not need to change
+-----------------------------------------------------------------------------
+"""
+
+RTL_BIDI_RANGES = ( (u'\u0590', u'\u07FF'),
+                     # Hebrew (0590-05FF), Arabic (0600-06FF),
+                     # Syriac (0700-074F), Arabic supplement (0750-077F),
+                     # Thaana (0780-07BF), Nko (07C0-07FF).
+                    (u'\u2D30', u'\u2D7F'), # Tifinagh
+                    )
+
+
+"""
+AUXILIARY GLOBAL FUNCTIONS
+=============================================================================
+"""
+
+
+def message(level, text):
+    """ A wrapper method for logging debug messages. """
+    logger =  logging.getLogger('MARKDOWN')
+    if logger.handlers:
+        # The logger is configured
+        logger.log(level, text)
+        if level > WARN:
+            sys.exit(0)
+    elif level > WARN:
+        raise MarkdownException, text
+    else:
+        warnings.warn(text, MarkdownWarning)
+
+
+def isBlockLevel(tag):
+    """Check if the tag is a block level HTML tag."""
+    return BLOCK_LEVEL_ELEMENTS.match(tag)
+
+"""
+MISC AUXILIARY CLASSES
+=============================================================================
+"""
+
+class AtomicString(unicode):
+    """A string which should not be further processed."""
+    pass
+
+
+class MarkdownException(Exception):
+    """ A Markdown Exception. """
+    pass
+
+
+class MarkdownWarning(Warning):
+    """ A Markdown Warning. """
+    pass
+
+
+"""
+OVERALL DESIGN
+=============================================================================
+
+Markdown processing takes place in four steps:
+
+1. A bunch of "preprocessors" munge the input text.
+2. BlockParser() parses the high-level structural elements of the
+   pre-processed text into an ElementTree.
+3. A bunch of "treeprocessors" are run against the ElementTree. One such
+   treeprocessor runs InlinePatterns against the ElementTree, detecting inline
+   markup.
+4. Some post-processors are run against the text after the ElementTree has
+   been serialized into text.
+5. The output is written to a string.
+
+Those steps are put together by the Markdown() class.
+
+"""
+
+import preprocessors
+import blockprocessors
+import treeprocessors
+import inlinepatterns
+import postprocessors
+import blockparser
+import etree_loader
+import odict
+
+# Extensions should use "markdown.etree" instead of "etree" (or do `from
+# markdown import etree`).  Do not import it by yourself.
+
+etree = etree_loader.importETree()
+
+# Adds the ability to output html4
+import html4
+
+
+class Markdown:
+    """Convert Markdown to HTML."""
+
+    def __init__(self,
+                 extensions=[],
+                 extension_configs={},
+                 safe_mode = False, 
+                 output_format=DEFAULT_OUTPUT_FORMAT):
+        """
+        Creates a new Markdown instance.
+
+        Keyword arguments:
+
+        * extensions: A list of extensions.
+           If they are of type string, the module mdx_name.py will be loaded.
+           If they are a subclass of markdown.Extension, they will be used
+           as-is.
+        * extension-configs: Configuration setting for extensions.
+        * safe_mode: Disallow raw html. One of "remove", "replace" or "escape".
+        * output_format: Format of output. Supported formats are:
+            * "xhtml1": Outputs XHTML 1.x. Default.
+            * "xhtml": Outputs latest supported version of XHTML (currently XHTML 1.1).
+            * "html4": Outputs HTML 4
+            * "html": Outputs latest supported version of HTML (currently HTML 4).
+            Note that it is suggested that the more specific formats ("xhtml1" 
+            and "html4") be used as "xhtml" or "html" may change in the future
+            if it makes sense at that time. 
+
+        """
+        
+        self.safeMode = safe_mode
+        self.registeredExtensions = []
+        self.docType = ""
+        self.stripTopLevelTags = True
+
+        # Preprocessors
+        self.preprocessors = odict.OrderedDict()
+        self.preprocessors["html_block"] = \
+                preprocessors.HtmlBlockPreprocessor(self)
+        self.preprocessors["reference"] = \
+                preprocessors.ReferencePreprocessor(self)
+        # footnote preprocessor will be inserted with "<reference"
+
+        # Block processors - ran by the parser
+        self.parser = blockparser.BlockParser()
+        self.parser.blockprocessors['empty'] = \
+                blockprocessors.EmptyBlockProcessor(self.parser)
+        self.parser.blockprocessors['indent'] = \
+                blockprocessors.ListIndentProcessor(self.parser)
+        self.parser.blockprocessors['code'] = \
+                blockprocessors.CodeBlockProcessor(self.parser)
+        self.parser.blockprocessors['hashheader'] = \
+                blockprocessors.HashHeaderProcessor(self.parser)
+        self.parser.blockprocessors['setextheader'] = \
+                blockprocessors.SetextHeaderProcessor(self.parser)
+        self.parser.blockprocessors['hr'] = \
+                blockprocessors.HRProcessor(self.parser)
+        self.parser.blockprocessors['olist'] = \
+                blockprocessors.OListProcessor(self.parser)
+        self.parser.blockprocessors['ulist'] = \
+                blockprocessors.UListProcessor(self.parser)
+        self.parser.blockprocessors['quote'] = \
+                blockprocessors.BlockQuoteProcessor(self.parser)
+        self.parser.blockprocessors['paragraph'] = \
+                blockprocessors.ParagraphProcessor(self.parser)
+
+
+        #self.prePatterns = []
+
+        # Inline patterns - Run on the tree
+        self.inlinePatterns = odict.OrderedDict()
+        self.inlinePatterns["backtick"] = \
+                inlinepatterns.BacktickPattern(inlinepatterns.BACKTICK_RE)
+        self.inlinePatterns["escape"] = \
+                inlinepatterns.SimpleTextPattern(inlinepatterns.ESCAPE_RE)
+        self.inlinePatterns["reference"] = \
+            inlinepatterns.ReferencePattern(inlinepatterns.REFERENCE_RE, self)
+        self.inlinePatterns["link"] = \
+                inlinepatterns.LinkPattern(inlinepatterns.LINK_RE, self)
+        self.inlinePatterns["image_link"] = \
+                inlinepatterns.ImagePattern(inlinepatterns.IMAGE_LINK_RE, self)
+        self.inlinePatterns["image_reference"] = \
+            inlinepatterns.ImageReferencePattern(inlinepatterns.IMAGE_REFERENCE_RE, self)
+        self.inlinePatterns["autolink"] = \
+            inlinepatterns.AutolinkPattern(inlinepatterns.AUTOLINK_RE, self)
+        self.inlinePatterns["automail"] = \
+            inlinepatterns.AutomailPattern(inlinepatterns.AUTOMAIL_RE, self)
+        self.inlinePatterns["linebreak2"] = \
+            inlinepatterns.SubstituteTagPattern(inlinepatterns.LINE_BREAK_2_RE, 'br')
+        self.inlinePatterns["linebreak"] = \
+            inlinepatterns.SubstituteTagPattern(inlinepatterns.LINE_BREAK_RE, 'br')
+        self.inlinePatterns["html"] = \
+                inlinepatterns.HtmlPattern(inlinepatterns.HTML_RE, self)
+        self.inlinePatterns["entity"] = \
+                inlinepatterns.HtmlPattern(inlinepatterns.ENTITY_RE, self)
+        self.inlinePatterns["not_strong"] = \
+                inlinepatterns.SimpleTextPattern(inlinepatterns.NOT_STRONG_RE)
+        self.inlinePatterns["strong_em"] = \
+            inlinepatterns.DoubleTagPattern(inlinepatterns.STRONG_EM_RE, 'strong,em')
+        self.inlinePatterns["strong"] = \
+            inlinepatterns.SimpleTagPattern(inlinepatterns.STRONG_RE, 'strong')
+        self.inlinePatterns["emphasis"] = \
+            inlinepatterns.SimpleTagPattern(inlinepatterns.EMPHASIS_RE, 'em')
+        self.inlinePatterns["emphasis2"] = \
+            inlinepatterns.SimpleTagPattern(inlinepatterns.EMPHASIS_2_RE, 'em')
+        # The order of the handlers matters!!!
+
+
+        # Tree processors - run once we have a basic parse.
+        self.treeprocessors = odict.OrderedDict()
+        self.treeprocessors["inline"] = treeprocessors.InlineProcessor(self)
+        self.treeprocessors["prettify"] = \
+                treeprocessors.PrettifyTreeprocessor(self)
+
+        # Postprocessors - finishing touches.
+        self.postprocessors = odict.OrderedDict()
+        self.postprocessors["raw_html"] = \
+                postprocessors.RawHtmlPostprocessor(self)
+        self.postprocessors["amp_substitute"] = \
+                postprocessors.AndSubstitutePostprocessor()
+        # footnote postprocessor will be inserted with ">amp_substitute"
+
+        # Map format keys to serializers
+        self.output_formats = {
+            'html'  : html4.to_html_string, 
+            'html4' : html4.to_html_string,
+            'xhtml' : etree.tostring, 
+            'xhtml1': etree.tostring,
+        }
+
+        self.references = {}
+        self.htmlStash = preprocessors.HtmlStash()
+        self.registerExtensions(extensions = extensions,
+                                configs = extension_configs)
+        self.set_output_format(output_format)
+        self.reset()
+
+    def registerExtensions(self, extensions, configs):
+        """
+        Register extensions with this instance of Markdown.
+
+        Keyword aurguments:
+
+        * extensions: A list of extensions, which can either
+           be strings or objects.  See the docstring on Markdown.
+        * configs: A dictionary mapping module names to config options.
+
+        """
+        for ext in extensions:
+            if isinstance(ext, basestring):
+                ext = load_extension(ext, configs.get(ext, []))
+            try:
+                ext.extendMarkdown(self, globals())
+            except AttributeError:
+                message(ERROR, "Incorrect type! Extension '%s' is "
+                               "neither a string or an Extension." %(repr(ext)))
+            
+
+    def registerExtension(self, extension):
+        """ This gets called by the extension """
+        self.registeredExtensions.append(extension)
+
+    def reset(self):
+        """
+        Resets all state variables so that we can start with a new text.
+        """
+        self.htmlStash.reset()
+        self.references.clear()
+
+        for extension in self.registeredExtensions:
+            extension.reset()
+
+    def set_output_format(self, format):
+        """ Set the output format for the class instance. """
+        try:
+            self.serializer = self.output_formats[format.lower()]
+        except KeyError:
+            message(CRITICAL, 'Invalid Output Format: "%s". Use one of %s.' \
+                               % (format, self.output_formats.keys()))
+
+    def convert(self, source):
+        """
+        Convert markdown to serialized XHTML or HTML.
+
+        Keyword arguments:
+
+        * source: Source text as a Unicode string.
+
+        """
+
+        # Fixup the source text
+        if not source.strip():
+            return u""  # a blank unicode string
+        try:
+            source = unicode(source)
+        except UnicodeDecodeError:
+            message(CRITICAL, 'UnicodeDecodeError: Markdown only accepts unicode or ascii input.')
+            return u""
+
+        source = source.replace(STX, "").replace(ETX, "")
+        source = source.replace("\r\n", "\n").replace("\r", "\n") + "\n\n"
+        source = re.sub(r'\n\s+\n', '\n\n', source)
+        source = source.expandtabs(TAB_LENGTH)
+
+        # Split into lines and run the line preprocessors.
+        self.lines = source.split("\n")
+        for prep in self.preprocessors.values():
+            self.lines = prep.run(self.lines)
+
+        # Parse the high-level elements.
+        root = self.parser.parseDocument(self.lines).getroot()
+
+        # Run the tree-processors
+        for treeprocessor in self.treeprocessors.values():
+            newRoot = treeprocessor.run(root)
+            if newRoot:
+                root = newRoot
+
+        # Serialize _properly_.  Strip top-level tags.
+        output, length = codecs.utf_8_decode(self.serializer(root, encoding="utf8"))
+        if self.stripTopLevelTags:
+            start = output.index('<%s>'%DOC_TAG)+len(DOC_TAG)+2
+            end = output.rindex('</%s>'%DOC_TAG)
+            output = output[start:end].strip()
+
+        # Run the text post-processors
+        for pp in self.postprocessors.values():
+            output = pp.run(output)
+
+        return output.strip()
+
+    def convertFile(self, input=None, output=None, encoding=None):
+        """Converts a markdown file and returns the HTML as a unicode string.
+
+        Decodes the file using the provided encoding (defaults to utf-8),
+        passes the file content to markdown, and outputs the html to either
+        the provided stream or the file with provided name, using the same
+        encoding as the source file.
+
+        **Note:** This is the only place that decoding and encoding of unicode
+        takes place in Python-Markdown.  (All other code is unicode-in /
+        unicode-out.)
+
+        Keyword arguments:
+
+        * input: Name of source text file.
+        * output: Name of output file. Writes to stdout if `None`.
+        * encoding: Encoding of input and output files. Defaults to utf-8.
+
+        """
+
+        encoding = encoding or "utf-8"
+
+        # Read the source
+        input_file = codecs.open(input, mode="r", encoding=encoding)
+        text = input_file.read()
+        input_file.close()
+        text = text.lstrip(u'\ufeff') # remove the byte-order mark
+
+        # Convert
+        html = self.convert(text)
+
+        # Write to file or stdout
+        if isinstance(output, (str, unicode)):
+            output_file = codecs.open(output, "w", encoding=encoding)
+            output_file.write(html)
+            output_file.close()
+        else:
+            output.write(html.encode(encoding))
+
+
+"""
+Extensions
+-----------------------------------------------------------------------------
+"""
+
+class Extension:
+    """ Base class for extensions to subclass. """
+    def __init__(self, configs = {}):
+        """Create an instance of an Extention.
+
+        Keyword arguments:
+
+        * configs: A dict of configuration setting used by an Extension.
+        """
+        self.config = configs
+
+    def getConfig(self, key):
+        """ Return a setting for the given key or an empty string. """
+        if key in self.config:
+            return self.config[key][0]
+        else:
+            return ""
+
+    def getConfigInfo(self):
+        """ Return all config settings as a list of tuples. """
+        return [(key, self.config[key][1]) for key in self.config.keys()]
+
+    def setConfig(self, key, value):
+        """ Set a config setting for `key` with the given `value`. """
+        self.config[key][0] = value
+
+    def extendMarkdown(self, md, md_globals):
+        """
+        Add the various proccesors and patterns to the Markdown Instance.
+
+        This method must be overriden by every extension.
+
+        Keyword arguments:
+
+        * md: The Markdown instance.
+
+        * md_globals: Global variables in the markdown module namespace.
+
+        """
+        pass
+
+
+def load_extension(ext_name, configs = []):
+    """Load extension by name, then return the module.
+
+    The extension name may contain arguments as part of the string in the
+    following format: "extname(key1=value1,key2=value2)"
+
+    """
+
+    # Parse extensions config params (ignore the order)
+    configs = dict(configs)
+    pos = ext_name.find("(") # find the first "("
+    if pos > 0:
+        ext_args = ext_name[pos+1:-1]
+        ext_name = ext_name[:pos]
+        pairs = [x.split("=") for x in ext_args.split(",")]
+        configs.update([(x.strip(), y.strip()) for (x, y) in pairs])
+
+    # Setup the module names
+    ext_module = 'markdown.extensions'
+    module_name_new_style = '.'.join([ext_module, ext_name])
+    module_name_old_style = '_'.join(['mdx', ext_name])
+
+    # Try loading the extention first from one place, then another
+    try: # New style (markdown.extensons.<extension>)
+        module = __import__(module_name_new_style, {}, {}, [ext_module])
+    except ImportError:
+        try: # Old style (mdx.<extension>)
+            module = __import__(module_name_old_style)
+        except ImportError:
+           message(WARN, "Failed loading extension '%s' from '%s' or '%s'"
+               % (ext_name, module_name_new_style, module_name_old_style))
+           # Return None so we don't try to initiate none-existant extension
+           return None
+
+    # If the module is loaded successfully, we expect it to define a
+    # function called makeExtension()
+    try:
+        return module.makeExtension(configs.items())
+    except AttributeError:
+        message(CRITICAL, "Failed to initiate extension '%s'" % ext_name)
+
+
+def load_extensions(ext_names):
+    """Loads multiple extensions"""
+    extensions = []
+    for ext_name in ext_names:
+        extension = load_extension(ext_name)
+        if extension:
+            extensions.append(extension)
+    return extensions
+
+
+"""
+EXPORTED FUNCTIONS
+=============================================================================
+
+Those are the two functions we really mean to export: markdown() and
+markdownFromFile().
+"""
+
+def markdown(text,
+             extensions = [],
+             safe_mode = False,
+             output_format = DEFAULT_OUTPUT_FORMAT):
+    """Convert a markdown string to HTML and return HTML as a unicode string.
+
+    This is a shortcut function for `Markdown` class to cover the most
+    basic use case.  It initializes an instance of Markdown, loads the
+    necessary extensions and runs the parser on the given text.
+
+    Keyword arguments:
+
+    * text: Markdown formatted text as Unicode or ASCII string.
+    * extensions: A list of extensions or extension names (may contain config args).
+    * safe_mode: Disallow raw html.  One of "remove", "replace" or "escape".
+    * output_format: Format of output. Supported formats are:
+        * "xhtml1": Outputs XHTML 1.x. Default.
+        * "xhtml": Outputs latest supported version of XHTML (currently XHTML 1.1).
+        * "html4": Outputs HTML 4
+        * "html": Outputs latest supported version of HTML (currently HTML 4).
+        Note that it is suggested that the more specific formats ("xhtml1" 
+        and "html4") be used as "xhtml" or "html" may change in the future
+        if it makes sense at that time. 
+
+    Returns: An HTML document as a string.
+
+    """
+    md = Markdown(extensions=load_extensions(extensions),
+                  safe_mode=safe_mode, 
+                  output_format=output_format)
+    return md.convert(text)
+
+
+def markdownFromFile(input = None,
+                     output = None,
+                     extensions = [],
+                     encoding = None,
+                     safe_mode = False,
+                     output_format = DEFAULT_OUTPUT_FORMAT):
+    """Read markdown code from a file and write it to a file or a stream."""
+    md = Markdown(extensions=load_extensions(extensions), 
+                  safe_mode=safe_mode,
+                  output_format=output_format)
+    md.convertFile(input, output, encoding)
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockparser.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockparser.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockparser.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,95 @@
+
+import markdown
+
+class State(list):
+    """ Track the current and nested state of the parser. 
+    
+    This utility class is used to track the state of the BlockParser and 
+    support multiple levels if nesting. It's just a simple API wrapped around
+    a list. Each time a state is set, that state is appended to the end of the
+    list. Each time a state is reset, that state is removed from the end of
+    the list.
+
+    Therefore, each time a state is set for a nested block, that state must be 
+    reset when we back out of that level of nesting or the state could be
+    corrupted.
+
+    While all the methods of a list object are available, only the three
+    defined below need be used.
+
+    """
+
+    def set(self, state):
+        """ Set a new state. """
+        self.append(state)
+
+    def reset(self):
+        """ Step back one step in nested state. """
+        self.pop()
+
+    def isstate(self, state):
+        """ Test that top (current) level is of given state. """
+        if len(self):
+            return self[-1] == state
+        else:
+            return False
+
+class BlockParser:
+    """ Parse Markdown blocks into an ElementTree object. 
+    
+    A wrapper class that stitches the various BlockProcessors together,
+    looping through them and creating an ElementTree object.
+    """
+
+    def __init__(self):
+        self.blockprocessors = markdown.odict.OrderedDict()
+        self.state = State()
+
+    def parseDocument(self, lines):
+        """ Parse a markdown document into an ElementTree. 
+        
+        Given a list of lines, an ElementTree object (not just a parent Element)
+        is created and the root element is passed to the parser as the parent.
+        The ElementTree object is returned.
+        
+        This should only be called on an entire document, not pieces.
+
+        """
+        # Create a ElementTree from the lines
+        self.root = markdown.etree.Element(markdown.DOC_TAG)
+        self.parseChunk(self.root, '\n'.join(lines))
+        return markdown.etree.ElementTree(self.root)
+
+    def parseChunk(self, parent, text):
+        """ Parse a chunk of markdown text and attach to given etree node. 
+        
+        While the ``text`` argument is generally assumed to contain multiple
+        blocks which will be split on blank lines, it could contain only one
+        block. Generally, this method would be called by extensions when
+        block parsing is required. 
+        
+        The ``parent`` etree Element passed in is altered in place. 
+        Nothing is returned.
+
+        """
+        self.parseBlocks(parent, text.split('\n\n'))
+
+    def parseBlocks(self, parent, blocks):
+        """ Process blocks of markdown text and attach to given etree node. 
+        
+        Given a list of ``blocks``, each blockprocessor is stepped through
+        until there are no blocks left. While an extension could potentially
+        call this method directly, it's generally expected to be used internally.
+
+        This is a public method as an extension may need to add/alter additional
+        BlockProcessors which call this method to recursively parse a nested
+        block.
+
+        """
+        while blocks:
+           for processor in self.blockprocessors.values():
+               if processor.test(parent, blocks[0]):
+                   processor.run(parent, blocks)
+                   break
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockprocessors.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockprocessors.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/blockprocessors.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,460 @@
+"""
+CORE MARKDOWN BLOCKPARSER
+=============================================================================
+
+This parser handles basic parsing of Markdown blocks.  It doesn't concern itself
+with inline elements such as **bold** or *italics*, but rather just catches 
+blocks, lists, quotes, etc.
+
+The BlockParser is made up of a bunch of BlockProssors, each handling a 
+different type of block. Extensions may add/replace/remove BlockProcessors
+as they need to alter how markdown blocks are parsed.
+
+"""
+
+import re
+import markdown
+
+class BlockProcessor:
+    """ Base class for block processors. 
+    
+    Each subclass will provide the methods below to work with the source and
+    tree. Each processor will need to define it's own ``test`` and ``run``
+    methods. The ``test`` method should return True or False, to indicate
+    whether the current block should be processed by this processor. If the
+    test passes, the parser will call the processors ``run`` method.
+
+    """
+
+    def __init__(self, parser=None):
+        self.parser = parser
+
+    def lastChild(self, parent):
+        """ Return the last child of an etree element. """
+        if len(parent):
+            return parent[-1]
+        else:
+            return None
+
+    def detab(self, text):
+        """ Remove a tab from the front of each line of the given text. """
+        newtext = []
+        lines = text.split('\n')
+        for line in lines:
+            if line.startswith(' '*markdown.TAB_LENGTH):
+                newtext.append(line[markdown.TAB_LENGTH:])
+            elif not line.strip():
+                newtext.append('')
+            else:
+                break
+        return '\n'.join(newtext), '\n'.join(lines[len(newtext):])
+
+    def looseDetab(self, text, level=1):
+        """ Remove a tab from front of lines but allowing dedented lines. """
+        lines = text.split('\n')
+        for i in range(len(lines)):
+            if lines[i].startswith(' '*markdown.TAB_LENGTH*level):
+                lines[i] = lines[i][markdown.TAB_LENGTH*level:]
+        return '\n'.join(lines)
+
+    def test(self, parent, block):
+        """ Test for block type. Must be overridden by subclasses. 
+        
+        As the parser loops through processors, it will call the ``test`` method
+        on each to determine if the given block of text is of that type. This
+        method must return a boolean ``True`` or ``False``. The actual method of
+        testing is left to the needs of that particular block type. It could 
+        be as simple as ``block.startswith(some_string)`` or a complex regular
+        expression. As the block type may be different depending on the parent
+        of the block (i.e. inside a list), the parent etree element is also 
+        provided and may be used as part of the test.
+
+        Keywords:
+        
+        * ``parent``: A etree element which will be the parent of the block.
+        * ``block``: A block of text from the source which has been split at 
+            blank lines.
+        """
+        pass
+
+    def run(self, parent, blocks):
+        """ Run processor. Must be overridden by subclasses. 
+        
+        When the parser determines the appropriate type of a block, the parser
+        will call the corresponding processor's ``run`` method. This method
+        should parse the individual lines of the block and append them to
+        the etree. 
+
+        Note that both the ``parent`` and ``etree`` keywords are pointers
+        to instances of the objects which should be edited in place. Each
+        processor must make changes to the existing objects as there is no
+        mechanism to return new/different objects to replace them.
+
+        This means that this method should be adding SubElements or adding text
+        to the parent, and should remove (``pop``) or add (``insert``) items to
+        the list of blocks.
+
+        Keywords:
+
+        * ``parent``: A etree element which is the parent of the current block.
+        * ``blocks``: A list of all remaining blocks of the document.
+        """
+        pass
+
+
+class ListIndentProcessor(BlockProcessor):
+    """ Process children of list items. 
+    
+    Example:
+        * a list item
+            process this part
+
+            or this part
+
+    """
+
+    INDENT_RE = re.compile(r'^(([ ]{%s})+)'% markdown.TAB_LENGTH)
+    ITEM_TYPES = ['li']
+    LIST_TYPES = ['ul', 'ol']
+
+    def test(self, parent, block):
+        return block.startswith(' '*markdown.TAB_LENGTH) and \
+                not self.parser.state.isstate('detabbed') and  \
+                (parent.tag in self.ITEM_TYPES or \
+                    (len(parent) and parent[-1] and \
+                        (parent[-1].tag in self.LIST_TYPES)
+                    )
+                )
+
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        level, sibling = self.get_level(parent, block)
+        block = self.looseDetab(block, level)
+
+        self.parser.state.set('detabbed')
+        if parent.tag in self.ITEM_TYPES:
+            # The parent is already a li. Just parse the child block.
+            self.parser.parseBlocks(parent, [block])
+        elif sibling.tag in self.ITEM_TYPES:
+            # The sibling is a li. Use it as parent.
+            self.parser.parseBlocks(sibling, [block])
+        elif len(sibling) and sibling[-1].tag in self.ITEM_TYPES:
+            # The parent is a list (``ol`` or ``ul``) which has children.
+            # Assume the last child li is the parent of this block.
+            if sibling[-1].text:
+                # If the parent li has text, that text needs to be moved to a p
+                block = '%s\n\n%s' % (sibling[-1].text, block)
+                sibling[-1].text = ''
+            self.parser.parseChunk(sibling[-1], block)
+        else:
+            self.create_item(sibling, block)
+        self.parser.state.reset()
+
+    def create_item(self, parent, block):
+        """ Create a new li and parse the block with it as the parent. """
+        li = markdown.etree.SubElement(parent, 'li')
+        self.parser.parseBlocks(li, [block])
+ 
+    def get_level(self, parent, block):
+        """ Get level of indent based on list level. """
+        # Get indent level
+        m = self.INDENT_RE.match(block)
+        if m:
+            indent_level = len(m.group(1))/markdown.TAB_LENGTH
+        else:
+            indent_level = 0
+        if self.parser.state.isstate('list'):
+            # We're in a tightlist - so we already are at correct parent.
+            level = 1
+        else:
+            # We're in a looselist - so we need to find parent.
+            level = 0
+        # Step through children of tree to find matching indent level.
+        while indent_level > level:
+            child = self.lastChild(parent)
+            if child and (child.tag in self.LIST_TYPES or child.tag in self.ITEM_TYPES):
+                if child.tag in self.LIST_TYPES:
+                    level += 1
+                parent = child
+            else:
+                # No more child levels. If we're short of indent_level,
+                # we have a code block. So we stop here.
+                break
+        return level, parent
+
+
+class CodeBlockProcessor(BlockProcessor):
+    """ Process code blocks. """
+
+    def test(self, parent, block):
+        return block.startswith(' '*markdown.TAB_LENGTH)
+    
+    def run(self, parent, blocks):
+        sibling = self.lastChild(parent)
+        block = blocks.pop(0)
+        theRest = ''
+        if sibling and sibling.tag == "pre" and len(sibling) \
+                    and sibling[0].tag == "code":
+            # The previous block was a code block. As blank lines do not start
+            # new code blocks, append this block to the previous, adding back
+            # linebreaks removed from the split into a list.
+            code = sibling[0]
+            block, theRest = self.detab(block)
+            code.text = markdown.AtomicString('%s\n%s\n' % (code.text, block.rstrip()))
+        else:
+            # This is a new codeblock. Create the elements and insert text.
+            pre = markdown.etree.SubElement(parent, 'pre')
+            code = markdown.etree.SubElement(pre, 'code')
+            block, theRest = self.detab(block)
+            code.text = markdown.AtomicString('%s\n' % block.rstrip())
+        if theRest:
+            # This block contained unindented line(s) after the first indented 
+            # line. Insert these lines as the first block of the master blocks
+            # list for future processing.
+            blocks.insert(0, theRest)
+
+
+class BlockQuoteProcessor(BlockProcessor):
+
+    RE = re.compile(r'(^|\n)[ ]{0,3}>[ ]?(.*)')
+
+    def test(self, parent, block):
+        return bool(self.RE.search(block))
+
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        m = self.RE.search(block)
+        if m:
+            before = block[:m.start()] # Lines before blockquote
+            # Pass lines before blockquote in recursively for parsing forst.
+            self.parser.parseBlocks(parent, [before])
+            # Remove ``> `` from begining of each line.
+            block = '\n'.join([self.clean(line) for line in 
+                            block[m.start():].split('\n')])
+        sibling = self.lastChild(parent)
+        if sibling and sibling.tag == "blockquote":
+            # Previous block was a blockquote so set that as this blocks parent
+            quote = sibling
+        else:
+            # This is a new blockquote. Create a new parent element.
+            quote = markdown.etree.SubElement(parent, 'blockquote')
+        # Recursively parse block with blockquote as parent.
+        self.parser.parseChunk(quote, block)
+
+    def clean(self, line):
+        """ Remove ``>`` from beginning of a line. """
+        m = self.RE.match(line)
+        if line.strip() == ">":
+            return ""
+        elif m:
+            return m.group(2)
+        else:
+            return line
+
+class OListProcessor(BlockProcessor):
+    """ Process ordered list blocks. """
+
+    TAG = 'ol'
+    # Detect an item (``1. item``). ``group(1)`` contains contents of item.
+    RE = re.compile(r'^[ ]{0,3}\d+\.[ ](.*)')
+    # Detect items on secondary lines. they can be of either list type.
+    CHILD_RE = re.compile(r'^[ ]{0,3}((\d+\.)|[*+-])[ ](.*)')
+    # Detect indented (nested) items of either type
+    INDENT_RE = re.compile(r'^[ ]{4,7}((\d+\.)|[*+-])[ ].*')
+
+    def test(self, parent, block):
+        return bool(self.RE.match(block))
+
+    def run(self, parent, blocks):
+        # Check fr multiple items in one block.
+        items = self.get_items(blocks.pop(0))
+        sibling = self.lastChild(parent)
+        if sibling and sibling.tag in ['ol', 'ul']:
+            # Previous block was a list item, so set that as parent
+            lst = sibling
+            # make sure previous item is in a p.
+            if len(lst) and lst[-1].text and not len(lst[-1]):
+                p = markdown.etree.SubElement(lst[-1], 'p')
+                p.text = lst[-1].text
+                lst[-1].text = ''
+            # parse first block differently as it gets wrapped in a p.
+            li = markdown.etree.SubElement(lst, 'li')
+            self.parser.state.set('looselist')
+            firstitem = items.pop(0)
+            self.parser.parseBlocks(li, [firstitem])
+            self.parser.state.reset()
+        else:
+            # This is a new list so create parent with appropriate tag.
+            lst = markdown.etree.SubElement(parent, self.TAG)
+        self.parser.state.set('list')
+        # Loop through items in block, recursively parsing each with the
+        # appropriate parent.
+        for item in items:
+            if item.startswith(' '*markdown.TAB_LENGTH):
+                # Item is indented. Parse with last item as parent
+                self.parser.parseBlocks(lst[-1], [item])
+            else:
+                # New item. Create li and parse with it as parent
+                li = markdown.etree.SubElement(lst, 'li')
+                self.parser.parseBlocks(li, [item])
+        self.parser.state.reset()
+
+    def get_items(self, block):
+        """ Break a block into list items. """
+        items = []
+        for line in block.split('\n'):
+            m = self.CHILD_RE.match(line)
+            if m:
+                # This is a new item. Append
+                items.append(m.group(3))
+            elif self.INDENT_RE.match(line):
+                # This is an indented (possibly nested) item.
+                if items[-1].startswith(' '*markdown.TAB_LENGTH):
+                    # Previous item was indented. Append to that item.
+                    items[-1] = '%s\n%s' % (items[-1], line)
+                else:
+                    items.append(line)
+            else:
+                # This is another line of previous item. Append to that item.
+                items[-1] = '%s\n%s' % (items[-1], line)
+        return items
+
+
+class UListProcessor(OListProcessor):
+    """ Process unordered list blocks. """
+
+    TAG = 'ul'
+    RE = re.compile(r'^[ ]{0,3}[*+-][ ](.*)')
+
+
+class HashHeaderProcessor(BlockProcessor):
+    """ Process Hash Headers. """
+
+    # Detect a header at start of any line in block
+    RE = re.compile(r'(^|\n)(?P<level>#{1,6})(?P<header>.*?)#*(\n|$)')
+
+    def test(self, parent, block):
+        return bool(self.RE.search(block))
+
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        m = self.RE.search(block)
+        if m:
+            before = block[:m.start()] # All lines before header
+            after = block[m.end():]    # All lines after header
+            if before:
+                # As the header was not the first line of the block and the
+                # lines before the header must be parsed first,
+                # recursively parse this lines as a block.
+                self.parser.parseBlocks(parent, [before])
+            # Create header using named groups from RE
+            h = markdown.etree.SubElement(parent, 'h%d' % len(m.group('level')))
+            h.text = m.group('header').strip()
+            if after:
+                # Insert remaining lines as first block for future parsing.
+                blocks.insert(0, after)
+        else:
+            # This should never happen, but just in case...
+            message(CRITICAL, "We've got a problem header!")
+
+
+class SetextHeaderProcessor(BlockProcessor):
+    """ Process Setext-style Headers. """
+
+    # Detect Setext-style header. Must be first 2 lines of block.
+    RE = re.compile(r'^.*?\n[=-]{3,}', re.MULTILINE)
+
+    def test(self, parent, block):
+        return bool(self.RE.match(block))
+
+    def run(self, parent, blocks):
+        lines = blocks.pop(0).split('\n')
+        # Determine level. ``=`` is 1 and ``-`` is 2.
+        if lines[1].startswith('='):
+            level = 1
+        else:
+            level = 2
+        h = markdown.etree.SubElement(parent, 'h%d' % level)
+        h.text = lines[0].strip()
+        if len(lines) > 2:
+            # Block contains additional lines. Add to  master blocks for later.
+            blocks.insert(0, '\n'.join(lines[2:]))
+
+
+class HRProcessor(BlockProcessor):
+    """ Process Horizontal Rules. """
+
+    RE = r'[ ]{0,3}(?P<ch>[*_-])[ ]?((?P=ch)[ ]?){2,}[ ]*'
+    # Detect hr on any line of a block.
+    SEARCH_RE = re.compile(r'(^|\n)%s(\n|$)' % RE)
+    # Match a hr on a single line of text.
+    MATCH_RE = re.compile(r'^%s$' % RE)
+
+    def test(self, parent, block):
+        return bool(self.SEARCH_RE.search(block))
+
+    def run(self, parent, blocks):
+        lines = blocks.pop(0).split('\n')
+        prelines = []
+        # Check for lines in block before hr.
+        for line in lines:
+            m = self.MATCH_RE.match(line)
+            if m:
+                break
+            else:
+                prelines.append(line)
+        if len(prelines):
+            # Recursively parse lines before hr so they get parsed first.
+            self.parser.parseBlocks(parent, ['\n'.join(prelines)])
+        # create hr
+        hr = markdown.etree.SubElement(parent, 'hr')
+        # check for lines in block after hr.
+        lines = lines[len(prelines)+1:]
+        if len(lines):
+            # Add lines after hr to master blocks for later parsing.
+            blocks.insert(0, '\n'.join(lines))
+
+
+class EmptyBlockProcessor(BlockProcessor):
+    """ Process blocks and start with an empty line. """
+
+    # Detect a block that only contains whitespace 
+    # or only whitespace on the first line.
+    RE = re.compile(r'^\s*\n')
+
+    def test(self, parent, block):
+        return bool(self.RE.match(block))
+
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        m = self.RE.match(block)
+        if m:
+            # Add remaining line to master blocks for later.
+            blocks.insert(0, block[m.end():])
+            sibling = self.lastChild(parent)
+            if sibling and sibling.tag == 'pre' and sibling[0] and \
+                    sibling[0].tag == 'code':
+                # Last block is a codeblock. Append to preserve whitespace.
+                sibling[0].text = markdown.AtomicString('%s/n/n/n' % sibling[0].text )
+
+
+class ParagraphProcessor(BlockProcessor):
+    """ Process Paragraph blocks. """
+
+    def test(self, parent, block):
+        return True
+
+    def run(self, parent, blocks):
+        block = blocks.pop(0)
+        if block.strip():
+            # Not a blank block. Add to parent, otherwise throw it away.
+            if self.parser.state.isstate('list'):
+                # The parent is a tight-list. Append to parent.text
+                if parent.text:
+                    parent.text = '%s\n%s' % (parent.text, block)
+                else:
+                    parent.text = block.lstrip()
+            else:
+                # Create a regular paragraph
+                p = markdown.etree.SubElement(parent, 'p')
+                p.text = block.lstrip()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/commandline.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/commandline.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/commandline.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,96 @@
+"""
+COMMAND-LINE SPECIFIC STUFF
+=============================================================================
+
+The rest of the code is specifically for handling the case where Python
+Markdown is called from the command line.
+"""
+
+import markdown
+import sys
+import logging
+from logging import DEBUG, INFO, WARN, ERROR, CRITICAL
+
+EXECUTABLE_NAME_FOR_USAGE = "python markdown.py"
+""" The name used in the usage statement displayed for python versions < 2.3.
+(With python 2.3 and higher the usage statement is generated by optparse
+and uses the actual name of the executable called.) """
+
+OPTPARSE_WARNING = """
+Python 2.3 or higher required for advanced command line options.
+For lower versions of Python use:
+
+      %s INPUT_FILE > OUTPUT_FILE
+
+""" % EXECUTABLE_NAME_FOR_USAGE
+
+def parse_options():
+    """
+    Define and parse `optparse` options for command-line usage.
+    """
+
+    try:
+        optparse = __import__("optparse")
+    except:
+        if len(sys.argv) == 2:
+            return {'input': sys.argv[1],
+                    'output': None,
+                    'safe': False,
+                    'extensions': [],
+                    'encoding': None }, CRITICAL
+        else:
+            print OPTPARSE_WARNING
+            return None, None
+
+    parser = optparse.OptionParser(usage="%prog INPUTFILE [options]")
+    parser.add_option("-f", "--file", dest="filename", default=sys.stdout,
+                      help="write output to OUTPUT_FILE",
+                      metavar="OUTPUT_FILE")
+    parser.add_option("-e", "--encoding", dest="encoding",
+                      help="encoding for input and output files",)
+    parser.add_option("-q", "--quiet", default = CRITICAL,
+                      action="store_const", const=CRITICAL+10, dest="verbose",
+                      help="suppress all messages")
+    parser.add_option("-v", "--verbose",
+                      action="store_const", const=INFO, dest="verbose",
+                      help="print info messages")
+    parser.add_option("-s", "--safe", dest="safe", default=False,
+                      metavar="SAFE_MODE",
+                      help="safe mode ('replace', 'remove' or 'escape'  user's HTML tag)")
+    parser.add_option("-o", "--output_format", dest="output_format", 
+                      default='xhtml1', metavar="OUTPUT_FORMAT",
+                      help="Format of output. One of 'xhtml1' (default) or 'html4'.")
+    parser.add_option("--noisy",
+                      action="store_const", const=DEBUG, dest="verbose",
+                      help="print debug messages")
+    parser.add_option("-x", "--extension", action="append", dest="extensions",
+                      help = "load extension EXTENSION", metavar="EXTENSION")
+
+    (options, args) = parser.parse_args()
+
+    if not len(args) == 1:
+        parser.print_help()
+        return None, None
+    else:
+        input_file = args[0]
+
+    if not options.extensions:
+        options.extensions = []
+
+    return {'input': input_file,
+            'output': options.filename,
+            'safe_mode': options.safe,
+            'extensions': options.extensions,
+            'encoding': options.encoding,
+            'output_format': options.output_format}, options.verbose
+
+def run():
+    """Run Markdown from the command line."""
+
+    # Parse options and adjust logging level if necessary
+    options, logging_level = parse_options()
+    if not options: sys.exit(0)
+    if logging_level: logging.getLogger('MARKDOWN').setLevel(logging_level)
+
+    # Run
+    markdown.markdownFromFile(**options)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/etree_loader.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/etree_loader.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/etree_loader.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+
+from markdown import message, CRITICAL
+import sys
+
+## Import
+def importETree():
+    """Import the best implementation of ElementTree, return a module object."""
+    etree_in_c = None
+    try: # Is it Python 2.5+ with C implemenation of ElementTree installed?
+        import xml.etree.cElementTree as etree_in_c
+    except ImportError:
+        try: # Is it Python 2.5+ with Python implementation of ElementTree?
+            import xml.etree.ElementTree as etree
+        except ImportError:
+            try: # An earlier version of Python with cElementTree installed?
+                import cElementTree as etree_in_c
+            except ImportError:
+                try: # An earlier version of Python with Python ElementTree?
+                    import elementtree.ElementTree as etree
+                except ImportError:
+                    message(CRITICAL, "Failed to import ElementTree")
+                    sys.exit(1)
+    if etree_in_c and etree_in_c.VERSION < "1.0":
+        message(CRITICAL, "For cElementTree version 1.0 or higher is required.")
+        sys.exit(1)
+    elif etree_in_c :
+        return etree_in_c
+    elif etree.VERSION < "1.1":
+        message(CRITICAL, "For ElementTree version 1.1 or higher is required")
+        sys.exit(1)
+    else :
+        return etree
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/html4.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/html4.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/html4.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,274 @@
+# markdown/html4.py
+#
+# Add html4 serialization to older versions of Elementree
+# Taken from ElementTree 1.3 preview with slight modifications
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh.  All rights reserved.
+#
+# fredrik at pythonware.com
+# http://www.pythonware.com
+#
+# --------------------------------------------------------------------
+# The ElementTree toolkit is
+#
+# Copyright (c) 1999-2007 by Fredrik Lundh
+#
+# By obtaining, using, and/or copying this software and/or its
+# associated documentation, you agree that you have read, understood,
+# and will comply with the following terms and conditions:
+#
+# Permission to use, copy, modify, and distribute this software and
+# its associated documentation for any purpose and without fee is
+# hereby granted, provided that the above copyright notice appears in
+# all copies, and that both that copyright notice and this permission
+# notice appear in supporting documentation, and that the name of
+# Secret Labs AB or the author not be used in advertising or publicity
+# pertaining to distribution of the software without specific, written
+# prior permission.
+#
+# SECRET LABS AB AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD
+# TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT-
+# ABILITY AND FITNESS.  IN NO EVENT SHALL SECRET LABS AB OR THE AUTHOR
+# BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+# --------------------------------------------------------------------
+
+
+import markdown
+ElementTree = markdown.etree.ElementTree
+QName = markdown.etree.QName
+Comment = markdown.etree.Comment
+PI = markdown.etree.PI
+ProcessingInstruction = markdown.etree.ProcessingInstruction
+
+HTML_EMPTY = ("area", "base", "basefont", "br", "col", "frame", "hr",
+              "img", "input", "isindex", "link", "meta" "param")
+
+try:
+    HTML_EMPTY = set(HTML_EMPTY)
+except NameError:
+    pass
+
+_namespace_map = {
+    # "well-known" namespace prefixes
+    "http://www.w3.org/XML/1998/namespace": "xml",
+    "http://www.w3.org/1999/xhtml": "html",
+    "http://www.w3.org/1999/02/22-rdf-syntax-ns#": "rdf",
+    "http://schemas.xmlsoap.org/wsdl/": "wsdl",
+    # xml schema
+    "http://www.w3.org/2001/XMLSchema": "xs",
+    "http://www.w3.org/2001/XMLSchema-instance": "xsi",
+    # dublic core
+    "http://purl.org/dc/elements/1.1/": "dc",
+}
+
+
+def _raise_serialization_error(text):
+    raise TypeError(
+        "cannot serialize %r (type %s)" % (text, type(text).__name__)
+        )
+
+def _encode(text, encoding):
+    try:
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_cdata(text, encoding):
+    # escape character data
+    try:
+        # it's worth avoiding do-nothing calls for strings that are
+        # shorter than 500 character, or so.  assume that's, by far,
+        # the most common case in most applications.
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+
+def _escape_attrib(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if "<" in text:
+            text = text.replace("<", "&lt;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        if "\n" in text:
+            text = text.replace("\n", "&#10;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+def _escape_attrib_html(text, encoding):
+    # escape attribute value
+    try:
+        if "&" in text:
+            text = text.replace("&", "&amp;")
+        if ">" in text:
+            text = text.replace(">", "&gt;")
+        if "\"" in text:
+            text = text.replace("\"", "&quot;")
+        return text.encode(encoding, "xmlcharrefreplace")
+    except (TypeError, AttributeError):
+        _raise_serialization_error(text)
+
+
+def _serialize_html(write, elem, encoding, qnames, namespaces):
+    tag = elem.tag
+    text = elem.text
+    if tag is Comment:
+        write("<!--%s-->" % _escape_cdata(text, encoding))
+    elif tag is ProcessingInstruction:
+        write("<?%s?>" % _escape_cdata(text, encoding))
+    else:
+        tag = qnames[tag]
+        if tag is None:
+            if text:
+                write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+        else:
+            write("<" + tag)
+            items = elem.items()
+            if items or namespaces:
+                items.sort() # lexical order
+                for k, v in items:
+                    if isinstance(k, QName):
+                        k = k.text
+                    if isinstance(v, QName):
+                        v = qnames[v.text]
+                    else:
+                        v = _escape_attrib_html(v, encoding)
+                    # FIXME: handle boolean attributes
+                    write(" %s=\"%s\"" % (qnames[k], v))
+                if namespaces:
+                    items = namespaces.items()
+                    items.sort(key=lambda x: x[1]) # sort on prefix
+                    for v, k in items:
+                        if k:
+                            k = ":" + k
+                        write(" xmlns%s=\"%s\"" % (
+                            k.encode(encoding),
+                            _escape_attrib(v, encoding)
+                            ))
+            write(">")
+            tag = tag.lower()
+            if text:
+                if tag == "script" or tag == "style":
+                    write(_encode(text, encoding))
+                else:
+                    write(_escape_cdata(text, encoding))
+            for e in elem:
+                _serialize_html(write, e, encoding, qnames, None)
+            if tag not in HTML_EMPTY:
+                write("</" + tag + ">")
+    if elem.tail:
+        write(_escape_cdata(elem.tail, encoding))
+
+def write_html(root, f,
+          # keyword arguments
+          encoding="us-ascii",
+          default_namespace=None):
+    assert root is not None
+    if not hasattr(f, "write"):
+        f = open(f, "wb")
+    write = f.write
+    if not encoding:
+        encoding = "us-ascii"
+    qnames, namespaces = _namespaces(
+            root, encoding, default_namespace
+            )
+    _serialize_html(
+                write, root, encoding, qnames, namespaces
+                )
+
+# --------------------------------------------------------------------
+# serialization support
+
+def _namespaces(elem, encoding, default_namespace=None):
+    # identify namespaces used in this tree
+
+    # maps qnames to *encoded* prefix:local names
+    qnames = {None: None}
+
+    # maps uri:s to prefixes
+    namespaces = {}
+    if default_namespace:
+        namespaces[default_namespace] = ""
+
+    def encode(text):
+        return text.encode(encoding)
+
+    def add_qname(qname):
+        # calculate serialized qname representation
+        try:
+            if qname[:1] == "{":
+                uri, tag = qname[1:].split("}", 1)
+                prefix = namespaces.get(uri)
+                if prefix is None:
+                    prefix = _namespace_map.get(uri)
+                    if prefix is None:
+                        prefix = "ns%d" % len(namespaces)
+                    if prefix != "xml":
+                        namespaces[uri] = prefix
+                if prefix:
+                    qnames[qname] = encode("%s:%s" % (prefix, tag))
+                else:
+                    qnames[qname] = encode(tag) # default element
+            else:
+                if default_namespace:
+                    # FIXME: can this be handled in XML 1.0?
+                    raise ValueError(
+                        "cannot use non-qualified names with "
+                        "default_namespace option"
+                        )
+                qnames[qname] = encode(qname)
+        except TypeError:
+            _raise_serialization_error(qname)
+
+    # populate qname and namespaces table
+    try:
+        iterate = elem.iter
+    except AttributeError:
+        iterate = elem.getiterator # cET compatibility
+    for elem in iterate():
+        tag = elem.tag
+        if isinstance(tag, QName) and tag.text not in qnames:
+            add_qname(tag.text)
+        elif isinstance(tag, basestring):
+            if tag not in qnames:
+                add_qname(tag)
+        elif tag is not None and tag is not Comment and tag is not PI:
+            _raise_serialization_error(tag)
+        for key, value in elem.items():
+            if isinstance(key, QName):
+                key = key.text
+            if key not in qnames:
+                add_qname(key)
+            if isinstance(value, QName) and value.text not in qnames:
+                add_qname(value.text)
+        text = elem.text
+        if isinstance(text, QName) and text.text not in qnames:
+            add_qname(text.text)
+    return qnames, namespaces
+
+def to_html_string(element, encoding=None):
+    class dummy:
+        pass
+    data = []
+    file = dummy()
+    file.write = data.append
+    write_html(ElementTree(element).getroot(),file,encoding)
+    return "".join(data)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/inlinepatterns.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/inlinepatterns.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/inlinepatterns.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,371 @@
+"""
+INLINE PATTERNS
+=============================================================================
+
+Inline patterns such as *emphasis* are handled by means of auxiliary
+objects, one per pattern.  Pattern objects must be instances of classes
+that extend markdown.Pattern.  Each pattern object uses a single regular
+expression and needs support the following methods:
+
+    pattern.getCompiledRegExp() # returns a regular expression
+
+    pattern.handleMatch(m) # takes a match object and returns
+                           # an ElementTree element or just plain text
+
+All of python markdown's built-in patterns subclass from Pattern,
+but you can add additional patterns that don't.
+
+Also note that all the regular expressions used by inline must
+capture the whole block.  For this reason, they all start with
+'^(.*)' and end with '(.*)!'.  In case with built-in expression
+Pattern takes care of adding the "^(.*)" and "(.*)!".
+
+Finally, the order in which regular expressions are applied is very
+important - e.g. if we first replace http://.../ links with <a> tags
+and _then_ try to replace inline html, we would end up with a mess.
+So, we apply the expressions in the following order:
+
+* escape and backticks have to go before everything else, so
+  that we can preempt any markdown patterns by escaping them.
+
+* then we handle auto-links (must be done before inline html)
+
+* then we handle inline HTML.  At this point we will simply
+  replace all inline HTML strings with a placeholder and add
+  the actual HTML to a hash.
+
+* then inline images (must be done before links)
+
+* then bracketed links, first regular then reference-style
+
+* finally we apply strong and emphasis
+"""
+
+import markdown
+import re
+from urlparse import urlparse, urlunparse
+import sys
+if sys.version >= "3.0":
+    from html import entities as htmlentitydefs
+else:
+    import htmlentitydefs
+
+"""
+The actual regular expressions for patterns
+-----------------------------------------------------------------------------
+"""
+
+NOBRACKET = r'[^\]\[]*'
+BRK = ( r'\[('
+        + (NOBRACKET + r'(\[')*6
+        + (NOBRACKET+ r'\])*')*6
+        + NOBRACKET + r')\]' )
+NOIMG = r'(?<!\!)'
+
+BACKTICK_RE = r'(?<!\\)(`+)(.+?)(?<!`)\2(?!`)' # `e=f()` or ``e=f("`")``
+ESCAPE_RE = r'\\(.)'                             # \<
+EMPHASIS_RE = r'(\*)([^\*]*)\2'                    # *emphasis*
+STRONG_RE = r'(\*{2}|_{2})(.*?)\2'                      # **strong**
+STRONG_EM_RE = r'(\*{3}|_{3})(.*?)\2'            # ***strong***
+
+if markdown.SMART_EMPHASIS:
+    EMPHASIS_2_RE = r'(?<!\S)(_)(\S.*?)\2'        # _emphasis_
+else:
+    EMPHASIS_2_RE = r'(_)(.*?)\2'                 # _emphasis_
+
+LINK_RE = NOIMG + BRK + \
+r'''\(\s*(<.*?>|((?:(?:\(.*?\))|[^\(\)]))*?)\s*((['"])(.*)\12)?\)'''
+# [text](url) or [text](<url>)
+
+IMAGE_LINK_RE = r'\!' + BRK + r'\s*\((<.*?>|([^\)]*))\)'
+# ![alttxt](http://x.com/) or ![alttxt](<http://x.com/>)
+REFERENCE_RE = NOIMG + BRK+ r'\s*\[([^\]]*)\]'           # [Google][3]
+IMAGE_REFERENCE_RE = r'\!' + BRK + '\s*\[([^\]]*)\]' # ![alt text][2]
+NOT_STRONG_RE = r'( \* )'                        # stand-alone * or _
+AUTOLINK_RE = r'<((?:f|ht)tps?://[^>]*)>'        # <http://www.123.com>
+AUTOMAIL_RE = r'<([^> \!]*@[^> ]*)>'               # <me at example.com>
+
+HTML_RE = r'(\<([a-zA-Z/][^\>]*?|\!--.*?--)\>)'               # <...>
+ENTITY_RE = r'(&[\#a-zA-Z0-9]*;)'               # &amp;
+LINE_BREAK_RE = r'  \n'                     # two spaces at end of line
+LINE_BREAK_2_RE = r'  $'                    # two spaces at end of text
+
+
+def dequote(string):
+    """Remove quotes from around a string."""
+    if ( ( string.startswith('"') and string.endswith('"'))
+         or (string.startswith("'") and string.endswith("'")) ):
+        return string[1:-1]
+    else:
+        return string
+
+ATTR_RE = re.compile("\{@([^\}]*)=([^\}]*)}") # {@id=123}
+
+def handleAttributes(text, parent):
+    """Set values of an element based on attribute definitions ({@id=123})."""
+    def attributeCallback(match):
+        parent.set(match.group(1), match.group(2).replace('\n', ' '))
+    return ATTR_RE.sub(attributeCallback, text)
+
+
+"""
+The pattern classes
+-----------------------------------------------------------------------------
+"""
+
+class Pattern:
+    """Base class that inline patterns subclass. """
+
+    def __init__ (self, pattern, markdown_instance=None):
+        """
+        Create an instant of an inline pattern.
+
+        Keyword arguments:
+
+        * pattern: A regular expression that matches a pattern
+
+        """
+        self.pattern = pattern
+        self.compiled_re = re.compile("^(.*?)%s(.*?)$" % pattern, re.DOTALL)
+
+        # Api for Markdown to pass safe_mode into instance
+        self.safe_mode = False
+        if markdown_instance:
+            self.markdown = markdown_instance
+
+    def getCompiledRegExp (self):
+        """ Return a compiled regular expression. """
+        return self.compiled_re
+
+    def handleMatch(self, m):
+        """Return a ElementTree element from the given match.
+
+        Subclasses should override this method.
+
+        Keyword arguments:
+
+        * m: A re match object containing a match of the pattern.
+
+        """
+        pass
+
+    def type(self):
+        """ Return class name, to define pattern type """
+        return self.__class__.__name__
+
+BasePattern = Pattern # for backward compatibility
+
+class SimpleTextPattern (Pattern):
+    """ Return a simple text of group(2) of a Pattern. """
+    def handleMatch(self, m):
+        text = m.group(2)
+        if text == markdown.INLINE_PLACEHOLDER_PREFIX:
+            return None
+        return text
+
+class SimpleTagPattern (Pattern):
+    """
+    Return element of type `tag` with a text attribute of group(3)
+    of a Pattern.
+
+    """
+    def __init__ (self, pattern, tag):
+        Pattern.__init__(self, pattern)
+        self.tag = tag
+
+    def handleMatch(self, m):
+        el = markdown.etree.Element(self.tag)
+        el.text = m.group(3)
+        return el
+
+
+class SubstituteTagPattern (SimpleTagPattern):
+    """ Return a eLement of type `tag` with no children. """
+    def handleMatch (self, m):
+        return markdown.etree.Element(self.tag)
+
+
+class BacktickPattern (Pattern):
+    """ Return a `<code>` element containing the matching text. """
+    def __init__ (self, pattern):
+        Pattern.__init__(self, pattern)
+        self.tag = "code"
+
+    def handleMatch(self, m):
+        el = markdown.etree.Element(self.tag)
+        el.text = markdown.AtomicString(m.group(3).strip())
+        return el
+
+
+class DoubleTagPattern (SimpleTagPattern):
+    """Return a ElementTree element nested in tag2 nested in tag1.
+
+    Useful for strong emphasis etc.
+
+    """
+    def handleMatch(self, m):
+        tag1, tag2 = self.tag.split(",")
+        el1 = markdown.etree.Element(tag1)
+        el2 = markdown.etree.SubElement(el1, tag2)
+        el2.text = m.group(3)
+        return el1
+
+
+class HtmlPattern (Pattern):
+    """ Store raw inline html and return a placeholder. """
+    def handleMatch (self, m):
+        rawhtml = m.group(2)
+        inline = True
+        place_holder = self.markdown.htmlStash.store(rawhtml)
+        return place_holder
+
+
+class LinkPattern (Pattern):
+    """ Return a link element from the given match. """
+    def handleMatch(self, m):
+        el = markdown.etree.Element("a")
+        el.text = m.group(2)
+        title = m.group(11)
+        href = m.group(9)
+
+        if href:
+            if href[0] == "<":
+                href = href[1:-1]
+            el.set("href", self.sanitize_url(href.strip()))
+        else:
+            el.set("href", "")
+
+        if title:
+            title = dequote(title) #.replace('"', "&quot;")
+            el.set("title", title)
+        return el
+
+    def sanitize_url(self, url):
+        """
+        Sanitize a url against xss attacks in "safe_mode".
+
+        Rather than specifically blacklisting `javascript:alert("XSS")` and all
+        its aliases (see <http://ha.ckers.org/xss.html>), we whitelist known
+        safe url formats. Most urls contain a network location, however some
+        are known not to (i.e.: mailto links). Script urls do not contain a
+        location. Additionally, for `javascript:...`, the scheme would be
+        "javascript" but some aliases will appear to `urlparse()` to have no
+        scheme. On top of that relative links (i.e.: "foo/bar.html") have no
+        scheme. Therefore we must check "path", "parameters", "query" and
+        "fragment" for any literal colons. We don't check "scheme" for colons
+        because it *should* never have any and "netloc" must allow the form:
+        `username:password at host:port`.
+
+        """
+        locless_schemes = ['', 'mailto', 'news']
+        scheme, netloc, path, params, query, fragment = url = urlparse(url)
+        safe_url = False
+        if netloc != '' or scheme in locless_schemes:
+            safe_url = True
+
+        for part in url[2:]:
+            if ":" in part:
+                safe_url = False
+
+        if self.markdown.safeMode and not safe_url:
+            return ''
+        else:
+            return urlunparse(url)
+
+class ImagePattern(LinkPattern):
+    """ Return a img element from the given match. """
+    def handleMatch(self, m):
+        el = markdown.etree.Element("img")
+        src_parts = m.group(9).split()
+        if src_parts:
+            src = src_parts[0]
+            if src[0] == "<" and src[-1] == ">":
+                src = src[1:-1]
+            el.set('src', self.sanitize_url(src))
+        else:
+            el.set('src', "")
+        if len(src_parts) > 1:
+            el.set('title', dequote(" ".join(src_parts[1:])))
+
+        if markdown.ENABLE_ATTRIBUTES:
+            truealt = handleAttributes(m.group(2), el)
+        else:
+            truealt = m.group(2)
+
+        el.set('alt', truealt)
+        return el
+
+class ReferencePattern(LinkPattern):
+    """ Match to a stored reference and return link element. """
+    def handleMatch(self, m):
+        if m.group(9):
+            id = m.group(9).lower()
+        else:
+            # if we got something like "[Google][]"
+            # we'll use "google" as the id
+            id = m.group(2).lower()
+
+        if not id in self.markdown.references: # ignore undefined refs
+            return None
+        href, title = self.markdown.references[id]
+
+        text = m.group(2)
+        return self.makeTag(href, title, text)
+
+    def makeTag(self, href, title, text):
+        el = markdown.etree.Element('a')
+
+        el.set('href', self.sanitize_url(href))
+        if title:
+            el.set('title', title)
+
+        el.text = text
+        return el
+
+
+class ImageReferencePattern (ReferencePattern):
+    """ Match to a stored reference and return img element. """
+    def makeTag(self, href, title, text):
+        el = markdown.etree.Element("img")
+        el.set("src", self.sanitize_url(href))
+        if title:
+            el.set("title", title)
+        el.set("alt", text)
+        return el
+
+
+class AutolinkPattern (Pattern):
+    """ Return a link Element given an autolink (`<http://example/com>`). """
+    def handleMatch(self, m):
+        el = markdown.etree.Element("a")
+        el.set('href', m.group(2))
+        el.text = markdown.AtomicString(m.group(2))
+        return el
+
+class AutomailPattern (Pattern):
+    """
+    Return a mailto link Element given an automail link (`<foo at example.com>`).
+    """
+    def handleMatch(self, m):
+        el = markdown.etree.Element('a')
+        email = m.group(2)
+        if email.startswith("mailto:"):
+            email = email[len("mailto:"):]
+
+        def codepoint2name(code):
+            """Return entity definition by code, or the code if not defined."""
+            entity = htmlentitydefs.codepoint2name.get(code)
+            if entity:
+                return "%s%s;" % (markdown.AMP_SUBSTITUTE, entity)
+            else:
+                return "%s#%d;" % (markdown.AMP_SUBSTITUTE, code)
+
+        letters = [codepoint2name(ord(letter)) for letter in email]
+        el.text = markdown.AtomicString(''.join(letters))
+
+        mailto = "mailto:" + email
+        mailto = "".join([markdown.AMP_SUBSTITUTE + '#%d;' %
+                          ord(letter) for letter in mailto])
+        el.set('href', mailto)
+        return el
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/odict.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/odict.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/odict.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,162 @@
+class OrderedDict(dict):
+    """
+    A dictionary that keeps its keys in the order in which they're inserted.
+    
+    Copied from Django's SortedDict with some modifications.
+
+    """
+    def __new__(cls, *args, **kwargs):
+        instance = super(OrderedDict, cls).__new__(cls, *args, **kwargs)
+        instance.keyOrder = []
+        return instance
+
+    def __init__(self, data=None):
+        if data is None:
+            data = {}
+        super(OrderedDict, self).__init__(data)
+        if isinstance(data, dict):
+            self.keyOrder = data.keys()
+        else:
+            self.keyOrder = []
+            for key, value in data:
+                if key not in self.keyOrder:
+                    self.keyOrder.append(key)
+
+    def __deepcopy__(self, memo):
+        from copy import deepcopy
+        return self.__class__([(key, deepcopy(value, memo))
+                               for key, value in self.iteritems()])
+
+    def __setitem__(self, key, value):
+        super(OrderedDict, self).__setitem__(key, value)
+        if key not in self.keyOrder:
+            self.keyOrder.append(key)
+
+    def __delitem__(self, key):
+        super(OrderedDict, self).__delitem__(key)
+        self.keyOrder.remove(key)
+
+    def __iter__(self):
+        for k in self.keyOrder:
+            yield k
+
+    def pop(self, k, *args):
+        result = super(OrderedDict, self).pop(k, *args)
+        try:
+            self.keyOrder.remove(k)
+        except ValueError:
+            # Key wasn't in the dictionary in the first place. No problem.
+            pass
+        return result
+
+    def popitem(self):
+        result = super(OrderedDict, self).popitem()
+        self.keyOrder.remove(result[0])
+        return result
+
+    def items(self):
+        return zip(self.keyOrder, self.values())
+
+    def iteritems(self):
+        for key in self.keyOrder:
+            yield key, super(OrderedDict, self).__getitem__(key)
+
+    def keys(self):
+        return self.keyOrder[:]
+
+    def iterkeys(self):
+        return iter(self.keyOrder)
+
+    def values(self):
+        return [super(OrderedDict, self).__getitem__(k) for k in self.keyOrder]
+
+    def itervalues(self):
+        for key in self.keyOrder:
+            yield super(OrderedDict, self).__getitem__(key)
+
+    def update(self, dict_):
+        for k, v in dict_.items():
+            self.__setitem__(k, v)
+
+    def setdefault(self, key, default):
+        if key not in self.keyOrder:
+            self.keyOrder.append(key)
+        return super(OrderedDict, self).setdefault(key, default)
+
+    def value_for_index(self, index):
+        """Return the value of the item at the given zero-based index."""
+        return self[self.keyOrder[index]]
+
+    def insert(self, index, key, value):
+        """Insert the key, value pair before the item with the given index."""
+        if key in self.keyOrder:
+            n = self.keyOrder.index(key)
+            del self.keyOrder[n]
+            if n < index:
+                index -= 1
+        self.keyOrder.insert(index, key)
+        super(OrderedDict, self).__setitem__(key, value)
+
+    def copy(self):
+        """Return a copy of this object."""
+        # This way of initializing the copy means it works for subclasses, too.
+        obj = self.__class__(self)
+        obj.keyOrder = self.keyOrder[:]
+        return obj
+
+    def __repr__(self):
+        """
+        Replace the normal dict.__repr__ with a version that returns the keys
+        in their sorted order.
+        """
+        return '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()])
+
+    def clear(self):
+        super(OrderedDict, self).clear()
+        self.keyOrder = []
+
+    def index(self, key):
+        """ Return the index of a given key. """
+        return self.keyOrder.index(key)
+
+    def index_for_location(self, location):
+        """ Return index or None for a given location. """
+        if location == '_begin':
+            i = 0
+        elif location == '_end':
+            i = None
+        elif location.startswith('<') or location.startswith('>'):
+            i = self.index(location[1:])
+            if location.startswith('>'):
+                if i >= len(self):
+                    # last item
+                    i = None
+                else:
+                    i += 1
+        else:
+            raise ValueError('Not a valid location: "%s". Location key '
+                             'must start with a ">" or "<".' % location)
+        return i
+
+    def add(self, key, value, location):
+        """ Insert by key location. """
+        i = self.index_for_location(location)
+        if i is not None:
+            self.insert(i, key, value)
+        else:
+            self.__setitem__(key, value)
+
+    def link(self, key, location):
+        """ Change location of an existing item. """
+        n = self.keyOrder.index(key)
+        del self.keyOrder[n]
+        i = self.index_for_location(location)
+        try:
+            if i is not None:
+                self.keyOrder.insert(i, key)
+            else:
+                self.keyOrder.append(key)
+        except Error:
+            # restore to prevent data loss and reraise
+            self.keyOrder.insert(n, key)
+            raise Error

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/postprocessors.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/postprocessors.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/postprocessors.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,77 @@
+"""
+POST-PROCESSORS
+=============================================================================
+
+Markdown also allows post-processors, which are similar to preprocessors in
+that they need to implement a "run" method. However, they are run after core
+processing.
+
+"""
+
+
+import markdown
+
+class Processor:
+    def __init__(self, markdown_instance=None):
+        if markdown_instance:
+            self.markdown = markdown_instance
+
+class Postprocessor(Processor):
+    """
+    Postprocessors are run after the ElementTree it converted back into text.
+
+    Each Postprocessor implements a "run" method that takes a pointer to a
+    text string, modifies it as necessary and returns a text string.
+
+    Postprocessors must extend markdown.Postprocessor.
+
+    """
+
+    def run(self, text):
+        """
+        Subclasses of Postprocessor should implement a `run` method, which
+        takes the html document as a single text string and returns a
+        (possibly modified) string.
+
+        """
+        pass
+
+
+class RawHtmlPostprocessor(Postprocessor):
+    """ Restore raw html to the document. """
+
+    def run(self, text):
+        """ Iterate over html stash and restore "safe" html. """
+        for i in range(self.markdown.htmlStash.html_counter):
+            html, safe  = self.markdown.htmlStash.rawHtmlBlocks[i]
+            if self.markdown.safeMode and not safe:
+                if str(self.markdown.safeMode).lower() == 'escape':
+                    html = self.escape(html)
+                elif str(self.markdown.safeMode).lower() == 'remove':
+                    html = ''
+                else:
+                    html = markdown.HTML_REMOVED_TEXT
+            if safe or not self.markdown.safeMode:
+                text = text.replace("<p>%s</p>" % 
+                            (markdown.preprocessors.HTML_PLACEHOLDER % i),
+                            html + "\n")
+            text =  text.replace(markdown.preprocessors.HTML_PLACEHOLDER % i, 
+                                 html)
+        return text
+
+    def escape(self, html):
+        """ Basic html escaping """
+        html = html.replace('&', '&amp;')
+        html = html.replace('<', '&lt;')
+        html = html.replace('>', '&gt;')
+        return html.replace('"', '&quot;')
+
+
+class AndSubstitutePostprocessor(Postprocessor):
+    """ Restore valid entities """
+    def __init__(self):
+        pass
+
+    def run(self, text):
+        text =  text.replace(markdown.AMP_SUBSTITUTE, "&")
+        return text

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/preprocessors.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/preprocessors.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/preprocessors.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,214 @@
+
+"""
+PRE-PROCESSORS
+=============================================================================
+
+Preprocessors work on source text before we start doing anything too
+complicated. 
+"""
+
+import re
+import markdown
+
+HTML_PLACEHOLDER_PREFIX = markdown.STX+"wzxhzdk:"
+HTML_PLACEHOLDER = HTML_PLACEHOLDER_PREFIX + "%d" + markdown.ETX
+
+class Processor:
+    def __init__(self, markdown_instance=None):
+        if markdown_instance:
+            self.markdown = markdown_instance
+
+class Preprocessor (Processor):
+    """
+    Preprocessors are run after the text is broken into lines.
+
+    Each preprocessor implements a "run" method that takes a pointer to a
+    list of lines of the document, modifies it as necessary and returns
+    either the same pointer or a pointer to a new list.
+
+    Preprocessors must extend markdown.Preprocessor.
+
+    """
+    def run(self, lines):
+        """
+        Each subclass of Preprocessor should override the `run` method, which
+        takes the document as a list of strings split by newlines and returns
+        the (possibly modified) list of lines.
+
+        """
+        pass
+
+class HtmlStash:
+    """
+    This class is used for stashing HTML objects that we extract
+    in the beginning and replace with place-holders.
+    """
+
+    def __init__ (self):
+        """ Create a HtmlStash. """
+        self.html_counter = 0 # for counting inline html segments
+        self.rawHtmlBlocks=[]
+
+    def store(self, html, safe=False):
+        """
+        Saves an HTML segment for later reinsertion.  Returns a
+        placeholder string that needs to be inserted into the
+        document.
+
+        Keyword arguments:
+
+        * html: an html segment
+        * safe: label an html segment as safe for safemode
+
+        Returns : a placeholder string
+
+        """
+        self.rawHtmlBlocks.append((html, safe))
+        placeholder = HTML_PLACEHOLDER % self.html_counter
+        self.html_counter += 1
+        return placeholder
+
+    def reset(self):
+        self.html_counter = 0
+        self.rawHtmlBlocks = []
+
+
+class HtmlBlockPreprocessor(Preprocessor):
+    """Remove html blocks from the text and store them for later retrieval."""
+
+    right_tag_patterns = ["</%s>", "%s>"]
+
+    def _get_left_tag(self, block):
+        return block[1:].replace(">", " ", 1).split()[0].lower()
+
+    def _get_right_tag(self, left_tag, block):
+        for p in self.right_tag_patterns:
+            tag = p % left_tag
+            i = block.rfind(tag)
+            if i > 2:
+                return tag.lstrip("<").rstrip(">"), i + len(p)-2 + len(left_tag)
+        return block.rstrip()[-len(left_tag)-2:-1].lower(), len(block)
+
+    def _equal_tags(self, left_tag, right_tag):
+        if left_tag == 'div' or left_tag[0] in ['?', '@', '%']: # handle PHP, etc.
+            return True
+        if ("/" + left_tag) == right_tag:
+            return True
+        if (right_tag == "--" and left_tag == "--"):
+            return True
+        elif left_tag == right_tag[1:] \
+            and right_tag[0] != "<":
+            return True
+        else:
+            return False
+
+    def _is_oneliner(self, tag):
+        return (tag in ['hr', 'hr/'])
+
+    def run(self, lines):
+        text = "\n".join(lines)
+        new_blocks = []
+        text = text.split("\n\n")
+        items = []
+        left_tag = ''
+        right_tag = ''
+        in_tag = False # flag
+
+        while text:
+            block = text[0]
+            if block.startswith("\n"):
+                block = block[1:]
+            text = text[1:]
+
+            if block.startswith("\n"):
+                block = block[1:]
+
+            if not in_tag:
+                if block.startswith("<"):
+                    left_tag = self._get_left_tag(block)
+                    right_tag, data_index = self._get_right_tag(left_tag, block)
+
+                    if data_index < len(block):
+                        text.insert(0, block[data_index:])
+                        block = block[:data_index]
+
+                    if not (markdown.isBlockLevel(left_tag) \
+                        or block[1] in ["!", "?", "@", "%"]):
+                        new_blocks.append(block)
+                        continue
+
+                    if self._is_oneliner(left_tag):
+                        new_blocks.append(block.strip())
+                        continue
+
+                    if block[1] == "!":
+                        # is a comment block
+                        left_tag = "--"
+                        right_tag, data_index = self._get_right_tag(left_tag, block)
+                        # keep checking conditions below and maybe just append
+
+                    if block.rstrip().endswith(">") \
+                        and self._equal_tags(left_tag, right_tag):
+                        new_blocks.append(
+                            self.markdown.htmlStash.store(block.strip()))
+                        continue
+                    else: #if not block[1] == "!":
+                        # if is block level tag and is not complete
+
+                        if markdown.isBlockLevel(left_tag) or left_tag == "--" \
+                        and not block.rstrip().endswith(">"):
+                            items.append(block.strip())
+                            in_tag = True
+                        else:
+                            new_blocks.append(
+                            self.markdown.htmlStash.store(block.strip()))
+
+                        continue
+
+                new_blocks.append(block)
+
+            else:
+                items.append(block.strip())
+
+                right_tag, data_index = self._get_right_tag(left_tag, block)
+
+                if self._equal_tags(left_tag, right_tag):
+                    # if find closing tag
+                    in_tag = False
+                    new_blocks.append(
+                        self.markdown.htmlStash.store('\n\n'.join(items)))
+                    items = []
+
+        if items:
+            new_blocks.append(self.markdown.htmlStash.store('\n\n'.join(items)))
+            new_blocks.append('\n')
+
+        new_text = "\n\n".join(new_blocks)
+        return new_text.split("\n")
+
+
+class ReferencePreprocessor(Preprocessor):
+    """ Remove reference definitions from text and store for later use. """
+
+    RE = re.compile(r'^(\ ?\ ?\ ?)\[([^\]]*)\]:\s*([^ ]*)(.*)$', re.DOTALL)
+
+    def run (self, lines):
+        new_text = [];
+        for line in lines:
+            m = self.RE.match(line)
+            if m:
+                id = m.group(2).strip().lower()
+                t = m.group(4).strip()  # potential title
+                if not t:
+                    self.markdown.references[id] = (m.group(3), t)
+                elif (len(t) >= 2
+                      and (t[0] == t[-1] == "\""
+                           or t[0] == t[-1] == "\'"
+                           or (t[0] == "(" and t[-1] == ")") ) ):
+                    self.markdown.references[id] = (m.group(3), t[1:-1])
+                else:
+                    new_text.append(line)
+            else:
+                new_text.append(line)
+
+        return new_text #+ "\n"

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/treeprocessors.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/treeprocessors.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/contrib/markdown/treeprocessors.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,329 @@
+import markdown
+import re
+
+def isString(s):
+    """ Check if it's string """
+    return isinstance(s, unicode) or isinstance(s, str)
+
+class Processor:
+    def __init__(self, markdown_instance=None):
+        if markdown_instance:
+            self.markdown = markdown_instance
+
+class Treeprocessor(Processor):
+    """
+    Treeprocessors are run on the ElementTree object before serialization.
+
+    Each Treeprocessor implements a "run" method that takes a pointer to an
+    ElementTree, modifies it as necessary and returns an ElementTree
+    object.
+
+    Treeprocessors must extend markdown.Treeprocessor.
+
+    """
+    def run(self, root):
+        """
+        Subclasses of Treeprocessor should implement a `run` method, which
+        takes a root ElementTree. This method can return another ElementTree 
+        object, and the existing root ElementTree will be replaced, or it can 
+        modify the current tree and return None.
+        """
+        pass
+
+
+class InlineProcessor(Treeprocessor):
+    """
+    A Treeprocessor that traverses a tree, applying inline patterns.
+    """
+
+    def __init__ (self, md):
+        self.__placeholder_prefix = markdown.INLINE_PLACEHOLDER_PREFIX
+        self.__placeholder_suffix = markdown.ETX
+        self.__placeholder_length = 4 + len(self.__placeholder_prefix) \
+                                      + len(self.__placeholder_suffix)
+        self.__placeholder_re = re.compile(markdown.INLINE_PLACEHOLDER % r'([0-9]{4})')
+        self.markdown = md
+
+    def __makePlaceholder(self, type):
+        """ Generate a placeholder """
+        id = "%04d" % len(self.stashed_nodes)
+        hash = markdown.INLINE_PLACEHOLDER % id
+        return hash, id
+
+    def __findPlaceholder(self, data, index):
+        """
+        Extract id from data string, start from index
+
+        Keyword arguments:
+
+        * data: string
+        * index: index, from which we start search
+
+        Returns: placeholder id and string index, after the found placeholder.
+        """
+
+        m = self.__placeholder_re.search(data, index)
+        if m:
+            return m.group(1), m.end()
+        else:
+            return None, index + 1
+
+    def __stashNode(self, node, type):
+        """ Add node to stash """
+        placeholder, id = self.__makePlaceholder(type)
+        self.stashed_nodes[id] = node
+        return placeholder
+
+    def __handleInline(self, data, patternIndex=0):
+        """
+        Process string with inline patterns and replace it
+        with placeholders
+
+        Keyword arguments:
+
+        * data: A line of Markdown text
+        * patternIndex: The index of the inlinePattern to start with
+
+        Returns: String with placeholders.
+
+        """
+        if not isinstance(data, markdown.AtomicString):
+            startIndex = 0
+            while patternIndex < len(self.markdown.inlinePatterns):
+                data, matched, startIndex = self.__applyPattern(
+                    self.markdown.inlinePatterns.value_for_index(patternIndex),
+                    data, patternIndex, startIndex)
+                if not matched:
+                    patternIndex += 1
+        return data
+
+    def __processElementText(self, node, subnode, isText=True):
+        """
+        Process placeholders in Element.text or Element.tail
+        of Elements popped from self.stashed_nodes.
+
+        Keywords arguments:
+
+        * node: parent node
+        * subnode: processing node
+        * isText: bool variable, True - it's text, False - it's tail
+
+        Returns: None
+
+        """
+        if isText:
+            text = subnode.text
+            subnode.text = None
+        else:
+            text = subnode.tail
+            subnode.tail = None
+
+        childResult = self.__processPlaceholders(text, subnode)
+
+        if not isText and node is not subnode:
+            pos = node.getchildren().index(subnode)
+            node.remove(subnode)
+        else:
+            pos = 0
+
+        childResult.reverse()
+        for newChild in childResult:
+            node.insert(pos, newChild)
+
+    def __processPlaceholders(self, data, parent):
+        """
+        Process string with placeholders and generate ElementTree tree.
+
+        Keyword arguments:
+
+        * data: string with placeholders instead of ElementTree elements.
+        * parent: Element, which contains processing inline data
+
+        Returns: list with ElementTree elements with applied inline patterns.
+        """
+        def linkText(text):
+            if text:
+                if result:
+                    if result[-1].tail:
+                        result[-1].tail += text
+                    else:
+                        result[-1].tail = text
+                else:
+                    if parent.text:
+                        parent.text += text
+                    else:
+                        parent.text = text
+
+        result = []
+        strartIndex = 0
+        while data:
+            index = data.find(self.__placeholder_prefix, strartIndex)
+            if index != -1:
+                id, phEndIndex = self.__findPlaceholder(data, index)
+
+                if id in self.stashed_nodes:
+                    node = self.stashed_nodes.get(id)
+
+                    if index > 0:
+                        text = data[strartIndex:index]
+                        linkText(text)
+
+                    if not isString(node): # it's Element
+                        for child in [node] + node.getchildren():
+                            if child.tail:
+                                if child.tail.strip():
+                                    self.__processElementText(node, child, False)
+                            if child.text:
+                                if child.text.strip():
+                                    self.__processElementText(child, child)
+                    else: # it's just a string
+                        linkText(node)
+                        strartIndex = phEndIndex
+                        continue
+
+                    strartIndex = phEndIndex
+                    result.append(node)
+
+                else: # wrong placeholder
+                    end = index + len(prefix)
+                    linkText(data[strartIndex:end])
+                    strartIndex = end
+            else:
+                text = data[strartIndex:]
+                linkText(text)
+                data = ""
+
+        return result
+
+    def __applyPattern(self, pattern, data, patternIndex, startIndex=0):
+        """
+        Check if the line fits the pattern, create the necessary
+        elements, add it to stashed_nodes.
+
+        Keyword arguments:
+
+        * data: the text to be processed
+        * pattern: the pattern to be checked
+        * patternIndex: index of current pattern
+        * startIndex: string index, from which we starting search
+
+        Returns: String with placeholders instead of ElementTree elements.
+
+        """
+        match = pattern.getCompiledRegExp().match(data[startIndex:])
+        leftData = data[:startIndex]
+
+        if not match:
+            return data, False, 0
+
+        node = pattern.handleMatch(match)
+
+        if node is None:
+            return data, True, len(leftData) + match.span(len(match.groups()))[0]
+
+        if not isString(node):
+            if not isinstance(node.text, markdown.AtomicString):
+                # We need to process current node too
+                for child in [node] + node.getchildren():
+                    if not isString(node):
+                        if child.text:
+                            child.text = self.__handleInline(child.text,
+                                                            patternIndex + 1)
+                        if child.tail:
+                            child.tail = self.__handleInline(child.tail,
+                                                            patternIndex)
+
+        placeholder = self.__stashNode(node, pattern.type())
+
+        return "%s%s%s%s" % (leftData,
+                             match.group(1),
+                             placeholder, match.groups()[-1]), True, 0
+
+    def run(self, tree):
+        """Apply inline patterns to a parsed Markdown tree.
+
+        Iterate over ElementTree, find elements with inline tag, apply inline
+        patterns and append newly created Elements to tree.  If you don't
+        want process your data with inline paterns, instead of normal string,
+        use subclass AtomicString:
+
+            node.text = markdown.AtomicString("data won't be processed with inline patterns")
+
+        Arguments:
+
+        * markdownTree: ElementTree object, representing Markdown tree.
+
+        Returns: ElementTree object with applied inline patterns.
+
+        """
+        self.stashed_nodes = {}
+
+        stack = [tree]
+
+        while stack:
+            currElement = stack.pop()
+            insertQueue = []
+            for child in currElement.getchildren():
+                if child.text and not isinstance(child.text, markdown.AtomicString):
+                    text = child.text
+                    child.text = None
+                    lst = self.__processPlaceholders(self.__handleInline(
+                                                    text), child)
+                    stack += lst
+                    insertQueue.append((child, lst))
+
+                if child.getchildren():
+                    stack.append(child)
+
+            for element, lst in insertQueue:
+                if element.text:
+                    element.text = \
+                        markdown.inlinepatterns.handleAttributes(element.text, 
+                                                                 element)
+                i = 0
+                for newChild in lst:
+                    # Processing attributes
+                    if newChild.tail:
+                        newChild.tail = \
+                            markdown.inlinepatterns.handleAttributes(newChild.tail,
+                                                                     element)
+                    if newChild.text:
+                        newChild.text = \
+                            markdown.inlinepatterns.handleAttributes(newChild.text,
+                                                                     newChild)
+                    element.insert(i, newChild)
+                    i += 1
+        return tree
+
+
+class PrettifyTreeprocessor(Treeprocessor):
+    """ Add linebreaks to the html document. """
+
+    def _prettifyETree(self, elem):
+        """ Recursively add linebreaks to ElementTree children. """
+
+        i = "\n"
+        if markdown.isBlockLevel(elem.tag) and elem.tag not in ['code', 'pre']:
+            if (not elem.text or not elem.text.strip()) \
+                    and len(elem) and markdown.isBlockLevel(elem[0].tag):
+                elem.text = i
+            for e in elem:
+                if markdown.isBlockLevel(e.tag):
+                    self._prettifyETree(e)
+            if not elem.tail or not elem.tail.strip():
+                elem.tail = i
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+
+    def run(self, root):
+        """ Add linebreaks to ElementTree root object. """
+
+        self._prettifyETree(root)
+        # Do <br />'s seperately as they are often in the middle of
+        # inline content and missed by _prettifyETree.
+        brs = root.getiterator('br')
+        for br in brs:
+            if not br.tail or not br.tail.strip():
+                br.tail = '\n'
+            else:
+                br.tail = '\n%s' % br.tail

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/convertTmplPathToModuleName.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/convertTmplPathToModuleName.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/Cheetah/convertTmplPathToModuleName.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,15 @@
+import os.path
+import string
+
+l = ['_'] * 256
+for c in string.digits + string.letters:
+    l[ord(c)] = c
+_pathNameTransChars = string.join(l, '')
+del l, c
+
+def convertTmplPathToModuleName(tmplPath,
+                                _pathNameTransChars=_pathNameTransChars,
+                                splitdrive=os.path.splitdrive,
+                                translate=string.translate,
+                                ):
+    return translate(splitdrive(tmplPath)[1], _pathNameTransChars)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+Metadata-Version: 1.0
+Name: Cheetah
+Version: 2.2.1
+Summary: Cheetah is a template engine and code generation tool.
+Home-page: http://www.cheetahtemplate.org/
+Author: R. Tyler Ballance
+Author-email: cheetahtemplate-discuss at lists.sf.net
+License: UNKNOWN
+Description: Cheetah is an open source template engine and code generation tool.
+        
+        It can be used standalone or combined with other tools and frameworks. Web
+        development is its principle use, but Cheetah is very flexible and is also being
+        used to generate C++ game code, Java, sql, form emails and even Python code.
+        
+        Documentation
+        ================================================================================
+        For a high-level introduction to Cheetah please refer to the User's Guide
+        at http://www.cheetahtemplate.org/learn.html
+        
+        Mailing list
+        ================================================================================
+        cheetahtemplate-discuss at lists.sourceforge.net
+        Subscribe at http://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
+        
+        Credits
+        ================================================================================
+        http://www.cheetahtemplate.org/credits.html
+        
+        Recent Changes
+        ================================================================================
+        See http://www.cheetahtemplate.org/CHANGES.txt for full details
+        
+        
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: Intended Audience :: System Administrators
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Operating System :: OS Independent
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Internet :: WWW/HTTP :: Site Management
+Classifier: Topic :: Software Development :: Code Generators
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Software Development :: User Interfaces
+Classifier: Topic :: Text Processing

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,101 @@
+CHANGES
+LICENSE
+MANIFEST.in
+README
+SetupConfig.py
+SetupTools.py
+TODO
+setup.py
+Cheetah.egg-info/PKG-INFO
+Cheetah.egg-info/SOURCES.txt
+Cheetah.egg-info/dependency_links.txt
+Cheetah.egg-info/top_level.txt
+bin/cheetah
+bin/cheetah-compile
+src/CacheRegion.py
+src/CacheStore.py
+src/CheetahWrapper.py
+src/Compiler.py
+src/Django.py
+src/DummyTransaction.py
+src/ErrorCatchers.py
+src/FileUtils.py
+src/Filters.py
+src/ImportHooks.py
+src/ImportManager.py
+src/NameMapper.py
+src/Parser.py
+src/Servlet.py
+src/SettingsManager.py
+src/SourceReader.py
+src/Template.py
+src/TemplateCmdLineIface.py
+src/Unspecified.py
+src/Version.py
+src/__init__.py
+src/_namemapper.c
+src/convertTmplPathToModuleName.py
+src/Macros/I18n.py
+src/Macros/__init__.py
+src/Templates/SkeletonPage.py
+src/Templates/SkeletonPage.tmpl
+src/Templates/_SkeletonPage.py
+src/Templates/__init__.py
+src/Tests/CheetahWrapper.py
+src/Tests/Filters.py
+src/Tests/NameMapper.py
+src/Tests/Regressions.py
+src/Tests/SyntaxAndOutput.py
+src/Tests/Template.py
+src/Tests/Test.py
+src/Tests/Unicode.py
+src/Tests/__init__.py
+src/Tests/unittest_local_copy.py
+src/Tests/xmlrunner.py
+src/Tools/CGITemplate.py
+src/Tools/MondoReport.py
+src/Tools/MondoReportDoc.txt
+src/Tools/RecursiveNull.py
+src/Tools/SiteHierarchy.py
+src/Tools/__init__.py
+src/Tools/turbocheetah/__init__.py
+src/Tools/turbocheetah/cheetahsupport.py
+src/Tools/turbocheetah/tests/__init__.py
+src/Tools/turbocheetah/tests/test_template.py
+src/Utils/Indenter.py
+src/Utils/Misc.py
+src/Utils/VerifyType.py
+src/Utils/WebInputMixin.py
+src/Utils/__init__.py
+src/Utils/htmlDecode.py
+src/Utils/htmlEncode.py
+src/Utils/memcache.py
+src/Utils/statprof.py
+src/contrib/__init__.py
+src/contrib/markdown/__init__.py
+src/contrib/markdown/blockparser.py
+src/contrib/markdown/blockprocessors.py
+src/contrib/markdown/commandline.py
+src/contrib/markdown/etree_loader.py
+src/contrib/markdown/html4.py
+src/contrib/markdown/inlinepatterns.py
+src/contrib/markdown/odict.py
+src/contrib/markdown/postprocessors.py
+src/contrib/markdown/preprocessors.py
+src/contrib/markdown/treeprocessors.py
+src/contrib/markdown/extensions/__init__.py
+src/contrib/markdown/extensions/abbr.py
+src/contrib/markdown/extensions/codehilite.py
+src/contrib/markdown/extensions/def_list.py
+src/contrib/markdown/extensions/extra.py
+src/contrib/markdown/extensions/fenced_code.py
+src/contrib/markdown/extensions/footnotes.py
+src/contrib/markdown/extensions/headerid.py
+src/contrib/markdown/extensions/html_tidy.py
+src/contrib/markdown/extensions/imagelinks.py
+src/contrib/markdown/extensions/legacy.py
+src/contrib/markdown/extensions/meta.py
+src/contrib/markdown/extensions/rss.py
+src/contrib/markdown/extensions/tables.py
+src/contrib/markdown/extensions/toc.py
+src/contrib/markdown/extensions/wikilinks.py
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/native_libs.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/native_libs.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/native_libs.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Cheetah/_namemapper.so

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+from Cheetah.CheetahWrapper import CheetahWrapper
+CheetahWrapper().main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah-compile
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah-compile	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/scripts/cheetah-compile	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+import sys
+from Cheetah.CheetahWrapper import CheetahWrapper
+sys.argv.insert(1, "compile")
+CheetahWrapper().main()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Cheetah-2.2.1-py2.6-linux-x86_64.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Cheetah

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,119 @@
+Metadata-Version: 1.0
+Name: Paste
+Version: 1.7.5.1
+Summary: Tools for using a Web Server Gateway Interface stack
+Home-page: http://pythonpaste.org
+Author: Ian Bicking
+Author-email: ianb at colorstudy.com
+License: MIT
+Description: These provide several pieces of "middleware" (or filters) that can be nested to build web applications.  Each
+        piece of middleware uses the WSGI (`PEP 333`_) interface, and should
+        be compatible with other middleware based on those interfaces.
+        
+        .. _PEP 333: http://www.python.org/peps/pep-0333.html
+        
+        Includes these features...
+        
+        Testing
+        -------
+        
+        * A fixture for testing WSGI applications conveniently and in-process,
+          in ``paste.fixture``
+        
+        * A fixture for testing command-line applications, also in
+          ``paste.fixture``
+        
+        * Check components for WSGI-compliance in ``paste.lint``
+        
+        Dispatching
+        -----------
+        
+        * Chain and cascade WSGI applications (returning the first non-error
+          response) in ``paste.cascade``
+        
+        * Dispatch to several WSGI applications based on URL prefixes, in
+          ``paste.urlmap``
+        
+        * Allow applications to make subrequests and forward requests
+          internally, in ``paste.recursive``
+        
+        Web Application
+        ---------------
+        
+        * Run CGI programs as WSGI applications in ``paste.cgiapp``
+        
+        * Traverse files and load WSGI applications from ``.py`` files (or
+          static files), in ``paste.urlparser``
+        
+        * Serve static directories of files, also in ``paste.urlparser``; also
+          in that module serving from Egg resources using ``pkg_resources``.
+        
+        Tools
+        -----
+        
+        * Catch HTTP-related exceptions (e.g., ``HTTPNotFound``) and turn them
+          into proper responses in ``paste.httpexceptions``
+        
+        * Several authentication techniques, including HTTP (Basic and
+          Digest), signed cookies, and CAS single-signon, in the
+          ``paste.auth`` package.
+        
+        * Create sessions in ``paste.session`` and ``paste.flup_session``
+        
+        * Gzip responses in ``paste.gzip``
+        
+        * A wide variety of routines for manipulating WSGI requests and
+          producing responses, in ``paste.request``, ``paste.response`` and
+          ``paste.wsgilib``
+        
+        Debugging Filters
+        -----------------
+        
+        * Catch (optionally email) errors with extended tracebacks (using
+          Zope/ZPT conventions) in ``paste.exceptions``
+        
+        * Catch errors presenting a `cgitb
+          <http://python.org/doc/current/lib/module-cgitb.html>`_-based
+          output, in ``paste.cgitb_catcher``.
+        
+        * Profile each request and append profiling information to the HTML,
+          in ``paste.debug.profile``
+        
+        * Capture ``print`` output and present it in the browser for
+          debugging, in ``paste.debug.prints``
+        
+        * Validate all HTML output from applications using the `WDG Validator
+          <http://www.htmlhelp.com/tools/validator/>`_, appending any errors
+          or warnings to the page, in ``paste.debug.wdg_validator``
+        
+        Other Tools
+        -----------
+        
+        * A file monitor to allow restarting the server when files have been
+          updated (for automatic restarting when editing code) in
+          ``paste.reloader``
+        
+        * A class for generating and traversing URLs, and creating associated
+          HTML code, in ``paste.url``
+        
+        The latest version is available in a `Subversion repository
+        <http://svn.pythonpaste.org/Paste/trunk#egg=Paste-dev>`_.
+        
+        For the latest changes see the `news file
+        <http://pythonpaste.org/news.html>`_.
+        
+        
+Keywords: web application server wsgi
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Application
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Server
+Classifier: Framework :: Paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,286 @@
+MANIFEST.in
+setup.cfg
+setup.py
+Paste.egg-info/PKG-INFO
+Paste.egg-info/SOURCES.txt
+Paste.egg-info/dependency_links.txt
+Paste.egg-info/entry_points.txt
+Paste.egg-info/namespace_packages.txt
+Paste.egg-info/not-zip-safe
+Paste.egg-info/requires.txt
+Paste.egg-info/top_level.txt
+docs/DeveloperGuidelines.txt
+docs/StyleGuide.txt
+docs/conf.py
+docs/developer-features.txt
+docs/do-it-yourself-framework.txt
+docs/future.txt
+docs/index.txt
+docs/license.txt
+docs/news.txt
+docs/paste-httpserver-threadpool.txt
+docs/testing-applications.txt
+docs/url-parsing-with-wsgi.txt
+docs/_build/DeveloperGuidelines.html
+docs/_build/StyleGuide.html
+docs/_build/developer-features.html
+docs/_build/do-it-yourself-framework.html
+docs/_build/future.html
+docs/_build/genindex.html
+docs/_build/index.html
+docs/_build/license.html
+docs/_build/modindex.html
+docs/_build/news.html
+docs/_build/paste-httpserver-threadpool.html
+docs/_build/py-modindex.html
+docs/_build/search.html
+docs/_build/testing-applications.html
+docs/_build/url-parsing-with-wsgi.html
+docs/_build/community/index.html
+docs/_build/community/mailing-list.html
+docs/_build/community/repository.html
+docs/_build/download/index.html
+docs/_build/include/contact.html
+docs/_build/include/reference_header.html
+docs/_build/modules/auth.auth_tkt.html
+docs/_build/modules/auth.basic.html
+docs/_build/modules/auth.cas.html
+docs/_build/modules/auth.cookie.html
+docs/_build/modules/auth.digest.html
+docs/_build/modules/auth.form.html
+docs/_build/modules/auth.grantip.html
+docs/_build/modules/auth.multi.html
+docs/_build/modules/auth.open_id.html
+docs/_build/modules/cascade.html
+docs/_build/modules/cgiapp.html
+docs/_build/modules/cgitb_catcher.html
+docs/_build/modules/debug.debugapp.html
+docs/_build/modules/debug.fsdiff.html
+docs/_build/modules/debug.prints.html
+docs/_build/modules/debug.profile.html
+docs/_build/modules/debug.watchthreads.html
+docs/_build/modules/debug.wdg_validate.html
+docs/_build/modules/errordocument.html
+docs/_build/modules/evalexception.html
+docs/_build/modules/exceptions.html
+docs/_build/modules/fileapp.html
+docs/_build/modules/fixture.html
+docs/_build/modules/gzipper.html
+docs/_build/modules/httpexceptions.html
+docs/_build/modules/httpheaders.html
+docs/_build/modules/httpserver.html
+docs/_build/modules/lint.html
+docs/_build/modules/pony.html
+docs/_build/modules/progress.html
+docs/_build/modules/proxy.html
+docs/_build/modules/recursive.html
+docs/_build/modules/registry.html
+docs/_build/modules/reloader.html
+docs/_build/modules/request.html
+docs/_build/modules/response.html
+docs/_build/modules/session.html
+docs/_build/modules/transaction.html
+docs/_build/modules/translogger.html
+docs/_build/modules/url.html
+docs/_build/modules/urlmap.html
+docs/_build/modules/urlparser.html
+docs/_build/modules/util.import_string.html
+docs/_build/modules/util.multidict.html
+docs/_build/modules/wsgilib.html
+docs/_build/modules/wsgiwrappers.html
+docs/community/index.txt
+docs/community/mailing-list.txt
+docs/community/repository.txt
+docs/download/index.txt
+docs/include/contact.txt
+docs/include/reference_header.txt
+docs/modules/auth.auth_tkt.txt
+docs/modules/auth.basic.txt
+docs/modules/auth.cas.txt
+docs/modules/auth.cookie.txt
+docs/modules/auth.digest.txt
+docs/modules/auth.form.txt
+docs/modules/auth.grantip.txt
+docs/modules/auth.multi.txt
+docs/modules/cascade.txt
+docs/modules/cgiapp.txt
+docs/modules/cgitb_catcher.txt
+docs/modules/debug.debugapp.txt
+docs/modules/debug.fsdiff.txt
+docs/modules/debug.prints.txt
+docs/modules/debug.profile.txt
+docs/modules/debug.watchthreads.txt
+docs/modules/debug.wdg_validate.txt
+docs/modules/errordocument.txt
+docs/modules/evalexception.txt
+docs/modules/exceptions.txt
+docs/modules/fileapp.txt
+docs/modules/fixture.txt
+docs/modules/gzipper.txt
+docs/modules/httpexceptions.txt
+docs/modules/httpheaders.txt
+docs/modules/httpserver.txt
+docs/modules/lint.txt
+docs/modules/pony.txt
+docs/modules/progress.txt
+docs/modules/proxy.txt
+docs/modules/recursive.txt
+docs/modules/registry.txt
+docs/modules/reloader.txt
+docs/modules/request.txt
+docs/modules/response.txt
+docs/modules/session.txt
+docs/modules/transaction.txt
+docs/modules/translogger.txt
+docs/modules/url.txt
+docs/modules/urlmap.txt
+docs/modules/urlparser.txt
+docs/modules/util.import_string.txt
+docs/modules/util.multidict.txt
+docs/modules/wsgilib.txt
+docs/modules/wsgiwrappers.txt
+paste/__init__.py
+paste/cascade.py
+paste/cgiapp.py
+paste/cgitb_catcher.py
+paste/config.py
+paste/errordocument.py
+paste/fileapp.py
+paste/fixture.py
+paste/flup_session.py
+paste/gzipper.py
+paste/httpexceptions.py
+paste/httpheaders.py
+paste/httpserver.py
+paste/lint.py
+paste/modpython.py
+paste/pony.py
+paste/progress.py
+paste/proxy.py
+paste/recursive.py
+paste/registry.py
+paste/reloader.py
+paste/request.py
+paste/response.py
+paste/session.py
+paste/transaction.py
+paste/translogger.py
+paste/url.py
+paste/urlmap.py
+paste/urlparser.py
+paste/wsgilib.py
+paste/wsgiwrappers.py
+paste/auth/__init__.py
+paste/auth/auth_tkt.py
+paste/auth/basic.py
+paste/auth/cas.py
+paste/auth/cookie.py
+paste/auth/digest.py
+paste/auth/form.py
+paste/auth/grantip.py
+paste/auth/multi.py
+paste/auth/open_id.py
+paste/cowbell/__init__.py
+paste/debug/__init__.py
+paste/debug/debugapp.py
+paste/debug/doctest_webapp.py
+paste/debug/fsdiff.py
+paste/debug/prints.py
+paste/debug/profile.py
+paste/debug/testserver.py
+paste/debug/watchthreads.py
+paste/debug/wdg_validate.py
+paste/evalexception/__init__.py
+paste/evalexception/evalcontext.py
+paste/evalexception/middleware.py
+paste/evalexception/media/MochiKit.packed.js
+paste/evalexception/media/debug.js
+paste/evalexception/media/minus.jpg
+paste/evalexception/media/plus.jpg
+paste/exceptions/__init__.py
+paste/exceptions/collector.py
+paste/exceptions/errormiddleware.py
+paste/exceptions/formatter.py
+paste/exceptions/reporter.py
+paste/exceptions/serial_number_generator.py
+paste/util/PySourceColor.py
+paste/util/UserDict24.py
+paste/util/__init__.py
+paste/util/classinit.py
+paste/util/classinstance.py
+paste/util/converters.py
+paste/util/dateinterval.py
+paste/util/datetimeutil.py
+paste/util/doctest24.py
+paste/util/filemixin.py
+paste/util/finddata.py
+paste/util/findpackage.py
+paste/util/import_string.py
+paste/util/intset.py
+paste/util/ip4.py
+paste/util/killthread.py
+paste/util/looper.py
+paste/util/mimeparse.py
+paste/util/multidict.py
+paste/util/quoting.py
+paste/util/scgiserver.py
+paste/util/string24.py
+paste/util/subprocess24.py
+paste/util/template.py
+paste/util/threadedprint.py
+paste/util/threadinglocal.py
+tests/__init__.py
+tests/test_cgiapp.py
+tests/test_cgitb_catcher.py
+tests/test_config.py
+tests/test_doctests.py
+tests/test_errordocument.py
+tests/test_fileapp.py
+tests/test_fixture.py
+tests/test_grantip.py
+tests/test_gzipper.py
+tests/test_httpheaders.py
+tests/test_import_string.py
+tests/test_multidict.py
+tests/test_profilemiddleware.py
+tests/test_proxy.py
+tests/test_recursive.py
+tests/test_registry.py
+tests/test_request.py
+tests/test_request_form.py
+tests/test_response.py
+tests/test_session.py
+tests/test_template.txt
+tests/test_urlmap.py
+tests/test_urlparser.py
+tests/test_wsgiwrappers.py
+tests/test_auth/__init__.py
+tests/test_auth/test_auth_cookie.py
+tests/test_auth/test_auth_digest.py
+tests/test_exceptions/__init__.py
+tests/test_exceptions/test_error_middleware.py
+tests/test_exceptions/test_formatter.py
+tests/test_exceptions/test_httpexceptions.py
+tests/test_exceptions/test_reporter.py
+tests/test_util/__init__.py
+tests/test_util/test_datetimeutil.py
+tests/test_util/test_mimeparse.py
+tests/urlparser_data/__init__.py
+tests/urlparser_data/secured.txt
+tests/urlparser_data/deep/sub/Main.txt
+tests/urlparser_data/find_file/index.txt
+tests/urlparser_data/hook/__init__.py
+tests/urlparser_data/hook/app.py
+tests/urlparser_data/hook/index.py
+tests/urlparser_data/not_found/__init__.py
+tests/urlparser_data/not_found/recur/__init__.py
+tests/urlparser_data/not_found/recur/isfound.txt
+tests/urlparser_data/not_found/simple/__init__.py
+tests/urlparser_data/not_found/simple/found.txt
+tests/urlparser_data/not_found/user/__init__.py
+tests/urlparser_data/not_found/user/list.py
+tests/urlparser_data/python/__init__.py
+tests/urlparser_data/python/simpleapp.py
+tests/urlparser_data/python/stream.py
+tests/urlparser_data/python/sub/__init__.py
+tests/urlparser_data/python/sub/simpleapp.py
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/entry_points.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/entry_points.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/entry_points.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+
+      [paste.app_factory]
+      cgi = paste.cgiapp:make_cgi_application [subprocess]
+      static = paste.urlparser:make_static
+      pkg_resources = paste.urlparser:make_pkg_resources
+      urlparser = paste.urlparser:make_url_parser
+      proxy = paste.proxy:make_proxy
+      test = paste.debug.debugapp:make_test_app
+      test_slow = paste.debug.debugapp:make_slow_app
+      transparent_proxy = paste.proxy:make_transparent_proxy
+      watch_threads = paste.debug.watchthreads:make_watch_threads
+
+      [paste.composite_factory]
+      urlmap = paste.urlmap:urlmap_factory
+      cascade = paste.cascade:make_cascade
+
+      [paste.filter_app_factory]
+      error_catcher = paste.exceptions.errormiddleware:make_error_middleware
+      cgitb = paste.cgitb_catcher:make_cgitb_middleware
+      flup_session = paste.flup_session:make_session_middleware [Flup]
+      gzip = paste.gzipper:make_gzip_middleware
+      httpexceptions = paste.httpexceptions:make_middleware
+      lint = paste.lint:make_middleware
+      printdebug = paste.debug.prints:PrintDebugMiddleware
+      profile = paste.debug.profile:make_profile_middleware [hotshot]
+      recursive = paste.recursive:make_recursive_middleware
+      # This isn't good enough to deserve the name egg:Paste#session:
+      paste_session = paste.session:make_session_middleware
+      wdg_validate = paste.debug.wdg_validate:make_wdg_validate_middleware [subprocess]
+      evalerror = paste.evalexception.middleware:make_eval_exception
+      auth_tkt = paste.auth.auth_tkt:make_auth_tkt_middleware
+      auth_basic = paste.auth.basic:make_basic
+      auth_digest = paste.auth.digest:make_digest
+      auth_form = paste.auth.form:make_form
+      grantip = paste.auth.grantip:make_grantip
+      openid = paste.auth.open_id:make_open_id_middleware [openid]
+      pony = paste.pony:make_pony
+      cowbell = paste.cowbell:make_cowbell
+      errordocument = paste.errordocument:make_errordocument
+      auth_cookie = paste.auth.cookie:make_auth_cookie
+      translogger = paste.translogger:make_filter
+      config = paste.config:make_config_filter
+      registry = paste.registry:make_registry_manager
+
+      [paste.server_runner]
+      http = paste.httpserver:server_runner
+      
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/namespace_packages.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/namespace_packages.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/namespace_packages.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/requires.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/requires.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/requires.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,15 @@
+
+
+[Flup]
+flup
+
+[openid]
+python-openid
+
+[Paste]
+
+
+[hotshot]
+
+
+[subprocess]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    # don't prevent use of paste if pkg_resources isn't installed
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__) 
+
+try:
+    import modulefinder
+except ImportError:
+    pass
+else:
+    for p in __path__:
+        modulefinder.AddPackagePath(__name__, p)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Package for authentication/identification of requests.
+
+The objective of this package is to provide single-focused middleware
+components that implement a particular specification.  Integration of
+the components into a usable system is up to a higher-level framework.
+"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/auth_tkt.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/auth_tkt.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/auth_tkt.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,396 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+##########################################################################
+#
+# Copyright (c) 2005 Imaginary Landscape LLC and Contributors.
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+##########################################################################
+"""
+Implementation of cookie signing as done in `mod_auth_tkt
+<http://www.openfusion.com.au/labs/mod_auth_tkt/>`_.
+
+mod_auth_tkt is an Apache module that looks for these signed cookies
+and sets ``REMOTE_USER``, ``REMOTE_USER_TOKENS`` (a comma-separated
+list of groups) and ``REMOTE_USER_DATA`` (arbitrary string data).
+
+This module is an alternative to the ``paste.auth.cookie`` module;
+it's primary benefit is compatibility with mod_auth_tkt, which in turn
+makes it possible to use the same authentication process with
+non-Python code run under Apache.
+"""
+
+import time as time_mod
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+import Cookie
+from paste import request
+from urllib import quote as url_quote
+from urllib import unquote as url_unquote
+
+
+class AuthTicket(object):
+
+    """
+    This class represents an authentication token.  You must pass in
+    the shared secret, the userid, and the IP address.  Optionally you
+    can include tokens (a list of strings, representing role names),
+    'user_data', which is arbitrary data available for your own use in
+    later scripts.  Lastly, you can override the cookie name and
+    timestamp.
+
+    Once you provide all the arguments, use .cookie_value() to
+    generate the appropriate authentication ticket.  .cookie()
+    generates a Cookie object, the str() of which is the complete
+    cookie header to be sent.
+
+    CGI usage::
+
+        token = auth_tkt.AuthTick('sharedsecret', 'username',
+            os.environ['REMOTE_ADDR'], tokens=['admin'])
+        print 'Status: 200 OK'
+        print 'Content-type: text/html'
+        print token.cookie()
+        print
+        ... redirect HTML ...
+
+    Webware usage::
+
+        token = auth_tkt.AuthTick('sharedsecret', 'username',
+            self.request().environ()['REMOTE_ADDR'], tokens=['admin'])
+        self.response().setCookie('auth_tkt', token.cookie_value())
+
+    Be careful not to do an HTTP redirect after login; use meta
+    refresh or Javascript -- some browsers have bugs where cookies
+    aren't saved when set on a redirect.
+    """
+
+    def __init__(self, secret, userid, ip, tokens=(), user_data='',
+                 time=None, cookie_name='auth_tkt',
+                 secure=False):
+        self.secret = secret
+        self.userid = userid
+        self.ip = ip
+        self.tokens = ','.join(tokens)
+        self.user_data = user_data
+        if time is None:
+            self.time = time_mod.time()
+        else:
+            self.time = time
+        self.cookie_name = cookie_name
+        self.secure = secure
+
+    def digest(self):
+        return calculate_digest(
+            self.ip, self.time, self.secret, self.userid, self.tokens,
+            self.user_data)
+
+    def cookie_value(self):
+        v = '%s%08x%s!' % (self.digest(), int(self.time), url_quote(self.userid))
+        if self.tokens:
+            v += self.tokens + '!'
+        v += self.user_data
+        return v
+
+    def cookie(self):
+        c = Cookie.SimpleCookie()
+        c[self.cookie_name] = self.cookie_value().encode('base64').strip().replace('\n', '')
+        c[self.cookie_name]['path'] = '/'
+        if self.secure:
+            c[self.cookie_name]['secure'] = 'true'
+        return c
+
+
+class BadTicket(Exception):
+    """
+    Exception raised when a ticket can't be parsed.  If we get
+    far enough to determine what the expected digest should have
+    been, expected is set.  This should not be shown by default,
+    but can be useful for debugging.
+    """
+    def __init__(self, msg, expected=None):
+        self.expected = expected
+        Exception.__init__(self, msg)
+
+
+def parse_ticket(secret, ticket, ip):
+    """
+    Parse the ticket, returning (timestamp, userid, tokens, user_data).
+
+    If the ticket cannot be parsed, ``BadTicket`` will be raised with
+    an explanation.
+    """
+    ticket = ticket.strip('"')
+    digest = ticket[:32]
+    try:
+        timestamp = int(ticket[32:40], 16)
+    except ValueError, e:
+        raise BadTicket('Timestamp is not a hex integer: %s' % e)
+    try:
+        userid, data = ticket[40:].split('!', 1)
+    except ValueError:
+        raise BadTicket('userid is not followed by !')
+    userid = url_unquote(userid)
+    if '!' in data:
+        tokens, user_data = data.split('!', 1)
+    else:
+        # @@: Is this the right order?
+        tokens = ''
+        user_data = data
+
+    expected = calculate_digest(ip, timestamp, secret,
+                                userid, tokens, user_data)
+
+    if expected != digest:
+        raise BadTicket('Digest signature is not correct',
+                        expected=(expected, digest))
+
+    tokens = tokens.split(',')
+
+    return (timestamp, userid, tokens, user_data)
+
+
+def calculate_digest(ip, timestamp, secret, userid, tokens, user_data):
+    secret = maybe_encode(secret)
+    userid = maybe_encode(userid)
+    tokens = maybe_encode(tokens)
+    user_data = maybe_encode(user_data)
+    digest0 = md5(
+        encode_ip_timestamp(ip, timestamp) + secret + userid + '\0'
+        + tokens + '\0' + user_data).hexdigest()
+    digest = md5(digest0 + secret).hexdigest()
+    return digest
+
+
+def encode_ip_timestamp(ip, timestamp):
+    ip_chars = ''.join(map(chr, map(int, ip.split('.'))))
+    t = int(timestamp)
+    ts = ((t & 0xff000000) >> 24,
+          (t & 0xff0000) >> 16,
+          (t & 0xff00) >> 8,
+          t & 0xff)
+    ts_chars = ''.join(map(chr, ts))
+    return ip_chars + ts_chars
+
+
+def maybe_encode(s, encoding='utf8'):
+    if isinstance(s, unicode):
+        s = s.encode(encoding)
+    return s
+
+
+class AuthTKTMiddleware(object):
+
+    """
+    Middleware that checks for signed cookies that match what
+    `mod_auth_tkt <http://www.openfusion.com.au/labs/mod_auth_tkt/>`_
+    looks for (if you have mod_auth_tkt installed, you don't need this
+    middleware, since Apache will set the environmental variables for
+    you).
+
+    Arguments:
+
+    ``secret``:
+        A secret that should be shared by any instances of this application.
+        If this app is served from more than one machine, they should all
+        have the same secret.
+
+    ``cookie_name``:
+        The name of the cookie to read and write from.  Default ``auth_tkt``.
+
+    ``secure``:
+        If the cookie should be set as 'secure' (only sent over SSL) and if
+        the login must be over SSL. (Defaults to False)
+
+    ``httponly``:
+        If the cookie should be marked as HttpOnly, which means that it's
+        not accessible to JavaScript. (Defaults to False)
+
+    ``include_ip``:
+        If the cookie should include the user's IP address.  If so, then
+        if they change IPs their cookie will be invalid.
+
+    ``logout_path``:
+        The path under this middleware that should signify a logout.  The
+        page will be shown as usual, but the user will also be logged out
+        when they visit this page.
+
+    If used with mod_auth_tkt, then these settings (except logout_path) should
+    match the analogous Apache configuration settings.
+
+    This also adds two functions to the request:
+
+    ``environ['paste.auth_tkt.set_user'](userid, tokens='', user_data='')``
+
+        This sets a cookie that logs the user in.  ``tokens`` is a
+        string (comma-separated groups) or a list of strings.
+        ``user_data`` is a string for your own use.
+
+    ``environ['paste.auth_tkt.logout_user']()``
+
+        Logs out the user.
+    """
+
+    def __init__(self, app, secret, cookie_name='auth_tkt', secure=False,
+                 include_ip=True, logout_path=None, httponly=False,
+                 no_domain_cookie=True, current_domain_cookie=True,
+                 wildcard_cookie=True):
+        self.app = app
+        self.secret = secret
+        self.cookie_name = cookie_name
+        self.secure = secure
+        self.httponly = httponly
+        self.include_ip = include_ip
+        self.logout_path = logout_path
+        self.no_domain_cookie = no_domain_cookie
+        self.current_domain_cookie = current_domain_cookie
+        self.wildcard_cookie = wildcard_cookie
+
+    def __call__(self, environ, start_response):
+        cookies = request.get_cookies(environ)
+        if self.cookie_name in cookies:
+            cookie_value = cookies[self.cookie_name].value
+        else:
+            cookie_value = ''
+        if cookie_value:
+            if self.include_ip:
+                remote_addr = environ['REMOTE_ADDR']
+            else:
+                # mod_auth_tkt uses this dummy value when IP is not
+                # checked:
+                remote_addr = '0.0.0.0'
+            # @@: This should handle bad signatures better:
+            # Also, timeouts should cause cookie refresh
+            try:
+                timestamp, userid, tokens, user_data = parse_ticket(
+                    self.secret, cookie_value, remote_addr)
+                tokens = ','.join(tokens)
+                environ['REMOTE_USER'] = userid
+                if environ.get('REMOTE_USER_TOKENS'):
+                    # We want to add tokens/roles to what's there:
+                    tokens = environ['REMOTE_USER_TOKENS'] + ',' + tokens
+                environ['REMOTE_USER_TOKENS'] = tokens
+                environ['REMOTE_USER_DATA'] = user_data
+                environ['AUTH_TYPE'] = 'cookie'
+            except BadTicket:
+                # bad credentials, just ignore without logging the user
+                # in or anything
+                pass
+        set_cookies = []
+
+        def set_user(userid, tokens='', user_data=''):
+            set_cookies.extend(self.set_user_cookie(
+                environ, userid, tokens, user_data))
+
+        def logout_user():
+            set_cookies.extend(self.logout_user_cookie(environ))
+
+        environ['paste.auth_tkt.set_user'] = set_user
+        environ['paste.auth_tkt.logout_user'] = logout_user
+        if self.logout_path and environ.get('PATH_INFO') == self.logout_path:
+            logout_user()
+
+        def cookie_setting_start_response(status, headers, exc_info=None):
+            headers.extend(set_cookies)
+            return start_response(status, headers, exc_info)
+
+        return self.app(environ, cookie_setting_start_response)
+
+    def set_user_cookie(self, environ, userid, tokens, user_data):
+        if not isinstance(tokens, basestring):
+            tokens = ','.join(tokens)
+        if self.include_ip:
+            remote_addr = environ['REMOTE_ADDR']
+        else:
+            remote_addr = '0.0.0.0'
+        ticket = AuthTicket(
+            self.secret,
+            userid,
+            remote_addr,
+            tokens=tokens,
+            user_data=user_data,
+            cookie_name=self.cookie_name,
+            secure=self.secure)
+        # @@: Should we set REMOTE_USER etc in the current
+        # environment right now as well?
+        cur_domain = environ.get('HTTP_HOST', environ.get('SERVER_NAME'))
+        wild_domain = '.' + cur_domain
+
+        cookie_options = ""
+        if self.secure:
+            cookie_options += "; secure"
+        if self.httponly:
+            cookie_options += "; HttpOnly"
+
+        cookies = []
+        if self.no_domain_cookie:
+            cookies.append(('Set-Cookie', '%s=%s; Path=/%s' % (
+                self.cookie_name, ticket.cookie_value(), cookie_options)))
+        if self.current_domain_cookie:
+            cookies.append(('Set-Cookie', '%s=%s; Path=/; Domain=%s%s' % (
+                self.cookie_name, ticket.cookie_value(), cur_domain,
+                cookie_options)))
+        if self.wildcard_cookie:
+            cookies.append(('Set-Cookie', '%s=%s; Path=/; Domain=%s%s' % (
+                self.cookie_name, ticket.cookie_value(), wild_domain,
+                cookie_options)))
+
+        return cookies
+
+    def logout_user_cookie(self, environ):
+        cur_domain = environ.get('HTTP_HOST', environ.get('SERVER_NAME'))
+        wild_domain = '.' + cur_domain
+        expires = 'Sat, 01-Jan-2000 12:00:00 GMT'
+        cookies = [
+            ('Set-Cookie', '%s=""; Expires="%s"; Path=/' % (self.cookie_name, expires)),
+            ('Set-Cookie', '%s=""; Expires="%s"; Path=/; Domain=%s' %
+             (self.cookie_name, expires, cur_domain)),
+            ('Set-Cookie', '%s=""; Expires="%s"; Path=/; Domain=%s' %
+             (self.cookie_name, expires, wild_domain)),
+            ]
+        return cookies
+
+
+def make_auth_tkt_middleware(
+    app,
+    global_conf,
+    secret=None,
+    cookie_name='auth_tkt',
+    secure=False,
+    include_ip=True,
+    logout_path=None):
+    """
+    Creates the `AuthTKTMiddleware
+    <class-paste.auth.auth_tkt.AuthTKTMiddleware.html>`_.
+
+    ``secret`` is requird, but can be set globally or locally.
+    """
+    from paste.deploy.converters import asbool
+    secure = asbool(secure)
+    include_ip = asbool(include_ip)
+    if secret is None:
+        secret = global_conf.get('secret')
+    if not secret:
+        raise ValueError(
+            "You must provide a 'secret' (in global or local configuration)")
+    return AuthTKTMiddleware(
+        app, secret, cookie_name, secure, include_ip, logout_path or None)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/basic.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/basic.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/basic.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,122 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Basic HTTP/1.0 Authentication
+
+This module implements ``Basic`` authentication as described in
+HTTP/1.0 specification [1]_ .  Do not use this module unless you
+are using SSL or need to work with very out-dated clients, instead
+use ``digest`` authentication.
+
+>>> from paste.wsgilib import dump_environ
+>>> from paste.httpserver import serve
+>>> # from paste.auth.basic import AuthBasicHandler
+>>> realm = 'Test Realm'
+>>> def authfunc(environ, username, password):
+...     return username == password
+>>> serve(AuthBasicHandler(dump_environ, realm, authfunc))
+serving on...
+
+.. [1] http://www.w3.org/Protocols/HTTP/1.0/draft-ietf-http-spec.html#BasicAA
+"""
+from paste.httpexceptions import HTTPUnauthorized
+from paste.httpheaders import *
+
+class AuthBasicAuthenticator(object):
+    """
+    implements ``Basic`` authentication details
+    """
+    type = 'basic'
+    def __init__(self, realm, authfunc):
+        self.realm = realm
+        self.authfunc = authfunc
+
+    def build_authentication(self):
+        head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
+        return HTTPUnauthorized(headers=head)
+
+    def authenticate(self, environ):
+        authorization = AUTHORIZATION(environ)
+        if not authorization:
+            return self.build_authentication()
+        (authmeth, auth) = authorization.split(' ', 1)
+        if 'basic' != authmeth.lower():
+            return self.build_authentication()
+        auth = auth.strip().decode('base64')
+        username, password = auth.split(':', 1)
+        if self.authfunc(environ, username, password):
+            return username
+        return self.build_authentication()
+
+    __call__ = authenticate
+
+class AuthBasicHandler(object):
+    """
+    HTTP/1.0 ``Basic`` authentication middleware
+
+    Parameters:
+
+        ``application``
+
+            The application object is called only upon successful
+            authentication, and can assume ``environ['REMOTE_USER']``
+            is set.  If the ``REMOTE_USER`` is already set, this
+            middleware is simply pass-through.
+
+        ``realm``
+
+            This is a identifier for the authority that is requesting
+            authorization.  It is shown to the user and should be unique
+            within the domain it is being used.
+
+        ``authfunc``
+
+            This is a mandatory user-defined function which takes a
+            ``environ``, ``username`` and ``password`` for its first
+            three arguments.  It should return ``True`` if the user is
+            authenticated.
+
+    """
+    def __init__(self, application, realm, authfunc):
+        self.application = application
+        self.authenticate = AuthBasicAuthenticator(realm, authfunc)
+
+    def __call__(self, environ, start_response):
+        username = REMOTE_USER(environ)
+        if not username:
+            result = self.authenticate(environ)
+            if isinstance(result, str):
+                AUTH_TYPE.update(environ, 'basic')
+                REMOTE_USER.update(environ, result)
+            else:
+                return result.wsgi_application(environ, start_response)
+        return self.application(environ, start_response)
+
+middleware = AuthBasicHandler
+
+__all__ = ['AuthBasicHandler']
+
+def make_basic(app, global_conf, realm, authfunc, **kw):
+    """
+    Grant access via basic authentication
+
+    Config looks like this::
+
+      [filter:grant]
+      use = egg:Paste#auth_basic
+      realm=myrealm
+      authfunc=somepackage.somemodule:somefunction
+      
+    """
+    from paste.util.import_string import eval_import
+    import types
+    authfunc = eval_import(authfunc)
+    assert isinstance(authfunc, types.FunctionType), "authfunc must resolve to a function"
+    return AuthBasicHandler(app, realm, authfunc)
+    
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cas.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cas.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cas.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,99 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+CAS 1.0 Authentication
+
+The Central Authentication System is a straight-forward single sign-on
+mechanism developed by Yale University's ITS department.  It has since
+enjoyed widespread success and is deployed at many major universities
+and some corporations.
+
+    https://clearinghouse.ja-sig.org/wiki/display/CAS/Home
+    http://www.yale.edu/tp/auth/usingcasatyale.html
+
+This implementation has the goal of maintaining current path arguments
+passed to the system so that it can be used as middleware at any stage
+of processing.  It has the secondary goal of allowing for other
+authentication methods to be used concurrently.
+"""
+import urllib
+from paste.request import construct_url
+from paste.httpexceptions import HTTPSeeOther, HTTPForbidden
+
+class CASLoginFailure(HTTPForbidden):
+    """ The exception raised if the authority returns 'no' """
+
+class CASAuthenticate(HTTPSeeOther):
+    """ The exception raised to authenticate the user """
+
+def AuthCASHandler(application, authority):
+    """
+    middleware to implement CAS 1.0 authentication
+
+    There are several possible outcomes:
+
+    0. If the REMOTE_USER environment variable is already populated;
+       then this middleware is a no-op, and the request is passed along
+       to the application.
+
+    1. If a query argument 'ticket' is found, then an attempt to
+       validate said ticket /w the authentication service done.  If the
+       ticket is not validated; an 403 'Forbidden' exception is raised.
+       Otherwise, the REMOTE_USER variable is set with the NetID that
+       was validated and AUTH_TYPE is set to "cas".
+
+    2. Otherwise, a 303 'See Other' is returned to the client directing
+       them to login using the CAS service.  After logon, the service
+       will send them back to this same URL, only with a 'ticket' query
+       argument.
+
+    Parameters:
+
+        ``authority``
+
+            This is a fully-qualified URL to a CAS 1.0 service. The URL
+            should end with a '/' and have the 'login' and 'validate'
+            sub-paths as described in the CAS 1.0 documentation.
+
+    """
+    assert authority.endswith("/") and authority.startswith("http")
+    def cas_application(environ, start_response):
+        username = environ.get('REMOTE_USER','')
+        if username:
+            return application(environ, start_response)
+        qs = environ.get('QUERY_STRING','').split("&")
+        if qs and qs[-1].startswith("ticket="):
+            # assume a response from the authority
+            ticket = qs.pop().split("=", 1)[1]
+            environ['QUERY_STRING'] = "&".join(qs)
+            service = construct_url(environ)
+            args = urllib.urlencode(
+                    {'service': service,'ticket': ticket})
+            requrl = authority + "validate?" + args
+            result = urllib.urlopen(requrl).read().split("\n")
+            if 'yes' == result[0]:
+                environ['REMOTE_USER'] = result[1]
+                environ['AUTH_TYPE'] = 'cas'
+                return application(environ, start_response)
+            exce = CASLoginFailure()
+        else:
+            service = construct_url(environ)
+            args = urllib.urlencode({'service': service})
+            location = authority + "login?" + args
+            exce = CASAuthenticate(location)
+        return exce.wsgi_application(environ, start_response)
+    return cas_application
+
+middleware = AuthCASHandler
+
+__all__ = ['CASLoginFailure', 'CASAuthenticate', 'AuthCASHandler' ]
+
+if '__main__' == __name__:
+    authority = "https://secure.its.yale.edu/cas/servlet/"
+    from paste.wsgilib import dump_environ
+    from paste.httpserver import serve
+    from paste.httpexceptions import *
+    serve(HTTPExceptionHandler(
+             AuthCASHandler(dump_environ, authority)))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cookie.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cookie.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/cookie.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,396 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Cookie "Saved" Authentication
+
+This authentication middleware saves the current REMOTE_USER,
+REMOTE_SESSION, and any other environment variables specified in a
+cookie so that it can be retrieved during the next request without
+requiring re-authentication. This uses a session cookie on the client
+side (so it goes away when the user closes their window) and does
+server-side expiration.
+
+Following is a very simple example where a form is presented asking for
+a user name (no actual checking), and dummy session identifier (perhaps
+corresponding to a database session id) is stored in the cookie.
+
+::
+
+  >>> from paste.httpserver import serve
+  >>> from paste.fileapp import DataApp
+  >>> from paste.httpexceptions import *
+  >>> from paste.auth.cookie import AuthCookieHandler
+  >>> from paste.wsgilib import parse_querystring
+  >>> def testapp(environ, start_response):
+  ...     user = dict(parse_querystring(environ)).get('user','')
+  ...     if user:
+  ...         environ['REMOTE_USER'] = user
+  ...         environ['REMOTE_SESSION'] = 'a-session-id'
+  ...     if environ.get('REMOTE_USER'):
+  ...         page = '<html><body>Welcome %s (%s)</body></html>'
+  ...         page %= (environ['REMOTE_USER'], environ['REMOTE_SESSION'])
+  ...     else:
+  ...         page = ('<html><body><form><input name="user" />'
+  ...                 '<input type="submit" /></form></body></html>')
+  ...     return DataApp(page, content_type="text/html")(
+  ...                    environ, start_response)
+  >>> serve(AuthCookieHandler(testapp))
+  serving on...
+
+"""
+
+import hmac, base64, random, time, warnings
+try:
+    from hashlib import sha1
+except ImportError:
+    # NOTE: We have to use the callable with hashlib (hashlib.sha1),
+    # otherwise hmac only accepts the sha module object itself
+    import sha as sha1
+from paste.request import get_cookies
+
+def make_time(value):
+    return time.strftime("%Y%m%d%H%M", time.gmtime(value))
+_signature_size = len(hmac.new('x', 'x', sha1).digest())
+_header_size = _signature_size + len(make_time(time.time()))
+
+# @@: Should this be using urllib.quote?
+# build encode/decode functions to safely pack away values
+_encode = [('\\', '\\x5c'), ('"', '\\x22'),
+           ('=', '\\x3d'), (';', '\\x3b')]
+_decode = [(v, k) for (k, v) in _encode]
+_decode.reverse()
+def encode(s, sublist = _encode):
+    return reduce((lambda a, (b, c): a.replace(b, c)), sublist, str(s))
+decode = lambda s: encode(s, _decode)
+
+class CookieTooLarge(RuntimeError):
+    def __init__(self, content, cookie):
+        RuntimeError.__init__("Signed cookie exceeds maximum size of 4096")
+        self.content = content
+        self.cookie = cookie
+
+_all_chars = ''.join([chr(x) for x in range(0, 255)])
+def new_secret():
+    """ returns a 64 byte secret """
+    return ''.join(random.sample(_all_chars, 64))
+
+class AuthCookieSigner(object):
+    """
+    save/restore ``environ`` entries via digially signed cookie
+
+    This class converts content into a timed and digitally signed
+    cookie, as well as having the facility to reverse this procedure.
+    If the cookie, after the content is encoded and signed exceeds the
+    maximum length (4096), then CookieTooLarge exception is raised.
+
+    The timeout of the cookie is handled on the server side for a few
+    reasons.  First, if a 'Expires' directive is added to a cookie, then
+    the cookie becomes persistent (lasting even after the browser window
+    has closed). Second, the user's clock may be wrong (perhaps
+    intentionally). The timeout is specified in minutes; and expiration
+    date returned is rounded to one second.
+
+    Constructor Arguments:
+
+        ``secret``
+
+            This is a secret key if you want to syncronize your keys so
+            that the cookie will be good across a cluster of computers.
+            It is recommended via the HMAC specification (RFC 2104) that
+            the secret key be 64 bytes since this is the block size of
+            the hashing.  If you do not provide a secret key, a random
+            one is generated each time you create the handler; this
+            should be sufficient for most cases.
+
+        ``timeout``
+
+            This is the time (in minutes) from which the cookie is set
+            to expire.  Note that on each request a new (replacement)
+            cookie is sent, hence this is effectively a session timeout
+            parameter for your entire cluster.  If you do not provide a
+            timeout, it is set at 30 minutes.
+
+        ``maxlen``
+
+            This is the maximum size of the *signed* cookie; hence the
+            actual content signed will be somewhat less.  If the cookie
+            goes over this size, a ``CookieTooLarge`` exception is
+            raised so that unexpected handling of cookies on the client
+            side are avoided.  By default this is set at 4k (4096 bytes),
+            which is the standard cookie size limit.
+
+    """
+    def __init__(self, secret = None, timeout = None, maxlen = None):
+        self.timeout = timeout or 30
+        if isinstance(timeout, basestring):
+            raise ValueError(
+                "Timeout must be a number (minutes), not a string (%r)"
+                % timeout)
+        self.maxlen  = maxlen or 4096
+        self.secret = secret or new_secret()
+
+    def sign(self, content):
+        """
+        Sign the content returning a valid cookie (that does not
+        need to be escaped and quoted).  The expiration of this
+        cookie is handled server-side in the auth() function.
+        """
+        cookie = base64.encodestring(
+            hmac.new(self.secret, content, sha1).digest() +
+            make_time(time.time() + 60*self.timeout) +
+            content)
+        cookie = cookie.replace("/", "_").replace("=", "~")
+        cookie = cookie.replace('\n', '').replace('\r', '')
+        if len(cookie) > self.maxlen:
+            raise CookieTooLarge(content, cookie)
+        return cookie
+
+    def auth(self, cookie):
+        """
+        Authenticate the cooke using the signature, verify that it
+        has not expired; and return the cookie's content
+        """
+        decode = base64.decodestring(
+            cookie.replace("_", "/").replace("~", "="))
+        signature = decode[:_signature_size]
+        expires = decode[_signature_size:_header_size]
+        content = decode[_header_size:]
+        if signature == hmac.new(self.secret, content, sha1).digest():
+            if int(expires) > int(make_time(time.time())):
+                return content
+            else:
+                # This is the normal case of an expired cookie; just
+                # don't bother doing anything here.
+                pass
+        else:
+            # This case can happen if the server is restarted with a
+            # different secret; or if the user's IP address changed
+            # due to a proxy.  However, it could also be a break-in
+            # attempt -- so should it be reported?
+            pass
+
+class AuthCookieEnviron(list):
+    """
+    a list of environment keys to be saved via cookie
+
+    An instance of this object, found at ``environ['paste.auth.cookie']``
+    lists the `environ` keys that were restored from or will be added
+    to the digially signed cookie.  This object can be accessed from an
+    `environ` variable by using this module's name.
+    """
+    def __init__(self, handler, scanlist):
+        list.__init__(self, scanlist)
+        self.handler = handler
+    def append(self, value):
+        if value in self:
+            return
+        list.append(self, str(value))
+
+class AuthCookieHandler(object):
+    """
+    the actual handler that should be put in your middleware stack
+
+    This middleware uses cookies to stash-away a previously authenticated
+    user (and perhaps other variables) so that re-authentication is not
+    needed.  This does not implement sessions; and therefore N servers
+    can be syncronized to accept the same saved authentication if they
+    all use the same cookie_name and secret.
+
+    By default, this handler scans the `environ` for the REMOTE_USER
+    and REMOTE_SESSION key; if found, it is stored. It can be
+    configured to scan other `environ` keys as well -- but be careful
+    not to exceed 2-3k (so that the encoded and signed cookie does not
+    exceed 4k). You can ask it to handle other environment variables
+    by doing:
+
+       ``environ['paste.auth.cookie'].append('your.environ.variable')``
+
+
+    Constructor Arguments:
+
+        ``application``
+
+            This is the wrapped application which will have access to
+            the ``environ['REMOTE_USER']`` restored by this middleware.
+
+        ``cookie_name``
+
+            The name of the cookie used to store this content, by default
+            it is ``PASTE_AUTH_COOKIE``.
+
+        ``scanlist``
+
+            This is the initial set of ``environ`` keys to
+            save/restore to the signed cookie.  By default is consists
+            only of ``REMOTE_USER`` and ``REMOTE_SESSION``; any tuple
+            or list of environment keys will work.  However, be
+            careful, as the total saved size is limited to around 3k.
+
+        ``signer``
+
+            This is the signer object used to create the actual cookie
+            values, by default, it is ``AuthCookieSigner`` and is passed
+            the remaining arguments to this function: ``secret``,
+            ``timeout``, and ``maxlen``.
+
+    At this time, each cookie is individually signed.  To store more
+    than the 4k of data; it is possible to sub-class this object to
+    provide different ``environ_name`` and ``cookie_name``
+    """
+    environ_name = 'paste.auth.cookie'
+    cookie_name  = 'PASTE_AUTH_COOKIE'
+    signer_class = AuthCookieSigner
+    environ_class = AuthCookieEnviron
+
+    def __init__(self, application, cookie_name=None, scanlist=None,
+                 signer=None, secret=None, timeout=None, maxlen=None):
+        if not signer:
+            signer = self.signer_class(secret, timeout, maxlen)
+        self.signer = signer
+        self.scanlist = scanlist or ('REMOTE_USER','REMOTE_SESSION')
+        self.application = application
+        self.cookie_name = cookie_name or self.cookie_name
+
+    def __call__(self, environ, start_response):
+        if self.environ_name in environ:
+            raise AssertionError("AuthCookie already installed!")
+        scanlist = self.environ_class(self, self.scanlist)
+        jar = get_cookies(environ)
+        if jar.has_key(self.cookie_name):
+            content = self.signer.auth(jar[self.cookie_name].value)
+            if content:
+                for pair in content.split(";"):
+                    (k, v) = pair.split("=")
+                    k = decode(k)
+                    if k not in scanlist:
+                        scanlist.append(k)
+                    if k in environ:
+                        continue
+                    environ[k] = decode(v)
+                    if 'REMOTE_USER' == k:
+                        environ['AUTH_TYPE'] = 'cookie'
+        environ[self.environ_name] = scanlist
+        if "paste.httpexceptions" in environ:
+            warnings.warn("Since paste.httpexceptions is hooked in your "
+                "processing chain before paste.auth.cookie, if an "
+                "HTTPRedirection is raised, the cookies this module sets "
+                "will not be included in your response.\n")
+
+        def response_hook(status, response_headers, exc_info=None):
+            """
+            Scan the environment for keys specified in the scanlist,
+            pack up their values, signs the content and issues a cookie.
+            """
+            scanlist = environ.get(self.environ_name)
+            assert scanlist and isinstance(scanlist, self.environ_class)
+            content = []
+            for k in scanlist:
+                v = environ.get(k)
+                if v is not None:
+                    if type(v) is not str:
+                        raise ValueError(
+                            "The value of the environmental variable %r "
+                            "is not a str (only str is allowed; got %r)"
+                            % (k, v))
+                    content.append("%s=%s" % (encode(k), encode(v)))
+            if content:
+                content = ";".join(content)
+                content = self.signer.sign(content)
+                cookie = '%s=%s; Path=/;' % (self.cookie_name, content)
+                if 'https' == environ['wsgi.url_scheme']:
+                    cookie += ' secure;'
+                response_headers.append(('Set-Cookie', cookie))
+            return start_response(status, response_headers, exc_info)
+        return self.application(environ, response_hook)
+
+middleware = AuthCookieHandler
+
+# Paste Deploy entry point:
+def make_auth_cookie(
+    app, global_conf,
+    # Should this get picked up from global_conf somehow?:
+    cookie_name='PASTE_AUTH_COOKIE',
+    scanlist=('REMOTE_USER', 'REMOTE_SESSION'),
+    # signer cannot be set
+    secret=None,
+    timeout=30,
+    maxlen=4096):
+    """
+    This middleware uses cookies to stash-away a previously
+    authenticated user (and perhaps other variables) so that
+    re-authentication is not needed.  This does not implement
+    sessions; and therefore N servers can be syncronized to accept the
+    same saved authentication if they all use the same cookie_name and
+    secret.
+
+    By default, this handler scans the `environ` for the REMOTE_USER
+    and REMOTE_SESSION key; if found, it is stored. It can be
+    configured to scan other `environ` keys as well -- but be careful
+    not to exceed 2-3k (so that the encoded and signed cookie does not
+    exceed 4k). You can ask it to handle other environment variables
+    by doing:
+
+       ``environ['paste.auth.cookie'].append('your.environ.variable')``
+
+    Configuration:
+
+        ``cookie_name``
+
+            The name of the cookie used to store this content, by
+            default it is ``PASTE_AUTH_COOKIE``.
+
+        ``scanlist``
+
+            This is the initial set of ``environ`` keys to
+            save/restore to the signed cookie.  By default is consists
+            only of ``REMOTE_USER`` and ``REMOTE_SESSION``; any
+            space-separated list of environment keys will work.
+            However, be careful, as the total saved size is limited to
+            around 3k.
+
+        ``secret``
+
+            The secret that will be used to sign the cookies.  If you
+            don't provide one (and none is set globally) then a random
+            secret will be created.  Each time the server is restarted
+            a new secret will then be created and all cookies will
+            become invalid!  This can be any string value.
+
+        ``timeout``
+
+            The time to keep the cookie, expressed in minutes.  This
+            is handled server-side, so a new cookie with a new timeout
+            is added to every response.
+
+        ``maxlen``
+
+            The maximum length of the cookie that is sent (default 4k,
+            which is a typical browser maximum)
+        
+    """
+    if isinstance(scanlist, basestring):
+        scanlist = scanlist.split()
+    if secret is None and global_conf.get('secret'):
+        secret = global_conf['secret']
+    try:
+        timeout = int(timeout)
+    except ValueError:
+        raise ValueError('Bad value for timeout (must be int): %r'
+                         % timeout)
+    try:
+        maxlen = int(maxlen)
+    except ValueError:
+        raise ValueError('Bad value for maxlen (must be int): %r'
+                         % maxlen)
+    return AuthCookieHandler(
+        app, cookie_name=cookie_name, scanlist=scanlist,
+        secret=secret, timeout=timeout, maxlen=maxlen)
+
+__all__ = ['AuthCookieHandler', 'AuthCookieSigner', 'AuthCookieEnviron']
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/digest.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/digest.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/digest.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,214 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Digest HTTP/1.1 Authentication
+
+This module implements ``Digest`` authentication as described by
+RFC 2617 [1]_ .
+
+Basically, you just put this module before your application, and it
+takes care of requesting and handling authentication requests.  This
+module has been tested with several common browsers "out-in-the-wild".
+
+>>> from paste.wsgilib import dump_environ
+>>> from paste.httpserver import serve
+>>> # from paste.auth.digest import digest_password, AuthDigestHandler
+>>> realm = 'Test Realm'
+>>> def authfunc(environ, realm, username):
+...     return digest_password(realm, username, username)
+>>> serve(AuthDigestHandler(dump_environ, realm, authfunc))
+serving on...
+
+This code has not been audited by a security expert, please use with
+caution (or better yet, report security holes). At this time, this
+implementation does not provide for further challenges, nor does it
+support Authentication-Info header.  It also uses md5, and an option
+to use sha would be a good thing.
+
+.. [1] http://www.faqs.org/rfcs/rfc2617.html
+"""
+from paste.httpexceptions import HTTPUnauthorized
+from paste.httpheaders import *
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+import time, random
+from urllib import quote as url_quote
+
+def digest_password(realm, username, password):
+    """ construct the appropriate hashcode needed for HTTP digest """
+    return md5("%s:%s:%s" % (username, realm, password)).hexdigest()
+
+class AuthDigestAuthenticator(object):
+    """ implementation of RFC 2617 - HTTP Digest Authentication """
+    def __init__(self, realm, authfunc):
+        self.nonce    = {} # list to prevent replay attacks
+        self.authfunc = authfunc
+        self.realm    = realm
+
+    def build_authentication(self, stale = ''):
+        """ builds the authentication error """
+        nonce  = md5(
+            "%s:%s" % (time.time(), random.random())).hexdigest()
+        opaque = md5(
+            "%s:%s" % (time.time(), random.random())).hexdigest()
+        self.nonce[nonce] = None
+        parts = {'realm': self.realm, 'qop': 'auth',
+                 'nonce': nonce, 'opaque': opaque }
+        if stale:
+            parts['stale'] = 'true'
+        head = ", ".join(['%s="%s"' % (k, v) for (k, v) in parts.items()])
+        head = [("WWW-Authenticate", 'Digest %s' % head)]
+        return HTTPUnauthorized(headers=head)
+
+    def compute(self, ha1, username, response, method,
+                      path, nonce, nc, cnonce, qop):
+        """ computes the authentication, raises error if unsuccessful """
+        if not ha1:
+            return self.build_authentication()
+        ha2 = md5('%s:%s' % (method, path)).hexdigest()
+        if qop:
+            chk = "%s:%s:%s:%s:%s:%s" % (ha1, nonce, nc, cnonce, qop, ha2)
+        else:
+            chk = "%s:%s:%s" % (ha1, nonce, ha2)
+        if response != md5(chk).hexdigest():
+            if nonce in self.nonce:
+                del self.nonce[nonce]
+            return self.build_authentication()
+        pnc = self.nonce.get(nonce,'00000000')
+        if nc <= pnc:
+            if nonce in self.nonce:
+                del self.nonce[nonce]
+            return self.build_authentication(stale = True)
+        self.nonce[nonce] = nc
+        return username
+
+    def authenticate(self, environ):
+        """ This function takes a WSGI environment and authenticates
+            the request returning authenticated user or error.
+        """
+        method = REQUEST_METHOD(environ)
+        fullpath = url_quote(SCRIPT_NAME(environ)) + url_quote(PATH_INFO(environ))
+        authorization = AUTHORIZATION(environ)
+        if not authorization:
+            return self.build_authentication()
+        (authmeth, auth) = authorization.split(" ", 1)
+        if 'digest' != authmeth.lower():
+            return self.build_authentication()
+        amap = {}
+        for itm in auth.split(", "):
+            (k,v) = [s.strip() for s in itm.split("=", 1)]
+            amap[k] = v.replace('"', '')
+        try:
+            username = amap['username']
+            authpath = amap['uri']
+            nonce    = amap['nonce']
+            realm    = amap['realm']
+            response = amap['response']
+            assert authpath.split("?", 1)[0] in fullpath
+            assert realm == self.realm
+            qop      = amap.get('qop', '')
+            cnonce   = amap.get('cnonce', '')
+            nc       = amap.get('nc', '00000000')
+            if qop:
+                assert 'auth' == qop
+                assert nonce and nc
+        except:
+            return self.build_authentication()
+        ha1 = self.authfunc(environ, realm, username)
+        return self.compute(ha1, username, response, method, authpath,
+                            nonce, nc, cnonce, qop)
+
+    __call__ = authenticate
+
+class AuthDigestHandler(object):
+    """
+    middleware for HTTP Digest authentication (RFC 2617)
+
+    This component follows the procedure below:
+
+        0. If the REMOTE_USER environment variable is already populated;
+           then this middleware is a no-op, and the request is passed
+           along to the application.
+
+        1. If the HTTP_AUTHORIZATION header was not provided or specifies
+           an algorithem other than ``digest``, then a HTTPUnauthorized
+           response is generated with the challenge.
+
+        2. If the response is malformed or or if the user's credientials
+           do not pass muster, another HTTPUnauthorized is raised.
+
+        3. If all goes well, and the user's credintials pass; then
+           REMOTE_USER environment variable is filled in and the
+           AUTH_TYPE is listed as 'digest'.
+
+    Parameters:
+
+        ``application``
+
+            The application object is called only upon successful
+            authentication, and can assume ``environ['REMOTE_USER']``
+            is set.  If the ``REMOTE_USER`` is already set, this
+            middleware is simply pass-through.
+
+        ``realm``
+
+            This is a identifier for the authority that is requesting
+            authorization.  It is shown to the user and should be unique
+            within the domain it is being used.
+
+        ``authfunc``
+
+            This is a callback function which performs the actual
+            authentication; the signature of this callback is:
+
+              authfunc(environ, realm, username) -> hashcode
+
+            This module provides a 'digest_password' helper function
+            which can help construct the hashcode; it is recommended
+            that the hashcode is stored in a database, not the user's
+            actual password (since you only need the hashcode).
+    """
+    def __init__(self, application, realm, authfunc):
+        self.authenticate = AuthDigestAuthenticator(realm, authfunc)
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        username = REMOTE_USER(environ)
+        if not username:
+            result = self.authenticate(environ)
+            if isinstance(result, str):
+                AUTH_TYPE.update(environ,'digest')
+                REMOTE_USER.update(environ, result)
+            else:
+                return result.wsgi_application(environ, start_response)
+        return self.application(environ, start_response)
+
+middleware = AuthDigestHandler
+
+__all__ = ['digest_password', 'AuthDigestHandler' ]
+
+def make_digest(app, global_conf, realm, authfunc, **kw):
+    """
+    Grant access via digest authentication
+
+    Config looks like this::
+
+      [filter:grant]
+      use = egg:Paste#auth_digest
+      realm=myrealm
+      authfunc=somepackage.somemodule:somefunction
+
+    """
+    from paste.util.import_string import eval_import
+    import types
+    authfunc = eval_import(authfunc)
+    assert isinstance(authfunc, types.FunctionType), "authfunc must resolve to a function"
+    return AuthDigestHandler(app, realm, authfunc)
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/form.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/form.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/form.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,149 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Authentication via HTML Form
+
+This is a very simple HTML form login screen that asks for the username
+and password.  This middleware component requires that an authorization
+function taking the name and passsword and that it be placed in your
+application stack. This class does not include any session management
+code or way to save the user's authorization; however, it is easy enough
+to put ``paste.auth.cookie`` in your application stack.
+
+>>> from paste.wsgilib import dump_environ
+>>> from paste.httpserver import serve
+>>> from paste.auth.cookie import AuthCookieHandler
+>>> from paste.auth.form import AuthFormHandler
+>>> def authfunc(environ, username, password):
+...    return username == password
+>>> serve(AuthCookieHandler(
+...           AuthFormHandler(dump_environ, authfunc)))
+serving on...
+
+"""
+from paste.request import construct_url, parse_formvars
+
+TEMPLATE = """\
+<html>
+  <head><title>Please Login!</title></head>
+  <body>
+    <h1>Please Login</h1>
+    <form action="%s" method="post">
+      <dl>
+        <dt>Username:</dt>
+        <dd><input type="text" name="username"></dd>
+        <dt>Password:</dt>
+        <dd><input type="password" name="password"></dd>
+      </dl>
+      <input type="submit" name="authform" />
+      <hr />
+    </form>
+  </body>
+</html>
+"""
+
+class AuthFormHandler(object):
+    """
+    HTML-based login middleware
+
+    This causes a HTML form to be returned if ``REMOTE_USER`` is
+    not found in the ``environ``.  If the form is returned, the
+    ``username`` and ``password`` combination are given to a
+    user-supplied authentication function, ``authfunc``.  If this
+    is successful, then application processing continues.
+
+    Parameters:
+
+        ``application``
+
+            The application object is called only upon successful
+            authentication, and can assume ``environ['REMOTE_USER']``
+            is set.  If the ``REMOTE_USER`` is already set, this
+            middleware is simply pass-through.
+
+        ``authfunc``
+
+            This is a mandatory user-defined function which takes a
+            ``environ``, ``username`` and ``password`` for its first
+            three arguments.  It should return ``True`` if the user is
+            authenticated.
+
+        ``template``
+
+            This is an optional (a default is provided) HTML
+            fragment that takes exactly one ``%s`` substution
+            argument; which *must* be used for the form's ``action``
+            to ensure that this middleware component does not alter
+            the current path.  The HTML form must use ``POST`` and
+            have two input names:  ``username`` and ``password``.
+
+    Since the authentication form is submitted (via ``POST``)
+    neither the ``PATH_INFO`` nor the ``QUERY_STRING`` are accessed,
+    and hence the current path remains _unaltered_ through the
+    entire authentication process. If authentication succeeds, the
+    ``REQUEST_METHOD`` is converted from a ``POST`` to a ``GET``,
+    so that a redirect is unnecessary (unlike most form auth
+    implementations)
+    """
+
+    def __init__(self, application, authfunc, template=None):
+        self.application = application
+        self.authfunc = authfunc
+        self.template = template or TEMPLATE
+
+    def __call__(self, environ, start_response):
+        username = environ.get('REMOTE_USER','')
+        if username:
+            return self.application(environ, start_response)
+
+        if 'POST' == environ['REQUEST_METHOD']:
+            formvars = parse_formvars(environ, include_get_vars=False)
+            username = formvars.get('username')
+            password = formvars.get('password')
+            if username and password:
+                if self.authfunc(environ, username, password):
+                    environ['AUTH_TYPE'] = 'form'
+                    environ['REMOTE_USER'] = username
+                    environ['REQUEST_METHOD'] = 'GET'
+                    environ['CONTENT_LENGTH'] = ''
+                    environ['CONTENT_TYPE'] = ''
+                    del environ['paste.parsed_formvars']
+                    return self.application(environ, start_response)
+
+        content = self.template % construct_url(environ)
+        start_response("200 OK", [('Content-Type', 'text/html'),
+                                  ('Content-Length', str(len(content)))])
+        return [content]
+
+middleware = AuthFormHandler
+
+__all__ = ['AuthFormHandler']
+
+def make_form(app, global_conf, realm, authfunc, **kw):
+    """
+    Grant access via form authentication
+
+    Config looks like this::
+
+      [filter:grant]
+      use = egg:Paste#auth_form
+      realm=myrealm
+      authfunc=somepackage.somemodule:somefunction
+      
+    """
+    from paste.util.import_string import eval_import
+    import types
+    authfunc = eval_import(authfunc)
+    assert isinstance(authfunc, types.FunctionType), "authfunc must resolve to a function"
+    template = kw.get('template')
+    if template is not None:
+        template = eval_import(template)
+        assert isinstance(template, str), "template must resolve to a string"
+
+    return AuthFormHandler(app, authfunc, template)
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/grantip.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/grantip.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/grantip.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,113 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Grant roles and logins based on IP address.
+"""
+from paste.util import ip4
+
+class GrantIPMiddleware(object):
+
+    """
+    On each request, ``ip_map`` is checked against ``REMOTE_ADDR``
+    and logins and roles are assigned based on that.
+
+    ``ip_map`` is a map of {ip_mask: (username, roles)}.  Either
+    ``username`` or ``roles`` may be None.  Roles may also be prefixed
+    with ``-``, like ``'-system'`` meaning that role should be
+    revoked.  ``'__remove__'`` for a username will remove the username.
+
+    If ``clobber_username`` is true (default) then any user
+    specification will override the current value of ``REMOTE_USER``.
+    ``'__remove__'`` will always clobber the username.
+
+    ``ip_mask`` is something that `paste.util.ip4:IP4Range
+    <class-paste.util.ip4.IP4Range.html>`_ can parse.  Simple IP
+    addresses, IP/mask, ip<->ip ranges, and hostnames are allowed.
+    """
+
+    def __init__(self, app, ip_map, clobber_username=True):
+        self.app = app
+        self.ip_map = []
+        for key, value in ip_map.items():
+            self.ip_map.append((ip4.IP4Range(key),
+                                self._convert_user_role(value[0], value[1])))
+        self.clobber_username = clobber_username
+
+    def _convert_user_role(self, username, roles):
+        if roles and isinstance(roles, basestring):
+            roles = roles.split(',')
+        return (username, roles)
+        
+    def __call__(self, environ, start_response):
+        addr = ip4.ip2int(environ['REMOTE_ADDR'], False)
+        remove_user = False
+        add_roles = []
+        for range, (username, roles) in self.ip_map:
+            if addr in range:
+                if roles:
+                    add_roles.extend(roles)
+                if username == '__remove__':
+                    remove_user = True
+                elif username:
+                    if (not environ.get('REMOTE_USER')
+                        or self.clobber_username):
+                        environ['REMOTE_USER'] = username
+        if (remove_user and 'REMOTE_USER' in environ):
+            del environ['REMOTE_USER']
+        if roles:
+            self._set_roles(environ, add_roles)
+        return self.app(environ, start_response)
+
+    def _set_roles(self, environ, roles):
+        cur_roles = environ.get('REMOTE_USER_TOKENS', '').split(',')
+        # Get rid of empty roles:
+        cur_roles = filter(None, cur_roles)
+        remove_roles = []
+        for role in roles:
+            if role.startswith('-'):
+                remove_roles.append(role[1:])
+            else:
+                if role not in cur_roles:
+                    cur_roles.append(role)
+        for role in remove_roles:
+            if role in cur_roles:
+                cur_roles.remove(role)
+        environ['REMOTE_USER_TOKENS'] = ','.join(cur_roles)
+        
+                
+def make_grantip(app, global_conf, clobber_username=False, **kw):
+    """
+    Grant roles or usernames based on IP addresses.
+
+    Config looks like this::
+
+      [filter:grant]
+      use = egg:Paste#grantip
+      clobber_username = true
+      # Give localhost system role (no username):
+      127.0.0.1 = -:system
+      # Give everyone in 192.168.0.* editor role:
+      192.168.0.0/24 = -:editor
+      # Give one IP the username joe:
+      192.168.0.7 = joe
+      # And one IP is should not be logged in:
+      192.168.0.10 = __remove__:-editor
+      
+    """
+    from paste.deploy.converters import asbool
+    clobber_username = asbool(clobber_username)
+    ip_map = {}
+    for key, value in kw.items():
+        if ':' in value:
+            username, role = value.split(':', 1)
+        else:
+            username = value
+            role = ''
+        if username == '-':
+            username = ''
+        if role == '-':
+            role = ''
+        ip_map[key] = value
+    return GrantIPMiddleware(app, ip_map, clobber_username)
+    
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/multi.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/multi.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/multi.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,79 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Authentication via Multiple Methods
+
+In some environments, the choice of authentication method to be used
+depends upon the environment and is not "fixed".  This middleware allows
+N authentication methods to be registered along with a goodness function
+which determines which method should be used. The following example
+demonstrates how to use both form and digest authentication in a server
+stack; by default it uses form-based authentication unless
+``*authmeth=digest`` is specified as a query argument.
+
+>>> from paste.auth import form, cookie, digest, multi
+>>> from paste.wsgilib import dump_environ
+>>> from paste.httpserver import serve
+>>>
+>>> multi = multi.MultiHandler(dump_environ)
+>>> def authfunc(environ, realm, user):
+...     return digest.digest_password(realm, user, user)
+>>> multi.add_method('digest', digest.middleware, "Test Realm", authfunc)
+>>> multi.set_query_argument('digest')
+>>>
+>>> def authfunc(environ, username, password):
+...     return username == password
+>>> multi.add_method('form', form.middleware, authfunc)
+>>> multi.set_default('form')
+>>> serve(cookie.middleware(multi))
+serving on...
+
+"""
+
+class MultiHandler(object):
+    """
+    Multiple Authentication Handler
+
+    This middleware provides two othogonal facilities:
+
+      - a manner to register any number of authentication middlewares
+
+      - a mechanism to register predicates which cause one of the
+        registered middlewares to be used depending upon the request
+
+    If none of the predicates returns True, then the application is
+    invoked directly without middleware
+    """
+    def __init__(self, application):
+        self.application = application
+        self.default = application
+        self.binding = {}
+        self.predicate = []
+    def add_method(self, name, factory, *args, **kwargs):
+        self.binding[name] = factory(self.application, *args, **kwargs)
+    def add_predicate(self, name, checker):
+        self.predicate.append((checker, self.binding[name]))
+    def set_default(self, name):
+        """ set default authentication method """
+        self.default = self.binding[name]
+    def set_query_argument(self, name, key = '*authmeth', value = None):
+        """ choose authentication method based on a query argument """
+        lookfor = "%s=%s" % (key, value or name)
+        self.add_predicate(name,
+            lambda environ: lookfor in environ.get('QUERY_STRING',''))
+    def __call__(self, environ, start_response):
+        for (checker, binding) in self.predicate:
+            if checker(environ):
+                return binding(environ, start_response)
+        return self.default(environ, start_response)
+
+middleware = MultiHandler
+
+__all__ = ['MultiHandler']
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/open_id.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/open_id.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/auth/open_id.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,412 @@
+# (c) 2005 Ben Bangert
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""
+OpenID Authentication (Consumer)
+
+OpenID is a distributed authentication system for single sign-on originally
+developed at/for LiveJournal.com.
+
+    http://openid.net/
+
+URL. You can have multiple identities in the same way you can have multiple
+URLs. All OpenID does is provide a way to prove that you own a URL (identity).
+And it does this without passing around your password, your email address, or
+anything you don't want it to. There's no profile exchange component at all:
+your profiile is your identity URL, but recipients of your identity can then
+learn more about you from any public, semantically interesting documents
+linked thereunder (FOAF, RSS, Atom, vCARD, etc.).
+
+``Note``: paste.auth.openid requires installation of the Python-OpenID
+libraries::
+
+    http://www.openidenabled.com/
+
+This module is based highly off the consumer.py that Python OpenID comes with.
+
+Using the OpenID Middleware
+===========================
+
+Using the OpenID middleware is fairly easy, the most minimal example using the
+basic login form thats included::
+
+    # Add to your wsgi app creation
+    from paste.auth import open_id
+
+    wsgi_app = open_id.middleware(wsgi_app, '/somewhere/to/store/openid/data')
+
+You will now have the OpenID form available at /oid on your site. Logging in will
+verify that the login worked.
+
+A more complete login should involve having the OpenID middleware load your own
+login page after verifying the OpenID URL so that you can retain the login
+information in your webapp (session, cookies, etc.)::
+
+    wsgi_app = open_id.middleware(wsgi_app, '/somewhere/to/store/openid/data',
+                                  login_redirect='/your/login/code')
+
+Your login code should then be configured to retrieve 'paste.auth.open_id' for
+the users OpenID URL. If this key does not exist, the user has not logged in.
+
+Once the login is retrieved, it should be saved in your webapp, and the user
+should be redirected to wherever they would normally go after a successful
+login.
+"""
+
+__all__ = ['AuthOpenIDHandler']
+
+import cgi
+import urlparse
+import re
+
+import paste.request
+from paste import httpexceptions
+
+def quoteattr(s):
+    qs = cgi.escape(s, 1)
+    return '"%s"' % (qs,)
+
+# You may need to manually add the openid package into your
+# python path if you don't have it installed with your system python.
+# If so, uncomment the line below, and change the path where you have
+# Python-OpenID.
+# sys.path.append('/path/to/openid/')
+
+from openid.store import filestore
+from openid.consumer import consumer
+from openid.oidutil import appendArgs
+
+class AuthOpenIDHandler(object):
+    """
+    This middleware implements OpenID Consumer behavior to authenticate a
+    URL against an OpenID Server.
+    """
+
+    def __init__(self, app, data_store_path, auth_prefix='/oid',
+                 login_redirect=None, catch_401=False,
+                 url_to_username=None):
+        """
+        Initialize the OpenID middleware
+
+        ``app``
+            Your WSGI app to call
+            
+        ``data_store_path``
+            Directory to store crypto data in for use with OpenID servers.
+            
+        ``auth_prefix``
+            Location for authentication process/verification
+            
+        ``login_redirect``
+            Location to load after successful process of login
+            
+        ``catch_401``
+            If true, then any 401 responses will turn into open ID login
+            requirements.
+            
+        ``url_to_username``
+            A function called like ``url_to_username(environ, url)``, which should
+            return a string username.  If not given, the URL will be the username.
+        """
+        store = filestore.FileOpenIDStore(data_store_path)
+        self.oidconsumer = consumer.OpenIDConsumer(store)
+
+        self.app = app
+        self.auth_prefix = auth_prefix
+        self.data_store_path = data_store_path
+        self.login_redirect = login_redirect
+        self.catch_401 = catch_401
+        self.url_to_username = url_to_username
+
+    def __call__(self, environ, start_response):
+        if environ['PATH_INFO'].startswith(self.auth_prefix):
+            # Let's load everything into a request dict to pass around easier
+            request = dict(environ=environ, start=start_response, body=[])
+            request['base_url'] = paste.request.construct_url(environ, with_path_info=False,
+                                                              with_query_string=False)
+
+            path = re.sub(self.auth_prefix, '', environ['PATH_INFO'])
+            request['parsed_uri'] = urlparse.urlparse(path)
+            request['query'] = dict(paste.request.parse_querystring(environ))
+
+            path = request['parsed_uri'][2]
+            if path == '/' or not path:
+                return self.render(request)
+            elif path == '/verify':
+                return self.do_verify(request)
+            elif path == '/process':
+                return self.do_process(request)
+            else:
+                return self.not_found(request)
+        else:
+            if self.catch_401:
+                return self.catch_401_app_call(environ, start_response)
+            return self.app(environ, start_response)
+
+    def catch_401_app_call(self, environ, start_response):
+        """
+        Call the application, and redirect if the app returns a 401 response
+        """
+        was_401 = []
+        def replacement_start_response(status, headers, exc_info=None):
+            if int(status.split(None, 1)) == 401:
+                # @@: Do I need to append something to go back to where we
+                # came from?
+                was_401.append(1)
+                def dummy_writer(v):
+                    pass
+                return dummy_writer
+            else:
+                return start_response(status, headers, exc_info)
+        app_iter = self.app(environ, replacement_start_response)
+        if was_401:
+            try:
+                list(app_iter)
+            finally:
+                if hasattr(app_iter, 'close'):
+                    app_iter.close()
+            redir_url = paste.request.construct_url(environ, with_path_info=False,
+                                                    with_query_string=False)
+            exc = httpexceptions.HTTPTemporaryRedirect(redir_url)
+            return exc.wsgi_application(environ, start_response)
+        else:
+            return app_iter
+
+    def do_verify(self, request):
+        """Process the form submission, initating OpenID verification.
+        """
+
+        # First, make sure that the user entered something
+        openid_url = request['query'].get('openid_url')
+        if not openid_url:
+            return self.render(request, 'Enter an identity URL to verify.',
+                        css_class='error', form_contents=openid_url)
+
+        oidconsumer = self.oidconsumer
+
+        # Then, ask the library to begin the authorization.
+        # Here we find out the identity server that will verify the
+        # user's identity, and get a token that allows us to
+        # communicate securely with the identity server.
+        status, info = oidconsumer.beginAuth(openid_url)
+
+        # If the URL was unusable (either because of network
+        # conditions, a server error, or that the response returned
+        # was not an OpenID identity page), the library will return
+        # an error code. Let the user know that that URL is unusable.
+        if status in [consumer.HTTP_FAILURE, consumer.PARSE_ERROR]:
+            if status == consumer.HTTP_FAILURE:
+                fmt = 'Failed to retrieve <q>%s</q>'
+            else:
+                fmt = 'Could not find OpenID information in <q>%s</q>'
+
+            message = fmt % (cgi.escape(openid_url),)
+            return self.render(request, message, css_class='error', form_contents=openid_url)
+        elif status == consumer.SUCCESS:
+            # The URL was a valid identity URL. Now we construct a URL
+            # that will get us to process the server response. We will
+            # need the token from the beginAuth call when processing
+            # the response. A cookie or a session object could be used
+            # to accomplish this, but for simplicity here we just add
+            # it as a query parameter of the return-to URL.
+            return_to = self.build_url(request, 'process', token=info.token)
+
+            # Now ask the library for the URL to redirect the user to
+            # his OpenID server. It is required for security that the
+            # return_to URL must be under the specified trust_root. We
+            # just use the base_url for this server as a trust root.
+            redirect_url = oidconsumer.constructRedirect(
+                info, return_to, trust_root=request['base_url'])
+
+            # Send the redirect response
+            return self.redirect(request, redirect_url)
+        else:
+            assert False, 'Not reached'
+
+    def do_process(self, request):
+        """Handle the redirect from the OpenID server.
+        """
+        oidconsumer = self.oidconsumer
+
+        # retrieve the token from the environment (in this case, the URL)
+        token = request['query'].get('token', '')
+
+        # Ask the library to check the response that the server sent
+        # us.  Status is a code indicating the response type. info is
+        # either None or a string containing more information about
+        # the return type.
+        status, info = oidconsumer.completeAuth(token, request['query'])
+
+        css_class = 'error'
+        openid_url = None
+        if status == consumer.FAILURE and info:
+            # In the case of failure, if info is non-None, it is the
+            # URL that we were verifying. We include it in the error
+            # message to help the user figure out what happened.
+            openid_url = info
+            fmt = "Verification of %s failed."
+            message = fmt % (cgi.escape(openid_url),)
+        elif status == consumer.SUCCESS:
+            # Success means that the transaction completed without
+            # error. If info is None, it means that the user cancelled
+            # the verification.
+            css_class = 'alert'
+            if info:
+                # This is a successful verification attempt. If this
+                # was a real application, we would do our login,
+                # comment posting, etc. here.
+                openid_url = info
+                if self.url_to_username:
+                    username = self.url_to_username(request['environ'], openid_url)
+                else:
+                    username = openid_url
+                if 'paste.auth_tkt.set_user' in request['environ']:
+                    request['environ']['paste.auth_tkt.set_user'](username)
+                if not self.login_redirect:
+                    fmt = ("If you had supplied a login redirect path, you would have "
+                           "been redirected there.  "
+                           "You have successfully verified %s as your identity.")
+                    message = fmt % (cgi.escape(openid_url),)
+                else:
+                    # @@: This stuff doesn't make sense to me; why not a remote redirect?
+                    request['environ']['paste.auth.open_id'] = openid_url
+                    request['environ']['PATH_INFO'] = self.login_redirect
+                    return self.app(request['environ'], request['start'])
+                    #exc = httpexceptions.HTTPTemporaryRedirect(self.login_redirect)
+                    #return exc.wsgi_application(request['environ'], request['start'])
+            else:
+                # cancelled
+                message = 'Verification cancelled'
+        else:
+            # Either we don't understand the code or there is no
+            # openid_url included with the error. Give a generic
+            # failure message. The library should supply debug
+            # information in a log.
+            message = 'Verification failed.'
+
+        return self.render(request, message, css_class, openid_url)
+
+    def build_url(self, request, action, **query):
+        """Build a URL relative to the server base_url, with the given
+        query parameters added."""
+        base = urlparse.urljoin(request['base_url'], self.auth_prefix + '/' + action)
+        return appendArgs(base, query)
+
+    def redirect(self, request, redirect_url):
+        """Send a redirect response to the given URL to the browser."""
+        response_headers = [('Content-type', 'text/plain'),
+                            ('Location', redirect_url)]
+        request['start']('302 REDIRECT', response_headers)
+        return ["Redirecting to %s" % redirect_url]
+
+    def not_found(self, request):
+        """Render a page with a 404 return code and a message."""
+        fmt = 'The path <q>%s</q> was not understood by this server.'
+        msg = fmt % (request['parsed_uri'],)
+        openid_url = request['query'].get('openid_url')
+        return self.render(request, msg, 'error', openid_url, status='404 Not Found')
+
+    def render(self, request, message=None, css_class='alert', form_contents=None,
+               status='200 OK', title="Python OpenID Consumer"):
+        """Render a page."""
+        response_headers = [('Content-type', 'text/html')]
+        request['start'](str(status), response_headers)
+
+        self.page_header(request, title)
+        if message:
+            request['body'].append("<div class='%s'>" % (css_class,))
+            request['body'].append(message)
+            request['body'].append("</div>")
+        self.page_footer(request, form_contents)
+        return request['body']
+
+    def page_header(self, request, title):
+        """Render the page header"""
+        request['body'].append('''\
+<html>
+  <head><title>%s</title></head>
+  <style type="text/css">
+      * {
+        font-family: verdana,sans-serif;
+      }
+      body {
+        width: 50em;
+        margin: 1em;
+      }
+      div {
+        padding: .5em;
+      }
+      table {
+        margin: none;
+        padding: none;
+      }
+      .alert {
+        border: 1px solid #e7dc2b;
+        background: #fff888;
+      }
+      .error {
+        border: 1px solid #ff0000;
+        background: #ffaaaa;
+      }
+      #verify-form {
+        border: 1px solid #777777;
+        background: #dddddd;
+        margin-top: 1em;
+        padding-bottom: 0em;
+      }
+  </style>
+  <body>
+    <h1>%s</h1>
+    <p>
+      This example consumer uses the <a
+      href="http://openid.schtuff.com/">Python OpenID</a> library. It
+      just verifies that the URL that you enter is your identity URL.
+    </p>
+''' % (title, title))
+
+    def page_footer(self, request, form_contents):
+        """Render the page footer"""
+        if not form_contents:
+            form_contents = ''
+
+        request['body'].append('''\
+    <div id="verify-form">
+      <form method="get" action=%s>
+        Identity&nbsp;URL:
+        <input type="text" name="openid_url" value=%s />
+        <input type="submit" value="Verify" />
+      </form>
+    </div>
+  </body>
+</html>
+''' % (quoteattr(self.build_url(request, 'verify')), quoteattr(form_contents)))
+
+
+middleware = AuthOpenIDHandler
+
+def make_open_id_middleware(
+    app,
+    global_conf,
+    # Should this default to something, or inherit something from global_conf?:
+    data_store_path,
+    auth_prefix='/oid',
+    login_redirect=None,
+    catch_401=False,
+    url_to_username=None,
+    apply_auth_tkt=False,
+    auth_tkt_logout_path=None):
+    from paste.deploy.converters import asbool
+    from paste.util import import_string
+    catch_401 = asbool(catch_401)
+    if url_to_username and isinstance(url_to_username, basestring):
+        url_to_username = import_string.eval_import(url_to_username)
+    apply_auth_tkt = asbool(apply_auth_tkt)
+    new_app = AuthOpenIDHandler(
+        app, data_store_path=data_store_path, auth_prefix=auth_prefix,
+        login_redirect=login_redirect, catch_401=catch_401,
+        url_to_username=url_to_username or None)
+    if apply_auth_tkt:
+        from paste.auth import auth_tkt
+        new_app = auth_tkt.make_auth_tkt_middleware(
+            new_app, global_conf, logout_path=auth_tkt_logout_path)
+    return new_app

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cascade.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cascade.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cascade.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,133 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Cascades through several applications, so long as applications
+return ``404 Not Found``.
+"""
+from paste import httpexceptions
+from paste.util import converters
+import tempfile
+from cStringIO import StringIO
+
+__all__ = ['Cascade']
+
+def make_cascade(loader, global_conf, catch='404', **local_conf):
+    """
+    Entry point for Paste Deploy configuration
+    
+    Expects configuration like::
+
+        [composit:cascade]
+        use = egg:Paste#cascade
+        # all start with 'app' and are sorted alphabetically
+        app1 = foo
+        app2 = bar
+        ...
+        catch = 404 500 ...
+    """
+    catch = map(int, converters.aslist(catch))
+    apps = []
+    for name, value in local_conf.items():
+        if not name.startswith('app'):
+            raise ValueError(
+                "Bad configuration key %r (=%r); all configuration keys "
+                "must start with 'app'"
+                % (name, value))
+        app = loader.get_app(value, global_conf=global_conf)
+        apps.append((name, app))
+    apps.sort()
+    apps = [app for name, app in apps]
+    return Cascade(apps, catch=catch)
+    
+class Cascade(object):
+
+    """
+    Passed a list of applications, ``Cascade`` will try each of them
+    in turn.  If one returns a status code listed in ``catch`` (by
+    default just ``404 Not Found``) then the next application is
+    tried.
+
+    If all applications fail, then the last application's failure
+    response is used.
+
+    Instances of this class are WSGI applications.
+    """
+
+    def __init__(self, applications, catch=(404,)):
+        self.apps = applications
+        self.catch_codes = {}
+        self.catch_exceptions = []
+        for error in catch:
+            if isinstance(error, str):
+                error = int(error.split(None, 1)[0])
+            if isinstance(error, httpexceptions.HTTPException):
+                exc = error
+                code = error.code
+            else:
+                exc = httpexceptions.get_exception(error)
+                code = error
+            self.catch_codes[code] = exc
+            self.catch_exceptions.append(exc)
+        self.catch_exceptions = tuple(self.catch_exceptions)
+                
+    def __call__(self, environ, start_response):
+        """
+        WSGI application interface
+        """
+        failed = []
+        def repl_start_response(status, headers, exc_info=None):
+            code = int(status.split(None, 1)[0])
+            if code in self.catch_codes:
+                failed.append(None)
+                return _consuming_writer
+            return start_response(status, headers, exc_info)
+
+        try:
+            length = int(environ.get('CONTENT_LENGTH', 0) or 0)
+        except ValueError:
+            length = 0
+        if length > 0:
+            # We have to copy wsgi.input
+            copy_wsgi_input = True
+            if length > 4096 or length < 0:
+                f = tempfile.TemporaryFile()
+                if length < 0:
+                    f.write(environ['wsgi.input'].read())
+                else:
+                    copy_len = length
+                    while copy_len > 0:
+                        chunk = environ['wsgi.input'].read(min(copy_len, 4096))
+                        if not chunk:
+                            raise IOError("Request body truncated")
+                        f.write(chunk)
+                        copy_len -= len(chunk)
+                f.seek(0)
+            else:
+                f = StringIO(environ['wsgi.input'].read(length))
+            environ['wsgi.input'] = f
+        else:
+            copy_wsgi_input = False
+        for app in self.apps[:-1]:
+            environ_copy = environ.copy()
+            if copy_wsgi_input:
+                environ_copy['wsgi.input'].seek(0)
+            failed = []
+            try:
+                v = app(environ_copy, repl_start_response)
+                if not failed:
+                    return v
+                else:
+                    if hasattr(v, 'close'):
+                        # Exhaust the iterator first:
+                        list(v)
+                        # then close:
+                        v.close()
+            except self.catch_exceptions, e:
+                pass
+        if copy_wsgi_input:
+            environ['wsgi.input'].seek(0)
+        return self.apps[-1](environ, start_response)
+
+def _consuming_writer(s):
+    pass

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgiapp.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgiapp.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgiapp.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,276 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Application that runs a CGI script.
+"""
+import os
+import sys
+import subprocess
+import urllib
+try:
+    import select
+except ImportError:
+    select = None
+
+from paste.util import converters
+
+__all__ = ['CGIError', 'CGIApplication']
+
+class CGIError(Exception):
+    """
+    Raised when the CGI script can't be found or doesn't
+    act like a proper CGI script.
+    """
+
+class CGIApplication(object):
+
+    """
+    This object acts as a proxy to a CGI application.  You pass in the
+    script path (``script``), an optional path to search for the
+    script (if the name isn't absolute) (``path``).  If you don't give
+    a path, then ``$PATH`` will be used.
+    """
+
+    def __init__(self,
+                 global_conf,
+                 script,
+                 path=None,
+                 include_os_environ=True,
+                 query_string=None):
+        if global_conf:
+            raise NotImplemented(
+                "global_conf is no longer supported for CGIApplication "
+                "(use make_cgi_application); please pass None instead")
+        self.script_filename = script
+        if path is None:
+            path = os.environ.get('PATH', '').split(':')
+        self.path = path
+        if '?' in script:
+            assert query_string is None, (
+                "You cannot have '?' in your script name (%r) and also "
+                "give a query_string (%r)" % (script, query_string))
+            script, query_string = script.split('?', 1)
+        if os.path.abspath(script) != script:
+            # relative path
+            for path_dir in self.path:
+                if os.path.exists(os.path.join(path_dir, script)):
+                    self.script = os.path.join(path_dir, script)
+                    break
+            else:
+                raise CGIError(
+                    "Script %r not found in path %r"
+                    % (script, self.path))
+        else:
+            self.script = script
+        self.include_os_environ = include_os_environ
+        self.query_string = query_string
+
+    def __call__(self, environ, start_response):
+        if 'REQUEST_URI' not in environ:
+            environ['REQUEST_URI'] = (
+                urllib.quote(environ.get('SCRIPT_NAME', ''))
+                + urllib.quote(environ.get('PATH_INFO', '')))
+        if self.include_os_environ:
+            cgi_environ = os.environ.copy()
+        else:
+            cgi_environ = {}
+        for name in environ:
+            # Should unicode values be encoded?
+            if (name.upper() == name
+                and isinstance(environ[name], str)):
+                cgi_environ[name] = environ[name]
+        if self.query_string is not None:
+            old = cgi_environ.get('QUERY_STRING', '')
+            if old:
+                old += '&'
+            cgi_environ['QUERY_STRING'] = old + self.query_string
+        cgi_environ['SCRIPT_FILENAME'] = self.script
+        proc = subprocess.Popen(
+            [self.script],
+            stdin=subprocess.PIPE,
+            stdout=subprocess.PIPE,
+            stderr=subprocess.PIPE,
+            env=cgi_environ,
+            cwd=os.path.dirname(self.script),
+            )
+        writer = CGIWriter(environ, start_response)
+        if select and sys.platform != 'win32':
+            proc_communicate(
+                proc,
+                stdin=StdinReader.from_environ(environ),
+                stdout=writer,
+                stderr=environ['wsgi.errors'])
+        else:
+            stdout, stderr = proc.communicate(StdinReader.from_environ(environ).read())
+            if stderr:
+                environ['wsgi.errors'].write(stderr)
+            writer.write(stdout)
+        if not writer.headers_finished:
+            start_response(writer.status, writer.headers)
+        return []
+
+class CGIWriter(object):
+
+    def __init__(self, environ, start_response):
+        self.environ = environ
+        self.start_response = start_response
+        self.status = '200 OK'
+        self.headers = []
+        self.headers_finished = False
+        self.writer = None
+        self.buffer = ''
+
+    def write(self, data):
+        if self.headers_finished:
+            self.writer(data)
+            return
+        self.buffer += data
+        while '\n' in self.buffer:
+            if '\r\n' in self.buffer and self.buffer.find('\r\n') < self.buffer.find('\n'):
+                line1, self.buffer = self.buffer.split('\r\n', 1)
+            else:
+                line1, self.buffer = self.buffer.split('\n', 1)
+            if not line1:
+                self.headers_finished = True
+                self.writer = self.start_response(
+                    self.status, self.headers)
+                self.writer(self.buffer)
+                del self.buffer
+                del self.headers
+                del self.status
+                break
+            elif ':' not in line1:
+                raise CGIError(
+                    "Bad header line: %r" % line1)
+            else:
+                name, value = line1.split(':', 1)
+                value = value.lstrip()
+                name = name.strip()
+                if name.lower() == 'status':
+                    if ' ' not in value:
+                        # WSGI requires this space, sometimes CGI scripts don't set it:
+                        value = '%s General' % value
+                    self.status = value
+                else:
+                    self.headers.append((name, value))
+
+class StdinReader(object):
+
+    def __init__(self, stdin, content_length):
+        self.stdin = stdin
+        self.content_length = content_length
+
+    def from_environ(cls, environ):
+        length = environ.get('CONTENT_LENGTH')
+        if length:
+            length = int(length)
+        else:
+            length = 0
+        return cls(environ['wsgi.input'], length)
+
+    from_environ = classmethod(from_environ)
+
+    def read(self, size=None):
+        if not self.content_length:
+            return ''
+        if size is None:
+            text = self.stdin.read(self.content_length)
+        else:
+            text = self.stdin.read(min(self.content_length, size))
+        self.content_length -= len(text)
+        return text
+
+def proc_communicate(proc, stdin=None, stdout=None, stderr=None):
+    """
+    Run the given process, piping input/output/errors to the given
+    file-like objects (which need not be actual file objects, unlike
+    the arguments passed to Popen).  Wait for process to terminate.
+
+    Note: this is taken from the posix version of
+    subprocess.Popen.communicate, but made more general through the
+    use of file-like objects.
+    """
+    read_set = []
+    write_set = []
+    input_buffer = ''
+    trans_nl = proc.universal_newlines and hasattr(open, 'newlines')
+
+    if proc.stdin:
+        # Flush stdio buffer.  This might block, if the user has
+        # been writing to .stdin in an uncontrolled fashion.
+        proc.stdin.flush()
+        if input:
+            write_set.append(proc.stdin)
+        else:
+            proc.stdin.close()
+    else:
+        assert stdin is None
+    if proc.stdout:
+        read_set.append(proc.stdout)
+    else:
+        assert stdout is None
+    if proc.stderr:
+        read_set.append(proc.stderr)
+    else:
+        assert stderr is None
+
+    while read_set or write_set:
+        rlist, wlist, xlist = select.select(read_set, write_set, [])
+
+        if proc.stdin in wlist:
+            # When select has indicated that the file is writable,
+            # we can write up to PIPE_BUF bytes without risk
+            # blocking.  POSIX defines PIPE_BUF >= 512
+            next, input_buffer = input_buffer, ''
+            next_len = 512-len(next)
+            if next_len:
+                next += stdin.read(next_len)
+            if not next:
+                proc.stdin.close()
+                write_set.remove(proc.stdin)
+            else:
+                bytes_written = os.write(proc.stdin.fileno(), next)
+                if bytes_written < len(next):
+                    input_buffer = next[bytes_written:]
+
+        if proc.stdout in rlist:
+            data = os.read(proc.stdout.fileno(), 1024)
+            if data == "":
+                proc.stdout.close()
+                read_set.remove(proc.stdout)
+            if trans_nl:
+                data = proc._translate_newlines(data)
+            stdout.write(data)
+
+        if proc.stderr in rlist:
+            data = os.read(proc.stderr.fileno(), 1024)
+            if data == "":
+                proc.stderr.close()
+                read_set.remove(proc.stderr)
+            if trans_nl:
+                data = proc._translate_newlines(data)
+            stderr.write(data)
+
+    try:
+        proc.wait()
+    except OSError, e:
+        if e.errno != 10:
+            raise
+
+def make_cgi_application(global_conf, script, path=None, include_os_environ=None,
+                         query_string=None):
+    """
+    Paste Deploy interface for :class:`CGIApplication`
+
+    This object acts as a proxy to a CGI application.  You pass in the
+    script path (``script``), an optional path to search for the
+    script (if the name isn't absolute) (``path``).  If you don't give
+    a path, then ``$PATH`` will be used.
+    """
+    if path is None:
+        path = global_conf.get('path') or global_conf.get('PATH')
+    include_os_environ = converters.asbool(include_os_environ)
+    return CGIApplication(
+        script, path=path, include_os_environ=include_os_environ,
+        query_string=query_string)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgitb_catcher.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgitb_catcher.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cgitb_catcher.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,116 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+WSGI middleware
+
+Captures any exceptions and prints a pretty report.  See the `cgitb
+documentation <http://python.org/doc/current/lib/module-cgitb.html>`_
+for more.
+"""
+
+import cgitb
+from cStringIO import StringIO
+import sys
+
+from paste.util import converters
+
+class NoDefault(object):
+    pass
+
+class CgitbMiddleware(object):
+
+    def __init__(self, app,
+                 global_conf=None,
+                 display=NoDefault,
+                 logdir=None,
+                 context=5,
+                 format="html"):
+        self.app = app
+        if global_conf is None:
+            global_conf = {}
+        if display is NoDefault:
+            display = global_conf.get('debug')
+        if isinstance(display, basestring):
+            display = converters.asbool(display)
+        self.display = display
+        self.logdir = logdir
+        self.context = int(context)
+        self.format = format
+
+    def __call__(self, environ, start_response):
+        try:
+            app_iter = self.app(environ, start_response)
+            return self.catching_iter(app_iter, environ)
+        except:
+            exc_info = sys.exc_info()
+            start_response('500 Internal Server Error',
+                           [('content-type', 'text/html')],
+                           exc_info)
+            response = self.exception_handler(exc_info, environ)
+            return [response]
+
+    def catching_iter(self, app_iter, environ):
+        if not app_iter:
+            raise StopIteration
+        error_on_close = False
+        try:
+            for v in app_iter:
+                yield v
+            if hasattr(app_iter, 'close'):
+                error_on_close = True
+                app_iter.close()
+        except:
+            response = self.exception_handler(sys.exc_info(), environ)
+            if not error_on_close and hasattr(app_iter, 'close'):
+                try:
+                    app_iter.close()
+                except:
+                    close_response = self.exception_handler(
+                        sys.exc_info(), environ)
+                    response += (
+                        '<hr noshade>Error in .close():<br>%s'
+                        % close_response)
+            yield response
+
+    def exception_handler(self, exc_info, environ):
+        dummy_file = StringIO()
+        hook = cgitb.Hook(file=dummy_file,
+                          display=self.display,
+                          logdir=self.logdir,
+                          context=self.context,
+                          format=self.format)
+        hook(*exc_info)
+        return dummy_file.getvalue()
+        
+def make_cgitb_middleware(app, global_conf,
+                          display=NoDefault,
+                          logdir=None,
+                          context=5,
+                          format='html'):
+    """
+    Wraps the application in the ``cgitb`` (standard library)
+    error catcher.
+        
+      display:
+        If true (or debug is set in the global configuration)
+        then the traceback will be displayed in the browser
+
+      logdir:
+        Writes logs of all errors in that directory
+
+      context:
+        Number of lines of context to show around each line of
+        source code
+    """
+    from paste.deploy.converters import asbool
+    if display is not NoDefault:
+        display = asbool(display)
+    if 'debug' in global_conf:
+        global_conf['debug'] = asbool(global_conf['debug'])
+    return CgitbMiddleware(
+        app, global_conf=global_conf,
+        display=display,
+        logdir=logdir,
+        context=context,
+        format=format)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/config.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/config.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/config.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,120 @@
+# (c) 2006 Ian Bicking, Philip Jenvey and contributors
+# Written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""Paste Configuration Middleware and Objects"""
+from paste.registry import RegistryManager, StackedObjectProxy
+
+__all__ = ['DispatchingConfig', 'CONFIG', 'ConfigMiddleware']
+
+class DispatchingConfig(StackedObjectProxy):
+    """
+    This is a configuration object that can be used globally,
+    imported, have references held onto.  The configuration may differ
+    by thread (or may not).
+
+    Specific configurations are registered (and deregistered) either
+    for the process or for threads.
+    """
+    # @@: What should happen when someone tries to add this
+    # configuration to itself?  Probably the conf should become
+    # resolved, and get rid of this delegation wrapper
+
+    def __init__(self, name='DispatchingConfig'):
+        super(DispatchingConfig, self).__init__(name=name)
+        self.__dict__['_process_configs'] = []
+
+    def push_thread_config(self, conf):
+        """
+        Make ``conf`` the active configuration for this thread.
+        Thread-local configuration always overrides process-wide
+        configuration.
+
+        This should be used like::
+
+            conf = make_conf()
+            dispatching_config.push_thread_config(conf)
+            try:
+                ... do stuff ...
+            finally:
+                dispatching_config.pop_thread_config(conf)
+        """
+        self._push_object(conf)
+
+    def pop_thread_config(self, conf=None):
+        """
+        Remove a thread-local configuration.  If ``conf`` is given,
+        it is checked against the popped configuration and an error
+        is emitted if they don't match.
+        """
+        self._pop_object(conf)
+
+    def push_process_config(self, conf):
+        """
+        Like push_thread_config, but applies the configuration to
+        the entire process.
+        """
+        self._process_configs.append(conf)
+
+    def pop_process_config(self, conf=None):
+        self._pop_from(self._process_configs, conf)
+
+    def _pop_from(self, lst, conf):
+        popped = lst.pop()
+        if conf is not None and popped is not conf:
+            raise AssertionError(
+                "The config popped (%s) is not the same as the config "
+                "expected (%s)"
+                % (popped, conf))
+
+    def _current_obj(self):
+        try:
+            return super(DispatchingConfig, self)._current_obj()
+        except TypeError:
+            if self._process_configs:
+                return self._process_configs[-1]
+            raise AttributeError(
+                "No configuration has been registered for this process "
+                "or thread")
+    current = current_conf = _current_obj
+
+CONFIG = DispatchingConfig()
+
+no_config = object()
+class ConfigMiddleware(RegistryManager):
+    """
+    A WSGI middleware that adds a ``paste.config`` key (by default)
+    to the request environment, as well as registering the
+    configuration temporarily (for the length of the request) with
+    ``paste.config.CONFIG`` (or any other ``DispatchingConfig``
+    object).
+    """
+
+    def __init__(self, application, config, dispatching_config=CONFIG,
+                 environ_key='paste.config'):
+        """
+        This delegates all requests to `application`, adding a *copy*
+        of the configuration `config`.
+        """
+        def register_config(environ, start_response):
+            popped_config = environ.get(environ_key, no_config)
+            current_config = environ[environ_key] = config.copy()
+            environ['paste.registry'].register(dispatching_config,
+                                               current_config)
+
+            try:
+                app_iter = application(environ, start_response)
+            finally:
+                if popped_config is no_config:
+                    environ.pop(environ_key, None)
+                else:
+                    environ[environ_key] = popped_config
+            return app_iter
+
+        super(self.__class__, self).__init__(register_config)
+
+def make_config_filter(app, global_conf, **local_conf):
+    conf = global_conf.copy()
+    conf.update(local_conf)
+    return ConfigMiddleware(app, conf)
+
+make_config_middleware = ConfigMiddleware.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cowbell/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cowbell/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/cowbell/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,104 @@
+# Cowbell images: http://commons.wikimedia.org/wiki/Image:Cowbell-1.jpg
+import os
+import re
+from paste.fileapp import FileApp
+from paste.response import header_value, remove_header
+
+SOUND = "http://www.c-eye.net/eyeon/WalkenWAVS/explorestudiospace.wav"
+
+class MoreCowbell(object):
+    def __init__(self, app):
+        self.app = app
+    def __call__(self, environ, start_response):
+        path_info = environ.get('PATH_INFO', '')
+        script_name = environ.get('SCRIPT_NAME', '')
+        for filename in ['bell-ascending.png', 'bell-descending.png']:
+            if path_info == '/.cowbell/'+ filename:
+                app = FileApp(os.path.join(os.path.dirname(__file__), filename))
+                return app(environ, start_response)
+        type = []
+        body = []
+        def repl_start_response(status, headers, exc_info=None):
+            ct = header_value(headers, 'content-type')
+            if ct and ct.startswith('text/html'):
+                type.append(ct)
+                remove_header(headers, 'content-length')
+                start_response(status, headers, exc_info)
+                return body.append
+            return start_response(status, headers, exc_info)
+        app_iter = self.app(environ, repl_start_response)
+        if type:
+            # Got text/html
+            body.extend(app_iter)
+            body = ''.join(body)
+            body = insert_head(body, self.javascript.replace('__SCRIPT_NAME__', script_name))
+            body = insert_body(body, self.resources.replace('__SCRIPT_NAME__', script_name))
+            return [body]
+        else:
+            return app_iter
+
+    javascript = '''\
+<script type="text/javascript">
+var cowbellState = 'hidden';
+var lastCowbellPosition = null;
+function showSomewhere() {
+  var sec, el;
+  if (cowbellState == 'hidden') {
+    el = document.getElementById('cowbell-ascending');
+    lastCowbellPosition = [parseInt(Math.random()*(window.innerWidth-200)), 
+                           parseInt(Math.random()*(window.innerHeight-200))];
+    el.style.left = lastCowbellPosition[0] + 'px';
+    el.style.top = lastCowbellPosition[1] + 'px';
+    el.style.display = '';
+    cowbellState = 'ascending';
+    sec = 1;
+  } else if (cowbellState == 'ascending') {
+    document.getElementById('cowbell-ascending').style.display = 'none';
+    el = document.getElementById('cowbell-descending');
+    el.style.left = lastCowbellPosition[0] + 'px';
+    el.style.top = lastCowbellPosition[1] + 'px';
+    el.style.display = '';
+    cowbellState = 'descending';
+    sec = 1;
+  } else {
+    document.getElementById('cowbell-descending').style.display = 'none';
+    cowbellState = 'hidden';
+    sec = Math.random()*20;
+  }
+  setTimeout(showSomewhere, sec*1000);
+}
+setTimeout(showSomewhere, Math.random()*20*1000);
+</script>
+'''
+
+    resources = '''\
+<div id="cowbell-ascending" style="display: none; position: fixed">
+<img src="__SCRIPT_NAME__/.cowbell/bell-ascending.png">
+</div>
+<div id="cowbell-descending" style="display: none; position: fixed">
+<img src="__SCRIPT_NAME__/.cowbell/bell-descending.png">
+</div>
+'''
+
+def insert_head(body, text):
+    end_head = re.search(r'</head>', body, re.I)
+    if end_head:
+        return body[:end_head.start()] + text + body[end_head.end():]
+    else:
+        return text + body
+
+def insert_body(body, text):
+    end_body = re.search(r'</body>', body, re.I)
+    if end_body:
+        return body[:end_body.start()] + text + body[end_body.end():]
+    else:
+        return body + text
+
+def make_cowbell(global_conf, app):
+    return MoreCowbell(app)
+
+if __name__ == '__main__':
+    from paste.debug.debugapp import SimpleApplication
+    app = MoreCowbell(SimpleApplication())
+    from paste.httpserver import serve
+    serve(app)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Package for debugging and development tools
+"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/debugapp.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/debugapp.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/debugapp.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,79 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Various Applications for Debugging/Testing Purposes
+"""
+
+import time
+__all__ = ['SimpleApplication', 'SlowConsumer']
+
+
+class SimpleApplication(object):
+    """
+    Produces a simple web page
+    """
+    def __call__(self, environ, start_response):
+        body = "<html><body>simple</body></html>"
+        start_response("200 OK", [('Content-Type', 'text/html'),
+                                  ('Content-Length', str(len(body)))])
+        return [body]
+
+class SlowConsumer(object):
+    """
+    Consumes an upload slowly...
+
+    NOTE: This should use the iterator form of ``wsgi.input``,
+          but it isn't implemented in paste.httpserver.
+    """
+    def __init__(self, chunk_size = 4096, delay = 1, progress = True):
+        self.chunk_size = chunk_size
+        self.delay = delay
+        self.progress = True
+
+    def __call__(self, environ, start_response):
+        size = 0
+        total  = environ.get('CONTENT_LENGTH')
+        if total:
+            remaining = int(total)
+            while remaining > 0:
+                if self.progress:
+                    print "%s of %s remaining" % (remaining, total)
+                if remaining > 4096:
+                    chunk = environ['wsgi.input'].read(4096)
+                else:
+                    chunk = environ['wsgi.input'].read(remaining)
+                if not chunk:
+                    break
+                size += len(chunk)
+                remaining -= len(chunk)
+                if self.delay:
+                    time.sleep(self.delay)
+            body = "<html><body>%d bytes</body></html>" % size
+        else:
+            body = ('<html><body>\n'
+                '<form method="post" enctype="multipart/form-data">\n'
+                '<input type="file" name="file">\n'
+                '<input type="submit" >\n'
+                '</form></body></html>\n')
+        print "bingles"
+        start_response("200 OK", [('Content-Type', 'text/html'),
+                                  ('Content-Length', len(body))])
+        return [body]
+
+def make_test_app(global_conf):
+    return SimpleApplication()
+
+make_test_app.__doc__ = SimpleApplication.__doc__
+
+def make_slow_app(global_conf, chunk_size=4096, delay=1, progress=True):
+    from paste.deploy.converters import asbool
+    return SlowConsumer(
+        chunk_size=int(chunk_size),
+        delay=int(delay),
+        progress=asbool(progress))
+
+make_slow_app.__doc__ = SlowConsumer.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/doctest_webapp.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/doctest_webapp.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/doctest_webapp.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,435 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+#!/usr/bin/env python2.4
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+These are functions for use when doctest-testing a document.
+"""
+
+try:
+    import subprocess
+except ImportError:
+    from paste.util import subprocess24 as subprocess
+import doctest
+import os
+import sys
+import shutil
+import re
+import cgi
+import rfc822
+from cStringIO import StringIO
+from paste.util import PySourceColor
+
+
+here = os.path.abspath(__file__)
+paste_parent = os.path.dirname(
+    os.path.dirname(os.path.dirname(here)))
+
+def run(command):
+    data = run_raw(command)
+    if data:
+        print data
+
+def run_raw(command):
+    """
+    Runs the string command, returns any output.
+    """
+    proc = subprocess.Popen(command, shell=True,
+                            stderr=subprocess.STDOUT,
+                            stdout=subprocess.PIPE, env=_make_env())
+    data = proc.stdout.read()
+    proc.wait()
+    while data.endswith('\n') or data.endswith('\r'):
+        data = data[:-1]
+    if data:
+        data = '\n'.join(
+            [l for l in data.splitlines() if l])
+        return data
+    else:
+        return ''
+
+def run_command(command, name, and_print=False):
+    output = run_raw(command)
+    data = '$ %s\n%s' % (command, output)
+    show_file('shell-command', name, description='shell transcript',
+              data=data)
+    if and_print and output:
+        print output
+
+def _make_env():
+    env = os.environ.copy()
+    env['PATH'] = (env.get('PATH', '')
+                   + ':'
+                   + os.path.join(paste_parent, 'scripts')
+                   + ':'
+                   + os.path.join(paste_parent, 'paste', '3rd-party',
+                                  'sqlobject-files', 'scripts'))
+    env['PYTHONPATH'] = (env.get('PYTHONPATH', '')
+                         + ':'
+                         + paste_parent)
+    return env
+
+def clear_dir(dir):
+    """
+    Clears (deletes) the given directory
+    """
+    shutil.rmtree(dir, True)
+
+def ls(dir=None, recurse=False, indent=0):
+    """
+    Show a directory listing
+    """
+    dir = dir or os.getcwd()
+    fns = os.listdir(dir)
+    fns.sort()
+    for fn in fns:
+        full = os.path.join(dir, fn)
+        if os.path.isdir(full):
+            fn = fn + '/'
+        print ' '*indent + fn
+        if os.path.isdir(full) and recurse:
+            ls(dir=full, recurse=True, indent=indent+2)
+
+default_app = None
+default_url = None
+
+def set_default_app(app, url):
+    global default_app
+    global default_url
+    default_app = app
+    default_url = url
+
+def resource_filename(fn):
+    """
+    Returns the filename of the resource -- generally in the directory
+    resources/DocumentName/fn
+    """
+    return os.path.join(
+        os.path.dirname(sys.testing_document_filename),
+        'resources',
+        os.path.splitext(os.path.basename(sys.testing_document_filename))[0],
+        fn)
+
+def show(path_info, example_name):
+    fn = resource_filename(example_name + '.html')
+    out = StringIO()
+    assert default_app is not None, (
+        "No default_app set")
+    url = default_url + path_info
+    out.write('<span class="doctest-url"><a href="%s">%s</a></span><br>\n'
+              % (url, url))
+    out.write('<div class="doctest-example">\n')
+    proc = subprocess.Popen(
+        ['paster', 'serve' '--server=console', '--no-verbose',
+         '--url=' + path_info],
+        stderr=subprocess.PIPE,
+        stdout=subprocess.PIPE,
+        env=_make_env())
+    stdout, errors = proc.communicate()
+    stdout = StringIO(stdout)
+    headers = rfc822.Message(stdout)
+    content = stdout.read()
+    for header, value in headers.items():
+        if header.lower() == 'status' and int(value.split()[0]) == 200:
+            continue
+        if header.lower() in ('content-type', 'content-length'):
+            continue
+        if (header.lower() == 'set-cookie'
+            and value.startswith('_SID_')):
+            continue
+        out.write('<span class="doctest-header">%s: %s</span><br>\n'
+                  % (header, value))
+    lines = [l for l in content.splitlines() if l.strip()]
+    for line in lines:
+        out.write(line + '\n')
+    if errors:
+        out.write('<pre class="doctest-errors">%s</pre>'
+                  % errors)
+    out.write('</div>\n')
+    result = out.getvalue()
+    if not os.path.exists(fn):
+        f = open(fn, 'wb')
+        f.write(result)
+        f.close()
+    else:
+        f = open(fn, 'rb')
+        expected = f.read()
+        f.close()
+        if not html_matches(expected, result):
+            print 'Pages did not match.  Expected from %s:' % fn
+            print '-'*60
+            print expected
+            print '='*60
+            print 'Actual output:'
+            print '-'*60
+            print result
+
+def html_matches(pattern, text):
+    regex = re.escape(pattern)
+    regex = regex.replace(r'\.\.\.', '.*')
+    regex = re.sub(r'0x[0-9a-f]+', '.*', regex)
+    regex = '^%s$' % regex
+    return re.search(regex, text)
+
+def convert_docstring_string(data):
+    if data.startswith('\n'):
+        data = data[1:]
+    lines = data.splitlines()
+    new_lines = []
+    for line in lines:
+        if line.rstrip() == '.':
+            new_lines.append('')
+        else:
+            new_lines.append(line)
+    data = '\n'.join(new_lines) + '\n'
+    return data
+
+def create_file(path, version, data):
+    data = convert_docstring_string(data)
+    write_data(path, data)
+    show_file(path, version)
+
+def append_to_file(path, version, data):
+    data = convert_docstring_string(data)
+    f = open(path, 'a')
+    f.write(data)
+    f.close()
+    # I think these appends can happen so quickly (in less than a second)
+    # that the .pyc file doesn't appear to be expired, even though it
+    # is after we've made this change; so we have to get rid of the .pyc
+    # file:
+    if path.endswith('.py'):
+        pyc_file = path + 'c'
+        if os.path.exists(pyc_file):
+            os.unlink(pyc_file)
+    show_file(path, version, description='added to %s' % path,
+              data=data)
+
+def show_file(path, version, description=None, data=None):
+    ext = os.path.splitext(path)[1]
+    if data is None:
+        f = open(path, 'rb')
+        data = f.read()
+        f.close()
+    if ext == '.py':
+        html = ('<div class="source-code">%s</div>' 
+                % PySourceColor.str2html(data, PySourceColor.dark))
+    else:
+        html = '<pre class="source-code">%s</pre>' % cgi.escape(data, 1)
+    html = '<span class="source-filename">%s</span><br>%s' % (
+        description or path, html)
+    write_data(resource_filename('%s.%s.gen.html' % (path, version)),
+               html)
+
+def call_source_highlight(input, format):
+    proc = subprocess.Popen(['source-highlight', '--out-format=html',
+                             '--no-doc', '--css=none',
+                             '--src-lang=%s' % format], shell=False,
+                            stdout=subprocess.PIPE)
+    stdout, stderr = proc.communicate(input)
+    result = stdout
+    proc.wait()
+    return result
+
+
+def write_data(path, data):
+    dir = os.path.dirname(os.path.abspath(path))
+    if not os.path.exists(dir):
+        os.makedirs(dir)
+    f = open(path, 'wb')
+    f.write(data)
+    f.close()
+    
+
+def change_file(path, changes):
+    f = open(os.path.abspath(path), 'rb')
+    lines = f.readlines()
+    f.close()
+    for change_type, line, text in changes:
+        if change_type == 'insert':
+            lines[line:line] = [text]
+        elif change_type == 'delete':
+            lines[line:text] = []
+        else:
+            assert 0, (
+                "Unknown change_type: %r" % change_type)
+    f = open(path, 'wb')
+    f.write(''.join(lines))
+    f.close()
+
+class LongFormDocTestParser(doctest.DocTestParser):
+
+    """
+    This parser recognizes some reST comments as commands, without
+    prompts or expected output, like:
+
+    .. run:
+
+        do_this(...
+        ...)
+    """
+
+    _EXAMPLE_RE = re.compile(r"""
+        # Source consists of a PS1 line followed by zero or more PS2 lines.
+        (?: (?P<source>
+                (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
+                (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
+            \n?
+            # Want consists of any non-blank lines that do not start with PS1.
+            (?P<want> (?:(?![ ]*$)    # Not a blank line
+                         (?![ ]*>>>)  # Not a line starting with PS1
+                         .*$\n?       # But any other line
+                      )*))
+        | 
+        (?: # This is for longer commands that are prefixed with a reST
+            # comment like '.. run:' (two colons makes that a directive).
+            # These commands cannot have any output.
+
+            (?:^\.\.[ ]*(?P<run>run):[ ]*\n) # Leading command/command
+            (?:[ ]*\n)?         # Blank line following
+            (?P<runsource>
+                (?:(?P<runindent> [ ]+)[^ ].*$)
+                (?:\n [ ]+ .*)*)
+            )
+        |
+        (?: # This is for shell commands
+
+            (?P<shellsource>
+                (?:^(P<shellindent> [ ]*) [$] .*)   # Shell line
+                (?:\n               [ ]*  [>] .*)*) # Continuation
+            \n?
+            # Want consists of any non-blank lines that do not start with $
+            (?P<shellwant> (?:(?![ ]*$)
+                              (?![ ]*[$]$)
+                              .*$\n?
+                           )*))
+        """, re.MULTILINE | re.VERBOSE)
+
+    def _parse_example(self, m, name, lineno):
+        r"""
+        Given a regular expression match from `_EXAMPLE_RE` (`m`),
+        return a pair `(source, want)`, where `source` is the matched
+        example's source code (with prompts and indentation stripped);
+        and `want` is the example's expected output (with indentation
+        stripped).
+
+        `name` is the string's name, and `lineno` is the line number
+        where the example starts; both are used for error messages.
+
+        >>> def parseit(s):
+        ...     p = LongFormDocTestParser()
+        ...     return p._parse_example(p._EXAMPLE_RE.search(s), '<string>', 1)
+        >>> parseit('>>> 1\n1')
+        ('1', {}, '1', None)
+        >>> parseit('>>> (1\n... +1)\n2')
+        ('(1\n+1)', {}, '2', None)
+        >>> parseit('.. run:\n\n    test1\n    test2\n')
+        ('test1\ntest2', {}, '', None)
+        """
+        # Get the example's indentation level.
+        runner = m.group('run') or ''
+        indent = len(m.group('%sindent' % runner))
+        
+        # Divide source into lines; check that they're properly
+        # indented; and then strip their indentation & prompts.
+        source_lines = m.group('%ssource' % runner).split('\n')
+        if runner:
+            self._check_prefix(source_lines[1:], ' '*indent, name, lineno)
+        else:
+            self._check_prompt_blank(source_lines, indent, name, lineno)
+            self._check_prefix(source_lines[2:], ' '*indent + '.', name, lineno)
+        if runner:
+            source = '\n'.join([sl[indent:] for sl in source_lines])
+        else:
+            source = '\n'.join([sl[indent+4:] for sl in source_lines])
+
+        if runner:
+            want = ''
+            exc_msg = None
+        else:
+            # Divide want into lines; check that it's properly indented; and
+            # then strip the indentation.  Spaces before the last newline should
+            # be preserved, so plain rstrip() isn't good enough.
+            want = m.group('want')
+            want_lines = want.split('\n')
+            if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
+                del want_lines[-1]  # forget final newline & spaces after it
+            self._check_prefix(want_lines, ' '*indent, name,
+                               lineno + len(source_lines))
+            want = '\n'.join([wl[indent:] for wl in want_lines])
+
+            # If `want` contains a traceback message, then extract it.
+            m = self._EXCEPTION_RE.match(want)
+            if m:
+                exc_msg = m.group('msg')
+            else:
+                exc_msg = None
+
+        # Extract options from the source.
+        options = self._find_options(source, name, lineno)
+
+        return source, options, want, exc_msg
+
+
+    def parse(self, string, name='<string>'):
+        """
+        Divide the given string into examples and intervening text,
+        and return them as a list of alternating Examples and strings.
+        Line numbers for the Examples are 0-based.  The optional
+        argument `name` is a name identifying this string, and is only
+        used for error messages.
+        """
+        string = string.expandtabs()
+        # If all lines begin with the same indentation, then strip it.
+        min_indent = self._min_indent(string)
+        if min_indent > 0:
+            string = '\n'.join([l[min_indent:] for l in string.split('\n')])
+
+        output = []
+        charno, lineno = 0, 0
+        # Find all doctest examples in the string:
+        for m in self._EXAMPLE_RE.finditer(string):
+            # Add the pre-example text to `output`.
+            output.append(string[charno:m.start()])
+            # Update lineno (lines before this example)
+            lineno += string.count('\n', charno, m.start())
+            # Extract info from the regexp match.
+            (source, options, want, exc_msg) = \
+                     self._parse_example(m, name, lineno)
+            # Create an Example, and add it to the list.
+            if not self._IS_BLANK_OR_COMMENT(source):
+                # @@: Erg, this is the only line I need to change...
+                output.append(doctest.Example(
+                    source, want, exc_msg,
+                    lineno=lineno,
+                    indent=min_indent+len(m.group('indent') or m.group('runindent')),
+                    options=options))
+            # Update lineno (lines inside this example)
+            lineno += string.count('\n', m.start(), m.end())
+            # Update charno.
+            charno = m.end()
+        # Add any remaining post-example text to `output`.
+        output.append(string[charno:])
+        return output
+
+
+
+if __name__ == '__main__':
+    if sys.argv[1:] and sys.argv[1] == 'doctest':
+        doctest.testmod()
+        sys.exit()
+    if not paste_parent in sys.path:
+        sys.path.append(paste_parent)
+    for fn in sys.argv[1:]:
+        fn = os.path.abspath(fn)
+        # @@: OK, ick; but this module gets loaded twice
+        sys.testing_document_filename = fn
+        doctest.testfile(
+            fn, module_relative=False,
+            optionflags=doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE,
+            parser=LongFormDocTestParser())
+        new = os.path.splitext(fn)[0] + '.html'
+        assert new != fn
+        os.system('rst2html.py %s > %s' % (fn, new))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/fsdiff.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/fsdiff.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/fsdiff.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,409 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Module to find differences over time in a filesystem
+
+Basically this takes a snapshot of a directory, then sees what changes
+were made.  The contents of the files are not checked, so you can
+detect that the content was changed, but not what the old version of
+the file was.
+"""
+
+import os
+from fnmatch import fnmatch
+from datetime import datetime
+from paste.util.UserDict24 import IterableUserDict
+import operator
+import re
+
+__all__ = ['Diff', 'Snapshot', 'File', 'Dir', 'report_expected_diffs',
+           'show_diff']
+
+class Diff(object):
+
+    """
+    Represents the difference between two snapshots
+    """
+
+    def __init__(self, before, after):
+        self.before = before
+        self.after = after
+        self._calculate()
+
+    def _calculate(self):
+        before = self.before.data
+        after = self.after.data
+        self.deleted = {}
+        self.updated = {}
+        self.created = after.copy()
+        for path, f in before.items():
+            if path not in after:
+                self.deleted[path] = f
+                continue
+            del self.created[path]
+            if f.mtime < after[path].mtime:
+                self.updated[path] = after[path]
+
+    def __str__(self):
+        return self.report()
+
+    def report(self, header=True, dates=False):
+        s = []
+        if header:
+            s.append('Difference in %s from %s to %s:' %
+                     (self.before.base_path,
+                      self.before.calculated,
+                      self.after.calculated))
+        for name, files, show_size in [
+            ('created', self.created, True),
+            ('deleted', self.deleted, True),
+            ('updated', self.updated, True)]:
+            if files:
+                s.append('-- %s: -------------------' % name)
+                files = files.items()
+                files.sort()
+                last = ''
+                for path, f in files:
+                    t = '  %s' % _space_prefix(last, path, indent=4,
+                                               include_sep=False)
+                    last = path
+                    if show_size and f.size != 'N/A':
+                        t += '  (%s bytes)' % f.size
+                    if dates:
+                        parts = []
+                        if self.before.get(path):
+                            parts.append(self.before[path].mtime)
+                        if self.after.get(path):
+                            parts.append(self.after[path].mtime)
+                        t += ' (mtime: %s)' % ('->'.join(map(repr, parts)))
+                    s.append(t)
+        if len(s) == 1:
+            s.append('  (no changes)')
+        return '\n'.join(s)
+
+class Snapshot(IterableUserDict):
+
+    """
+    Represents a snapshot of a set of files.  Has a dictionary-like
+    interface, keyed relative to ``base_path``
+    """
+
+    def __init__(self, base_path, files=None, ignore_wildcards=(),
+                 ignore_paths=(), ignore_hidden=True):
+        self.base_path = base_path
+        self.ignore_wildcards = ignore_wildcards
+        self.ignore_hidden = ignore_hidden
+        self.ignore_paths = ignore_paths
+        self.calculated = None
+        self.data = files or {}
+        if files is None:
+            self.find_files()
+
+    ############################################################
+    ## File finding
+    ############################################################
+
+    def find_files(self):
+        """
+        Find all the files under the base path, and put them in
+        ``self.data``
+        """
+        self._find_traverse('', self.data)
+        self.calculated = datetime.now()
+
+    def _ignore_file(self, fn):
+        if fn in self.ignore_paths:
+            return True
+        if self.ignore_hidden and os.path.basename(fn).startswith('.'):
+            return True
+        for pat in self.ignore_wildcards:
+            if fnmatch(fn, pat):
+                return True
+        return False
+
+    def _ignore_file(self, fn):
+        if fn in self.ignore_paths:
+            return True
+        if self.ignore_hidden and os.path.basename(fn).startswith('.'):
+            return True
+        return False
+
+    def _find_traverse(self, path, result):
+        full = os.path.join(self.base_path, path)
+        if os.path.isdir(full):
+            if path:
+                # Don't actually include the base path
+                result[path] = Dir(self.base_path, path)
+            for fn in os.listdir(full):
+                fn = os.path.join(path, fn)
+                if self._ignore_file(fn):
+                    continue
+                self._find_traverse(fn, result)
+        else:
+            result[path] = File(self.base_path, path)
+
+    def __repr__(self):
+        return '<%s in %r from %r>' % (
+            self.__class__.__name__, self.base_path,
+            self.calculated or '(no calculation done)')
+
+    def compare_expected(self, expected, comparison=operator.eq,
+                         differ=None, not_found=None,
+                         include_success=False):
+        """
+        Compares a dictionary of ``path: content`` to the
+        found files.  Comparison is done by equality, or the
+        ``comparison(actual_content, expected_content)`` function given.
+
+        Returns dictionary of differences, keyed by path.  Each
+        difference is either noted, or the output of
+        ``differ(actual_content, expected_content)`` is given.
+
+        If a file does not exist and ``not_found`` is given, then
+        ``not_found(path)`` is put in.
+        """
+        result = {}
+        for path in expected:
+            orig_path = path
+            path = path.strip('/')
+            if path not in self.data:
+                if not_found:
+                    msg = not_found(path)
+                else:
+                    msg = 'not found'
+                result[path] = msg
+                continue
+            expected_content = expected[orig_path]
+            file = self.data[path]
+            actual_content = file.bytes
+            if not comparison(actual_content, expected_content):
+                if differ:
+                    msg = differ(actual_content, expected_content)
+                else:
+                    if len(actual_content) < len(expected_content):
+                        msg = 'differ (%i bytes smaller)' % (
+                            len(expected_content) - len(actual_content))
+                    elif len(actual_content) > len(expected_content):
+                        msg = 'differ (%i bytes larger)' % (
+                            len(actual_content) - len(expected_content))
+                    else:
+                        msg = 'diff (same size)'
+                result[path] = msg
+            elif include_success:
+                result[path] = 'same!'
+        return result
+
+    def diff_to_now(self):
+        return Diff(self, self.clone())
+
+    def clone(self):
+        return self.__class__(base_path=self.base_path,
+                              ignore_wildcards=self.ignore_wildcards,
+                              ignore_paths=self.ignore_paths,
+                              ignore_hidden=self.ignore_hidden)
+
+class File(object):
+
+    """
+    Represents a single file found as the result of a command.
+
+    Has attributes:
+
+    ``path``:
+        The path of the file, relative to the ``base_path``
+
+    ``full``:
+        The full path
+
+    ``stat``:
+        The results of ``os.stat``.  Also ``mtime`` and ``size``
+        contain the ``.st_mtime`` and ``st_size`` of the stat.
+
+    ``bytes``:
+        The contents of the file.
+
+    You may use the ``in`` operator with these objects (tested against
+    the contents of the file), and the ``.mustcontain()`` method.
+    """
+
+    file = True
+    dir = False
+
+    def __init__(self, base_path, path):
+        self.base_path = base_path
+        self.path = path
+        self.full = os.path.join(base_path, path)
+        self.stat = os.stat(self.full)
+        self.mtime = self.stat.st_mtime
+        self.size = self.stat.st_size
+        self._bytes = None
+
+    def bytes__get(self):
+        if self._bytes is None:
+            f = open(self.full, 'rb')
+            self._bytes = f.read()
+            f.close()
+        return self._bytes
+    bytes = property(bytes__get)
+
+    def __contains__(self, s):
+        return s in self.bytes
+
+    def mustcontain(self, s):
+        __tracebackhide__ = True
+        bytes = self.bytes
+        if s not in bytes:
+            print 'Could not find %r in:' % s
+            print bytes
+            assert s in bytes
+
+    def __repr__(self):
+        return '<%s %s:%s>' % (
+            self.__class__.__name__,
+            self.base_path, self.path)
+
+class Dir(File):
+
+    """
+    Represents a directory created by a command.
+    """
+
+    file = False
+    dir = True
+
+    def __init__(self, base_path, path):
+        self.base_path = base_path
+        self.path = path
+        self.full = os.path.join(base_path, path)
+        self.size = 'N/A'
+        self.mtime = 'N/A'
+
+    def __repr__(self):
+        return '<%s %s:%s>' % (
+            self.__class__.__name__,
+            self.base_path, self.path)
+
+    def bytes__get(self):
+        raise NotImplementedError(
+            "Directory %r doesn't have content" % self)
+
+    bytes = property(bytes__get)
+    
+
+def _space_prefix(pref, full, sep=None, indent=None, include_sep=True):
+    """
+    Anything shared by pref and full will be replaced with spaces
+    in full, and full returned.
+
+    Example::
+
+        >>> _space_prefix('/foo/bar', '/foo')
+        '    /bar'
+    """
+    if sep is None:
+        sep = os.path.sep
+    pref = pref.split(sep)
+    full = full.split(sep)
+    padding = []
+    while pref and full and pref[0] == full[0]:
+        if indent is None:
+            padding.append(' ' * (len(full[0]) + len(sep)))
+        else:
+            padding.append(' ' * indent)
+        full.pop(0)
+        pref.pop(0)
+    if padding:
+        if include_sep:
+            return ''.join(padding) + sep + sep.join(full)
+        else:
+            return ''.join(padding) + sep.join(full)
+    else:
+        return sep.join(full)
+
+def report_expected_diffs(diffs, colorize=False):
+    """
+    Takes the output of compare_expected, and returns a string
+    description of the differences.
+    """
+    if not diffs:
+        return 'No differences'
+    diffs = diffs.items()
+    diffs.sort()
+    s = []
+    last = ''
+    for path, desc in diffs:
+        t = _space_prefix(last, path, indent=4, include_sep=False)
+        if colorize:
+            t = color_line(t, 11)
+        last = path
+        if len(desc.splitlines()) > 1:
+            cur_indent = len(re.search(r'^[ ]*', t).group(0))
+            desc = indent(cur_indent+2, desc)
+            if colorize:
+                t += '\n'
+                for line in desc.splitlines():
+                    if line.strip().startswith('+'):
+                        line = color_line(line, 10)
+                    elif line.strip().startswith('-'):
+                        line = color_line(line, 9)
+                    else:
+                        line = color_line(line, 14)
+                    t += line+'\n'
+            else:
+                t += '\n' + desc
+        else:
+            t += ' '+desc
+        s.append(t)
+    s.append('Files with differences: %s' % len(diffs))
+    return '\n'.join(s)
+
+def color_code(foreground=None, background=None):
+    """
+    0  black
+    1  red
+    2  green
+    3  yellow
+    4  blue
+    5  magenta (purple)
+    6  cyan
+    7  white (gray)
+
+    Add 8 to get high-intensity
+    """
+    if foreground is None and background is None:
+        # Reset
+        return '\x1b[0m'
+    codes = []
+    if foreground is None:
+        codes.append('[39m')
+    elif foreground > 7:
+        codes.append('[1m')
+        codes.append('[%im' % (22+foreground))
+    else:
+        codes.append('[%im' % (30+foreground))
+    if background is None:
+        codes.append('[49m')
+    else:
+        codes.append('[%im' % (40+background))
+    return '\x1b' + '\x1b'.join(codes)
+
+def color_line(line, foreground=None, background=None):
+    match = re.search(r'^(\s*)', line)
+    return (match.group(1) + color_code(foreground, background)
+            + line[match.end():] + color_code())
+
+def indent(indent, text):
+    return '\n'.join(
+        [' '*indent + l for l in text.splitlines()])
+
+def show_diff(actual_content, expected_content):
+    actual_lines = [l.strip() for l in actual_content.splitlines()
+                    if l.strip()]
+    expected_lines = [l.strip() for l in expected_content.splitlines()
+                      if l.strip()]
+    if len(actual_lines) == len(expected_lines) == 1:
+        return '%r not %r' % (actual_lines[0], expected_lines[0])
+    if not actual_lines:
+        return 'Empty; should have:\n'+expected_content
+    import difflib
+    return '\n'.join(difflib.ndiff(actual_lines, expected_lines))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/prints.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/prints.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/prints.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,148 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware that displays everything that is printed inline in
+application pages.
+
+Anything printed during the request will get captured and included on
+the page.  It will usually be included as a floating element in the
+top right hand corner of the page.  If you want to override this
+you can include a tag in your template where it will be placed::
+
+  <pre id="paste-debug-prints"></pre>
+
+You might want to include ``style="white-space: normal"``, as all the
+whitespace will be quoted, and this allows the text to wrap if
+necessary.
+
+"""
+
+from cStringIO import StringIO
+import re
+import cgi
+from paste.util import threadedprint
+from paste import wsgilib
+from paste import response
+import sys
+
+_threadedprint_installed = False
+
+__all__ = ['PrintDebugMiddleware']
+
+class TeeFile(object):
+
+    def __init__(self, files):
+        self.files = files
+
+    def write(self, v):
+        if isinstance(v, unicode):
+            # WSGI is picky in this case
+            v = str(v)
+        for file in self.files:
+            file.write(v)
+
+class PrintDebugMiddleware(object):
+
+    """
+    This middleware captures all the printed statements, and inlines
+    them in HTML pages, so that you can see all the (debug-intended)
+    print statements in the page itself.
+
+    There are two keys added to the environment to control this:
+    ``environ['paste.printdebug_listeners']`` is a list of functions
+    that will be called everytime something is printed.
+
+    ``environ['paste.remove_printdebug']`` is a function that, if
+    called, will disable printing of output for that request.
+
+    If you have ``replace_stdout=True`` then stdout is replaced, not
+    captured.
+    """
+
+    log_template = (
+        '<pre style="width: 40%%; border: 2px solid #000; white-space: normal; '
+        'background-color: #ffd; color: #000; float: right;">'
+        '<b style="border-bottom: 1px solid #000">Log messages</b><br>'
+        '%s</pre>')
+
+    def __init__(self, app, global_conf=None, force_content_type=False,
+                 print_wsgi_errors=True, replace_stdout=False):
+        # @@: global_conf should be handled separately and only for
+        # the entry point
+        self.app = app
+        self.force_content_type = force_content_type
+        if isinstance(print_wsgi_errors, basestring):
+            from paste.deploy.converters import asbool
+            print_wsgi_errors = asbool(print_wsgi_errors)
+        self.print_wsgi_errors = print_wsgi_errors
+        self.replace_stdout = replace_stdout
+        self._threaded_print_stdout = None
+
+    def __call__(self, environ, start_response):
+        global _threadedprint_installed
+        if environ.get('paste.testing'):
+            # In a testing environment this interception isn't
+            # useful:
+            return self.app(environ, start_response)
+        if (not _threadedprint_installed
+            or self._threaded_print_stdout is not sys.stdout):
+            # @@: Not strictly threadsafe
+            _threadedprint_installed = True
+            threadedprint.install(leave_stdout=not self.replace_stdout)
+            self._threaded_print_stdout = sys.stdout
+        removed = []
+        def remove_printdebug():
+            removed.append(None)
+        environ['paste.remove_printdebug'] = remove_printdebug
+        logged = StringIO()
+        listeners = [logged]
+        environ['paste.printdebug_listeners'] = listeners
+        if self.print_wsgi_errors:
+            listeners.append(environ['wsgi.errors'])
+        replacement_stdout = TeeFile(listeners)
+        threadedprint.register(replacement_stdout)
+        try:
+            status, headers, body = wsgilib.intercept_output(
+                environ, self.app)
+            if status is None:
+                # Some error occurred
+                status = '500 Server Error'
+                headers = [('Content-type', 'text/html')]
+                start_response(status, headers)
+                if not body:
+                    body = 'An error occurred'
+            content_type = response.header_value(headers, 'content-type')
+            if (removed or
+                (not self.force_content_type and
+                 (not content_type
+                  or not content_type.startswith('text/html')))):
+                if replacement_stdout == logged:
+                    # Then the prints will be lost, unless...
+                    environ['wsgi.errors'].write(logged.getvalue())
+                start_response(status, headers)
+                return [body]
+            response.remove_header(headers, 'content-length')
+            body = self.add_log(body, logged.getvalue())
+            start_response(status, headers)
+            return [body]
+        finally:
+            threadedprint.deregister()
+
+    _body_re = re.compile(r'<body[^>]*>', re.I)
+    _explicit_re = re.compile(r'<pre\s*[^>]*id="paste-debug-prints".*?>',
+                              re.I+re.S)
+    
+    def add_log(self, html, log):
+        if not log:
+            return html
+        text = cgi.escape(log)
+        text = text.replace('\n', '<br>')
+        text = text.replace('  ', '&nbsp; ')
+        match = self._explicit_re.search(html)
+        if not match:
+            text = self.log_template % text
+            match = self._body_re.search(html)
+        if not match:
+            return text + html
+        else:
+            return html[:match.end()] + text + html[match.end():]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/profile.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/profile.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/profile.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,227 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware that profiles the request and displays profiling
+information at the bottom of each page.
+"""
+
+
+import sys
+import os
+import hotshot
+import hotshot.stats
+import threading
+import cgi
+import time
+from cStringIO import StringIO
+from paste import response
+
+__all__ = ['ProfileMiddleware', 'profile_decorator']
+
+class ProfileMiddleware(object):
+
+    """
+    Middleware that profiles all requests.
+
+    All HTML pages will have profiling information appended to them.
+    The data is isolated to that single request, and does not include
+    data from previous requests.
+
+    This uses the ``hotshot`` module, which affects performance of the
+    application.  It also runs in a single-threaded mode, so it is
+    only usable in development environments.
+    """
+
+    style = ('clear: both; background-color: #ff9; color: #000; '
+             'border: 2px solid #000; padding: 5px;')
+
+    def __init__(self, app, global_conf=None,
+                 log_filename='profile.log.tmp',
+                 limit=40):
+        self.app = app
+        self.lock = threading.Lock()
+        self.log_filename = log_filename
+        self.limit = limit
+
+    def __call__(self, environ, start_response):
+        catch_response = []
+        body = []
+        def replace_start_response(status, headers, exc_info=None):
+            catch_response.extend([status, headers])
+            start_response(status, headers, exc_info)
+            return body.append
+        def run_app():
+            app_iter = self.app(environ, replace_start_response)
+            try:
+                body.extend(app_iter)
+            finally:
+                if hasattr(app_iter, 'close'):
+                    app_iter.close()
+        self.lock.acquire()
+        try:
+            prof = hotshot.Profile(self.log_filename)
+            prof.addinfo('URL', environ.get('PATH_INFO', ''))
+            try:
+                prof.runcall(run_app)
+            finally:
+                prof.close()
+            body = ''.join(body)
+            headers = catch_response[1]
+            content_type = response.header_value(headers, 'content-type')
+            if content_type is None or not content_type.startswith('text/html'):
+                # We can't add info to non-HTML output
+                return [body]
+            stats = hotshot.stats.load(self.log_filename)
+            stats.strip_dirs()
+            stats.sort_stats('time', 'calls')
+            output = capture_output(stats.print_stats, self.limit)
+            output_callers = capture_output(
+                stats.print_callers, self.limit)
+            body += '<pre style="%s">%s\n%s</pre>' % (
+                self.style, cgi.escape(output), cgi.escape(output_callers))
+            return [body]
+        finally:
+            self.lock.release()
+
+def capture_output(func, *args, **kw):
+    # Not threadsafe! (that's okay when ProfileMiddleware uses it,
+    # though, since it synchronizes itself.)
+    out = StringIO()
+    old_stdout = sys.stdout
+    sys.stdout = out
+    try:
+        func(*args, **kw)
+    finally:
+        sys.stdout = old_stdout
+    return out.getvalue()
+
+def profile_decorator(**options):
+
+    """
+    Profile a single function call.
+    
+    Used around a function, like::
+
+        @profile_decorator(options...)
+        def ...
+
+    All calls to the function will be profiled.  The options are
+    all keywords, and are:
+
+        log_file:
+            The filename to log to (or ``'stdout'`` or ``'stderr'``).
+            Default: stderr.
+        display_limit:
+            Only show the top N items, default: 20.
+        sort_stats:
+            A list of string-attributes to sort on.  Default
+            ``('time', 'calls')``.
+        strip_dirs:
+            Strip directories/module names from files?  Default True.
+        add_info:
+            If given, this info will be added to the report (for your
+            own tracking).  Default: none.
+        log_filename:
+            The temporary filename to log profiling data to.  Default;
+            ``./profile_data.log.tmp``
+        no_profile:
+            If true, then don't actually profile anything.  Useful for
+            conditional profiling.
+    """
+
+    if options.get('no_profile'):
+        def decorator(func):
+            return func
+        return decorator
+    def decorator(func):
+        def replacement(*args, **kw):
+            return DecoratedProfile(func, **options)(*args, **kw)
+        return replacement
+    return decorator
+
+class DecoratedProfile(object):
+
+    lock = threading.Lock()
+
+    def __init__(self, func, **options):
+        self.func = func
+        self.options = options
+
+    def __call__(self, *args, **kw):
+        self.lock.acquire()
+        try:
+            return self.profile(self.func, *args, **kw)
+        finally:
+            self.lock.release()
+
+    def profile(self, func, *args, **kw):
+        ops = self.options
+        prof_filename = ops.get('log_filename', 'profile_data.log.tmp')
+        prof = hotshot.Profile(prof_filename)
+        prof.addinfo('Function Call',
+                     self.format_function(func, *args, **kw))
+        if ops.get('add_info'):
+            prof.addinfo('Extra info', ops['add_info'])
+        exc_info = None
+        try:
+            start_time = time.time()
+            try:
+                result = prof.runcall(func, *args, **kw)
+            except:
+                exc_info = sys.exc_info()
+            end_time = time.time()
+        finally:
+            prof.close()
+        stats = hotshot.stats.load(prof_filename)
+        os.unlink(prof_filename)
+        if ops.get('strip_dirs', True):
+            stats.strip_dirs()
+        stats.sort_stats(*ops.get('sort_stats', ('time', 'calls')))
+        display_limit = ops.get('display_limit', 20)
+        output = capture_output(stats.print_stats, display_limit)
+        output_callers = capture_output(
+            stats.print_callers, display_limit)
+        output_file = ops.get('log_file')
+        if output_file in (None, 'stderr'):
+            f = sys.stderr
+        elif output_file in ('-', 'stdout'):
+            f = sys.stdout
+        else:
+            f = open(output_file, 'a')
+            f.write('\n%s\n' % ('-'*60))
+            f.write('Date: %s\n' % time.strftime('%c'))
+        f.write('Function call: %s\n'
+                % self.format_function(func, *args, **kw))
+        f.write('Wall time: %0.2f seconds\n'
+                % (end_time - start_time))
+        f.write(output)
+        f.write(output_callers)
+        if output_file not in (None, '-', 'stdout', 'stderr'):
+            f.close()
+        if exc_info:
+            # We captured an exception earlier, now we re-raise it
+            raise exc_info[0], exc_info[1], exc_info[2]
+        return result
+        
+    def format_function(self, func, *args, **kw):
+        args = map(repr, args)
+        args.extend(
+            ['%s=%r' % (k, v) for k, v in kw.items()])
+        return '%s(%s)' % (func.__name__, ', '.join(args))
+            
+            
+def make_profile_middleware(
+    app, global_conf,
+    log_filename='profile.log.tmp',
+    limit=40):
+    """
+    Wrap the application in a component that will profile each
+    request.  The profiling data is then appended to the output
+    of each page.
+
+    Note that this serializes all requests (i.e., removing
+    concurrency).  Therefore never use this in production.
+    """
+    limit = int(limit)
+    return ProfileMiddleware(
+        app, log_filename=log_filename, limit=limit)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/testserver.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/testserver.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/testserver.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,93 @@
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+WSGI Test Server
+
+This builds upon paste.util.baseserver to customize it for regressions
+where using raw_interactive won't do.
+
+
+"""
+import time
+from paste.httpserver import *
+
+class WSGIRegressionServer(WSGIServer):
+    """
+    A threaded WSGIServer for use in regression testing.  To use this
+    module, call serve(application, regression=True), and then call
+    server.accept() to let it handle one request.  When finished, use
+    server.stop() to shutdown the server. Note that all pending requests
+    are processed before the server shuts down.
+    """
+    defaulttimeout = 10
+    def __init__ (self, *args, **kwargs):
+        WSGIServer.__init__(self, *args, **kwargs)
+        self.stopping = []
+        self.pending = []
+        self.timeout = self.defaulttimeout
+        # this is a local connection, be quick
+        self.socket.settimeout(2) 
+    def serve_forever(self):
+        from threading import Thread
+        thread = Thread(target=self.serve_pending)
+        thread.start()
+    def reset_expires(self):
+        if self.timeout:
+            self.expires = time.time() + self.timeout
+    def close_request(self, *args, **kwargs):
+        WSGIServer.close_request(self, *args, **kwargs)
+        self.pending.pop()
+        self.reset_expires()
+    def serve_pending(self):
+        self.reset_expires()
+        while not self.stopping or self.pending:
+            now = time.time()
+            if now > self.expires and self.timeout:
+                # note regression test doesn't handle exceptions in
+                # threads very well; so we just print and exit
+                print "\nWARNING: WSGIRegressionServer timeout exceeded\n"
+                break
+            if self.pending:
+                self.handle_request()
+            time.sleep(.1)
+    def stop(self):
+        """ stop the server (called from tester's thread) """
+        self.stopping.append(True)
+    def accept(self, count = 1):
+        """ accept another request (called from tester's thread) """
+        assert not self.stopping
+        [self.pending.append(True) for x in range(count)]
+
+def serve(application, host=None, port=None, handler=None):
+    server = WSGIRegressionServer(application, host, port, handler)
+    print "serving on %s:%s" % server.server_address
+    server.serve_forever()
+    return server
+
+if __name__ == '__main__':
+    import urllib
+    from paste.wsgilib import dump_environ
+    server = serve(dump_environ)
+    baseuri = ("http://%s:%s" % server.server_address)
+
+    def fetch(path):
+        # tell the server to humor exactly one more request
+        server.accept(1)
+        # not needed; but this is what you do if the server 
+        # may not respond in a resonable time period
+        import socket
+        socket.setdefaulttimeout(5)
+        # build a uri, fetch and return
+        return urllib.urlopen(baseuri + path).read()
+      
+    assert "PATH_INFO: /foo" in fetch("/foo")
+    assert "PATH_INFO: /womble" in fetch("/womble")
+
+    # ok, let's make one more final request...
+    server.accept(1)
+    # and then schedule a stop()
+    server.stop()
+    # and then... fetch it...
+    urllib.urlopen(baseuri)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/watchthreads.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/watchthreads.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/watchthreads.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,347 @@
+"""
+Watches the key ``paste.httpserver.thread_pool`` to see how many
+threads there are and report on any wedged threads.
+"""
+import sys
+import cgi
+import time
+import traceback
+from cStringIO import StringIO
+from thread import get_ident
+from paste import httpexceptions
+from paste.request import construct_url, parse_formvars
+from paste.util.template import HTMLTemplate, bunch
+
+page_template = HTMLTemplate('''
+<html>
+ <head>
+  <style type="text/css">
+   body {
+     font-family: sans-serif;
+   }
+   table.environ tr td {
+     border-bottom: #bbb 1px solid;
+   }
+   table.environ tr td.bottom {
+     border-bottom: none;
+   }
+   table.thread {
+     border: 1px solid #000;
+     margin-bottom: 1em;
+   }
+   table.thread tr td {
+     border-bottom: #999 1px solid;
+     padding-right: 1em;
+   }
+   table.thread tr td.bottom {
+     border-bottom: none;
+   }
+   table.thread tr.this_thread td {
+     background-color: #006;
+     color: #fff;
+   }
+   a.button {
+     background-color: #ddd;
+     border: #aaa outset 2px;
+     text-decoration: none;
+     margin-top: 10px;
+     font-size: 80%;
+     color: #000;
+   }
+   a.button:hover {
+     background-color: #eee;
+     border: #bbb outset 2px;
+   }
+   a.button:active {
+     border: #bbb inset 2px;
+   }
+  </style>
+  <title>{{title}}</title>
+ </head>
+ <body>
+  <h1>{{title}}</h1>
+  {{if kill_thread_id}}
+  <div style="background-color: #060; color: #fff;
+              border: 2px solid #000;">
+  Thread {{kill_thread_id}} killed
+  </div>
+  {{endif}}
+  <div>Pool size: {{nworkers}}
+       {{if actual_workers > nworkers}}
+         + {{actual_workers-nworkers}} extra
+       {{endif}}
+       ({{nworkers_used}} used including current request)<br>
+       idle: {{len(track_threads["idle"])}},
+       busy: {{len(track_threads["busy"])}},
+       hung: {{len(track_threads["hung"])}},
+       dying: {{len(track_threads["dying"])}},
+       zombie: {{len(track_threads["zombie"])}}</div>
+
+{{for thread in threads}}
+
+<table class="thread">
+ <tr {{if thread.thread_id == this_thread_id}}class="this_thread"{{endif}}>
+  <td>
+   <b>Thread</b>
+   {{if thread.thread_id == this_thread_id}}
+   (<i>this</i> request)
+   {{endif}}</td>
+  <td>
+   <b>{{thread.thread_id}}
+    {{if allow_kill}}
+    <form action="{{script_name}}/kill" method="POST"
+          style="display: inline">
+      <input type="hidden" name="thread_id" value="{{thread.thread_id}}">
+      <input type="submit" value="kill">
+    </form>
+    {{endif}}
+   </b>
+  </td>
+ </tr>
+ <tr>
+  <td>Time processing request</td>
+  <td>{{thread.time_html|html}}</td>
+ </tr>
+ <tr>
+  <td>URI</td>
+  <td>{{if thread.uri == 'unknown'}}
+      unknown
+      {{else}}<a href="{{thread.uri}}">{{thread.uri_short}}</a>
+      {{endif}}
+  </td>
+ <tr>
+  <td colspan="2" class="bottom">
+   <a href="#" class="button" style="width: 9em; display: block"
+      onclick="
+        var el = document.getElementById('environ-{{thread.thread_id}}');
+        if (el.style.display) {
+            el.style.display = '';
+            this.innerHTML = \'&#9662; Hide environ\';
+        } else {
+            el.style.display = 'none';
+            this.innerHTML = \'&#9656; Show environ\';
+        }
+        return false
+      ">&#9656; Show environ</a>
+   
+   <div id="environ-{{thread.thread_id}}" style="display: none">
+    {{if thread.environ:}}
+    <table class="environ">
+     {{for loop, item in looper(sorted(thread.environ.items()))}}
+     {{py:key, value=item}}
+     <tr>
+      <td {{if loop.last}}class="bottom"{{endif}}>{{key}}</td>
+      <td {{if loop.last}}class="bottom"{{endif}}>{{value}}</td>
+     </tr>
+     {{endfor}}
+    </table>
+    {{else}}
+    Thread is in process of starting
+    {{endif}}
+   </div>
+
+   {{if thread.traceback}}
+   <a href="#" class="button" style="width: 9em; display: block"
+      onclick="
+        var el = document.getElementById('traceback-{{thread.thread_id}}');
+        if (el.style.display) {
+            el.style.display = '';
+            this.innerHTML = \'&#9662; Hide traceback\';
+        } else {
+            el.style.display = 'none';
+            this.innerHTML = \'&#9656; Show traceback\';
+        }
+        return false
+      ">&#9656; Show traceback</a>
+
+    <div id="traceback-{{thread.thread_id}}" style="display: none">
+      <pre class="traceback">{{thread.traceback}}</pre>
+    </div>
+    {{endif}}
+
+  </td>
+ </tr>
+</table>
+
+{{endfor}}
+
+ </body>
+</html>
+''', name='watchthreads.page_template')
+
+class WatchThreads(object):
+
+    """
+    Application that watches the threads in ``paste.httpserver``,
+    showing the length each thread has been working on a request.
+
+    If allow_kill is true, then you can kill errant threads through
+    this application.
+
+    This application can expose private information (specifically in
+    the environment, like cookies), so it should be protected.
+    """
+
+    def __init__(self, allow_kill=False):
+        self.allow_kill = allow_kill
+
+    def __call__(self, environ, start_response):
+        if 'paste.httpserver.thread_pool' not in environ:
+            start_response('403 Forbidden', [('Content-type', 'text/plain')])
+            return ['You must use the threaded Paste HTTP server to use this application']
+        if environ.get('PATH_INFO') == '/kill':
+            return self.kill(environ, start_response)
+        else:
+            return self.show(environ, start_response)
+
+    def show(self, environ, start_response):
+        start_response('200 OK', [('Content-type', 'text/html')])
+        form = parse_formvars(environ)
+        if form.get('kill'):
+            kill_thread_id = form['kill']
+        else:
+            kill_thread_id = None
+        thread_pool = environ['paste.httpserver.thread_pool']
+        nworkers = thread_pool.nworkers
+        now = time.time()
+
+
+        workers = thread_pool.worker_tracker.items()
+        workers.sort(key=lambda v: v[1][0])
+        threads = []
+        for thread_id, (time_started, worker_environ) in workers:
+            thread = bunch()
+            threads.append(thread)
+            if worker_environ:
+                thread.uri = construct_url(worker_environ)
+            else:
+                thread.uri = 'unknown'
+            thread.thread_id = thread_id
+            thread.time_html = format_time(now-time_started)
+            thread.uri_short = shorten(thread.uri)
+            thread.environ = worker_environ
+            thread.traceback = traceback_thread(thread_id)
+            
+        page = page_template.substitute(
+            title="Thread Pool Worker Tracker",
+            nworkers=nworkers,
+            actual_workers=len(thread_pool.workers),
+            nworkers_used=len(workers),
+            script_name=environ['SCRIPT_NAME'],
+            kill_thread_id=kill_thread_id,
+            allow_kill=self.allow_kill,
+            threads=threads,
+            this_thread_id=get_ident(),
+            track_threads=thread_pool.track_threads())
+
+        return [page]
+
+    def kill(self, environ, start_response):
+        if not self.allow_kill:
+            exc = httpexceptions.HTTPForbidden(
+                'Killing threads has not been enabled.  Shame on you '
+                'for trying!')
+            return exc(environ, start_response)
+        vars = parse_formvars(environ)
+        thread_id = int(vars['thread_id'])
+        thread_pool = environ['paste.httpserver.thread_pool']
+        if thread_id not in thread_pool.worker_tracker:
+            exc = httpexceptions.PreconditionFailed(
+                'You tried to kill thread %s, but it is not working on '
+                'any requests' % thread_id)
+            return exc(environ, start_response)
+        thread_pool.kill_worker(thread_id)
+        script_name = environ['SCRIPT_NAME'] or '/'
+        exc = httpexceptions.HTTPFound(
+            headers=[('Location', script_name+'?kill=%s' % thread_id)])
+        return exc(environ, start_response)
+        
+def traceback_thread(thread_id):
+    """
+    Returns a plain-text traceback of the given thread, or None if it
+    can't get a traceback.
+    """
+    if not hasattr(sys, '_current_frames'):
+        # Only 2.5 has support for this, with this special function
+        return None
+    frames = sys._current_frames()
+    if not thread_id in frames:
+        return None
+    frame = frames[thread_id]
+    out = StringIO()
+    traceback.print_stack(frame, file=out)
+    return out.getvalue()
+
+hide_keys = ['paste.httpserver.thread_pool']
+
+def format_environ(environ):
+    if environ is None:
+        return environ_template.substitute(
+            key='---',
+            value='No environment registered for this thread yet')
+    environ_rows = []
+    for key, value in sorted(environ.items()):
+        if key in hide_keys:
+            continue
+        try:
+            if key.upper() != key:
+                value = repr(value)
+            environ_rows.append(
+                environ_template.substitute(
+                key=cgi.escape(str(key)),
+                value=cgi.escape(str(value))))
+        except Exception, e:
+            environ_rows.append(
+                environ_template.substitute(
+                key=cgi.escape(str(key)),
+                value='Error in <code>repr()</code>: %s' % e))
+    return ''.join(environ_rows)
+    
+def format_time(time_length):
+    if time_length >= 60*60:
+        # More than an hour
+        time_string = '%i:%02i:%02i' % (int(time_length/60/60),
+                                        int(time_length/60) % 60,
+                                        time_length % 60)
+    elif time_length >= 120:
+        time_string = '%i:%02i' % (int(time_length/60),
+                                   time_length % 60)
+    elif time_length > 60:
+        time_string = '%i sec' % time_length
+    elif time_length > 1:
+        time_string = '%0.1f sec' % time_length
+    else:
+        time_string = '%0.2f sec' % time_length
+    if time_length < 5:
+        return time_string
+    elif time_length < 120:
+        return '<span style="color: #900">%s</span>' % time_string
+    else:
+        return '<span style="background-color: #600; color: #fff">%s</span>' % time_string
+
+def shorten(s):
+    if len(s) > 60:
+        return s[:40]+'...'+s[-10:]
+    else:
+        return s
+
+def make_watch_threads(global_conf, allow_kill=False):
+    from paste.deploy.converters import asbool
+    return WatchThreads(allow_kill=asbool(allow_kill))
+make_watch_threads.__doc__ = WatchThreads.__doc__
+
+def make_bad_app(global_conf, pause=0):
+    pause = int(pause)
+    def bad_app(environ, start_response):
+        import thread
+        if pause:
+            time.sleep(pause)
+        else:
+            count = 0
+            while 1:
+                print "I'm alive %s (%s)" % (count, thread.get_ident())
+                time.sleep(10)
+                count += 1
+        start_response('200 OK', [('content-type', 'text/plain')])
+        return ['OK, paused %s seconds' % pause]
+    return bad_app

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/wdg_validate.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/wdg_validate.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/debug/wdg_validate.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,121 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware that tests the validity of all generated HTML using the
+`WDG HTML Validator <http://www.htmlhelp.com/tools/validator/>`_
+"""
+
+from cStringIO import StringIO
+try:
+    import subprocess
+except ImportError:
+    from paste.util import subprocess24 as subprocess
+from paste.response import header_value
+import re
+import cgi
+
+__all__ = ['WDGValidateMiddleware']
+
+class WDGValidateMiddleware(object):
+
+    """
+    Middleware that checks HTML and appends messages about the validity of
+    the HTML.  Uses: http://www.htmlhelp.com/tools/validator/ -- interacts
+    with the command line client.  Use the configuration ``wdg_path`` to
+    override the path (default: looks for ``validate`` in $PATH).
+
+    To install, in your web context's __init__.py::
+
+        def urlparser_wrap(environ, start_response, app):
+            return wdg_validate.WDGValidateMiddleware(app)(
+                environ, start_response)
+
+    Or in your configuration::
+
+        middleware.append('paste.wdg_validate.WDGValidateMiddleware')
+    """
+
+    _end_body_regex = re.compile(r'</body>', re.I)
+
+    def __init__(self, app, global_conf=None, wdg_path='validate'):
+        self.app = app
+        self.wdg_path = wdg_path
+
+    def __call__(self, environ, start_response):
+        output = StringIO()
+        response = []
+
+        def writer_start_response(status, headers, exc_info=None):
+            response.extend((status, headers))
+            start_response(status, headers, exc_info)
+            return output.write
+
+        app_iter = self.app(environ, writer_start_response)
+        try:
+            for s in app_iter:
+                output.write(s)
+        finally:
+            if hasattr(app_iter, 'close'):
+                app_iter.close()
+        page = output.getvalue()
+        status, headers = response
+        v = header_value(headers, 'content-type') or ''
+        if (not v.startswith('text/html')
+            and not v.startswith('text/xhtml')
+            and not v.startswith('application/xhtml')):
+            # Can't validate
+            # @@: Should validate CSS too... but using what?
+            return [page]
+        ops = []
+        if v.startswith('text/xhtml+xml'):
+            ops.append('--xml')
+        # @@: Should capture encoding too
+        html_errors = self.call_wdg_validate(
+            self.wdg_path, ops, page)
+        if html_errors:
+            page = self.add_error(page, html_errors)[0]
+            headers.remove(
+                     ('Content-Length',
+                      str(header_value(headers, 'content-length'))))
+            headers.append(('Content-Length', str(len(page))))
+        return [page]
+
+    def call_wdg_validate(self, wdg_path, ops, page):
+        if subprocess is None:
+            raise ValueError(
+                "This middleware requires the subprocess module from "
+                "Python 2.4")
+        proc = subprocess.Popen([wdg_path] + ops,
+                                shell=False,
+                                close_fds=True,
+                                stdout=subprocess.PIPE,
+                                stdin=subprocess.PIPE,
+                                stderr=subprocess.STDOUT)
+        stdout = proc.communicate(page)[0]
+        proc.wait()
+        return stdout
+
+    def add_error(self, html_page, html_errors):
+        add_text = ('<pre style="background-color: #ffd; color: #600; '
+                    'border: 1px solid #000;">%s</pre>'
+                    % cgi.escape(html_errors))
+        match = self._end_body_regex.search(html_page)
+        if match:
+            return [html_page[:match.start()]
+                    + add_text
+                    + html_page[match.start():]]
+        else:
+            return [html_page + add_text]
+
+def make_wdg_validate_middleware(
+    app, global_conf, wdg_path='validate'):
+    """
+    Wraps the application in the WDG validator from
+    http://www.htmlhelp.com/tools/validator/
+
+    Validation errors are appended to the text of each page.
+    You can configure this by giving the path to the validate
+    executable (by default picked up from $PATH)
+    """
+    return WDGValidateMiddleware(
+        app, global_conf, wdg_path=wdg_path)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/errordocument.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/errordocument.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/errordocument.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,383 @@
+# (c) 2005-2006 James Gardner <james at pythonweb.org>
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware to display error documents for certain status codes
+
+The middleware in this module can be used to intercept responses with
+specified status codes and internally forward the request to an appropriate
+URL where the content can be displayed to the user as an error document.
+"""
+
+import warnings
+import sys
+from urlparse import urlparse
+from paste.recursive import ForwardRequestException, RecursiveMiddleware, RecursionLoop
+from paste.util import converters
+from paste.response import replace_header
+
+def forward(app, codes):
+    """
+    Intercepts a response with a particular status code and returns the
+    content from a specified URL instead.
+
+    The arguments are:
+
+    ``app``
+        The WSGI application or middleware chain.
+
+    ``codes``
+        A dictionary of integer status codes and the URL to be displayed
+        if the response uses that code.
+
+    For example, you might want to create a static file to display a
+    "File Not Found" message at the URL ``/error404.html`` and then use
+    ``forward`` middleware to catch all 404 status codes and display the page
+    you created. In this example ``app`` is your exisiting WSGI
+    applicaiton::
+
+        from paste.errordocument import forward
+        app = forward(app, codes={404:'/error404.html'})
+
+    """
+    for code in codes:
+        if not isinstance(code, int):
+            raise TypeError('All status codes should be type int. '
+                '%s is not valid'%repr(code))
+
+    def error_codes_mapper(code, message, environ, global_conf, codes):
+        if codes.has_key(code):
+            return codes[code]
+        else:
+            return None
+
+    #return _StatusBasedRedirect(app, error_codes_mapper, codes=codes)
+    return RecursiveMiddleware(
+        StatusBasedForward(
+            app,
+            error_codes_mapper,
+            codes=codes,
+        )
+    )
+
+class StatusKeeper(object):
+    def __init__(self, app, status, url, headers):
+        self.app = app
+        self.status = status
+        self.url = url
+        self.headers = headers
+
+    def __call__(self, environ, start_response):
+        def keep_status_start_response(status, headers, exc_info=None):
+            for header, value in headers:
+                if header.lower() == 'set-cookie':
+                    self.headers.append((header, value))
+                else:
+                    replace_header(self.headers, header, value)
+            return start_response(self.status, self.headers, exc_info)
+        parts = self.url.split('?')
+        environ['PATH_INFO'] = parts[0]
+        if len(parts) > 1:
+            environ['QUERY_STRING'] = parts[1]
+        else:
+            environ['QUERY_STRING'] = ''
+        #raise Exception(self.url, self.status)
+        try:
+            return self.app(environ, keep_status_start_response)
+        except RecursionLoop, e:
+            environ['wsgi.errors'].write('Recursion error getting error page: %s\n' % e)
+            keep_status_start_response('500 Server Error', [('Content-type', 'text/plain')], sys.exc_info())
+            return ['Error: %s.  (Error page could not be fetched)'
+                    % self.status]
+
+
+class StatusBasedForward(object):
+    """
+    Middleware that lets you test a response against a custom mapper object to
+    programatically determine whether to internally forward to another URL and
+    if so, which URL to forward to.
+
+    If you don't need the full power of this middleware you might choose to use
+    the simpler ``forward`` middleware instead.
+
+    The arguments are:
+
+    ``app``
+        The WSGI application or middleware chain.
+
+    ``mapper``
+        A callable that takes a status code as the
+        first parameter, a message as the second, and accepts optional environ,
+        global_conf and named argments afterwards. It should return a
+        URL to forward to or ``None`` if the code is not to be intercepted.
+
+    ``global_conf``
+        Optional default configuration from your config file. If ``debug`` is
+        set to ``true`` a message will be written to ``wsgi.errors`` on each
+        internal forward stating the URL forwarded to.
+
+    ``**params``
+        Optional, any other configuration and extra arguments you wish to
+        pass which will in turn be passed back to the custom mapper object.
+
+    Here is an example where a ``404 File Not Found`` status response would be
+    redirected to the URL ``/error?code=404&message=File%20Not%20Found``. This
+    could be useful for passing the status code and message into another
+    application to display an error document:
+
+    .. code-block:: python
+
+        from paste.errordocument import StatusBasedForward
+        from paste.recursive import RecursiveMiddleware
+        from urllib import urlencode
+
+        def error_mapper(code, message, environ, global_conf, kw)
+            if code in [404, 500]:
+                params = urlencode({'message':message, 'code':code})
+                url = '/error?'%(params)
+                return url
+            else:
+                return None
+
+        app = RecursiveMiddleware(
+            StatusBasedForward(app, mapper=error_mapper),
+        )
+
+    """
+
+    def __init__(self, app, mapper, global_conf=None, **params):
+        if global_conf is None:
+            global_conf = {}
+        # @@: global_conf shouldn't really come in here, only in a
+        # separate make_status_based_forward function
+        if global_conf:
+            self.debug = converters.asbool(global_conf.get('debug', False))
+        else:
+            self.debug = False
+        self.application = app
+        self.mapper = mapper
+        self.global_conf = global_conf
+        self.params = params
+
+    def __call__(self, environ, start_response):
+        url = []
+        writer = []
+
+        def change_response(status, headers, exc_info=None):
+            status_code = status.split(' ')
+            try:
+                code = int(status_code[0])
+            except (ValueError, TypeError):
+                raise Exception(
+                    'StatusBasedForward middleware '
+                    'received an invalid status code %s'%repr(status_code[0])
+                )
+            message = ' '.join(status_code[1:])
+            new_url = self.mapper(
+                code,
+                message,
+                environ,
+                self.global_conf,
+                **self.params
+            )
+            if not (new_url == None or isinstance(new_url, str)):
+                raise TypeError(
+                    'Expected the url to internally '
+                    'redirect to in the StatusBasedForward mapper'
+                    'to be a string or None, not %r' % new_url)
+            if new_url:
+                url.append([new_url, status, headers])
+                # We have to allow the app to write stuff, even though
+                # we'll ignore it:
+                return [].append
+            else:
+                return start_response(status, headers, exc_info)
+
+        app_iter = self.application(environ, change_response)
+        if url:
+            if hasattr(app_iter, 'close'):
+                app_iter.close()
+
+            def factory(app):
+                return StatusKeeper(app, status=url[0][1], url=url[0][0],
+                                    headers=url[0][2])
+            raise ForwardRequestException(factory=factory)
+        else:
+            return app_iter
+
+def make_errordocument(app, global_conf, **kw):
+    """
+    Paste Deploy entry point to create a error document wrapper.
+
+    Use like::
+
+        [filter-app:main]
+        use = egg:Paste#errordocument
+        next = real-app
+        500 = /lib/msg/500.html
+        404 = /lib/msg/404.html
+    """
+    map = {}
+    for status, redir_loc in kw.items():
+        try:
+            status = int(status)
+        except ValueError:
+            raise ValueError('Bad status code: %r' % status)
+        map[status] = redir_loc
+    forwarder = forward(app, map)
+    return forwarder
+
+__pudge_all__ = [
+    'forward',
+    'make_errordocument',
+    'empty_error',
+    'make_empty_error',
+    'StatusBasedForward',
+]
+
+
+###############################################################################
+## Deprecated
+###############################################################################
+
+def custom_forward(app, mapper, global_conf=None, **kw):
+    """
+    Deprectated; use StatusBasedForward instead.
+    """
+    warnings.warn(
+        "errordocuments.custom_forward has been deprecated; please "
+        "use errordocuments.StatusBasedForward",
+        DeprecationWarning, 2)
+    if global_conf is None:
+        global_conf = {}
+    return _StatusBasedRedirect(app, mapper, global_conf, **kw)
+
+class _StatusBasedRedirect(object):
+    """
+    Deprectated; use StatusBasedForward instead.
+    """
+    def __init__(self, app, mapper, global_conf=None, **kw):
+
+        warnings.warn(
+            "errordocuments._StatusBasedRedirect has been deprecated; please "
+            "use errordocuments.StatusBasedForward",
+            DeprecationWarning, 2)
+
+        if global_conf is None:
+            global_conf = {}
+        self.application = app
+        self.mapper = mapper
+        self.global_conf = global_conf
+        self.kw = kw
+        self.fallback_template = """
+            <html>
+            <head>
+            <title>Error %(code)s</title>
+            </html>
+            <body>
+            <h1>Error %(code)s</h1>
+            <p>%(message)s</p>
+            <hr>
+            <p>
+                Additionally an error occurred trying to produce an
+                error document.  A description of the error was logged
+                to <tt>wsgi.errors</tt>.
+            </p>
+            </body>
+            </html>
+        """
+
+    def __call__(self, environ, start_response):
+        url = []
+        code_message = []
+        try:
+            def change_response(status, headers, exc_info=None):
+                new_url = None
+                parts = status.split(' ')
+                try:
+                    code = int(parts[0])
+                except (ValueError, TypeError):
+                    raise Exception(
+                        '_StatusBasedRedirect middleware '
+                        'received an invalid status code %s'%repr(parts[0])
+                    )
+                message = ' '.join(parts[1:])
+                new_url = self.mapper(
+                    code,
+                    message,
+                    environ,
+                    self.global_conf,
+                    self.kw
+                )
+                if not (new_url == None or isinstance(new_url, str)):
+                    raise TypeError(
+                        'Expected the url to internally '
+                        'redirect to in the _StatusBasedRedirect error_mapper'
+                        'to be a string or None, not %s'%repr(new_url)
+                    )
+                if new_url:
+                    url.append(new_url)
+                code_message.append([code, message])
+                return start_response(status, headers, exc_info)
+            app_iter = self.application(environ, change_response)
+        except:
+            try:
+                import sys
+                error = str(sys.exc_info()[1])
+            except:
+                error = ''
+            try:
+                code, message = code_message[0]
+            except:
+                code, message = ['', '']
+            environ['wsgi.errors'].write(
+                'Error occurred in _StatusBasedRedirect '
+                'intercepting the response: '+str(error)
+            )
+            return [self.fallback_template
+                    % {'message': message, 'code': code}]
+        else:
+            if url:
+                url_ = url[0]
+                new_environ = {}
+                for k, v in environ.items():
+                    if k != 'QUERY_STRING':
+                        new_environ['QUERY_STRING'] = urlparse(url_)[4]
+                    else:
+                        new_environ[k] = v
+                class InvalidForward(Exception):
+                    pass
+                def eat_start_response(status, headers, exc_info=None):
+                    """
+                    We don't want start_response to do anything since it
+                    has already been called
+                    """
+                    if status[:3] != '200':
+                        raise InvalidForward(
+                            "The URL %s to internally forward "
+                            "to in order to create an error document did not "
+                            "return a '200' status code." % url_
+                        )
+                forward = environ['paste.recursive.forward']
+                old_start_response = forward.start_response
+                forward.start_response = eat_start_response
+                try:
+                    app_iter = forward(url_, new_environ)
+                except InvalidForward, e:
+                    code, message = code_message[0]
+                    environ['wsgi.errors'].write(
+                        'Error occurred in '
+                        '_StatusBasedRedirect redirecting '
+                        'to new URL: '+str(url[0])
+                    )
+                    return [
+                        self.fallback_template%{
+                            'message':message,
+                            'code':code,
+                        }
+                    ]
+                else:
+                    forward.start_response = old_start_response
+                    return app_iter
+            else:
+                return app_iter

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+An exception handler for interactive debugging
+"""
+from paste.evalexception.middleware import EvalException
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/evalcontext.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/evalcontext.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/evalcontext.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,68 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+from cStringIO import StringIO
+import traceback
+import threading
+import pdb
+import sys
+
+exec_lock = threading.Lock()
+
+class EvalContext(object):
+
+    """
+    Class that represents a interactive interface.  It has its own
+    namespace.  Use eval_context.exec_expr(expr) to run commands; the
+    output of those commands is returned, as are print statements.
+
+    This is essentially what doctest does, and is taken directly from
+    doctest.
+    """
+
+    def __init__(self, namespace, globs):
+        self.namespace = namespace
+        self.globs = globs
+
+    def exec_expr(self, s):
+        out = StringIO()
+        exec_lock.acquire()
+        save_stdout = sys.stdout
+        try:
+            debugger = _OutputRedirectingPdb(save_stdout)
+            debugger.reset()
+            pdb.set_trace = debugger.set_trace
+            sys.stdout = out
+            try:
+                code = compile(s, '<web>', "single", 0, 1)
+                exec code in self.namespace, self.globs
+                debugger.set_continue()
+            except KeyboardInterrupt:
+                raise
+            except:
+                traceback.print_exc(file=out)
+                debugger.set_continue()
+        finally:
+            sys.stdout = save_stdout
+            exec_lock.release()
+        return out.getvalue()
+
+# From doctest
+class _OutputRedirectingPdb(pdb.Pdb):
+    """
+    A specialized version of the python debugger that redirects stdout
+    to a given stream when interacting with the user.  Stdout is *not*
+    redirected when traced code is executed.
+    """
+    def __init__(self, out):
+        self.__out = out
+        pdb.Pdb.__init__(self)
+
+    def trace_dispatch(self, *args):
+        # Redirect stdout to the given stream.
+        save_stdout = sys.stdout
+        sys.stdout = self.__out
+        # Call Pdb's trace dispatch method.
+        try:
+            return pdb.Pdb.trace_dispatch(self, *args)
+        finally:
+            sys.stdout = save_stdout

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/MochiKit.packed.js
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/MochiKit.packed.js	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/MochiKit.packed.js	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7829 @@
+/***
+
+    MochiKit.MochiKit 1.4.2 : PACKED VERSION
+
+    THIS FILE IS AUTOMATICALLY GENERATED.  If creating patches, please
+    diff against the source tree, not this file.
+
+    See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+    (c) 2005 Bob Ippolito.  All rights Reserved.
+
+***/
+
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.Base");
+}
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.Base)=="undefined"){
+MochiKit.Base={};
+}
+if(typeof (MochiKit.__export__)=="undefined"){
+MochiKit.__export__=(MochiKit.__compat__||(typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined"));
+}
+MochiKit.Base.VERSION="1.4.2";
+MochiKit.Base.NAME="MochiKit.Base";
+MochiKit.Base.update=function(_1,_2){
+if(_1===null||_1===undefined){
+_1={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+_1[k]=o[k];
+}
+}
+}
+return _1;
+};
+MochiKit.Base.update(MochiKit.Base,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},camelize:function(_6){
+var _7=_6.split("-");
+var cc=_7[0];
+for(var i=1;i<_7.length;i++){
+cc+=_7[i].charAt(0).toUpperCase()+_7[i].substring(1);
+}
+return cc;
+},counter:function(n){
+if(arguments.length===0){
+n=1;
+}
+return function(){
+return n++;
+};
+},clone:function(_b){
+var me=arguments.callee;
+if(arguments.length==1){
+me.prototype=_b;
+return new me();
+}
+},_deps:function(_d,_e){
+if(!(_d in MochiKit)){
+MochiKit[_d]={};
+}
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit."+_d);
+}
+for(var i=0;i<_e.length;i++){
+if(typeof (dojo)!="undefined"){
+dojo.require("MochiKit."+_e[i]);
+}
+if(typeof (JSAN)!="undefined"){
+JSAN.use("MochiKit."+_e[i],[]);
+}
+if(!(_e[i] in MochiKit)){
+throw "MochiKit."+_d+" depends on MochiKit."+_e[i]+"!";
+}
+}
+},_flattenArray:function(res,lst){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(o instanceof Array){
+arguments.callee(res,o);
+}else{
+res.push(o);
+}
+}
+return res;
+},flattenArray:function(lst){
+return MochiKit.Base._flattenArray([],lst);
+},flattenArguments:function(lst){
+var res=[];
+var m=MochiKit.Base;
+var _18=m.extend(null,arguments);
+while(_18.length){
+var o=_18.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+for(var i=o.length-1;i>=0;i--){
+_18.unshift(o[i]);
+}
+}else{
+res.push(o);
+}
+}
+return res;
+},extend:function(_1b,obj,_1d){
+if(!_1d){
+_1d=0;
+}
+if(obj){
+var l=obj.length;
+if(typeof (l)!="number"){
+if(typeof (MochiKit.Iter)!="undefined"){
+obj=MochiKit.Iter.list(obj);
+l=obj.length;
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(!_1b){
+_1b=[];
+}
+for(var i=_1d;i<l;i++){
+_1b.push(obj[i]);
+}
+}
+return _1b;
+},updatetree:function(_20,obj){
+if(_20===null||_20===undefined){
+_20={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="undefined"&&o!==null){
+for(var k in o){
+var v=o[k];
+if(typeof (_20[k])=="object"&&typeof (v)=="object"){
+arguments.callee(_20[k],v);
+}else{
+_20[k]=v;
+}
+}
+}
+}
+return _20;
+},setdefault:function(_26,obj){
+if(_26===null||_26===undefined){
+_26={};
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+for(var k in o){
+if(!(k in _26)){
+_26[k]=o[k];
+}
+}
+}
+return _26;
+},keys:function(obj){
+var _2c=[];
+for(var _2d in obj){
+_2c.push(_2d);
+}
+return _2c;
+},values:function(obj){
+var _2f=[];
+for(var _30 in obj){
+_2f.push(obj[_30]);
+}
+return _2f;
+},items:function(obj){
+var _32=[];
+var e;
+for(var _34 in obj){
+var v;
+try{
+v=obj[_34];
+}
+catch(e){
+continue;
+}
+_32.push([_34,v]);
+}
+return _32;
+},_newNamedError:function(_36,_37,_38){
+_38.prototype=new MochiKit.Base.NamedError(_36.NAME+"."+_37);
+_36[_37]=_38;
+},operator:{truth:function(a){
+return !!a;
+},lognot:function(a){
+return !a;
+},identity:function(a){
+return a;
+},not:function(a){
+return ~a;
+},neg:function(a){
+return -a;
+},add:function(a,b){
+return a+b;
+},sub:function(a,b){
+return a-b;
+},div:function(a,b){
+return a/b;
+},mod:function(a,b){
+return a%b;
+},mul:function(a,b){
+return a*b;
+},and:function(a,b){
+return a&b;
+},or:function(a,b){
+return a|b;
+},xor:function(a,b){
+return a^b;
+},lshift:function(a,b){
+return a<<b;
+},rshift:function(a,b){
+return a>>b;
+},zrshift:function(a,b){
+return a>>>b;
+},eq:function(a,b){
+return a==b;
+},ne:function(a,b){
+return a!=b;
+},gt:function(a,b){
+return a>b;
+},ge:function(a,b){
+return a>=b;
+},lt:function(a,b){
+return a<b;
+},le:function(a,b){
+return a<=b;
+},seq:function(a,b){
+return a===b;
+},sne:function(a,b){
+return a!==b;
+},ceq:function(a,b){
+return MochiKit.Base.compare(a,b)===0;
+},cne:function(a,b){
+return MochiKit.Base.compare(a,b)!==0;
+},cgt:function(a,b){
+return MochiKit.Base.compare(a,b)==1;
+},cge:function(a,b){
+return MochiKit.Base.compare(a,b)!=-1;
+},clt:function(a,b){
+return MochiKit.Base.compare(a,b)==-1;
+},cle:function(a,b){
+return MochiKit.Base.compare(a,b)!=1;
+},logand:function(a,b){
+return a&&b;
+},logor:function(a,b){
+return a||b;
+},contains:function(a,b){
+return b in a;
+}},forwardCall:function(_76){
+return function(){
+return this[_76].apply(this,arguments);
+};
+},itemgetter:function(_77){
+return function(arg){
+return arg[_77];
+};
+},typeMatcher:function(){
+var _79={};
+for(var i=0;i<arguments.length;i++){
+var typ=arguments[i];
+_79[typ]=typ;
+}
+return function(){
+for(var i=0;i<arguments.length;i++){
+if(!(typeof (arguments[i]) in _79)){
+return false;
+}
+}
+return true;
+};
+},isNull:function(){
+for(var i=0;i<arguments.length;i++){
+if(arguments[i]!==null){
+return false;
+}
+}
+return true;
+},isUndefinedOrNull:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(typeof (o)=="undefined"||o===null)){
+return false;
+}
+}
+return true;
+},isEmpty:function(obj){
+return !MochiKit.Base.isNotEmpty.apply(this,arguments);
+},isNotEmpty:function(obj){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(!(o&&o.length)){
+return false;
+}
+}
+return true;
+},isArrayLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+var typ=typeof (o);
+if((typ!="object"&&!(typ=="function"&&typeof (o.item)=="function"))||o===null||typeof (o.length)!="number"||o.nodeType===3||o.nodeType===4){
+return false;
+}
+}
+return true;
+},isDateLike:function(){
+for(var i=0;i<arguments.length;i++){
+var o=arguments[i];
+if(typeof (o)!="object"||o===null||typeof (o.getTime)!="function"){
+return false;
+}
+}
+return true;
+},xmap:function(fn){
+if(fn===null){
+return MochiKit.Base.extend(null,arguments,1);
+}
+var _8a=[];
+for(var i=1;i<arguments.length;i++){
+_8a.push(fn(arguments[i]));
+}
+return _8a;
+},map:function(fn,lst){
+var m=MochiKit.Base;
+var itr=MochiKit.Iter;
+var _90=m.isArrayLike;
+if(arguments.length<=2){
+if(!_90(lst)){
+if(itr){
+lst=itr.list(lst);
+if(fn===null){
+return lst;
+}
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+return m.extend(null,lst);
+}
+var _91=[];
+for(var i=0;i<lst.length;i++){
+_91.push(fn(lst[i]));
+}
+return _91;
+}else{
+if(fn===null){
+fn=Array;
+}
+var _93=null;
+for(i=1;i<arguments.length;i++){
+if(!_90(arguments[i])){
+if(itr){
+return itr.list(itr.imap.apply(null,arguments));
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+var l=arguments[i].length;
+if(_93===null||_93>l){
+_93=l;
+}
+}
+_91=[];
+for(i=0;i<_93;i++){
+var _95=[];
+for(var j=1;j<arguments.length;j++){
+_95.push(arguments[j][i]);
+}
+_91.push(fn.apply(this,_95));
+}
+return _91;
+}
+},xfilter:function(fn){
+var _98=[];
+if(fn===null){
+fn=MochiKit.Base.operator.truth;
+}
+for(var i=1;i<arguments.length;i++){
+var o=arguments[i];
+if(fn(o)){
+_98.push(o);
+}
+}
+return _98;
+},filter:function(fn,lst,_9d){
+var _9e=[];
+var m=MochiKit.Base;
+if(!m.isArrayLike(lst)){
+if(MochiKit.Iter){
+lst=MochiKit.Iter.list(lst);
+}else{
+throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+}
+}
+if(fn===null){
+fn=m.operator.truth;
+}
+if(typeof (Array.prototype.filter)=="function"){
+return Array.prototype.filter.call(lst,fn,_9d);
+}else{
+if(typeof (_9d)=="undefined"||_9d===null){
+for(var i=0;i<lst.length;i++){
+var o=lst[i];
+if(fn(o)){
+_9e.push(o);
+}
+}
+}else{
+for(i=0;i<lst.length;i++){
+o=lst[i];
+if(fn.call(_9d,o)){
+_9e.push(o);
+}
+}
+}
+}
+return _9e;
+},_wrapDumbFunction:function(_a2){
+return function(){
+switch(arguments.length){
+case 0:
+return _a2();
+case 1:
+return _a2(arguments[0]);
+case 2:
+return _a2(arguments[0],arguments[1]);
+case 3:
+return _a2(arguments[0],arguments[1],arguments[2]);
+}
+var _a3=[];
+for(var i=0;i<arguments.length;i++){
+_a3.push("arguments["+i+"]");
+}
+return eval("(func("+_a3.join(",")+"))");
+};
+},methodcaller:function(_a5){
+var _a6=MochiKit.Base.extend(null,arguments,1);
+if(typeof (_a5)=="function"){
+return function(obj){
+return _a5.apply(obj,_a6);
+};
+}else{
+return function(obj){
+return obj[_a5].apply(obj,_a6);
+};
+}
+},method:function(_a9,_aa){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([_aa,_a9],arguments,2));
+},compose:function(f1,f2){
+var _ae=[];
+var m=MochiKit.Base;
+if(arguments.length===0){
+throw new TypeError("compose() requires at least one argument");
+}
+for(var i=0;i<arguments.length;i++){
+var fn=arguments[i];
+if(typeof (fn)!="function"){
+throw new TypeError(m.repr(fn)+" is not a function");
+}
+_ae.push(fn);
+}
+return function(){
+var _b2=arguments;
+for(var i=_ae.length-1;i>=0;i--){
+_b2=[_ae[i].apply(this,_b2)];
+}
+return _b2[0];
+};
+},bind:function(_b4,_b5){
+if(typeof (_b4)=="string"){
+_b4=_b5[_b4];
+}
+var _b6=_b4.im_func;
+var _b7=_b4.im_preargs;
+var _b8=_b4.im_self;
+var m=MochiKit.Base;
+if(typeof (_b4)=="function"&&typeof (_b4.apply)=="undefined"){
+_b4=m._wrapDumbFunction(_b4);
+}
+if(typeof (_b6)!="function"){
+_b6=_b4;
+}
+if(typeof (_b5)!="undefined"){
+_b8=_b5;
+}
+if(typeof (_b7)=="undefined"){
+_b7=[];
+}else{
+_b7=_b7.slice();
+}
+m.extend(_b7,arguments,2);
+var _ba=function(){
+var _bb=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_bb=m.concat(me.im_preargs,_bb);
+}
+var _bd=me.im_self;
+if(!_bd){
+_bd=this;
+}
+return me.im_func.apply(_bd,_bb);
+};
+_ba.im_self=_b8;
+_ba.im_func=_b6;
+_ba.im_preargs=_b7;
+return _ba;
+},bindLate:function(_be,_bf){
+var m=MochiKit.Base;
+if(typeof (_be)!="string"){
+return m.bind.apply(this,arguments);
+}
+var _c1=m.extend([],arguments,2);
+var _c2=function(){
+var _c3=arguments;
+var me=arguments.callee;
+if(me.im_preargs.length>0){
+_c3=m.concat(me.im_preargs,_c3);
+}
+var _c5=me.im_self;
+if(!_c5){
+_c5=this;
+}
+return _c5[me.im_func].apply(_c5,_c3);
+};
+_c2.im_self=_bf;
+_c2.im_func=_be;
+_c2.im_preargs=_c1;
+return _c2;
+},bindMethods:function(_c6){
+var _c7=MochiKit.Base.bind;
+for(var k in _c6){
+var _c9=_c6[k];
+if(typeof (_c9)=="function"){
+_c6[k]=_c7(_c9,_c6);
+}
+}
+},registerComparator:function(_ca,_cb,_cc,_cd){
+MochiKit.Base.comparatorRegistry.register(_ca,_cb,_cc,_cd);
+},_primitives:{"boolean":true,"string":true,"number":true},compare:function(a,b){
+if(a==b){
+return 0;
+}
+var _d0=(typeof (a)=="undefined"||a===null);
+var _d1=(typeof (b)=="undefined"||b===null);
+if(_d0&&_d1){
+return 0;
+}else{
+if(_d0){
+return -1;
+}else{
+if(_d1){
+return 1;
+}
+}
+}
+var m=MochiKit.Base;
+var _d3=m._primitives;
+if(!(typeof (a) in _d3&&typeof (b) in _d3)){
+try{
+return m.comparatorRegistry.match(a,b);
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+}
+if(a<b){
+return -1;
+}else{
+if(a>b){
+return 1;
+}
+}
+var _d4=m.repr;
+throw new TypeError(_d4(a)+" and "+_d4(b)+" can not be compared");
+},compareDateLike:function(a,b){
+return MochiKit.Base.compare(a.getTime(),b.getTime());
+},compareArrayLike:function(a,b){
+var _d9=MochiKit.Base.compare;
+var _da=a.length;
+var _db=0;
+if(_da>b.length){
+_db=1;
+_da=b.length;
+}else{
+if(_da<b.length){
+_db=-1;
+}
+}
+for(var i=0;i<_da;i++){
+var cmp=_d9(a[i],b[i]);
+if(cmp){
+return cmp;
+}
+}
+return _db;
+},registerRepr:function(_de,_df,_e0,_e1){
+MochiKit.Base.reprRegistry.register(_de,_df,_e0,_e1);
+},repr:function(o){
+if(typeof (o)=="undefined"){
+return "undefined";
+}else{
+if(o===null){
+return "null";
+}
+}
+try{
+if(typeof (o.__repr__)=="function"){
+return o.__repr__();
+}else{
+if(typeof (o.repr)=="function"&&o.repr!=arguments.callee){
+return o.repr();
+}
+}
+return MochiKit.Base.reprRegistry.match(o);
+}
+catch(e){
+if(typeof (o.NAME)=="string"&&(o.toString==Function.prototype.toString||o.toString==Object.prototype.toString)){
+return o.NAME;
+}
+}
+try{
+var _e3=(o+"");
+}
+catch(e){
+return "["+typeof (o)+"]";
+}
+if(typeof (o)=="function"){
+_e3=_e3.replace(/^\s+/,"").replace(/\s+/g," ");
+_e3=_e3.replace(/,(\S)/,", $1");
+var idx=_e3.indexOf("{");
+if(idx!=-1){
+_e3=_e3.substr(0,idx)+"{...}";
+}
+}
+return _e3;
+},reprArrayLike:function(o){
+var m=MochiKit.Base;
+return "["+m.map(m.repr,o).join(", ")+"]";
+},reprString:function(o){
+return ("\""+o.replace(/(["\\])/g,"\\$1")+"\"").replace(/[\f]/g,"\\f").replace(/[\b]/g,"\\b").replace(/[\n]/g,"\\n").replace(/[\t]/g,"\\t").replace(/[\v]/g,"\\v").replace(/[\r]/g,"\\r");
+},reprNumber:function(o){
+return o+"";
+},registerJSON:function(_e9,_ea,_eb,_ec){
+MochiKit.Base.jsonRegistry.register(_e9,_ea,_eb,_ec);
+},evalJSON:function(){
+return eval("("+MochiKit.Base._filterJSON(arguments[0])+")");
+},_filterJSON:function(s){
+var m=s.match(/^\s*\/\*(.*)\*\/\s*$/);
+if(m){
+return m[1];
+}
+return s;
+},serializeJSON:function(o){
+var _f0=typeof (o);
+if(_f0=="number"||_f0=="boolean"){
+return o+"";
+}else{
+if(o===null){
+return "null";
+}else{
+if(_f0=="string"){
+var res="";
+for(var i=0;i<o.length;i++){
+var c=o.charAt(i);
+if(c=="\""){
+res+="\\\"";
+}else{
+if(c=="\\"){
+res+="\\\\";
+}else{
+if(c=="\b"){
+res+="\\b";
+}else{
+if(c=="\f"){
+res+="\\f";
+}else{
+if(c=="\n"){
+res+="\\n";
+}else{
+if(c=="\r"){
+res+="\\r";
+}else{
+if(c=="\t"){
+res+="\\t";
+}else{
+if(o.charCodeAt(i)<=31){
+var hex=o.charCodeAt(i).toString(16);
+if(hex.length<2){
+hex="0"+hex;
+}
+res+="\\u00"+hex.toUpperCase();
+}else{
+res+=c;
+}
+}
+}
+}
+}
+}
+}
+}
+}
+return "\""+res+"\"";
+}
+}
+}
+var me=arguments.callee;
+var _f6;
+if(typeof (o.__json__)=="function"){
+_f6=o.__json__();
+if(o!==_f6){
+return me(_f6);
+}
+}
+if(typeof (o.json)=="function"){
+_f6=o.json();
+if(o!==_f6){
+return me(_f6);
+}
+}
+if(_f0!="function"&&typeof (o.length)=="number"){
+var res=[];
+for(var i=0;i<o.length;i++){
+var val=me(o[i]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(val);
+}
+return "["+res.join(", ")+"]";
+}
+var m=MochiKit.Base;
+try{
+_f6=m.jsonRegistry.match(o);
+if(o!==_f6){
+return me(_f6);
+}
+}
+catch(e){
+if(e!=m.NotFound){
+throw e;
+}
+}
+if(_f0=="undefined"){
+throw new TypeError("undefined can not be serialized as JSON");
+}
+if(_f0=="function"){
+return null;
+}
+res=[];
+for(var k in o){
+var _fa;
+if(typeof (k)=="number"){
+_fa="\""+k+"\"";
+}else{
+if(typeof (k)=="string"){
+_fa=me(k);
+}else{
+continue;
+}
+}
+val=me(o[k]);
+if(typeof (val)!="string"){
+continue;
+}
+res.push(_fa+":"+val);
+}
+return "{"+res.join(", ")+"}";
+},objEqual:function(a,b){
+return (MochiKit.Base.compare(a,b)===0);
+},arrayEqual:function(_fd,arr){
+if(_fd.length!=arr.length){
+return false;
+}
+return (MochiKit.Base.compare(_fd,arr)===0);
+},concat:function(){
+var _ff=[];
+var _100=MochiKit.Base.extend;
+for(var i=0;i<arguments.length;i++){
+_100(_ff,arguments[i]);
+}
+return _ff;
+},keyComparator:function(key){
+var m=MochiKit.Base;
+var _104=m.compare;
+if(arguments.length==1){
+return function(a,b){
+return _104(a[key],b[key]);
+};
+}
+var _107=m.extend(null,arguments);
+return function(a,b){
+var rval=0;
+for(var i=0;(rval===0)&&(i<_107.length);i++){
+var key=_107[i];
+rval=_104(a[key],b[key]);
+}
+return rval;
+};
+},reverseKeyComparator:function(key){
+var _10e=MochiKit.Base.keyComparator.apply(this,arguments);
+return function(a,b){
+return _10e(b,a);
+};
+},partial:function(func){
+var m=MochiKit.Base;
+return m.bind.apply(this,m.extend([func,undefined],arguments,1));
+},listMinMax:function(_113,lst){
+if(lst.length===0){
+return null;
+}
+var cur=lst[0];
+var _116=MochiKit.Base.compare;
+for(var i=1;i<lst.length;i++){
+var o=lst[i];
+if(_116(o,cur)==_113){
+cur=o;
+}
+}
+return cur;
+},objMax:function(){
+return MochiKit.Base.listMinMax(1,arguments);
+},objMin:function(){
+return MochiKit.Base.listMinMax(-1,arguments);
+},findIdentical:function(lst,_11a,_11b,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_11b)=="undefined"||_11b===null){
+_11b=0;
+}
+for(var i=_11b;i<end;i++){
+if(lst[i]===_11a){
+return i;
+}
+}
+return -1;
+},mean:function(){
+var sum=0;
+var m=MochiKit.Base;
+var args=m.extend(null,arguments);
+var _121=args.length;
+while(args.length){
+var o=args.shift();
+if(o&&typeof (o)=="object"&&typeof (o.length)=="number"){
+_121+=o.length-1;
+for(var i=o.length-1;i>=0;i--){
+sum+=o[i];
+}
+}else{
+sum+=o;
+}
+}
+if(_121<=0){
+throw new TypeError("mean() requires at least one argument");
+}
+return sum/_121;
+},median:function(){
+var data=MochiKit.Base.flattenArguments(arguments);
+if(data.length===0){
+throw new TypeError("median() requires at least one argument");
+}
+data.sort(compare);
+if(data.length%2==0){
+var _125=data.length/2;
+return (data[_125]+data[_125-1])/2;
+}else{
+return data[(data.length-1)/2];
+}
+},findValue:function(lst,_127,_128,end){
+if(typeof (end)=="undefined"||end===null){
+end=lst.length;
+}
+if(typeof (_128)=="undefined"||_128===null){
+_128=0;
+}
+var cmp=MochiKit.Base.compare;
+for(var i=_128;i<end;i++){
+if(cmp(lst[i],_127)===0){
+return i;
+}
+}
+return -1;
+},nodeWalk:function(node,_12d){
+var _12e=[node];
+var _12f=MochiKit.Base.extend;
+while(_12e.length){
+var res=_12d(_12e.shift());
+if(res){
+_12f(_12e,res);
+}
+}
+},nameFunctions:function(_131){
+var base=_131.NAME;
+if(typeof (base)=="undefined"){
+base="";
+}else{
+base=base+".";
+}
+for(var name in _131){
+var o=_131[name];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+name;
+}
+catch(e){
+}
+}
+}
+},queryString:function(_135,_136){
+if(typeof (MochiKit.DOM)!="undefined"&&arguments.length==1&&(typeof (_135)=="string"||(typeof (_135.nodeType)!="undefined"&&_135.nodeType>0))){
+var kv=MochiKit.DOM.formContents(_135);
+_135=kv[0];
+_136=kv[1];
+}else{
+if(arguments.length==1){
+if(typeof (_135.length)=="number"&&_135.length==2){
+return arguments.callee(_135[0],_135[1]);
+}
+var o=_135;
+_135=[];
+_136=[];
+for(var k in o){
+var v=o[k];
+if(typeof (v)=="function"){
+continue;
+}else{
+if(MochiKit.Base.isArrayLike(v)){
+for(var i=0;i<v.length;i++){
+_135.push(k);
+_136.push(v[i]);
+}
+}else{
+_135.push(k);
+_136.push(v);
+}
+}
+}
+}
+}
+var rval=[];
+var len=Math.min(_135.length,_136.length);
+var _13e=MochiKit.Base.urlEncode;
+for(var i=0;i<len;i++){
+v=_136[i];
+if(typeof (v)!="undefined"&&v!==null){
+rval.push(_13e(_135[i])+"="+_13e(v));
+}
+}
+return rval.join("&");
+},parseQueryString:function(_13f,_140){
+var qstr=(_13f.charAt(0)=="?")?_13f.substring(1):_13f;
+var _142=qstr.replace(/\+/g,"%20").split(/\&amp\;|\&\#38\;|\&#x26;|\&/);
+var o={};
+var _144;
+if(typeof (decodeURIComponent)!="undefined"){
+_144=decodeURIComponent;
+}else{
+_144=unescape;
+}
+if(_140){
+for(var i=0;i<_142.length;i++){
+var pair=_142[i].split("=");
+var name=_144(pair.shift());
+if(!name){
+continue;
+}
+var arr=o[name];
+if(!(arr instanceof Array)){
+arr=[];
+o[name]=arr;
+}
+arr.push(_144(pair.join("=")));
+}
+}else{
+for(i=0;i<_142.length;i++){
+pair=_142[i].split("=");
+var name=pair.shift();
+if(!name){
+continue;
+}
+o[_144(name)]=_144(pair.join("="));
+}
+}
+return o;
+}});
+MochiKit.Base.AdapterRegistry=function(){
+this.pairs=[];
+};
+MochiKit.Base.AdapterRegistry.prototype={register:function(name,_14a,wrap,_14c){
+if(_14c){
+this.pairs.unshift([name,_14a,wrap]);
+}else{
+this.pairs.push([name,_14a,wrap]);
+}
+},match:function(){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[1].apply(this,arguments)){
+return pair[2].apply(this,arguments);
+}
+}
+throw MochiKit.Base.NotFound;
+},unregister:function(name){
+for(var i=0;i<this.pairs.length;i++){
+var pair=this.pairs[i];
+if(pair[0]==name){
+this.pairs.splice(i,1);
+return true;
+}
+}
+return false;
+}};
+MochiKit.Base.EXPORT=["flattenArray","noop","camelize","counter","clone","extend","update","updatetree","setdefault","keys","values","items","NamedError","operator","forwardCall","itemgetter","typeMatcher","isCallable","isUndefined","isUndefinedOrNull","isNull","isEmpty","isNotEmpty","isArrayLike","isDateLike","xmap","map","xfilter","filter","methodcaller","compose","bind","bindLate","bindMethods","NotFound","AdapterRegistry","registerComparator","compare","registerRepr","repr","objEqual","arrayEqual","concat","keyComparator","reverseKeyComparator","partial","merge","listMinMax","listMax","listMin","objMax","objMin","nodeWalk","zip","urlEncode","queryString","serializeJSON","registerJSON","evalJSON","parseQueryString","findValue","findIdentical","flattenArguments","method","average","mean","median"];
+MochiKit.Base.EXPORT_OK=["nameFunctions","comparatorRegistry","reprRegistry","jsonRegistry","compareDateLike","compareArrayLike","reprArrayLike","reprString","reprNumber"];
+MochiKit.Base._exportSymbols=function(_152,_153){
+if(!MochiKit.__export__){
+return;
+}
+var all=_153.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_152[all[i]]=_153[all[i]];
+}
+};
+MochiKit.Base.__new__=function(){
+var m=this;
+m.noop=m.operator.identity;
+m.forward=m.forwardCall;
+m.find=m.findValue;
+if(typeof (encodeURIComponent)!="undefined"){
+m.urlEncode=function(_157){
+return encodeURIComponent(_157).replace(/\'/g,"%27");
+};
+}else{
+m.urlEncode=function(_158){
+return escape(_158).replace(/\+/g,"%2B").replace(/\"/g,"%22").rval.replace(/\'/g,"%27");
+};
+}
+m.NamedError=function(name){
+this.message=name;
+this.name=name;
+};
+m.NamedError.prototype=new Error();
+m.update(m.NamedError.prototype,{repr:function(){
+if(this.message&&this.message!=this.name){
+return this.name+"("+m.repr(this.message)+")";
+}else{
+return this.name+"()";
+}
+},toString:m.forwardCall("repr")});
+m.NotFound=new m.NamedError("MochiKit.Base.NotFound");
+m.listMax=m.partial(m.listMinMax,1);
+m.listMin=m.partial(m.listMinMax,-1);
+m.isCallable=m.typeMatcher("function");
+m.isUndefined=m.typeMatcher("undefined");
+m.merge=m.partial(m.update,null);
+m.zip=m.partial(m.map,null);
+m.average=m.mean;
+m.comparatorRegistry=new m.AdapterRegistry();
+m.registerComparator("dateLike",m.isDateLike,m.compareDateLike);
+m.registerComparator("arrayLike",m.isArrayLike,m.compareArrayLike);
+m.reprRegistry=new m.AdapterRegistry();
+m.registerRepr("arrayLike",m.isArrayLike,m.reprArrayLike);
+m.registerRepr("string",m.typeMatcher("string"),m.reprString);
+m.registerRepr("numbers",m.typeMatcher("number","boolean"),m.reprNumber);
+m.jsonRegistry=new m.AdapterRegistry();
+var all=m.concat(m.EXPORT,m.EXPORT_OK);
+m.EXPORT_TAGS={":common":m.concat(m.EXPORT_OK),":all":all};
+m.nameFunctions(this);
+};
+MochiKit.Base.__new__();
+if(MochiKit.__export__){
+compare=MochiKit.Base.compare;
+compose=MochiKit.Base.compose;
+serializeJSON=MochiKit.Base.serializeJSON;
+mean=MochiKit.Base.mean;
+median=MochiKit.Base.median;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Base);
+MochiKit.Base._deps("Iter",["Base"]);
+MochiKit.Iter.NAME="MochiKit.Iter";
+MochiKit.Iter.VERSION="1.4.2";
+MochiKit.Base.update(MochiKit.Iter,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},registerIteratorFactory:function(name,_15c,_15d,_15e){
+MochiKit.Iter.iteratorRegistry.register(name,_15c,_15d,_15e);
+},isIterable:function(o){
+return o!=null&&(typeof (o.next)=="function"||typeof (o.iter)=="function");
+},iter:function(_160,_161){
+var self=MochiKit.Iter;
+if(arguments.length==2){
+return self.takewhile(function(a){
+return a!=_161;
+},_160);
+}
+if(typeof (_160.next)=="function"){
+return _160;
+}else{
+if(typeof (_160.iter)=="function"){
+return _160.iter();
+}
+}
+try{
+return self.iteratorRegistry.match(_160);
+}
+catch(e){
+var m=MochiKit.Base;
+if(e==m.NotFound){
+e=new TypeError(typeof (_160)+": "+m.repr(_160)+" is not iterable");
+}
+throw e;
+}
+},count:function(n){
+if(!n){
+n=0;
+}
+var m=MochiKit.Base;
+return {repr:function(){
+return "count("+n+")";
+},toString:m.forwardCall("repr"),next:m.counter(n)};
+},cycle:function(p){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+var lst=[];
+var _16b=self.iter(p);
+return {repr:function(){
+return "cycle(...)";
+},toString:m.forwardCall("repr"),next:function(){
+try{
+var rval=_16b.next();
+lst.push(rval);
+return rval;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+if(lst.length===0){
+this.next=function(){
+throw self.StopIteration;
+};
+}else{
+var i=-1;
+this.next=function(){
+i=(i+1)%lst.length;
+return lst[i];
+};
+}
+return this.next();
+}
+}};
+},repeat:function(elem,n){
+var m=MochiKit.Base;
+if(typeof (n)=="undefined"){
+return {repr:function(){
+return "repeat("+m.repr(elem)+")";
+},toString:m.forwardCall("repr"),next:function(){
+return elem;
+}};
+}
+return {repr:function(){
+return "repeat("+m.repr(elem)+", "+n+")";
+},toString:m.forwardCall("repr"),next:function(){
+if(n<=0){
+throw MochiKit.Iter.StopIteration;
+}
+n-=1;
+return elem;
+}};
+},next:function(_171){
+return _171.next();
+},izip:function(p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var next=self.next;
+var _177=m.map(self.iter,arguments);
+return {repr:function(){
+return "izip(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return m.map(next,_177);
+}};
+},ifilter:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilter(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},ifilterfalse:function(pred,seq){
+var m=MochiKit.Base;
+seq=MochiKit.Iter.iter(seq);
+if(pred===null){
+pred=m.operator.truth;
+}
+return {repr:function(){
+return "ifilterfalse(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+return rval;
+}
+}
+return undefined;
+}};
+},islice:function(seq){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+seq=self.iter(seq);
+var _183=0;
+var stop=0;
+var step=1;
+var i=-1;
+if(arguments.length==2){
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_183=arguments[1];
+stop=arguments[2];
+}else{
+_183=arguments[1];
+stop=arguments[2];
+step=arguments[3];
+}
+}
+return {repr:function(){
+return "islice("+["...",_183,stop,step].join(", ")+")";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+while(i<_183){
+rval=seq.next();
+i++;
+}
+if(_183>=stop){
+throw self.StopIteration;
+}
+_183+=step;
+return rval;
+}};
+},imap:function(fun,p,q){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+var _18d=m.map(self.iter,m.extend(null,arguments,1));
+var map=m.map;
+var next=self.next;
+return {repr:function(){
+return "imap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(this,map(next,_18d));
+}};
+},applymap:function(fun,seq,self){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+return {repr:function(){
+return "applymap(...)";
+},toString:m.forwardCall("repr"),next:function(){
+return fun.apply(self,seq.next());
+}};
+},chain:function(p,q){
+var self=MochiKit.Iter;
+var m=MochiKit.Base;
+if(arguments.length==1){
+return self.iter(arguments[0]);
+}
+var _198=m.map(self.iter,arguments);
+return {repr:function(){
+return "chain(...)";
+},toString:m.forwardCall("repr"),next:function(){
+while(_198.length>1){
+try{
+var _199=_198[0].next();
+return _199;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+_198.shift();
+var _199=_198[0].next();
+return _199;
+}
+}
+if(_198.length==1){
+var arg=_198.shift();
+this.next=m.bind("next",arg);
+return this.next();
+}
+throw self.StopIteration;
+}};
+},takewhile:function(pred,seq){
+var self=MochiKit.Iter;
+seq=self.iter(seq);
+return {repr:function(){
+return "takewhile(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=seq.next();
+if(!pred(rval)){
+this.next=function(){
+throw self.StopIteration;
+};
+this.next();
+}
+return rval;
+}};
+},dropwhile:function(pred,seq){
+seq=MochiKit.Iter.iter(seq);
+var m=MochiKit.Base;
+var bind=m.bind;
+return {"repr":function(){
+return "dropwhile(...)";
+},"toString":m.forwardCall("repr"),"next":function(){
+while(true){
+var rval=seq.next();
+if(!pred(rval)){
+break;
+}
+}
+this.next=bind("next",seq);
+return rval;
+}};
+},_tee:function(_1a4,sync,_1a6){
+sync.pos[_1a4]=-1;
+var m=MochiKit.Base;
+var _1a8=m.listMin;
+return {repr:function(){
+return "tee("+_1a4+", ...)";
+},toString:m.forwardCall("repr"),next:function(){
+var rval;
+var i=sync.pos[_1a4];
+if(i==sync.max){
+rval=_1a6.next();
+sync.deque.push(rval);
+sync.max+=1;
+sync.pos[_1a4]+=1;
+}else{
+rval=sync.deque[i-sync.min];
+sync.pos[_1a4]+=1;
+if(i==sync.min&&_1a8(sync.pos)!=sync.min){
+sync.min+=1;
+sync.deque.shift();
+}
+}
+return rval;
+}};
+},tee:function(_1ab,n){
+var rval=[];
+var sync={"pos":[],"deque":[],"max":-1,"min":-1};
+if(arguments.length==1||typeof (n)=="undefined"||n===null){
+n=2;
+}
+var self=MochiKit.Iter;
+_1ab=self.iter(_1ab);
+var _tee=self._tee;
+for(var i=0;i<n;i++){
+rval.push(_tee(i,sync,_1ab));
+}
+return rval;
+},list:function(_1b2){
+var rval;
+if(_1b2 instanceof Array){
+return _1b2.slice();
+}
+if(typeof (_1b2)=="function"&&!(_1b2 instanceof Function)&&typeof (_1b2.length)=="number"){
+rval=[];
+for(var i=0;i<_1b2.length;i++){
+rval.push(_1b2[i]);
+}
+return rval;
+}
+var self=MochiKit.Iter;
+_1b2=self.iter(_1b2);
+var rval=[];
+var _1b6;
+try{
+while(true){
+_1b6=_1b2.next();
+rval.push(_1b6);
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return rval;
+}
+return undefined;
+},reduce:function(fn,_1b8,_1b9){
+var i=0;
+var x=_1b9;
+var self=MochiKit.Iter;
+_1b8=self.iter(_1b8);
+if(arguments.length<3){
+try{
+x=_1b8.next();
+}
+catch(e){
+if(e==self.StopIteration){
+e=new TypeError("reduce() of empty sequence with no initial value");
+}
+throw e;
+}
+i++;
+}
+try{
+while(true){
+x=fn(x,_1b8.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},range:function(){
+var _1bd=0;
+var stop=0;
+var step=1;
+if(arguments.length==1){
+stop=arguments[0];
+}else{
+if(arguments.length==2){
+_1bd=arguments[0];
+stop=arguments[1];
+}else{
+if(arguments.length==3){
+_1bd=arguments[0];
+stop=arguments[1];
+step=arguments[2];
+}else{
+throw new TypeError("range() takes 1, 2, or 3 arguments!");
+}
+}
+}
+if(step===0){
+throw new TypeError("range() step must not be 0");
+}
+return {next:function(){
+if((step>0&&_1bd>=stop)||(step<0&&_1bd<=stop)){
+throw MochiKit.Iter.StopIteration;
+}
+var rval=_1bd;
+_1bd+=step;
+return rval;
+},repr:function(){
+return "range("+[_1bd,stop,step].join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+},sum:function(_1c1,_1c2){
+if(typeof (_1c2)=="undefined"||_1c2===null){
+_1c2=0;
+}
+var x=_1c2;
+var self=MochiKit.Iter;
+_1c1=self.iter(_1c1);
+try{
+while(true){
+x+=_1c1.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+return x;
+},exhaust:function(_1c5){
+var self=MochiKit.Iter;
+_1c5=self.iter(_1c5);
+try{
+while(true){
+_1c5.next();
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+},forEach:function(_1c7,func,obj){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length>2){
+func=m.bind(func,obj);
+}
+if(m.isArrayLike(_1c7)&&!self.isIterable(_1c7)){
+try{
+for(var i=0;i<_1c7.length;i++){
+func(_1c7[i]);
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}else{
+self.exhaust(self.imap(func,_1c7));
+}
+},every:function(_1cd,func){
+var self=MochiKit.Iter;
+try{
+self.ifilterfalse(func,_1cd).next();
+return false;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return true;
+}
+},sorted:function(_1d0,cmp){
+var rval=MochiKit.Iter.list(_1d0);
+if(arguments.length==1){
+cmp=MochiKit.Base.compare;
+}
+rval.sort(cmp);
+return rval;
+},reversed:function(_1d3){
+var rval=MochiKit.Iter.list(_1d3);
+rval.reverse();
+return rval;
+},some:function(_1d5,func){
+var self=MochiKit.Iter;
+try{
+self.ifilter(func,_1d5).next();
+return true;
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+return false;
+}
+},iextend:function(lst,_1d9){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(m.isArrayLike(_1d9)&&!self.isIterable(_1d9)){
+for(var i=0;i<_1d9.length;i++){
+lst.push(_1d9[i]);
+}
+}else{
+_1d9=self.iter(_1d9);
+try{
+while(true){
+lst.push(_1d9.next());
+}
+}
+catch(e){
+if(e!=self.StopIteration){
+throw e;
+}
+}
+}
+return lst;
+},groupby:function(_1dd,_1de){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1de=m.operator.identity;
+}
+_1dd=self.iter(_1dd);
+var pk=undefined;
+var k=undefined;
+var v;
+function fetch(){
+v=_1dd.next();
+k=_1de(v);
+}
+function eat(){
+var ret=v;
+v=undefined;
+return ret;
+}
+var _1e5=true;
+var _1e6=m.compare;
+return {repr:function(){
+return "groupby(...)";
+},next:function(){
+while(_1e6(k,pk)===0){
+fetch();
+if(_1e5){
+_1e5=false;
+break;
+}
+}
+pk=k;
+return [k,{next:function(){
+if(v==undefined){
+fetch();
+}
+if(_1e6(k,pk)!==0){
+throw self.StopIteration;
+}
+return eat();
+}}];
+}};
+},groupby_as_array:function(_1e7,_1e8){
+var m=MochiKit.Base;
+var self=MochiKit.Iter;
+if(arguments.length<2){
+_1e8=m.operator.identity;
+}
+_1e7=self.iter(_1e7);
+var _1eb=[];
+var _1ec=true;
+var _1ed;
+var _1ee=m.compare;
+while(true){
+try{
+var _1ef=_1e7.next();
+var key=_1e8(_1ef);
+}
+catch(e){
+if(e==self.StopIteration){
+break;
+}
+throw e;
+}
+if(_1ec||_1ee(key,_1ed)!==0){
+var _1f1=[];
+_1eb.push([key,_1f1]);
+}
+_1f1.push(_1ef);
+_1ec=false;
+_1ed=key;
+}
+return _1eb;
+},arrayLikeIter:function(_1f2){
+var i=0;
+return {repr:function(){
+return "arrayLikeIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+if(i>=_1f2.length){
+throw MochiKit.Iter.StopIteration;
+}
+return _1f2[i++];
+}};
+},hasIterateNext:function(_1f4){
+return (_1f4&&typeof (_1f4.iterateNext)=="function");
+},iterateNextIter:function(_1f5){
+return {repr:function(){
+return "iterateNextIter(...)";
+},toString:MochiKit.Base.forwardCall("repr"),next:function(){
+var rval=_1f5.iterateNext();
+if(rval===null||rval===undefined){
+throw MochiKit.Iter.StopIteration;
+}
+return rval;
+}};
+}});
+MochiKit.Iter.EXPORT_OK=["iteratorRegistry","arrayLikeIter","hasIterateNext","iterateNextIter"];
+MochiKit.Iter.EXPORT=["StopIteration","registerIteratorFactory","iter","count","cycle","repeat","next","izip","ifilter","ifilterfalse","islice","imap","applymap","chain","takewhile","dropwhile","tee","list","reduce","range","sum","exhaust","forEach","every","sorted","reversed","some","iextend","groupby","groupby_as_array"];
+MochiKit.Iter.__new__=function(){
+var m=MochiKit.Base;
+if(typeof (StopIteration)!="undefined"){
+this.StopIteration=StopIteration;
+}else{
+this.StopIteration=new m.NamedError("StopIteration");
+}
+this.iteratorRegistry=new m.AdapterRegistry();
+this.registerIteratorFactory("arrayLike",m.isArrayLike,this.arrayLikeIter);
+this.registerIteratorFactory("iterateNext",this.hasIterateNext,this.iterateNextIter);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Iter.__new__();
+if(MochiKit.__export__){
+reduce=MochiKit.Iter.reduce;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Iter);
+MochiKit.Base._deps("Logging",["Base"]);
+MochiKit.Logging.NAME="MochiKit.Logging";
+MochiKit.Logging.VERSION="1.4.2";
+MochiKit.Logging.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Logging.toString=function(){
+return this.__repr__();
+};
+MochiKit.Logging.EXPORT=["LogLevel","LogMessage","Logger","alertListener","logger","log","logError","logDebug","logFatal","logWarning"];
+MochiKit.Logging.EXPORT_OK=["logLevelAtLeast","isLogMessage","compareLogMessage"];
+MochiKit.Logging.LogMessage=function(num,_1f9,info){
+this.num=num;
+this.level=_1f9;
+this.info=info;
+this.timestamp=new Date();
+};
+MochiKit.Logging.LogMessage.prototype={repr:function(){
+var m=MochiKit.Base;
+return "LogMessage("+m.map(m.repr,[this.num,this.level,this.info]).join(", ")+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Logging,{logLevelAtLeast:function(_1fc){
+var self=MochiKit.Logging;
+if(typeof (_1fc)=="string"){
+_1fc=self.LogLevel[_1fc];
+}
+return function(msg){
+var _1ff=msg.level;
+if(typeof (_1ff)=="string"){
+_1ff=self.LogLevel[_1ff];
+}
+return _1ff>=_1fc;
+};
+},isLogMessage:function(){
+var _200=MochiKit.Logging.LogMessage;
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof _200)){
+return false;
+}
+}
+return true;
+},compareLogMessage:function(a,b){
+return MochiKit.Base.compare([a.level,a.info],[b.level,b.info]);
+},alertListener:function(msg){
+alert("num: "+msg.num+"\nlevel: "+msg.level+"\ninfo: "+msg.info.join(" "));
+}});
+MochiKit.Logging.Logger=function(_205){
+this.counter=0;
+if(typeof (_205)=="undefined"||_205===null){
+_205=-1;
+}
+this.maxSize=_205;
+this._messages=[];
+this.listeners={};
+this.useNativeConsole=false;
+};
+MochiKit.Logging.Logger.prototype={clear:function(){
+this._messages.splice(0,this._messages.length);
+},logToConsole:function(msg){
+if(typeof (window)!="undefined"&&window.console&&window.console.log){
+window.console.log(msg.replace(/%/g,"\uff05"));
+}else{
+if(typeof (opera)!="undefined"&&opera.postError){
+opera.postError(msg);
+}else{
+if(typeof (printfire)=="function"){
+printfire(msg);
+}else{
+if(typeof (Debug)!="undefined"&&Debug.writeln){
+Debug.writeln(msg);
+}else{
+if(typeof (debug)!="undefined"&&debug.trace){
+debug.trace(msg);
+}
+}
+}
+}
+}
+},dispatchListeners:function(msg){
+for(var k in this.listeners){
+var pair=this.listeners[k];
+if(pair.ident!=k||(pair[0]&&!pair[0](msg))){
+continue;
+}
+pair[1](msg);
+}
+},addListener:function(_20a,_20b,_20c){
+if(typeof (_20b)=="string"){
+_20b=MochiKit.Logging.logLevelAtLeast(_20b);
+}
+var _20d=[_20b,_20c];
+_20d.ident=_20a;
+this.listeners[_20a]=_20d;
+},removeListener:function(_20e){
+delete this.listeners[_20e];
+},baseLog:function(_20f,_210){
+if(typeof (_20f)=="number"){
+if(_20f>=MochiKit.Logging.LogLevel.FATAL){
+_20f="FATAL";
+}else{
+if(_20f>=MochiKit.Logging.LogLevel.ERROR){
+_20f="ERROR";
+}else{
+if(_20f>=MochiKit.Logging.LogLevel.WARNING){
+_20f="WARNING";
+}else{
+if(_20f>=MochiKit.Logging.LogLevel.INFO){
+_20f="INFO";
+}else{
+_20f="DEBUG";
+}
+}
+}
+}
+}
+var msg=new MochiKit.Logging.LogMessage(this.counter,_20f,MochiKit.Base.extend(null,arguments,1));
+this._messages.push(msg);
+this.dispatchListeners(msg);
+if(this.useNativeConsole){
+this.logToConsole(msg.level+": "+msg.info.join(" "));
+}
+this.counter+=1;
+while(this.maxSize>=0&&this._messages.length>this.maxSize){
+this._messages.shift();
+}
+},getMessages:function(_212){
+var _213=0;
+if(!(typeof (_212)=="undefined"||_212===null)){
+_213=Math.max(0,this._messages.length-_212);
+}
+return this._messages.slice(_213);
+},getMessageText:function(_214){
+if(typeof (_214)=="undefined"||_214===null){
+_214=30;
+}
+var _215=this.getMessages(_214);
+if(_215.length){
+var lst=map(function(m){
+return "\n  ["+m.num+"] "+m.level+": "+m.info.join(" ");
+},_215);
+lst.unshift("LAST "+_215.length+" MESSAGES:");
+return lst.join("");
+}
+return "";
+},debuggingBookmarklet:function(_218){
+if(typeof (MochiKit.LoggingPane)=="undefined"){
+alert(this.getMessageText());
+}else{
+MochiKit.LoggingPane.createLoggingPane(_218||false);
+}
+}};
+MochiKit.Logging.__new__=function(){
+this.LogLevel={ERROR:40,FATAL:50,WARNING:30,INFO:20,DEBUG:10};
+var m=MochiKit.Base;
+m.registerComparator("LogMessage",this.isLogMessage,this.compareLogMessage);
+var _21a=m.partial;
+var _21b=this.Logger;
+var _21c=_21b.prototype.baseLog;
+m.update(this.Logger.prototype,{debug:_21a(_21c,"DEBUG"),log:_21a(_21c,"INFO"),error:_21a(_21c,"ERROR"),fatal:_21a(_21c,"FATAL"),warning:_21a(_21c,"WARNING")});
+var self=this;
+var _21e=function(name){
+return function(){
+self.logger[name].apply(self.logger,arguments);
+};
+};
+this.log=_21e("log");
+this.logError=_21e("error");
+this.logDebug=_21e("debug");
+this.logFatal=_21e("fatal");
+this.logWarning=_21e("warning");
+this.logger=new _21b();
+this.logger.useNativeConsole=true;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+if(typeof (printfire)=="undefined"&&typeof (document)!="undefined"&&document.createEvent&&typeof (dispatchEvent)!="undefined"){
+printfire=function(){
+printfire.args=arguments;
+var ev=document.createEvent("Events");
+ev.initEvent("printfire",false,true);
+dispatchEvent(ev);
+};
+}
+MochiKit.Logging.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Logging);
+MochiKit.Base._deps("DateTime",["Base"]);
+MochiKit.DateTime.NAME="MochiKit.DateTime";
+MochiKit.DateTime.VERSION="1.4.2";
+MochiKit.DateTime.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DateTime.toString=function(){
+return this.__repr__();
+};
+MochiKit.DateTime.isoDate=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var iso=str.split("-");
+if(iso.length===0){
+return null;
+}
+var date=new Date(iso[0],iso[1]-1,iso[2]);
+date.setFullYear(iso[0]);
+date.setMonth(iso[1]-1);
+date.setDate(iso[2]);
+return date;
+};
+MochiKit.DateTime._isoRegexp=/(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
+MochiKit.DateTime.isoTimestamp=function(str){
+str=str+"";
+if(typeof (str)!="string"||str.length===0){
+return null;
+}
+var res=str.match(MochiKit.DateTime._isoRegexp);
+if(typeof (res)=="undefined"||res===null){
+return null;
+}
+var year,_227,day,hour,min,sec,msec;
+year=parseInt(res[1],10);
+if(typeof (res[2])=="undefined"||res[2]===""){
+return new Date(year);
+}
+_227=parseInt(res[2],10)-1;
+day=parseInt(res[3],10);
+if(typeof (res[4])=="undefined"||res[4]===""){
+return new Date(year,_227,day);
+}
+hour=parseInt(res[4],10);
+min=parseInt(res[5],10);
+sec=(typeof (res[6])!="undefined"&&res[6]!=="")?parseInt(res[6],10):0;
+if(typeof (res[7])!="undefined"&&res[7]!==""){
+msec=Math.round(1000*parseFloat("0."+res[7]));
+}else{
+msec=0;
+}
+if((typeof (res[8])=="undefined"||res[8]==="")&&(typeof (res[9])=="undefined"||res[9]==="")){
+return new Date(year,_227,day,hour,min,sec,msec);
+}
+var ofs;
+if(typeof (res[9])!="undefined"&&res[9]!==""){
+ofs=parseInt(res[10],10)*3600000;
+if(typeof (res[11])!="undefined"&&res[11]!==""){
+ofs+=parseInt(res[11],10)*60000;
+}
+if(res[9]=="-"){
+ofs=-ofs;
+}
+}else{
+ofs=0;
+}
+return new Date(Date.UTC(year,_227,day,hour,min,sec,msec)-ofs);
+};
+MochiKit.DateTime.toISOTime=function(date,_22f){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var hh=date.getHours();
+var mm=date.getMinutes();
+var ss=date.getSeconds();
+var lst=[((_22f&&(hh<10))?"0"+hh:hh),((mm<10)?"0"+mm:mm),((ss<10)?"0"+ss:ss)];
+return lst.join(":");
+};
+MochiKit.DateTime.toISOTimestamp=function(date,_235){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var sep=_235?"T":" ";
+var foot=_235?"Z":"";
+if(_235){
+date=new Date(date.getTime()+(date.getTimezoneOffset()*60000));
+}
+return MochiKit.DateTime.toISODate(date)+sep+MochiKit.DateTime.toISOTime(date,_235)+foot;
+};
+MochiKit.DateTime.toISODate=function(date){
+if(typeof (date)=="undefined"||date===null){
+return null;
+}
+var _239=MochiKit.DateTime._padTwo;
+var _23a=MochiKit.DateTime._padFour;
+return [_23a(date.getFullYear()),_239(date.getMonth()+1),_239(date.getDate())].join("-");
+};
+MochiKit.DateTime.americanDate=function(d){
+d=d+"";
+if(typeof (d)!="string"||d.length===0){
+return null;
+}
+var a=d.split("/");
+return new Date(a[2],a[0]-1,a[1]);
+};
+MochiKit.DateTime._padTwo=function(n){
+return (n>9)?n:"0"+n;
+};
+MochiKit.DateTime._padFour=function(n){
+switch(n.toString().length){
+case 1:
+return "000"+n;
+break;
+case 2:
+return "00"+n;
+break;
+case 3:
+return "0"+n;
+break;
+case 4:
+default:
+return n;
+}
+};
+MochiKit.DateTime.toPaddedAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+var _240=MochiKit.DateTime._padTwo;
+return [_240(d.getMonth()+1),_240(d.getDate()),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.toAmericanDate=function(d){
+if(typeof (d)=="undefined"||d===null){
+return null;
+}
+return [d.getMonth()+1,d.getDate(),d.getFullYear()].join("/");
+};
+MochiKit.DateTime.EXPORT=["isoDate","isoTimestamp","toISOTime","toISOTimestamp","toISODate","americanDate","toPaddedAmericanDate","toAmericanDate"];
+MochiKit.DateTime.EXPORT_OK=[];
+MochiKit.DateTime.EXPORT_TAGS={":common":MochiKit.DateTime.EXPORT,":all":MochiKit.DateTime.EXPORT};
+MochiKit.DateTime.__new__=function(){
+var base=this.NAME+".";
+for(var k in this){
+var o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.DateTime.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.DateTime);
+}else{
+(function(_245,_246){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_246.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_245[all[i]]=_246[all[i]];
+}
+}
+})(this,MochiKit.DateTime);
+}
+MochiKit.Base._deps("Format",["Base"]);
+MochiKit.Format.NAME="MochiKit.Format";
+MochiKit.Format.VERSION="1.4.2";
+MochiKit.Format.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Format.toString=function(){
+return this.__repr__();
+};
+MochiKit.Format._numberFormatter=function(_249,_24a,_24b,_24c,_24d,_24e,_24f,_250,_251){
+return function(num){
+num=parseFloat(num);
+if(typeof (num)=="undefined"||num===null||isNaN(num)){
+return _249;
+}
+var _253=_24a;
+var _254=_24b;
+if(num<0){
+num=-num;
+}else{
+_253=_253.replace(/-/,"");
+}
+var me=arguments.callee;
+var fmt=MochiKit.Format.formatLocale(_24c);
+if(_24d){
+num=num*100;
+_254=fmt.percent+_254;
+}
+num=MochiKit.Format.roundToFixed(num,_24e);
+var _257=num.split(/\./);
+var _258=_257[0];
+var frac=(_257.length==1)?"":_257[1];
+var res="";
+while(_258.length<_24f){
+_258="0"+_258;
+}
+if(_250){
+while(_258.length>_250){
+var i=_258.length-_250;
+res=fmt.separator+_258.substring(i,_258.length)+res;
+_258=_258.substring(0,i);
+}
+}
+res=_258+res;
+if(_24e>0){
+while(frac.length<_251){
+frac=frac+"0";
+}
+res=res+fmt.decimal+frac;
+}
+return _253+res+_254;
+};
+};
+MochiKit.Format.numberFormatter=function(_25c,_25d,_25e){
+if(typeof (_25d)=="undefined"){
+_25d="";
+}
+var _25f=_25c.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+if(!_25f){
+throw TypeError("Invalid pattern");
+}
+var _260=_25c.substr(0,_25f.index);
+var _261=_25c.substr(_25f.index+_25f[0].length);
+if(_260.search(/-/)==-1){
+_260=_260+"-";
+}
+var _262=_25f[1];
+var frac=(typeof (_25f[2])=="string"&&_25f[2]!="")?_25f[2]:"";
+var _264=(typeof (_25f[3])=="string"&&_25f[3]!="");
+var tmp=_262.split(/,/);
+var _266;
+if(typeof (_25e)=="undefined"){
+_25e="default";
+}
+if(tmp.length==1){
+_266=null;
+}else{
+_266=tmp[1].length;
+}
+var _267=_262.length-_262.replace(/0/g,"").length;
+var _268=frac.length-frac.replace(/0/g,"").length;
+var _269=frac.length;
+var rval=MochiKit.Format._numberFormatter(_25d,_260,_261,_25e,_264,_269,_267,_266,_268);
+var m=MochiKit.Base;
+if(m){
+var fn=arguments.callee;
+var args=m.concat(arguments);
+rval.repr=function(){
+return [self.NAME,"(",map(m.repr,args).join(", "),")"].join("");
+};
+}
+return rval;
+};
+MochiKit.Format.formatLocale=function(_26e){
+if(typeof (_26e)=="undefined"||_26e===null){
+_26e="default";
+}
+if(typeof (_26e)=="string"){
+var rval=MochiKit.Format.LOCALE[_26e];
+if(typeof (rval)=="string"){
+rval=arguments.callee(rval);
+MochiKit.Format.LOCALE[_26e]=rval;
+}
+return rval;
+}else{
+return _26e;
+}
+};
+MochiKit.Format.twoDigitAverage=function(_270,_271){
+if(_271){
+var res=_270/_271;
+if(!isNaN(res)){
+return MochiKit.Format.twoDigitFloat(res);
+}
+}
+return "0";
+};
+MochiKit.Format.twoDigitFloat=function(_273){
+var res=roundToFixed(_273,2);
+if(res.indexOf(".00")>0){
+return res.substring(0,res.length-3);
+}else{
+if(res.charAt(res.length-1)=="0"){
+return res.substring(0,res.length-1);
+}else{
+return res;
+}
+}
+};
+MochiKit.Format.lstrip=function(str,_276){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_276){
+return str.replace(/^\s+/,"");
+}else{
+return str.replace(new RegExp("^["+_276+"]+"),"");
+}
+};
+MochiKit.Format.rstrip=function(str,_278){
+str=str+"";
+if(typeof (str)!="string"){
+return null;
+}
+if(!_278){
+return str.replace(/\s+$/,"");
+}else{
+return str.replace(new RegExp("["+_278+"]+$"),"");
+}
+};
+MochiKit.Format.strip=function(str,_27a){
+var self=MochiKit.Format;
+return self.rstrip(self.lstrip(str,_27a),_27a);
+};
+MochiKit.Format.truncToFixed=function(_27c,_27d){
+var res=Math.floor(_27c).toFixed(0);
+if(_27c<0){
+res=Math.ceil(_27c).toFixed(0);
+if(res.charAt(0)!="-"&&_27d>0){
+res="-"+res;
+}
+}
+if(res.indexOf("e")<0&&_27d>0){
+var tail=_27c.toString();
+if(tail.indexOf("e")>0){
+tail=".";
+}else{
+if(tail.indexOf(".")<0){
+tail=".";
+}else{
+tail=tail.substring(tail.indexOf("."));
+}
+}
+if(tail.length-1>_27d){
+tail=tail.substring(0,_27d+1);
+}
+while(tail.length-1<_27d){
+tail+="0";
+}
+res+=tail;
+}
+return res;
+};
+MochiKit.Format.roundToFixed=function(_280,_281){
+var _282=Math.abs(_280)+0.5*Math.pow(10,-_281);
+var res=MochiKit.Format.truncToFixed(_282,_281);
+if(_280<0){
+res="-"+res;
+}
+return res;
+};
+MochiKit.Format.percentFormat=function(_284){
+return MochiKit.Format.twoDigitFloat(100*_284)+"%";
+};
+MochiKit.Format.EXPORT=["truncToFixed","roundToFixed","numberFormatter","formatLocale","twoDigitAverage","twoDigitFloat","percentFormat","lstrip","rstrip","strip"];
+MochiKit.Format.LOCALE={en_US:{separator:",",decimal:".",percent:"%"},de_DE:{separator:".",decimal:",",percent:"%"},pt_BR:{separator:".",decimal:",",percent:"%"},fr_FR:{separator:" ",decimal:",",percent:"%"},"default":"en_US"};
+MochiKit.Format.EXPORT_OK=[];
+MochiKit.Format.EXPORT_TAGS={":all":MochiKit.Format.EXPORT,":common":MochiKit.Format.EXPORT};
+MochiKit.Format.__new__=function(){
+var base=this.NAME+".";
+var k,v,o;
+for(k in this.LOCALE){
+o=this.LOCALE[k];
+if(typeof (o)=="object"){
+o.repr=function(){
+return this.NAME;
+};
+o.NAME=base+"LOCALE."+k;
+}
+}
+for(k in this){
+o=this[k];
+if(typeof (o)=="function"&&typeof (o.NAME)=="undefined"){
+try{
+o.NAME=base+k;
+}
+catch(e){
+}
+}
+}
+};
+MochiKit.Format.__new__();
+if(typeof (MochiKit.Base)!="undefined"){
+MochiKit.Base._exportSymbols(this,MochiKit.Format);
+}else{
+(function(_289,_28a){
+if((typeof (JSAN)=="undefined"&&typeof (dojo)=="undefined")||(MochiKit.__export__===false)){
+var all=_28a.EXPORT_TAGS[":all"];
+for(var i=0;i<all.length;i++){
+_289[all[i]]=_28a[all[i]];
+}
+}
+})(this,MochiKit.Format);
+}
+MochiKit.Base._deps("Async",["Base"]);
+MochiKit.Async.NAME="MochiKit.Async";
+MochiKit.Async.VERSION="1.4.2";
+MochiKit.Async.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Async.toString=function(){
+return this.__repr__();
+};
+MochiKit.Async.Deferred=function(_28d){
+this.chain=[];
+this.id=this._nextId();
+this.fired=-1;
+this.paused=0;
+this.results=[null,null];
+this.canceller=_28d;
+this.silentlyCancelled=false;
+this.chained=false;
+};
+MochiKit.Async.Deferred.prototype={repr:function(){
+var _28e;
+if(this.fired==-1){
+_28e="unfired";
+}else{
+if(this.fired===0){
+_28e="success";
+}else{
+_28e="error";
+}
+}
+return "Deferred("+this.id+", "+_28e+")";
+},toString:MochiKit.Base.forwardCall("repr"),_nextId:MochiKit.Base.counter(),cancel:function(){
+var self=MochiKit.Async;
+if(this.fired==-1){
+if(this.canceller){
+this.canceller(this);
+}else{
+this.silentlyCancelled=true;
+}
+if(this.fired==-1){
+this.errback(new self.CancelledError(this));
+}
+}else{
+if((this.fired===0)&&(this.results[0] instanceof self.Deferred)){
+this.results[0].cancel();
+}
+}
+},_resback:function(res){
+this.fired=((res instanceof Error)?1:0);
+this.results[this.fired]=res;
+this._fire();
+},_check:function(){
+if(this.fired!=-1){
+if(!this.silentlyCancelled){
+throw new MochiKit.Async.AlreadyCalledError(this);
+}
+this.silentlyCancelled=false;
+return;
+}
+},callback:function(res){
+this._check();
+if(res instanceof MochiKit.Async.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+this._resback(res);
+},errback:function(res){
+this._check();
+var self=MochiKit.Async;
+if(res instanceof self.Deferred){
+throw new Error("Deferred instances can only be chained if they are the result of a callback");
+}
+if(!(res instanceof Error)){
+res=new self.GenericError(res);
+}
+this._resback(res);
+},addBoth:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,fn);
+},addCallback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(fn,null);
+},addErrback:function(fn){
+if(arguments.length>1){
+fn=MochiKit.Base.partial.apply(null,arguments);
+}
+return this.addCallbacks(null,fn);
+},addCallbacks:function(cb,eb){
+if(this.chained){
+throw new Error("Chained Deferreds can not be re-used");
+}
+this.chain.push([cb,eb]);
+if(this.fired>=0){
+this._fire();
+}
+return this;
+},_fire:function(){
+var _299=this.chain;
+var _29a=this.fired;
+var res=this.results[_29a];
+var self=this;
+var cb=null;
+while(_299.length>0&&this.paused===0){
+var pair=_299.shift();
+var f=pair[_29a];
+if(f===null){
+continue;
+}
+try{
+res=f(res);
+_29a=((res instanceof Error)?1:0);
+if(res instanceof MochiKit.Async.Deferred){
+cb=function(res){
+self._resback(res);
+self.paused--;
+if((self.paused===0)&&(self.fired>=0)){
+self._fire();
+}
+};
+this.paused++;
+}
+}
+catch(err){
+_29a=1;
+if(!(err instanceof Error)){
+err=new MochiKit.Async.GenericError(err);
+}
+res=err;
+}
+}
+this.fired=_29a;
+this.results[_29a]=res;
+if(cb&&this.paused){
+res.addBoth(cb);
+res.chained=true;
+}
+}};
+MochiKit.Base.update(MochiKit.Async,{evalJSONRequest:function(req){
+return MochiKit.Base.evalJSON(req.responseText);
+},succeed:function(_2a2){
+var d=new MochiKit.Async.Deferred();
+d.callback.apply(d,arguments);
+return d;
+},fail:function(_2a4){
+var d=new MochiKit.Async.Deferred();
+d.errback.apply(d,arguments);
+return d;
+},getXMLHttpRequest:function(){
+var self=arguments.callee;
+if(!self.XMLHttpRequest){
+var _2a7=[function(){
+return new XMLHttpRequest();
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP");
+},function(){
+return new ActiveXObject("Microsoft.XMLHTTP");
+},function(){
+return new ActiveXObject("Msxml2.XMLHTTP.4.0");
+},function(){
+throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
+}];
+for(var i=0;i<_2a7.length;i++){
+var func=_2a7[i];
+try{
+self.XMLHttpRequest=func;
+return func();
+}
+catch(e){
+}
+}
+}
+return self.XMLHttpRequest();
+},_xhr_onreadystatechange:function(d){
+var m=MochiKit.Base;
+if(this.readyState==4){
+try{
+this.onreadystatechange=null;
+}
+catch(e){
+try{
+this.onreadystatechange=m.noop;
+}
+catch(e){
+}
+}
+var _2ac=null;
+try{
+_2ac=this.status;
+if(!_2ac&&m.isNotEmpty(this.responseText)){
+_2ac=304;
+}
+}
+catch(e){
+}
+if(_2ac==200||_2ac==201||_2ac==204||_2ac==304||_2ac==1223){
+d.callback(this);
+}else{
+var err=new MochiKit.Async.XMLHttpRequestError(this,"Request failed");
+if(err.number){
+d.errback(err);
+}else{
+d.errback(err);
+}
+}
+}
+},_xhr_canceller:function(req){
+try{
+req.onreadystatechange=null;
+}
+catch(e){
+try{
+req.onreadystatechange=MochiKit.Base.noop;
+}
+catch(e){
+}
+}
+req.abort();
+},sendXMLHttpRequest:function(req,_2b0){
+if(typeof (_2b0)=="undefined"||_2b0===null){
+_2b0="";
+}
+var m=MochiKit.Base;
+var self=MochiKit.Async;
+var d=new self.Deferred(m.partial(self._xhr_canceller,req));
+try{
+req.onreadystatechange=m.bind(self._xhr_onreadystatechange,req,d);
+req.send(_2b0);
+}
+catch(e){
+try{
+req.onreadystatechange=null;
+}
+catch(ignore){
+}
+d.errback(e);
+}
+return d;
+},doXHR:function(url,opts){
+var self=MochiKit.Async;
+return self.callLater(0,self._doXHR,url,opts);
+},_doXHR:function(url,opts){
+var m=MochiKit.Base;
+opts=m.update({method:"GET",sendContent:""},opts);
+var self=MochiKit.Async;
+var req=self.getXMLHttpRequest();
+if(opts.queryString){
+var qs=m.queryString(opts.queryString);
+if(qs){
+url+="?"+qs;
+}
+}
+if("username" in opts){
+req.open(opts.method,url,true,opts.username,opts.password);
+}else{
+req.open(opts.method,url,true);
+}
+if(req.overrideMimeType&&opts.mimeType){
+req.overrideMimeType(opts.mimeType);
+}
+req.setRequestHeader("X-Requested-With","XMLHttpRequest");
+if(opts.headers){
+var _2bd=opts.headers;
+if(!m.isArrayLike(_2bd)){
+_2bd=m.items(_2bd);
+}
+for(var i=0;i<_2bd.length;i++){
+var _2bf=_2bd[i];
+var name=_2bf[0];
+var _2c1=_2bf[1];
+req.setRequestHeader(name,_2c1);
+}
+}
+return self.sendXMLHttpRequest(req,opts.sendContent);
+},_buildURL:function(url){
+if(arguments.length>1){
+var m=MochiKit.Base;
+var qs=m.queryString.apply(null,m.extend(null,arguments,1));
+if(qs){
+return url+"?"+qs;
+}
+}
+return url;
+},doSimpleXMLHttpRequest:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+return self.doXHR(url);
+},loadJSONDoc:function(url){
+var self=MochiKit.Async;
+url=self._buildURL.apply(self,arguments);
+var d=self.doXHR(url,{"mimeType":"text/plain","headers":[["Accept","application/json"]]});
+d=d.addCallback(self.evalJSONRequest);
+return d;
+},wait:function(_2ca,_2cb){
+var d=new MochiKit.Async.Deferred();
+var m=MochiKit.Base;
+if(typeof (_2cb)!="undefined"){
+d.addCallback(function(){
+return _2cb;
+});
+}
+var _2ce=setTimeout(m.bind("callback",d),Math.floor(_2ca*1000));
+d.canceller=function(){
+try{
+clearTimeout(_2ce);
+}
+catch(e){
+}
+};
+return d;
+},callLater:function(_2cf,func){
+var m=MochiKit.Base;
+var _2d2=m.partial.apply(m,m.extend(null,arguments,1));
+return MochiKit.Async.wait(_2cf).addCallback(function(res){
+return _2d2();
+});
+}});
+MochiKit.Async.DeferredLock=function(){
+this.waiting=[];
+this.locked=false;
+this.id=this._nextId();
+};
+MochiKit.Async.DeferredLock.prototype={__class__:MochiKit.Async.DeferredLock,acquire:function(){
+var d=new MochiKit.Async.Deferred();
+if(this.locked){
+this.waiting.push(d);
+}else{
+this.locked=true;
+d.callback(this);
+}
+return d;
+},release:function(){
+if(!this.locked){
+throw TypeError("Tried to release an unlocked DeferredLock");
+}
+this.locked=false;
+if(this.waiting.length>0){
+this.locked=true;
+this.waiting.shift().callback(this);
+}
+},_nextId:MochiKit.Base.counter(),repr:function(){
+var _2d5;
+if(this.locked){
+_2d5="locked, "+this.waiting.length+" waiting";
+}else{
+_2d5="unlocked";
+}
+return "DeferredLock("+this.id+", "+_2d5+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Async.DeferredList=function(list,_2d7,_2d8,_2d9,_2da){
+MochiKit.Async.Deferred.apply(this,[_2da]);
+this.list=list;
+var _2db=[];
+this.resultList=_2db;
+this.finishedCount=0;
+this.fireOnOneCallback=_2d7;
+this.fireOnOneErrback=_2d8;
+this.consumeErrors=_2d9;
+var cb=MochiKit.Base.bind(this._cbDeferred,this);
+for(var i=0;i<list.length;i++){
+var d=list[i];
+_2db.push(undefined);
+d.addCallback(cb,i,true);
+d.addErrback(cb,i,false);
+}
+if(list.length===0&&!_2d7){
+this.callback(this.resultList);
+}
+};
+MochiKit.Async.DeferredList.prototype=new MochiKit.Async.Deferred();
+MochiKit.Async.DeferredList.prototype._cbDeferred=function(_2df,_2e0,_2e1){
+this.resultList[_2df]=[_2e0,_2e1];
+this.finishedCount+=1;
+if(this.fired==-1){
+if(_2e0&&this.fireOnOneCallback){
+this.callback([_2df,_2e1]);
+}else{
+if(!_2e0&&this.fireOnOneErrback){
+this.errback(_2e1);
+}else{
+if(this.finishedCount==this.list.length){
+this.callback(this.resultList);
+}
+}
+}
+}
+if(!_2e0&&this.consumeErrors){
+_2e1=null;
+}
+return _2e1;
+};
+MochiKit.Async.gatherResults=function(_2e2){
+var d=new MochiKit.Async.DeferredList(_2e2,false,true,false);
+d.addCallback(function(_2e4){
+var ret=[];
+for(var i=0;i<_2e4.length;i++){
+ret.push(_2e4[i][1]);
+}
+return ret;
+});
+return d;
+};
+MochiKit.Async.maybeDeferred=function(func){
+var self=MochiKit.Async;
+var _2e9;
+try{
+var r=func.apply(null,MochiKit.Base.extend([],arguments,1));
+if(r instanceof self.Deferred){
+_2e9=r;
+}else{
+if(r instanceof Error){
+_2e9=self.fail(r);
+}else{
+_2e9=self.succeed(r);
+}
+}
+}
+catch(e){
+_2e9=self.fail(e);
+}
+return _2e9;
+};
+MochiKit.Async.EXPORT=["AlreadyCalledError","CancelledError","BrowserComplianceError","GenericError","XMLHttpRequestError","Deferred","succeed","fail","getXMLHttpRequest","doSimpleXMLHttpRequest","loadJSONDoc","wait","callLater","sendXMLHttpRequest","DeferredLock","DeferredList","gatherResults","maybeDeferred","doXHR"];
+MochiKit.Async.EXPORT_OK=["evalJSONRequest"];
+MochiKit.Async.__new__=function(){
+var m=MochiKit.Base;
+var ne=m.partial(m._newNamedError,this);
+ne("AlreadyCalledError",function(_2ed){
+this.deferred=_2ed;
+});
+ne("CancelledError",function(_2ee){
+this.deferred=_2ee;
+});
+ne("BrowserComplianceError",function(msg){
+this.message=msg;
+});
+ne("GenericError",function(msg){
+this.message=msg;
+});
+ne("XMLHttpRequestError",function(req,msg){
+this.req=req;
+this.message=msg;
+try{
+this.number=req.status;
+}
+catch(e){
+}
+});
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Async.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Async);
+MochiKit.Base._deps("DOM",["Base"]);
+MochiKit.DOM.NAME="MochiKit.DOM";
+MochiKit.DOM.VERSION="1.4.2";
+MochiKit.DOM.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DOM.toString=function(){
+return this.__repr__();
+};
+MochiKit.DOM.EXPORT=["removeEmptyTextNodes","formContents","currentWindow","currentDocument","withWindow","withDocument","registerDOMConverter","coerceToDOM","createDOM","createDOMFunc","isChildNode","getNodeAttribute","removeNodeAttribute","setNodeAttribute","updateNodeAttributes","appendChildNodes","insertSiblingNodesAfter","insertSiblingNodesBefore","replaceChildNodes","removeElement","swapDOM","BUTTON","TT","PRE","H1","H2","H3","H4","H5","H6","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","DL","DT","DD","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG","getElement","$","getElementsByTagAndClassName","addToCallStack","addLoadEvent","focusOnLoad","setElementClass","toggleElementClass","addElementClass","removeElementClass","swapElementClass","hasElementClass","computedStyle","escapeHTML","toHTML","emitHTML","scrapeText","getFirstParentByTagAndClassName","getFirstElementBy
 TagAndClassName"];
+MochiKit.DOM.EXPORT_OK=["domConverters"];
+MochiKit.DOM.DEPRECATED=[["computedStyle","MochiKit.Style.getStyle","1.4"],["elementDimensions","MochiKit.Style.getElementDimensions","1.4"],["elementPosition","MochiKit.Style.getElementPosition","1.4"],["getViewportDimensions","MochiKit.Style.getViewportDimensions","1.4"],["hideElement","MochiKit.Style.hideElement","1.4"],["makeClipping","MochiKit.Style.makeClipping","1.4.1"],["makePositioned","MochiKit.Style.makePositioned","1.4.1"],["setElementDimensions","MochiKit.Style.setElementDimensions","1.4"],["setElementPosition","MochiKit.Style.setElementPosition","1.4"],["setDisplayForElement","MochiKit.Style.setDisplayForElement","1.4"],["setOpacity","MochiKit.Style.setOpacity","1.4"],["showElement","MochiKit.Style.showElement","1.4"],["undoClipping","MochiKit.Style.undoClipping","1.4.1"],["undoPositioned","MochiKit.Style.undoPositioned","1.4.1"],["Coordinates","MochiKit.Style.Coordinates","1.4"],["Dimensions","MochiKit.Style.Dimensions","1.4"]];
+MochiKit.Base.update(MochiKit.DOM,{currentWindow:function(){
+return MochiKit.DOM._window;
+},currentDocument:function(){
+return MochiKit.DOM._document;
+},withWindow:function(win,func){
+var self=MochiKit.DOM;
+var _2f6=self._document;
+var _2f7=self._window;
+var rval;
+try{
+self._window=win;
+self._document=win.document;
+rval=func();
+}
+catch(e){
+self._window=_2f7;
+self._document=_2f6;
+throw e;
+}
+self._window=_2f7;
+self._document=_2f6;
+return rval;
+},formContents:function(elem){
+var _2fa=[];
+var _2fb=[];
+var m=MochiKit.Base;
+var self=MochiKit.DOM;
+if(typeof (elem)=="undefined"||elem===null){
+elem=self._document.body;
+}else{
+elem=self.getElement(elem);
+}
+m.nodeWalk(elem,function(elem){
+var name=elem.name;
+if(m.isNotEmpty(name)){
+var _300=elem.tagName.toUpperCase();
+if(_300==="INPUT"&&(elem.type=="radio"||elem.type=="checkbox")&&!elem.checked){
+return null;
+}
+if(_300==="SELECT"){
+if(elem.type=="select-one"){
+if(elem.selectedIndex>=0){
+var opt=elem.options[elem.selectedIndex];
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2fa.push(name);
+_2fb.push(v);
+return null;
+}
+_2fa.push(name);
+_2fb.push("");
+return null;
+}else{
+var opts=elem.options;
+if(!opts.length){
+_2fa.push(name);
+_2fb.push("");
+return null;
+}
+for(var i=0;i<opts.length;i++){
+var opt=opts[i];
+if(!opt.selected){
+continue;
+}
+var v=opt.value;
+if(!v){
+var h=opt.outerHTML;
+if(h&&!h.match(/^[^>]+\svalue\s*=/i)){
+v=opt.text;
+}
+}
+_2fa.push(name);
+_2fb.push(v);
+}
+return null;
+}
+}
+if(_300==="FORM"||_300==="P"||_300==="SPAN"||_300==="DIV"){
+return elem.childNodes;
+}
+_2fa.push(name);
+_2fb.push(elem.value||"");
+return null;
+}
+return elem.childNodes;
+});
+return [_2fa,_2fb];
+},withDocument:function(doc,func){
+var self=MochiKit.DOM;
+var _309=self._document;
+var rval;
+try{
+self._document=doc;
+rval=func();
+}
+catch(e){
+self._document=_309;
+throw e;
+}
+self._document=_309;
+return rval;
+},registerDOMConverter:function(name,_30c,wrap,_30e){
+MochiKit.DOM.domConverters.register(name,_30c,wrap,_30e);
+},coerceToDOM:function(node,ctx){
+var m=MochiKit.Base;
+var im=MochiKit.Iter;
+var self=MochiKit.DOM;
+if(im){
+var iter=im.iter;
+var _315=im.repeat;
+}
+var map=m.map;
+var _317=self.domConverters;
+var _318=arguments.callee;
+var _319=m.NotFound;
+while(true){
+if(typeof (node)=="undefined"||node===null){
+return null;
+}
+if(typeof (node)=="function"&&typeof (node.length)=="number"&&!(node instanceof Function)){
+node=im?im.list(node):m.extend(null,node);
+}
+if(typeof (node.nodeType)!="undefined"&&node.nodeType>0){
+return node;
+}
+if(typeof (node)=="number"||typeof (node)=="boolean"){
+node=node.toString();
+}
+if(typeof (node)=="string"){
+return self._document.createTextNode(node);
+}
+if(typeof (node.__dom__)=="function"){
+node=node.__dom__(ctx);
+continue;
+}
+if(typeof (node.dom)=="function"){
+node=node.dom(ctx);
+continue;
+}
+if(typeof (node)=="function"){
+node=node.apply(ctx,[ctx]);
+continue;
+}
+if(im){
+var _31a=null;
+try{
+_31a=iter(node);
+}
+catch(e){
+}
+if(_31a){
+return map(_318,_31a,_315(ctx));
+}
+}else{
+if(m.isArrayLike(node)){
+var func=function(n){
+return _318(n,ctx);
+};
+return map(func,node);
+}
+}
+try{
+node=_317.match(node,ctx);
+continue;
+}
+catch(e){
+if(e!=_319){
+throw e;
+}
+}
+return self._document.createTextNode(node.toString());
+}
+return undefined;
+},isChildNode:function(node,_31e){
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+node=self.getElement(node);
+}
+if(typeof (_31e)=="string"){
+_31e=self.getElement(_31e);
+}
+if(typeof (node)=="undefined"||node===null){
+return false;
+}
+while(node!=null&&node!==self._document){
+if(node===_31e){
+return true;
+}
+node=node.parentNode;
+}
+return false;
+},setNodeAttribute:function(node,attr,_322){
+var o={};
+o[attr]=_322;
+try{
+return MochiKit.DOM.updateNodeAttributes(node,o);
+}
+catch(e){
+}
+return null;
+},getNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _327=self.attributeArray.renames[attr];
+var _328=self.attributeArray.ignoreAttr[attr];
+node=self.getElement(node);
+try{
+if(_327){
+return node[_327];
+}
+var _329=node.getAttribute(attr);
+if(_329!=_328){
+return _329;
+}
+}
+catch(e){
+}
+return null;
+},removeNodeAttribute:function(node,attr){
+var self=MochiKit.DOM;
+var _32d=self.attributeArray.renames[attr];
+node=self.getElement(node);
+try{
+if(_32d){
+return node[_32d];
+}
+return node.removeAttribute(attr);
+}
+catch(e){
+}
+return null;
+},updateNodeAttributes:function(node,_32f){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+if(_32f){
+var _332=MochiKit.Base.updatetree;
+if(self.attributeArray.compliant){
+for(var k in _32f){
+var v=_32f[k];
+if(typeof (v)=="object"&&typeof (elem[k])=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_332(elem[k],v);
+}
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+if(typeof (elem[k])=="string"&&elem[k]!=v){
+elem[k]=v;
+}
+}
+}else{
+var _335=self.attributeArray.renames;
+for(var k in _32f){
+v=_32f[k];
+var _336=_335[k];
+if(k=="style"&&typeof (v)=="string"){
+elem.style.cssText=v;
+}else{
+if(typeof (_336)=="string"){
+elem[_336]=v;
+}else{
+if(typeof (elem[k])=="object"&&typeof (v)=="object"){
+if(k=="style"&&MochiKit.Style){
+MochiKit.Style.setStyle(elem,v);
+}else{
+_332(elem[k],v);
+}
+}else{
+if(k.substring(0,2)=="on"){
+if(typeof (v)=="string"){
+v=new Function(v);
+}
+elem[k]=v;
+}else{
+elem.setAttribute(k,v);
+}
+}
+}
+}
+if(typeof (elem[k])=="string"&&elem[k]!=v){
+elem[k]=v;
+}
+}
+}
+}
+return elem;
+},appendChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _33a=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _33b=MochiKit.Base.concat;
+while(_33a.length){
+var n=_33a.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+elem.appendChild(n);
+}else{
+_33a=_33b(n,_33a);
+}
+}
+}
+return elem;
+},insertSiblingNodesBefore:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _340=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+var _341=elem.parentNode;
+var _342=MochiKit.Base.concat;
+while(_340.length){
+var n=_340.shift();
+if(typeof (n)=="undefined"||n===null){
+}else{
+if(typeof (n.nodeType)=="number"){
+_341.insertBefore(n,elem);
+}else{
+_340=_342(n,_340);
+}
+}
+}
+return _341;
+},insertSiblingNodesAfter:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+}
+var _347=[self.coerceToDOM(MochiKit.Base.extend(null,arguments,1),elem)];
+if(elem.nextSibling){
+return self.insertSiblingNodesBefore(elem.nextSibling,_347);
+}else{
+return self.appendChildNodes(elem.parentNode,_347);
+}
+},replaceChildNodes:function(node){
+var elem=node;
+var self=MochiKit.DOM;
+if(typeof (node)=="string"){
+elem=self.getElement(node);
+arguments[0]=elem;
+}
+var _34b;
+while((_34b=elem.firstChild)){
+elem.removeChild(_34b);
+}
+if(arguments.length<2){
+return elem;
+}else{
+return self.appendChildNodes.apply(this,arguments);
+}
+},createDOM:function(name,_34d){
+var elem;
+var self=MochiKit.DOM;
+var m=MochiKit.Base;
+if(typeof (_34d)=="string"||typeof (_34d)=="number"){
+var args=m.extend([name,null],arguments,1);
+return arguments.callee.apply(this,args);
+}
+if(typeof (name)=="string"){
+var _352=self._xhtml;
+if(_34d&&!self.attributeArray.compliant){
+var _353="";
+if("name" in _34d){
+_353+=" name=\""+self.escapeHTML(_34d.name)+"\"";
+}
+if(name=="input"&&"type" in _34d){
+_353+=" type=\""+self.escapeHTML(_34d.type)+"\"";
+}
+if(_353){
+name="<"+name+_353+">";
+_352=false;
+}
+}
+var d=self._document;
+if(_352&&d===document){
+elem=d.createElementNS("http://www.w3.org/1999/xhtml",name);
+}else{
+elem=d.createElement(name);
+}
+}else{
+elem=name;
+}
+if(_34d){
+self.updateNodeAttributes(elem,_34d);
+}
+if(arguments.length<=2){
+return elem;
+}else{
+var args=m.extend([elem],arguments,2);
+return self.appendChildNodes.apply(this,args);
+}
+},createDOMFunc:function(){
+var m=MochiKit.Base;
+return m.partial.apply(this,m.extend([MochiKit.DOM.createDOM],arguments));
+},removeElement:function(elem){
+var self=MochiKit.DOM;
+var e=self.coerceToDOM(self.getElement(elem));
+e.parentNode.removeChild(e);
+return e;
+},swapDOM:function(dest,src){
+var self=MochiKit.DOM;
+dest=self.getElement(dest);
+var _35c=dest.parentNode;
+if(src){
+src=self.coerceToDOM(self.getElement(src),_35c);
+_35c.replaceChild(src,dest);
+}else{
+_35c.removeChild(dest);
+}
+return src;
+},getElement:function(id){
+var self=MochiKit.DOM;
+if(arguments.length==1){
+return ((typeof (id)=="string")?self._document.getElementById(id):id);
+}else{
+return MochiKit.Base.map(self.getElement,arguments);
+}
+},getElementsByTagAndClassName:function(_35f,_360,_361){
+var self=MochiKit.DOM;
+if(typeof (_35f)=="undefined"||_35f===null){
+_35f="*";
+}
+if(typeof (_361)=="undefined"||_361===null){
+_361=self._document;
+}
+_361=self.getElement(_361);
+if(_361==null){
+return [];
+}
+var _363=(_361.getElementsByTagName(_35f)||self._document.all);
+if(typeof (_360)=="undefined"||_360===null){
+return MochiKit.Base.extend(null,_363);
+}
+var _364=[];
+for(var i=0;i<_363.length;i++){
+var _366=_363[i];
+var cls=_366.className;
+if(typeof (cls)!="string"){
+cls=_366.getAttribute("class");
+}
+if(typeof (cls)=="string"){
+var _368=cls.split(" ");
+for(var j=0;j<_368.length;j++){
+if(_368[j]==_360){
+_364.push(_366);
+break;
+}
+}
+}
+}
+return _364;
+},_newCallStack:function(path,once){
+var rval=function(){
+var _36d=arguments.callee.callStack;
+for(var i=0;i<_36d.length;i++){
+if(_36d[i].apply(this,arguments)===false){
+break;
+}
+}
+if(once){
+try{
+this[path]=null;
+}
+catch(e){
+}
+}
+};
+rval.callStack=[];
+return rval;
+},addToCallStack:function(_36f,path,func,once){
+var self=MochiKit.DOM;
+var _374=_36f[path];
+var _375=_374;
+if(!(typeof (_374)=="function"&&typeof (_374.callStack)=="object"&&_374.callStack!==null)){
+_375=self._newCallStack(path,once);
+if(typeof (_374)=="function"){
+_375.callStack.push(_374);
+}
+_36f[path]=_375;
+}
+_375.callStack.push(func);
+},addLoadEvent:function(func){
+var self=MochiKit.DOM;
+self.addToCallStack(self._window,"onload",func,true);
+},focusOnLoad:function(_378){
+var self=MochiKit.DOM;
+self.addLoadEvent(function(){
+_378=self.getElement(_378);
+if(_378){
+_378.focus();
+}
+});
+},setElementClass:function(_37a,_37b){
+var self=MochiKit.DOM;
+var obj=self.getElement(_37a);
+if(self.attributeArray.compliant){
+obj.setAttribute("class",_37b);
+}else{
+obj.setAttribute("className",_37b);
+}
+},toggleElementClass:function(_37e){
+var self=MochiKit.DOM;
+for(var i=1;i<arguments.length;i++){
+var obj=self.getElement(arguments[i]);
+if(!self.addElementClass(obj,_37e)){
+self.removeElementClass(obj,_37e);
+}
+}
+},addElementClass:function(_382,_383){
+var self=MochiKit.DOM;
+var obj=self.getElement(_382);
+var cls=obj.className;
+if(typeof (cls)!="string"){
+cls=obj.getAttribute("class");
+}
+if(typeof (cls)!="string"||cls.length===0){
+self.setElementClass(obj,_383);
+return true;
+}
+if(cls==_383){
+return false;
+}
+var _387=cls.split(" ");
+for(var i=0;i<_387.length;i++){
+if(_387[i]==_383){
+return false;
+}
+}
+self.setElementClass(obj,cls+" "+_383);
+return true;
+},removeElementClass:function(_389,_38a){
+var self=MochiKit.DOM;
+var obj=self.getElement(_389);
+var cls=obj.className;
+if(typeof (cls)!="string"){
+cls=obj.getAttribute("class");
+}
+if(typeof (cls)!="string"||cls.length===0){
+return false;
+}
+if(cls==_38a){
+self.setElementClass(obj,"");
+return true;
+}
+var _38e=cls.split(" ");
+for(var i=0;i<_38e.length;i++){
+if(_38e[i]==_38a){
+_38e.splice(i,1);
+self.setElementClass(obj,_38e.join(" "));
+return true;
+}
+}
+return false;
+},swapElementClass:function(_390,_391,_392){
+var obj=MochiKit.DOM.getElement(_390);
+var res=MochiKit.DOM.removeElementClass(obj,_391);
+if(res){
+MochiKit.DOM.addElementClass(obj,_392);
+}
+return res;
+},hasElementClass:function(_395,_396){
+var obj=MochiKit.DOM.getElement(_395);
+if(obj==null){
+return false;
+}
+var cls=obj.className;
+if(typeof (cls)!="string"){
+cls=obj.getAttribute("class");
+}
+if(typeof (cls)!="string"){
+return false;
+}
+var _399=cls.split(" ");
+for(var i=1;i<arguments.length;i++){
+var good=false;
+for(var j=0;j<_399.length;j++){
+if(_399[j]==arguments[i]){
+good=true;
+break;
+}
+}
+if(!good){
+return false;
+}
+}
+return true;
+},escapeHTML:function(s){
+return s.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+},toHTML:function(dom){
+return MochiKit.DOM.emitHTML(dom).join("");
+},emitHTML:function(dom,lst){
+if(typeof (lst)=="undefined"||lst===null){
+lst=[];
+}
+var _3a1=[dom];
+var self=MochiKit.DOM;
+var _3a3=self.escapeHTML;
+var _3a4=self.attributeArray;
+while(_3a1.length){
+dom=_3a1.pop();
+if(typeof (dom)=="string"){
+lst.push(dom);
+}else{
+if(dom.nodeType==1){
+lst.push("<"+dom.tagName.toLowerCase());
+var _3a5=[];
+var _3a6=_3a4(dom);
+for(var i=0;i<_3a6.length;i++){
+var a=_3a6[i];
+_3a5.push([" ",a.name,"=\"",_3a3(a.value),"\""]);
+}
+_3a5.sort();
+for(i=0;i<_3a5.length;i++){
+var _3a9=_3a5[i];
+for(var j=0;j<_3a9.length;j++){
+lst.push(_3a9[j]);
+}
+}
+if(dom.hasChildNodes()){
+lst.push(">");
+_3a1.push("</"+dom.tagName.toLowerCase()+">");
+var _3ab=dom.childNodes;
+for(i=_3ab.length-1;i>=0;i--){
+_3a1.push(_3ab[i]);
+}
+}else{
+lst.push("/>");
+}
+}else{
+if(dom.nodeType==3){
+lst.push(_3a3(dom.nodeValue));
+}
+}
+}
+}
+return lst;
+},scrapeText:function(node,_3ad){
+var rval=[];
+(function(node){
+var cn=node.childNodes;
+if(cn){
+for(var i=0;i<cn.length;i++){
+arguments.callee.call(this,cn[i]);
+}
+}
+var _3b2=node.nodeValue;
+if(typeof (_3b2)=="string"){
+rval.push(_3b2);
+}
+})(MochiKit.DOM.getElement(node));
+if(_3ad){
+return rval;
+}else{
+return rval.join("");
+}
+},removeEmptyTextNodes:function(_3b3){
+_3b3=MochiKit.DOM.getElement(_3b3);
+for(var i=0;i<_3b3.childNodes.length;i++){
+var node=_3b3.childNodes[i];
+if(node.nodeType==3&&!/\S/.test(node.nodeValue)){
+node.parentNode.removeChild(node);
+}
+}
+},getFirstElementByTagAndClassName:function(_3b6,_3b7,_3b8){
+var self=MochiKit.DOM;
+if(typeof (_3b6)=="undefined"||_3b6===null){
+_3b6="*";
+}
+if(typeof (_3b8)=="undefined"||_3b8===null){
+_3b8=self._document;
+}
+_3b8=self.getElement(_3b8);
+if(_3b8==null){
+return null;
+}
+var _3ba=(_3b8.getElementsByTagName(_3b6)||self._document.all);
+if(_3ba.length<=0){
+return null;
+}else{
+if(typeof (_3b7)=="undefined"||_3b7===null){
+return _3ba[0];
+}
+}
+for(var i=0;i<_3ba.length;i++){
+var _3bc=_3ba[i];
+var cls=_3bc.className;
+if(typeof (cls)!="string"){
+cls=_3bc.getAttribute("class");
+}
+if(typeof (cls)=="string"){
+var _3be=cls.split(" ");
+for(var j=0;j<_3be.length;j++){
+if(_3be[j]==_3b7){
+return _3bc;
+}
+}
+}
+}
+return null;
+},getFirstParentByTagAndClassName:function(elem,_3c1,_3c2){
+var self=MochiKit.DOM;
+elem=self.getElement(elem);
+if(typeof (_3c1)=="undefined"||_3c1===null){
+_3c1="*";
+}else{
+_3c1=_3c1.toUpperCase();
+}
+if(typeof (_3c2)=="undefined"||_3c2===null){
+_3c2=null;
+}
+if(elem){
+elem=elem.parentNode;
+}
+while(elem&&elem.tagName){
+var _3c4=elem.tagName.toUpperCase();
+if((_3c1==="*"||_3c1==_3c4)&&(_3c2===null||self.hasElementClass(elem,_3c2))){
+return elem;
+}
+elem=elem.parentNode;
+}
+return null;
+},__new__:function(win){
+var m=MochiKit.Base;
+if(typeof (document)!="undefined"){
+this._document=document;
+var _3c7="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+this._xhtml=(document.documentElement&&document.createElementNS&&document.documentElement.namespaceURI===_3c7);
+}else{
+if(MochiKit.MockDOM){
+this._document=MochiKit.MockDOM.document;
+}
+}
+this._window=win;
+this.domConverters=new m.AdapterRegistry();
+var _3c8=this._document.createElement("span");
+var _3c9;
+if(_3c8&&_3c8.attributes&&_3c8.attributes.length>0){
+var _3ca=m.filter;
+_3c9=function(node){
+return _3ca(_3c9.ignoreAttrFilter,node.attributes);
+};
+_3c9.ignoreAttr={};
+var _3cc=_3c8.attributes;
+var _3cd=_3c9.ignoreAttr;
+for(var i=0;i<_3cc.length;i++){
+var a=_3cc[i];
+_3cd[a.name]=a.value;
+}
+_3c9.ignoreAttrFilter=function(a){
+return (_3c9.ignoreAttr[a.name]!=a.value);
+};
+_3c9.compliant=false;
+_3c9.renames={"class":"className","checked":"defaultChecked","usemap":"useMap","for":"htmlFor","readonly":"readOnly","colspan":"colSpan","bgcolor":"bgColor","cellspacing":"cellSpacing","cellpadding":"cellPadding"};
+}else{
+_3c9=function(node){
+return node.attributes;
+};
+_3c9.compliant=true;
+_3c9.ignoreAttr={};
+_3c9.renames={};
+}
+this.attributeArray=_3c9;
+var _3d2=function(_3d3,arr){
+var _3d5=arr[0];
+var _3d6=arr[1];
+var _3d7=_3d6.split(".")[1];
+var str="";
+str+="if (!MochiKit."+_3d7+") { throw new Error(\"";
+str+="This function has been deprecated and depends on MochiKit.";
+str+=_3d7+".\");}";
+str+="return "+_3d6+".apply(this, arguments);";
+MochiKit[_3d3][_3d5]=new Function(str);
+};
+for(var i=0;i<MochiKit.DOM.DEPRECATED.length;i++){
+_3d2("DOM",MochiKit.DOM.DEPRECATED[i]);
+}
+var _3d9=this.createDOMFunc;
+this.UL=_3d9("ul");
+this.OL=_3d9("ol");
+this.LI=_3d9("li");
+this.DL=_3d9("dl");
+this.DT=_3d9("dt");
+this.DD=_3d9("dd");
+this.TD=_3d9("td");
+this.TR=_3d9("tr");
+this.TBODY=_3d9("tbody");
+this.THEAD=_3d9("thead");
+this.TFOOT=_3d9("tfoot");
+this.TABLE=_3d9("table");
+this.TH=_3d9("th");
+this.INPUT=_3d9("input");
+this.SPAN=_3d9("span");
+this.A=_3d9("a");
+this.DIV=_3d9("div");
+this.IMG=_3d9("img");
+this.BUTTON=_3d9("button");
+this.TT=_3d9("tt");
+this.PRE=_3d9("pre");
+this.H1=_3d9("h1");
+this.H2=_3d9("h2");
+this.H3=_3d9("h3");
+this.H4=_3d9("h4");
+this.H5=_3d9("h5");
+this.H6=_3d9("h6");
+this.BR=_3d9("br");
+this.HR=_3d9("hr");
+this.LABEL=_3d9("label");
+this.TEXTAREA=_3d9("textarea");
+this.FORM=_3d9("form");
+this.P=_3d9("p");
+this.SELECT=_3d9("select");
+this.OPTION=_3d9("option");
+this.OPTGROUP=_3d9("optgroup");
+this.LEGEND=_3d9("legend");
+this.FIELDSET=_3d9("fieldset");
+this.STRONG=_3d9("strong");
+this.CANVAS=_3d9("canvas");
+this.$=this.getElement;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.DOM.__new__(((typeof (window)=="undefined")?this:window));
+if(MochiKit.__export__){
+withWindow=MochiKit.DOM.withWindow;
+withDocument=MochiKit.DOM.withDocument;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.DOM);
+MochiKit.Base._deps("Selector",["Base","DOM","Iter"]);
+MochiKit.Selector.NAME="MochiKit.Selector";
+MochiKit.Selector.VERSION="1.4.2";
+MochiKit.Selector.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Selector.toString=function(){
+return this.__repr__();
+};
+MochiKit.Selector.EXPORT=["Selector","findChildElements","findDocElements","$$"];
+MochiKit.Selector.EXPORT_OK=[];
+MochiKit.Selector.Selector=function(_3da){
+this.params={classNames:[],pseudoClassNames:[]};
+this.expression=_3da.toString().replace(/(^\s+|\s+$)/g,"");
+this.parseExpression();
+this.compileMatcher();
+};
+MochiKit.Selector.Selector.prototype={__class__:MochiKit.Selector.Selector,parseExpression:function(){
+function abort(_3db){
+throw "Parse error in selector: "+_3db;
+}
+if(this.expression==""){
+abort("empty expression");
+}
+var repr=MochiKit.Base.repr;
+var _3dd=this.params;
+var expr=this.expression;
+var _3df,_3e0,_3e1,rest;
+while(_3df=expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)){
+_3dd.attributes=_3dd.attributes||[];
+_3dd.attributes.push({name:_3df[2],operator:_3df[3],value:_3df[4]||_3df[5]||""});
+expr=_3df[1];
+}
+if(expr=="*"){
+return this.params.wildcard=true;
+}
+while(_3df=expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)){
+_3e0=_3df[1];
+_3e1=_3df[2];
+rest=_3df[3];
+switch(_3e0){
+case "#":
+_3dd.id=_3e1;
+break;
+case ".":
+_3dd.classNames.push(_3e1);
+break;
+case ":":
+_3dd.pseudoClassNames.push(_3e1);
+break;
+case "":
+case undefined:
+_3dd.tagName=_3e1.toUpperCase();
+break;
+default:
+abort(repr(expr));
+}
+expr=rest;
+}
+if(expr.length>0){
+abort(repr(expr));
+}
+},buildMatchExpression:function(){
+var repr=MochiKit.Base.repr;
+var _3e4=this.params;
+var _3e5=[];
+var _3e6,i;
+function childElements(_3e8){
+return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, "+_3e8+".childNodes)";
+}
+if(_3e4.wildcard){
+_3e5.push("true");
+}
+if(_3e6=_3e4.id){
+_3e5.push("element.id == "+repr(_3e6));
+}
+if(_3e6=_3e4.tagName){
+_3e5.push("element.tagName.toUpperCase() == "+repr(_3e6));
+}
+if((_3e6=_3e4.classNames).length>0){
+for(i=0;i<_3e6.length;i++){
+_3e5.push("MochiKit.DOM.hasElementClass(element, "+repr(_3e6[i])+")");
+}
+}
+if((_3e6=_3e4.pseudoClassNames).length>0){
+for(i=0;i<_3e6.length;i++){
+var _3e9=_3e6[i].match(/^([^(]+)(?:\((.*)\))?$/);
+var _3ea=_3e9[1];
+var _3eb=_3e9[2];
+switch(_3ea){
+case "root":
+_3e5.push("element.nodeType == 9 || element === element.ownerDocument.documentElement");
+break;
+case "nth-child":
+case "nth-last-child":
+case "nth-of-type":
+case "nth-last-of-type":
+_3e9=_3eb.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
+if(!_3e9){
+throw "Invalid argument to pseudo element nth-child: "+_3eb;
+}
+var a,b;
+if(_3e9[0]=="odd"){
+a=2;
+b=1;
+}else{
+if(_3e9[0]=="even"){
+a=2;
+b=0;
+}else{
+a=_3e9[2]&&parseInt(_3e9)||null;
+b=parseInt(_3e9[3]);
+}
+}
+_3e5.push("this.nthChild(element,"+a+","+b+","+!!_3ea.match("^nth-last")+","+!!_3ea.match("of-type$")+")");
+break;
+case "first-child":
+_3e5.push("this.nthChild(element, null, 1)");
+break;
+case "last-child":
+_3e5.push("this.nthChild(element, null, 1, true)");
+break;
+case "first-of-type":
+_3e5.push("this.nthChild(element, null, 1, false, true)");
+break;
+case "last-of-type":
+_3e5.push("this.nthChild(element, null, 1, true, true)");
+break;
+case "only-child":
+_3e5.push(childElements("element.parentNode")+".length == 1");
+break;
+case "only-of-type":
+_3e5.push("MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, "+childElements("element.parentNode")+").length == 1");
+break;
+case "empty":
+_3e5.push("element.childNodes.length == 0");
+break;
+case "enabled":
+_3e5.push("(this.isUIElement(element) && element.disabled === false)");
+break;
+case "disabled":
+_3e5.push("(this.isUIElement(element) && element.disabled === true)");
+break;
+case "checked":
+_3e5.push("(this.isUIElement(element) && element.checked === true)");
+break;
+case "not":
+var _3ee=new MochiKit.Selector.Selector(_3eb);
+_3e5.push("!( "+_3ee.buildMatchExpression()+")");
+break;
+}
+}
+}
+if(_3e6=_3e4.attributes){
+MochiKit.Base.map(function(_3ef){
+var _3f0="MochiKit.DOM.getNodeAttribute(element, "+repr(_3ef.name)+")";
+var _3f1=function(_3f2){
+return _3f0+".split("+repr(_3f2)+")";
+};
+_3e5.push(_3f0+" != null");
+switch(_3ef.operator){
+case "=":
+_3e5.push(_3f0+" == "+repr(_3ef.value));
+break;
+case "~=":
+_3e5.push("MochiKit.Base.findValue("+_3f1(" ")+", "+repr(_3ef.value)+") > -1");
+break;
+case "^=":
+_3e5.push(_3f0+".substring(0, "+_3ef.value.length+") == "+repr(_3ef.value));
+break;
+case "$=":
+_3e5.push(_3f0+".substring("+_3f0+".length - "+_3ef.value.length+") == "+repr(_3ef.value));
+break;
+case "*=":
+_3e5.push(_3f0+".match("+repr(_3ef.value)+")");
+break;
+case "|=":
+_3e5.push(_3f1("-")+"[0].toUpperCase() == "+repr(_3ef.value.toUpperCase()));
+break;
+case "!=":
+_3e5.push(_3f0+" != "+repr(_3ef.value));
+break;
+case "":
+case undefined:
+break;
+default:
+throw "Unknown operator "+_3ef.operator+" in selector";
+}
+},_3e6);
+}
+return _3e5.join(" && ");
+},compileMatcher:function(){
+var code="return (!element.tagName) ? false : "+this.buildMatchExpression()+";";
+this.match=new Function("element",code);
+},nthChild:function(_3f4,a,b,_3f7,_3f8){
+var _3f9=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3f4.parentNode.childNodes);
+if(_3f8){
+_3f9=MochiKit.Base.filter(function(node){
+return node.tagName==_3f4.tagName;
+},_3f9);
+}
+if(_3f7){
+_3f9=MochiKit.Iter.reversed(_3f9);
+}
+if(a){
+var _3fc=MochiKit.Base.findIdentical(_3f9,_3f4);
+return ((_3fc+1-b)/a)%1==0;
+}else{
+return b==MochiKit.Base.findIdentical(_3f9,_3f4)+1;
+}
+},isUIElement:function(_3fd){
+return MochiKit.Base.findValue(["input","button","select","option","textarea","object"],_3fd.tagName.toLowerCase())>-1;
+},findElements:function(_3fe,axis){
+var _400;
+if(axis==undefined){
+axis="";
+}
+function inScope(_401,_402){
+if(axis==""){
+return MochiKit.DOM.isChildNode(_401,_402);
+}else{
+if(axis==">"){
+return _401.parentNode===_402;
+}else{
+if(axis=="+"){
+return _401===nextSiblingElement(_402);
+}else{
+if(axis=="~"){
+var _403=_402;
+while(_403=nextSiblingElement(_403)){
+if(_401===_403){
+return true;
+}
+}
+return false;
+}else{
+throw "Invalid axis: "+axis;
+}
+}
+}
+}
+}
+if(_400=MochiKit.DOM.getElement(this.params.id)){
+if(this.match(_400)){
+if(!_3fe||inScope(_400,_3fe)){
+return [_400];
+}
+}
+}
+function nextSiblingElement(node){
+node=node.nextSibling;
+while(node&&node.nodeType!=1){
+node=node.nextSibling;
+}
+return node;
+}
+if(axis==""){
+_3fe=(_3fe||MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName||"*");
+}else{
+if(axis==">"){
+if(!_3fe){
+throw "> combinator not allowed without preceeding expression";
+}
+_3fe=MochiKit.Base.filter(function(node){
+return node.nodeType==1;
+},_3fe.childNodes);
+}else{
+if(axis=="+"){
+if(!_3fe){
+throw "+ combinator not allowed without preceeding expression";
+}
+_3fe=nextSiblingElement(_3fe)&&[nextSiblingElement(_3fe)];
+}else{
+if(axis=="~"){
+if(!_3fe){
+throw "~ combinator not allowed without preceeding expression";
+}
+var _406=[];
+while(nextSiblingElement(_3fe)){
+_3fe=nextSiblingElement(_3fe);
+_406.push(_3fe);
+}
+_3fe=_406;
+}
+}
+}
+}
+if(!_3fe){
+return [];
+}
+var _407=MochiKit.Base.filter(MochiKit.Base.bind(function(_408){
+return this.match(_408);
+},this),_3fe);
+return _407;
+},repr:function(){
+return "Selector("+this.expression+")";
+},toString:MochiKit.Base.forwardCall("repr")};
+MochiKit.Base.update(MochiKit.Selector,{findChildElements:function(_409,_40a){
+var uniq=function(arr){
+var res=[];
+for(var i=0;i<arr.length;i++){
+if(MochiKit.Base.findIdentical(res,arr[i])<0){
+res.push(arr[i]);
+}
+}
+return res;
+};
+return MochiKit.Base.flattenArray(MochiKit.Base.map(function(_40f){
+var _410="";
+var _411=function(_412,expr){
+if(match=expr.match(/^[>+~]$/)){
+_410=match[0];
+return _412;
+}else{
+var _414=new MochiKit.Selector.Selector(expr);
+var _415=MochiKit.Iter.reduce(function(_416,_417){
+return MochiKit.Base.extend(_416,_414.findElements(_417||_409,_410));
+},_412,[]);
+_410="";
+return _415;
+}
+};
+var _418=_40f.replace(/(^\s+|\s+$)/g,"").split(/\s+/);
+return uniq(MochiKit.Iter.reduce(_411,_418,[null]));
+},_40a));
+},findDocElements:function(){
+return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(),arguments);
+},__new__:function(){
+var m=MochiKit.Base;
+this.$$=this.findDocElements;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Selector.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Selector);
+MochiKit.Base._deps("Style",["Base","DOM"]);
+MochiKit.Style.NAME="MochiKit.Style";
+MochiKit.Style.VERSION="1.4.2";
+MochiKit.Style.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Style.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.EXPORT_OK=[];
+MochiKit.Style.EXPORT=["setStyle","setOpacity","getStyle","getElementDimensions","elementDimensions","setElementDimensions","getElementPosition","elementPosition","setElementPosition","makePositioned","undoPositioned","makeClipping","undoClipping","setDisplayForElement","hideElement","showElement","getViewportDimensions","getViewportPosition","Dimensions","Coordinates"];
+MochiKit.Style.Dimensions=function(w,h){
+this.w=w;
+this.h=h;
+};
+MochiKit.Style.Dimensions.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{w: "+repr(this.w)+", h: "+repr(this.h)+"}";
+};
+MochiKit.Style.Dimensions.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Style.Coordinates=function(x,y){
+this.x=x;
+this.y=y;
+};
+MochiKit.Style.Coordinates.prototype.__repr__=function(){
+var repr=MochiKit.Base.repr;
+return "{x: "+repr(this.x)+", y: "+repr(this.y)+"}";
+};
+MochiKit.Style.Coordinates.prototype.toString=function(){
+return this.__repr__();
+};
+MochiKit.Base.update(MochiKit.Style,{getStyle:function(elem,_421){
+var dom=MochiKit.DOM;
+var d=dom._document;
+elem=dom.getElement(elem);
+_421=MochiKit.Base.camelize(_421);
+if(!elem||elem==d){
+return undefined;
+}
+if(_421=="opacity"&&typeof (elem.filters)!="undefined"){
+var _424=(MochiKit.Style.getStyle(elem,"filter")||"").match(/alpha\(opacity=(.*)\)/);
+if(_424&&_424[1]){
+return parseFloat(_424[1])/100;
+}
+return 1;
+}
+if(_421=="float"||_421=="cssFloat"||_421=="styleFloat"){
+if(elem.style["float"]){
+return elem.style["float"];
+}else{
+if(elem.style.cssFloat){
+return elem.style.cssFloat;
+}else{
+if(elem.style.styleFloat){
+return elem.style.styleFloat;
+}else{
+return "none";
+}
+}
+}
+}
+var _425=elem.style?elem.style[_421]:null;
+if(!_425){
+if(d.defaultView&&d.defaultView.getComputedStyle){
+var css=d.defaultView.getComputedStyle(elem,null);
+_421=_421.replace(/([A-Z])/g,"-$1").toLowerCase();
+_425=css?css.getPropertyValue(_421):null;
+}else{
+if(elem.currentStyle){
+_425=elem.currentStyle[_421];
+if(/^\d/.test(_425)&&!/px$/.test(_425)&&_421!="fontWeight"){
+var left=elem.style.left;
+var _428=elem.runtimeStyle.left;
+elem.runtimeStyle.left=elem.currentStyle.left;
+elem.style.left=_425||0;
+_425=elem.style.pixelLeft+"px";
+elem.style.left=left;
+elem.runtimeStyle.left=_428;
+}
+}
+}
+}
+if(_421=="opacity"){
+_425=parseFloat(_425);
+}
+if(/Opera/.test(navigator.userAgent)&&(MochiKit.Base.findValue(["left","top","right","bottom"],_421)!=-1)){
+if(MochiKit.Style.getStyle(elem,"position")=="static"){
+_425="auto";
+}
+}
+return _425=="auto"?null:_425;
+},setStyle:function(elem,_42a){
+elem=MochiKit.DOM.getElement(elem);
+for(var name in _42a){
+switch(name){
+case "opacity":
+MochiKit.Style.setOpacity(elem,_42a[name]);
+break;
+case "float":
+case "cssFloat":
+case "styleFloat":
+if(typeof (elem.style["float"])!="undefined"){
+elem.style["float"]=_42a[name];
+}else{
+if(typeof (elem.style.cssFloat)!="undefined"){
+elem.style.cssFloat=_42a[name];
+}else{
+elem.style.styleFloat=_42a[name];
+}
+}
+break;
+default:
+elem.style[MochiKit.Base.camelize(name)]=_42a[name];
+}
+}
+},setOpacity:function(elem,o){
+elem=MochiKit.DOM.getElement(elem);
+var self=MochiKit.Style;
+if(o==1){
+var _42f=/Gecko/.test(navigator.userAgent)&&!(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
+elem.style["opacity"]=_42f?0.999999:1;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"");
+}
+}else{
+if(o<0.00001){
+o=0;
+}
+elem.style["opacity"]=o;
+if(/MSIE/.test(navigator.userAgent)){
+elem.style["filter"]=self.getStyle(elem,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+o*100+")";
+}
+}
+},getElementPosition:function(elem,_431){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+elem=dom.getElement(elem);
+if(!elem||(!(elem.x&&elem.y)&&(!elem.parentNode===null||self.getStyle(elem,"display")=="none"))){
+return undefined;
+}
+var c=new self.Coordinates(0,0);
+var box=null;
+var _436=null;
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var b=d.body;
+if(!elem.parentNode&&elem.x&&elem.y){
+c.x+=elem.x||0;
+c.y+=elem.y||0;
+}else{
+if(elem.getBoundingClientRect){
+box=elem.getBoundingClientRect();
+c.x+=box.left+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+c.y+=box.top+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}else{
+if(elem.offsetParent){
+c.x+=elem.offsetLeft;
+c.y+=elem.offsetTop;
+_436=elem.offsetParent;
+if(_436!=elem){
+while(_436){
+c.x+=parseInt(_436.style.borderLeftWidth)||0;
+c.y+=parseInt(_436.style.borderTopWidth)||0;
+c.x+=_436.offsetLeft;
+c.y+=_436.offsetTop;
+_436=_436.offsetParent;
+}
+}
+var ua=navigator.userAgent.toLowerCase();
+if((typeof (opera)!="undefined"&&parseFloat(opera.version())<9)||(ua.indexOf("AppleWebKit")!=-1&&self.getStyle(elem,"position")=="absolute")){
+c.x-=b.offsetLeft;
+c.y-=b.offsetTop;
+}
+if(elem.parentNode){
+_436=elem.parentNode;
+}else{
+_436=null;
+}
+while(_436){
+var _43b=_436.tagName.toUpperCase();
+if(_43b==="BODY"||_43b==="HTML"){
+break;
+}
+var disp=self.getStyle(_436,"display");
+if(disp.search(/^inline|table-row.*$/i)){
+c.x-=_436.scrollLeft;
+c.y-=_436.scrollTop;
+}
+if(_436.parentNode){
+_436=_436.parentNode;
+}else{
+_436=null;
+}
+}
+}
+}
+}
+if(typeof (_431)!="undefined"){
+_431=arguments.callee(_431);
+if(_431){
+c.x-=(_431.x||0);
+c.y-=(_431.y||0);
+}
+}
+return c;
+},setElementPosition:function(elem,_43e,_43f){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_43f)=="undefined"){
+_43f="px";
+}
+var _440={};
+var _441=MochiKit.Base.isUndefinedOrNull;
+if(!_441(_43e.x)){
+_440["left"]=_43e.x+_43f;
+}
+if(!_441(_43e.y)){
+_440["top"]=_43e.y+_43f;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_440});
+},makePositioned:function(_442){
+_442=MochiKit.DOM.getElement(_442);
+var pos=MochiKit.Style.getStyle(_442,"position");
+if(pos=="static"||!pos){
+_442.style.position="relative";
+if(/Opera/.test(navigator.userAgent)){
+_442.style.top=0;
+_442.style.left=0;
+}
+}
+},undoPositioned:function(_444){
+_444=MochiKit.DOM.getElement(_444);
+if(_444.style.position=="relative"){
+_444.style.position=_444.style.top=_444.style.left=_444.style.bottom=_444.style.right="";
+}
+},makeClipping:function(_445){
+_445=MochiKit.DOM.getElement(_445);
+var s=_445.style;
+var _447={"overflow":s.overflow,"overflow-x":s.overflowX,"overflow-y":s.overflowY};
+if((MochiKit.Style.getStyle(_445,"overflow")||"visible")!="hidden"){
+_445.style.overflow="hidden";
+_445.style.overflowX="hidden";
+_445.style.overflowY="hidden";
+}
+return _447;
+},undoClipping:function(_448,_449){
+_448=MochiKit.DOM.getElement(_448);
+if(typeof (_449)=="string"){
+_448.style.overflow=_449;
+}else{
+if(_449!=null){
+_448.style.overflow=_449["overflow"];
+_448.style.overflowX=_449["overflow-x"];
+_448.style.overflowY=_449["overflow-y"];
+}
+}
+},getElementDimensions:function(elem,_44b){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+if(typeof (elem.w)=="number"||typeof (elem.h)=="number"){
+return new self.Dimensions(elem.w||0,elem.h||0);
+}
+elem=dom.getElement(elem);
+if(!elem){
+return undefined;
+}
+var disp=self.getStyle(elem,"display");
+if(disp=="none"||disp==""||typeof (disp)=="undefined"){
+var s=elem.style;
+var _450=s.visibility;
+var _451=s.position;
+var _452=s.display;
+s.visibility="hidden";
+s.position="absolute";
+s.display=self._getDefaultDisplay(elem);
+var _453=elem.offsetWidth;
+var _454=elem.offsetHeight;
+s.display=_452;
+s.position=_451;
+s.visibility=_450;
+}else{
+_453=elem.offsetWidth||0;
+_454=elem.offsetHeight||0;
+}
+if(_44b){
+var _455="colSpan" in elem&&"rowSpan" in elem;
+var _456=(_455&&elem.parentNode&&self.getStyle(elem.parentNode,"borderCollapse")=="collapse");
+if(_456){
+if(/MSIE/.test(navigator.userAgent)){
+var _457=elem.previousSibling?0.5:1;
+var _458=elem.nextSibling?0.5:1;
+}else{
+var _457=0.5;
+var _458=0.5;
+}
+}else{
+var _457=1;
+var _458=1;
+}
+_453-=Math.round((parseFloat(self.getStyle(elem,"paddingLeft"))||0)+(parseFloat(self.getStyle(elem,"paddingRight"))||0)+_457*(parseFloat(self.getStyle(elem,"borderLeftWidth"))||0)+_458*(parseFloat(self.getStyle(elem,"borderRightWidth"))||0));
+if(_455){
+if(/Gecko|Opera/.test(navigator.userAgent)&&!/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)){
+var _459=0;
+}else{
+if(/MSIE/.test(navigator.userAgent)){
+var _459=1;
+}else{
+var _459=_456?0.5:1;
+}
+}
+}else{
+var _459=1;
+}
+_454-=Math.round((parseFloat(self.getStyle(elem,"paddingTop"))||0)+(parseFloat(self.getStyle(elem,"paddingBottom"))||0)+_459*((parseFloat(self.getStyle(elem,"borderTopWidth"))||0)+(parseFloat(self.getStyle(elem,"borderBottomWidth"))||0)));
+}
+return new self.Dimensions(_453,_454);
+},setElementDimensions:function(elem,_45b,_45c){
+elem=MochiKit.DOM.getElement(elem);
+if(typeof (_45c)=="undefined"){
+_45c="px";
+}
+var _45d={};
+var _45e=MochiKit.Base.isUndefinedOrNull;
+if(!_45e(_45b.w)){
+_45d["width"]=_45b.w+_45c;
+}
+if(!_45e(_45b.h)){
+_45d["height"]=_45b.h+_45c;
+}
+MochiKit.DOM.updateNodeAttributes(elem,{"style":_45d});
+},_getDefaultDisplay:function(elem){
+var self=MochiKit.Style;
+var dom=MochiKit.DOM;
+elem=dom.getElement(elem);
+if(!elem){
+return undefined;
+}
+var _462=elem.tagName.toUpperCase();
+return self._defaultDisplay[_462]||"block";
+},setDisplayForElement:function(_463,_464){
+var _465=MochiKit.Base.extend(null,arguments,1);
+var _466=MochiKit.DOM.getElement;
+for(var i=0;i<_465.length;i++){
+_464=_466(_465[i]);
+if(_464){
+_464.style.display=_463;
+}
+}
+},getViewportDimensions:function(){
+var d=new MochiKit.Style.Dimensions();
+var w=MochiKit.DOM._window;
+var b=MochiKit.DOM._document.body;
+if(w.innerWidth){
+d.w=w.innerWidth;
+d.h=w.innerHeight;
+}else{
+if(b&&b.parentElement&&b.parentElement.clientWidth){
+d.w=b.parentElement.clientWidth;
+d.h=b.parentElement.clientHeight;
+}else{
+if(b&&b.clientWidth){
+d.w=b.clientWidth;
+d.h=b.clientHeight;
+}
+}
+}
+return d;
+},getViewportPosition:function(){
+var c=new MochiKit.Style.Coordinates(0,0);
+var d=MochiKit.DOM._document;
+var de=d.documentElement;
+var db=d.body;
+if(de&&(de.scrollTop||de.scrollLeft)){
+c.x=de.scrollLeft;
+c.y=de.scrollTop;
+}else{
+if(db){
+c.x=db.scrollLeft;
+c.y=db.scrollTop;
+}
+}
+return c;
+},__new__:function(){
+var m=MochiKit.Base;
+var _470=["A","ABBR","ACRONYM","B","BASEFONT","BDO","BIG","BR","CITE","CODE","DFN","EM","FONT","I","IMG","KBD","LABEL","Q","S","SAMP","SMALL","SPAN","STRIKE","STRONG","SUB","SUP","TEXTAREA","TT","U","VAR"];
+this._defaultDisplay={"TABLE":"table","THEAD":"table-header-group","TBODY":"table-row-group","TFOOT":"table-footer-group","COLGROUP":"table-column-group","COL":"table-column","TR":"table-row","TD":"table-cell","TH":"table-cell","CAPTION":"table-caption","LI":"list-item","INPUT":"inline-block","SELECT":"inline-block"};
+if(/MSIE/.test(navigator.userAgent)){
+for(var k in this._defaultDisplay){
+var v=this._defaultDisplay[k];
+if(v.indexOf("table")==0){
+this._defaultDisplay[k]="block";
+}
+}
+}
+for(var i=0;i<_470.length;i++){
+this._defaultDisplay[_470[i]]="inline";
+}
+this.elementPosition=this.getElementPosition;
+this.elementDimensions=this.getElementDimensions;
+this.hideElement=m.partial(this.setDisplayForElement,"none");
+this.showElement=m.partial(this.setDisplayForElement,"block");
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+}});
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Style);
+MochiKit.Base._deps("LoggingPane",["Base","Logging"]);
+MochiKit.LoggingPane.NAME="MochiKit.LoggingPane";
+MochiKit.LoggingPane.VERSION="1.4.2";
+MochiKit.LoggingPane.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.LoggingPane.toString=function(){
+return this.__repr__();
+};
+MochiKit.LoggingPane.createLoggingPane=function(_474){
+var m=MochiKit.LoggingPane;
+_474=!(!_474);
+if(m._loggingPane&&m._loggingPane.inline!=_474){
+m._loggingPane.closePane();
+m._loggingPane=null;
+}
+if(!m._loggingPane||m._loggingPane.closed){
+m._loggingPane=new m.LoggingPane(_474,MochiKit.Logging.logger);
+}
+return m._loggingPane;
+};
+MochiKit.LoggingPane.LoggingPane=function(_476,_477){
+if(typeof (_477)=="undefined"||_477===null){
+_477=MochiKit.Logging.logger;
+}
+this.logger=_477;
+var _478=MochiKit.Base.update;
+var _479=MochiKit.Base.updatetree;
+var bind=MochiKit.Base.bind;
+var _47b=MochiKit.Base.clone;
+var win=window;
+var uid="_MochiKit_LoggingPane";
+if(typeof (MochiKit.DOM)!="undefined"){
+win=MochiKit.DOM.currentWindow();
+}
+if(!_476){
+var url=win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g,"_");
+var name=uid+"_"+url;
+var nwin=win.open("",name,"dependent,resizable,height=200");
+if(!nwin){
+alert("Not able to open debugging window due to pop-up blocking.");
+return undefined;
+}
+nwin.document.write("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\" "+"\"http://www.w3.org/TR/html4/loose.dtd\">"+"<html><head><title>[MochiKit.LoggingPane]</title></head>"+"<body></body></html>");
+nwin.document.close();
+nwin.document.title+=" "+win.document.title;
+win=nwin;
+}
+var doc=win.document;
+this.doc=doc;
+var _482=doc.getElementById(uid);
+var _483=!!_482;
+if(_482&&typeof (_482.loggingPane)!="undefined"){
+_482.loggingPane.logger=this.logger;
+_482.loggingPane.buildAndApplyFilter();
+return _482.loggingPane;
+}
+if(_483){
+var _484;
+while((_484=_482.firstChild)){
+_482.removeChild(_484);
+}
+}else{
+_482=doc.createElement("div");
+_482.id=uid;
+}
+_482.loggingPane=this;
+var _485=doc.createElement("input");
+var _486=doc.createElement("input");
+var _487=doc.createElement("button");
+var _488=doc.createElement("button");
+var _489=doc.createElement("button");
+var _48a=doc.createElement("button");
+var _48b=doc.createElement("div");
+var _48c=doc.createElement("div");
+var _48d=uid+"_Listener";
+this.colorTable=_47b(this.colorTable);
+var _48e=[];
+var _48f=null;
+var _490=function(msg){
+var _492=msg.level;
+if(typeof (_492)=="number"){
+_492=MochiKit.Logging.LogLevel[_492];
+}
+return _492;
+};
+var _493=function(msg){
+return msg.info.join(" ");
+};
+var _495=bind(function(msg){
+var _497=_490(msg);
+var text=_493(msg);
+var c=this.colorTable[_497];
+var p=doc.createElement("span");
+p.className="MochiKit-LogMessage MochiKit-LogLevel-"+_497;
+p.style.cssText="margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: "+c;
+p.appendChild(doc.createTextNode(_497+": "+text));
+_48c.appendChild(p);
+_48c.appendChild(doc.createElement("br"));
+if(_48b.offsetHeight>_48b.scrollHeight){
+_48b.scrollTop=0;
+}else{
+_48b.scrollTop=_48b.scrollHeight;
+}
+},this);
+var _49b=function(msg){
+_48e[_48e.length]=msg;
+_495(msg);
+};
+var _49d=function(){
+var _49e,_49f;
+try{
+_49e=new RegExp(_485.value);
+_49f=new RegExp(_486.value);
+}
+catch(e){
+logDebug("Error in filter regex: "+e.message);
+return null;
+}
+return function(msg){
+return (_49e.test(_490(msg))&&_49f.test(_493(msg)));
+};
+};
+var _4a1=function(){
+while(_48c.firstChild){
+_48c.removeChild(_48c.firstChild);
+}
+};
+var _4a2=function(){
+_48e=[];
+_4a1();
+};
+var _4a3=bind(function(){
+if(this.closed){
+return;
+}
+this.closed=true;
+if(MochiKit.LoggingPane._loggingPane==this){
+MochiKit.LoggingPane._loggingPane=null;
+}
+this.logger.removeListener(_48d);
+try{
+try{
+_482.loggingPane=null;
+}
+catch(e){
+logFatal("Bookmarklet was closed incorrectly.");
+}
+if(_476){
+_482.parentNode.removeChild(_482);
+}else{
+this.win.close();
+}
+}
+catch(e){
+}
+},this);
+var _4a4=function(){
+_4a1();
+for(var i=0;i<_48e.length;i++){
+var msg=_48e[i];
+if(_48f===null||_48f(msg)){
+_495(msg);
+}
+}
+};
+this.buildAndApplyFilter=function(){
+_48f=_49d();
+_4a4();
+this.logger.removeListener(_48d);
+this.logger.addListener(_48d,_48f,_49b);
+};
+var _4a7=bind(function(){
+_48e=this.logger.getMessages();
+_4a4();
+},this);
+var _4a8=bind(function(_4a9){
+_4a9=_4a9||window.event;
+key=_4a9.which||_4a9.keyCode;
+if(key==13){
+this.buildAndApplyFilter();
+}
+},this);
+var _4aa="display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: "+this.logFont;
+if(_476){
+_4aa+="; height: 10em; border-top: 2px solid black";
+}else{
+_4aa+="; height: 100%;";
+}
+_482.style.cssText=_4aa;
+if(!_483){
+doc.body.appendChild(_482);
+}
+_4aa={"cssText":"width: 33%; display: inline; font: "+this.logFont};
+_479(_485,{"value":"FATAL|ERROR|WARNING|INFO|DEBUG","onkeypress":_4a8,"style":_4aa});
+_482.appendChild(_485);
+_479(_486,{"value":".*","onkeypress":_4a8,"style":_4aa});
+_482.appendChild(_486);
+_4aa="width: 8%; display:inline; font: "+this.logFont;
+_487.appendChild(doc.createTextNode("Filter"));
+_487.onclick=bind("buildAndApplyFilter",this);
+_487.style.cssText=_4aa;
+_482.appendChild(_487);
+_488.appendChild(doc.createTextNode("Load"));
+_488.onclick=_4a7;
+_488.style.cssText=_4aa;
+_482.appendChild(_488);
+_489.appendChild(doc.createTextNode("Clear"));
+_489.onclick=_4a2;
+_489.style.cssText=_4aa;
+_482.appendChild(_489);
+_48a.appendChild(doc.createTextNode("Close"));
+_48a.onclick=_4a3;
+_48a.style.cssText=_4aa;
+_482.appendChild(_48a);
+_48b.style.cssText="overflow: auto; width: 100%";
+_48c.style.cssText="width: 100%; height: "+(_476?"8em":"100%");
+_48b.appendChild(_48c);
+_482.appendChild(_48b);
+this.buildAndApplyFilter();
+_4a7();
+if(_476){
+this.win=undefined;
+}else{
+this.win=win;
+}
+this.inline=_476;
+this.closePane=_4a3;
+this.closed=false;
+return this;
+};
+MochiKit.LoggingPane.LoggingPane.prototype={"logFont":"8pt Verdana,sans-serif","colorTable":{"ERROR":"red","FATAL":"darkred","WARNING":"blue","INFO":"black","DEBUG":"green"}};
+MochiKit.LoggingPane.EXPORT_OK=["LoggingPane"];
+MochiKit.LoggingPane.EXPORT=["createLoggingPane"];
+MochiKit.LoggingPane.__new__=function(){
+this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)};
+MochiKit.Base.nameFunctions(this);
+MochiKit.LoggingPane._loggingPane=null;
+};
+MochiKit.LoggingPane.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.LoggingPane);
+MochiKit.Base._deps("Color",["Base","DOM","Style"]);
+MochiKit.Color.NAME="MochiKit.Color";
+MochiKit.Color.VERSION="1.4.2";
+MochiKit.Color.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Color.toString=function(){
+return this.__repr__();
+};
+MochiKit.Color.Color=function(red,_4ac,blue,_4ae){
+if(typeof (_4ae)=="undefined"||_4ae===null){
+_4ae=1;
+}
+this.rgb={r:red,g:_4ac,b:blue,a:_4ae};
+};
+MochiKit.Color.Color.prototype={__class__:MochiKit.Color.Color,colorWithAlpha:function(_4af){
+var rgb=this.rgb;
+var m=MochiKit.Color;
+return m.Color.fromRGB(rgb.r,rgb.g,rgb.b,_4af);
+},colorWithHue:function(hue){
+var hsl=this.asHSL();
+hsl.h=hue;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithSaturation:function(_4b5){
+var hsl=this.asHSL();
+hsl.s=_4b5;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},colorWithLightness:function(_4b8){
+var hsl=this.asHSL();
+hsl.l=_4b8;
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},darkerColorWithLevel:function(_4bb){
+var hsl=this.asHSL();
+hsl.l=Math.max(hsl.l-_4bb,0);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},lighterColorWithLevel:function(_4be){
+var hsl=this.asHSL();
+hsl.l=Math.min(hsl.l+_4be,1);
+var m=MochiKit.Color;
+return m.Color.fromHSL(hsl);
+},blendedColor:function(_4c1,_4c2){
+if(typeof (_4c2)=="undefined"||_4c2===null){
+_4c2=0.5;
+}
+var sf=1-_4c2;
+var s=this.rgb;
+var d=_4c1.rgb;
+var df=_4c2;
+return MochiKit.Color.Color.fromRGB((s.r*sf)+(d.r*df),(s.g*sf)+(d.g*df),(s.b*sf)+(d.b*df),(s.a*sf)+(d.a*df));
+},compareRGB:function(_4c7){
+var a=this.asRGB();
+var b=_4c7.asRGB();
+return MochiKit.Base.compare([a.r,a.g,a.b,a.a],[b.r,b.g,b.b,b.a]);
+},isLight:function(){
+return this.asHSL().b>0.5;
+},isDark:function(){
+return (!this.isLight());
+},toHSLString:function(){
+var c=this.asHSL();
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hslString;
+if(!rval){
+var mid=(ccc(c.h,360).toFixed(0)+","+ccc(c.s,100).toPrecision(4)+"%"+","+ccc(c.l,100).toPrecision(4)+"%");
+var a=c.a;
+if(a>=1){
+a=1;
+rval="hsl("+mid+")";
+}else{
+if(a<=0){
+a=0;
+}
+rval="hsla("+mid+","+a+")";
+}
+this._hslString=rval;
+}
+return rval;
+},toRGBString:function(){
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._rgbString;
+if(!rval){
+var mid=(ccc(c.r,255).toFixed(0)+","+ccc(c.g,255).toFixed(0)+","+ccc(c.b,255).toFixed(0));
+if(c.a!=1){
+rval="rgba("+mid+","+c.a+")";
+}else{
+rval="rgb("+mid+")";
+}
+this._rgbString=rval;
+}
+return rval;
+},asRGB:function(){
+return MochiKit.Base.clone(this.rgb);
+},toHexString:function(){
+var m=MochiKit.Color;
+var c=this.rgb;
+var ccc=MochiKit.Color.clampColorComponent;
+var rval=this._hexString;
+if(!rval){
+rval=("#"+m.toColorPart(ccc(c.r,255))+m.toColorPart(ccc(c.g,255))+m.toColorPart(ccc(c.b,255)));
+this._hexString=rval;
+}
+return rval;
+},asHSV:function(){
+var hsv=this.hsv;
+var c=this.rgb;
+if(typeof (hsv)=="undefined"||hsv===null){
+hsv=MochiKit.Color.rgbToHSV(this.rgb);
+this.hsv=hsv;
+}
+return MochiKit.Base.clone(hsv);
+},asHSL:function(){
+var hsl=this.hsl;
+var c=this.rgb;
+if(typeof (hsl)=="undefined"||hsl===null){
+hsl=MochiKit.Color.rgbToHSL(this.rgb);
+this.hsl=hsl;
+}
+return MochiKit.Base.clone(hsl);
+},toString:function(){
+return this.toRGBString();
+},repr:function(){
+var c=this.rgb;
+var col=[c.r,c.g,c.b,c.a];
+return this.__class__.NAME+"("+col.join(", ")+")";
+}};
+MochiKit.Base.update(MochiKit.Color.Color,{fromRGB:function(red,_4de,blue,_4e0){
+var _4e1=MochiKit.Color.Color;
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_4de=rgb.g;
+blue=rgb.b;
+if(typeof (rgb.a)=="undefined"){
+_4e0=undefined;
+}else{
+_4e0=rgb.a;
+}
+}
+return new _4e1(red,_4de,blue,_4e0);
+},fromHSL:function(hue,_4e4,_4e5,_4e6){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hslToRGB.apply(m,arguments));
+},fromHSV:function(hue,_4e9,_4ea,_4eb){
+var m=MochiKit.Color;
+return m.Color.fromRGB(m.hsvToRGB.apply(m,arguments));
+},fromName:function(name){
+var _4ee=MochiKit.Color.Color;
+if(name.charAt(0)=="\""){
+name=name.substr(1,name.length-2);
+}
+var _4ef=_4ee._namedColors[name.toLowerCase()];
+if(typeof (_4ef)=="string"){
+return _4ee.fromHexString(_4ef);
+}else{
+if(name=="transparent"){
+return _4ee.transparentColor();
+}
+}
+return null;
+},fromString:function(_4f0){
+var self=MochiKit.Color.Color;
+var _4f2=_4f0.substr(0,3);
+if(_4f2=="rgb"){
+return self.fromRGBString(_4f0);
+}else{
+if(_4f2=="hsl"){
+return self.fromHSLString(_4f0);
+}else{
+if(_4f0.charAt(0)=="#"){
+return self.fromHexString(_4f0);
+}
+}
+}
+return self.fromName(_4f0);
+},fromHexString:function(_4f3){
+if(_4f3.charAt(0)=="#"){
+_4f3=_4f3.substring(1);
+}
+var _4f4=[];
+var i,hex;
+if(_4f3.length==3){
+for(i=0;i<3;i++){
+hex=_4f3.substr(i,1);
+_4f4.push(parseInt(hex+hex,16)/255);
+}
+}else{
+for(i=0;i<6;i+=2){
+hex=_4f3.substr(i,2);
+_4f4.push(parseInt(hex,16)/255);
+}
+}
+var _4f7=MochiKit.Color.Color;
+return _4f7.fromRGB.apply(_4f7,_4f4);
+},_fromColorString:function(pre,_4f9,_4fa,_4fb){
+if(_4fb.indexOf(pre)===0){
+_4fb=_4fb.substring(_4fb.indexOf("(",3)+1,_4fb.length-1);
+}
+var _4fc=_4fb.split(/\s*,\s*/);
+var _4fd=[];
+for(var i=0;i<_4fc.length;i++){
+var c=_4fc[i];
+var val;
+var _501=c.substring(c.length-3);
+if(c.charAt(c.length-1)=="%"){
+val=0.01*parseFloat(c.substring(0,c.length-1));
+}else{
+if(_501=="deg"){
+val=parseFloat(c)/360;
+}else{
+if(_501=="rad"){
+val=parseFloat(c)/(Math.PI*2);
+}else{
+val=_4fa[i]*parseFloat(c);
+}
+}
+}
+_4fd.push(val);
+}
+return this[_4f9].apply(this,_4fd);
+},fromComputedStyle:function(elem,_503){
+var d=MochiKit.DOM;
+var cls=MochiKit.Color.Color;
+for(elem=d.getElement(elem);elem;elem=elem.parentNode){
+var _506=MochiKit.Style.getStyle.apply(d,arguments);
+if(!_506){
+continue;
+}
+var _507=cls.fromString(_506);
+if(!_507){
+break;
+}
+if(_507.asRGB().a>0){
+return _507;
+}
+}
+return null;
+},fromBackground:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"backgroundColor","background-color")||cls.whiteColor();
+},fromText:function(elem){
+var cls=MochiKit.Color.Color;
+return cls.fromComputedStyle(elem,"color","color")||cls.blackColor();
+},namedColors:function(){
+return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
+}});
+MochiKit.Base.update(MochiKit.Color,{clampColorComponent:function(v,_50d){
+v*=_50d;
+if(v<0){
+return 0;
+}else{
+if(v>_50d){
+return _50d;
+}else{
+return v;
+}
+}
+},_hslValue:function(n1,n2,hue){
+if(hue>6){
+hue-=6;
+}else{
+if(hue<0){
+hue+=6;
+}
+}
+var val;
+if(hue<1){
+val=n1+(n2-n1)*hue;
+}else{
+if(hue<3){
+val=n2;
+}else{
+if(hue<4){
+val=n1+(n2-n1)*(4-hue);
+}else{
+val=n1;
+}
+}
+}
+return val;
+},hsvToRGB:function(hue,_513,_514,_515){
+if(arguments.length==1){
+var hsv=hue;
+hue=hsv.h;
+_513=hsv.s;
+_514=hsv.v;
+_515=hsv.a;
+}
+var red;
+var _518;
+var blue;
+if(_513===0){
+red=_514;
+_518=_514;
+blue=_514;
+}else{
+var i=Math.floor(hue*6);
+var f=(hue*6)-i;
+var p=_514*(1-_513);
+var q=_514*(1-(_513*f));
+var t=_514*(1-(_513*(1-f)));
+switch(i){
+case 1:
+red=q;
+_518=_514;
+blue=p;
+break;
+case 2:
+red=p;
+_518=_514;
+blue=t;
+break;
+case 3:
+red=p;
+_518=q;
+blue=_514;
+break;
+case 4:
+red=t;
+_518=p;
+blue=_514;
+break;
+case 5:
+red=_514;
+_518=p;
+blue=q;
+break;
+case 6:
+case 0:
+red=_514;
+_518=t;
+blue=p;
+break;
+}
+}
+return {r:red,g:_518,b:blue,a:_515};
+},hslToRGB:function(hue,_520,_521,_522){
+if(arguments.length==1){
+var hsl=hue;
+hue=hsl.h;
+_520=hsl.s;
+_521=hsl.l;
+_522=hsl.a;
+}
+var red;
+var _525;
+var blue;
+if(_520===0){
+red=_521;
+_525=_521;
+blue=_521;
+}else{
+var m2;
+if(_521<=0.5){
+m2=_521*(1+_520);
+}else{
+m2=_521+_520-(_521*_520);
+}
+var m1=(2*_521)-m2;
+var f=MochiKit.Color._hslValue;
+var h6=hue*6;
+red=f(m1,m2,h6+2);
+_525=f(m1,m2,h6);
+blue=f(m1,m2,h6-2);
+}
+return {r:red,g:_525,b:blue,a:_522};
+},rgbToHSV:function(red,_52c,blue,_52e){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_52c=rgb.g;
+blue=rgb.b;
+_52e=rgb.a;
+}
+var max=Math.max(Math.max(red,_52c),blue);
+var min=Math.min(Math.min(red,_52c),blue);
+var hue;
+var _533;
+var _534=max;
+if(min==max){
+hue=0;
+_533=0;
+}else{
+var _535=(max-min);
+_533=_535/max;
+if(red==max){
+hue=(_52c-blue)/_535;
+}else{
+if(_52c==max){
+hue=2+((blue-red)/_535);
+}else{
+hue=4+((red-_52c)/_535);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_533,v:_534,a:_52e};
+},rgbToHSL:function(red,_537,blue,_539){
+if(arguments.length==1){
+var rgb=red;
+red=rgb.r;
+_537=rgb.g;
+blue=rgb.b;
+_539=rgb.a;
+}
+var max=Math.max(red,Math.max(_537,blue));
+var min=Math.min(red,Math.min(_537,blue));
+var hue;
+var _53e;
+var _53f=(max+min)/2;
+var _540=max-min;
+if(_540===0){
+hue=0;
+_53e=0;
+}else{
+if(_53f<=0.5){
+_53e=_540/(max+min);
+}else{
+_53e=_540/(2-max-min);
+}
+if(red==max){
+hue=(_537-blue)/_540;
+}else{
+if(_537==max){
+hue=2+((blue-red)/_540);
+}else{
+hue=4+((red-_537)/_540);
+}
+}
+hue/=6;
+if(hue<0){
+hue+=1;
+}
+if(hue>1){
+hue-=1;
+}
+}
+return {h:hue,s:_53e,l:_53f,a:_539};
+},toColorPart:function(num){
+num=Math.round(num);
+var _542=num.toString(16);
+if(num<16){
+return "0"+_542;
+}
+return _542;
+},__new__:function(){
+var m=MochiKit.Base;
+this.Color.fromRGBString=m.bind(this.Color._fromColorString,this.Color,"rgb","fromRGB",[1/255,1/255,1/255,1]);
+this.Color.fromHSLString=m.bind(this.Color._fromColorString,this.Color,"hsl","fromHSL",[1/360,0.01,0.01,1]);
+var _544=1/3;
+var _545={black:[0,0,0],blue:[0,0,1],brown:[0.6,0.4,0.2],cyan:[0,1,1],darkGray:[_544,_544,_544],gray:[0.5,0.5,0.5],green:[0,1,0],lightGray:[2*_544,2*_544,2*_544],magenta:[1,0,1],orange:[1,0.5,0],purple:[0.5,0,0.5],red:[1,0,0],transparent:[0,0,0,0],white:[1,1,1],yellow:[1,1,0]};
+var _546=function(name,r,g,b,a){
+var rval=this.fromRGB(r,g,b,a);
+this[name]=function(){
+return rval;
+};
+return rval;
+};
+for(var k in _545){
+var name=k+"Color";
+var _54f=m.concat([_546,this.Color,name],_545[k]);
+this.Color[name]=m.bind.apply(null,_54f);
+}
+var _550=function(){
+for(var i=0;i<arguments.length;i++){
+if(!(arguments[i] instanceof MochiKit.Color.Color)){
+return false;
+}
+}
+return true;
+};
+var _552=function(a,b){
+return a.compareRGB(b);
+};
+m.nameFunctions(this);
+m.registerComparator(this.Color.NAME,_550,_552);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+}});
+MochiKit.Color.EXPORT=["Color"];
+MochiKit.Color.EXPORT_OK=["clampColorComponent","rgbToHSL","hslToRGB","rgbToHSV","hsvToRGB","toColorPart"];
+MochiKit.Color.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Color);
+MochiKit.Color.Color._namedColors={aliceblue:"#f0f8ff",antiquewhite:"#faebd7",aqua:"#00ffff",aquamarine:"#7fffd4",azure:"#f0ffff",beige:"#f5f5dc",bisque:"#ffe4c4",black:"#000000",blanchedalmond:"#ffebcd",blue:"#0000ff",blueviolet:"#8a2be2",brown:"#a52a2a",burlywood:"#deb887",cadetblue:"#5f9ea0",chartreuse:"#7fff00",chocolate:"#d2691e",coral:"#ff7f50",cornflowerblue:"#6495ed",cornsilk:"#fff8dc",crimson:"#dc143c",cyan:"#00ffff",darkblue:"#00008b",darkcyan:"#008b8b",darkgoldenrod:"#b8860b",darkgray:"#a9a9a9",darkgreen:"#006400",darkgrey:"#a9a9a9",darkkhaki:"#bdb76b",darkmagenta:"#8b008b",darkolivegreen:"#556b2f",darkorange:"#ff8c00",darkorchid:"#9932cc",darkred:"#8b0000",darksalmon:"#e9967a",darkseagreen:"#8fbc8f",darkslateblue:"#483d8b",darkslategray:"#2f4f4f",darkslategrey:"#2f4f4f",darkturquoise:"#00ced1",darkviolet:"#9400d3",deeppink:"#ff1493",deepskyblue:"#00bfff",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1e90ff",firebrick:"#b22222",floralwhite:"#fffaf0",forestgreen
 :"#228b22",fuchsia:"#ff00ff",gainsboro:"#dcdcdc",ghostwhite:"#f8f8ff",gold:"#ffd700",goldenrod:"#daa520",gray:"#808080",green:"#008000",greenyellow:"#adff2f",grey:"#808080",honeydew:"#f0fff0",hotpink:"#ff69b4",indianred:"#cd5c5c",indigo:"#4b0082",ivory:"#fffff0",khaki:"#f0e68c",lavender:"#e6e6fa",lavenderblush:"#fff0f5",lawngreen:"#7cfc00",lemonchiffon:"#fffacd",lightblue:"#add8e6",lightcoral:"#f08080",lightcyan:"#e0ffff",lightgoldenrodyellow:"#fafad2",lightgray:"#d3d3d3",lightgreen:"#90ee90",lightgrey:"#d3d3d3",lightpink:"#ffb6c1",lightsalmon:"#ffa07a",lightseagreen:"#20b2aa",lightskyblue:"#87cefa",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#b0c4de",lightyellow:"#ffffe0",lime:"#00ff00",limegreen:"#32cd32",linen:"#faf0e6",magenta:"#ff00ff",maroon:"#800000",mediumaquamarine:"#66cdaa",mediumblue:"#0000cd",mediumorchid:"#ba55d3",mediumpurple:"#9370db",mediumseagreen:"#3cb371",mediumslateblue:"#7b68ee",mediumspringgreen:"#00fa9a",mediumturquoise:"#48d1cc",
 mediumvioletred:"#c71585",midnightblue:"#191970",mintcream:"#f5fffa",mistyrose:"#ffe4e1",moccasin:"#ffe4b5",navajowhite:"#ffdead",navy:"#000080",oldlace:"#fdf5e6",olive:"#808000",olivedrab:"#6b8e23",orange:"#ffa500",orangered:"#ff4500",orchid:"#da70d6",palegoldenrod:"#eee8aa",palegreen:"#98fb98",paleturquoise:"#afeeee",palevioletred:"#db7093",papayawhip:"#ffefd5",peachpuff:"#ffdab9",peru:"#cd853f",pink:"#ffc0cb",plum:"#dda0dd",powderblue:"#b0e0e6",purple:"#800080",red:"#ff0000",rosybrown:"#bc8f8f",royalblue:"#4169e1",saddlebrown:"#8b4513",salmon:"#fa8072",sandybrown:"#f4a460",seagreen:"#2e8b57",seashell:"#fff5ee",sienna:"#a0522d",silver:"#c0c0c0",skyblue:"#87ceeb",slateblue:"#6a5acd",slategray:"#708090",slategrey:"#708090",snow:"#fffafa",springgreen:"#00ff7f",steelblue:"#4682b4",tan:"#d2b48c",teal:"#008080",thistle:"#d8bfd8",tomato:"#ff6347",turquoise:"#40e0d0",violet:"#ee82ee",wheat:"#f5deb3",white:"#ffffff",whitesmoke:"#f5f5f5",yellow:"#ffff00",yellowgreen:"#9acd32"};
+MochiKit.Base._deps("Signal",["Base","DOM","Style"]);
+MochiKit.Signal.NAME="MochiKit.Signal";
+MochiKit.Signal.VERSION="1.4.2";
+MochiKit.Signal._observers=[];
+MochiKit.Signal.Event=function(src,e){
+this._event=e||window.event;
+this._src=src;
+};
+MochiKit.Base.update(MochiKit.Signal.Event.prototype,{__repr__:function(){
+var repr=MochiKit.Base.repr;
+var str="{event(): "+repr(this.event())+", src(): "+repr(this.src())+", type(): "+repr(this.type())+", target(): "+repr(this.target());
+if(this.type()&&this.type().indexOf("key")===0||this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu"){
+str+=", modifier(): "+"{alt: "+repr(this.modifier().alt)+", ctrl: "+repr(this.modifier().ctrl)+", meta: "+repr(this.modifier().meta)+", shift: "+repr(this.modifier().shift)+", any: "+repr(this.modifier().any)+"}";
+}
+if(this.type()&&this.type().indexOf("key")===0){
+str+=", key(): {code: "+repr(this.key().code)+", string: "+repr(this.key().string)+"}";
+}
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+str+=", mouse(): {page: "+repr(this.mouse().page)+", client: "+repr(this.mouse().client);
+if(this.type()!="mousemove"&&this.type()!="mousewheel"){
+str+=", button: {left: "+repr(this.mouse().button.left)+", middle: "+repr(this.mouse().button.middle)+", right: "+repr(this.mouse().button.right)+"}";
+}
+if(this.type()=="mousewheel"){
+str+=", wheel: "+repr(this.mouse().wheel);
+}
+str+="}";
+}
+if(this.type()=="mouseover"||this.type()=="mouseout"||this.type()=="mouseenter"||this.type()=="mouseleave"){
+str+=", relatedTarget(): "+repr(this.relatedTarget());
+}
+str+="}";
+return str;
+},toString:function(){
+return this.__repr__();
+},src:function(){
+return this._src;
+},event:function(){
+return this._event;
+},type:function(){
+if(this._event.type==="DOMMouseScroll"){
+return "mousewheel";
+}else{
+return this._event.type||undefined;
+}
+},target:function(){
+return this._event.target||this._event.srcElement;
+},_relatedTarget:null,relatedTarget:function(){
+if(this._relatedTarget!==null){
+return this._relatedTarget;
+}
+var elem=null;
+if(this.type()=="mouseover"||this.type()=="mouseenter"){
+elem=(this._event.relatedTarget||this._event.fromElement);
+}else{
+if(this.type()=="mouseout"||this.type()=="mouseleave"){
+elem=(this._event.relatedTarget||this._event.toElement);
+}
+}
+try{
+if(elem!==null&&elem.nodeType!==null){
+this._relatedTarget=elem;
+return elem;
+}
+}
+catch(ignore){
+}
+return undefined;
+},_modifier:null,modifier:function(){
+if(this._modifier!==null){
+return this._modifier;
+}
+var m={};
+m.alt=this._event.altKey;
+m.ctrl=this._event.ctrlKey;
+m.meta=this._event.metaKey||false;
+m.shift=this._event.shiftKey;
+m.any=m.alt||m.ctrl||m.shift||m.meta;
+this._modifier=m;
+return m;
+},_key:null,key:function(){
+if(this._key!==null){
+return this._key;
+}
+var k={};
+if(this.type()&&this.type().indexOf("key")===0){
+if(this.type()=="keydown"||this.type()=="keyup"){
+k.code=this._event.keyCode;
+k.string=(MochiKit.Signal._specialKeys[k.code]||"KEY_UNKNOWN");
+this._key=k;
+return k;
+}else{
+if(this.type()=="keypress"){
+k.code=0;
+k.string="";
+if(typeof (this._event.charCode)!="undefined"&&this._event.charCode!==0&&!MochiKit.Signal._specialMacKeys[this._event.charCode]){
+k.code=this._event.charCode;
+k.string=String.fromCharCode(k.code);
+}else{
+if(this._event.keyCode&&typeof (this._event.charCode)=="undefined"){
+k.code=this._event.keyCode;
+k.string=String.fromCharCode(k.code);
+}
+}
+this._key=k;
+return k;
+}
+}
+}
+return undefined;
+},_mouse:null,mouse:function(){
+if(this._mouse!==null){
+return this._mouse;
+}
+var m={};
+var e=this._event;
+if(this.type()&&(this.type().indexOf("mouse")===0||this.type().indexOf("click")!=-1||this.type()=="contextmenu")){
+m.client=new MochiKit.Style.Coordinates(0,0);
+if(e.clientX||e.clientY){
+m.client.x=(!e.clientX||e.clientX<0)?0:e.clientX;
+m.client.y=(!e.clientY||e.clientY<0)?0:e.clientY;
+}
+m.page=new MochiKit.Style.Coordinates(0,0);
+if(e.pageX||e.pageY){
+m.page.x=(!e.pageX||e.pageX<0)?0:e.pageX;
+m.page.y=(!e.pageY||e.pageY<0)?0:e.pageY;
+}else{
+var de=MochiKit.DOM._document.documentElement;
+var b=MochiKit.DOM._document.body;
+m.page.x=e.clientX+(de.scrollLeft||b.scrollLeft)-(de.clientLeft||0);
+m.page.y=e.clientY+(de.scrollTop||b.scrollTop)-(de.clientTop||0);
+}
+if(this.type()!="mousemove"&&this.type()!="mousewheel"){
+m.button={};
+m.button.left=false;
+m.button.right=false;
+m.button.middle=false;
+if(e.which){
+m.button.left=(e.which==1);
+m.button.middle=(e.which==2);
+m.button.right=(e.which==3);
+}else{
+m.button.left=!!(e.button&1);
+m.button.right=!!(e.button&2);
+m.button.middle=!!(e.button&4);
+}
+}
+if(this.type()=="mousewheel"){
+m.wheel=new MochiKit.Style.Coordinates(0,0);
+if(e.wheelDeltaX||e.wheelDeltaY){
+m.wheel.x=e.wheelDeltaX/-40||0;
+m.wheel.y=e.wheelDeltaY/-40||0;
+}else{
+if(e.wheelDelta){
+m.wheel.y=e.wheelDelta/-40;
+}else{
+m.wheel.y=e.detail||0;
+}
+}
+}
+this._mouse=m;
+return m;
+}
+return undefined;
+},stop:function(){
+this.stopPropagation();
+this.preventDefault();
+},stopPropagation:function(){
+if(this._event.stopPropagation){
+this._event.stopPropagation();
+}else{
+this._event.cancelBubble=true;
+}
+},preventDefault:function(){
+if(this._event.preventDefault){
+this._event.preventDefault();
+}else{
+if(this._confirmUnload===null){
+this._event.returnValue=false;
+}
+}
+},_confirmUnload:null,confirmUnload:function(msg){
+if(this.type()=="beforeunload"){
+this._confirmUnload=msg;
+this._event.returnValue=msg;
+}
+}});
+MochiKit.Signal._specialMacKeys={3:"KEY_ENTER",63289:"KEY_NUM_PAD_CLEAR",63276:"KEY_PAGE_UP",63277:"KEY_PAGE_DOWN",63275:"KEY_END",63273:"KEY_HOME",63234:"KEY_ARROW_LEFT",63232:"KEY_ARROW_UP",63235:"KEY_ARROW_RIGHT",63233:"KEY_ARROW_DOWN",63302:"KEY_INSERT",63272:"KEY_DELETE"};
+(function(){
+var _561=MochiKit.Signal._specialMacKeys;
+for(i=63236;i<=63242;i++){
+_561[i]="KEY_F"+(i-63236+1);
+}
+})();
+MochiKit.Signal._specialKeys={8:"KEY_BACKSPACE",9:"KEY_TAB",12:"KEY_NUM_PAD_CLEAR",13:"KEY_ENTER",16:"KEY_SHIFT",17:"KEY_CTRL",18:"KEY_ALT",19:"KEY_PAUSE",20:"KEY_CAPS_LOCK",27:"KEY_ESCAPE",32:"KEY_SPACEBAR",33:"KEY_PAGE_UP",34:"KEY_PAGE_DOWN",35:"KEY_END",36:"KEY_HOME",37:"KEY_ARROW_LEFT",38:"KEY_ARROW_UP",39:"KEY_ARROW_RIGHT",40:"KEY_ARROW_DOWN",44:"KEY_PRINT_SCREEN",45:"KEY_INSERT",46:"KEY_DELETE",59:"KEY_SEMICOLON",91:"KEY_WINDOWS_LEFT",92:"KEY_WINDOWS_RIGHT",93:"KEY_SELECT",106:"KEY_NUM_PAD_ASTERISK",107:"KEY_NUM_PAD_PLUS_SIGN",109:"KEY_NUM_PAD_HYPHEN-MINUS",110:"KEY_NUM_PAD_FULL_STOP",111:"KEY_NUM_PAD_SOLIDUS",144:"KEY_NUM_LOCK",145:"KEY_SCROLL_LOCK",186:"KEY_SEMICOLON",187:"KEY_EQUALS_SIGN",188:"KEY_COMMA",189:"KEY_HYPHEN-MINUS",190:"KEY_FULL_STOP",191:"KEY_SOLIDUS",192:"KEY_GRAVE_ACCENT",219:"KEY_LEFT_SQUARE_BRACKET",220:"KEY_REVERSE_SOLIDUS",221:"KEY_RIGHT_SQUARE_BRACKET",222:"KEY_APOSTROPHE"};
+(function(){
+var _562=MochiKit.Signal._specialKeys;
+for(var i=48;i<=57;i++){
+_562[i]="KEY_"+(i-48);
+}
+for(i=65;i<=90;i++){
+_562[i]="KEY_"+String.fromCharCode(i);
+}
+for(i=96;i<=105;i++){
+_562[i]="KEY_NUM_PAD_"+(i-96);
+}
+for(i=112;i<=123;i++){
+_562[i]="KEY_F"+(i-112+1);
+}
+})();
+MochiKit.Signal.Ident=function(_564){
+this.source=_564.source;
+this.signal=_564.signal;
+this.listener=_564.listener;
+this.isDOM=_564.isDOM;
+this.objOrFunc=_564.objOrFunc;
+this.funcOrStr=_564.funcOrStr;
+this.connected=_564.connected;
+};
+MochiKit.Signal.Ident.prototype={};
+MochiKit.Base.update(MochiKit.Signal,{__repr__:function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+},toString:function(){
+return this.__repr__();
+},_unloadCache:function(){
+var self=MochiKit.Signal;
+var _566=self._observers;
+for(var i=0;i<_566.length;i++){
+if(_566[i].signal!=="onload"&&_566[i].signal!=="onunload"){
+self._disconnect(_566[i]);
+}
+}
+},_listener:function(src,sig,func,obj,_56c){
+var self=MochiKit.Signal;
+var E=self.Event;
+if(!_56c){
+if(typeof (func.im_self)=="undefined"){
+return MochiKit.Base.bindLate(func,obj);
+}else{
+return func;
+}
+}
+obj=obj||src;
+if(typeof (func)=="string"){
+if(sig==="onload"||sig==="onunload"){
+return function(_56f){
+obj[func].apply(obj,[new E(src,_56f)]);
+var _570=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:obj,funcOrStr:func});
+MochiKit.Signal._disconnect(_570);
+};
+}else{
+return function(_571){
+obj[func].apply(obj,[new E(src,_571)]);
+};
+}
+}else{
+if(sig==="onload"||sig==="onunload"){
+return function(_572){
+func.apply(obj,[new E(src,_572)]);
+var _573=new MochiKit.Signal.Ident({source:src,signal:sig,objOrFunc:func});
+MochiKit.Signal._disconnect(_573);
+};
+}else{
+return function(_574){
+func.apply(obj,[new E(src,_574)]);
+};
+}
+}
+},_browserAlreadyHasMouseEnterAndLeave:function(){
+return /MSIE/.test(navigator.userAgent);
+},_browserLacksMouseWheelEvent:function(){
+return /Gecko\//.test(navigator.userAgent);
+},_mouseEnterListener:function(src,sig,func,obj){
+var E=MochiKit.Signal.Event;
+return function(_57a){
+var e=new E(src,_57a);
+try{
+e.relatedTarget().nodeName;
+}
+catch(err){
+return;
+}
+e.stop();
+if(MochiKit.DOM.isChildNode(e.relatedTarget(),src)){
+return;
+}
+e.type=function(){
+return sig;
+};
+if(typeof (func)=="string"){
+return obj[func].apply(obj,[e]);
+}else{
+return func.apply(obj,[e]);
+}
+};
+},_getDestPair:function(_57c,_57d){
+var obj=null;
+var func=null;
+if(typeof (_57d)!="undefined"){
+obj=_57c;
+func=_57d;
+if(typeof (_57d)=="string"){
+if(typeof (_57c[_57d])!="function"){
+throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+}
+}else{
+if(typeof (_57d)!="function"){
+throw new Error("'funcOrStr' must be a function or string");
+}
+}
+}else{
+if(typeof (_57c)!="function"){
+throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+}else{
+func=_57c;
+}
+}
+return [obj,func];
+},connect:function(src,sig,_582,_583){
+src=MochiKit.DOM.getElement(src);
+var self=MochiKit.Signal;
+if(typeof (sig)!="string"){
+throw new Error("'sig' must be a string");
+}
+var _585=self._getDestPair(_582,_583);
+var obj=_585[0];
+var func=_585[1];
+if(typeof (obj)=="undefined"||obj===null){
+obj=src;
+}
+var _588=!!(src.addEventListener||src.attachEvent);
+if(_588&&(sig==="onmouseenter"||sig==="onmouseleave")&&!self._browserAlreadyHasMouseEnterAndLeave()){
+var _589=self._mouseEnterListener(src,sig.substr(2),func,obj);
+if(sig==="onmouseenter"){
+sig="onmouseover";
+}else{
+sig="onmouseout";
+}
+}else{
+if(_588&&sig=="onmousewheel"&&self._browserLacksMouseWheelEvent()){
+var _589=self._listener(src,sig,func,obj,_588);
+sig="onDOMMouseScroll";
+}else{
+var _589=self._listener(src,sig,func,obj,_588);
+}
+}
+if(src.addEventListener){
+src.addEventListener(sig.substr(2),_589,false);
+}else{
+if(src.attachEvent){
+src.attachEvent(sig,_589);
+}
+}
+var _58a=new MochiKit.Signal.Ident({source:src,signal:sig,listener:_589,isDOM:_588,objOrFunc:_582,funcOrStr:_583,connected:true});
+self._observers.push(_58a);
+if(!_588&&typeof (src.__connect__)=="function"){
+var args=MochiKit.Base.extend([_58a],arguments,1);
+src.__connect__.apply(src,args);
+}
+return _58a;
+},_disconnect:function(_58c){
+if(!_58c.connected){
+return;
+}
+_58c.connected=false;
+var src=_58c.source;
+var sig=_58c.signal;
+var _58f=_58c.listener;
+if(!_58c.isDOM){
+if(typeof (src.__disconnect__)=="function"){
+src.__disconnect__(_58c,sig,_58c.objOrFunc,_58c.funcOrStr);
+}
+return;
+}
+if(src.removeEventListener){
+src.removeEventListener(sig.substr(2),_58f,false);
+}else{
+if(src.detachEvent){
+src.detachEvent(sig,_58f);
+}else{
+throw new Error("'src' must be a DOM element");
+}
+}
+},disconnect:function(_590){
+var self=MochiKit.Signal;
+var _592=self._observers;
+var m=MochiKit.Base;
+if(arguments.length>1){
+var src=MochiKit.DOM.getElement(arguments[0]);
+var sig=arguments[1];
+var obj=arguments[2];
+var func=arguments[3];
+for(var i=_592.length-1;i>=0;i--){
+var o=_592[i];
+if(o.source===src&&o.signal===sig&&o.objOrFunc===obj&&o.funcOrStr===func){
+self._disconnect(o);
+if(!self._lock){
+_592.splice(i,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+}else{
+var idx=m.findIdentical(_592,_590);
+if(idx>=0){
+self._disconnect(_590);
+if(!self._lock){
+_592.splice(idx,1);
+}else{
+self._dirty=true;
+}
+return true;
+}
+}
+return false;
+},disconnectAllTo:function(_59b,_59c){
+var self=MochiKit.Signal;
+var _59e=self._observers;
+var _59f=self._disconnect;
+var _5a0=self._lock;
+var _5a1=self._dirty;
+if(typeof (_59c)==="undefined"){
+_59c=null;
+}
+for(var i=_59e.length-1;i>=0;i--){
+var _5a3=_59e[i];
+if(_5a3.objOrFunc===_59b&&(_59c===null||_5a3.funcOrStr===_59c)){
+_59f(_5a3);
+if(_5a0){
+_5a1=true;
+}else{
+_59e.splice(i,1);
+}
+}
+}
+self._dirty=_5a1;
+},disconnectAll:function(src,sig){
+src=MochiKit.DOM.getElement(src);
+var m=MochiKit.Base;
+var _5a7=m.flattenArguments(m.extend(null,arguments,1));
+var self=MochiKit.Signal;
+var _5a9=self._disconnect;
+var _5aa=self._observers;
+var i,_5ac;
+var _5ad=self._lock;
+var _5ae=self._dirty;
+if(_5a7.length===0){
+for(i=_5aa.length-1;i>=0;i--){
+_5ac=_5aa[i];
+if(_5ac.source===src){
+_5a9(_5ac);
+if(!_5ad){
+_5aa.splice(i,1);
+}else{
+_5ae=true;
+}
+}
+}
+}else{
+var sigs={};
+for(i=0;i<_5a7.length;i++){
+sigs[_5a7[i]]=true;
+}
+for(i=_5aa.length-1;i>=0;i--){
+_5ac=_5aa[i];
+if(_5ac.source===src&&_5ac.signal in sigs){
+_5a9(_5ac);
+if(!_5ad){
+_5aa.splice(i,1);
+}else{
+_5ae=true;
+}
+}
+}
+}
+self._dirty=_5ae;
+},signal:function(src,sig){
+var self=MochiKit.Signal;
+var _5b3=self._observers;
+src=MochiKit.DOM.getElement(src);
+var args=MochiKit.Base.extend(null,arguments,2);
+var _5b5=[];
+self._lock=true;
+for(var i=0;i<_5b3.length;i++){
+var _5b7=_5b3[i];
+if(_5b7.source===src&&_5b7.signal===sig&&_5b7.connected){
+try{
+_5b7.listener.apply(src,args);
+}
+catch(e){
+_5b5.push(e);
+}
+}
+}
+self._lock=false;
+if(self._dirty){
+self._dirty=false;
+for(var i=_5b3.length-1;i>=0;i--){
+if(!_5b3[i].connected){
+_5b3.splice(i,1);
+}
+}
+}
+if(_5b5.length==1){
+throw _5b5[0];
+}else{
+if(_5b5.length>1){
+var e=new Error("Multiple errors thrown in handling 'sig', see errors property");
+e.errors=_5b5;
+throw e;
+}
+}
+}});
+MochiKit.Signal.EXPORT_OK=[];
+MochiKit.Signal.EXPORT=["connect","disconnect","signal","disconnectAll","disconnectAllTo"];
+MochiKit.Signal.__new__=function(win){
+var m=MochiKit.Base;
+this._document=document;
+this._window=win;
+this._lock=false;
+this._dirty=false;
+try{
+this.connect(window,"onunload",this._unloadCache);
+}
+catch(e){
+}
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Signal.__new__(this);
+if(MochiKit.__export__){
+connect=MochiKit.Signal.connect;
+disconnect=MochiKit.Signal.disconnect;
+disconnectAll=MochiKit.Signal.disconnectAll;
+signal=MochiKit.Signal.signal;
+}
+MochiKit.Base._exportSymbols(this,MochiKit.Signal);
+MochiKit.Base._deps("Position",["Base","DOM","Style"]);
+MochiKit.Position.NAME="MochiKit.Position";
+MochiKit.Position.VERSION="1.4.2";
+MochiKit.Position.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Position.toString=function(){
+return this.__repr__();
+};
+MochiKit.Position.EXPORT_OK=[];
+MochiKit.Position.EXPORT=[];
+MochiKit.Base.update(MochiKit.Position,{includeScrollOffsets:false,prepare:function(){
+var _5bb=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
+var _5bc=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;
+this.windowOffset=new MochiKit.Style.Coordinates(_5bb,_5bc);
+},cumulativeOffset:function(_5bd){
+var _5be=0;
+var _5bf=0;
+do{
+_5be+=_5bd.offsetTop||0;
+_5bf+=_5bd.offsetLeft||0;
+_5bd=_5bd.offsetParent;
+}while(_5bd);
+return new MochiKit.Style.Coordinates(_5bf,_5be);
+},realOffset:function(_5c0){
+var _5c1=0;
+var _5c2=0;
+do{
+_5c1+=_5c0.scrollTop||0;
+_5c2+=_5c0.scrollLeft||0;
+_5c0=_5c0.parentNode;
+}while(_5c0);
+return new MochiKit.Style.Coordinates(_5c2,_5c1);
+},within:function(_5c3,x,y){
+if(this.includeScrollOffsets){
+return this.withinIncludingScrolloffsets(_5c3,x,y);
+}
+this.xcomp=x;
+this.ycomp=y;
+this.offset=this.cumulativeOffset(_5c3);
+if(_5c3.style.position=="fixed"){
+this.offset.x+=this.windowOffset.x;
+this.offset.y+=this.windowOffset.y;
+}
+return (y>=this.offset.y&&y<this.offset.y+_5c3.offsetHeight&&x>=this.offset.x&&x<this.offset.x+_5c3.offsetWidth);
+},withinIncludingScrolloffsets:function(_5c6,x,y){
+var _5c9=this.realOffset(_5c6);
+this.xcomp=x+_5c9.x-this.windowOffset.x;
+this.ycomp=y+_5c9.y-this.windowOffset.y;
+this.offset=this.cumulativeOffset(_5c6);
+return (this.ycomp>=this.offset.y&&this.ycomp<this.offset.y+_5c6.offsetHeight&&this.xcomp>=this.offset.x&&this.xcomp<this.offset.x+_5c6.offsetWidth);
+},overlap:function(mode,_5cb){
+if(!mode){
+return 0;
+}
+if(mode=="vertical"){
+return ((this.offset.y+_5cb.offsetHeight)-this.ycomp)/_5cb.offsetHeight;
+}
+if(mode=="horizontal"){
+return ((this.offset.x+_5cb.offsetWidth)-this.xcomp)/_5cb.offsetWidth;
+}
+},absolutize:function(_5cc){
+_5cc=MochiKit.DOM.getElement(_5cc);
+if(_5cc.style.position=="absolute"){
+return;
+}
+MochiKit.Position.prepare();
+var _5cd=MochiKit.Position.positionedOffset(_5cc);
+var _5ce=_5cc.clientWidth;
+var _5cf=_5cc.clientHeight;
+var _5d0={"position":_5cc.style.position,"left":_5cd.x-parseFloat(_5cc.style.left||0),"top":_5cd.y-parseFloat(_5cc.style.top||0),"width":_5cc.style.width,"height":_5cc.style.height};
+_5cc.style.position="absolute";
+_5cc.style.top=_5cd.y+"px";
+_5cc.style.left=_5cd.x+"px";
+_5cc.style.width=_5ce+"px";
+_5cc.style.height=_5cf+"px";
+return _5d0;
+},positionedOffset:function(_5d1){
+var _5d2=0,_5d3=0;
+do{
+_5d2+=_5d1.offsetTop||0;
+_5d3+=_5d1.offsetLeft||0;
+_5d1=_5d1.offsetParent;
+if(_5d1){
+p=MochiKit.Style.getStyle(_5d1,"position");
+if(p=="relative"||p=="absolute"){
+break;
+}
+}
+}while(_5d1);
+return new MochiKit.Style.Coordinates(_5d3,_5d2);
+},relativize:function(_5d4,_5d5){
+_5d4=MochiKit.DOM.getElement(_5d4);
+if(_5d4.style.position=="relative"){
+return;
+}
+MochiKit.Position.prepare();
+var top=parseFloat(_5d4.style.top||0)-(_5d5["top"]||0);
+var left=parseFloat(_5d4.style.left||0)-(_5d5["left"]||0);
+_5d4.style.position=_5d5["position"];
+_5d4.style.top=top+"px";
+_5d4.style.left=left+"px";
+_5d4.style.width=_5d5["width"];
+_5d4.style.height=_5d5["height"];
+},clone:function(_5d8,_5d9){
+_5d8=MochiKit.DOM.getElement(_5d8);
+_5d9=MochiKit.DOM.getElement(_5d9);
+_5d9.style.position="absolute";
+var _5da=this.cumulativeOffset(_5d8);
+_5d9.style.top=_5da.y+"px";
+_5d9.style.left=_5da.x+"px";
+_5d9.style.width=_5d8.offsetWidth+"px";
+_5d9.style.height=_5d8.offsetHeight+"px";
+},page:function(_5db){
+var _5dc=0;
+var _5dd=0;
+var _5de=_5db;
+do{
+_5dc+=_5de.offsetTop||0;
+_5dd+=_5de.offsetLeft||0;
+if(_5de.offsetParent==document.body&&MochiKit.Style.getStyle(_5de,"position")=="absolute"){
+break;
+}
+}while(_5de=_5de.offsetParent);
+_5de=_5db;
+do{
+_5dc-=_5de.scrollTop||0;
+_5dd-=_5de.scrollLeft||0;
+}while(_5de=_5de.parentNode);
+return new MochiKit.Style.Coordinates(_5dd,_5dc);
+}});
+MochiKit.Position.__new__=function(win){
+var m=MochiKit.Base;
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+m.nameFunctions(this);
+};
+MochiKit.Position.__new__(this);
+MochiKit.Base._exportSymbols(this,MochiKit.Position);
+MochiKit.Base._deps("Visual",["Base","DOM","Style","Color","Position"]);
+MochiKit.Visual.NAME="MochiKit.Visual";
+MochiKit.Visual.VERSION="1.4.2";
+MochiKit.Visual.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Visual.toString=function(){
+return this.__repr__();
+};
+MochiKit.Visual._RoundCorners=function(e,_5e2){
+e=MochiKit.DOM.getElement(e);
+this._setOptions(_5e2);
+if(this.options.__unstable__wrapElement){
+e=this._doWrap(e);
+}
+var _5e3=this.options.color;
+var C=MochiKit.Color.Color;
+if(this.options.color==="fromElement"){
+_5e3=C.fromBackground(e);
+}else{
+if(!(_5e3 instanceof C)){
+_5e3=C.fromString(_5e3);
+}
+}
+this.isTransparent=(_5e3.asRGB().a<=0);
+var _5e5=this.options.bgColor;
+if(this.options.bgColor==="fromParent"){
+_5e5=C.fromBackground(e.offsetParent);
+}else{
+if(!(_5e5 instanceof C)){
+_5e5=C.fromString(_5e5);
+}
+}
+this._roundCornersImpl(e,_5e3,_5e5);
+};
+MochiKit.Visual._RoundCorners.prototype={_doWrap:function(e){
+var _5e7=e.parentNode;
+var doc=MochiKit.DOM.currentDocument();
+if(typeof (doc.defaultView)==="undefined"||doc.defaultView===null){
+return e;
+}
+var _5e9=doc.defaultView.getComputedStyle(e,null);
+if(typeof (_5e9)==="undefined"||_5e9===null){
+return e;
+}
+var _5ea=MochiKit.DOM.DIV({"style":{display:"block",marginTop:_5e9.getPropertyValue("padding-top"),marginRight:_5e9.getPropertyValue("padding-right"),marginBottom:_5e9.getPropertyValue("padding-bottom"),marginLeft:_5e9.getPropertyValue("padding-left"),padding:"0px"}});
+_5ea.innerHTML=e.innerHTML;
+e.innerHTML="";
+e.appendChild(_5ea);
+return e;
+},_roundCornersImpl:function(e,_5ec,_5ed){
+if(this.options.border){
+this._renderBorder(e,_5ed);
+}
+if(this._isTopRounded()){
+this._roundTopCorners(e,_5ec,_5ed);
+}
+if(this._isBottomRounded()){
+this._roundBottomCorners(e,_5ec,_5ed);
+}
+},_renderBorder:function(el,_5ef){
+var _5f0="1px solid "+this._borderColor(_5ef);
+var _5f1="border-left: "+_5f0;
+var _5f2="border-right: "+_5f0;
+var _5f3="style='"+_5f1+";"+_5f2+"'";
+el.innerHTML="<div "+_5f3+">"+el.innerHTML+"</div>";
+},_roundTopCorners:function(el,_5f5,_5f6){
+var _5f7=this._createCorner(_5f6);
+for(var i=0;i<this.options.numSlices;i++){
+_5f7.appendChild(this._createCornerSlice(_5f5,_5f6,i,"top"));
+}
+el.style.paddingTop=0;
+el.insertBefore(_5f7,el.firstChild);
+},_roundBottomCorners:function(el,_5fa,_5fb){
+var _5fc=this._createCorner(_5fb);
+for(var i=(this.options.numSlices-1);i>=0;i--){
+_5fc.appendChild(this._createCornerSlice(_5fa,_5fb,i,"bottom"));
+}
+el.style.paddingBottom=0;
+el.appendChild(_5fc);
+},_createCorner:function(_5fe){
+var dom=MochiKit.DOM;
+return dom.DIV({style:{backgroundColor:_5fe.toString()}});
+},_createCornerSlice:function(_600,_601,n,_603){
+var _604=MochiKit.DOM.SPAN();
+var _605=_604.style;
+_605.backgroundColor=_600.toString();
+_605.display="block";
+_605.height="1px";
+_605.overflow="hidden";
+_605.fontSize="1px";
+var _606=this._borderColor(_600,_601);
+if(this.options.border&&n===0){
+_605.borderTopStyle="solid";
+_605.borderTopWidth="1px";
+_605.borderLeftWidth="0px";
+_605.borderRightWidth="0px";
+_605.borderBottomWidth="0px";
+_605.height="0px";
+_605.borderColor=_606.toString();
+}else{
+if(_606){
+_605.borderColor=_606.toString();
+_605.borderStyle="solid";
+_605.borderWidth="0px 1px";
+}
+}
+if(!this.options.compact&&(n==(this.options.numSlices-1))){
+_605.height="2px";
+}
+this._setMargin(_604,n,_603);
+this._setBorder(_604,n,_603);
+return _604;
+},_setOptions:function(_607){
+this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false,__unstable__wrapElement:false};
+MochiKit.Base.update(this.options,_607);
+this.options.numSlices=(this.options.compact?2:4);
+},_whichSideTop:function(){
+var _608=this.options.corners;
+if(this._hasString(_608,"all","top")){
+return "";
+}
+var _609=(_608.indexOf("tl")!=-1);
+var _60a=(_608.indexOf("tr")!=-1);
+if(_609&&_60a){
+return "";
+}
+if(_609){
+return "left";
+}
+if(_60a){
+return "right";
+}
+return "";
+},_whichSideBottom:function(){
+var _60b=this.options.corners;
+if(this._hasString(_60b,"all","bottom")){
+return "";
+}
+var _60c=(_60b.indexOf("bl")!=-1);
+var _60d=(_60b.indexOf("br")!=-1);
+if(_60c&&_60d){
+return "";
+}
+if(_60c){
+return "left";
+}
+if(_60d){
+return "right";
+}
+return "";
+},_borderColor:function(_60e,_60f){
+if(_60e=="transparent"){
+return _60f;
+}else{
+if(this.options.border){
+return this.options.border;
+}else{
+if(this.options.blend){
+return _60f.blendedColor(_60e);
+}
+}
+}
+return "";
+},_setMargin:function(el,n,_612){
+var _613=this._marginSize(n)+"px";
+var _614=(_612=="top"?this._whichSideTop():this._whichSideBottom());
+var _615=el.style;
+if(_614=="left"){
+_615.marginLeft=_613;
+_615.marginRight="0px";
+}else{
+if(_614=="right"){
+_615.marginRight=_613;
+_615.marginLeft="0px";
+}else{
+_615.marginLeft=_613;
+_615.marginRight=_613;
+}
+}
+},_setBorder:function(el,n,_618){
+var _619=this._borderSize(n)+"px";
+var _61a=(_618=="top"?this._whichSideTop():this._whichSideBottom());
+var _61b=el.style;
+if(_61a=="left"){
+_61b.borderLeftWidth=_619;
+_61b.borderRightWidth="0px";
+}else{
+if(_61a=="right"){
+_61b.borderRightWidth=_619;
+_61b.borderLeftWidth="0px";
+}else{
+_61b.borderLeftWidth=_619;
+_61b.borderRightWidth=_619;
+}
+}
+},_marginSize:function(n){
+if(this.isTransparent){
+return 0;
+}
+var o=this.options;
+if(o.compact&&o.blend){
+var _61e=[1,0];
+return _61e[n];
+}else{
+if(o.compact){
+var _61f=[2,1];
+return _61f[n];
+}else{
+if(o.blend){
+var _620=[3,2,1,0];
+return _620[n];
+}else{
+var _621=[5,3,2,1];
+return _621[n];
+}
+}
+}
+},_borderSize:function(n){
+var o=this.options;
+var _624;
+if(o.compact&&(o.blend||this.isTransparent)){
+return 1;
+}else{
+if(o.compact){
+_624=[1,0];
+}else{
+if(o.blend){
+_624=[2,1,1,1];
+}else{
+if(o.border){
+_624=[0,2,0,0];
+}else{
+if(this.isTransparent){
+_624=[5,3,2,1];
+}else{
+return 0;
+}
+}
+}
+}
+}
+return _624[n];
+},_hasString:function(str){
+for(var i=1;i<arguments.length;i++){
+if(str.indexOf(arguments[i])!=-1){
+return true;
+}
+}
+return false;
+},_isTopRounded:function(){
+return this._hasString(this.options.corners,"all","top","tl","tr");
+},_isBottomRounded:function(){
+return this._hasString(this.options.corners,"all","bottom","bl","br");
+},_hasSingleTextChild:function(el){
+return (el.childNodes.length==1&&el.childNodes[0].nodeType==3);
+}};
+MochiKit.Visual.roundElement=function(e,_629){
+new MochiKit.Visual._RoundCorners(e,_629);
+};
+MochiKit.Visual.roundClass=function(_62a,_62b,_62c){
+var _62d=MochiKit.DOM.getElementsByTagAndClassName(_62a,_62b);
+for(var i=0;i<_62d.length;i++){
+MochiKit.Visual.roundElement(_62d[i],_62c);
+}
+};
+MochiKit.Visual.tagifyText=function(_62f,_630){
+_630=_630||"position:relative";
+if(/MSIE/.test(navigator.userAgent)){
+_630+=";zoom:1";
+}
+_62f=MochiKit.DOM.getElement(_62f);
+var ma=MochiKit.Base.map;
+ma(function(_632){
+if(_632.nodeType==3){
+ma(function(_633){
+_62f.insertBefore(MochiKit.DOM.SPAN({style:_630},_633==" "?String.fromCharCode(160):_633),_632);
+},_632.nodeValue.split(""));
+MochiKit.DOM.removeElement(_632);
+}
+},_62f.childNodes);
+};
+MochiKit.Visual.forceRerendering=function(_634){
+try{
+_634=MochiKit.DOM.getElement(_634);
+var n=document.createTextNode(" ");
+_634.appendChild(n);
+_634.removeChild(n);
+}
+catch(e){
+}
+};
+MochiKit.Visual.multiple=function(_636,_637,_638){
+_638=MochiKit.Base.update({speed:0.1,delay:0},_638);
+var _639=_638.delay;
+var _63a=0;
+MochiKit.Base.map(function(_63b){
+_638.delay=_63a*_638.speed+_639;
+new _637(_63b,_638);
+_63a+=1;
+},_636);
+};
+MochiKit.Visual.PAIRS={"slide":["slideDown","slideUp"],"blind":["blindDown","blindUp"],"appear":["appear","fade"],"size":["grow","shrink"]};
+MochiKit.Visual.toggle=function(_63c,_63d,_63e){
+_63c=MochiKit.DOM.getElement(_63c);
+_63d=(_63d||"appear").toLowerCase();
+_63e=MochiKit.Base.update({queue:{position:"end",scope:(_63c.id||"global"),limit:1}},_63e);
+var v=MochiKit.Visual;
+v[MochiKit.Style.getStyle(_63c,"display")!="none"?v.PAIRS[_63d][1]:v.PAIRS[_63d][0]](_63c,_63e);
+};
+MochiKit.Visual.Transitions={};
+MochiKit.Visual.Transitions.linear=function(pos){
+return pos;
+};
+MochiKit.Visual.Transitions.sinoidal=function(pos){
+return 0.5-Math.cos(pos*Math.PI)/2;
+};
+MochiKit.Visual.Transitions.reverse=function(pos){
+return 1-pos;
+};
+MochiKit.Visual.Transitions.flicker=function(pos){
+return 0.25-Math.cos(pos*Math.PI)/4+Math.random()/2;
+};
+MochiKit.Visual.Transitions.wobble=function(pos){
+return 0.5-Math.cos(9*pos*Math.PI)/2;
+};
+MochiKit.Visual.Transitions.pulse=function(pos,_646){
+if(_646){
+pos*=2*_646;
+}else{
+pos*=10;
+}
+var _647=pos-Math.floor(pos);
+return (Math.floor(pos)%2==0)?_647:1-_647;
+};
+MochiKit.Visual.Transitions.parabolic=function(pos){
+return pos*pos;
+};
+MochiKit.Visual.Transitions.none=function(pos){
+return 0;
+};
+MochiKit.Visual.Transitions.full=function(pos){
+return 1;
+};
+MochiKit.Visual.ScopedQueue=function(){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls();
+}
+this.__init__();
+};
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype,{__init__:function(){
+this.effects=[];
+this.interval=null;
+},add:function(_64c){
+var _64d=new Date().getTime();
+var _64e=(typeof (_64c.options.queue)=="string")?_64c.options.queue:_64c.options.queue.position;
+var ma=MochiKit.Base.map;
+switch(_64e){
+case "front":
+ma(function(e){
+if(e.state=="idle"){
+e.startOn+=_64c.finishOn;
+e.finishOn+=_64c.finishOn;
+}
+},this.effects);
+break;
+case "end":
+var _651;
+ma(function(e){
+var i=e.finishOn;
+if(i>=(_651||i)){
+_651=i;
+}
+},this.effects);
+_64d=_651||_64d;
+break;
+case "break":
+ma(function(e){
+e.finalize();
+},this.effects);
+break;
+}
+_64c.startOn+=_64d;
+_64c.finishOn+=_64d;
+if(!_64c.options.queue.limit||this.effects.length<_64c.options.queue.limit){
+this.effects.push(_64c);
+}
+if(!this.interval){
+this.interval=this.startLoop(MochiKit.Base.bind(this.loop,this),40);
+}
+},startLoop:function(func,_656){
+return setInterval(func,_656);
+},remove:function(_657){
+this.effects=MochiKit.Base.filter(function(e){
+return e!=_657;
+},this.effects);
+if(!this.effects.length){
+this.stopLoop(this.interval);
+this.interval=null;
+}
+},stopLoop:function(_659){
+clearInterval(_659);
+},loop:function(){
+var _65a=new Date().getTime();
+MochiKit.Base.map(function(_65b){
+_65b.loop(_65a);
+},this.effects);
+}});
+MochiKit.Visual.Queues={instances:{},get:function(_65c){
+if(typeof (_65c)!="string"){
+return _65c;
+}
+if(!this.instances[_65c]){
+this.instances[_65c]=new MochiKit.Visual.ScopedQueue();
+}
+return this.instances[_65c];
+}};
+MochiKit.Visual.Queue=MochiKit.Visual.Queues.get("global");
+MochiKit.Visual.DefaultOptions={transition:MochiKit.Visual.Transitions.sinoidal,duration:1,fps:25,sync:false,from:0,to:1,delay:0,queue:"parallel"};
+MochiKit.Visual.Base=function(){
+};
+MochiKit.Visual.Base.prototype={__class__:MochiKit.Visual.Base,start:function(_65d){
+var v=MochiKit.Visual;
+this.options=MochiKit.Base.setdefault(_65d,v.DefaultOptions);
+this.currentFrame=0;
+this.state="idle";
+this.startOn=this.options.delay*1000;
+this.finishOn=this.startOn+(this.options.duration*1000);
+this.event("beforeStart");
+if(!this.options.sync){
+v.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).add(this);
+}
+},loop:function(_65f){
+if(_65f>=this.startOn){
+if(_65f>=this.finishOn){
+return this.finalize();
+}
+var pos=(_65f-this.startOn)/(this.finishOn-this.startOn);
+var _661=Math.round(pos*this.options.fps*this.options.duration);
+if(_661>this.currentFrame){
+this.render(pos);
+this.currentFrame=_661;
+}
+}
+},render:function(pos){
+if(this.state=="idle"){
+this.state="running";
+this.event("beforeSetup");
+this.setup();
+this.event("afterSetup");
+}
+if(this.state=="running"){
+if(this.options.transition){
+pos=this.options.transition(pos);
+}
+pos*=(this.options.to-this.options.from);
+pos+=this.options.from;
+this.event("beforeUpdate");
+this.update(pos);
+this.event("afterUpdate");
+}
+},cancel:function(){
+if(!this.options.sync){
+MochiKit.Visual.Queues.get(typeof (this.options.queue)=="string"?"global":this.options.queue.scope).remove(this);
+}
+this.state="finished";
+},finalize:function(){
+this.render(1);
+this.cancel();
+this.event("beforeFinish");
+this.finish();
+this.event("afterFinish");
+},setup:function(){
+},finish:function(){
+},update:function(_663){
+},event:function(_664){
+if(this.options[_664+"Internal"]){
+this.options[_664+"Internal"](this);
+}
+if(this.options[_664]){
+this.options[_664](this);
+}
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.Visual.Parallel=function(_665,_666){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_665,_666);
+}
+this.__init__(_665,_666);
+};
+MochiKit.Visual.Parallel.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype,{__class__:MochiKit.Visual.Parallel,__init__:function(_668,_669){
+this.effects=_668||[];
+this.start(_669);
+},update:function(_66a){
+MochiKit.Base.map(function(_66b){
+_66b.render(_66a);
+},this.effects);
+},finish:function(){
+MochiKit.Base.map(function(_66c){
+_66c.finalize();
+},this.effects);
+}});
+MochiKit.Visual.Sequence=function(_66d,_66e){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_66d,_66e);
+}
+this.__init__(_66d,_66e);
+};
+MochiKit.Visual.Sequence.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Sequence.prototype,{__class__:MochiKit.Visual.Sequence,__init__:function(_670,_671){
+var defs={transition:MochiKit.Visual.Transitions.linear,duration:0};
+this.effects=_670||[];
+MochiKit.Base.map(function(_673){
+defs.duration+=_673.options.duration;
+},this.effects);
+MochiKit.Base.setdefault(_671,defs);
+this.start(_671);
+},update:function(_674){
+var time=_674*this.options.duration;
+for(var i=0;i<this.effects.length;i++){
+var _677=this.effects[i];
+if(time<=_677.options.duration){
+_677.render(time/_677.options.duration);
+break;
+}else{
+time-=_677.options.duration;
+}
+}
+},finish:function(){
+MochiKit.Base.map(function(_678){
+_678.finalize();
+},this.effects);
+}});
+MochiKit.Visual.Opacity=function(_679,_67a){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_679,_67a);
+}
+this.__init__(_679,_67a);
+};
+MochiKit.Visual.Opacity.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype,{__class__:MochiKit.Visual.Opacity,__init__:function(_67c,_67d){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+this.element=MochiKit.DOM.getElement(_67c);
+if(this.element.currentStyle&&(!this.element.currentStyle.hasLayout)){
+s.setStyle(this.element,{zoom:1});
+}
+_67d=b.update({from:s.getStyle(this.element,"opacity")||0,to:1},_67d);
+this.start(_67d);
+},update:function(_680){
+MochiKit.Style.setStyle(this.element,{"opacity":_680});
+}});
+MochiKit.Visual.Move=function(_681,_682){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_681,_682);
+}
+this.__init__(_681,_682);
+};
+MochiKit.Visual.Move.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Move.prototype,{__class__:MochiKit.Visual.Move,__init__:function(_684,_685){
+this.element=MochiKit.DOM.getElement(_684);
+_685=MochiKit.Base.update({x:0,y:0,mode:"relative"},_685);
+this.start(_685);
+},setup:function(){
+MochiKit.Style.makePositioned(this.element);
+var s=this.element.style;
+var _687=s.visibility;
+var _688=s.display;
+if(_688=="none"){
+s.visibility="hidden";
+s.display="";
+}
+this.originalLeft=parseFloat(MochiKit.Style.getStyle(this.element,"left")||"0");
+this.originalTop=parseFloat(MochiKit.Style.getStyle(this.element,"top")||"0");
+if(this.options.mode=="absolute"){
+this.options.x-=this.originalLeft;
+this.options.y-=this.originalTop;
+}
+if(_688=="none"){
+s.visibility=_687;
+s.display=_688;
+}
+},update:function(_689){
+MochiKit.Style.setStyle(this.element,{left:Math.round(this.options.x*_689+this.originalLeft)+"px",top:Math.round(this.options.y*_689+this.originalTop)+"px"});
+}});
+MochiKit.Visual.Scale=function(_68a,_68b,_68c){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_68a,_68b,_68c);
+}
+this.__init__(_68a,_68b,_68c);
+};
+MochiKit.Visual.Scale.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype,{__class__:MochiKit.Visual.Scale,__init__:function(_68e,_68f,_690){
+this.element=MochiKit.DOM.getElement(_68e);
+_690=MochiKit.Base.update({scaleX:true,scaleY:true,scaleContent:true,scaleFromCenter:false,scaleMode:"box",scaleFrom:100,scaleTo:_68f},_690);
+this.start(_690);
+},setup:function(){
+this.restoreAfterFinish=this.options.restoreAfterFinish||false;
+this.elementPositioning=MochiKit.Style.getStyle(this.element,"position");
+var ma=MochiKit.Base.map;
+var b=MochiKit.Base.bind;
+this.originalStyle={};
+ma(b(function(k){
+this.originalStyle[k]=this.element.style[k];
+},this),["top","left","width","height","fontSize"]);
+this.originalTop=this.element.offsetTop;
+this.originalLeft=this.element.offsetLeft;
+var _694=MochiKit.Style.getStyle(this.element,"font-size")||"100%";
+ma(b(function(_695){
+if(_694.indexOf(_695)>0){
+this.fontSize=parseFloat(_694);
+this.fontSizeType=_695;
+}
+},this),["em","px","%"]);
+this.factor=(this.options.scaleTo-this.options.scaleFrom)/100;
+if(/^content/.test(this.options.scaleMode)){
+this.dims=[this.element.scrollHeight,this.element.scrollWidth];
+}else{
+if(this.options.scaleMode=="box"){
+this.dims=[this.element.offsetHeight,this.element.offsetWidth];
+}else{
+this.dims=[this.options.scaleMode.originalHeight,this.options.scaleMode.originalWidth];
+}
+}
+},update:function(_696){
+var _697=(this.options.scaleFrom/100)+(this.factor*_696);
+if(this.options.scaleContent&&this.fontSize){
+MochiKit.Style.setStyle(this.element,{fontSize:this.fontSize*_697+this.fontSizeType});
+}
+this.setDimensions(this.dims[0]*_697,this.dims[1]*_697);
+},finish:function(){
+if(this.restoreAfterFinish){
+MochiKit.Style.setStyle(this.element,this.originalStyle);
+}
+},setDimensions:function(_698,_699){
+var d={};
+var r=Math.round;
+if(/MSIE/.test(navigator.userAgent)){
+r=Math.ceil;
+}
+if(this.options.scaleX){
+d.width=r(_699)+"px";
+}
+if(this.options.scaleY){
+d.height=r(_698)+"px";
+}
+if(this.options.scaleFromCenter){
+var topd=(_698-this.dims[0])/2;
+var _69d=(_699-this.dims[1])/2;
+if(this.elementPositioning=="absolute"){
+if(this.options.scaleY){
+d.top=this.originalTop-topd+"px";
+}
+if(this.options.scaleX){
+d.left=this.originalLeft-_69d+"px";
+}
+}else{
+if(this.options.scaleY){
+d.top=-topd+"px";
+}
+if(this.options.scaleX){
+d.left=-_69d+"px";
+}
+}
+}
+MochiKit.Style.setStyle(this.element,d);
+}});
+MochiKit.Visual.Highlight=function(_69e,_69f){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_69e,_69f);
+}
+this.__init__(_69e,_69f);
+};
+MochiKit.Visual.Highlight.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype,{__class__:MochiKit.Visual.Highlight,__init__:function(_6a1,_6a2){
+this.element=MochiKit.DOM.getElement(_6a1);
+_6a2=MochiKit.Base.update({startcolor:"#ffff99"},_6a2);
+this.start(_6a2);
+},setup:function(){
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+if(s.getStyle(this.element,"display")=="none"){
+this.cancel();
+return;
+}
+this.oldStyle={backgroundImage:s.getStyle(this.element,"background-image")};
+s.setStyle(this.element,{backgroundImage:"none"});
+if(!this.options.endcolor){
+this.options.endcolor=MochiKit.Color.Color.fromBackground(this.element).toHexString();
+}
+if(b.isUndefinedOrNull(this.options.restorecolor)){
+this.options.restorecolor=s.getStyle(this.element,"background-color");
+}
+this._base=b.map(b.bind(function(i){
+return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this._delta=b.map(b.bind(function(i){
+return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i];
+},this),[0,1,2]);
+},update:function(_6a7){
+var m="#";
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(this._base[i]+this._delta[i]*_6a7));
+},this),[0,1,2]);
+MochiKit.Style.setStyle(this.element,{backgroundColor:m});
+},finish:function(){
+MochiKit.Style.setStyle(this.element,MochiKit.Base.update(this.oldStyle,{backgroundColor:this.options.restorecolor}));
+}});
+MochiKit.Visual.ScrollTo=function(_6aa,_6ab){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_6aa,_6ab);
+}
+this.__init__(_6aa,_6ab);
+};
+MochiKit.Visual.ScrollTo.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype,{__class__:MochiKit.Visual.ScrollTo,__init__:function(_6ad,_6ae){
+this.element=MochiKit.DOM.getElement(_6ad);
+this.start(_6ae);
+},setup:function(){
+var p=MochiKit.Position;
+p.prepare();
+var _6b0=p.cumulativeOffset(this.element);
+if(this.options.offset){
+_6b0.y+=this.options.offset;
+}
+var max;
+if(window.innerHeight){
+max=window.innerHeight-window.height;
+}else{
+if(document.documentElement&&document.documentElement.clientHeight){
+max=document.documentElement.clientHeight-document.body.scrollHeight;
+}else{
+if(document.body){
+max=document.body.clientHeight-document.body.scrollHeight;
+}
+}
+}
+this.scrollStart=p.windowOffset.y;
+this.delta=(_6b0.y>max?max:_6b0.y)-this.scrollStart;
+},update:function(_6b2){
+var p=MochiKit.Position;
+p.prepare();
+window.scrollTo(p.windowOffset.x,this.scrollStart+(_6b2*this.delta));
+}});
+MochiKit.Visual.CSS_LENGTH=/^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+MochiKit.Visual.Morph=function(_6b4,_6b5){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_6b4,_6b5);
+}
+this.__init__(_6b4,_6b5);
+};
+MochiKit.Visual.Morph.prototype=new MochiKit.Visual.Base();
+MochiKit.Base.update(MochiKit.Visual.Morph.prototype,{__class__:MochiKit.Visual.Morph,__init__:function(_6b7,_6b8){
+this.element=MochiKit.DOM.getElement(_6b7);
+this.start(_6b8);
+},setup:function(){
+var b=MochiKit.Base;
+var _6ba=this.options.style;
+this.styleStart={};
+this.styleEnd={};
+this.units={};
+var _6bb,unit;
+for(var s in _6ba){
+_6bb=_6ba[s];
+s=b.camelize(s);
+if(MochiKit.Visual.CSS_LENGTH.test(_6bb)){
+var _6be=_6bb.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_6bb=parseFloat(_6be[1]);
+unit=(_6be.length==3)?_6be[2]:null;
+this.styleEnd[s]=_6bb;
+this.units[s]=unit;
+_6bb=MochiKit.Style.getStyle(this.element,s);
+_6be=_6bb.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+_6bb=parseFloat(_6be[1]);
+this.styleStart[s]=_6bb;
+}else{
+if(/[Cc]olor$/.test(s)){
+var c=MochiKit.Color.Color;
+_6bb=c.fromString(_6bb);
+if(_6bb){
+this.units[s]="color";
+this.styleEnd[s]=_6bb.toHexString();
+_6bb=MochiKit.Style.getStyle(this.element,s);
+this.styleStart[s]=c.fromString(_6bb).toHexString();
+this.styleStart[s]=b.map(b.bind(function(i){
+return parseInt(this.styleStart[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+this.styleEnd[s]=b.map(b.bind(function(i){
+return parseInt(this.styleEnd[s].slice(i*2+1,i*2+3),16);
+},this),[0,1,2]);
+}
+}else{
+this.element.style[s]=_6bb;
+}
+}
+}
+},update:function(_6c2){
+var _6c3;
+for(var s in this.styleStart){
+if(this.units[s]=="color"){
+var m="#";
+var _6c6=this.styleStart[s];
+var end=this.styleEnd[s];
+MochiKit.Base.map(MochiKit.Base.bind(function(i){
+m+=MochiKit.Color.toColorPart(Math.round(_6c6[i]+(end[i]-_6c6[i])*_6c2));
+},this),[0,1,2]);
+this.element.style[s]=m;
+}else{
+_6c3=this.styleStart[s]+Math.round((this.styleEnd[s]-this.styleStart[s])*_6c2*1000)/1000+this.units[s];
+this.element.style[s]=_6c3;
+}
+}
+}});
+MochiKit.Visual.fade=function(_6c9,_6ca){
+var s=MochiKit.Style;
+var _6cc=s.getStyle(_6c9,"opacity");
+_6ca=MochiKit.Base.update({from:s.getStyle(_6c9,"opacity")||1,to:0,afterFinishInternal:function(_6cd){
+if(_6cd.options.to!==0){
+return;
+}
+s.hideElement(_6cd.element);
+s.setStyle(_6cd.element,{"opacity":_6cc});
+}},_6ca);
+return new MochiKit.Visual.Opacity(_6c9,_6ca);
+};
+MochiKit.Visual.appear=function(_6ce,_6cf){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_6cf=MochiKit.Base.update({from:(s.getStyle(_6ce,"display")=="none"?0:s.getStyle(_6ce,"opacity")||0),to:1,afterFinishInternal:function(_6d2){
+v.forceRerendering(_6d2.element);
+},beforeSetupInternal:function(_6d3){
+s.setStyle(_6d3.element,{"opacity":_6d3.options.from});
+s.showElement(_6d3.element);
+}},_6cf);
+return new v.Opacity(_6ce,_6cf);
+};
+MochiKit.Visual.puff=function(_6d4,_6d5){
+var s=MochiKit.Style;
+var v=MochiKit.Visual;
+_6d4=MochiKit.DOM.getElement(_6d4);
+var _6d8=MochiKit.Style.getElementDimensions(_6d4,true);
+var _6d9={position:s.getStyle(_6d4,"position"),top:_6d4.style.top,left:_6d4.style.left,width:_6d4.style.width,height:_6d4.style.height,opacity:s.getStyle(_6d4,"opacity")};
+_6d5=MochiKit.Base.update({beforeSetupInternal:function(_6da){
+MochiKit.Position.absolutize(_6da.effects[0].element);
+},afterFinishInternal:function(_6db){
+s.hideElement(_6db.effects[0].element);
+s.setStyle(_6db.effects[0].element,_6d9);
+},scaleContent:true,scaleFromCenter:true},_6d5);
+return new v.Parallel([new v.Scale(_6d4,200,{sync:true,scaleFromCenter:_6d5.scaleFromCenter,scaleMode:{originalHeight:_6d8.h,originalWidth:_6d8.w},scaleContent:_6d5.scaleContent,restoreAfterFinish:true}),new v.Opacity(_6d4,{sync:true,to:0})],_6d5);
+};
+MochiKit.Visual.blindUp=function(_6dc,_6dd){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6dc=d.getElement(_6dc);
+var _6e0=s.getElementDimensions(_6dc,true);
+var _6e1=s.makeClipping(_6dc);
+_6dd=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_6e0.h,originalWidth:_6e0.w},restoreAfterFinish:true,afterFinishInternal:function(_6e2){
+s.hideElement(_6e2.element);
+s.undoClipping(_6e2.element,_6e1);
+}},_6dd);
+return new MochiKit.Visual.Scale(_6dc,0,_6dd);
+};
+MochiKit.Visual.blindDown=function(_6e3,_6e4){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6e3=d.getElement(_6e3);
+var _6e7=s.getElementDimensions(_6e3,true);
+var _6e8;
+_6e4=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_6e7.h,originalWidth:_6e7.w},restoreAfterFinish:true,afterSetupInternal:function(_6e9){
+_6e8=s.makeClipping(_6e9.element);
+s.setStyle(_6e9.element,{height:"0px"});
+s.showElement(_6e9.element);
+},afterFinishInternal:function(_6ea){
+s.undoClipping(_6ea.element,_6e8);
+}},_6e4);
+return new MochiKit.Visual.Scale(_6e3,100,_6e4);
+};
+MochiKit.Visual.switchOff=function(_6eb,_6ec){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6eb=d.getElement(_6eb);
+var _6ef=s.getElementDimensions(_6eb,true);
+var _6f0=s.getStyle(_6eb,"opacity");
+var _6f1;
+_6ec=MochiKit.Base.update({duration:0.7,restoreAfterFinish:true,beforeSetupInternal:function(_6f2){
+s.makePositioned(_6eb);
+_6f1=s.makeClipping(_6eb);
+},afterFinishInternal:function(_6f3){
+s.hideElement(_6eb);
+s.undoClipping(_6eb,_6f1);
+s.undoPositioned(_6eb);
+s.setStyle(_6eb,{"opacity":_6f0});
+}},_6ec);
+var v=MochiKit.Visual;
+return new v.Sequence([new v.appear(_6eb,{sync:true,duration:0.57*_6ec.duration,from:0,transition:v.Transitions.flicker}),new v.Scale(_6eb,1,{sync:true,duration:0.43*_6ec.duration,scaleFromCenter:true,scaleX:false,scaleMode:{originalHeight:_6ef.h,originalWidth:_6ef.w},scaleContent:false,restoreAfterFinish:true})],_6ec);
+};
+MochiKit.Visual.dropOut=function(_6f5,_6f6){
+var d=MochiKit.DOM;
+var s=MochiKit.Style;
+_6f5=d.getElement(_6f5);
+var _6f9={top:s.getStyle(_6f5,"top"),left:s.getStyle(_6f5,"left"),opacity:s.getStyle(_6f5,"opacity")};
+_6f6=MochiKit.Base.update({duration:0.5,distance:100,beforeSetupInternal:function(_6fa){
+s.makePositioned(_6fa.effects[0].element);
+},afterFinishInternal:function(_6fb){
+s.hideElement(_6fb.effects[0].element);
+s.undoPositioned(_6fb.effects[0].element);
+s.setStyle(_6fb.effects[0].element,_6f9);
+}},_6f6);
+var v=MochiKit.Visual;
+return new v.Parallel([new v.Move(_6f5,{x:0,y:_6f6.distance,sync:true}),new v.Opacity(_6f5,{sync:true,to:0})],_6f6);
+};
+MochiKit.Visual.shake=function(_6fd,_6fe){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_6fd=d.getElement(_6fd);
+var _702={top:s.getStyle(_6fd,"top"),left:s.getStyle(_6fd,"left")};
+_6fe=MochiKit.Base.update({duration:0.5,afterFinishInternal:function(_703){
+s.undoPositioned(_6fd);
+s.setStyle(_6fd,_702);
+}},_6fe);
+return new v.Sequence([new v.Move(_6fd,{sync:true,duration:0.1*_6fe.duration,x:20,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:-40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:-40,y:0}),new v.Move(_6fd,{sync:true,duration:0.2*_6fe.duration,x:40,y:0}),new v.Move(_6fd,{sync:true,duration:0.1*_6fe.duration,x:-20,y:0})],_6fe);
+};
+MochiKit.Visual.slideDown=function(_704,_705){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_704=d.getElement(_704);
+if(!_704.firstChild){
+throw new Error("MochiKit.Visual.slideDown must be used on a element with a child");
+}
+d.removeEmptyTextNodes(_704);
+var _709=s.getStyle(_704.firstChild,"bottom")||0;
+var _70a=s.getElementDimensions(_704,true);
+var _70b;
+_705=b.update({scaleContent:false,scaleX:false,scaleFrom:0,scaleMode:{originalHeight:_70a.h,originalWidth:_70a.w},restoreAfterFinish:true,afterSetupInternal:function(_70c){
+s.makePositioned(_70c.element);
+s.makePositioned(_70c.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_70c.element,{top:""});
+}
+_70b=s.makeClipping(_70c.element);
+s.setStyle(_70c.element,{height:"0px"});
+s.showElement(_70c.element);
+},afterUpdateInternal:function(_70d){
+var _70e=s.getElementDimensions(_70d.element,true);
+s.setStyle(_70d.element.firstChild,{bottom:(_70d.dims[0]-_70e.h)+"px"});
+},afterFinishInternal:function(_70f){
+s.undoClipping(_70f.element,_70b);
+if(/MSIE/.test(navigator.userAgent)){
+s.undoPositioned(_70f.element);
+s.undoPositioned(_70f.element.firstChild);
+}else{
+s.undoPositioned(_70f.element.firstChild);
+s.undoPositioned(_70f.element);
+}
+s.setStyle(_70f.element.firstChild,{bottom:_709});
+}},_705);
+return new MochiKit.Visual.Scale(_704,100,_705);
+};
+MochiKit.Visual.slideUp=function(_710,_711){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+_710=d.getElement(_710);
+if(!_710.firstChild){
+throw new Error("MochiKit.Visual.slideUp must be used on a element with a child");
+}
+d.removeEmptyTextNodes(_710);
+var _715=s.getStyle(_710.firstChild,"bottom");
+var _716=s.getElementDimensions(_710,true);
+var _717;
+_711=b.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_716.h,originalWidth:_716.w},scaleFrom:100,restoreAfterFinish:true,beforeStartInternal:function(_718){
+s.makePositioned(_718.element);
+s.makePositioned(_718.element.firstChild);
+if(/Opera/.test(navigator.userAgent)){
+s.setStyle(_718.element,{top:""});
+}
+_717=s.makeClipping(_718.element);
+s.showElement(_718.element);
+},afterUpdateInternal:function(_719){
+var _71a=s.getElementDimensions(_719.element,true);
+s.setStyle(_719.element.firstChild,{bottom:(_719.dims[0]-_71a.h)+"px"});
+},afterFinishInternal:function(_71b){
+s.hideElement(_71b.element);
+s.undoClipping(_71b.element,_717);
+s.undoPositioned(_71b.element.firstChild);
+s.undoPositioned(_71b.element);
+s.setStyle(_71b.element.firstChild,{bottom:_715});
+}},_711);
+return new MochiKit.Visual.Scale(_710,0,_711);
+};
+MochiKit.Visual.squish=function(_71c,_71d){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+var s=MochiKit.Style;
+var _721=s.getElementDimensions(_71c,true);
+var _722;
+_71d=b.update({restoreAfterFinish:true,scaleMode:{originalHeight:_721.w,originalWidth:_721.h},beforeSetupInternal:function(_723){
+_722=s.makeClipping(_723.element);
+},afterFinishInternal:function(_724){
+s.hideElement(_724.element);
+s.undoClipping(_724.element,_722);
+}},_71d);
+return new MochiKit.Visual.Scale(_71c,/Opera/.test(navigator.userAgent)?1:0,_71d);
+};
+MochiKit.Visual.grow=function(_725,_726){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_725=d.getElement(_725);
+_726=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.full,scaleContent:true,scaleFromCenter:false},_726);
+var _72a={top:_725.style.top,left:_725.style.left,height:_725.style.height,width:_725.style.width,opacity:s.getStyle(_725,"opacity")};
+var dims=s.getElementDimensions(_725,true);
+var _72c,_72d;
+var _72e,_72f;
+switch(_726.direction){
+case "top-left":
+_72c=_72d=_72e=_72f=0;
+break;
+case "top-right":
+_72c=dims.w;
+_72d=_72f=0;
+_72e=-dims.w;
+break;
+case "bottom-left":
+_72c=_72e=0;
+_72d=dims.h;
+_72f=-dims.h;
+break;
+case "bottom-right":
+_72c=dims.w;
+_72d=dims.h;
+_72e=-dims.w;
+_72f=-dims.h;
+break;
+case "center":
+_72c=dims.w/2;
+_72d=dims.h/2;
+_72e=-dims.w/2;
+_72f=-dims.h/2;
+break;
+}
+var _730=MochiKit.Base.update({beforeSetupInternal:function(_731){
+s.setStyle(_731.effects[0].element,{height:"0px"});
+s.showElement(_731.effects[0].element);
+},afterFinishInternal:function(_732){
+s.undoClipping(_732.effects[0].element);
+s.undoPositioned(_732.effects[0].element);
+s.setStyle(_732.effects[0].element,_72a);
+}},_726);
+return new v.Move(_725,{x:_72c,y:_72d,duration:0.01,beforeSetupInternal:function(_733){
+s.hideElement(_733.element);
+s.makeClipping(_733.element);
+s.makePositioned(_733.element);
+},afterFinishInternal:function(_734){
+new v.Parallel([new v.Opacity(_734.element,{sync:true,to:1,from:0,transition:_726.opacityTransition}),new v.Move(_734.element,{x:_72e,y:_72f,sync:true,transition:_726.moveTransition}),new v.Scale(_734.element,100,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,scaleFrom:/Opera/.test(navigator.userAgent)?1:0,transition:_726.scaleTransition,scaleContent:_726.scaleContent,scaleFromCenter:_726.scaleFromCenter,restoreAfterFinish:true})],_730);
+}});
+};
+MochiKit.Visual.shrink=function(_735,_736){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_735=d.getElement(_735);
+_736=MochiKit.Base.update({direction:"center",moveTransition:v.Transitions.sinoidal,scaleTransition:v.Transitions.sinoidal,opacityTransition:v.Transitions.none,scaleContent:true,scaleFromCenter:false},_736);
+var _73a={top:_735.style.top,left:_735.style.left,height:_735.style.height,width:_735.style.width,opacity:s.getStyle(_735,"opacity")};
+var dims=s.getElementDimensions(_735,true);
+var _73c,_73d;
+switch(_736.direction){
+case "top-left":
+_73c=_73d=0;
+break;
+case "top-right":
+_73c=dims.w;
+_73d=0;
+break;
+case "bottom-left":
+_73c=0;
+_73d=dims.h;
+break;
+case "bottom-right":
+_73c=dims.w;
+_73d=dims.h;
+break;
+case "center":
+_73c=dims.w/2;
+_73d=dims.h/2;
+break;
+}
+var _73e;
+var _73f=MochiKit.Base.update({beforeStartInternal:function(_740){
+s.makePositioned(_740.effects[0].element);
+_73e=s.makeClipping(_740.effects[0].element);
+},afterFinishInternal:function(_741){
+s.hideElement(_741.effects[0].element);
+s.undoClipping(_741.effects[0].element,_73e);
+s.undoPositioned(_741.effects[0].element);
+s.setStyle(_741.effects[0].element,_73a);
+}},_736);
+return new v.Parallel([new v.Opacity(_735,{sync:true,to:0,from:1,transition:_736.opacityTransition}),new v.Scale(_735,/Opera/.test(navigator.userAgent)?1:0,{scaleMode:{originalHeight:dims.h,originalWidth:dims.w},sync:true,transition:_736.scaleTransition,scaleContent:_736.scaleContent,scaleFromCenter:_736.scaleFromCenter,restoreAfterFinish:true}),new v.Move(_735,{x:_73c,y:_73d,sync:true,transition:_736.moveTransition})],_73f);
+};
+MochiKit.Visual.pulsate=function(_742,_743){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var b=MochiKit.Base;
+var _747=MochiKit.Style.getStyle(_742,"opacity");
+_743=b.update({duration:3,from:0,afterFinishInternal:function(_748){
+MochiKit.Style.setStyle(_748.element,{"opacity":_747});
+}},_743);
+var _749=_743.transition||v.Transitions.sinoidal;
+_743.transition=function(pos){
+return _749(1-v.Transitions.pulse(pos,_743.pulses));
+};
+return new v.Opacity(_742,_743);
+};
+MochiKit.Visual.fold=function(_74b,_74c){
+var d=MochiKit.DOM;
+var v=MochiKit.Visual;
+var s=MochiKit.Style;
+_74b=d.getElement(_74b);
+var _750=s.getElementDimensions(_74b,true);
+var _751={top:_74b.style.top,left:_74b.style.left,width:_74b.style.width,height:_74b.style.height};
+var _752=s.makeClipping(_74b);
+_74c=MochiKit.Base.update({scaleContent:false,scaleX:false,scaleMode:{originalHeight:_750.h,originalWidth:_750.w},afterFinishInternal:function(_753){
+new v.Scale(_74b,1,{scaleContent:false,scaleY:false,scaleMode:{originalHeight:_750.h,originalWidth:_750.w},afterFinishInternal:function(_754){
+s.hideElement(_754.element);
+s.undoClipping(_754.element,_752);
+s.setStyle(_754.element,_751);
+}});
+}},_74c);
+return new v.Scale(_74b,5,_74c);
+};
+MochiKit.Visual.Color=MochiKit.Color.Color;
+MochiKit.Visual.getElementsComputedStyle=MochiKit.DOM.computedStyle;
+MochiKit.Visual.__new__=function(){
+var m=MochiKit.Base;
+m.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":m.concat(this.EXPORT,this.EXPORT_OK)};
+};
+MochiKit.Visual.EXPORT=["roundElement","roundClass","tagifyText","multiple","toggle","Parallel","Sequence","Opacity","Move","Scale","Highlight","ScrollTo","Morph","fade","appear","puff","blindUp","blindDown","switchOff","dropOut","shake","slideDown","slideUp","squish","grow","shrink","pulsate","fold"];
+MochiKit.Visual.EXPORT_OK=["Base","PAIRS"];
+MochiKit.Visual.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Visual);
+MochiKit.Base._deps("DragAndDrop",["Base","Iter","DOM","Signal","Visual","Position"]);
+MochiKit.DragAndDrop.NAME="MochiKit.DragAndDrop";
+MochiKit.DragAndDrop.VERSION="1.4.2";
+MochiKit.DragAndDrop.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.DragAndDrop.toString=function(){
+return this.__repr__();
+};
+MochiKit.DragAndDrop.EXPORT=["Droppable","Draggable"];
+MochiKit.DragAndDrop.EXPORT_OK=["Droppables","Draggables"];
+MochiKit.DragAndDrop.Droppables={drops:[],remove:function(_756){
+this.drops=MochiKit.Base.filter(function(d){
+return d.element!=MochiKit.DOM.getElement(_756);
+},this.drops);
+},register:function(drop){
+this.drops.push(drop);
+},unregister:function(drop){
+this.drops=MochiKit.Base.filter(function(d){
+return d!=drop;
+},this.drops);
+},prepare:function(_75b){
+MochiKit.Base.map(function(drop){
+if(drop.isAccepted(_75b)){
+if(drop.options.activeclass){
+MochiKit.DOM.addElementClass(drop.element,drop.options.activeclass);
+}
+drop.options.onactive(drop.element,_75b);
+}
+},this.drops);
+},findDeepestChild:function(_75d){
+deepest=_75d[0];
+for(i=1;i<_75d.length;++i){
+if(MochiKit.DOM.isChildNode(_75d[i].element,deepest.element)){
+deepest=_75d[i];
+}
+}
+return deepest;
+},show:function(_75e,_75f){
+if(!this.drops.length){
+return;
+}
+var _760=[];
+if(this.last_active){
+this.last_active.deactivate();
+}
+MochiKit.Iter.forEach(this.drops,function(drop){
+if(drop.isAffected(_75e,_75f)){
+_760.push(drop);
+}
+});
+if(_760.length>0){
+drop=this.findDeepestChild(_760);
+MochiKit.Position.within(drop.element,_75e.page.x,_75e.page.y);
+drop.options.onhover(_75f,drop.element,MochiKit.Position.overlap(drop.options.overlap,drop.element));
+drop.activate();
+}
+},fire:function(_762,_763){
+if(!this.last_active){
+return;
+}
+MochiKit.Position.prepare();
+if(this.last_active.isAffected(_762.mouse(),_763)){
+this.last_active.options.ondrop(_763,this.last_active.element,_762);
+}
+},reset:function(_764){
+MochiKit.Base.map(function(drop){
+if(drop.options.activeclass){
+MochiKit.DOM.removeElementClass(drop.element,drop.options.activeclass);
+}
+drop.options.ondesactive(drop.element,_764);
+},this.drops);
+if(this.last_active){
+this.last_active.deactivate();
+}
+}};
+MochiKit.DragAndDrop.Droppable=function(_766,_767){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_766,_767);
+}
+this.__init__(_766,_767);
+};
+MochiKit.DragAndDrop.Droppable.prototype={__class__:MochiKit.DragAndDrop.Droppable,__init__:function(_769,_76a){
+var d=MochiKit.DOM;
+var b=MochiKit.Base;
+this.element=d.getElement(_769);
+this.options=b.update({greedy:true,hoverclass:null,activeclass:null,hoverfunc:b.noop,accept:null,onactive:b.noop,ondesactive:b.noop,onhover:b.noop,ondrop:b.noop,containment:[],tree:false},_76a);
+this.options._containers=[];
+b.map(MochiKit.Base.bind(function(c){
+this.options._containers.push(d.getElement(c));
+},this),this.options.containment);
+MochiKit.Style.makePositioned(this.element);
+MochiKit.DragAndDrop.Droppables.register(this);
+},isContained:function(_76e){
+if(this.options._containers.length){
+var _76f;
+if(this.options.tree){
+_76f=_76e.treeNode;
+}else{
+_76f=_76e.parentNode;
+}
+return MochiKit.Iter.some(this.options._containers,function(c){
+return _76f==c;
+});
+}else{
+return true;
+}
+},isAccepted:function(_771){
+return ((!this.options.accept)||MochiKit.Iter.some(this.options.accept,function(c){
+return MochiKit.DOM.hasElementClass(_771,c);
+}));
+},isAffected:function(_773,_774){
+return ((this.element!=_774)&&this.isContained(_774)&&this.isAccepted(_774)&&MochiKit.Position.within(this.element,_773.page.x,_773.page.y));
+},deactivate:function(){
+if(this.options.hoverclass){
+MochiKit.DOM.removeElementClass(this.element,this.options.hoverclass);
+}
+this.options.hoverfunc(this.element,false);
+MochiKit.DragAndDrop.Droppables.last_active=null;
+},activate:function(){
+if(this.options.hoverclass){
+MochiKit.DOM.addElementClass(this.element,this.options.hoverclass);
+}
+this.options.hoverfunc(this.element,true);
+MochiKit.DragAndDrop.Droppables.last_active=this;
+},destroy:function(){
+MochiKit.DragAndDrop.Droppables.unregister(this);
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.DragAndDrop.Draggables={drags:[],register:function(_775){
+if(this.drags.length===0){
+var conn=MochiKit.Signal.connect;
+this.eventMouseUp=conn(document,"onmouseup",this,this.endDrag);
+this.eventMouseMove=conn(document,"onmousemove",this,this.updateDrag);
+this.eventKeypress=conn(document,"onkeypress",this,this.keyPress);
+}
+this.drags.push(_775);
+},unregister:function(_777){
+this.drags=MochiKit.Base.filter(function(d){
+return d!=_777;
+},this.drags);
+if(this.drags.length===0){
+var disc=MochiKit.Signal.disconnect;
+disc(this.eventMouseUp);
+disc(this.eventMouseMove);
+disc(this.eventKeypress);
+}
+},activate:function(_77a){
+window.focus();
+this.activeDraggable=_77a;
+},deactivate:function(){
+this.activeDraggable=null;
+},updateDrag:function(_77b){
+if(!this.activeDraggable){
+return;
+}
+var _77c=_77b.mouse();
+if(this._lastPointer&&(MochiKit.Base.repr(this._lastPointer.page)==MochiKit.Base.repr(_77c.page))){
+return;
+}
+this._lastPointer=_77c;
+this.activeDraggable.updateDrag(_77b,_77c);
+},endDrag:function(_77d){
+if(!this.activeDraggable){
+return;
+}
+this._lastPointer=null;
+this.activeDraggable.endDrag(_77d);
+this.activeDraggable=null;
+},keyPress:function(_77e){
+if(this.activeDraggable){
+this.activeDraggable.keyPress(_77e);
+}
+},notify:function(_77f,_780,_781){
+MochiKit.Signal.signal(this,_77f,_780,_781);
+}};
+MochiKit.DragAndDrop.Draggable=function(_782,_783){
+var cls=arguments.callee;
+if(!(this instanceof cls)){
+return new cls(_782,_783);
+}
+this.__init__(_782,_783);
+};
+MochiKit.DragAndDrop.Draggable.prototype={__class__:MochiKit.DragAndDrop.Draggable,__init__:function(_785,_786){
+var v=MochiKit.Visual;
+var b=MochiKit.Base;
+_786=b.update({handle:false,starteffect:function(_789){
+this._savedOpacity=MochiKit.Style.getStyle(_789,"opacity")||1;
+new v.Opacity(_789,{duration:0.2,from:this._savedOpacity,to:0.7});
+},reverteffect:function(_78a,_78b,_78c){
+var dur=Math.sqrt(Math.abs(_78b^2)+Math.abs(_78c^2))*0.02;
+return new v.Move(_78a,{x:-_78c,y:-_78b,duration:dur});
+},endeffect:function(_78e){
+new v.Opacity(_78e,{duration:0.2,from:0.7,to:this._savedOpacity});
+},onchange:b.noop,zindex:1000,revert:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,snap:false},_786);
+var d=MochiKit.DOM;
+this.element=d.getElement(_785);
+if(_786.handle&&(typeof (_786.handle)=="string")){
+this.handle=d.getFirstElementByTagAndClassName(null,_786.handle,this.element);
+}
+if(!this.handle){
+this.handle=d.getElement(_786.handle);
+}
+if(!this.handle){
+this.handle=this.element;
+}
+if(_786.scroll&&!_786.scroll.scrollTo&&!_786.scroll.outerHTML){
+_786.scroll=d.getElement(_786.scroll);
+this._isScrollChild=MochiKit.DOM.isChildNode(this.element,_786.scroll);
+}
+MochiKit.Style.makePositioned(this.element);
+this.delta=this.currentDelta();
+this.options=_786;
+this.dragging=false;
+this.eventMouseDown=MochiKit.Signal.connect(this.handle,"onmousedown",this,this.initDrag);
+MochiKit.DragAndDrop.Draggables.register(this);
+},destroy:function(){
+MochiKit.Signal.disconnect(this.eventMouseDown);
+MochiKit.DragAndDrop.Draggables.unregister(this);
+},currentDelta:function(){
+var s=MochiKit.Style.getStyle;
+return [parseInt(s(this.element,"left")||"0"),parseInt(s(this.element,"top")||"0")];
+},initDrag:function(_791){
+if(!_791.mouse().button.left){
+return;
+}
+var src=_791.target();
+var _793=(src.tagName||"").toUpperCase();
+if(_793==="INPUT"||_793==="SELECT"||_793==="OPTION"||_793==="BUTTON"||_793==="TEXTAREA"){
+return;
+}
+if(this._revert){
+this._revert.cancel();
+this._revert=null;
+}
+var _794=_791.mouse();
+var pos=MochiKit.Position.cumulativeOffset(this.element);
+this.offset=[_794.page.x-pos.x,_794.page.y-pos.y];
+MochiKit.DragAndDrop.Draggables.activate(this);
+_791.stop();
+},startDrag:function(_796){
+this.dragging=true;
+if(this.options.selectclass){
+MochiKit.DOM.addElementClass(this.element,this.options.selectclass);
+}
+if(this.options.zindex){
+this.originalZ=parseInt(MochiKit.Style.getStyle(this.element,"z-index")||"0");
+this.element.style.zIndex=this.options.zindex;
+}
+if(this.options.ghosting){
+this._clone=this.element.cloneNode(true);
+this.ghostPosition=MochiKit.Position.absolutize(this.element);
+this.element.parentNode.insertBefore(this._clone,this.element);
+}
+if(this.options.scroll){
+if(this.options.scroll==window){
+var _797=this._getWindowScroll(this.options.scroll);
+this.originalScrollLeft=_797.left;
+this.originalScrollTop=_797.top;
+}else{
+this.originalScrollLeft=this.options.scroll.scrollLeft;
+this.originalScrollTop=this.options.scroll.scrollTop;
+}
+}
+MochiKit.DragAndDrop.Droppables.prepare(this.element);
+MochiKit.DragAndDrop.Draggables.notify("start",this,_796);
+if(this.options.starteffect){
+this.options.starteffect(this.element);
+}
+},updateDrag:function(_798,_799){
+if(!this.dragging){
+this.startDrag(_798);
+}
+MochiKit.Position.prepare();
+MochiKit.DragAndDrop.Droppables.show(_799,this.element);
+MochiKit.DragAndDrop.Draggables.notify("drag",this,_798);
+this.draw(_799);
+this.options.onchange(this);
+if(this.options.scroll){
+this.stopScrolling();
+var p,q;
+if(this.options.scroll==window){
+var s=this._getWindowScroll(this.options.scroll);
+p=new MochiKit.Style.Coordinates(s.left,s.top);
+q=new MochiKit.Style.Coordinates(s.left+s.width,s.top+s.height);
+}else{
+p=MochiKit.Position.page(this.options.scroll);
+p.x+=this.options.scroll.scrollLeft;
+p.y+=this.options.scroll.scrollTop;
+p.x+=(window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0);
+p.y+=(window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0);
+q=new MochiKit.Style.Coordinates(p.x+this.options.scroll.offsetWidth,p.y+this.options.scroll.offsetHeight);
+}
+var _79d=[0,0];
+if(_799.page.x>(q.x-this.options.scrollSensitivity)){
+_79d[0]=_799.page.x-(q.x-this.options.scrollSensitivity);
+}else{
+if(_799.page.x<(p.x+this.options.scrollSensitivity)){
+_79d[0]=_799.page.x-(p.x+this.options.scrollSensitivity);
+}
+}
+if(_799.page.y>(q.y-this.options.scrollSensitivity)){
+_79d[1]=_799.page.y-(q.y-this.options.scrollSensitivity);
+}else{
+if(_799.page.y<(p.y+this.options.scrollSensitivity)){
+_79d[1]=_799.page.y-(p.y+this.options.scrollSensitivity);
+}
+}
+this.startScrolling(_79d);
+}
+if(/AppleWebKit/.test(navigator.appVersion)){
+window.scrollBy(0,0);
+}
+_798.stop();
+},finishDrag:function(_79e,_79f){
+var dr=MochiKit.DragAndDrop;
+this.dragging=false;
+if(this.options.selectclass){
+MochiKit.DOM.removeElementClass(this.element,this.options.selectclass);
+}
+if(this.options.ghosting){
+MochiKit.Position.relativize(this.element,this.ghostPosition);
+MochiKit.DOM.removeElement(this._clone);
+this._clone=null;
+}
+if(_79f){
+dr.Droppables.fire(_79e,this.element);
+}
+dr.Draggables.notify("end",this,_79e);
+var _7a1=this.options.revert;
+if(_7a1&&typeof (_7a1)=="function"){
+_7a1=_7a1(this.element);
+}
+var d=this.currentDelta();
+if(_7a1&&this.options.reverteffect){
+this._revert=this.options.reverteffect(this.element,d[1]-this.delta[1],d[0]-this.delta[0]);
+}else{
+this.delta=d;
+}
+if(this.options.zindex){
+this.element.style.zIndex=this.originalZ;
+}
+if(this.options.endeffect){
+this.options.endeffect(this.element);
+}
+dr.Draggables.deactivate();
+dr.Droppables.reset(this.element);
+},keyPress:function(_7a3){
+if(_7a3.key().string!="KEY_ESCAPE"){
+return;
+}
+this.finishDrag(_7a3,false);
+_7a3.stop();
+},endDrag:function(_7a4){
+if(!this.dragging){
+return;
+}
+this.stopScrolling();
+this.finishDrag(_7a4,true);
+_7a4.stop();
+},draw:function(_7a5){
+var pos=MochiKit.Position.cumulativeOffset(this.element);
+var d=this.currentDelta();
+pos.x-=d[0];
+pos.y-=d[1];
+if(this.options.scroll&&(this.options.scroll!=window&&this._isScrollChild)){
+pos.x-=this.options.scroll.scrollLeft-this.originalScrollLeft;
+pos.y-=this.options.scroll.scrollTop-this.originalScrollTop;
+}
+var p=[_7a5.page.x-pos.x-this.offset[0],_7a5.page.y-pos.y-this.offset[1]];
+if(this.options.snap){
+if(typeof (this.options.snap)=="function"){
+p=this.options.snap(p[0],p[1]);
+}else{
+if(this.options.snap instanceof Array){
+var i=-1;
+p=MochiKit.Base.map(MochiKit.Base.bind(function(v){
+i+=1;
+return Math.round(v/this.options.snap[i])*this.options.snap[i];
+},this),p);
+}else{
+p=MochiKit.Base.map(MochiKit.Base.bind(function(v){
+return Math.round(v/this.options.snap)*this.options.snap;
+},this),p);
+}
+}
+}
+var _7ac=this.element.style;
+if((!this.options.constraint)||(this.options.constraint=="horizontal")){
+_7ac.left=p[0]+"px";
+}
+if((!this.options.constraint)||(this.options.constraint=="vertical")){
+_7ac.top=p[1]+"px";
+}
+if(_7ac.visibility=="hidden"){
+_7ac.visibility="";
+}
+},stopScrolling:function(){
+if(this.scrollInterval){
+clearInterval(this.scrollInterval);
+this.scrollInterval=null;
+MochiKit.DragAndDrop.Draggables._lastScrollPointer=null;
+}
+},startScrolling:function(_7ad){
+if(!_7ad[0]&&!_7ad[1]){
+return;
+}
+this.scrollSpeed=[_7ad[0]*this.options.scrollSpeed,_7ad[1]*this.options.scrollSpeed];
+this.lastScrolled=new Date();
+this.scrollInterval=setInterval(MochiKit.Base.bind(this.scroll,this),10);
+},scroll:function(){
+var _7ae=new Date();
+var _7af=_7ae-this.lastScrolled;
+this.lastScrolled=_7ae;
+if(this.options.scroll==window){
+var s=this._getWindowScroll(this.options.scroll);
+if(this.scrollSpeed[0]||this.scrollSpeed[1]){
+var dm=_7af/1000;
+this.options.scroll.scrollTo(s.left+dm*this.scrollSpeed[0],s.top+dm*this.scrollSpeed[1]);
+}
+}else{
+this.options.scroll.scrollLeft+=this.scrollSpeed[0]*_7af/1000;
+this.options.scroll.scrollTop+=this.scrollSpeed[1]*_7af/1000;
+}
+var d=MochiKit.DragAndDrop;
+MochiKit.Position.prepare();
+d.Droppables.show(d.Draggables._lastPointer,this.element);
+d.Draggables.notify("drag",this);
+if(this._isScrollChild){
+d.Draggables._lastScrollPointer=d.Draggables._lastScrollPointer||d.Draggables._lastPointer;
+d.Draggables._lastScrollPointer.x+=this.scrollSpeed[0]*_7af/1000;
+d.Draggables._lastScrollPointer.y+=this.scrollSpeed[1]*_7af/1000;
+if(d.Draggables._lastScrollPointer.x<0){
+d.Draggables._lastScrollPointer.x=0;
+}
+if(d.Draggables._lastScrollPointer.y<0){
+d.Draggables._lastScrollPointer.y=0;
+}
+this.draw(d.Draggables._lastScrollPointer);
+}
+this.options.onchange(this);
+},_getWindowScroll:function(win){
+var vp,w,h;
+MochiKit.DOM.withWindow(win,function(){
+vp=MochiKit.Style.getViewportPosition(win.document);
+});
+if(win.innerWidth){
+w=win.innerWidth;
+h=win.innerHeight;
+}else{
+if(win.document.documentElement&&win.document.documentElement.clientWidth){
+w=win.document.documentElement.clientWidth;
+h=win.document.documentElement.clientHeight;
+}else{
+w=win.document.body.offsetWidth;
+h=win.document.body.offsetHeight;
+}
+}
+return {top:vp.y,left:vp.x,width:w,height:h};
+},repr:function(){
+return "["+this.__class__.NAME+", options:"+MochiKit.Base.repr(this.options)+"]";
+}};
+MochiKit.DragAndDrop.__new__=function(){
+MochiKit.Base.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)};
+};
+MochiKit.DragAndDrop.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.DragAndDrop);
+MochiKit.Base._deps("Sortable",["Base","Iter","DOM","Position","DragAndDrop"]);
+MochiKit.Sortable.NAME="MochiKit.Sortable";
+MochiKit.Sortable.VERSION="1.4.2";
+MochiKit.Sortable.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.Sortable.toString=function(){
+return this.__repr__();
+};
+MochiKit.Sortable.EXPORT=[];
+MochiKit.Sortable.EXPORT_OK=[];
+MochiKit.Base.update(MochiKit.Sortable,{sortables:{},_findRootElement:function(_7b7){
+while(_7b7.tagName.toUpperCase()!="BODY"){
+if(_7b7.id&&MochiKit.Sortable.sortables[_7b7.id]){
+return _7b7;
+}
+_7b7=_7b7.parentNode;
+}
+},_createElementId:function(_7b8){
+if(_7b8.id==null||_7b8.id==""){
+var d=MochiKit.DOM;
+var id;
+var _7bb=1;
+while(d.getElement(id="sortable"+_7bb)!=null){
+_7bb+=1;
+}
+d.setNodeAttribute(_7b8,"id",id);
+}
+},options:function(_7bc){
+_7bc=MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(_7bc));
+if(!_7bc){
+return;
+}
+return MochiKit.Sortable.sortables[_7bc.id];
+},destroy:function(_7bd){
+var s=MochiKit.Sortable.options(_7bd);
+var b=MochiKit.Base;
+var d=MochiKit.DragAndDrop;
+if(s){
+MochiKit.Signal.disconnect(s.startHandle);
+MochiKit.Signal.disconnect(s.endHandle);
+b.map(function(dr){
+d.Droppables.remove(dr);
+},s.droppables);
+b.map(function(dr){
+dr.destroy();
+},s.draggables);
+delete MochiKit.Sortable.sortables[s.element.id];
+}
+},create:function(_7c3,_7c4){
+_7c3=MochiKit.DOM.getElement(_7c3);
+var self=MochiKit.Sortable;
+self._createElementId(_7c3);
+_7c4=MochiKit.Base.update({element:_7c3,tag:"li",dropOnEmpty:false,tree:false,treeTag:"ul",overlap:"vertical",constraint:"vertical",containment:[_7c3],handle:false,only:false,hoverclass:null,ghosting:false,scroll:false,scrollSensitivity:20,scrollSpeed:15,format:/^[^_]*_(.*)$/,onChange:MochiKit.Base.noop,onUpdate:MochiKit.Base.noop,accept:null},_7c4);
+self.destroy(_7c3);
+var _7c6={revert:true,ghosting:_7c4.ghosting,scroll:_7c4.scroll,scrollSensitivity:_7c4.scrollSensitivity,scrollSpeed:_7c4.scrollSpeed,constraint:_7c4.constraint,handle:_7c4.handle};
+if(_7c4.starteffect){
+_7c6.starteffect=_7c4.starteffect;
+}
+if(_7c4.reverteffect){
+_7c6.reverteffect=_7c4.reverteffect;
+}else{
+if(_7c4.ghosting){
+_7c6.reverteffect=function(_7c7){
+_7c7.style.top=0;
+_7c7.style.left=0;
+};
+}
+}
+if(_7c4.endeffect){
+_7c6.endeffect=_7c4.endeffect;
+}
+if(_7c4.zindex){
+_7c6.zindex=_7c4.zindex;
+}
+var _7c8={overlap:_7c4.overlap,containment:_7c4.containment,hoverclass:_7c4.hoverclass,onhover:self.onHover,tree:_7c4.tree,accept:_7c4.accept};
+var _7c9={onhover:self.onEmptyHover,overlap:_7c4.overlap,containment:_7c4.containment,hoverclass:_7c4.hoverclass,accept:_7c4.accept};
+MochiKit.DOM.removeEmptyTextNodes(_7c3);
+_7c4.draggables=[];
+_7c4.droppables=[];
+if(_7c4.dropOnEmpty||_7c4.tree){
+new MochiKit.DragAndDrop.Droppable(_7c3,_7c9);
+_7c4.droppables.push(_7c3);
+}
+MochiKit.Base.map(function(e){
+var _7cb=_7c4.handle?MochiKit.DOM.getFirstElementByTagAndClassName(null,_7c4.handle,e):e;
+_7c4.draggables.push(new MochiKit.DragAndDrop.Draggable(e,MochiKit.Base.update(_7c6,{handle:_7cb})));
+new MochiKit.DragAndDrop.Droppable(e,_7c8);
+if(_7c4.tree){
+e.treeNode=_7c3;
+}
+_7c4.droppables.push(e);
+},(self.findElements(_7c3,_7c4)||[]));
+if(_7c4.tree){
+MochiKit.Base.map(function(e){
+new MochiKit.DragAndDrop.Droppable(e,_7c9);
+e.treeNode=_7c3;
+_7c4.droppables.push(e);
+},(self.findTreeElements(_7c3,_7c4)||[]));
+}
+self.sortables[_7c3.id]=_7c4;
+_7c4.lastValue=self.serialize(_7c3);
+_7c4.startHandle=MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables,"start",MochiKit.Base.partial(self.onStart,_7c3));
+_7c4.endHandle=MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables,"end",MochiKit.Base.partial(self.onEnd,_7c3));
+},onStart:function(_7cd,_7ce){
+var self=MochiKit.Sortable;
+var _7d0=self.options(_7cd);
+_7d0.lastValue=self.serialize(_7d0.element);
+},onEnd:function(_7d1,_7d2){
+var self=MochiKit.Sortable;
+self.unmark();
+var _7d4=self.options(_7d1);
+if(_7d4.lastValue!=self.serialize(_7d4.element)){
+_7d4.onUpdate(_7d4.element);
+}
+},findElements:function(_7d5,_7d6){
+return MochiKit.Sortable.findChildren(_7d5,_7d6.only,_7d6.tree,_7d6.tag);
+},findTreeElements:function(_7d7,_7d8){
+return MochiKit.Sortable.findChildren(_7d7,_7d8.only,_7d8.tree?true:false,_7d8.treeTag);
+},findChildren:function(_7d9,only,_7db,_7dc){
+if(!_7d9.hasChildNodes()){
+return null;
+}
+_7dc=_7dc.toUpperCase();
+if(only){
+only=MochiKit.Base.flattenArray([only]);
+}
+var _7dd=[];
+MochiKit.Base.map(function(e){
+if(e.tagName&&e.tagName.toUpperCase()==_7dc&&(!only||MochiKit.Iter.some(only,function(c){
+return MochiKit.DOM.hasElementClass(e,c);
+}))){
+_7dd.push(e);
+}
+if(_7db){
+var _7e0=MochiKit.Sortable.findChildren(e,only,_7db,_7dc);
+if(_7e0&&_7e0.length>0){
+_7dd=_7dd.concat(_7e0);
+}
+}
+},_7d9.childNodes);
+return _7dd;
+},onHover:function(_7e1,_7e2,_7e3){
+if(MochiKit.DOM.isChildNode(_7e2,_7e1)){
+return;
+}
+var self=MochiKit.Sortable;
+if(_7e3>0.33&&_7e3<0.66&&self.options(_7e2).tree){
+return;
+}else{
+if(_7e3>0.5){
+self.mark(_7e2,"before");
+if(_7e2.previousSibling!=_7e1){
+var _7e5=_7e1.parentNode;
+_7e1.style.visibility="hidden";
+_7e2.parentNode.insertBefore(_7e1,_7e2);
+if(_7e2.parentNode!=_7e5){
+self.options(_7e5).onChange(_7e1);
+}
+self.options(_7e2.parentNode).onChange(_7e1);
+}
+}else{
+self.mark(_7e2,"after");
+var _7e6=_7e2.nextSibling||null;
+if(_7e6!=_7e1){
+var _7e5=_7e1.parentNode;
+_7e1.style.visibility="hidden";
+_7e2.parentNode.insertBefore(_7e1,_7e6);
+if(_7e2.parentNode!=_7e5){
+self.options(_7e5).onChange(_7e1);
+}
+self.options(_7e2.parentNode).onChange(_7e1);
+}
+}
+}
+},_offsetSize:function(_7e7,type){
+if(type=="vertical"||type=="height"){
+return _7e7.offsetHeight;
+}else{
+return _7e7.offsetWidth;
+}
+},onEmptyHover:function(_7e9,_7ea,_7eb){
+var _7ec=_7e9.parentNode;
+var self=MochiKit.Sortable;
+var _7ee=self.options(_7ea);
+if(!MochiKit.DOM.isChildNode(_7ea,_7e9)){
+var _7ef;
+var _7f0=self.findElements(_7ea,{tag:_7ee.tag,only:_7ee.only});
+var _7f1=null;
+if(_7f0){
+var _7f2=self._offsetSize(_7ea,_7ee.overlap)*(1-_7eb);
+for(_7ef=0;_7ef<_7f0.length;_7ef+=1){
+if(_7f2-self._offsetSize(_7f0[_7ef],_7ee.overlap)>=0){
+_7f2-=self._offsetSize(_7f0[_7ef],_7ee.overlap);
+}else{
+if(_7f2-(self._offsetSize(_7f0[_7ef],_7ee.overlap)/2)>=0){
+_7f1=_7ef+1<_7f0.length?_7f0[_7ef+1]:null;
+break;
+}else{
+_7f1=_7f0[_7ef];
+break;
+}
+}
+}
+}
+_7ea.insertBefore(_7e9,_7f1);
+self.options(_7ec).onChange(_7e9);
+_7ee.onChange(_7e9);
+}
+},unmark:function(){
+var m=MochiKit.Sortable._marker;
+if(m){
+MochiKit.Style.hideElement(m);
+}
+},mark:function(_7f4,_7f5){
+var d=MochiKit.DOM;
+var self=MochiKit.Sortable;
+var _7f8=self.options(_7f4.parentNode);
+if(_7f8&&!_7f8.ghosting){
+return;
+}
+if(!self._marker){
+self._marker=d.getElement("dropmarker")||document.createElement("DIV");
+MochiKit.Style.hideElement(self._marker);
+d.addElementClass(self._marker,"dropmarker");
+self._marker.style.position="absolute";
+document.getElementsByTagName("body").item(0).appendChild(self._marker);
+}
+var _7f9=MochiKit.Position.cumulativeOffset(_7f4);
+self._marker.style.left=_7f9.x+"px";
+self._marker.style.top=_7f9.y+"px";
+if(_7f5=="after"){
+if(_7f8.overlap=="horizontal"){
+self._marker.style.left=(_7f9.x+_7f4.clientWidth)+"px";
+}else{
+self._marker.style.top=(_7f9.y+_7f4.clientHeight)+"px";
+}
+}
+MochiKit.Style.showElement(self._marker);
+},_tree:function(_7fa,_7fb,_7fc){
+var self=MochiKit.Sortable;
+var _7fe=self.findElements(_7fa,_7fb)||[];
+for(var i=0;i<_7fe.length;++i){
+var _800=_7fe[i].id.match(_7fb.format);
+if(!_800){
+continue;
+}
+var _801={id:encodeURIComponent(_800?_800[1]:null),element:_7fa,parent:_7fc,children:[],position:_7fc.children.length,container:self._findChildrenElement(_7fe[i],_7fb.treeTag.toUpperCase())};
+if(_801.container){
+self._tree(_801.container,_7fb,_801);
+}
+_7fc.children.push(_801);
+}
+return _7fc;
+},_findChildrenElement:function(_802,_803){
+if(_802&&_802.hasChildNodes){
+_803=_803.toUpperCase();
+for(var i=0;i<_802.childNodes.length;++i){
+if(_802.childNodes[i].tagName.toUpperCase()==_803){
+return _802.childNodes[i];
+}
+}
+}
+return null;
+},tree:function(_805,_806){
+_805=MochiKit.DOM.getElement(_805);
+var _807=MochiKit.Sortable.options(_805);
+_806=MochiKit.Base.update({tag:_807.tag,treeTag:_807.treeTag,only:_807.only,name:_805.id,format:_807.format},_806||{});
+var root={id:null,parent:null,children:new Array,container:_805,position:0};
+return MochiKit.Sortable._tree(_805,_806,root);
+},setSequence:function(_809,_80a,_80b){
+var self=MochiKit.Sortable;
+var b=MochiKit.Base;
+_809=MochiKit.DOM.getElement(_809);
+_80b=b.update(self.options(_809),_80b||{});
+var _80e={};
+b.map(function(n){
+var m=n.id.match(_80b.format);
+if(m){
+_80e[m[1]]=[n,n.parentNode];
+}
+n.parentNode.removeChild(n);
+},self.findElements(_809,_80b));
+b.map(function(_811){
+var n=_80e[_811];
+if(n){
+n[1].appendChild(n[0]);
+delete _80e[_811];
+}
+},_80a);
+},_constructIndex:function(node){
+var _814="";
+do{
+if(node.id){
+_814="["+node.position+"]"+_814;
+}
+}while((node=node.parent)!=null);
+return _814;
+},sequence:function(_815,_816){
+_815=MochiKit.DOM.getElement(_815);
+var self=MochiKit.Sortable;
+var _816=MochiKit.Base.update(self.options(_815),_816||{});
+return MochiKit.Base.map(function(item){
+return item.id.match(_816.format)?item.id.match(_816.format)[1]:"";
+},MochiKit.DOM.getElement(self.findElements(_815,_816)||[]));
+},serialize:function(_819,_81a){
+_819=MochiKit.DOM.getElement(_819);
+var self=MochiKit.Sortable;
+_81a=MochiKit.Base.update(self.options(_819),_81a||{});
+var name=encodeURIComponent(_81a.name||_819.id);
+if(_81a.tree){
+return MochiKit.Base.flattenArray(MochiKit.Base.map(function(item){
+return [name+self._constructIndex(item)+"[id]="+encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+},self.tree(_819,_81a).children)).join("&");
+}else{
+return MochiKit.Base.map(function(item){
+return name+"[]="+encodeURIComponent(item);
+},self.sequence(_819,_81a)).join("&");
+}
+}});
+MochiKit.Sortable.Sortable=MochiKit.Sortable;
+MochiKit.Sortable.__new__=function(){
+MochiKit.Base.nameFunctions(this);
+this.EXPORT_TAGS={":common":this.EXPORT,":all":MochiKit.Base.concat(this.EXPORT,this.EXPORT_OK)};
+};
+MochiKit.Sortable.__new__();
+MochiKit.Base._exportSymbols(this,MochiKit.Sortable);
+if(typeof (MochiKit)=="undefined"){
+MochiKit={};
+}
+if(typeof (MochiKit.MochiKit)=="undefined"){
+MochiKit.MochiKit={};
+}
+MochiKit.MochiKit.NAME="MochiKit.MochiKit";
+MochiKit.MochiKit.VERSION="1.4.2";
+MochiKit.MochiKit.__repr__=function(){
+return "["+this.NAME+" "+this.VERSION+"]";
+};
+MochiKit.MochiKit.toString=function(){
+return this.__repr__();
+};
+MochiKit.MochiKit.SUBMODULES=["Base","Iter","Logging","DateTime","Format","Async","DOM","Selector","Style","LoggingPane","Color","Signal","Position","Visual","DragAndDrop","Sortable"];
+if(typeof (JSAN)!="undefined"||typeof (dojo)!="undefined"){
+if(typeof (dojo)!="undefined"){
+dojo.provide("MochiKit.MochiKit");
+(function(lst){
+for(var i=0;i<lst.length;i++){
+dojo.require("MochiKit."+lst[i]);
+}
+})(MochiKit.MochiKit.SUBMODULES);
+}
+if(typeof (JSAN)!="undefined"){
+(function(lst){
+for(var i=0;i<lst.length;i++){
+JSAN.use("MochiKit."+lst[i],[]);
+}
+})(MochiKit.MochiKit.SUBMODULES);
+}
+(function(){
+var _823=MochiKit.Base.extend;
+var self=MochiKit.MochiKit;
+var _825=self.SUBMODULES;
+var _826=[];
+var _827=[];
+var _828={};
+var i,k,m,all;
+for(i=0;i<_825.length;i++){
+m=MochiKit[_825[i]];
+_823(_826,m.EXPORT);
+_823(_827,m.EXPORT_OK);
+for(k in m.EXPORT_TAGS){
+_828[k]=_823(_828[k],m.EXPORT_TAGS[k]);
+}
+all=m.EXPORT_TAGS[":all"];
+if(!all){
+all=_823(null,m.EXPORT,m.EXPORT_OK);
+}
+var j;
+for(j=0;j<all.length;j++){
+k=all[j];
+self[k]=m[k];
+}
+}
+self.EXPORT=_826;
+self.EXPORT_OK=_827;
+self.EXPORT_TAGS=_828;
+}());
+}else{
+if(typeof (MochiKit.__compat__)=="undefined"){
+MochiKit.__compat__=true;
+}
+(function(){
+if(typeof (document)=="undefined"){
+return;
+}
+var _82e=document.getElementsByTagName("script");
+var _82f="http://www.w3.org/1999/xhtml";
+var _830="http://www.w3.org/2000/svg";
+var _831="http://www.w3.org/1999/xlink";
+var _832="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+var base=null;
+var _834=null;
+var _835={};
+var i;
+var src;
+for(i=0;i<_82e.length;i++){
+src=null;
+switch(_82e[i].namespaceURI){
+case _830:
+src=_82e[i].getAttributeNS(_831,"href");
+break;
+default:
+src=_82e[i].getAttribute("src");
+break;
+}
+if(!src){
+continue;
+}
+_835[src]=true;
+if(src.match(/MochiKit.js(\?.*)?$/)){
+base=src.substring(0,src.lastIndexOf("MochiKit.js"));
+_834=_82e[i];
+}
+}
+if(base===null){
+return;
+}
+var _838=MochiKit.MochiKit.SUBMODULES;
+for(var i=0;i<_838.length;i++){
+if(MochiKit[_838[i]]){
+continue;
+}
+var uri=base+_838[i]+".js";
+if(uri in _835){
+continue;
+}
+if(_834.namespaceURI==_830||_834.namespaceURI==_832){
+var s=document.createElementNS(_834.namespaceURI,"script");
+s.setAttribute("id","MochiKit_"+base+_838[i]);
+if(_834.namespaceURI==_830){
+s.setAttributeNS(_831,"href",uri);
+}else{
+s.setAttribute("src",uri);
+}
+s.setAttribute("type","application/x-javascript");
+_834.parentNode.appendChild(s);
+}else{
+document.write("<"+_834.nodeName+" src=\""+uri+"\" type=\"text/javascript\"></script>");
+}
+}
+})();
+}
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/debug.js
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/debug.js	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/debug.js	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,161 @@
+function showFrame(anchor) {
+    var tbid = anchor.getAttribute('tbid');
+    var expanded = anchor.expanded;
+    if (expanded) {
+        MochiKit.DOM.hideElement(anchor.expandedElement);
+        anchor.expanded = false;
+        _swapImage(anchor);
+        return false;
+    }
+    anchor.expanded = true;
+    if (anchor.expandedElement) {
+        MochiKit.DOM.showElement(anchor.expandedElement);
+        _swapImage(anchor);
+        $('debug_input_'+tbid).focus();
+        return false;
+    }
+    var url = debug_base
+        + '/show_frame?tbid=' + tbid
+        + '&debugcount=' + debug_count;
+    var d = MochiKit.Async.doSimpleXMLHttpRequest(url);
+    d.addCallbacks(function (data) {
+        var el = MochiKit.DOM.DIV({});
+        anchor.parentNode.insertBefore(el, anchor.nextSibling);
+        el.innerHTML = data.responseText;
+        anchor.expandedElement = el;
+        _swapImage(anchor);
+        $('debug_input_'+tbid).focus();
+    }, function (error) {
+        showError(error.req.responseText);
+    });
+    return false;
+}
+
+function _swapImage(anchor) {
+    var el = anchor.getElementsByTagName('IMG')[0];
+    if (anchor.expanded) {
+        var img = 'minus.jpg';
+    } else {
+        var img = 'plus.jpg';
+    }
+    el.src = debug_base + '/media/' + img;
+}
+
+function submitInput(button, tbid) {
+    var input = $(button.getAttribute('input-from'));
+    var output = $(button.getAttribute('output-to'));
+    var url = debug_base
+        + '/exec_input';
+    var history = input.form.history;
+    input.historyPosition = 0;
+    if (! history) {
+        history = input.form.history = [];
+    }
+    history.push(input.value);
+    var vars = {
+        tbid: tbid,
+        debugcount: debug_count,
+        input: input.value
+    };
+    MochiKit.DOM.showElement(output);
+    var d = MochiKit.Async.doSimpleXMLHttpRequest(url, vars);
+    d.addCallbacks(function (data) {
+        var result = data.responseText;
+        output.innerHTML += result;
+        input.value = '';
+        input.focus();
+    }, function (error) {
+        showError(error.req.responseText);
+    });
+    return false;
+}
+
+function showError(msg) {
+    var el = $('error-container');
+    if (el.innerHTML) {
+        el.innerHTML += '<hr noshade>\n' + msg;
+    } else {
+        el.innerHTML = msg;
+    }
+    MochiKit.DOM.showElement('error-area');
+}
+
+function clearError() {
+    var el = $('error-container');
+    el.innerHTML = '';
+    MochiKit.DOM.hideElement('error-area');
+}
+
+function expandInput(button) {
+    var input = button.form.elements.input;
+    stdops = {
+        name: 'input',
+        style: 'width: 100%',
+        autocomplete: 'off'
+    };
+    if (input.tagName == 'INPUT') {
+        var newEl = MochiKit.DOM.TEXTAREA(stdops);
+        var text = 'Contract';
+    } else {
+        stdops['type'] = 'text';
+        stdops['onkeypress'] = 'upArrow(this)';
+        var newEl = MochiKit.DOM.INPUT(stdops);
+        var text = 'Expand';
+    }
+    newEl.value = input.value;
+    newEl.id = input.id;
+    MochiKit.DOM.swapDOM(input, newEl);
+    newEl.focus();
+    button.value = text;
+    return false;
+}
+
+function upArrow(input, event) {
+    if (window.event) {
+        event = window.event;
+    }
+    if (event.keyCode != 38 && event.keyCode != 40) {
+        // not an up- or down-arrow
+        return true;
+    }
+    var dir = event.keyCode == 38 ? 1 : -1;
+    var history = input.form.history;
+    if (! history) {
+        history = input.form.history = [];
+    }
+    var pos = input.historyPosition || 0;
+    if (! pos && dir == -1) {
+        return true;
+    }
+    if (! pos && input.value) {
+        history.push(input.value);
+        pos = 1;
+    }
+    pos += dir;
+    if (history.length-pos < 0) {
+        pos = 1;
+    }
+    if (history.length-pos > history.length-1) {
+        input.value = '';
+        return true;
+    }
+    input.historyPosition = pos;
+    var line = history[history.length-pos];
+    input.value = line;
+}
+
+function expandLong(anchor) {
+    var span = anchor;
+    while (span) {
+        if (span.style && span.style.display == 'none') {
+            break;
+        }
+        span = span.nextSibling;
+    }
+    if (! span) {
+        return false;
+    }
+    MochiKit.DOM.showElement(span);
+    MochiKit.DOM.hideElement(anchor);
+    return false;
+}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/minus.jpg
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/minus.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/plus.jpg
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/media/plus.jpg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/middleware.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/middleware.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/evalexception/middleware.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,610 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Exception-catching middleware that allows interactive debugging.
+
+This middleware catches all unexpected exceptions.  A normal
+traceback, like produced by
+``paste.exceptions.errormiddleware.ErrorMiddleware`` is given, plus
+controls to see local variables and evaluate expressions in a local
+context.
+
+This can only be used in single-process environments, because
+subsequent requests must go back to the same process that the
+exception originally occurred in.  Threaded or non-concurrent
+environments both work.
+
+This shouldn't be used in production in any way.  That would just be
+silly.
+
+If calling from an XMLHttpRequest call, if the GET variable ``_`` is
+given then it will make the response more compact (and less
+Javascripty), since if you use innerHTML it'll kill your browser.  You
+can look for the header X-Debug-URL in your 500 responses if you want
+to see the full debuggable traceback.  Also, this URL is printed to
+``wsgi.errors``, so you can open it up in another browser window.
+"""
+import sys
+import os
+import cgi
+import traceback
+from cStringIO import StringIO
+import pprint
+import itertools
+import time
+import re
+from paste.exceptions import errormiddleware, formatter, collector
+from paste import wsgilib
+from paste import urlparser
+from paste import httpexceptions
+from paste import registry
+from paste import request
+from paste import response
+import evalcontext
+
+limit = 200
+
+def html_quote(v):
+    """
+    Escape HTML characters, plus translate None to ''
+    """
+    if v is None:
+        return ''
+    return cgi.escape(str(v), 1)
+
+def preserve_whitespace(v, quote=True):
+    """
+    Quote a value for HTML, preserving whitespace (translating
+    newlines to ``<br>`` and multiple spaces to use ``&nbsp;``).
+
+    If ``quote`` is true, then the value will be HTML quoted first.
+    """
+    if quote:
+        v = html_quote(v)
+    v = v.replace('\n', '<br>\n')
+    v = re.sub(r'()(  +)', _repl_nbsp, v)
+    v = re.sub(r'(\n)( +)', _repl_nbsp, v)
+    v = re.sub(r'^()( +)', _repl_nbsp, v)
+    return '<code>%s</code>' % v
+
+def _repl_nbsp(match):
+    if len(match.group(2)) == 1:
+        return '&nbsp;'
+    return match.group(1) + '&nbsp;' * (len(match.group(2))-1) + ' '
+
+def simplecatcher(application):
+    """
+    A simple middleware that catches errors and turns them into simple
+    tracebacks.
+    """
+    def simplecatcher_app(environ, start_response):
+        try:
+            return application(environ, start_response)
+        except:
+            out = StringIO()
+            traceback.print_exc(file=out)
+            start_response('500 Server Error',
+                           [('content-type', 'text/html')],
+                           sys.exc_info())
+            res = out.getvalue()
+            return ['<h3>Error</h3><pre>%s</pre>'
+                    % html_quote(res)]
+    return simplecatcher_app
+
+def wsgiapp():
+    """
+    Turns a function or method into a WSGI application.
+    """
+    def decorator(func):
+        def wsgiapp_wrapper(*args):
+            # we get 3 args when this is a method, two when it is
+            # a function :(
+            if len(args) == 3:
+                environ = args[1]
+                start_response = args[2]
+                args = [args[0]]
+            else:
+                environ, start_response = args
+                args = []
+            def application(environ, start_response):
+                form = wsgilib.parse_formvars(environ,
+                                              include_get_vars=True)
+                headers = response.HeaderDict(
+                    {'content-type': 'text/html',
+                     'status': '200 OK'})
+                form['environ'] = environ
+                form['headers'] = headers
+                res = func(*args, **form.mixed())
+                status = headers.pop('status')
+                start_response(status, headers.headeritems())
+                return [res]
+            app = httpexceptions.make_middleware(application)
+            app = simplecatcher(app)
+            return app(environ, start_response)
+        wsgiapp_wrapper.exposed = True
+        return wsgiapp_wrapper
+    return decorator
+
+def get_debug_info(func):
+    """
+    A decorator (meant to be used under ``wsgiapp()``) that resolves
+    the ``debugcount`` variable to a ``DebugInfo`` object (or gives an
+    error if it can't be found).
+    """
+    def debug_info_replacement(self, **form):
+        try:
+            if 'debugcount' not in form:
+                raise ValueError('You must provide a debugcount parameter')
+            debugcount = form.pop('debugcount')
+            try:
+                debugcount = int(debugcount)
+            except ValueError:
+                raise ValueError('Bad value for debugcount')
+            if debugcount not in self.debug_infos:
+                raise ValueError(
+                    'Debug %s no longer found (maybe it has expired?)'
+                    % debugcount)
+            debug_info = self.debug_infos[debugcount]
+            return func(self, debug_info=debug_info, **form)
+        except ValueError, e:
+            form['headers']['status'] = '500 Server Error'
+            return '<html>There was an error: %s</html>' % html_quote(e)
+    return debug_info_replacement
+
+debug_counter = itertools.count(int(time.time()))
+def get_debug_count(environ):
+    """
+    Return the unique debug count for the current request
+    """
+    if 'paste.evalexception.debug_count' in environ:
+        return environ['paste.evalexception.debug_count']
+    else:
+        environ['paste.evalexception.debug_count'] = next = debug_counter.next()
+        return next
+
+class EvalException(object):
+
+    def __init__(self, application, global_conf=None,
+                 xmlhttp_key=None):
+        self.application = application
+        self.debug_infos = {}
+        if xmlhttp_key is None:
+            if global_conf is None:
+                xmlhttp_key = '_'
+            else:
+                xmlhttp_key = global_conf.get('xmlhttp_key', '_')
+        self.xmlhttp_key = xmlhttp_key
+
+    def __call__(self, environ, start_response):
+        assert not environ['wsgi.multiprocess'], (
+            "The EvalException middleware is not usable in a "
+            "multi-process environment")
+        environ['paste.evalexception'] = self
+        if environ.get('PATH_INFO', '').startswith('/_debug/'):
+            return self.debug(environ, start_response)
+        else:
+            return self.respond(environ, start_response)
+
+    def debug(self, environ, start_response):
+        assert request.path_info_pop(environ) == '_debug'
+        next_part = request.path_info_pop(environ)
+        method = getattr(self, next_part, None)
+        if not method:
+            exc = httpexceptions.HTTPNotFound(
+                '%r not found when parsing %r'
+                % (next_part, wsgilib.construct_url(environ)))
+            return exc.wsgi_application(environ, start_response)
+        if not getattr(method, 'exposed', False):
+            exc = httpexceptions.HTTPForbidden(
+                '%r not allowed' % next_part)
+            return exc.wsgi_application(environ, start_response)
+        return method(environ, start_response)
+
+    def media(self, environ, start_response):
+        """
+        Static path where images and other files live
+        """
+        app = urlparser.StaticURLParser(
+            os.path.join(os.path.dirname(__file__), 'media'))
+        return app(environ, start_response)
+    media.exposed = True
+
+    def mochikit(self, environ, start_response):
+        """
+        Static path where MochiKit lives
+        """
+        app = urlparser.StaticURLParser(
+            os.path.join(os.path.dirname(__file__), 'mochikit'))
+        return app(environ, start_response)
+    mochikit.exposed = True
+
+    def summary(self, environ, start_response):
+        """
+        Returns a JSON-format summary of all the cached
+        exception reports
+        """
+        start_response('200 OK', [('Content-type', 'text/x-json')])
+        data = [];
+        items = self.debug_infos.values()
+        items.sort(lambda a, b: cmp(a.created, b.created))
+        data = [item.json() for item in items]
+        return [repr(data)]
+    summary.exposed = True
+
+    def view(self, environ, start_response):
+        """
+        View old exception reports
+        """
+        id = int(request.path_info_pop(environ))
+        if id not in self.debug_infos:
+            start_response(
+                '500 Server Error',
+                [('Content-type', 'text/html')])
+            return [
+                "Traceback by id %s does not exist (maybe "
+                "the server has been restarted?)"
+                % id]
+        debug_info = self.debug_infos[id]
+        return debug_info.wsgi_application(environ, start_response)
+    view.exposed = True
+
+    def make_view_url(self, environ, base_path, count):
+        return base_path + '/_debug/view/%s' % count
+
+    #@wsgiapp()
+    #@get_debug_info
+    def show_frame(self, tbid, debug_info, **kw):
+        frame = debug_info.frame(int(tbid))
+        vars = frame.tb_frame.f_locals
+        if vars:
+            registry.restorer.restoration_begin(debug_info.counter)
+            local_vars = make_table(vars)
+            registry.restorer.restoration_end()
+        else:
+            local_vars = 'No local vars'
+        return input_form(tbid, debug_info) + local_vars
+
+    show_frame = wsgiapp()(get_debug_info(show_frame))
+
+    #@wsgiapp()
+    #@get_debug_info
+    def exec_input(self, tbid, debug_info, input, **kw):
+        if not input.strip():
+            return ''
+        input = input.rstrip() + '\n'
+        frame = debug_info.frame(int(tbid))
+        vars = frame.tb_frame.f_locals
+        glob_vars = frame.tb_frame.f_globals
+        context = evalcontext.EvalContext(vars, glob_vars)
+        registry.restorer.restoration_begin(debug_info.counter)
+        output = context.exec_expr(input)
+        registry.restorer.restoration_end()
+        input_html = formatter.str2html(input)
+        return ('<code style="color: #060">&gt;&gt;&gt;</code> '
+                '<code>%s</code><br>\n%s'
+                % (preserve_whitespace(input_html, quote=False),
+                   preserve_whitespace(output)))
+
+    exec_input = wsgiapp()(get_debug_info(exec_input))
+
+    def respond(self, environ, start_response):
+        if environ.get('paste.throw_errors'):
+            return self.application(environ, start_response)
+        base_path = request.construct_url(environ, with_path_info=False,
+                                          with_query_string=False)
+        environ['paste.throw_errors'] = True
+        started = []
+        def detect_start_response(status, headers, exc_info=None):
+            try:
+                return start_response(status, headers, exc_info)
+            except:
+                raise
+            else:
+                started.append(True)
+        try:
+            __traceback_supplement__ = errormiddleware.Supplement, self, environ
+            app_iter = self.application(environ, detect_start_response)
+            try:
+                return_iter = list(app_iter)
+                return return_iter
+            finally:
+                if hasattr(app_iter, 'close'):
+                    app_iter.close()
+        except:
+            exc_info = sys.exc_info()
+            for expected in environ.get('paste.expected_exceptions', []):
+                if isinstance(exc_info[1], expected):
+                    raise
+
+            # Tell the Registry to save its StackedObjectProxies current state
+            # for later restoration
+            registry.restorer.save_registry_state(environ)
+
+            count = get_debug_count(environ)
+            view_uri = self.make_view_url(environ, base_path, count)
+            if not started:
+                headers = [('content-type', 'text/html')]
+                headers.append(('X-Debug-URL', view_uri))
+                start_response('500 Internal Server Error',
+                               headers,
+                               exc_info)
+            environ['wsgi.errors'].write('Debug at: %s\n' % view_uri)
+
+            exc_data = collector.collect_exception(*exc_info)
+            debug_info = DebugInfo(count, exc_info, exc_data, base_path,
+                                   environ, view_uri)
+            assert count not in self.debug_infos
+            self.debug_infos[count] = debug_info
+
+            if self.xmlhttp_key:
+                get_vars = wsgilib.parse_querystring(environ)
+                if dict(get_vars).get(self.xmlhttp_key):
+                    exc_data = collector.collect_exception(*exc_info)
+                    html = formatter.format_html(
+                        exc_data, include_hidden_frames=False,
+                        include_reusable=False, show_extra_data=False)
+                    return [html]
+
+            # @@: it would be nice to deal with bad content types here
+            return debug_info.content()
+
+    def exception_handler(self, exc_info, environ):
+        simple_html_error = False
+        if self.xmlhttp_key:
+            get_vars = wsgilib.parse_querystring(environ)
+            if dict(get_vars).get(self.xmlhttp_key):
+                simple_html_error = True
+        return errormiddleware.handle_exception(
+            exc_info, environ['wsgi.errors'],
+            html=True,
+            debug_mode=True,
+            simple_html_error=simple_html_error)
+
+class DebugInfo(object):
+
+    def __init__(self, counter, exc_info, exc_data, base_path,
+                 environ, view_uri):
+        self.counter = counter
+        self.exc_data = exc_data
+        self.base_path = base_path
+        self.environ = environ
+        self.view_uri = view_uri
+        self.created = time.time()
+        self.exc_type, self.exc_value, self.tb = exc_info
+        __exception_formatter__ = 1
+        self.frames = []
+        n = 0
+        tb = self.tb
+        while tb is not None and (limit is None or n < limit):
+            if tb.tb_frame.f_locals.get('__exception_formatter__'):
+                # Stop recursion. @@: should make a fake ExceptionFrame
+                break
+            self.frames.append(tb)
+            tb = tb.tb_next
+            n += 1
+
+    def json(self):
+        """Return the JSON-able representation of this object"""
+        return {
+            'uri': self.view_uri,
+            'created': time.strftime('%c', time.gmtime(self.created)),
+            'created_timestamp': self.created,
+            'exception_type': str(self.exc_type),
+            'exception': str(self.exc_value),
+            }
+
+    def frame(self, tbid):
+        for frame in self.frames:
+            if id(frame) == tbid:
+                return frame
+        else:
+            raise ValueError, (
+                "No frame by id %s found from %r" % (tbid, self.frames))
+
+    def wsgi_application(self, environ, start_response):
+        start_response('200 OK', [('content-type', 'text/html')])
+        return self.content()
+
+    def content(self):
+        html = format_eval_html(self.exc_data, self.base_path, self.counter)
+        head_html = (formatter.error_css + formatter.hide_display_js)
+        head_html += self.eval_javascript()
+        repost_button = make_repost_button(self.environ)
+        page = error_template % {
+            'repost_button': repost_button or '',
+            'head_html': head_html,
+            'body': html}
+        return [page]
+
+    def eval_javascript(self):
+        base_path = self.base_path + '/_debug'
+        return (
+            '<script type="text/javascript" src="%s/media/MochiKit.packed.js">'
+            '</script>\n'
+            '<script type="text/javascript" src="%s/media/debug.js">'
+            '</script>\n'
+            '<script type="text/javascript">\n'
+            'debug_base = %r;\n'
+            'debug_count = %r;\n'
+            '</script>\n'
+            % (base_path, base_path, base_path, self.counter))
+
+class EvalHTMLFormatter(formatter.HTMLFormatter):
+
+    def __init__(self, base_path, counter, **kw):
+        super(EvalHTMLFormatter, self).__init__(**kw)
+        self.base_path = base_path
+        self.counter = counter
+
+    def format_source_line(self, filename, frame):
+        line = formatter.HTMLFormatter.format_source_line(
+            self, filename, frame)
+        return (line +
+                '  <a href="#" class="switch_source" '
+                'tbid="%s" onClick="return showFrame(this)">&nbsp; &nbsp; '
+                '<img src="%s/_debug/media/plus.jpg" border=0 width=9 '
+                'height=9> &nbsp; &nbsp;</a>'
+                % (frame.tbid, self.base_path))
+
+def make_table(items):
+    if isinstance(items, dict):
+        items = items.items()
+        items.sort()
+    rows = []
+    i = 0
+    for name, value in items:
+        i += 1
+        out = StringIO()
+        try:
+            pprint.pprint(value, out)
+        except Exception, e:
+            print >> out, 'Error: %s' % e
+        value = html_quote(out.getvalue())
+        if len(value) > 100:
+            # @@: This can actually break the HTML :(
+            # should I truncate before quoting?
+            orig_value = value
+            value = value[:100]
+            value += '<a class="switch_source" style="background-color: #999" href="#" onclick="return expandLong(this)">...</a>'
+            value += '<span style="display: none">%s</span>' % orig_value[100:]
+        value = formatter.make_wrappable(value)
+        if i % 2:
+            attr = ' class="even"'
+        else:
+            attr = ' class="odd"'
+        rows.append('<tr%s style="vertical-align: top;"><td>'
+                    '<b>%s</b></td><td style="overflow: auto">%s<td></tr>'
+                    % (attr, html_quote(name),
+                       preserve_whitespace(value, quote=False)))
+    return '<table>%s</table>' % (
+        '\n'.join(rows))
+
+def format_eval_html(exc_data, base_path, counter):
+    short_formatter = EvalHTMLFormatter(
+        base_path=base_path,
+        counter=counter,
+        include_reusable=False)
+    short_er = short_formatter.format_collected_data(exc_data)
+    long_formatter = EvalHTMLFormatter(
+        base_path=base_path,
+        counter=counter,
+        show_hidden_frames=True,
+        show_extra_data=False,
+        include_reusable=False)
+    long_er = long_formatter.format_collected_data(exc_data)
+    text_er = formatter.format_text(exc_data, show_hidden_frames=True)
+    if short_formatter.filter_frames(exc_data.frames) != \
+        long_formatter.filter_frames(exc_data.frames):
+        # Only display the full traceback when it differs from the
+        # short version
+        full_traceback_html = """
+    <br>
+    <script type="text/javascript">
+    show_button('full_traceback', 'full traceback')
+    </script>
+    <div id="full_traceback" class="hidden-data">
+    %s
+    </div>
+        """ % long_er
+    else:
+        full_traceback_html = ''
+
+    return """
+    %s
+    %s
+    <br>
+    <script type="text/javascript">
+    show_button('text_version', 'text version')
+    </script>
+    <div id="text_version" class="hidden-data">
+    <textarea style="width: 100%%" rows=10 cols=60>%s</textarea>
+    </div>
+    """ % (short_er, full_traceback_html, cgi.escape(text_er))
+
+def make_repost_button(environ):
+    url = request.construct_url(environ)
+    if environ['REQUEST_METHOD'] == 'GET':
+        return ('<button onclick="window.location.href=%r">'
+                'Re-GET Page</button><br>' % url)
+    else:
+        # @@: I'd like to reconstruct this, but I can't because
+        # the POST body is probably lost at this point, and
+        # I can't get it back :(
+        return None
+    # @@: Use or lose the following code block
+    """
+    fields = []
+    for name, value in wsgilib.parse_formvars(
+        environ, include_get_vars=False).items():
+        if hasattr(value, 'filename'):
+            # @@: Arg, we'll just submit the body, and leave out
+            # the filename :(
+            value = value.value
+        fields.append(
+            '<input type="hidden" name="%s" value="%s">'
+            % (html_quote(name), html_quote(value)))
+    return '''
+<form action="%s" method="POST">
+%s
+<input type="submit" value="Re-POST Page">
+</form>''' % (url, '\n'.join(fields))
+"""
+
+
+def input_form(tbid, debug_info):
+    return '''
+<form action="#" method="POST"
+ onsubmit="return submitInput($(\'submit_%(tbid)s\'), %(tbid)s)">
+<div id="exec-output-%(tbid)s" style="width: 95%%;
+ padding: 5px; margin: 5px; border: 2px solid #000;
+ display: none"></div>
+<input type="text" name="input" id="debug_input_%(tbid)s"
+ style="width: 100%%"
+ autocomplete="off" onkeypress="upArrow(this, event)"><br>
+<input type="submit" value="Execute" name="submitbutton"
+ onclick="return submitInput(this, %(tbid)s)"
+ id="submit_%(tbid)s"
+ input-from="debug_input_%(tbid)s"
+ output-to="exec-output-%(tbid)s">
+<input type="submit" value="Expand"
+ onclick="return expandInput(this)">
+</form>
+ ''' % {'tbid': tbid}
+
+error_template = '''
+<html>
+<head>
+ <title>Server Error</title>
+ %(head_html)s
+</head>
+<body>
+
+<div id="error-area" style="display: none; background-color: #600; color: #fff; border: 2px solid black">
+<div id="error-container"></div>
+<button onclick="return clearError()">clear this</button>
+</div>
+
+%(repost_button)s
+
+%(body)s
+
+</body>
+</html>
+'''
+
+def make_eval_exception(app, global_conf, xmlhttp_key=None):
+    """
+    Wraps the application in an interactive debugger.
+
+    This debugger is a major security hole, and should only be
+    used during development.
+
+    xmlhttp_key is a string that, if present in QUERY_STRING,
+    indicates that the request is an XMLHttp request, and the
+    Javascript/interactive debugger should not be returned.  (If you
+    try to put the debugger somewhere with innerHTML, you will often
+    crash the browser)
+    """
+    if xmlhttp_key is None:
+        xmlhttp_key = global_conf.get('xmlhttp_key', '_')
+    return EvalException(app, xmlhttp_key=xmlhttp_key)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Package for catching exceptions and displaying annotated exception
+reports
+"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/collector.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/collector.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/collector.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,526 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+##############################################################################
+#
+# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (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.
+#
+##############################################################################
+## Originally zExceptions.ExceptionFormatter from Zope;
+## Modified by Ian Bicking, Imaginary Landscape, 2005
+"""
+An exception collector that finds traceback information plus
+supplements
+"""
+
+import sys
+import traceback
+import time
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+import linecache
+from paste.exceptions import serial_number_generator
+import warnings
+
+DEBUG_EXCEPTION_FORMATTER = True
+DEBUG_IDENT_PREFIX = 'E-'
+FALLBACK_ENCODING = 'UTF-8'
+
+__all__ = ['collect_exception', 'ExceptionCollector']
+
+class ExceptionCollector(object):
+
+    """
+    Produces a data structure that can be used by formatters to
+    display exception reports.
+
+    Magic variables:
+
+    If you define one of these variables in your local scope, you can
+    add information to tracebacks that happen in that context.  This
+    allows applications to add all sorts of extra information about
+    the context of the error, including URLs, environmental variables,
+    users, hostnames, etc.  These are the variables we look for:
+
+    ``__traceback_supplement__``:
+        You can define this locally or globally (unlike all the other
+        variables, which must be defined locally).
+
+        ``__traceback_supplement__`` is a tuple of ``(factory, arg1,
+        arg2...)``.  When there is an exception, ``factory(arg1, arg2,
+        ...)`` is called, and the resulting object is inspected for
+        supplemental information.
+
+    ``__traceback_info__``:
+        This information is added to the traceback, usually fairly
+        literally.
+
+    ``__traceback_hide__``:
+        If set and true, this indicates that the frame should be
+        hidden from abbreviated tracebacks.  This way you can hide
+        some of the complexity of the larger framework and let the
+        user focus on their own errors.
+
+        By setting it to ``'before'``, all frames before this one will
+        be thrown away.  By setting it to ``'after'`` then all frames
+        after this will be thrown away until ``'reset'`` is found.  In
+        each case the frame where it is set is included, unless you
+        append ``'_and_this'`` to the value (e.g.,
+        ``'before_and_this'``).
+
+        Note that formatters will ignore this entirely if the frame
+        that contains the error wouldn't normally be shown according
+        to these rules.
+
+    ``__traceback_reporter__``:
+        This should be a reporter object (see the reporter module),
+        or a list/tuple of reporter objects.  All reporters found this
+        way will be given the exception, innermost first.
+
+    ``__traceback_decorator__``:
+        This object (defined in a local or global scope) will get the
+        result of this function (the CollectedException defined
+        below).  It may modify this object in place, or return an
+        entirely new object.  This gives the object the ability to
+        manipulate the traceback arbitrarily.
+
+    The actually interpretation of these values is largely up to the
+    reporters and formatters.
+    
+    ``collect_exception(*sys.exc_info())`` will return an object with
+    several attributes:
+
+    ``frames``:
+        A list of frames
+    ``exception_formatted``:
+        The formatted exception, generally a full traceback
+    ``exception_type``:
+        The type of the exception, like ``ValueError``
+    ``exception_value``:
+        The string value of the exception, like ``'x not in list'``
+    ``identification_code``:
+        A hash of the exception data meant to identify the general
+        exception, so that it shares this code with other exceptions
+        that derive from the same problem.  The code is a hash of
+        all the module names and function names in the traceback,
+        plus exception_type.  This should be shown to users so they
+        can refer to the exception later. (@@: should it include a
+        portion that allows identification of the specific instance
+        of the exception as well?)
+        
+    The list of frames goes innermost first.  Each frame has these
+    attributes; some values may be None if they could not be
+    determined.
+
+    ``modname``:
+        the name of the module
+    ``filename``:
+        the filename of the module
+    ``lineno``:
+        the line of the error
+    ``revision``:
+        the contents of __version__ or __revision__
+    ``name``:
+        the function name
+    ``supplement``:
+        an object created from ``__traceback_supplement__``
+    ``supplement_exception``:
+        a simple traceback of any exception ``__traceback_supplement__``
+        created
+    ``traceback_info``:
+        the str() of any ``__traceback_info__`` variable found in the local
+        scope (@@: should it str()-ify it or not?)
+    ``traceback_hide``:
+        the value of any ``__traceback_hide__`` variable
+    ``traceback_log``:
+        the value of any ``__traceback_log__`` variable
+    
+
+    ``__traceback_supplement__`` is thrown away, but a fixed
+    set of attributes are captured; each of these attributes is
+    optional.
+
+    ``object``:
+        the name of the object being visited
+    ``source_url``:
+        the original URL requested
+    ``line``:
+        the line of source being executed (for interpreters, like ZPT)
+    ``column``:
+        the column of source being executed
+    ``expression``:
+        the expression being evaluated (also for interpreters)
+    ``warnings``:
+        a list of (string) warnings to be displayed
+    ``getInfo``:
+        a function/method that takes no arguments, and returns a string
+        describing any extra information
+    ``extraData``:
+        a function/method that takes no arguments, and returns a
+        dictionary.  The contents of this dictionary will not be
+        displayed in the context of the traceback, but globally for
+        the exception.  Results will be grouped by the keys in the
+        dictionaries (which also serve as titles).  The keys can also
+        be tuples of (importance, title); in this case the importance
+        should be ``important`` (shows up at top), ``normal`` (shows
+        up somewhere; unspecified), ``supplemental`` (shows up at
+        bottom), or ``extra`` (shows up hidden or not at all).
+
+    These are used to create an object with attributes of the same
+    names (``getInfo`` becomes a string attribute, not a method).
+    ``__traceback_supplement__`` implementations should be careful to
+    produce values that are relatively static and unlikely to cause
+    further errors in the reporting system -- any complex
+    introspection should go in ``getInfo()`` and should ultimately
+    return a string.
+
+    Note that all attributes are optional, and under certain
+    circumstances may be None or may not exist at all -- the collector
+    can only do a best effort, but must avoid creating any exceptions
+    itself.
+
+    Formatters may want to use ``__traceback_hide__`` as a hint to
+    hide frames that are part of the 'framework' or underlying system.
+    There are a variety of rules about special values for this
+    variables that formatters should be aware of.
+    
+    TODO:
+
+    More attributes in __traceback_supplement__?  Maybe an attribute
+    that gives a list of local variables that should also be
+    collected?  Also, attributes that would be explicitly meant for
+    the entire request, not just a single frame.  Right now some of
+    the fixed set of attributes (e.g., source_url) are meant for this
+    use, but there's no explicit way for the supplement to indicate
+    new values, e.g., logged-in user, HTTP referrer, environment, etc.
+    Also, the attributes that do exist are Zope/Web oriented.
+
+    More information on frames?  cgitb, for instance, produces
+    extensive information on local variables.  There exists the
+    possibility that getting this information may cause side effects,
+    which can make debugging more difficult; but it also provides
+    fodder for post-mortem debugging.  However, the collector is not
+    meant to be configurable, but to capture everything it can and let
+    the formatters be configurable.  Maybe this would have to be a
+    configuration value, or maybe it could be indicated by another
+    magical variable (which would probably mean 'show all local
+    variables below this frame')
+    """
+
+    show_revisions = 0
+
+    def __init__(self, limit=None):
+        self.limit = limit
+
+    def getLimit(self):
+        limit = self.limit
+        if limit is None:
+            limit = getattr(sys, 'tracebacklimit', None)
+        return limit
+
+    def getRevision(self, globals):
+        if not self.show_revisions:
+            return None
+        revision = globals.get('__revision__', None)
+        if revision is None:
+            # Incorrect but commonly used spelling
+            revision = globals.get('__version__', None)
+
+        if revision is not None:
+            try:
+                revision = str(revision).strip()
+            except:
+                revision = '???'
+        return revision
+
+    def collectSupplement(self, supplement, tb):
+        result = {}
+
+        for name in ('object', 'source_url', 'line', 'column',
+                     'expression', 'warnings'):
+            result[name] = getattr(supplement, name, None)
+
+        func = getattr(supplement, 'getInfo', None)
+        if func:
+            result['info'] = func()
+        else:
+            result['info'] = None
+        func = getattr(supplement, 'extraData', None)
+        if func:
+            result['extra'] = func()
+        else:
+            result['extra'] = None
+        return SupplementaryData(**result)
+
+    def collectLine(self, tb, extra_data):
+        f = tb.tb_frame
+        lineno = tb.tb_lineno
+        co = f.f_code
+        filename = co.co_filename
+        name = co.co_name
+        globals = f.f_globals
+        locals = f.f_locals
+        if not hasattr(locals, 'has_key'):
+            # Something weird about this frame; it's not a real dict
+            warnings.warn(
+                "Frame %s has an invalid locals(): %r" % (
+                globals.get('__name__', 'unknown'), locals))
+            locals = {}
+        data = {}
+        data['modname'] = globals.get('__name__', None)
+        data['filename'] = filename
+        data['lineno'] = lineno
+        data['revision'] = self.getRevision(globals)
+        data['name'] = name
+        data['tbid'] = id(tb)
+
+        # Output a traceback supplement, if any.
+        if locals.has_key('__traceback_supplement__'):
+            # Use the supplement defined in the function.
+            tbs = locals['__traceback_supplement__']
+        elif globals.has_key('__traceback_supplement__'):
+            # Use the supplement defined in the module.
+            # This is used by Scripts (Python).
+            tbs = globals['__traceback_supplement__']
+        else:
+            tbs = None
+        if tbs is not None:
+            factory = tbs[0]
+            args = tbs[1:]
+            try:
+                supp = factory(*args)
+                data['supplement'] = self.collectSupplement(supp, tb)
+                if data['supplement'].extra:
+                    for key, value in data['supplement'].extra.items():
+                        extra_data.setdefault(key, []).append(value)
+            except:
+                if DEBUG_EXCEPTION_FORMATTER:
+                    out = StringIO()
+                    traceback.print_exc(file=out)
+                    text = out.getvalue()
+                    data['supplement_exception'] = text
+                # else just swallow the exception.
+
+        try:
+            tbi = locals.get('__traceback_info__', None)
+            if tbi is not None:
+                data['traceback_info'] = str(tbi)
+        except:
+            pass
+
+        marker = []
+        for name in ('__traceback_hide__', '__traceback_log__',
+                     '__traceback_decorator__'):
+            try:
+                tbh = locals.get(name, globals.get(name, marker))
+                if tbh is not marker:
+                    data[name[2:-2]] = tbh
+            except:
+                pass
+
+        return data
+
+    def collectExceptionOnly(self, etype, value):
+        return traceback.format_exception_only(etype, value)
+
+    def collectException(self, etype, value, tb, limit=None):
+        # The next line provides a way to detect recursion.
+        __exception_formatter__ = 1
+        frames = []
+        ident_data = []
+        traceback_decorators = []
+        if limit is None:
+            limit = self.getLimit()
+        n = 0
+        extra_data = {}
+        while tb is not None and (limit is None or n < limit):
+            if tb.tb_frame.f_locals.get('__exception_formatter__'):
+                # Stop recursion. @@: should make a fake ExceptionFrame
+                frames.append('(Recursive formatException() stopped)\n')
+                break
+            data = self.collectLine(tb, extra_data)
+            frame = ExceptionFrame(**data)
+            frames.append(frame)
+            if frame.traceback_decorator is not None:
+                traceback_decorators.append(frame.traceback_decorator)
+            ident_data.append(frame.modname or '?')
+            ident_data.append(frame.name or '?')
+            tb = tb.tb_next
+            n = n + 1
+        ident_data.append(str(etype))
+        ident = serial_number_generator.hash_identifier(
+            ' '.join(ident_data), length=5, upper=True,
+            prefix=DEBUG_IDENT_PREFIX)
+
+        result = CollectedException(
+            frames=frames,
+            exception_formatted=self.collectExceptionOnly(etype, value),
+            exception_type=etype,
+            exception_value=self.safeStr(value),
+            identification_code=ident,
+            date=time.localtime(),
+            extra_data=extra_data)
+        if etype is ImportError:
+            extra_data[('important', 'sys.path')] = [sys.path]
+        for decorator in traceback_decorators:
+            try:
+                new_result = decorator(result)
+                if new_result is not None:
+                    result = new_result
+            except:
+                pass
+        return result
+
+    def safeStr(self, obj):
+        try:
+            return str(obj)
+        except UnicodeEncodeError:
+            try:
+                return unicode(obj).encode(FALLBACK_ENCODING, 'replace')
+            except UnicodeEncodeError:
+                # This is when something is really messed up, but this can
+                # happen when the __str__ of an object has to handle unicode
+                return repr(obj)
+
+limit = 200
+
+class Bunch(object):
+
+    """
+    A generic container
+    """
+
+    def __init__(self, **attrs):
+        for name, value in attrs.items():
+            setattr(self, name, value)
+
+    def __repr__(self):
+        name = '<%s ' % self.__class__.__name__
+        name += ' '.join(['%s=%r' % (name, str(value)[:30])
+                          for name, value in self.__dict__.items()
+                          if not name.startswith('_')])
+        return name + '>'
+
+class CollectedException(Bunch):
+    """
+    This is the result of collection the exception; it contains copies
+    of data of interest.
+    """
+    # A list of frames (ExceptionFrame instances), innermost last:
+    frames = []
+    # The result of traceback.format_exception_only; this looks
+    # like a normal traceback you'd see in the interactive interpreter
+    exception_formatted = None
+    # The *string* representation of the type of the exception
+    # (@@: should we give the # actual class? -- we can't keep the
+    # actual exception around, but the class should be safe)
+    # Something like 'ValueError'
+    exception_type = None
+    # The string representation of the exception, from ``str(e)``.
+    exception_value = None
+    # An identifier which should more-or-less classify this particular
+    # exception, including where in the code it happened.
+    identification_code = None
+    # The date, as time.localtime() returns:
+    date = None
+    # A dictionary of supplemental data:
+    extra_data = {}
+
+class SupplementaryData(Bunch):
+    """
+    The result of __traceback_supplement__.  We don't keep the
+    supplement object around, for fear of GC problems and whatnot.
+    (@@: Maybe I'm being too superstitious about copying only specific
+    information over)
+    """
+
+    # These attributes are copied from the object, or left as None
+    # if the object doesn't have these attributes:
+    object = None
+    source_url = None
+    line = None
+    column = None
+    expression = None
+    warnings = None
+    # This is the *return value* of supplement.getInfo():
+    info = None
+
+class ExceptionFrame(Bunch):
+    """
+    This represents one frame of the exception.  Each frame is a
+    context in the call stack, typically represented by a line
+    number and module name in the traceback.
+    """
+
+    # The name of the module; can be None, especially when the code
+    # isn't associated with a module.
+    modname = None
+    # The filename (@@: when no filename, is it None or '?'?)
+    filename = None
+    # Line number
+    lineno = None
+    # The value of __revision__ or __version__ -- but only if
+    # show_revision = True (by defaut it is false).  (@@: Why not
+    # collect this?)
+    revision = None
+    # The name of the function with the error (@@: None or '?' when
+    # unknown?)
+    name = None
+    # A SupplementaryData object, if __traceback_supplement__ was found
+    # (and produced no errors)
+    supplement = None
+    # If accessing __traceback_supplement__ causes any error, the
+    # plain-text traceback is stored here
+    supplement_exception = None
+    # The str() of any __traceback_info__ value found
+    traceback_info = None
+    # The value of __traceback_hide__
+    traceback_hide = False
+    # The value of __traceback_decorator__
+    traceback_decorator = None
+    # The id() of the traceback scope, can be used to reference the
+    # scope for use elsewhere
+    tbid = None
+
+    def get_source_line(self, context=0):
+        """
+        Return the source of the current line of this frame.  You
+        probably want to .strip() it as well, as it is likely to have
+        leading whitespace.
+
+        If context is given, then that many lines on either side will
+        also be returned.  E.g., context=1 will give 3 lines.
+        """
+        if not self.filename or not self.lineno:
+            return None
+        lines = []
+        for lineno in range(self.lineno-context, self.lineno+context+1):
+            lines.append(linecache.getline(self.filename, lineno))
+        return ''.join(lines)
+        
+if hasattr(sys, 'tracebacklimit'):
+    limit = min(limit, sys.tracebacklimit)
+
+col = ExceptionCollector()
+
+def collect_exception(t, v, tb, limit=None):
+    """
+    Collection an exception from ``sys.exc_info()``.
+    
+    Use like::
+
+      try:
+          blah blah
+      except:
+          exc_data = collect_exception(*sys.exc_info())
+    """
+    return col.collectException(t, v, tb, limit=limit)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/errormiddleware.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/errormiddleware.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/errormiddleware.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,460 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Error handler middleware
+"""
+import sys
+import traceback
+import cgi
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+from paste.exceptions import formatter, collector, reporter
+from paste import wsgilib
+from paste import request
+
+__all__ = ['ErrorMiddleware', 'handle_exception']
+
+class _NoDefault(object):
+    def __repr__(self):
+        return '<NoDefault>'
+NoDefault = _NoDefault()
+
+class ErrorMiddleware(object):
+
+    """
+    Error handling middleware
+    
+    Usage::
+
+        error_catching_wsgi_app = ErrorMiddleware(wsgi_app)
+
+    Settings:
+
+      ``debug``:
+          If true, then tracebacks will be shown in the browser.
+
+      ``error_email``:
+          an email address (or list of addresses) to send exception 
+          reports to
+
+      ``error_log``:
+          a filename to append tracebacks to
+
+      ``show_exceptions_in_wsgi_errors``:
+          If true, then errors will be printed to ``wsgi.errors`` 
+          (frequently a server error log, or stderr).
+
+      ``from_address``, ``smtp_server``, ``error_subject_prefix``, ``smtp_username``, ``smtp_password``, ``smtp_use_tls``:
+          variables to control the emailed exception reports
+
+      ``error_message``:
+          When debug mode is off, the error message to show to users.
+
+      ``xmlhttp_key``:
+          When this key (default ``_``) is in the request GET variables
+          (not POST!), expect that this is an XMLHttpRequest, and the
+          response should be more minimal; it should not be a complete
+          HTML page.
+
+    Environment Configuration:
+    
+      ``paste.throw_errors``:
+          If this setting in the request environment is true, then this
+          middleware is disabled. This can be useful in a testing situation
+          where you don't want errors to be caught and transformed.
+
+      ``paste.expected_exceptions``:
+          When this middleware encounters an exception listed in this
+          environment variable and when the ``start_response`` has not 
+          yet occurred, the exception will be re-raised instead of being
+          caught.  This should generally be set by middleware that may 
+          (but probably shouldn't be) installed above this middleware, 
+          and wants to get certain exceptions.  Exceptions raised after
+          ``start_response`` have been called are always caught since
+          by definition they are no longer expected.
+
+    """
+
+    def __init__(self, application, global_conf=None,
+                 debug=NoDefault,
+                 error_email=None,
+                 error_log=None,
+                 show_exceptions_in_wsgi_errors=NoDefault,
+                 from_address=None,
+                 smtp_server=None,
+                 smtp_username=None,
+                 smtp_password=None,
+                 smtp_use_tls=False,
+                 error_subject_prefix=None,
+                 error_message=None,
+                 xmlhttp_key=None):
+        from paste.util import converters
+        self.application = application
+        # @@: global_conf should be handled elsewhere in a separate
+        # function for the entry point
+        if global_conf is None:
+            global_conf = {}
+        if debug is NoDefault:
+            debug = converters.asbool(global_conf.get('debug'))
+        if show_exceptions_in_wsgi_errors is NoDefault:
+            show_exceptions_in_wsgi_errors = converters.asbool(global_conf.get('show_exceptions_in_wsgi_errors'))
+        self.debug_mode = converters.asbool(debug)
+        if error_email is None:
+            error_email = (global_conf.get('error_email')
+                           or global_conf.get('admin_email')
+                           or global_conf.get('webmaster_email')
+                           or global_conf.get('sysadmin_email'))
+        self.error_email = converters.aslist(error_email)
+        self.error_log = error_log
+        self.show_exceptions_in_wsgi_errors = show_exceptions_in_wsgi_errors
+        if from_address is None:
+            from_address = global_conf.get('error_from_address', 'errors at localhost')
+        self.from_address = from_address
+        if smtp_server is None:
+            smtp_server = global_conf.get('smtp_server', 'localhost')
+        self.smtp_server = smtp_server
+        self.smtp_username = smtp_username or global_conf.get('smtp_username')
+        self.smtp_password = smtp_password or global_conf.get('smtp_password')
+        self.smtp_use_tls = smtp_use_tls or converters.asbool(global_conf.get('smtp_use_tls'))
+        self.error_subject_prefix = error_subject_prefix or ''
+        if error_message is None:
+            error_message = global_conf.get('error_message')
+        self.error_message = error_message
+        if xmlhttp_key is None:
+            xmlhttp_key = global_conf.get('xmlhttp_key', '_')
+        self.xmlhttp_key = xmlhttp_key
+            
+    def __call__(self, environ, start_response):
+        """
+        The WSGI application interface.
+        """
+        # We want to be careful about not sending headers twice,
+        # and the content type that the app has committed to (if there
+        # is an exception in the iterator body of the response)
+        if environ.get('paste.throw_errors'):
+            return self.application(environ, start_response)
+        environ['paste.throw_errors'] = True
+
+        try:
+            __traceback_supplement__ = Supplement, self, environ
+            sr_checker = ResponseStartChecker(start_response)
+            app_iter = self.application(environ, sr_checker)
+            return self.make_catching_iter(app_iter, environ, sr_checker)
+        except:
+            exc_info = sys.exc_info()
+            try:
+                for expect in environ.get('paste.expected_exceptions', []):
+                    if isinstance(exc_info[1], expect):
+                        raise
+                start_response('500 Internal Server Error',
+                               [('content-type', 'text/html')],
+                               exc_info)
+                # @@: it would be nice to deal with bad content types here
+                response = self.exception_handler(exc_info, environ)
+                return [response]
+            finally:
+                # clean up locals...
+                exc_info = None
+
+    def make_catching_iter(self, app_iter, environ, sr_checker):
+        if isinstance(app_iter, (list, tuple)):
+            # These don't raise
+            return app_iter
+        return CatchingIter(app_iter, environ, sr_checker, self)
+
+    def exception_handler(self, exc_info, environ):
+        simple_html_error = False
+        if self.xmlhttp_key:
+            get_vars = wsgilib.parse_querystring(environ)
+            if dict(get_vars).get(self.xmlhttp_key):
+                simple_html_error = True
+        return handle_exception(
+            exc_info, environ['wsgi.errors'],
+            html=True,
+            debug_mode=self.debug_mode,
+            error_email=self.error_email,
+            error_log=self.error_log,
+            show_exceptions_in_wsgi_errors=self.show_exceptions_in_wsgi_errors,
+            error_email_from=self.from_address,
+            smtp_server=self.smtp_server,
+            smtp_username=self.smtp_username,
+            smtp_password=self.smtp_password,
+            smtp_use_tls=self.smtp_use_tls,
+            error_subject_prefix=self.error_subject_prefix,
+            error_message=self.error_message,
+            simple_html_error=simple_html_error)
+
+class ResponseStartChecker(object):
+    def __init__(self, start_response):
+        self.start_response = start_response
+        self.response_started = False
+
+    def __call__(self, *args):
+        self.response_started = True
+        self.start_response(*args)
+
+class CatchingIter(object):
+
+    """
+    A wrapper around the application iterator that will catch
+    exceptions raised by the a generator, or by the close method, and
+    display or report as necessary.
+    """
+
+    def __init__(self, app_iter, environ, start_checker, error_middleware):
+        self.app_iterable = app_iter
+        self.app_iterator = iter(app_iter)
+        self.environ = environ
+        self.start_checker = start_checker
+        self.error_middleware = error_middleware
+        self.closed = False
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        __traceback_supplement__ = (
+            Supplement, self.error_middleware, self.environ)
+        if self.closed:
+            raise StopIteration
+        try:
+            return self.app_iterator.next()
+        except StopIteration:
+            self.closed = True
+            close_response = self._close()
+            if close_response is not None:
+                return close_response
+            else:
+                raise StopIteration
+        except:
+            self.closed = True
+            close_response = self._close()
+            exc_info = sys.exc_info()
+            response = self.error_middleware.exception_handler(
+                exc_info, self.environ)
+            if close_response is not None:
+                response += (
+                    '<hr noshade>Error in .close():<br>%s'
+                    % close_response)
+
+            if not self.start_checker.response_started:
+                self.start_checker('500 Internal Server Error',
+                               [('content-type', 'text/html')],
+                               exc_info)
+
+            return response
+
+    def close(self):
+        # This should at least print something to stderr if the
+        # close method fails at this point
+        if not self.closed:
+            self._close()
+
+    def _close(self):
+        """Close and return any error message"""
+        if not hasattr(self.app_iterable, 'close'):
+            return None
+        try:
+            self.app_iterable.close()
+            return None
+        except:
+            close_response = self.error_middleware.exception_handler(
+                sys.exc_info(), self.environ)
+            return close_response
+
+
+class Supplement(object):
+
+    """
+    This is a supplement used to display standard WSGI information in
+    the traceback.
+    """
+
+    def __init__(self, middleware, environ):
+        self.middleware = middleware
+        self.environ = environ
+        self.source_url = request.construct_url(environ)
+
+    def extraData(self):
+        data = {}
+        cgi_vars = data[('extra', 'CGI Variables')] = {}
+        wsgi_vars = data[('extra', 'WSGI Variables')] = {}
+        hide_vars = ['paste.config', 'wsgi.errors', 'wsgi.input',
+                     'wsgi.multithread', 'wsgi.multiprocess',
+                     'wsgi.run_once', 'wsgi.version',
+                     'wsgi.url_scheme']
+        for name, value in self.environ.items():
+            if name.upper() == name:
+                if value:
+                    cgi_vars[name] = value
+            elif name not in hide_vars:
+                wsgi_vars[name] = value
+        if self.environ['wsgi.version'] != (1, 0):
+            wsgi_vars['wsgi.version'] = self.environ['wsgi.version']
+        proc_desc = tuple([int(bool(self.environ[key]))
+                           for key in ('wsgi.multiprocess',
+                                       'wsgi.multithread',
+                                       'wsgi.run_once')])
+        wsgi_vars['wsgi process'] = self.process_combos[proc_desc]
+        wsgi_vars['application'] = self.middleware.application
+        if 'paste.config' in self.environ:
+            data[('extra', 'Configuration')] = dict(self.environ['paste.config'])
+        return data
+
+    process_combos = {
+        # multiprocess, multithread, run_once
+        (0, 0, 0): 'Non-concurrent server',
+        (0, 1, 0): 'Multithreaded',
+        (1, 0, 0): 'Multiprocess',
+        (1, 1, 0): 'Multi process AND threads (?)',
+        (0, 0, 1): 'Non-concurrent CGI',
+        (0, 1, 1): 'Multithread CGI (?)',
+        (1, 0, 1): 'CGI',
+        (1, 1, 1): 'Multi thread/process CGI (?)',
+        }
+    
+def handle_exception(exc_info, error_stream, html=True,
+                     debug_mode=False,
+                     error_email=None,
+                     error_log=None,
+                     show_exceptions_in_wsgi_errors=False,
+                     error_email_from='errors at localhost',
+                     smtp_server='localhost',
+                     smtp_username=None, 
+                     smtp_password=None, 
+                     smtp_use_tls=False,
+                     error_subject_prefix='',
+                     error_message=None,
+                     simple_html_error=False,
+                     ):
+    """
+    For exception handling outside of a web context
+
+    Use like::
+
+        import sys
+        from paste.exceptions.errormiddleware import handle_exception
+        try:
+            do stuff
+        except:
+            handle_exception(
+                sys.exc_info(), sys.stderr, html=False, ...other config...)
+
+    If you want to report, but not fully catch the exception, call
+    ``raise`` after ``handle_exception``, which (when given no argument)
+    will reraise the exception.
+    """
+    reported = False
+    exc_data = collector.collect_exception(*exc_info)
+    extra_data = ''
+    if error_email:
+        rep = reporter.EmailReporter(
+            to_addresses=error_email,
+            from_address=error_email_from,
+            smtp_server=smtp_server,
+            smtp_username=smtp_username,
+            smtp_password=smtp_password,
+            smtp_use_tls=smtp_use_tls,
+            subject_prefix=error_subject_prefix)
+        rep_err = send_report(rep, exc_data, html=html)
+        if rep_err:
+            extra_data += rep_err
+        else:
+            reported = True
+    if error_log:
+        rep = reporter.LogReporter(
+            filename=error_log)
+        rep_err = send_report(rep, exc_data, html=html)
+        if rep_err:
+            extra_data += rep_err
+        else:
+            reported = True
+    if show_exceptions_in_wsgi_errors:
+        rep = reporter.FileReporter(
+            file=error_stream)
+        rep_err = send_report(rep, exc_data, html=html)
+        if rep_err:
+            extra_data += rep_err
+        else:
+            reported = True
+    else:
+        error_stream.write('Error - %s: %s\n' % (
+            exc_data.exception_type, exc_data.exception_value))
+    if html:
+        if debug_mode and simple_html_error:
+            return_error = formatter.format_html(
+                exc_data, include_hidden_frames=False,
+                include_reusable=False, show_extra_data=False)
+            reported = True
+        elif debug_mode and not simple_html_error:
+            error_html = formatter.format_html(
+                exc_data,
+                include_hidden_frames=True,
+                include_reusable=False)
+            head_html = formatter.error_css + formatter.hide_display_js
+            return_error = error_template(
+                head_html, error_html, extra_data)
+            extra_data = ''
+            reported = True
+        else:
+            msg = error_message or '''
+            An error occurred.  See the error logs for more information.
+            (Turn debug on to display exception reports here)
+            '''
+            return_error = error_template('', msg, '')
+    else:
+        return_error = None
+    if not reported and error_stream:
+        err_report = formatter.format_text(exc_data, show_hidden_frames=True)
+        err_report += '\n' + '-'*60 + '\n'
+        error_stream.write(err_report)
+    if extra_data:
+        error_stream.write(extra_data)
+    return return_error
+
+def send_report(rep, exc_data, html=True):
+    try:
+        rep.report(exc_data)
+    except:
+        output = StringIO()
+        traceback.print_exc(file=output)
+        if html:
+            return """
+            <p>Additionally an error occurred while sending the %s report:
+
+            <pre>%s</pre>
+            </p>""" % (
+                cgi.escape(str(rep)), output.getvalue())
+        else:
+            return (
+                "Additionally an error occurred while sending the "
+                "%s report:\n%s" % (str(rep), output.getvalue()))
+    else:
+        return ''
+
+def error_template(head_html, exception, extra):
+    return '''
+    <html>
+    <head>
+    <title>Server Error</title>
+    %s
+    </head>
+    <body>
+    <h1>Server Error</h1>
+    %s
+    %s
+    </body>
+    </html>''' % (head_html, exception, extra)
+
+def make_error_middleware(app, global_conf, **kw):
+    return ErrorMiddleware(app, global_conf=global_conf, **kw)
+
+doc_lines = ErrorMiddleware.__doc__.splitlines(True)
+for i in range(len(doc_lines)):
+    if doc_lines[i].strip().startswith('Settings'):
+        make_error_middleware.__doc__ = ''.join(doc_lines[i:])
+        break
+del i, doc_lines

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/formatter.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/formatter.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/formatter.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,564 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Formatters for the exception data that comes from ExceptionCollector.
+"""
+# @@: TODO:
+# Use this: http://www.zope.org/Members/tino/VisualTraceback/VisualTracebackNews
+
+import cgi
+import re
+from paste.util import PySourceColor
+
+def html_quote(s):
+    return cgi.escape(str(s), True)
+
+class AbstractFormatter(object):
+
+    general_data_order = ['object', 'source_url']
+
+    def __init__(self, show_hidden_frames=False,
+                 include_reusable=True,
+                 show_extra_data=True,
+                 trim_source_paths=()):
+        self.show_hidden_frames = show_hidden_frames
+        self.trim_source_paths = trim_source_paths
+        self.include_reusable = include_reusable
+        self.show_extra_data = show_extra_data
+
+    def format_collected_data(self, exc_data):
+        general_data = {}
+        if self.show_extra_data:
+            for name, value_list in exc_data.extra_data.items():
+                if isinstance(name, tuple):
+                    importance, title = name
+                else:
+                    importance, title = 'normal', name
+                for value in value_list:
+                    general_data[(importance, name)] = self.format_extra_data(
+                        importance, title, value)
+        lines = []
+        frames = self.filter_frames(exc_data.frames)
+        for frame in frames:
+            sup = frame.supplement
+            if sup:
+                if sup.object:
+                    general_data[('important', 'object')] = self.format_sup_object(
+                        sup.object)
+                if sup.source_url:
+                    general_data[('important', 'source_url')] = self.format_sup_url(
+                        sup.source_url)
+                if sup.line:
+                    lines.append(self.format_sup_line_pos(sup.line, sup.column))
+                if sup.expression:
+                    lines.append(self.format_sup_expression(sup.expression))
+                if sup.warnings:
+                    for warning in sup.warnings:
+                        lines.append(self.format_sup_warning(warning))
+                if sup.info:
+                    lines.extend(self.format_sup_info(sup.info))
+            if frame.supplement_exception:
+                lines.append('Exception in supplement:')
+                lines.append(self.quote_long(frame.supplement_exception))
+            if frame.traceback_info:
+                lines.append(self.format_traceback_info(frame.traceback_info))
+            filename = frame.filename
+            if filename and self.trim_source_paths:
+                for path, repl in self.trim_source_paths:
+                    if filename.startswith(path):
+                        filename = repl + filename[len(path):]
+                        break
+            lines.append(self.format_source_line(filename or '?', frame))
+            source = frame.get_source_line()
+            long_source = frame.get_source_line(2)
+            if source:
+                lines.append(self.format_long_source(
+                    source, long_source))
+        etype = exc_data.exception_type
+        if not isinstance(etype, basestring):
+            etype = etype.__name__
+        exc_info = self.format_exception_info(
+            etype,
+            exc_data.exception_value)
+        data_by_importance = {'important': [], 'normal': [],
+                              'supplemental': [], 'extra': []}
+        for (importance, name), value in general_data.items():
+            data_by_importance[importance].append(
+                (name, value))
+        for value in data_by_importance.values():
+            value.sort()
+        return self.format_combine(data_by_importance, lines, exc_info)
+
+    def filter_frames(self, frames):
+        """
+        Removes any frames that should be hidden, according to the
+        values of traceback_hide, self.show_hidden_frames, and the
+        hidden status of the final frame.
+        """
+        if self.show_hidden_frames:
+            return frames
+        new_frames = []
+        hidden = False
+        for frame in frames:
+            hide = frame.traceback_hide
+            # @@: It would be nice to signal a warning if an unknown
+            # hide string was used, but I'm not sure where to put
+            # that warning.
+            if hide == 'before':
+                new_frames = []
+                hidden = False
+            elif hide == 'before_and_this':
+                new_frames = []
+                hidden = False
+                continue
+            elif hide == 'reset':
+                hidden = False
+            elif hide == 'reset_and_this':
+                hidden = False
+                continue
+            elif hide == 'after':
+                hidden = True
+            elif hide == 'after_and_this':
+                hidden = True
+                continue
+            elif hide:
+                continue
+            elif hidden:
+                continue
+            new_frames.append(frame)
+        if frames[-1] not in new_frames:
+            # We must include the last frame; that we don't indicates
+            # that the error happened where something was "hidden",
+            # so we just have to show everything
+            return frames
+        return new_frames
+
+    def pretty_string_repr(self, s):
+        """
+        Formats the string as a triple-quoted string when it contains
+        newlines.
+        """
+        if '\n' in s:
+            s = repr(s)
+            s = s[0]*3 + s[1:-1] + s[-1]*3
+            s = s.replace('\\n', '\n')
+            return s
+        else:
+            return repr(s)
+
+    def long_item_list(self, lst):
+        """
+        Returns true if the list contains items that are long, and should
+        be more nicely formatted.
+        """
+        how_many = 0
+        for item in lst:
+            if len(repr(item)) > 40:
+                how_many += 1
+                if how_many >= 3:
+                    return True
+        return False
+
+class TextFormatter(AbstractFormatter):
+
+    def quote(self, s):
+        return s
+    def quote_long(self, s):
+        return s
+    def emphasize(self, s):
+        return s
+    def format_sup_object(self, obj):
+        return 'In object: %s' % self.emphasize(self.quote(repr(obj)))
+    def format_sup_url(self, url):
+        return 'URL: %s' % self.quote(url)
+    def format_sup_line_pos(self, line, column):
+        if column:
+            return self.emphasize('Line %i, Column %i' % (line, column))
+        else:
+            return self.emphasize('Line %i' % line)
+    def format_sup_expression(self, expr):
+        return self.emphasize('In expression: %s' % self.quote(expr))
+    def format_sup_warning(self, warning):
+        return 'Warning: %s' % self.quote(warning)
+    def format_sup_info(self, info):
+        return [self.quote_long(info)]
+    def format_source_line(self, filename, frame):
+        return 'File %r, line %s in %s' % (
+            filename, frame.lineno or '?', frame.name or '?')
+    def format_long_source(self, source, long_source):
+        return self.format_source(source)
+    def format_source(self, source_line):
+        return '  ' + self.quote(source_line.strip())
+    def format_exception_info(self, etype, evalue):
+        return self.emphasize(
+            '%s: %s' % (self.quote(etype), self.quote(evalue)))
+    def format_traceback_info(self, info):
+        return info
+        
+    def format_combine(self, data_by_importance, lines, exc_info):
+        lines[:0] = [value for n, value in data_by_importance['important']]
+        lines.append(exc_info)
+        for name in 'normal', 'supplemental', 'extra':
+            lines.extend([value for n, value in data_by_importance[name]])
+        return self.format_combine_lines(lines)
+
+    def format_combine_lines(self, lines):
+        return '\n'.join(lines)
+
+    def format_extra_data(self, importance, title, value):
+        if isinstance(value, str):
+            s = self.pretty_string_repr(value)
+            if '\n' in s:
+                return '%s:\n%s' % (title, s)
+            else:
+                return '%s: %s' % (title, s)
+        elif isinstance(value, dict):
+            lines = ['\n', title, '-'*len(title)]
+            items = value.items()
+            items.sort()
+            for n, v in items:
+                try:
+                    v = repr(v)
+                except Exception, e:
+                    v = 'Cannot display: %s' % e
+                v = truncate(v)
+                lines.append('  %s: %s' % (n, v))
+            return '\n'.join(lines)
+        elif (isinstance(value, (list, tuple))
+              and self.long_item_list(value)):
+            parts = [truncate(repr(v)) for v in value]
+            return '%s: [\n    %s]' % (
+                title, ',\n    '.join(parts))
+        else:
+            return '%s: %s' % (title, truncate(repr(value)))
+
+class HTMLFormatter(TextFormatter):
+
+    def quote(self, s):
+        return html_quote(s)
+    def quote_long(self, s):
+        return '<pre>%s</pre>' % self.quote(s)
+    def emphasize(self, s):
+        return '<b>%s</b>' % s
+    def format_sup_url(self, url):
+        return 'URL: <a href="%s">%s</a>' % (url, url)
+    def format_combine_lines(self, lines):
+        return '<br>\n'.join(lines)
+    def format_source_line(self, filename, frame):
+        name = self.quote(frame.name or '?')
+        return 'Module <span class="module" title="%s">%s</span>:<b>%s</b> in <code>%s</code>' % (
+            filename, frame.modname or '?', frame.lineno or '?',
+            name)
+        return 'File %r, line %s in <tt>%s</tt>' % (
+            filename, frame.lineno, name)
+    def format_long_source(self, source, long_source):
+        q_long_source = str2html(long_source, False, 4, True)
+        q_source = str2html(source, True, 0, False)
+        return ('<code style="display: none" class="source" source-type="long"><a class="switch_source" onclick="return switch_source(this, \'long\')" href="#">&lt;&lt;&nbsp; </a>%s</code>'
+                '<code class="source" source-type="short"><a onclick="return switch_source(this, \'short\')" class="switch_source" href="#">&gt;&gt;&nbsp; </a>%s</code>'
+                % (q_long_source,
+                   q_source))
+    def format_source(self, source_line):
+        return '&nbsp;&nbsp;<code class="source">%s</code>' % self.quote(source_line.strip())
+    def format_traceback_info(self, info):
+        return '<pre>%s</pre>' % self.quote(info)
+
+    def format_extra_data(self, importance, title, value):
+        if isinstance(value, str):
+            s = self.pretty_string_repr(value)
+            if '\n' in s:
+                return '%s:<br><pre>%s</pre>' % (title, self.quote(s))
+            else:
+                return '%s: <tt>%s</tt>' % (title, self.quote(s))
+        elif isinstance(value, dict):
+            return self.zebra_table(title, value)
+        elif (isinstance(value, (list, tuple))
+              and self.long_item_list(value)):
+            return '%s: <tt>[<br>\n&nbsp; &nbsp; %s]</tt>' % (
+                title, ',<br>&nbsp; &nbsp; '.join(map(self.quote, map(repr, value))))
+        else:
+            return '%s: <tt>%s</tt>' % (title, self.quote(repr(value)))
+
+    def format_combine(self, data_by_importance, lines, exc_info):
+        lines[:0] = [value for n, value in data_by_importance['important']]
+        lines.append(exc_info)
+        for name in 'normal', 'supplemental':
+            lines.extend([value for n, value in data_by_importance[name]])
+        if data_by_importance['extra']:
+            lines.append(
+                '<script type="text/javascript">\nshow_button(\'extra_data\', \'extra data\');\n</script>\n' +
+                '<div id="extra_data" class="hidden-data">\n')
+            lines.extend([value for n, value in data_by_importance['extra']])
+            lines.append('</div>')
+        text = self.format_combine_lines(lines)
+        if self.include_reusable:
+            return error_css + hide_display_js + text
+        else:
+            # Usually because another error is already on this page,
+            # and so the js & CSS are unneeded
+            return text
+
+    def zebra_table(self, title, rows, table_class="variables"):
+        if isinstance(rows, dict):
+            rows = rows.items()
+            rows.sort()
+        table = ['<table class="%s">' % table_class,
+                 '<tr class="header"><th colspan="2">%s</th></tr>'
+                 % self.quote(title)]
+        odd = False
+        for name, value in rows:
+            try:
+                value = repr(value)
+            except Exception, e:
+                value = 'Cannot print: %s' % e
+            odd = not odd
+            table.append(
+                '<tr class="%s"><td>%s</td>'
+                % (odd and 'odd' or 'even', self.quote(name)))
+            table.append(
+                '<td><tt>%s</tt></td></tr>'
+                % make_wrappable(self.quote(truncate(value))))
+        table.append('</table>')
+        return '\n'.join(table)
+
+hide_display_js = r'''
+<script type="text/javascript">
+function hide_display(id) {
+    var el = document.getElementById(id);
+    if (el.className == "hidden-data") {
+        el.className = "";
+        return true;
+    } else {
+        el.className = "hidden-data";
+        return false;
+    }
+}
+document.write('<style type="text/css">\n');
+document.write('.hidden-data {display: none}\n');
+document.write('</style>\n');
+function show_button(toggle_id, name) {
+    document.write('<a href="#' + toggle_id
+        + '" onclick="javascript:hide_display(\'' + toggle_id
+        + '\')" class="button">' + name + '</a><br>');
+}
+
+function switch_source(el, hide_type) {
+    while (el) {
+        if (el.getAttribute &&
+            el.getAttribute('source-type') == hide_type) {
+            break;
+        }
+        el = el.parentNode;
+    }
+    if (! el) {
+        return false;
+    }
+    el.style.display = 'none';
+    if (hide_type == 'long') {
+        while (el) {
+            if (el.getAttribute &&
+                el.getAttribute('source-type') == 'short') {
+                break;
+            }
+            el = el.nextSibling;
+        }
+    } else {
+        while (el) {
+            if (el.getAttribute &&
+                el.getAttribute('source-type') == 'long') {
+                break;
+            }
+            el = el.previousSibling;
+        }
+    }
+    if (el) {
+        el.style.display = '';
+    }
+    return false;
+}
+
+</script>'''
+    
+
+error_css = """
+<style type="text/css">
+body {
+  font-family: Helvetica, sans-serif;
+}
+
+table {
+  width: 100%;
+}
+
+tr.header {
+  background-color: #006;
+  color: #fff;
+}
+
+tr.even {
+  background-color: #ddd;
+}
+
+table.variables td {
+  vertical-align: top;
+  overflow: auto;
+}
+
+a.button {
+  background-color: #ccc;
+  border: 2px outset #aaa;
+  color: #000;
+  text-decoration: none;
+}
+
+a.button:hover {
+  background-color: #ddd;
+}
+
+code.source {
+  color: #006;
+}
+
+a.switch_source {
+  color: #090;
+  text-decoration: none;
+}
+
+a.switch_source:hover {
+  background-color: #ddd;
+}
+
+.source-highlight {
+  background-color: #ff9;
+}
+
+</style>
+"""
+
+def format_html(exc_data, include_hidden_frames=False, **ops):
+    if not include_hidden_frames:
+        return HTMLFormatter(**ops).format_collected_data(exc_data)
+    short_er = format_html(exc_data, show_hidden_frames=False, **ops)
+    # @@: This should have a way of seeing if the previous traceback
+    # was actually trimmed at all
+    ops['include_reusable'] = False
+    ops['show_extra_data'] = False
+    long_er = format_html(exc_data, show_hidden_frames=True, **ops)
+    text_er = format_text(exc_data, show_hidden_frames=True, **ops)
+    return """
+    %s
+    <br>
+    <script type="text/javascript">
+    show_button('full_traceback', 'full traceback')
+    </script>
+    <div id="full_traceback" class="hidden-data">
+    %s
+    </div>
+    <br>
+    <script type="text/javascript">
+    show_button('text_version', 'text version')
+    </script>
+    <div id="text_version" class="hidden-data">
+    <textarea style="width: 100%%" rows=10 cols=60>%s</textarea>
+    </div>
+    """ % (short_er, long_er, cgi.escape(text_er))
+        
+def format_text(exc_data, **ops):
+    return TextFormatter(**ops).format_collected_data(exc_data)
+
+whitespace_re = re.compile(r'  +')
+pre_re = re.compile(r'</?pre.*?>')
+error_re = re.compile(r'<h3>ERROR: .*?</h3>')
+
+def str2html(src, strip=False, indent_subsequent=0,
+             highlight_inner=False):
+    """
+    Convert a string to HTML.  Try to be really safe about it,
+    returning a quoted version of the string if nothing else works.
+    """
+    try:
+        return _str2html(src, strip=strip,
+                         indent_subsequent=indent_subsequent,
+                         highlight_inner=highlight_inner)
+    except:
+        return html_quote(src)
+
+def _str2html(src, strip=False, indent_subsequent=0,
+              highlight_inner=False):
+    if strip:
+        src = src.strip()
+    orig_src = src
+    try:
+        src = PySourceColor.str2html(src, form='snip')
+        src = error_re.sub('', src)
+        src = pre_re.sub('', src)
+        src = re.sub(r'^[\n\r]{0,1}', '', src)
+        src = re.sub(r'[\n\r]{0,1}$', '', src)
+    except:
+        src = html_quote(orig_src)
+    lines = src.splitlines()
+    if len(lines) == 1:
+        return lines[0]
+    indent = ' '*indent_subsequent
+    for i in range(1, len(lines)):
+        lines[i] = indent+lines[i]
+        if highlight_inner and i == len(lines)/2:
+            lines[i] = '<span class="source-highlight">%s</span>' % lines[i]
+    src = '<br>\n'.join(lines)
+    src = whitespace_re.sub(
+        lambda m: '&nbsp;'*(len(m.group(0))-1) + ' ', src)
+    return src
+
+def truncate(string, limit=1000):
+    """
+    Truncate the string to the limit number of
+    characters
+    """
+    if len(string) > limit:
+        return string[:limit-20]+'...'+string[-17:]
+    else:
+        return string
+
+def make_wrappable(html, wrap_limit=60,
+                   split_on=';?&@!$#-/\\"\''):
+    # Currently using <wbr>, maybe should use &#8203;
+    #   http://www.cs.tut.fi/~jkorpela/html/nobr.html
+    if len(html) <= wrap_limit:
+        return html
+    words = html.split()
+    new_words = []
+    for word in words:
+        wrapped_word = ''
+        while len(word) > wrap_limit:
+            for char in split_on:
+                if char in word:
+                    first, rest = word.split(char, 1)
+                    wrapped_word += first+char+'<wbr>'
+                    word = rest
+                    break
+            else:
+                for i in range(0, len(word), wrap_limit):
+                    wrapped_word += word[i:i+wrap_limit]+'<wbr>'
+                word = ''
+        wrapped_word += word
+        new_words.append(wrapped_word)
+    return ' '.join(new_words)
+
+def make_pre_wrappable(html, wrap_limit=60,
+                       split_on=';?&@!$#-/\\"\''):
+    """
+    Like ``make_wrappable()`` but intended for text that will
+    go in a ``<pre>`` block, so wrap on a line-by-line basis.
+    """
+    lines = html.splitlines()
+    new_lines = []
+    for line in lines:
+        if len(line) > wrap_limit:
+            for char in split_on:
+                if char in line:
+                    parts = line.split(char)
+                    line = '<wbr>'.join(parts)
+                    break
+        new_lines.append(line)
+    return '\n'.join(lines)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/reporter.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/reporter.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/reporter.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,141 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+from email.MIMEText import MIMEText
+from email.MIMEMultipart import MIMEMultipart
+import smtplib
+import time
+try:
+    from socket import sslerror
+except ImportError:
+    sslerror = None
+from paste.exceptions import formatter
+
+class Reporter(object):
+
+    def __init__(self, **conf):
+        for name, value in conf.items():
+            if not hasattr(self, name):
+                raise TypeError(
+                    "The keyword argument %s was not expected"
+                    % name)
+            setattr(self, name, value)
+        self.check_params()
+
+    def check_params(self):
+        pass
+
+    def format_date(self, exc_data):
+        return time.strftime('%c', exc_data.date)
+
+    def format_html(self, exc_data, **kw):
+        return formatter.format_html(exc_data, **kw)
+
+    def format_text(self, exc_data, **kw):
+        return formatter.format_text(exc_data, **kw)
+
+class EmailReporter(Reporter):
+
+    to_addresses = None
+    from_address = None
+    smtp_server = 'localhost'
+    smtp_username = None
+    smtp_password = None
+    smtp_use_tls = False
+    subject_prefix = ''
+
+    def report(self, exc_data):
+        msg = self.assemble_email(exc_data)
+        server = smtplib.SMTP(self.smtp_server)
+        if self.smtp_use_tls:
+            server.ehlo()
+            server.starttls()
+            server.ehlo()
+        if self.smtp_username and self.smtp_password:
+            server.login(self.smtp_username, self.smtp_password)
+        server.sendmail(self.from_address,
+                        self.to_addresses, msg.as_string())
+        try:
+            server.quit()
+        except sslerror:
+            # sslerror is raised in tls connections on closing sometimes
+            pass
+
+    def check_params(self):
+        if not self.to_addresses:
+            raise ValueError("You must set to_addresses")
+        if not self.from_address:
+            raise ValueError("You must set from_address")
+        if isinstance(self.to_addresses, (str, unicode)):
+            self.to_addresses = [self.to_addresses]
+
+    def assemble_email(self, exc_data):
+        short_html_version = self.format_html(
+            exc_data, show_hidden_frames=False)
+        long_html_version = self.format_html(
+            exc_data, show_hidden_frames=True)
+        text_version = self.format_text(
+            exc_data, show_hidden_frames=False)
+        msg = MIMEMultipart()
+        msg.set_type('multipart/alternative')
+        msg.preamble = msg.epilogue = ''
+        text_msg = MIMEText(text_version)
+        text_msg.set_type('text/plain')
+        text_msg.set_param('charset', 'ASCII')
+        msg.attach(text_msg)
+        html_msg = MIMEText(short_html_version)
+        html_msg.set_type('text/html')
+        # @@: Correct character set?
+        html_msg.set_param('charset', 'UTF-8')
+        html_long = MIMEText(long_html_version)
+        html_long.set_type('text/html')
+        html_long.set_param('charset', 'UTF-8')
+        msg.attach(html_msg)
+        msg.attach(html_long)
+        subject = '%s: %s' % (exc_data.exception_type,
+                              formatter.truncate(str(exc_data.exception_value)))
+        msg['Subject'] = self.subject_prefix + subject
+        msg['From'] = self.from_address
+        msg['To'] = ', '.join(self.to_addresses)
+        return msg
+
+class LogReporter(Reporter):
+
+    filename = None
+    show_hidden_frames = True
+
+    def check_params(self):
+        assert self.filename is not None, (
+            "You must give a filename")
+
+    def report(self, exc_data):
+        text = self.format_text(
+            exc_data, show_hidden_frames=self.show_hidden_frames)
+        f = open(self.filename, 'a')
+        try:
+            f.write(text + '\n' + '-'*60 + '\n')
+        finally:
+            f.close()
+
+class FileReporter(Reporter):
+
+    file = None
+    show_hidden_frames = True
+
+    def check_params(self):
+        assert self.file is not None, (
+            "You must give a file object")
+
+    def report(self, exc_data):
+        text = self.format_text(
+            exc_data, show_hidden_frames=self.show_hidden_frames)
+        self.file.write(text + '\n' + '-'*60 + '\n')
+
+class WSGIAppReporter(Reporter):
+
+    def __init__(self, exc_data):
+        self.exc_data = exc_data
+
+    def __call__(self, environ, start_response):
+        start_response('500 Server Error', [('Content-type', 'text/html')])
+        return [formatter.format_html(self.exc_data)]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/serial_number_generator.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/serial_number_generator.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/exceptions/serial_number_generator.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,123 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Creates a human-readable identifier, using numbers and digits,
+avoiding ambiguous numbers and letters.  hash_identifier can be used
+to create compact representations that are unique for a certain string
+(or concatenation of strings)
+"""
+
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+
+good_characters = "23456789abcdefghjkmnpqrtuvwxyz"
+
+base = len(good_characters)
+
+def make_identifier(number):
+    """
+    Encodes a number as an identifier.
+    """
+    if not isinstance(number, (int, long)):
+        raise ValueError(
+            "You can only make identifiers out of integers (not %r)"
+            % number)
+    if number < 0:
+        raise ValueError(
+            "You cannot make identifiers out of negative numbers: %r"
+            % number)
+    result = []
+    while number:
+        next = number % base
+        result.append(good_characters[next])
+        # Note, this depends on integer rounding of results:
+        number = number / base
+    return ''.join(result)
+
+def hash_identifier(s, length, pad=True, hasher=md5, prefix='',
+                    group=None, upper=False):
+    """
+    Hashes the string (with the given hashing module), then turns that
+    hash into an identifier of the given length (using modulo to
+    reduce the length of the identifier).  If ``pad`` is False, then
+    the minimum-length identifier will be used; otherwise the
+    identifier will be padded with 0's as necessary.
+
+    ``prefix`` will be added last, and does not count towards the
+    target length.  ``group`` will group the characters with ``-`` in
+    the given lengths, and also does not count towards the target
+    length.  E.g., ``group=4`` will cause a identifier like
+    ``a5f3-hgk3-asdf``.  Grouping occurs before the prefix.
+    """
+    if not callable(hasher):
+        # Accept sha/md5 modules as well as callables
+        hasher = hasher.new
+    if length > 26 and hasher is md5:
+        raise ValueError, (
+            "md5 cannot create hashes longer than 26 characters in "
+            "length (you gave %s)" % length)
+    if isinstance(s, unicode):
+        s = s.encode('utf-8')
+    h = hasher(str(s))
+    bin_hash = h.digest()
+    modulo = base ** length
+    number = 0
+    for c in list(bin_hash):
+        number = (number * 256 + ord(c)) % modulo
+    ident = make_identifier(number)
+    if pad:
+        ident = good_characters[0]*(length-len(ident)) + ident
+    if group:
+        parts = []
+        while ident:
+            parts.insert(0, ident[-group:])
+            ident = ident[:-group]
+        ident = '-'.join(parts)
+    if upper:
+        ident = ident.upper()
+    return prefix + ident
+
+# doctest tests:
+__test__ = {
+    'make_identifier': """
+    >>> make_identifier(0)
+    ''
+    >>> make_identifier(1000)
+    'c53'
+    >>> make_identifier(-100)
+    Traceback (most recent call last):
+        ...
+    ValueError: You cannot make identifiers out of negative numbers: -100
+    >>> make_identifier('test')
+    Traceback (most recent call last):
+        ...
+    ValueError: You can only make identifiers out of integers (not 'test')
+    >>> make_identifier(1000000000000)
+    'c53x9rqh3'
+    """,
+    'hash_identifier': """
+    >>> hash_identifier(0, 5)
+    'cy2dr'
+    >>> hash_identifier(0, 10)
+    'cy2dr6rg46'
+    >>> hash_identifier('this is a test of a long string', 5)
+    'awatu'
+    >>> hash_identifier(0, 26)
+    'cy2dr6rg46cx8t4w2f3nfexzk4'
+    >>> hash_identifier(0, 30)
+    Traceback (most recent call last):
+        ...
+    ValueError: md5 cannot create hashes longer than 26 characters in length (you gave 30)
+    >>> hash_identifier(0, 10, group=4)
+    'cy-2dr6-rg46'
+    >>> hash_identifier(0, 10, group=4, upper=True, prefix='M-')
+    'M-CY-2DR6-RG46'
+    """}
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fileapp.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fileapp.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fileapp.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,354 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Ian Bicking, Clark C. Evans and contributors
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""
+This module handles sending static content such as in-memory data or
+files.  At this time it has cache helpers and understands the
+if-modified-since request header.
+"""
+
+import os, time, mimetypes, zipfile, tarfile
+from paste.httpexceptions import *
+from paste.httpheaders import *
+
+CACHE_SIZE = 4096
+BLOCK_SIZE = 4096 * 16
+
+__all__ = ['DataApp', 'FileApp', 'DirectoryApp', 'ArchiveStore']
+
+class DataApp(object):
+    """
+    Returns an application that will send content in a single chunk,
+    this application has support for setting cache-control and for
+    responding to conditional (or HEAD) requests.
+
+    Constructor Arguments:
+
+        ``content``     the content being sent to the client
+
+        ``headers``     the headers to send /w the response
+
+        The remaining ``kwargs`` correspond to headers, where the
+        underscore is replaced with a dash.  These values are only
+        added to the headers if they are not already provided; thus,
+        they can be used for default values.  Examples include, but
+        are not limited to:
+
+            ``content_type``
+            ``content_encoding``
+            ``content_location``
+
+    ``cache_control()``
+
+        This method provides validated construction of the ``Cache-Control``
+        header as well as providing for automated filling out of the
+        ``EXPIRES`` header for HTTP/1.0 clients.
+
+    ``set_content()``
+
+        This method provides a mechanism to set the content after the
+        application has been constructed.  This method does things
+        like changing ``Last-Modified`` and ``Content-Length`` headers.
+
+    """
+
+    allowed_methods = ('GET', 'HEAD')
+
+    def __init__(self, content, headers=None, allowed_methods=None,
+                 **kwargs):
+        assert isinstance(headers, (type(None), list))
+        self.expires = None
+        self.content = None
+        self.content_length = None
+        self.last_modified = 0
+        if allowed_methods is not None:
+            self.allowed_methods = allowed_methods
+        self.headers = headers or []
+        for (k, v) in kwargs.items():
+            header = get_header(k)
+            header.update(self.headers, v)
+        ACCEPT_RANGES.update(self.headers, bytes=True)
+        if not CONTENT_TYPE(self.headers):
+            CONTENT_TYPE.update(self.headers)
+        if content is not None:
+            self.set_content(content)
+
+    def cache_control(self, **kwargs):
+        self.expires = CACHE_CONTROL.apply(self.headers, **kwargs) or None
+        return self
+
+    def set_content(self, content, last_modified=None):
+        assert content is not None
+        if last_modified is None:
+            self.last_modified = time.time()
+        else:
+            self.last_modified = last_modified
+        self.content = content
+        self.content_length = len(content)
+        LAST_MODIFIED.update(self.headers, time=self.last_modified)
+        return self
+
+    def content_disposition(self, **kwargs):
+        CONTENT_DISPOSITION.apply(self.headers, **kwargs)
+        return self
+
+    def __call__(self, environ, start_response):
+        method = environ['REQUEST_METHOD'].upper()
+        if method not in self.allowed_methods:
+            exc = HTTPMethodNotAllowed(
+                'You cannot %s a file' % method,
+                headers=[('Allow', ','.join(self.allowed_methods))])
+            return exc(environ, start_response)
+        return self.get(environ, start_response)
+
+    def calculate_etag(self):
+        return '"%s-%s"' % (self.last_modified, self.content_length)
+
+    def get(self, environ, start_response):
+        headers = self.headers[:]
+        current_etag = self.calculate_etag()
+        ETAG.update(headers, current_etag)
+        if self.expires is not None:
+            EXPIRES.update(headers, delta=self.expires)
+
+        try:
+            client_etags = IF_NONE_MATCH.parse(environ)
+            if client_etags:
+                for etag in client_etags:
+                    if etag == current_etag or etag == '*':
+                        # horribly inefficient, n^2 performance, yuck!
+                        for head in list_headers(entity=True):
+                            head.delete(headers)
+                        start_response('304 Not Modified', headers)
+                        return ['']
+        except HTTPBadRequest, exce:
+            return exce.wsgi_application(environ, start_response)
+
+        # If we get If-None-Match and If-Modified-Since, and
+        # If-None-Match doesn't match, then we should not try to
+        # figure out If-Modified-Since (which has 1-second granularity
+        # and just isn't as accurate)
+        if not client_etags:
+            try:
+                client_clock = IF_MODIFIED_SINCE.parse(environ)
+                if client_clock >= int(self.last_modified):
+                    # horribly inefficient, n^2 performance, yuck!
+                    for head in list_headers(entity=True):
+                        head.delete(headers)
+                    start_response('304 Not Modified', headers)
+                    return [''] # empty body
+            except HTTPBadRequest, exce:
+                return exce.wsgi_application(environ, start_response)
+
+        (lower, upper) = (0, self.content_length - 1)
+        range = RANGE.parse(environ)
+        if range and 'bytes' == range[0] and 1 == len(range[1]):
+            (lower, upper) = range[1][0]
+            upper = upper or (self.content_length - 1)
+            if upper >= self.content_length or lower > upper:
+                return HTTPRequestRangeNotSatisfiable((
+                  "Range request was made beyond the end of the content,\r\n"
+                  "which is %s long.\r\n  Range: %s\r\n") % (
+                     self.content_length, RANGE(environ))
+                ).wsgi_application(environ, start_response)
+
+        content_length = upper - lower + 1
+        CONTENT_RANGE.update(headers, first_byte=lower, last_byte=upper,
+                            total_length = self.content_length)
+        CONTENT_LENGTH.update(headers, content_length)
+        if content_length == self.content_length:
+            start_response('200 OK', headers)
+        else:
+            start_response('206 Partial Content', headers)
+        if self.content is not None:
+            return [self.content[lower:upper+1]]
+        return (lower, content_length)
+
+class FileApp(DataApp):
+    """
+    Returns an application that will send the file at the given
+    filename.  Adds a mime type based on ``mimetypes.guess_type()``.
+    See DataApp for the arguments beyond ``filename``.
+    """
+
+    def __init__(self, filename, headers=None, **kwargs):
+        self.filename = filename
+        content_type, content_encoding = self.guess_type()
+        if content_type and 'content_type' not in kwargs:
+            kwargs['content_type'] = content_type
+        if content_encoding and 'content_encoding' not in kwargs:
+            kwargs['content_encoding'] = content_encoding
+        DataApp.__init__(self, None, headers, **kwargs)
+
+    def guess_type(self):
+        return mimetypes.guess_type(self.filename)
+
+    def update(self, force=False):
+        stat = os.stat(self.filename)
+        if not force and stat.st_mtime == self.last_modified:
+            return
+        self.last_modified = stat.st_mtime
+        if stat.st_size < CACHE_SIZE:
+            fh = open(self.filename,"rb")
+            self.set_content(fh.read(), stat.st_mtime)
+            fh.close()
+        else:
+            self.content = None
+            self.content_length = stat.st_size
+            # This is updated automatically if self.set_content() is
+            # called
+            LAST_MODIFIED.update(self.headers, time=self.last_modified)
+
+    def get(self, environ, start_response):
+        is_head = environ['REQUEST_METHOD'].upper() == 'HEAD'
+        if 'max-age=0' in CACHE_CONTROL(environ).lower():
+            self.update(force=True) # RFC 2616 13.2.6
+        else:
+            self.update()
+        if not self.content:
+            if not os.path.exists(self.filename):
+                exc = HTTPNotFound(
+                    'The resource does not exist',
+                    comment="No file at %r" % self.filename)
+                return exc(environ, start_response)
+            try:
+                file = open(self.filename, 'rb')
+            except (IOError, OSError), e:
+                exc = HTTPForbidden(
+                    'You are not permitted to view this file (%s)' % e)
+                return exc.wsgi_application(
+                    environ, start_response)
+        retval = DataApp.get(self, environ, start_response)
+        if isinstance(retval, list):
+            # cached content, exception, or not-modified
+            if is_head:
+                return ['']
+            return retval
+        (lower, content_length) = retval
+        if is_head:
+            return ['']
+        file.seek(lower)
+        file_wrapper = environ.get('wsgi.file_wrapper', None)
+        if file_wrapper:
+            return file_wrapper(file, BLOCK_SIZE)
+        else:
+            return _FileIter(file, size=content_length)
+
+class _FileIter(object):
+
+    def __init__(self, file, block_size=None, size=None):
+        self.file = file
+        self.size = size
+        self.block_size = block_size or BLOCK_SIZE
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        chunk_size = self.block_size
+        if self.size is not None:
+            if chunk_size > self.size:
+                chunk_size = self.size
+            self.size -= chunk_size
+        data = self.file.read(chunk_size)
+        if not data:
+            raise StopIteration
+        return data
+
+    def close(self):
+        self.file.close()
+
+
+class DirectoryApp(object):
+    """
+    Returns an application that dispatches requests to corresponding FileApps based on PATH_INFO.
+    FileApp instances are cached. This app makes sure not to serve any files that are not in a subdirectory.
+    To customize FileApp creation override ``DirectoryApp.make_fileapp``
+    """
+
+    def __init__(self, path):
+        self.path = os.path.abspath(path)
+        if not self.path.endswith(os.path.sep):
+            self.path += os.path.sep
+        assert os.path.isdir(self.path)
+        self.cached_apps = {}
+
+    make_fileapp = FileApp
+
+    def __call__(self, environ, start_response):
+        path_info = environ['PATH_INFO']
+        app = self.cached_apps.get(path_info)
+        if app is None:
+            path = os.path.join(self.path, path_info.lstrip('/'))
+            if not os.path.normpath(path).startswith(self.path):
+                app = HTTPForbidden()
+            elif os.path.isfile(path):
+                app = self.make_fileapp(path)
+                self.cached_apps[path_info] = app
+            else:
+                app = HTTPNotFound(comment=path)
+        return app(environ, start_response)
+
+
+class ArchiveStore(object):
+    """
+    Returns an application that serves up a DataApp for items requested
+    in a given zip or tar archive.
+
+    Constructor Arguments:
+
+        ``filepath``    the path to the archive being served
+
+    ``cache_control()``
+
+        This method provides validated construction of the ``Cache-Control``
+        header as well as providing for automated filling out of the
+        ``EXPIRES`` header for HTTP/1.0 clients.
+    """
+
+    def __init__(self, filepath):
+        if zipfile.is_zipfile(filepath):
+            self.archive = zipfile.ZipFile(filepath,"r")
+        elif tarfile.is_tarfile(filepath):
+            self.archive = tarfile.TarFileCompat(filepath,"r")
+        else:
+            raise AssertionError("filepath '%s' is not a zip or tar " % filepath)
+        self.expires = None
+        self.last_modified = time.time()
+        self.cache = {}
+
+    def cache_control(self, **kwargs):
+        self.expires = CACHE_CONTROL.apply(self.headers, **kwargs) or None
+        return self
+
+    def __call__(self, environ, start_response):
+        path = environ.get("PATH_INFO","")
+        if path.startswith("/"):
+            path = path[1:]
+        application = self.cache.get(path)
+        if application:
+            return application(environ, start_response)
+        try:
+            info = self.archive.getinfo(path)
+        except KeyError:
+            exc = HTTPNotFound("The file requested, '%s', was not found." % path)
+            return exc.wsgi_application(environ, start_response)
+        if info.filename.endswith("/"):
+            exc = HTTPNotFound("Path requested, '%s', is not a file." % path)
+            return exc.wsgi_application(environ, start_response)
+        content_type, content_encoding = mimetypes.guess_type(info.filename)
+        # 'None' is not a valid content-encoding, so don't set the header if
+        # mimetypes.guess_type returns None
+        if content_encoding is not None:
+            app = DataApp(None, content_type = content_type,
+                                content_encoding = content_encoding)
+        else:
+            app = DataApp(None, content_type = content_type)
+        app.set_content(self.archive.read(path),
+                time.mktime(info.date_time + (0,0,0)))
+        self.cache[path] = app
+        app.expires = self.expires
+        return app(environ, start_response)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fixture.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fixture.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/fixture.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1725 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Routines for testing WSGI applications.
+
+Most interesting is the `TestApp <class-paste.fixture.TestApp.html>`_
+for testing WSGI applications, and the `TestFileEnvironment
+<class-paste.fixture.TestFileEnvironment.html>`_ class for testing the
+effects of command-line scripts.
+"""
+
+import sys
+import random
+import urllib
+import urlparse
+import mimetypes
+import time
+import cgi
+import os
+import shutil
+import smtplib
+import shlex
+from Cookie import BaseCookie
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+import re
+try:
+    import subprocess
+except ImportError:
+    from paste.util import subprocess24 as subprocess
+
+from paste import wsgilib
+from paste import lint
+from paste.response import HeaderDict
+
+def tempnam_no_warning(*args):
+    """
+    An os.tempnam with the warning turned off, because sometimes
+    you just need to use this and don't care about the stupid
+    security warning.
+    """
+    return os.tempnam(*args)
+
+class NoDefault(object):
+    pass
+
+def sorted(l):
+    l = list(l)
+    l.sort()
+    return l
+
+class Dummy_smtplib(object):
+
+    existing = None
+
+    def __init__(self, server):
+        import warnings
+        warnings.warn(
+            'Dummy_smtplib is not maintained and is deprecated',
+            DeprecationWarning, 2)
+        assert not self.existing, (
+            "smtplib.SMTP() called again before Dummy_smtplib.existing.reset() "
+            "called.")
+        self.server = server
+        self.open = True
+        self.__class__.existing = self
+
+    def quit(self):
+        assert self.open, (
+            "Called %s.quit() twice" % self)
+        self.open = False
+
+    def sendmail(self, from_address, to_addresses, msg):
+        self.from_address = from_address
+        self.to_addresses = to_addresses
+        self.message = msg
+
+    def install(cls):
+        smtplib.SMTP = cls
+
+    install = classmethod(install)
+
+    def reset(self):
+        assert not self.open, (
+            "SMTP connection not quit")
+        self.__class__.existing = None
+
+class AppError(Exception):
+    pass
+
+class TestApp(object):
+
+    # for py.test
+    disabled = True
+
+    def __init__(self, app, namespace=None, relative_to=None,
+                 extra_environ=None, pre_request_hook=None,
+                 post_request_hook=None):
+        """
+        Wraps a WSGI application in a more convenient interface for
+        testing.
+
+        ``app`` may be an application, or a Paste Deploy app
+        URI, like ``'config:filename.ini#test'``.
+
+        ``namespace`` is a dictionary that will be written to (if
+        provided).  This can be used with doctest or some other
+        system, and the variable ``res`` will be assigned everytime
+        you make a request (instead of returning the request).
+
+        ``relative_to`` is a directory, and filenames used for file
+        uploads are calculated relative to this.  Also ``config:``
+        URIs that aren't absolute.
+
+        ``extra_environ`` is a dictionary of values that should go
+        into the environment for each request.  These can provide a
+        communication channel with the application.
+
+        ``pre_request_hook`` is a function to be called prior to
+        making requests (such as ``post`` or ``get``). This function
+        must take one argument (the instance of the TestApp).
+
+        ``post_request_hook`` is a function, similar to
+        ``pre_request_hook``, to be called after requests are made.
+        """
+        if isinstance(app, (str, unicode)):
+            from paste.deploy import loadapp
+            # @@: Should pick up relative_to from calling module's
+            # __file__
+            app = loadapp(app, relative_to=relative_to)
+        self.app = app
+        self.namespace = namespace
+        self.relative_to = relative_to
+        if extra_environ is None:
+            extra_environ = {}
+        self.extra_environ = extra_environ
+        self.pre_request_hook = pre_request_hook
+        self.post_request_hook = post_request_hook
+        self.reset()
+
+    def reset(self):
+        """
+        Resets the state of the application; currently just clears
+        saved cookies.
+        """
+        self.cookies = {}
+
+    def _make_environ(self):
+        environ = self.extra_environ.copy()
+        environ['paste.throw_errors'] = True
+        return environ
+
+    def get(self, url, params=None, headers=None, extra_environ=None,
+            status=None, expect_errors=False):
+        """
+        Get the given url (well, actually a path like
+        ``'/page.html'``).
+
+        ``params``:
+            A query string, or a dictionary that will be encoded
+            into a query string.  You may also include a query
+            string on the ``url``.
+
+        ``headers``:
+            A dictionary of extra headers to send.
+
+        ``extra_environ``:
+            A dictionary of environmental variables that should
+            be added to the request.
+
+        ``status``:
+            The integer status code you expect (if not 200 or 3xx).
+            If you expect a 404 response, for instance, you must give
+            ``status=404`` or it will be an error.  You can also give
+            a wildcard, like ``'3*'`` or ``'*'``.
+
+        ``expect_errors``:
+            If this is not true, then if anything is written to
+            ``wsgi.errors`` it will be an error.  If it is true, then
+            non-200/3xx responses are also okay.
+
+        Returns a `response object
+        <class-paste.fixture.TestResponse.html>`_
+        """
+        if extra_environ is None:
+            extra_environ = {}
+        # Hide from py.test:
+        __tracebackhide__ = True
+        if params:
+            if not isinstance(params, (str, unicode)):
+                params = urllib.urlencode(params, doseq=True)
+            if '?' in url:
+                url += '&'
+            else:
+                url += '?'
+            url += params
+        environ = self._make_environ()
+        url = str(url)
+        if '?' in url:
+            url, environ['QUERY_STRING'] = url.split('?', 1)
+        else:
+            environ['QUERY_STRING'] = ''
+        self._set_headers(headers, environ)
+        environ.update(extra_environ)
+        req = TestRequest(url, environ, expect_errors)
+        return self.do_request(req, status=status)
+
+    def _gen_request(self, method, url, params='', headers=None, extra_environ=None,
+             status=None, upload_files=None, expect_errors=False):
+        """
+        Do a generic request.
+        """
+        if headers is None:
+            headers = {}
+        if extra_environ is None:
+            extra_environ = {}
+        environ = self._make_environ()
+        # @@: Should this be all non-strings?
+        if isinstance(params, (list, tuple, dict)):
+            params = urllib.urlencode(params)
+        if hasattr(params, 'items'):
+            # Some other multi-dict like format
+            params = urllib.urlencode(params.items())
+        if upload_files:
+            params = cgi.parse_qsl(params, keep_blank_values=True)
+            content_type, params = self.encode_multipart(
+                params, upload_files)
+            environ['CONTENT_TYPE'] = content_type
+        elif params:
+            environ.setdefault('CONTENT_TYPE', 'application/x-www-form-urlencoded')
+        if '?' in url:
+            url, environ['QUERY_STRING'] = url.split('?', 1)
+        else:
+            environ['QUERY_STRING'] = ''
+        environ['CONTENT_LENGTH'] = str(len(params))
+        environ['REQUEST_METHOD'] = method
+        environ['wsgi.input'] = StringIO(params)
+        self._set_headers(headers, environ)
+        environ.update(extra_environ)
+        req = TestRequest(url, environ, expect_errors)
+        return self.do_request(req, status=status)
+
+    def post(self, url, params='', headers=None, extra_environ=None,
+             status=None, upload_files=None, expect_errors=False):
+        """
+        Do a POST request.  Very like the ``.get()`` method.
+        ``params`` are put in the body of the request.
+
+        ``upload_files`` is for file uploads.  It should be a list of
+        ``[(fieldname, filename, file_content)]``.  You can also use
+        just ``[(fieldname, filename)]`` and the file content will be
+        read from disk.
+
+        Returns a `response object
+        <class-paste.fixture.TestResponse.html>`_
+        """
+        return self._gen_request('POST', url, params=params, headers=headers,
+                                 extra_environ=extra_environ,status=status,
+                                 upload_files=upload_files,
+                                 expect_errors=expect_errors)
+
+    def put(self, url, params='', headers=None, extra_environ=None,
+             status=None, upload_files=None, expect_errors=False):
+        """
+        Do a PUT request.  Very like the ``.get()`` method.
+        ``params`` are put in the body of the request.
+
+        ``upload_files`` is for file uploads.  It should be a list of
+        ``[(fieldname, filename, file_content)]``.  You can also use
+        just ``[(fieldname, filename)]`` and the file content will be
+        read from disk.
+
+        Returns a `response object
+        <class-paste.fixture.TestResponse.html>`_
+        """
+        return self._gen_request('PUT', url, params=params, headers=headers,
+                                 extra_environ=extra_environ,status=status,
+                                 upload_files=upload_files,
+                                 expect_errors=expect_errors)
+
+    def delete(self, url, params='', headers=None, extra_environ=None,
+               status=None, expect_errors=False):
+        """
+        Do a DELETE request.  Very like the ``.get()`` method.
+        ``params`` are put in the body of the request.
+
+        Returns a `response object
+        <class-paste.fixture.TestResponse.html>`_
+        """
+        return self._gen_request('DELETE', url, params=params, headers=headers,
+                                 extra_environ=extra_environ,status=status,
+                                 upload_files=None, expect_errors=expect_errors)
+
+
+
+
+    def _set_headers(self, headers, environ):
+        """
+        Turn any headers into environ variables
+        """
+        if not headers:
+            return
+        for header, value in headers.items():
+            if header.lower() == 'content-type':
+                var = 'CONTENT_TYPE'
+            elif header.lower() == 'content-length':
+                var = 'CONTENT_LENGTH'
+            else:
+                var = 'HTTP_%s' % header.replace('-', '_').upper()
+            environ[var] = value
+
+    def encode_multipart(self, params, files):
+        """
+        Encodes a set of parameters (typically a name/value list) and
+        a set of files (a list of (name, filename, file_body)) into a
+        typical POST body, returning the (content_type, body).
+        """
+        boundary = '----------a_BoUnDaRy%s$' % random.random()
+        lines = []
+        for key, value in params:
+            lines.append('--'+boundary)
+            lines.append('Content-Disposition: form-data; name="%s"' % key)
+            lines.append('')
+            lines.append(value)
+        for file_info in files:
+            key, filename, value = self._get_file_info(file_info)
+            lines.append('--'+boundary)
+            lines.append('Content-Disposition: form-data; name="%s"; filename="%s"'
+                         % (key, filename))
+            fcontent = mimetypes.guess_type(filename)[0]
+            lines.append('Content-Type: %s' %
+                         fcontent or 'application/octet-stream')
+            lines.append('')
+            lines.append(value)
+        lines.append('--' + boundary + '--')
+        lines.append('')
+        body = '\r\n'.join(lines)
+        content_type = 'multipart/form-data; boundary=%s' % boundary
+        return content_type, body
+
+    def _get_file_info(self, file_info):
+        if len(file_info) == 2:
+            # It only has a filename
+            filename = file_info[1]
+            if self.relative_to:
+                filename = os.path.join(self.relative_to, filename)
+            f = open(filename, 'rb')
+            content = f.read()
+            f.close()
+            return (file_info[0], filename, content)
+        elif len(file_info) == 3:
+            return file_info
+        else:
+            raise ValueError(
+                "upload_files need to be a list of tuples of (fieldname, "
+                "filename, filecontent) or (fieldname, filename); "
+                "you gave: %r"
+                % repr(file_info)[:100])
+
+    def do_request(self, req, status):
+        """
+        Executes the given request (``req``), with the expected
+        ``status``.  Generally ``.get()`` and ``.post()`` are used
+        instead.
+        """
+        if self.pre_request_hook:
+            self.pre_request_hook(self)
+        __tracebackhide__ = True
+        if self.cookies:
+            c = BaseCookie()
+            for name, value in self.cookies.items():
+                c[name] = value
+            hc = '; '.join(['='.join([m.key, m.value]) for m in c.values()])
+            req.environ['HTTP_COOKIE'] = hc
+        req.environ['paste.testing'] = True
+        req.environ['paste.testing_variables'] = {}
+        app = lint.middleware(self.app)
+        old_stdout = sys.stdout
+        out = CaptureStdout(old_stdout)
+        try:
+            sys.stdout = out
+            start_time = time.time()
+            raise_on_wsgi_error = not req.expect_errors
+            raw_res = wsgilib.raw_interactive(
+                app, req.url,
+                raise_on_wsgi_error=raise_on_wsgi_error,
+                **req.environ)
+            end_time = time.time()
+        finally:
+            sys.stdout = old_stdout
+            sys.stderr.write(out.getvalue())
+        res = self._make_response(raw_res, end_time - start_time)
+        res.request = req
+        for name, value in req.environ['paste.testing_variables'].items():
+            if hasattr(res, name):
+                raise ValueError(
+                    "paste.testing_variables contains the variable %r, but "
+                    "the response object already has an attribute by that "
+                    "name" % name)
+            setattr(res, name, value)
+        if self.namespace is not None:
+            self.namespace['res'] = res
+        if not req.expect_errors:
+            self._check_status(status, res)
+            self._check_errors(res)
+        res.cookies_set = {}
+        for header in res.all_headers('set-cookie'):
+            c = BaseCookie(header)
+            for key, morsel in c.items():
+                self.cookies[key] = morsel.value
+                res.cookies_set[key] = morsel.value
+        if self.post_request_hook:
+            self.post_request_hook(self)
+        if self.namespace is None:
+            # It's annoying to return the response in doctests, as it'll
+            # be printed, so we only return it is we couldn't assign
+            # it anywhere
+            return res
+
+    def _check_status(self, status, res):
+        __tracebackhide__ = True
+        if status == '*':
+            return
+        if isinstance(status, (list, tuple)):
+            if res.status not in status:
+                raise AppError(
+                    "Bad response: %s (not one of %s for %s)\n%s"
+                    % (res.full_status, ', '.join(map(str, status)),
+                       res.request.url, res.body))
+            return
+        if status is None:
+            if res.status >= 200 and res.status < 400:
+                return
+            raise AppError(
+                "Bad response: %s (not 200 OK or 3xx redirect for %s)\n%s"
+                % (res.full_status, res.request.url,
+                   res.body))
+        if status != res.status:
+            raise AppError(
+                "Bad response: %s (not %s)" % (res.full_status, status))
+
+    def _check_errors(self, res):
+        if res.errors:
+            raise AppError(
+                "Application had errors logged:\n%s" % res.errors)
+
+    def _make_response(self, (status, headers, body, errors), total_time):
+        return TestResponse(self, status, headers, body, errors,
+                            total_time)
+
+class CaptureStdout(object):
+
+    def __init__(self, actual):
+        self.captured = StringIO()
+        self.actual = actual
+
+    def write(self, s):
+        self.captured.write(s)
+        self.actual.write(s)
+
+    def flush(self):
+        self.actual.flush()
+
+    def writelines(self, lines):
+        for item in lines:
+            self.write(item)
+
+    def getvalue(self):
+        return self.captured.getvalue()
+
+class TestResponse(object):
+
+    # for py.test
+    disabled = True
+
+    """
+    Instances of this class are return by `TestApp
+    <class-paste.fixture.TestApp.html>`_
+    """
+
+    def __init__(self, test_app, status, headers, body, errors,
+                 total_time):
+        self.test_app = test_app
+        self.status = int(status.split()[0])
+        self.full_status = status
+        self.headers = headers
+        self.header_dict = HeaderDict.fromlist(self.headers)
+        self.body = body
+        self.errors = errors
+        self._normal_body = None
+        self.time = total_time
+        self._forms_indexed = None
+
+    def forms__get(self):
+        """
+        Returns a dictionary of ``Form`` objects.  Indexes are both in
+        order (from zero) and by form id (if the form is given an id).
+        """
+        if self._forms_indexed is None:
+            self._parse_forms()
+        return self._forms_indexed
+
+    forms = property(forms__get,
+                     doc="""
+                     A list of <form>s found on the page (instances of
+                     `Form <class-paste.fixture.Form.html>`_)
+                     """)
+
+    def form__get(self):
+        forms = self.forms
+        if not forms:
+            raise TypeError(
+                "You used response.form, but no forms exist")
+        if 1 in forms:
+            # There is more than one form
+            raise TypeError(
+                "You used response.form, but more than one form exists")
+        return forms[0]
+
+    form = property(form__get,
+                    doc="""
+                    Returns a single `Form
+                    <class-paste.fixture.Form.html>`_ instance; it
+                    is an error if there are multiple forms on the
+                    page.
+                    """)
+
+    _tag_re = re.compile(r'<(/?)([:a-z0-9_\-]*)(.*?)>', re.S|re.I)
+
+    def _parse_forms(self):
+        forms = self._forms_indexed = {}
+        form_texts = []
+        started = None
+        for match in self._tag_re.finditer(self.body):
+            end = match.group(1) == '/'
+            tag = match.group(2).lower()
+            if tag != 'form':
+                continue
+            if end:
+                assert started, (
+                    "</form> unexpected at %s" % match.start())
+                form_texts.append(self.body[started:match.end()])
+                started = None
+            else:
+                assert not started, (
+                    "Nested form tags at %s" % match.start())
+                started = match.start()
+        assert not started, (
+            "Danging form: %r" % self.body[started:])
+        for i, text in enumerate(form_texts):
+            form = Form(self, text)
+            forms[i] = form
+            if form.id:
+                forms[form.id] = form
+
+    def header(self, name, default=NoDefault):
+        """
+        Returns the named header; an error if there is not exactly one
+        matching header (unless you give a default -- always an error
+        if there is more than one header)
+        """
+        found = None
+        for cur_name, value in self.headers:
+            if cur_name.lower() == name.lower():
+                assert not found, (
+                    "Ambiguous header: %s matches %r and %r"
+                    % (name, found, value))
+                found = value
+        if found is None:
+            if default is NoDefault:
+                raise KeyError(
+                    "No header found: %r (from %s)"
+                    % (name, ', '.join([n for n, v in self.headers])))
+            else:
+                return default
+        return found
+
+    def all_headers(self, name):
+        """
+        Gets all headers by the ``name``, returns as a list
+        """
+        found = []
+        for cur_name, value in self.headers:
+            if cur_name.lower() == name.lower():
+                found.append(value)
+        return found
+
+    def follow(self, **kw):
+        """
+        If this request is a redirect, follow that redirect.  It
+        is an error if this is not a redirect response.  Returns
+        another response object.
+        """
+        assert self.status >= 300 and self.status < 400, (
+            "You can only follow redirect responses (not %s)"
+            % self.full_status)
+        location = self.header('location')
+        type, rest = urllib.splittype(location)
+        host, path = urllib.splithost(rest)
+        # @@: We should test that it's not a remote redirect
+        return self.test_app.get(location, **kw)
+
+    def click(self, description=None, linkid=None, href=None,
+              anchor=None, index=None, verbose=False):
+        """
+        Click the link as described.  Each of ``description``,
+        ``linkid``, and ``url`` are *patterns*, meaning that they are
+        either strings (regular expressions), compiled regular
+        expressions (objects with a ``search`` method), or callables
+        returning true or false.
+
+        All the given patterns are ANDed together:
+
+        * ``description`` is a pattern that matches the contents of the
+          anchor (HTML and all -- everything between ``<a...>`` and
+          ``</a>``)
+
+        * ``linkid`` is a pattern that matches the ``id`` attribute of
+          the anchor.  It will receive the empty string if no id is
+          given.
+
+        * ``href`` is a pattern that matches the ``href`` of the anchor;
+          the literal content of that attribute, not the fully qualified
+          attribute.
+
+        * ``anchor`` is a pattern that matches the entire anchor, with
+          its contents.
+
+        If more than one link matches, then the ``index`` link is
+        followed.  If ``index`` is not given and more than one link
+        matches, or if no link matches, then ``IndexError`` will be
+        raised.
+
+        If you give ``verbose`` then messages will be printed about
+        each link, and why it does or doesn't match.  If you use
+        ``app.click(verbose=True)`` you'll see a list of all the
+        links.
+
+        You can use multiple criteria to essentially assert multiple
+        aspects about the link, e.g., where the link's destination is.
+        """
+        __tracebackhide__ = True
+        found_html, found_desc, found_attrs = self._find_element(
+            tag='a', href_attr='href',
+            href_extract=None,
+            content=description,
+            id=linkid,
+            href_pattern=href,
+            html_pattern=anchor,
+            index=index, verbose=verbose)
+        return self.goto(found_attrs['uri'])
+
+    def clickbutton(self, description=None, buttonid=None, href=None,
+                    button=None, index=None, verbose=False):
+        """
+        Like ``.click()``, except looks for link-like buttons.
+        This kind of button should look like
+        ``<button onclick="...location.href='url'...">``.
+        """
+        __tracebackhide__ = True
+        found_html, found_desc, found_attrs = self._find_element(
+            tag='button', href_attr='onclick',
+            href_extract=re.compile(r"location\.href='(.*?)'"),
+            content=description,
+            id=buttonid,
+            href_pattern=href,
+            html_pattern=button,
+            index=index, verbose=verbose)
+        return self.goto(found_attrs['uri'])
+
+    def _find_element(self, tag, href_attr, href_extract,
+                      content, id,
+                      href_pattern,
+                      html_pattern,
+                      index, verbose):
+        content_pat = _make_pattern(content)
+        id_pat = _make_pattern(id)
+        href_pat = _make_pattern(href_pattern)
+        html_pat = _make_pattern(html_pattern)
+
+        _tag_re = re.compile(r'<%s\s+(.*?)>(.*?)</%s>' % (tag, tag),
+                             re.I+re.S)
+
+        def printlog(s):
+            if verbose:
+                print s
+
+        found_links = []
+        total_links = 0
+        for match in _tag_re.finditer(self.body):
+            el_html = match.group(0)
+            el_attr = match.group(1)
+            el_content = match.group(2)
+            attrs = _parse_attrs(el_attr)
+            if verbose:
+                printlog('Element: %r' % el_html)
+            if not attrs.get(href_attr):
+                printlog('  Skipped: no %s attribute' % href_attr)
+                continue
+            el_href = attrs[href_attr]
+            if href_extract:
+                m = href_extract.search(el_href)
+                if not m:
+                    printlog("  Skipped: doesn't match extract pattern")
+                    continue
+                el_href = m.group(1)
+            attrs['uri'] = el_href
+            if el_href.startswith('#'):
+                printlog('  Skipped: only internal fragment href')
+                continue
+            if el_href.startswith('javascript:'):
+                printlog('  Skipped: cannot follow javascript:')
+                continue
+            total_links += 1
+            if content_pat and not content_pat(el_content):
+                printlog("  Skipped: doesn't match description")
+                continue
+            if id_pat and not id_pat(attrs.get('id', '')):
+                printlog("  Skipped: doesn't match id")
+                continue
+            if href_pat and not href_pat(el_href):
+                printlog("  Skipped: doesn't match href")
+                continue
+            if html_pat and not html_pat(el_html):
+                printlog("  Skipped: doesn't match html")
+                continue
+            printlog("  Accepted")
+            found_links.append((el_html, el_content, attrs))
+        if not found_links:
+            raise IndexError(
+                "No matching elements found (from %s possible)"
+                % total_links)
+        if index is None:
+            if len(found_links) > 1:
+                raise IndexError(
+                    "Multiple links match: %s"
+                    % ', '.join([repr(anc) for anc, d, attr in found_links]))
+            found_link = found_links[0]
+        else:
+            try:
+                found_link = found_links[index]
+            except IndexError:
+                raise IndexError(
+                    "Only %s (out of %s) links match; index %s out of range"
+                    % (len(found_links), total_links, index))
+        return found_link
+
+    def goto(self, href, method='get', **args):
+        """
+        Go to the (potentially relative) link ``href``, using the
+        given method (``'get'`` or ``'post'``) and any extra arguments
+        you want to pass to the ``app.get()`` or ``app.post()``
+        methods.
+
+        All hostnames and schemes will be ignored.
+        """
+        scheme, host, path, query, fragment = urlparse.urlsplit(href)
+        # We
+        scheme = host = fragment = ''
+        href = urlparse.urlunsplit((scheme, host, path, query, fragment))
+        href = urlparse.urljoin(self.request.full_url, href)
+        method = method.lower()
+        assert method in ('get', 'post'), (
+            'Only "get" or "post" are allowed for method (you gave %r)'
+            % method)
+        if method == 'get':
+            method = self.test_app.get
+        else:
+            method = self.test_app.post
+        return method(href, **args)
+
+    _normal_body_regex = re.compile(r'[ \n\r\t]+')
+
+    def normal_body__get(self):
+        if self._normal_body is None:
+            self._normal_body = self._normal_body_regex.sub(
+                ' ', self.body)
+        return self._normal_body
+
+    normal_body = property(normal_body__get,
+                           doc="""
+                           Return the whitespace-normalized body
+                           """)
+
+    def __contains__(self, s):
+        """
+        A response 'contains' a string if it is present in the body
+        of the response.  Whitespace is normalized when searching
+        for a string.
+        """
+        if not isinstance(s, (str, unicode)):
+            s = str(s)
+        if isinstance(s, unicode):
+            ## FIXME: we don't know that this response uses utf8:
+            s = s.encode('utf8')
+        return (self.body.find(s) != -1
+                or self.normal_body.find(s) != -1)
+
+    def mustcontain(self, *strings, **kw):
+        """
+        Assert that the response contains all of the strings passed
+        in as arguments.
+
+        Equivalent to::
+
+            assert string in res
+        """
+        if 'no' in kw:
+            no = kw['no']
+            del kw['no']
+            if isinstance(no, basestring):
+                no = [no]
+        else:
+            no = []
+        if kw:
+            raise TypeError(
+                "The only keyword argument allowed is 'no'")
+        for s in strings:
+            if not s in self:
+                print >> sys.stderr, "Actual response (no %r):" % s
+                print >> sys.stderr, self
+                raise IndexError(
+                    "Body does not contain string %r" % s)
+        for no_s in no:
+            if no_s in self:
+                print >> sys.stderr, "Actual response (has %r)" % no_s
+                print >> sys.stderr, self
+                raise IndexError(
+                    "Body contains string %r" % s)
+
+    def __repr__(self):
+        return '<Response %s %r>' % (self.full_status, self.body[:20])
+
+    def __str__(self):
+        simple_body = '\n'.join([l for l in self.body.splitlines()
+                                 if l.strip()])
+        return 'Response: %s\n%s\n%s' % (
+            self.status,
+            '\n'.join(['%s: %s' % (n, v) for n, v in self.headers]),
+            simple_body)
+
+    def showbrowser(self):
+        """
+        Show this response in a browser window (for debugging purposes,
+        when it's hard to read the HTML).
+        """
+        import webbrowser
+        fn = tempnam_no_warning(None, 'paste-fixture') + '.html'
+        f = open(fn, 'wb')
+        f.write(self.body)
+        f.close()
+        url = 'file:' + fn.replace(os.sep, '/')
+        webbrowser.open_new(url)
+
+class TestRequest(object):
+
+    # for py.test
+    disabled = True
+
+    """
+    Instances of this class are created by `TestApp
+    <class-paste.fixture.TestApp.html>`_ with the ``.get()`` and
+    ``.post()`` methods, and are consumed there by ``.do_request()``.
+
+    Instances are also available as a ``.req`` attribute on
+    `TestResponse <class-paste.fixture.TestResponse.html>`_ instances.
+
+    Useful attributes:
+
+    ``url``:
+        The url (actually usually the path) of the request, without
+        query string.
+
+    ``environ``:
+        The environment dictionary used for the request.
+
+    ``full_url``:
+        The url/path, with query string.
+    """
+
+    def __init__(self, url, environ, expect_errors=False):
+        if url.startswith('http://localhost'):
+            url = url[len('http://localhost'):]
+        self.url = url
+        self.environ = environ
+        if environ.get('QUERY_STRING'):
+            self.full_url = url + '?' + environ['QUERY_STRING']
+        else:
+            self.full_url = url
+        self.expect_errors = expect_errors
+
+
+class Form(object):
+
+    """
+    This object represents a form that has been found in a page.
+    This has a couple useful attributes:
+
+    ``text``:
+        the full HTML of the form.
+
+    ``action``:
+        the relative URI of the action.
+
+    ``method``:
+        the method (e.g., ``'GET'``).
+
+    ``id``:
+        the id, or None if not given.
+
+    ``fields``:
+        a dictionary of fields, each value is a list of fields by
+        that name.  ``<input type=\"radio\">`` and ``<select>`` are
+        both represented as single fields with multiple options.
+    """
+
+    # @@: This really should be using Mechanize/ClientForm or
+    # something...
+
+    _tag_re = re.compile(r'<(/?)([:a-z0-9_\-]*)([^>]*?)>', re.I)
+
+    def __init__(self, response, text):
+        self.response = response
+        self.text = text
+        self._parse_fields()
+        self._parse_action()
+
+    def _parse_fields(self):
+        in_select = None
+        in_textarea = None
+        fields = {}
+        for match in self._tag_re.finditer(self.text):
+            end = match.group(1) == '/'
+            tag = match.group(2).lower()
+            if tag not in ('input', 'select', 'option', 'textarea',
+                           'button'):
+                continue
+            if tag == 'select' and end:
+                assert in_select, (
+                    '%r without starting select' % match.group(0))
+                in_select = None
+                continue
+            if tag == 'textarea' and end:
+                assert in_textarea, (
+                    "</textarea> with no <textarea> at %s" % match.start())
+                in_textarea[0].value = html_unquote(self.text[in_textarea[1]:match.start()])
+                in_textarea = None
+                continue
+            if end:
+                continue
+            attrs = _parse_attrs(match.group(3))
+            if 'name' in attrs:
+                name = attrs.pop('name')
+            else:
+                name = None
+            if tag == 'option':
+                in_select.options.append((attrs.get('value'),
+                                          'selected' in attrs))
+                continue
+            if tag == 'input' and attrs.get('type') == 'radio':
+                field = fields.get(name)
+                if not field:
+                    field = Radio(self, tag, name, match.start(), **attrs)
+                    fields.setdefault(name, []).append(field)
+                else:
+                    field = field[0]
+                    assert isinstance(field, Radio)
+                field.options.append((attrs.get('value'),
+                                      'checked' in attrs))
+                continue
+            tag_type = tag
+            if tag == 'input':
+                tag_type = attrs.get('type', 'text').lower()
+            FieldClass = Field.classes.get(tag_type, Field)
+            field = FieldClass(self, tag, name, match.start(), **attrs)
+            if tag == 'textarea':
+                assert not in_textarea, (
+                    "Nested textareas: %r and %r"
+                    % (in_textarea, match.group(0)))
+                in_textarea = field, match.end()
+            elif tag == 'select':
+                assert not in_select, (
+                    "Nested selects: %r and %r"
+                    % (in_select, match.group(0)))
+                in_select = field
+            fields.setdefault(name, []).append(field)
+        self.fields = fields
+
+    def _parse_action(self):
+        self.action = None
+        for match in self._tag_re.finditer(self.text):
+            end = match.group(1) == '/'
+            tag = match.group(2).lower()
+            if tag != 'form':
+                continue
+            if end:
+                break
+            attrs = _parse_attrs(match.group(3))
+            self.action = attrs.get('action', '')
+            self.method = attrs.get('method', 'GET')
+            self.id = attrs.get('id')
+            # @@: enctype?
+        else:
+            assert 0, "No </form> tag found"
+        assert self.action is not None, (
+            "No <form> tag found")
+
+    def __setitem__(self, name, value):
+        """
+        Set the value of the named field.  If there is 0 or multiple
+        fields by that name, it is an error.
+
+        Setting the value of a ``<select>`` selects the given option
+        (and confirms it is an option).  Setting radio fields does the
+        same.  Checkboxes get boolean values.  You cannot set hidden
+        fields or buttons.
+
+        Use ``.set()`` if there is any ambiguity and you must provide
+        an index.
+        """
+        fields = self.fields.get(name)
+        assert fields is not None, (
+            "No field by the name %r found (fields: %s)"
+            % (name, ', '.join(map(repr, self.fields.keys()))))
+        assert len(fields) == 1, (
+            "Multiple fields match %r: %s"
+            % (name, ', '.join(map(repr, fields))))
+        fields[0].value = value
+
+    def __getitem__(self, name):
+        """
+        Get the named field object (ambiguity is an error).
+        """
+        fields = self.fields.get(name)
+        assert fields is not None, (
+            "No field by the name %r found" % name)
+        assert len(fields) == 1, (
+            "Multiple fields match %r: %s"
+            % (name, ', '.join(map(repr, fields))))
+        return fields[0]
+
+    def set(self, name, value, index=None):
+        """
+        Set the given name, using ``index`` to disambiguate.
+        """
+        if index is None:
+            self[name] = value
+        else:
+            fields = self.fields.get(name)
+            assert fields is not None, (
+                "No fields found matching %r" % name)
+            field = fields[index]
+            field.value = value
+
+    def get(self, name, index=None, default=NoDefault):
+        """
+        Get the named/indexed field object, or ``default`` if no field
+        is found.
+        """
+        fields = self.fields.get(name)
+        if fields is None and default is not NoDefault:
+            return default
+        if index is None:
+            return self[name]
+        else:
+            fields = self.fields.get(name)
+            assert fields is not None, (
+                "No fields found matching %r" % name)
+            field = fields[index]
+            return field
+
+    def select(self, name, value, index=None):
+        """
+        Like ``.set()``, except also confirms the target is a
+        ``<select>``.
+        """
+        field = self.get(name, index=index)
+        assert isinstance(field, Select)
+        field.value = value
+
+    def submit(self, name=None, index=None, **args):
+        """
+        Submits the form.  If ``name`` is given, then also select that
+        button (using ``index`` to disambiguate)``.
+
+        Any extra keyword arguments are passed to the ``.get()`` or
+        ``.post()`` method.
+
+        Returns a response object.
+        """
+        fields = self.submit_fields(name, index=index)
+        return self.response.goto(self.action, method=self.method,
+                                  params=fields, **args)
+
+    def submit_fields(self, name=None, index=None):
+        """
+        Return a list of ``[(name, value), ...]`` for the current
+        state of the form.
+        """
+        submit = []
+        if name is not None:
+            field = self.get(name, index=index)
+            submit.append((field.name, field.value_if_submitted()))
+        for name, fields in self.fields.items():
+            if name is None:
+                continue
+            for field in fields:
+                value = field.value
+                if value is None:
+                    continue
+                submit.append((name, value))
+        return submit
+
+
+_attr_re = re.compile(r'([^= \n\r\t]+)[ \n\r\t]*(?:=[ \n\r\t]*(?:"([^"]*)"|([^"][^ \n\r\t>]*)))?', re.S)
+
+def _parse_attrs(text):
+    attrs = {}
+    for match in _attr_re.finditer(text):
+        attr_name = match.group(1).lower()
+        attr_body = match.group(2) or match.group(3)
+        attr_body = html_unquote(attr_body or '')
+        attrs[attr_name] = attr_body
+    return attrs
+
+class Field(object):
+
+    """
+    Field object.
+    """
+
+    # Dictionary of field types (select, radio, etc) to classes
+    classes = {}
+
+    settable = True
+
+    def __init__(self, form, tag, name, pos,
+                 value=None, id=None, **attrs):
+        self.form = form
+        self.tag = tag
+        self.name = name
+        self.pos = pos
+        self._value = value
+        self.id = id
+        self.attrs = attrs
+
+    def value__set(self, value):
+        if not self.settable:
+            raise AttributeError(
+                "You cannot set the value of the <%s> field %r"
+                % (self.tag, self.name))
+        self._value = value
+
+    def force_value(self, value):
+        """
+        Like setting a value, except forces it even for, say, hidden
+        fields.
+        """
+        self._value = value
+
+    def value__get(self):
+        return self._value
+
+    value = property(value__get, value__set)
+
+class Select(Field):
+
+    """
+    Field representing ``<select>``
+    """
+
+    def __init__(self, *args, **attrs):
+        super(Select, self).__init__(*args, **attrs)
+        self.options = []
+        self.multiple = attrs.get('multiple')
+        assert not self.multiple, (
+            "<select multiple> not yet supported")
+        # Undetermined yet:
+        self.selectedIndex = None
+
+    def value__set(self, value):
+        for i, (option, checked) in enumerate(self.options):
+            if option == str(value):
+                self.selectedIndex = i
+                break
+        else:
+            raise ValueError(
+                "Option %r not found (from %s)"
+                % (value, ', '.join(
+                [repr(o) for o, c in self.options])))
+
+    def value__get(self):
+        if self.selectedIndex is not None:
+            return self.options[self.selectedIndex][0]
+        else:
+            for option, checked in self.options:
+                if checked:
+                    return option
+            else:
+                if self.options:
+                    return self.options[0][0]
+                else:
+                    return None
+
+    value = property(value__get, value__set)
+
+Field.classes['select'] = Select
+
+class Radio(Select):
+
+    """
+    Field representing ``<input type="radio">``
+    """
+
+Field.classes['radio'] = Radio
+
+class Checkbox(Field):
+
+    """
+    Field representing ``<input type="checkbox">``
+    """
+
+    def __init__(self, *args, **attrs):
+        super(Checkbox, self).__init__(*args, **attrs)
+        self.checked = 'checked' in attrs
+
+    def value__set(self, value):
+        self.checked = not not value
+
+    def value__get(self):
+        if self.checked:
+            if self._value is None:
+                return 'on'
+            else:
+                return self._value
+        else:
+            return None
+
+    value = property(value__get, value__set)
+
+Field.classes['checkbox'] = Checkbox
+
+class Text(Field):
+    """
+    Field representing ``<input type="text">``
+    """
+    def __init__(self, form, tag, name, pos,
+                 value='', id=None, **attrs):
+        #text fields default to empty string
+        Field.__init__(self, form, tag, name, pos,
+                       value=value, id=id, **attrs)
+
+Field.classes['text'] = Text
+
+class Textarea(Text):
+    """
+    Field representing ``<textarea>``
+    """
+
+Field.classes['textarea'] = Textarea
+
+class Hidden(Text):
+    """
+    Field representing ``<input type="hidden">``
+    """
+
+Field.classes['hidden'] = Hidden
+
+class Submit(Field):
+    """
+    Field representing ``<input type="submit">`` and ``<button>``
+    """
+
+    settable = False
+
+    def value__get(self):
+        return None
+
+    value = property(value__get)
+
+    def value_if_submitted(self):
+        return self._value
+
+Field.classes['submit'] = Submit
+
+Field.classes['button'] = Submit
+
+Field.classes['image'] = Submit
+
+############################################################
+## Command-line testing
+############################################################
+
+
+class TestFileEnvironment(object):
+
+    """
+    This represents an environment in which files will be written, and
+    scripts will be run.
+    """
+
+    # for py.test
+    disabled = True
+
+    def __init__(self, base_path, template_path=None,
+                 script_path=None,
+                 environ=None, cwd=None, start_clear=True,
+                 ignore_paths=None, ignore_hidden=True):
+        """
+        Creates an environment.  ``base_path`` is used as the current
+        working directory, and generally where changes are looked for.
+
+        ``template_path`` is the directory to look for *template*
+        files, which are files you'll explicitly add to the
+        environment.  This is done with ``.writefile()``.
+
+        ``script_path`` is the PATH for finding executables.  Usually
+        grabbed from ``$PATH``.
+
+        ``environ`` is the operating system environment,
+        ``os.environ`` if not given.
+
+        ``cwd`` is the working directory, ``base_path`` by default.
+
+        If ``start_clear`` is true (default) then the ``base_path``
+        will be cleared (all files deleted) when an instance is
+        created.  You can also use ``.clear()`` to clear the files.
+
+        ``ignore_paths`` is a set of specific filenames that should be
+        ignored when created in the environment.  ``ignore_hidden``
+        means, if true (default) that filenames and directories
+        starting with ``'.'`` will be ignored.
+        """
+        self.base_path = base_path
+        self.template_path = template_path
+        if environ is None:
+            environ = os.environ.copy()
+        self.environ = environ
+        if script_path is None:
+            if sys.platform == 'win32':
+                script_path = environ.get('PATH', '').split(';')
+            else:
+                script_path = environ.get('PATH', '').split(':')
+        self.script_path = script_path
+        if cwd is None:
+            cwd = base_path
+        self.cwd = cwd
+        if start_clear:
+            self.clear()
+        elif not os.path.exists(base_path):
+            os.makedirs(base_path)
+        self.ignore_paths = ignore_paths or []
+        self.ignore_hidden = ignore_hidden
+
+    def run(self, script, *args, **kw):
+        """
+        Run the command, with the given arguments.  The ``script``
+        argument can have space-separated arguments, or you can use
+        the positional arguments.
+
+        Keywords allowed are:
+
+        ``expect_error``: (default False)
+            Don't raise an exception in case of errors
+        ``expect_stderr``: (default ``expect_error``)
+            Don't raise an exception if anything is printed to stderr
+        ``stdin``: (default ``""``)
+            Input to the script
+        ``printresult``: (default True)
+            Print the result after running
+        ``cwd``: (default ``self.cwd``)
+            The working directory to run in
+
+        Returns a `ProcResponse
+        <class-paste.fixture.ProcResponse.html>`_ object.
+        """
+        __tracebackhide__ = True
+        expect_error = _popget(kw, 'expect_error', False)
+        expect_stderr = _popget(kw, 'expect_stderr', expect_error)
+        cwd = _popget(kw, 'cwd', self.cwd)
+        stdin = _popget(kw, 'stdin', None)
+        printresult = _popget(kw, 'printresult', True)
+        args = map(str, args)
+        assert not kw, (
+            "Arguments not expected: %s" % ', '.join(kw.keys()))
+        if ' ' in script:
+            assert not args, (
+                "You cannot give a multi-argument script (%r) "
+                "and arguments (%s)" % (script, args))
+            script, args = script.split(None, 1)
+            args = shlex.split(args)
+        script = self._find_exe(script)
+        all = [script] + args
+        files_before = self._find_files()
+        proc = subprocess.Popen(all, stdin=subprocess.PIPE,
+                                stderr=subprocess.PIPE,
+                                stdout=subprocess.PIPE,
+                                cwd=cwd,
+                                env=self.environ)
+        stdout, stderr = proc.communicate(stdin)
+        files_after = self._find_files()
+        result = ProcResult(
+            self, all, stdin, stdout, stderr,
+            returncode=proc.returncode,
+            files_before=files_before,
+            files_after=files_after)
+        if printresult:
+            print result
+            print '-'*40
+        if not expect_error:
+            result.assert_no_error()
+        if not expect_stderr:
+            result.assert_no_stderr()
+        return result
+
+    def _find_exe(self, script_name):
+        if self.script_path is None:
+            script_name = os.path.join(self.cwd, script_name)
+            if not os.path.exists(script_name):
+                raise OSError(
+                    "Script %s does not exist" % script_name)
+            return script_name
+        for path in self.script_path:
+            fn = os.path.join(path, script_name)
+            if os.path.exists(fn):
+                return fn
+        raise OSError(
+            "Script %s could not be found in %s"
+            % (script_name, ':'.join(self.script_path)))
+
+    def _find_files(self):
+        result = {}
+        for fn in os.listdir(self.base_path):
+            if self._ignore_file(fn):
+                continue
+            self._find_traverse(fn, result)
+        return result
+
+    def _ignore_file(self, fn):
+        if fn in self.ignore_paths:
+            return True
+        if self.ignore_hidden and os.path.basename(fn).startswith('.'):
+            return True
+        return False
+
+    def _find_traverse(self, path, result):
+        full = os.path.join(self.base_path, path)
+        if os.path.isdir(full):
+            result[path] = FoundDir(self.base_path, path)
+            for fn in os.listdir(full):
+                fn = os.path.join(path, fn)
+                if self._ignore_file(fn):
+                    continue
+                self._find_traverse(fn, result)
+        else:
+            result[path] = FoundFile(self.base_path, path)
+
+    def clear(self):
+        """
+        Delete all the files in the base directory.
+        """
+        if os.path.exists(self.base_path):
+            shutil.rmtree(self.base_path)
+        os.mkdir(self.base_path)
+
+    def writefile(self, path, content=None,
+                  frompath=None):
+        """
+        Write a file to the given path.  If ``content`` is given then
+        that text is written, otherwise the file in ``frompath`` is
+        used.  ``frompath`` is relative to ``self.template_path``
+        """
+        full = os.path.join(self.base_path, path)
+        if not os.path.exists(os.path.dirname(full)):
+            os.makedirs(os.path.dirname(full))
+        f = open(full, 'wb')
+        if content is not None:
+            f.write(content)
+        if frompath is not None:
+            if self.template_path:
+                frompath = os.path.join(self.template_path, frompath)
+            f2 = open(frompath, 'rb')
+            f.write(f2.read())
+            f2.close()
+        f.close()
+        return FoundFile(self.base_path, path)
+
+class ProcResult(object):
+
+    """
+    Represents the results of running a command in
+    `TestFileEnvironment
+    <class-paste.fixture.TestFileEnvironment.html>`_.
+
+    Attributes to pay particular attention to:
+
+    ``stdout``, ``stderr``:
+        What is produced
+
+    ``files_created``, ``files_deleted``, ``files_updated``:
+        Dictionaries mapping filenames (relative to the ``base_dir``)
+        to `FoundFile <class-paste.fixture.FoundFile.html>`_ or
+        `FoundDir <class-paste.fixture.FoundDir.html>`_ objects.
+    """
+
+    def __init__(self, test_env, args, stdin, stdout, stderr,
+                 returncode, files_before, files_after):
+        self.test_env = test_env
+        self.args = args
+        self.stdin = stdin
+        self.stdout = stdout
+        self.stderr = stderr
+        self.returncode = returncode
+        self.files_before = files_before
+        self.files_after = files_after
+        self.files_deleted = {}
+        self.files_updated = {}
+        self.files_created = files_after.copy()
+        for path, f in files_before.items():
+            if path not in files_after:
+                self.files_deleted[path] = f
+                continue
+            del self.files_created[path]
+            if f.mtime < files_after[path].mtime:
+                self.files_updated[path] = files_after[path]
+
+    def assert_no_error(self):
+        __tracebackhide__ = True
+        assert self.returncode == 0, (
+            "Script returned code: %s" % self.returncode)
+
+    def assert_no_stderr(self):
+        __tracebackhide__ = True
+        if self.stderr:
+            print 'Error output:'
+            print self.stderr
+            raise AssertionError("stderr output not expected")
+
+    def __str__(self):
+        s = ['Script result: %s' % ' '.join(self.args)]
+        if self.returncode:
+            s.append('  return code: %s' % self.returncode)
+        if self.stderr:
+            s.append('-- stderr: --------------------')
+            s.append(self.stderr)
+        if self.stdout:
+            s.append('-- stdout: --------------------')
+            s.append(self.stdout)
+        for name, files, show_size in [
+            ('created', self.files_created, True),
+            ('deleted', self.files_deleted, True),
+            ('updated', self.files_updated, True)]:
+            if files:
+                s.append('-- %s: -------------------' % name)
+                files = files.items()
+                files.sort()
+                last = ''
+                for path, f in files:
+                    t = '  %s' % _space_prefix(last, path, indent=4,
+                                               include_sep=False)
+                    last = path
+                    if show_size and f.size != 'N/A':
+                        t += '  (%s bytes)' % f.size
+                    s.append(t)
+        return '\n'.join(s)
+
+class FoundFile(object):
+
+    """
+    Represents a single file found as the result of a command.
+
+    Has attributes:
+
+    ``path``:
+        The path of the file, relative to the ``base_path``
+
+    ``full``:
+        The full path
+
+    ``stat``:
+        The results of ``os.stat``.  Also ``mtime`` and ``size``
+        contain the ``.st_mtime`` and ``st_size`` of the stat.
+
+    ``bytes``:
+        The contents of the file.
+
+    You may use the ``in`` operator with these objects (tested against
+    the contents of the file), and the ``.mustcontain()`` method.
+    """
+
+    file = True
+    dir = False
+
+    def __init__(self, base_path, path):
+        self.base_path = base_path
+        self.path = path
+        self.full = os.path.join(base_path, path)
+        self.stat = os.stat(self.full)
+        self.mtime = self.stat.st_mtime
+        self.size = self.stat.st_size
+        self._bytes = None
+
+    def bytes__get(self):
+        if self._bytes is None:
+            f = open(self.full, 'rb')
+            self._bytes = f.read()
+            f.close()
+        return self._bytes
+    bytes = property(bytes__get)
+
+    def __contains__(self, s):
+        return s in self.bytes
+
+    def mustcontain(self, s):
+        __tracebackhide__ = True
+        bytes = self.bytes
+        if s not in bytes:
+            print 'Could not find %r in:' % s
+            print bytes
+            assert s in bytes
+
+    def __repr__(self):
+        return '<%s %s:%s>' % (
+            self.__class__.__name__,
+            self.base_path, self.path)
+
+class FoundDir(object):
+
+    """
+    Represents a directory created by a command.
+    """
+
+    file = False
+    dir = True
+
+    def __init__(self, base_path, path):
+        self.base_path = base_path
+        self.path = path
+        self.full = os.path.join(base_path, path)
+        self.size = 'N/A'
+        self.mtime = 'N/A'
+
+    def __repr__(self):
+        return '<%s %s:%s>' % (
+            self.__class__.__name__,
+            self.base_path, self.path)
+
+def _popget(d, key, default=None):
+    """
+    Pop the key if found (else return default)
+    """
+    if key in d:
+        return d.pop(key)
+    return default
+
+def _space_prefix(pref, full, sep=None, indent=None, include_sep=True):
+    """
+    Anything shared by pref and full will be replaced with spaces
+    in full, and full returned.
+    """
+    if sep is None:
+        sep = os.path.sep
+    pref = pref.split(sep)
+    full = full.split(sep)
+    padding = []
+    while pref and full and pref[0] == full[0]:
+        if indent is None:
+            padding.append(' ' * (len(full[0]) + len(sep)))
+        else:
+            padding.append(' ' * indent)
+        full.pop(0)
+        pref.pop(0)
+    if padding:
+        if include_sep:
+            return ''.join(padding) + sep + sep.join(full)
+        else:
+            return ''.join(padding) + sep.join(full)
+    else:
+        return sep.join(full)
+
+def _make_pattern(pat):
+    if pat is None:
+        return None
+    if isinstance(pat, (str, unicode)):
+        pat = re.compile(pat)
+    if hasattr(pat, 'search'):
+        return pat.search
+    if callable(pat):
+        return pat
+    assert 0, (
+        "Cannot make callable pattern object out of %r" % pat)
+
+def setup_module(module=None):
+    """
+    This is used by py.test if it is in the module, so you can
+    import this directly.
+
+    Use like::
+
+        from paste.fixture import setup_module
+    """
+    # Deprecated June 2008
+    import warnings
+    warnings.warn(
+        'setup_module is deprecated',
+        DeprecationWarning, 2)
+    if module is None:
+        # The module we were called from must be the module...
+        module = sys._getframe().f_back.f_globals['__name__']
+    if isinstance(module, (str, unicode)):
+        module = sys.modules[module]
+    if hasattr(module, 'reset_state'):
+        module.reset_state()
+
+def html_unquote(v):
+    """
+    Unquote (some) entities in HTML.  (incomplete)
+    """
+    for ent, repl in [('&nbsp;', ' '), ('&gt;', '>'),
+                      ('&lt;', '<'), ('&quot;', '"'),
+                      ('&amp;', '&')]:
+        v = v.replace(ent, repl)
+    return v

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/flup_session.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/flup_session.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/flup_session.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,108 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Creates a session object.
+
+In your application, use::
+
+    environ['paste.flup_session_service'].session
+
+This will return a dictionary.  The contents of this dictionary will
+be saved to disk when the request is completed.  The session will be
+created when you first fetch the session dictionary, and a cookie will
+be sent in that case.  There's current no way to use sessions without
+cookies, and there's no way to delete a session except to clear its
+data.
+"""
+
+from paste import httpexceptions
+from paste import wsgilib
+import flup.middleware.session
+flup_session = flup.middleware.session
+
+# This is a dictionary of existing stores, keyed by a tuple of
+# store type and parameters
+store_cache = {}
+
+class NoDefault(object):
+    pass
+
+class SessionMiddleware(object):
+
+    session_classes = {
+        'memory': (flup_session.MemorySessionStore,
+                   [('session_timeout', 'timeout', int, 60)]),
+        'disk': (flup_session.DiskSessionStore,
+                 [('session_timeout', 'timeout', int, 60),
+                  ('session_dir', 'storeDir', str, '/tmp/sessions')]),
+        'shelve': (flup_session.ShelveSessionStore,
+                   [('session_timeout', 'timeout', int, 60),
+                    ('session_file', 'storeFile', str,
+                     '/tmp/session.shelve')]),
+        }
+
+
+    def __init__(self, app,
+                 global_conf=None,
+                 session_type=NoDefault,
+                 cookie_name=NoDefault,
+                 **store_config
+                 ):
+        self.application = app
+        if session_type is NoDefault:
+            session_type = global_conf.get('session_type', 'disk')
+        self.session_type = session_type
+        try:
+            self.store_class, self.store_args = self.session_classes[self.session_type]
+        except KeyError:
+            raise KeyError(
+                "The session_type %s is unknown (I know about %s)"
+                % (self.session_type,
+                   ', '.join(self.session_classes.keys())))
+        kw = {}
+        for config_name, kw_name, coercer, default in self.store_args:
+            value = coercer(store_config.get(config_name, default))
+            kw[kw_name] = value
+        self.store = self.store_class(**kw)
+        if cookie_name is NoDefault:
+            cookie_name = global_conf.get('session_cookie', '_SID_')
+        self.cookie_name = cookie_name
+        
+    def __call__(self, environ, start_response):
+        service = flup_session.SessionService(
+            self.store, environ, cookieName=self.cookie_name,
+            fieldName=self.cookie_name)
+        environ['paste.flup_session_service'] = service
+
+        def cookie_start_response(status, headers, exc_info=None):
+            service.addCookie(headers)
+            return start_response(status, headers, exc_info)
+
+        try:
+            app_iter = self.application(environ, cookie_start_response)
+        except httpexceptions.HTTPException, e:
+            headers = (e.headers or {}).items()
+            service.addCookie(headers)
+            e.headers = dict(headers)
+            service.close()
+            raise
+        except:
+            service.close()
+            raise
+
+        return wsgilib.add_close(app_iter, service.close)
+            
+def make_session_middleware(app, global_conf,
+                            session_type=NoDefault,
+                            cookie_name=NoDefault,
+                            **store_config):
+    """
+    Wraps the application in a session-managing middleware.
+    The session service can then be found in
+    ``environ['paste.flup_session_service']``
+    """
+    return SessionMiddleware(
+        app, global_conf=global_conf,
+        session_type=session_type, cookie_name=cookie_name,
+        **store_config)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/gzipper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/gzipper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/gzipper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,111 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+WSGI middleware
+
+Gzip-encodes the response.
+"""
+
+import gzip
+from paste.response import header_value, remove_header
+from paste.httpheaders import CONTENT_LENGTH
+
+try:
+    from cStringIO import StringIO
+except ImportError:
+    from StringIO import StringIO
+
+class GzipOutput(object):
+    pass
+
+class middleware(object):
+
+    def __init__(self, application, compress_level=6):
+        self.application = application
+        self.compress_level = int(compress_level)
+
+    def __call__(self, environ, start_response):
+        if 'gzip' not in environ.get('HTTP_ACCEPT_ENCODING', ''):
+            # nothing for us to do, so this middleware will
+            # be a no-op:
+            return self.application(environ, start_response)
+        response = GzipResponse(start_response, self.compress_level)
+        app_iter = self.application(environ,
+                                    response.gzip_start_response)
+        if app_iter is not None:
+            response.finish_response(app_iter)
+
+        return response.write()
+
+class GzipResponse(object):
+
+    def __init__(self, start_response, compress_level):
+        self.start_response = start_response
+        self.compress_level = compress_level
+        self.buffer = StringIO()
+        self.compressible = False
+        self.content_length = None
+
+    def gzip_start_response(self, status, headers, exc_info=None):
+        self.headers = headers
+        ct = header_value(headers,'content-type')
+        ce = header_value(headers,'content-encoding')
+        self.compressible = False
+        if ct and (ct.startswith('text/') or ct.startswith('application/')) \
+            and 'zip' not in ct:
+            self.compressible = True
+        if ce:
+            self.compressible = False
+        if self.compressible:
+            headers.append(('content-encoding', 'gzip'))
+        remove_header(headers, 'content-length')
+        self.headers = headers
+        self.status = status
+        return self.buffer.write
+
+    def write(self):
+        out = self.buffer
+        out.seek(0)
+        s = out.getvalue()
+        out.close()
+        return [s]
+
+    def finish_response(self, app_iter):
+        if self.compressible:
+            output = gzip.GzipFile(mode='wb', compresslevel=self.compress_level,
+                fileobj=self.buffer)
+        else:
+            output = self.buffer
+        try:
+            for s in app_iter:
+                output.write(s)
+            if self.compressible:
+                output.close()
+        finally:
+            if hasattr(app_iter, 'close'):
+                app_iter.close()
+        content_length = self.buffer.tell()
+        CONTENT_LENGTH.update(self.headers, content_length)
+        self.start_response(self.status, self.headers)
+
+def filter_factory(application, **conf):
+    import warnings
+    warnings.warn(
+        'This function is deprecated; use make_gzip_middleware instead',
+        DeprecationWarning, 2)
+    def filter(application):
+        return middleware(application)
+    return filter
+
+def make_gzip_middleware(app, global_conf, compress_level=6):
+    """
+    Wrap the middleware, so that it applies gzipping to a response
+    when it is supported by the browser and the content is of
+    type ``text/*`` or ``application/*``
+    """
+    compress_level = int(compress_level)
+    return middleware(app, compress_level=compress_level)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpexceptions.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpexceptions.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpexceptions.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,660 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Ian Bicking, Clark C. Evans and contributors
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# Some of this code was funded by http://prometheusresearch.com
+"""
+HTTP Exception Middleware
+
+This module processes Python exceptions that relate to HTTP exceptions
+by defining a set of exceptions, all subclasses of HTTPException, and a
+request handler (`middleware`) that catches these exceptions and turns
+them into proper responses.
+
+This module defines exceptions according to RFC 2068 [1]_ : codes with
+100-300 are not really errors; 400's are client errors, and 500's are
+server errors.  According to the WSGI specification [2]_ , the application
+can call ``start_response`` more then once only under two conditions:
+(a) the response has not yet been sent, or (b) if the second and
+subsequent invocations of ``start_response`` have a valid ``exc_info``
+argument obtained from ``sys.exc_info()``.  The WSGI specification then
+requires the server or gateway to handle the case where content has been
+sent and then an exception was encountered.
+
+Exceptions in the 5xx range and those raised after ``start_response``
+has been called are treated as serious errors and the ``exc_info`` is
+filled-in with information needed for a lower level module to generate a
+stack trace and log information.
+
+Exception
+  HTTPException
+    HTTPRedirection
+      * 300 - HTTPMultipleChoices
+      * 301 - HTTPMovedPermanently
+      * 302 - HTTPFound
+      * 303 - HTTPSeeOther
+      * 304 - HTTPNotModified
+      * 305 - HTTPUseProxy
+      * 306 - Unused (not implemented, obviously)
+      * 307 - HTTPTemporaryRedirect
+    HTTPError
+      HTTPClientError
+        * 400 - HTTPBadRequest
+        * 401 - HTTPUnauthorized
+        * 402 - HTTPPaymentRequired
+        * 403 - HTTPForbidden
+        * 404 - HTTPNotFound
+        * 405 - HTTPMethodNotAllowed
+        * 406 - HTTPNotAcceptable
+        * 407 - HTTPProxyAuthenticationRequired
+        * 408 - HTTPRequestTimeout
+        * 409 - HTTPConfict
+        * 410 - HTTPGone
+        * 411 - HTTPLengthRequired
+        * 412 - HTTPPreconditionFailed
+        * 413 - HTTPRequestEntityTooLarge
+        * 414 - HTTPRequestURITooLong
+        * 415 - HTTPUnsupportedMediaType
+        * 416 - HTTPRequestRangeNotSatisfiable
+        * 417 - HTTPExpectationFailed
+      HTTPServerError
+        * 500 - HTTPInternalServerError
+        * 501 - HTTPNotImplemented
+        * 502 - HTTPBadGateway
+        * 503 - HTTPServiceUnavailable
+        * 504 - HTTPGatewayTimeout
+        * 505 - HTTPVersionNotSupported
+
+References:
+
+.. [1] http://www.python.org/peps/pep-0333.html#error-handling
+.. [2] http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.5
+
+"""
+
+import types
+from paste.wsgilib import catch_errors_app
+from paste.response import has_header, header_value, replace_header
+from paste.request import resolve_relative_url
+from paste.util.quoting import strip_html, html_quote, no_quote, comment_quote
+
+SERVER_NAME = 'WSGI Server'
+TEMPLATE = """\
+<html>\r
+  <head><title>%(title)s</title></head>\r
+  <body>\r
+    <h1>%(title)s</h1>\r
+    <p>%(body)s</p>\r
+    <hr noshade>\r
+    <div align="right">%(server)s</div>\r
+  </body>\r
+</html>\r
+"""
+
+class HTTPException(Exception):
+    """
+    the HTTP exception base class
+
+    This encapsulates an HTTP response that interrupts normal application
+    flow; but one which is not necessarly an error condition. For
+    example, codes in the 300's are exceptions in that they interrupt
+    normal processing; however, they are not considered errors.
+
+    This class is complicated by 4 factors:
+
+      1. The content given to the exception may either be plain-text or
+         as html-text.
+
+      2. The template may want to have string-substitutions taken from
+         the current ``environ`` or values from incoming headers. This
+         is especially troublesome due to case sensitivity.
+
+      3. The final output may either be text/plain or text/html
+         mime-type as requested by the client application.
+
+      4. Each exception has a default explanation, but those who
+         raise exceptions may want to provide additional detail.
+
+    Attributes:
+
+       ``code``
+           the HTTP status code for the exception
+
+       ``title``
+           remainder of the status line (stuff after the code)
+
+       ``explanation``
+           a plain-text explanation of the error message that is
+           not subject to environment or header substitutions;
+           it is accessible in the template via %(explanation)s
+
+       ``detail``
+           a plain-text message customization that is not subject
+           to environment or header substitutions; accessible in
+           the template via %(detail)s
+
+       ``template``
+           a content fragment (in HTML) used for environment and
+           header substitution; the default template includes both
+           the explanation and further detail provided in the
+           message
+
+       ``required_headers``
+           a sequence of headers which are required for proper
+           construction of the exception
+
+    Parameters:
+
+       ``detail``
+         a plain-text override of the default ``detail``
+
+       ``headers``
+         a list of (k,v) header pairs
+
+       ``comment``
+         a plain-text additional information which is
+         usually stripped/hidden for end-users
+
+    To override the template (which is HTML content) or the plain-text
+    explanation, one must subclass the given exception; or customize it
+    after it has been created.  This particular breakdown of a message
+    into explanation, detail and template allows both the creation of
+    plain-text and html messages for various clients as well as
+    error-free substitution of environment variables and headers.
+    """
+
+    code = None
+    title = None
+    explanation = ''
+    detail = ''
+    comment = ''
+    template = "%(explanation)s\r\n<br/>%(detail)s\r\n<!-- %(comment)s -->"
+    required_headers = ()
+
+    def __init__(self, detail=None, headers=None, comment=None):
+        assert self.code, "Do not directly instantiate abstract exceptions."
+        assert isinstance(headers, (type(None), list)), (
+            "headers must be None or a list: %r"
+            % headers)
+        assert isinstance(detail, (type(None), basestring)), (
+            "detail must be None or a string: %r" % detail)
+        assert isinstance(comment, (type(None), basestring)), (
+            "comment must be None or a string: %r" % comment)
+        self.headers = headers or tuple()
+        for req in self.required_headers:
+            assert headers and has_header(headers, req), (
+                "Exception %s must be passed the header %r "
+                "(got headers: %r)"
+                % (self.__class__.__name__, req, headers))
+        if detail is not None:
+            self.detail = detail
+        if comment is not None:
+            self.comment = comment
+        Exception.__init__(self,"%s %s\n%s\n%s\n" % (
+            self.code, self.title, self.explanation, self.detail))
+
+    def make_body(self, environ, template, escfunc, comment_escfunc=None):
+        comment_escfunc = comment_escfunc or escfunc
+        args = {'explanation': escfunc(self.explanation),
+                'detail': escfunc(self.detail),
+                'comment': comment_escfunc(self.comment)}
+        if HTTPException.template != self.template:
+            for (k, v) in environ.items():
+                args[k] = escfunc(v)
+            if self.headers:
+                for (k, v) in self.headers:
+                    args[k.lower()] = escfunc(v)
+        for key, value in args.items():
+            if isinstance(value, unicode):
+                args[key] = value.encode('utf8', 'xmlcharrefreplace')
+        return template % args
+
+    def plain(self, environ):
+        """ text/plain representation of the exception """
+        body = self.make_body(environ, strip_html(self.template), no_quote, comment_quote)
+        return ('%s %s\r\n%s\r\n' % (self.code, self.title, body))
+
+    def html(self, environ):
+        """ text/html representation of the exception """
+        body = self.make_body(environ, self.template, html_quote, comment_quote)
+        return TEMPLATE % {
+                   'title': self.title,
+                   'code': self.code,
+                   'server': SERVER_NAME,
+                   'body': body }
+
+    def prepare_content(self, environ):
+        if self.headers:
+            headers = list(self.headers)
+        else:
+            headers = []
+        if 'html' in environ.get('HTTP_ACCEPT','') or \
+            '*/*' in environ.get('HTTP_ACCEPT',''):
+            replace_header(headers, 'content-type', 'text/html')
+            content = self.html(environ)
+        else:
+            replace_header(headers, 'content-type', 'text/plain')
+            content = self.plain(environ)
+        if isinstance(content, unicode):
+            content = content.encode('utf8')
+            cur_content_type = (
+                header_value(headers, 'content-type')
+                or 'text/html')
+            replace_header(
+                headers, 'content-type',
+                cur_content_type + '; charset=utf8')
+        return headers, content
+
+    def response(self, environ):
+        from paste.wsgiwrappers import WSGIResponse
+        headers, content = self.prepare_content(environ)
+        resp = WSGIResponse(code=self.code, content=content)
+        resp.headers = resp.headers.fromlist(headers)
+        return resp
+
+    def wsgi_application(self, environ, start_response, exc_info=None):
+        """
+        This exception as a WSGI application
+        """
+        headers, content = self.prepare_content(environ)
+        start_response('%s %s' % (self.code, self.title),
+                       headers,
+                       exc_info)
+        return [content]
+
+    __call__ = wsgi_application
+
+    def __repr__(self):
+        return '<%s %s; code=%s>' % (self.__class__.__name__,
+                                     self.title, self.code)
+
+class HTTPError(HTTPException):
+    """
+    base class for status codes in the 400's and 500's
+
+    This is an exception which indicates that an error has occurred,
+    and that any work in progress should not be committed.  These are
+    typically results in the 400's and 500's.
+    """
+
+#
+# 3xx Redirection
+#
+#  This class of status code indicates that further action needs to be
+#  taken by the user agent in order to fulfill the request. The action
+#  required MAY be carried out by the user agent without interaction with
+#  the user if and only if the method used in the second request is GET or
+#  HEAD. A client SHOULD detect infinite redirection loops, since such
+#  loops generate network traffic for each redirection.
+#
+
+class HTTPRedirection(HTTPException):
+    """
+    base class for 300's status code (redirections)
+
+    This is an abstract base class for 3xx redirection.  It indicates
+    that further action needs to be taken by the user agent in order
+    to fulfill the request.  It does not necessarly signal an error
+    condition.
+    """
+
+class _HTTPMove(HTTPRedirection):
+    """
+    redirections which require a Location field
+
+    Since a 'Location' header is a required attribute of 301, 302, 303,
+    305 and 307 (but not 304), this base class provides the mechanics to
+    make this easy.  While this has the same parameters as HTTPException,
+    if a location is not provided in the headers; it is assumed that the
+    detail _is_ the location (this for backward compatibility, otherwise
+    we'd add a new attribute).
+    """
+    required_headers = ('location',)
+    explanation = 'The resource has been moved to'
+    template = (
+        '%(explanation)s <a href="%(location)s">%(location)s</a>;\r\n'
+        'you should be redirected automatically.\r\n'
+        '%(detail)s\r\n<!-- %(comment)s -->')
+
+    def __init__(self, detail=None, headers=None, comment=None):
+        assert isinstance(headers, (type(None), list))
+        headers = headers or []
+        location = header_value(headers,'location')
+        if not location:
+            location = detail
+            detail = ''
+            headers.append(('location', location))
+        assert location, ("HTTPRedirection specified neither a "
+                          "location in the headers nor did it "
+                          "provide a detail argument.")
+        HTTPRedirection.__init__(self, location, headers, comment)
+        if detail is not None:
+            self.detail = detail
+
+    def relative_redirect(cls, dest_uri, environ, detail=None, headers=None, comment=None):
+        """
+        Create a redirect object with the dest_uri, which may be relative,
+        considering it relative to the uri implied by the given environ.
+        """
+        location = resolve_relative_url(dest_uri, environ)
+        headers = headers or []
+        headers.append(('Location', location))
+        return cls(detail=detail, headers=headers, comment=comment)
+
+    relative_redirect = classmethod(relative_redirect)
+
+    def location(self):
+        for name, value in self.headers:
+            if name.lower() == 'location':
+                return value
+        else:
+            raise KeyError("No location set for %s" % self)
+
+class HTTPMultipleChoices(_HTTPMove):
+    code = 300
+    title = 'Multiple Choices'
+
+class HTTPMovedPermanently(_HTTPMove):
+    code = 301
+    title = 'Moved Permanently'
+
+class HTTPFound(_HTTPMove):
+    code = 302
+    title = 'Found'
+    explanation = 'The resource was found at'
+
+# This one is safe after a POST (the redirected location will be
+# retrieved with GET):
+class HTTPSeeOther(_HTTPMove):
+    code = 303
+    title = 'See Other'
+
+class HTTPNotModified(HTTPRedirection):
+    # @@: but not always (HTTP section 14.18.1)...?
+    # @@: Removed 'date' requirement, as its not required for an ETag
+    # @@: FIXME: This should require either an ETag or a date header
+    code = 304
+    title = 'Not Modified'
+    message = ''
+    # @@: should include date header, optionally other headers
+    # @@: should not return a content body
+    def plain(self, environ):
+        return ''
+    def html(self, environ):
+        """ text/html representation of the exception """
+        return ''
+
+class HTTPUseProxy(_HTTPMove):
+    # @@: OK, not a move, but looks a little like one
+    code = 305
+    title = 'Use Proxy'
+    explanation = (
+        'The resource must be accessed through a proxy '
+        'located at')
+
+class HTTPTemporaryRedirect(_HTTPMove):
+    code = 307
+    title = 'Temporary Redirect'
+
+#
+# 4xx Client Error
+#
+#  The 4xx class of status code is intended for cases in which the client
+#  seems to have erred. Except when responding to a HEAD request, the
+#  server SHOULD include an entity containing an explanation of the error
+#  situation, and whether it is a temporary or permanent condition. These
+#  status codes are applicable to any request method. User agents SHOULD
+#  display any included entity to the user.
+#
+
+class HTTPClientError(HTTPError):
+    """
+    base class for the 400's, where the client is in-error
+
+    This is an error condition in which the client is presumed to be
+    in-error.  This is an expected problem, and thus is not considered
+    a bug.  A server-side traceback is not warranted.  Unless specialized,
+    this is a '400 Bad Request'
+    """
+    code = 400
+    title = 'Bad Request'
+    explanation = ('The server could not comply with the request since\r\n'
+                   'it is either malformed or otherwise incorrect.\r\n')
+
+class HTTPBadRequest(HTTPClientError):
+    pass
+
+class HTTPUnauthorized(HTTPClientError):
+    code = 401
+    title = 'Unauthorized'
+    explanation = (
+        'This server could not verify that you are authorized to\r\n'
+        'access the document you requested.  Either you supplied the\r\n'
+        'wrong credentials (e.g., bad password), or your browser\r\n'
+        'does not understand how to supply the credentials required.\r\n')
+
+class HTTPPaymentRequired(HTTPClientError):
+    code = 402
+    title = 'Payment Required'
+    explanation = ('Access was denied for financial reasons.')
+
+class HTTPForbidden(HTTPClientError):
+    code = 403
+    title = 'Forbidden'
+    explanation = ('Access was denied to this resource.')
+
+class HTTPNotFound(HTTPClientError):
+    code = 404
+    title = 'Not Found'
+    explanation = ('The resource could not be found.')
+
+class HTTPMethodNotAllowed(HTTPClientError):
+    required_headers = ('allow',)
+    code = 405
+    title = 'Method Not Allowed'
+    # override template since we need an environment variable
+    template = ('The method %(REQUEST_METHOD)s is not allowed for '
+                'this resource.\r\n%(detail)s')
+
+class HTTPNotAcceptable(HTTPClientError):
+    code = 406
+    title = 'Not Acceptable'
+    # override template since we need an environment variable
+    template = ('The resource could not be generated that was '
+                'acceptable to your browser (content\r\nof type '
+                '%(HTTP_ACCEPT)s).\r\n%(detail)s')
+
+class HTTPProxyAuthenticationRequired(HTTPClientError):
+    code = 407
+    title = 'Proxy Authentication Required'
+    explanation = ('Authentication /w a local proxy is needed.')
+
+class HTTPRequestTimeout(HTTPClientError):
+    code = 408
+    title = 'Request Timeout'
+    explanation = ('The server has waited too long for the request to '
+                   'be sent by the client.')
+
+class HTTPConflict(HTTPClientError):
+    code = 409
+    title = 'Conflict'
+    explanation = ('There was a conflict when trying to complete '
+                   'your request.')
+
+class HTTPGone(HTTPClientError):
+    code = 410
+    title = 'Gone'
+    explanation = ('This resource is no longer available.  No forwarding '
+                   'address is given.')
+
+class HTTPLengthRequired(HTTPClientError):
+    code = 411
+    title = 'Length Required'
+    explanation = ('Content-Length header required.')
+
+class HTTPPreconditionFailed(HTTPClientError):
+    code = 412
+    title = 'Precondition Failed'
+    explanation = ('Request precondition failed.')
+
+class HTTPRequestEntityTooLarge(HTTPClientError):
+    code = 413
+    title = 'Request Entity Too Large'
+    explanation = ('The body of your request was too large for this server.')
+
+class HTTPRequestURITooLong(HTTPClientError):
+    code = 414
+    title = 'Request-URI Too Long'
+    explanation = ('The request URI was too long for this server.')
+
+class HTTPUnsupportedMediaType(HTTPClientError):
+    code = 415
+    title = 'Unsupported Media Type'
+    # override template since we need an environment variable
+    template = ('The request media type %(CONTENT_TYPE)s is not '
+                'supported by this server.\r\n%(detail)s')
+
+class HTTPRequestRangeNotSatisfiable(HTTPClientError):
+    code = 416
+    title = 'Request Range Not Satisfiable'
+    explanation = ('The Range requested is not available.')
+
+class HTTPExpectationFailed(HTTPClientError):
+    code = 417
+    title = 'Expectation Failed'
+    explanation = ('Expectation failed.')
+
+#
+# 5xx Server Error
+#
+#  Response status codes beginning with the digit "5" indicate cases in
+#  which the server is aware that it has erred or is incapable of
+#  performing the request. Except when responding to a HEAD request, the
+#  server SHOULD include an entity containing an explanation of the error
+#  situation, and whether it is a temporary or permanent condition. User
+#  agents SHOULD display any included entity to the user. These response
+#  codes are applicable to any request method.
+#
+
+class HTTPServerError(HTTPError):
+    """
+    base class for the 500's, where the server is in-error
+
+    This is an error condition in which the server is presumed to be
+    in-error.  This is usually unexpected, and thus requires a traceback;
+    ideally, opening a support ticket for the customer. Unless specialized,
+    this is a '500 Internal Server Error'
+    """
+    code = 500
+    title = 'Internal Server Error'
+    explanation = (
+      'The server has either erred or is incapable of performing\r\n'
+      'the requested operation.\r\n')
+
+class HTTPInternalServerError(HTTPServerError):
+    pass
+
+class HTTPNotImplemented(HTTPServerError):
+    code = 501
+    title = 'Not Implemented'
+    # override template since we need an environment variable
+    template = ('The request method %(REQUEST_METHOD)s is not implemented '
+                'for this server.\r\n%(detail)s')
+
+class HTTPBadGateway(HTTPServerError):
+    code = 502
+    title = 'Bad Gateway'
+    explanation = ('Bad gateway.')
+
+class HTTPServiceUnavailable(HTTPServerError):
+    code = 503
+    title = 'Service Unavailable'
+    explanation = ('The server is currently unavailable. '
+                   'Please try again at a later time.')
+
+class HTTPGatewayTimeout(HTTPServerError):
+    code = 504
+    title = 'Gateway Timeout'
+    explanation = ('The gateway has timed out.')
+
+class HTTPVersionNotSupported(HTTPServerError):
+    code = 505
+    title = 'HTTP Version Not Supported'
+    explanation = ('The HTTP version is not supported.')
+
+# abstract HTTP related exceptions
+__all__ = ['HTTPException', 'HTTPRedirection', 'HTTPError' ]
+
+_exceptions = {}
+for name, value in globals().items():
+    if (isinstance(value, (type, types.ClassType)) and
+        issubclass(value, HTTPException) and
+        value.code):
+        _exceptions[value.code] = value
+        __all__.append(name)
+
+def get_exception(code):
+    return _exceptions[code]
+
+############################################################
+## Middleware implementation:
+############################################################
+
+class HTTPExceptionHandler(object):
+    """
+    catches exceptions and turns them into proper HTTP responses
+
+    This middleware catches any exceptions (which are subclasses of
+    ``HTTPException``) and turns them into proper HTTP responses.
+    Note if the headers have already been sent, the stack trace is
+    always maintained as this indicates a programming error.
+
+    Note that you must raise the exception before returning the
+    app_iter, and you cannot use this with generator apps that don't
+    raise an exception until after their app_iter is iterated over.
+    """
+
+    def __init__(self, application, warning_level=None):
+        assert not warning_level or ( warning_level > 99 and
+                                      warning_level < 600)
+        if warning_level is not None:
+            import warnings
+            warnings.warn('The warning_level parameter is not used or supported',
+                          DeprecationWarning, 2)
+        self.warning_level = warning_level or 500
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        environ['paste.httpexceptions'] = self
+        environ.setdefault('paste.expected_exceptions',
+                           []).append(HTTPException)
+        try:
+            return self.application(environ, start_response)
+        except HTTPException, exc:
+            return exc(environ, start_response)
+
+def middleware(*args, **kw):
+    import warnings
+    # deprecated 13 dec 2005
+    warnings.warn('httpexceptions.middleware is deprecated; use '
+                  'make_middleware or HTTPExceptionHandler instead',
+                  DeprecationWarning, 2)
+    return make_middleware(*args, **kw)
+
+def make_middleware(app, global_conf=None, warning_level=None):
+    """
+    ``httpexceptions`` middleware; this catches any
+    ``paste.httpexceptions.HTTPException`` exceptions (exceptions like
+    ``HTTPNotFound``, ``HTTPMovedPermanently``, etc) and turns them
+    into proper HTTP responses.
+
+    ``warning_level`` can be an integer corresponding to an HTTP code.
+    Any code over that value will be passed 'up' the chain, potentially
+    reported on by another piece of middleware.
+    """
+    if warning_level:
+        warning_level = int(warning_level)
+    return HTTPExceptionHandler(app, warning_level=warning_level)
+
+__all__.extend(['HTTPExceptionHandler', 'get_exception'])

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpheaders.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpheaders.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpheaders.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1097 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Ian Bicking, Clark C. Evans and contributors
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# Some of this code was funded by: http://prometheusresearch.com
+"""
+HTTP Message Header Fields (see RFC 4229)
+
+This contains general support for HTTP/1.1 message headers [1]_ in a
+manner that supports WSGI ``environ`` [2]_ and ``response_headers``
+[3]_. Specifically, this module defines a ``HTTPHeader`` class whose
+instances correspond to field-name items.  The actual field-content for
+the message-header is stored in the appropriate WSGI collection (either
+the ``environ`` for requests, or ``response_headers`` for responses).
+
+Each ``HTTPHeader`` instance is a callable (defining ``__call__``)
+that takes one of the following:
+
+  - an ``environ`` dictionary, returning the corresponding header
+    value by according to the WSGI's ``HTTP_`` prefix mechanism, e.g.,
+    ``USER_AGENT(environ)`` returns ``environ.get('HTTP_USER_AGENT')``
+
+  - a ``response_headers`` list, giving a comma-delimited string for
+    each corresponding ``header_value`` tuple entries (see below).
+
+  - a sequence of string ``*args`` that are comma-delimited into
+    a single string value: ``CONTENT_TYPE("text/html","text/plain")``
+    returns ``"text/html, text/plain"``
+
+  - a set of ``**kwargs`` keyword arguments that are used to create
+    a header value, in a manner dependent upon the particular header in
+    question (to make value construction easier and error-free):
+    ``CONTENT_DISPOSITION(max_age=CONTENT_DISPOSITION.ONEWEEK)``
+    returns ``"public, max-age=60480"``
+
+Each ``HTTPHeader`` instance also provides several methods to act on
+a WSGI collection, for removing and setting header values.
+
+  ``delete(collection)``
+
+    This method removes all entries of the corresponding header from
+    the given collection (``environ`` or ``response_headers``), e.g.,
+    ``USER_AGENT.delete(environ)`` deletes the 'HTTP_USER_AGENT' entry
+    from the ``environ``.
+
+  ``update(collection, *args, **kwargs)``
+
+    This method does an in-place replacement of the given header entry,
+    for example: ``CONTENT_LENGTH(response_headers,len(body))``
+
+    The first argument is a valid ``environ`` dictionary or
+    ``response_headers`` list; remaining arguments are passed on to
+    ``__call__(*args, **kwargs)`` for value construction.
+
+  ``apply(collection, **kwargs)``
+
+    This method is similar to update, only that it may affect other
+    headers.  For example, according to recommendations in RFC 2616,
+    certain Cache-Control configurations should also set the
+    ``Expires`` header for HTTP/1.0 clients. By default, ``apply()``
+    is simply ``update()`` but limited to keyword arguments.
+
+This particular approach to managing headers within a WSGI collection
+has several advantages:
+
+  1. Typos in the header name are easily detected since they become a
+     ``NameError`` when executed.  The approach of using header strings
+     directly can be problematic; for example, the following should
+     return ``None`` : ``environ.get("HTTP_ACCEPT_LANGUAGES")``
+
+  2. For specific headers with validation, using ``__call__`` will
+     result in an automatic header value check.  For example, the
+     _ContentDisposition header will reject a value having ``maxage``
+     or ``max_age`` (the appropriate parameter is ``max-age`` ).
+
+  3. When appending/replacing headers, the field-name has the suggested
+     RFC capitalization (e.g. ``Content-Type`` or ``ETag``) for
+     user-agents that incorrectly use case-sensitive matches.
+
+  4. Some headers (such as ``Content-Type``) are 0, that is,
+     only one entry of this type may occur in a given set of
+     ``response_headers``.  This module knows about those cases and
+     enforces this cardinality constraint.
+
+  5. The exact details of WSGI header management are abstracted so
+     the programmer need not worry about operational differences
+     between ``environ`` dictionary or ``response_headers`` list.
+
+  6. Sorting of ``HTTPHeaders`` is done following the RFC suggestion
+     that general-headers come first, followed by request and response
+     headers, and finishing with entity-headers.
+
+  7. Special care is given to exceptional cases such as Set-Cookie
+     which violates the RFC's recommendation about combining header
+     content into a single entry using comma separation.
+
+A particular difficulty with HTTP message headers is a categorization
+of sorts as described in section 4.2:
+
+    Multiple message-header fields with the same field-name MAY be
+    present in a message if and only if the entire field-value for
+    that header field is defined as a comma-separated list [i.e.,
+    #(values)]. It MUST be possible to combine the multiple header
+    fields into one "field-name: field-value" pair, without changing
+    the semantics of the message, by appending each subsequent
+    field-value to the first, each separated by a comma.
+
+This creates three fundamentally different kinds of headers:
+
+  - Those that do not have a #(values) production, and hence are
+    singular and may only occur once in a set of response fields;
+    this case is handled by the ``_SingleValueHeader`` subclass.
+
+  - Those which have the #(values) production and follow the
+    combining rule outlined above; our ``_MultiValueHeader`` case.
+
+  - Those which are multi-valued, but cannot be combined (such as the
+    ``Set-Cookie`` header due to its ``Expires`` parameter); or where
+    combining them into a single header entry would cause common
+    user-agents to fail (``WWW-Authenticate``, ``Warning``) since
+    they fail to handle dates even when properly quoted. This case
+    is handled by ``_MultiEntryHeader``.
+
+Since this project does not have time to provide rigorous support
+and validation for all headers, it does a basic construction of
+headers listed in RFC 2616 (plus a few others) so that they can
+be obtained by simply doing ``from paste.httpheaders import *``;
+the name of the header instance is the "common name" less any
+dashes to give CamelCase style names.
+
+.. [1] http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.2
+.. [2] http://www.python.org/peps/pep-0333.html#environ-variables
+.. [3] http://www.python.org/peps/pep-0333.html#the-start-response-callable
+
+"""
+import mimetypes
+import urllib2
+import re
+from rfc822 import formatdate, parsedate_tz, mktime_tz
+from time import time as now
+from httpexceptions import HTTPBadRequest
+
+__all__ = ['get_header', 'list_headers', 'normalize_headers',
+           'HTTPHeader', 'EnvironVariable' ]
+
+class EnvironVariable(str):
+    """
+    a CGI ``environ`` variable as described by WSGI
+
+    This is a helper object so that standard WSGI ``environ`` variables
+    can be extracted w/o syntax error possibility.
+    """
+    def __call__(self, environ):
+        return environ.get(self,'')
+    def __repr__(self):
+        return '<EnvironVariable %s>' % self
+    def update(self, environ, value):
+        environ[self] = value
+REMOTE_USER    = EnvironVariable("REMOTE_USER")
+REMOTE_SESSION = EnvironVariable("REMOTE_SESSION")
+AUTH_TYPE      = EnvironVariable("AUTH_TYPE")
+REQUEST_METHOD = EnvironVariable("REQUEST_METHOD")
+SCRIPT_NAME    = EnvironVariable("SCRIPT_NAME")
+PATH_INFO      = EnvironVariable("PATH_INFO")
+
+for _name, _obj in globals().items():
+    if isinstance(_obj, EnvironVariable):
+        __all__.append(_name)
+
+_headers = {}
+
+class HTTPHeader(object):
+    """
+    an HTTP header
+
+    HTTPHeader instances represent a particular ``field-name`` of an
+    HTTP message header. They do not hold a field-value, but instead
+    provide operations that work on is corresponding values.  Storage
+    of the actual field values is done with WSGI ``environ`` or
+    ``response_headers`` as appropriate.  Typically, a sub-classes that
+    represent a specific HTTP header, such as _ContentDisposition, are
+    0.  Once constructed the HTTPHeader instances themselves
+    are immutable and stateless.
+
+    For purposes of documentation a "container" refers to either a
+    WSGI ``environ`` dictionary, or a ``response_headers`` list.
+
+    Member variables (and correspondingly constructor arguments).
+
+      ``name``
+
+          the ``field-name`` of the header, in "common form"
+          as presented in RFC 2616; e.g. 'Content-Type'
+
+      ``category``
+
+          one of 'general', 'request', 'response', or 'entity'
+
+      ``version``
+
+          version of HTTP (informational) with which the header should
+          be recognized
+
+      ``sort_order``
+
+          sorting order to be applied before sorting on
+          field-name when ordering headers in a response
+
+    Special Methods:
+
+       ``__call__``
+
+           The primary method of the HTTPHeader instance is to make
+           it a callable, it takes either a collection, a string value,
+           or keyword arguments and attempts to find/construct a valid
+           field-value
+
+       ``__lt__``
+
+           This method is used so that HTTPHeader objects can be
+           sorted in a manner suggested by RFC 2616.
+
+       ``__str__``
+
+           The string-value for instances of this class is
+           the ``field-name``.
+
+    Primary Methods:
+
+       ``delete()``
+
+           remove the all occurrences (if any) of the given
+           header in the collection provided
+
+       ``update()``
+
+           replaces (if they exist) all field-value items
+           in the given collection with the value provided
+
+       ``tuples()``
+
+           returns a set of (field-name, field-value) tuples
+           5 for extending ``response_headers``
+
+    Custom Methods (these may not be implemented):
+
+       ``apply()``
+
+           similar to ``update``, but with two differences; first,
+           only keyword arguments can be used, and second, specific
+           sub-classes may introduce side-effects
+
+       ``parse()``
+
+           converts a string value of the header into a more usable
+           form, such as time in seconds for a date header, etc.
+
+    The collected versions of initialized header instances are immediately
+    registered and accessible through the ``get_header`` function.  Do not
+    inherit from this directly, use one of ``_SingleValueHeader``,
+    ``_MultiValueHeader``, or ``_MultiEntryHeader`` as appropriate.
+    """
+
+    #
+    # Things which can be customized
+    #
+    version = '1.1'
+    category = 'general'
+    reference = ''
+    extensions = {}
+
+    def compose(self, **kwargs):
+        """
+        build header value from keyword arguments
+
+        This method is used to build the corresponding header value when
+        keyword arguments (or no arguments) were provided.  The result
+        should be a sequence of values.  For example, the ``Expires``
+        header takes a keyword argument ``time`` (e.g. time.time()) from
+        which it returns a the corresponding date.
+        """
+        raise NotImplementedError()
+
+    def parse(self, *args, **kwargs):
+        """
+        convert raw header value into more usable form
+
+        This method invokes ``values()`` with the arguments provided,
+        parses the header results, and then returns a header-specific
+        data structure corresponding to the header.  For example, the
+        ``Expires`` header returns seconds (as returned by time.time())
+        """
+        raise NotImplementedError()
+
+    def apply(self, collection, **kwargs):
+        """
+        update the collection /w header value (may have side effects)
+
+        This method is similar to ``update`` only that usage may result
+        in other headers being changed as recommended by the corresponding
+        specification.  The return value is defined by the particular
+        sub-class. For example, the ``_CacheControl.apply()`` sets the
+        ``Expires`` header in addition to its normal behavior.
+        """
+        self.update(collection, **kwargs)
+
+    #
+    # Things which are standardized (mostly)
+    #
+    def __new__(cls, name, category=None, reference=None, version=None):
+        """
+        construct a new ``HTTPHeader`` instance
+
+        We use the ``__new__`` operator to ensure that only one
+        ``HTTPHeader`` instance exists for each field-name, and to
+        register the header so that it can be found/enumerated.
+        """
+        self = get_header(name, raiseError=False)
+        if self:
+            # Allow the registration to happen again, but assert
+            # that everything is identical.
+            assert self.name == name, \
+                "duplicate registration with different capitalization"
+            assert self.category == category, \
+                "duplicate registration with different category"
+            assert cls == self.__class__, \
+                "duplicate registration with different class"
+            return self
+
+        self = object.__new__(cls)
+        self.name = name
+        assert isinstance(self.name, str)
+        self.category = category or self.category
+        self.version  = version or self.version
+        self.reference = reference or self.reference
+        _headers[self.name.lower()] = self
+        self.sort_order = {'general': 1, 'request': 2,
+                           'response': 3, 'entity': 4 }[self.category]
+        self._environ_name = getattr(self, '_environ_name',
+                                'HTTP_'+ self.name.upper().replace("-","_"))
+        self._headers_name = getattr(self, '_headers_name',
+                                 self.name.lower())
+        assert self.version in ('1.1', '1.0', '0.9')
+        return self
+
+    def __str__(self):
+        return self.name
+
+    def __lt__(self, other):
+        """
+        sort header instances as specified by RFC 2616
+
+        Re-define sorting so that general headers are first, followed
+        by request/response headers, and then entity headers.  The
+        list.sort() methods use the less-than operator for this purpose.
+        """
+        if isinstance(other, HTTPHeader):
+            if self.sort_order != other.sort_order:
+                return self.sort_order < other.sort_order
+            return self.name < other.name
+        return False
+
+    def __repr__(self):
+        ref = self.reference and (' (%s)' % self.reference) or ''
+        return '<%s %s%s>' % (self.__class__.__name__, self.name, ref)
+
+    def values(self, *args, **kwargs):
+        """
+        find/construct field-value(s) for the given header
+
+        Resolution is done according to the following arguments:
+
+        - If only keyword arguments are given, then this is equivalent
+          to ``compose(**kwargs)``.
+
+        - If the first (and only) argument is a dict, it is assumed
+          to be a WSGI ``environ`` and the result of the corresponding
+          ``HTTP_`` entry is returned.
+
+        - If the first (and only) argument is a list, it is assumed
+          to be a WSGI ``response_headers`` and the field-value(s)
+          for this header are collected and returned.
+
+        - In all other cases, the arguments are collected, checked that
+          they are string values, possibly verified by the header's
+          logic, and returned.
+
+        At this time it is an error to provide keyword arguments if args
+        is present (this might change).  It is an error to provide both
+        a WSGI object and also string arguments.  If no arguments are
+        provided, then ``compose()`` is called to provide a default
+        value for the header; if there is not default it is an error.
+        """
+        if not args:
+            return self.compose(**kwargs)
+        if list == type(args[0]):
+            assert 1 == len(args)
+            result = []
+            name = self.name.lower()
+            for value in [value for header, value in args[0]
+                         if header.lower() == name]:
+                result.append(value)
+            return result
+        if dict == type(args[0]):
+            assert 1 == len(args) and 'wsgi.version' in args[0]
+            value = args[0].get(self._environ_name)
+            if not value:
+                return ()
+            return (value,)
+        for item in args:
+            assert not type(item) in (dict, list)
+        return args
+
+    def __call__(self, *args, **kwargs):
+        """
+        converts ``values()`` into a string value
+
+        This method converts the results of ``values()`` into a string
+        value for common usage.  By default, it is asserted that only
+        one value exists; if you need to access all values then either
+        call ``values()`` directly, or inherit ``_MultiValueHeader``
+        which overrides this method to return a comma separated list of
+        values as described by section 4.2 of RFC 2616.
+        """
+        values = self.values(*args, **kwargs)
+        assert isinstance(values, (tuple, list))
+        if not values:
+            return ''
+        assert len(values) == 1, "more than one value: %s" % repr(values)
+        return str(values[0]).strip()
+
+    def delete(self, collection):
+        """
+        removes all occurances of the header from the collection provided
+        """
+        if type(collection) == dict:
+            if self._environ_name in collection:
+                del collection[self._environ_name]
+            return self
+        assert list == type(collection)
+        i = 0
+        while i < len(collection):
+            if collection[i][0].lower() == self._headers_name:
+                del collection[i]
+                continue
+            i += 1
+
+    def update(self, collection, *args, **kwargs):
+        """
+        updates the collection with the provided header value
+
+        This method replaces (in-place when possible) all occurrences of
+        the given header with the provided value.  If no value is
+        provided, this is the same as ``remove`` (note that this case
+        can only occur if the target is a collection w/o a corresponding
+        header value). The return value is the new header value (which
+        could be a list for ``_MultiEntryHeader`` instances).
+        """
+        value = self.__call__(*args, **kwargs)
+        if not value:
+            self.delete(collection)
+            return
+        if type(collection) == dict:
+            collection[self._environ_name] = value
+            return
+        assert list == type(collection)
+        i = 0
+        found = False
+        while i < len(collection):
+            if collection[i][0].lower() == self._headers_name:
+                if found:
+                    del collection[i]
+                    continue
+                collection[i] = (self.name, value)
+                found = True
+            i += 1
+        if not found:
+            collection.append((self.name, value))
+
+    def tuples(self, *args, **kwargs):
+        value = self.__call__(*args, **kwargs)
+        if not value:
+            return ()
+        return [(self.name, value)]
+
+class _SingleValueHeader(HTTPHeader):
+    """
+    a ``HTTPHeader`` with exactly a single value
+
+    This is the default behavior of ``HTTPHeader`` where returning a
+    the string-value of headers via ``__call__`` assumes that only
+    a single value exists.
+    """
+    pass
+
+class _MultiValueHeader(HTTPHeader):
+    """
+    a ``HTTPHeader`` with one or more values
+
+    The field-value for these header instances is is allowed to be more
+    than one value; whereby the ``__call__`` method returns a comma
+    separated list as described by section 4.2 of RFC 2616.
+    """
+
+    def __call__(self, *args, **kwargs):
+        results = self.values(*args, **kwargs)
+        if not results:
+            return ''
+        return ", ".join([str(v).strip() for v in results])
+
+    def parse(self, *args, **kwargs):
+        value = self.__call__(*args, **kwargs)
+        values = value.split(',')
+        return [
+            v.strip() for v in values
+            if v.strip()]
+
+class _MultiEntryHeader(HTTPHeader):
+    """
+    a multi-value ``HTTPHeader`` where items cannot be combined with a comma
+
+    This header is multi-valued, but the values should not be combined
+    with a comma since the header is not in compliance with RFC 2616
+    (Set-Cookie due to Expires parameter) or which common user-agents do
+    not behave well when the header values are combined.
+    """
+
+    def update(self, collection, *args, **kwargs):
+        assert list == type(collection), "``environ`` may not be updated"
+        self.delete(collection)
+        collection.extend(self.tuples(*args, **kwargs))
+
+    def tuples(self, *args, **kwargs):
+        values = self.values(*args, **kwargs)
+        if not values:
+            return ()
+        return [(self.name, value.strip()) for value in values]
+
+def get_header(name, raiseError=True):
+    """
+    find the given ``HTTPHeader`` instance
+
+    This function finds the corresponding ``HTTPHeader`` for the
+    ``name`` provided.  So that python-style names can be used,
+    underscores are converted to dashes before the lookup.
+    """
+    retval = _headers.get(str(name).strip().lower().replace("_","-"))
+    if not retval and raiseError:
+        raise AssertionError("'%s' is an unknown header" % name)
+    return retval
+
+def list_headers(general=None, request=None, response=None, entity=None):
+    " list all headers for a given category "
+    if not (general or request or response or entity):
+        general = request = response = entity = True
+    search = []
+    for (bool, strval) in ((general, 'general'), (request, 'request'),
+                           (response, 'response'), (entity, 'entity')):
+        if bool:
+            search.append(strval)
+    return [head for head in _headers.values() if head.category in search]
+
+def normalize_headers(response_headers, strict=True):
+    """
+    sort headers as suggested by  RFC 2616
+
+    This alters the underlying response_headers to use the common
+    name for each header; as well as sorting them with general
+    headers first, followed by request/response headers, then
+    entity headers, and unknown headers last.
+    """
+    category = {}
+    for idx in range(len(response_headers)):
+        (key, val) = response_headers[idx]
+        head = get_header(key, strict)
+        if not head:
+            newhead = '-'.join([x.capitalize() for x in
+                                key.replace("_","-").split("-")])
+            response_headers[idx] = (newhead, val)
+            category[newhead] = 4
+            continue
+        response_headers[idx] = (str(head), val)
+        category[str(head)] = head.sort_order
+    def compare(a, b):
+        ac = category[a[0]]
+        bc = category[b[0]]
+        if ac == bc:
+            return cmp(a[0], b[0])
+        return cmp(ac, bc)
+    response_headers.sort(compare)
+
+class _DateHeader(_SingleValueHeader):
+    """
+    handle date-based headers
+
+    This extends the ``_SingleValueHeader`` object with specific
+    treatment of time values:
+
+    - It overrides ``compose`` to provide a sole keyword argument
+      ``time`` which is an offset in seconds from the current time.
+
+    - A ``time`` method is provided which parses the given value
+      and returns the current time value.
+    """
+
+    def compose(self, time=None, delta=None):
+        time = time or now()
+        if delta:
+            assert type(delta) == int
+            time += delta
+        return (formatdate(time),)
+
+    def parse(self, *args, **kwargs):
+        """ return the time value (in seconds since 1970) """
+        value = self.__call__(*args, **kwargs)
+        if value:
+            try:
+                return mktime_tz(parsedate_tz(value))
+            except (TypeError, OverflowError):
+                raise HTTPBadRequest((
+                    "Received an ill-formed timestamp for %s: %s\r\n") %
+                    (self.name, value))
+
+#
+# Following are specific HTTP headers. Since these classes are mostly
+# singletons, there is no point in keeping the class around once it has
+# been instantiated, so we use the same name.
+#
+
+class _CacheControl(_MultiValueHeader):
+    """
+    Cache-Control, RFC 2616 14.9  (use ``CACHE_CONTROL``)
+
+    This header can be constructed (using keyword arguments), by
+    first specifying one of the following mechanisms:
+
+      ``public``
+
+          if True, this argument specifies that the
+          response, as a whole, may be cashed.
+
+      ``private``
+
+          if True, this argument specifies that the response, as a
+          whole, may be cashed; this implementation does not support
+          the enumeration of private fields
+
+      ``no_cache``
+
+          if True, this argument specifies that the response, as a
+          whole, may not be cashed; this implementation does not
+          support the enumeration of private fields
+
+    In general, only one of the above three may be True, the other 2
+    must then be False or None.  If all three are None, then the cache
+    is assumed to be ``public``.  Following one of these mechanism
+    specifiers are various modifiers:
+
+      ``no_store``
+
+          indicates if content may be stored on disk;
+          otherwise cache is limited to memory (note:
+          users can still save the data, this applies
+          to intermediate caches)
+
+      ``max_age``
+
+          the maximum duration (in seconds) for which
+          the content should be cached; if ``no-cache``
+          is specified, this defaults to 0 seconds
+
+      ``s_maxage``
+
+          the maximum duration (in seconds) for which the
+          content should be allowed in a shared cache.
+
+      ``no_transform``
+
+          specifies that an intermediate cache should
+          not convert the content from one type to
+          another (e.g. transform a BMP to a PNG).
+
+      ``extensions``
+
+          gives additional cache-control extensions,
+          such as items like, community="UCI" (14.9.6)
+
+    The usage of ``apply()`` on this header has side-effects. As
+    recommended by RFC 2616, if ``max_age`` is provided, then then the
+    ``Expires`` header is also calculated for HTTP/1.0 clients and
+    proxies (this is done at the time ``apply()`` is called).  For
+    ``no-cache`` and for ``private`` cases, we either do not want the
+    response cached or do not want any response accidently returned to
+    other users; so to prevent this case, we set the ``Expires`` header
+    to the time of the request, signifying to HTTP/1.0 transports that
+    the content isn't to be cached.  If you are using SSL, your
+    communication is already "private", so to work with HTTP/1.0
+    browsers over SSL, consider specifying your cache as ``public`` as
+    the distinction between public and private is moot.
+    """
+
+    # common values for max-age; "good enough" approximates
+    ONE_HOUR  = 60*60
+    ONE_DAY   = ONE_HOUR * 24
+    ONE_WEEK  = ONE_DAY * 7
+    ONE_MONTH = ONE_DAY * 30
+    ONE_YEAR  = ONE_WEEK * 52
+
+    def _compose(self, public=None, private=None, no_cache=None,
+                 no_store=False, max_age=None, s_maxage=None,
+                 no_transform=False, **extensions):
+        assert isinstance(max_age, (type(None), int))
+        assert isinstance(s_maxage, (type(None), int))
+        expires = 0
+        result = []
+        if private is True:
+            assert not public and not no_cache and not s_maxage
+            result.append('private')
+        elif no_cache is True:
+            assert not public and not private and not max_age
+            result.append('no-cache')
+        else:
+            assert public is None or public is True
+            assert not private and not no_cache
+            expires = max_age
+            result.append('public')
+        if no_store:
+            result.append('no-store')
+        if no_transform:
+            result.append('no-transform')
+        if max_age is not None:
+            result.append('max-age=%d' % max_age)
+        if s_maxage is not None:
+            result.append('s-maxage=%d' % s_maxage)
+        for (k, v) in extensions.items():
+            if k not in self.extensions:
+                raise AssertionError("unexpected extension used: '%s'" % k)
+            result.append('%s="%s"' % (k.replace("_", "-"), v))
+        return (result, expires)
+
+    def compose(self, **kwargs):
+        (result, expires) = self._compose(**kwargs)
+        return result
+
+    def apply(self, collection, **kwargs):
+        """ returns the offset expiration in seconds """
+        (result, expires) = self._compose(**kwargs)
+        if expires is not None:
+            EXPIRES.update(collection, delta=expires)
+        self.update(collection, *result)
+        return expires
+
+_CacheControl('Cache-Control', 'general', 'RFC 2616, 14.9')
+
+class _ContentType(_SingleValueHeader):
+    """
+    Content-Type, RFC 2616 section 14.17
+
+    Unlike other headers, use the CGI variable instead.
+    """
+    version = '1.0'
+    _environ_name = 'CONTENT_TYPE'
+
+    # common mimetype constants
+    UNKNOWN    = 'application/octet-stream'
+    TEXT_PLAIN = 'text/plain'
+    TEXT_HTML  = 'text/html'
+    TEXT_XML   = 'text/xml'
+
+    def compose(self, major=None, minor=None, charset=None):
+        if not major:
+            if minor in ('plain', 'html', 'xml'):
+                major = 'text'
+            else:
+                assert not minor and not charset
+                return (self.UNKNOWN,)
+        if not minor:
+            minor = "*"
+        result = "%s/%s" % (major, minor)
+        if charset:
+            result += "; charset=%s" % charset
+        return (result,)
+
+_ContentType('Content-Type', 'entity', 'RFC 2616, 14.17')
+
+class _ContentLength(_SingleValueHeader):
+    """
+    Content-Length, RFC 2616 section 14.13
+
+    Unlike other headers, use the CGI variable instead.
+    """
+    version = "1.0"
+    _environ_name = 'CONTENT_LENGTH'
+
+_ContentLength('Content-Length', 'entity', 'RFC 2616, 14.13')
+
+class _ContentDisposition(_SingleValueHeader):
+    """
+    Content-Disposition, RFC 2183 (use ``CONTENT_DISPOSITION``)
+
+    This header can be constructed (using keyword arguments),
+    by first specifying one of the following mechanisms:
+
+      ``attachment``
+
+          if True, this specifies that the content should not be
+          shown in the browser and should be handled externally,
+          even if the browser could render the content
+
+      ``inline``
+
+         exclusive with attachment; indicates that the content
+         should be rendered in the browser if possible, but
+         otherwise it should be handled externally
+
+    Only one of the above 2 may be True.  If both are None, then
+    the disposition is assumed to be an ``attachment``. These are
+    distinct fields since support for field enumeration may be
+    added in the future.
+
+      ``filename``
+
+          the filename parameter, if any, to be reported; if
+          this is None, then the current object's filename
+          attribute is used
+
+    The usage of ``apply()`` on this header has side-effects. If
+    filename is provided, and Content-Type is not set or is
+    'application/octet-stream', then the mimetypes.guess is used to
+    upgrade the Content-Type setting.
+    """
+
+    def _compose(self, attachment=None, inline=None, filename=None):
+        result = []
+        if inline is True:
+            assert not attachment
+            result.append('inline')
+        else:
+            assert not inline
+            result.append('attachment')
+        if filename:
+            assert '"' not in filename
+            filename = filename.split("/")[-1]
+            filename = filename.split("\\")[-1]
+            result.append('filename="%s"' % filename)
+        return (("; ".join(result),), filename)
+
+    def compose(self, **kwargs):
+        (result, mimetype) = self._compose(**kwargs)
+        return result
+
+    def apply(self, collection, **kwargs):
+        """ return the new Content-Type side-effect value """
+        (result, filename) = self._compose(**kwargs)
+        mimetype = CONTENT_TYPE(collection)
+        if filename and (not mimetype or CONTENT_TYPE.UNKNOWN == mimetype):
+            mimetype, _ = mimetypes.guess_type(filename)
+            if mimetype and CONTENT_TYPE.UNKNOWN != mimetype:
+                CONTENT_TYPE.update(collection, mimetype)
+        self.update(collection, *result)
+        return mimetype
+
+_ContentDisposition('Content-Disposition', 'entity', 'RFC 2183')
+
+class _IfModifiedSince(_DateHeader):
+    """
+    If-Modified-Since, RFC 2616 section 14.25
+    """
+    version = '1.0'
+
+    def __call__(self, *args, **kwargs):
+        """
+        Split the value on ';' incase the header includes extra attributes. E.g.
+        IE 6 is known to send:
+        If-Modified-Since: Sun, 25 Jun 2006 20:36:35 GMT; length=1506
+        """
+        return _DateHeader.__call__(self, *args, **kwargs).split(';', 1)[0]
+
+    def parse(self, *args, **kwargs):
+        value = _DateHeader.parse(self, *args, **kwargs)
+        if value and value > now():
+            raise HTTPBadRequest((
+              "Please check your system clock.\r\n"
+              "According to this server, the time provided in the\r\n"
+              "%s header is in the future.\r\n") % self.name)
+        return value
+_IfModifiedSince('If-Modified-Since', 'request', 'RFC 2616, 14.25')
+
+class _Range(_MultiValueHeader):
+    """
+    Range, RFC 2616 14.35 (use ``RANGE``)
+
+    According to section 14.16, the response to this message should be a
+    206 Partial Content and that if multiple non-overlapping byte ranges
+    are requested (it is an error to request multiple overlapping
+    ranges) the result should be sent as multipart/byteranges mimetype.
+
+    The server should respond with '416 Requested Range Not Satisfiable'
+    if the requested ranges are out-of-bounds.  The specification also
+    indicates that a syntax error in the Range request should result in
+    the header being ignored rather than a '400 Bad Request'.
+    """
+
+    def parse(self, *args, **kwargs):
+        """
+        Returns a tuple (units, list), where list is a sequence of
+        (begin, end) tuples; and end is None if it was not provided.
+        """
+        value = self.__call__(*args, **kwargs)
+        if not value:
+            return None
+        ranges = []
+        last_end   = -1
+        try:
+            (units, range) = value.split("=", 1)
+            units = units.strip().lower()
+            for item in range.split(","):
+                (begin, end) = item.split("-")
+                if not begin.strip():
+                    begin = 0
+                else:
+                    begin = int(begin)
+                if begin <= last_end:
+                    raise ValueError()
+                if not end.strip():
+                    end = None
+                else:
+                    end = int(end)
+                last_end = end
+                ranges.append((begin, end))
+        except ValueError:
+            # In this case where the Range header is malformed,
+            # section 14.16 says to treat the request as if the
+            # Range header was not present.  How do I log this?
+            return None
+        return (units, ranges)
+_Range('Range', 'request', 'RFC 2616, 14.35')
+
+class _AcceptLanguage(_MultiValueHeader):
+    """
+    Accept-Language, RFC 2616 section 14.4
+    """
+
+    def parse(self, *args, **kwargs):
+        """
+        Return a list of language tags sorted by their "q" values.  For example,
+        "en-us,en;q=0.5" should return ``["en-us", "en"]``.  If there is no
+        ``Accept-Language`` header present, default to ``[]``.
+        """
+        header = self.__call__(*args, **kwargs)
+        if header is None:
+            return []
+        langs = [v for v in header.split(",") if v]
+        qs = []
+        for lang in langs:
+            pieces = lang.split(";")
+            lang, params = pieces[0].strip().lower(), pieces[1:]
+            q = 1
+            for param in params:
+                if '=' not in param:
+                    # Malformed request; probably a bot, we'll ignore
+                    continue
+                lvalue, rvalue = param.split("=")
+                lvalue = lvalue.strip().lower()
+                rvalue = rvalue.strip()
+                if lvalue == "q":
+                    q = float(rvalue)
+            qs.append((lang, q))
+        qs.sort(lambda a, b: -cmp(a[1], b[1]))
+        return [lang for (lang, q) in qs]
+_AcceptLanguage('Accept-Language', 'request', 'RFC 2616, 14.4')
+
+class _AcceptRanges(_MultiValueHeader):
+    """
+    Accept-Ranges, RFC 2616 section 14.5
+    """
+    def compose(self, none=None, bytes=None):
+        if bytes:
+            return ('bytes',)
+        return ('none',)
+_AcceptRanges('Accept-Ranges', 'response', 'RFC 2616, 14.5')
+
+class _ContentRange(_SingleValueHeader):
+    """
+    Content-Range, RFC 2616 section 14.6
+    """
+    def compose(self, first_byte=None, last_byte=None, total_length=None):
+        retval = "bytes %d-%d/%d" % (first_byte, last_byte, total_length)
+        assert last_byte == -1 or first_byte <= last_byte
+        assert last_byte  < total_length
+        return (retval,)
+_ContentRange('Content-Range', 'entity', 'RFC 2616, 14.6')
+
+class _Authorization(_SingleValueHeader):
+    """
+    Authorization, RFC 2617 (RFC 2616, 14.8)
+    """
+    def compose(self, digest=None, basic=None, username=None, password=None,
+                challenge=None, path=None, method=None):
+        assert username and password
+        if basic or not challenge:
+            assert not digest
+            userpass = "%s:%s" % (username.strip(), password.strip())
+            return "Basic %s" % userpass.encode('base64').strip()
+        assert challenge and not basic
+        path = path or "/"
+        (_, realm) = challenge.split('realm="')
+        (realm, _) = realm.split('"', 1)
+        auth = urllib2.AbstractDigestAuthHandler()
+        auth.add_password(realm, path, username, password)
+        (token, challenge) = challenge.split(' ', 1)
+        chal = urllib2.parse_keqv_list(urllib2.parse_http_list(challenge))
+        class FakeRequest(object):
+            def get_full_url(self):
+                return path
+            def has_data(self):
+                return False
+            def get_method(self):
+                return method or "GET"
+            get_selector = get_full_url
+        retval = "Digest %s" % auth.get_authorization(FakeRequest(), chal)
+        return (retval,)
+_Authorization('Authorization', 'request', 'RFC 2617')
+
+#
+# For now, construct a minimalistic version of the field-names; at a
+# later date more complicated headers may sprout content constructors.
+# The items commented out have concrete variants.
+#
+for (name,              category, version, style,      comment) in \
+(("Accept"             ,'request' ,'1.1','multi-value','RFC 2616, 14.1' )
+,("Accept-Charset"     ,'request' ,'1.1','multi-value','RFC 2616, 14.2' )
+,("Accept-Encoding"    ,'request' ,'1.1','multi-value','RFC 2616, 14.3' )
+#,("Accept-Language"    ,'request' ,'1.1','multi-value','RFC 2616, 14.4' )
+#,("Accept-Ranges"      ,'response','1.1','multi-value','RFC 2616, 14.5' )
+,("Age"                ,'response','1.1','singular'   ,'RFC 2616, 14.6' )
+,("Allow"              ,'entity'  ,'1.0','multi-value','RFC 2616, 14.7' )
+#,("Authorization"      ,'request' ,'1.0','singular'   ,'RFC 2616, 14.8' )
+#,("Cache-Control"      ,'general' ,'1.1','multi-value','RFC 2616, 14.9' )
+,("Cookie"             ,'request' ,'1.0','multi-value','RFC 2109/Netscape')
+,("Connection"         ,'general' ,'1.1','multi-value','RFC 2616, 14.10')
+,("Content-Encoding"   ,'entity'  ,'1.0','multi-value','RFC 2616, 14.11')
+#,("Content-Disposition",'entity'  ,'1.1','multi-value','RFC 2616, 15.5' )
+,("Content-Language"   ,'entity'  ,'1.1','multi-value','RFC 2616, 14.12')
+#,("Content-Length"     ,'entity'  ,'1.0','singular'   ,'RFC 2616, 14.13')
+,("Content-Location"   ,'entity'  ,'1.1','singular'   ,'RFC 2616, 14.14')
+,("Content-MD5"        ,'entity'  ,'1.1','singular'   ,'RFC 2616, 14.15')
+#,("Content-Range"      ,'entity'  ,'1.1','singular'   ,'RFC 2616, 14.16')
+#,("Content-Type"       ,'entity'  ,'1.0','singular'   ,'RFC 2616, 14.17')
+,("Date"               ,'general' ,'1.0','date-header','RFC 2616, 14.18')
+,("ETag"               ,'response','1.1','singular'   ,'RFC 2616, 14.19')
+,("Expect"             ,'request' ,'1.1','multi-value','RFC 2616, 14.20')
+,("Expires"            ,'entity'  ,'1.0','date-header','RFC 2616, 14.21')
+,("From"               ,'request' ,'1.0','singular'   ,'RFC 2616, 14.22')
+,("Host"               ,'request' ,'1.1','singular'   ,'RFC 2616, 14.23')
+,("If-Match"           ,'request' ,'1.1','multi-value','RFC 2616, 14.24')
+#,("If-Modified-Since"  ,'request' ,'1.0','date-header','RFC 2616, 14.25')
+,("If-None-Match"      ,'request' ,'1.1','multi-value','RFC 2616, 14.26')
+,("If-Range"           ,'request' ,'1.1','singular'   ,'RFC 2616, 14.27')
+,("If-Unmodified-Since",'request' ,'1.1','date-header' ,'RFC 2616, 14.28')
+,("Last-Modified"      ,'entity'  ,'1.0','date-header','RFC 2616, 14.29')
+,("Location"           ,'response','1.0','singular'   ,'RFC 2616, 14.30')
+,("Max-Forwards"       ,'request' ,'1.1','singular'   ,'RFC 2616, 14.31')
+,("Pragma"             ,'general' ,'1.0','multi-value','RFC 2616, 14.32')
+,("Proxy-Authenticate" ,'response','1.1','multi-value','RFC 2616, 14.33')
+,("Proxy-Authorization",'request' ,'1.1','singular'   ,'RFC 2616, 14.34')
+#,("Range"              ,'request' ,'1.1','multi-value','RFC 2616, 14.35')
+,("Referer"            ,'request' ,'1.0','singular'   ,'RFC 2616, 14.36')
+,("Retry-After"        ,'response','1.1','singular'   ,'RFC 2616, 14.37')
+,("Server"             ,'response','1.0','singular'   ,'RFC 2616, 14.38')
+,("Set-Cookie"         ,'response','1.0','multi-entry','RFC 2109/Netscape')
+,("TE"                 ,'request' ,'1.1','multi-value','RFC 2616, 14.39')
+,("Trailer"            ,'general' ,'1.1','multi-value','RFC 2616, 14.40')
+,("Transfer-Encoding"  ,'general' ,'1.1','multi-value','RFC 2616, 14.41')
+,("Upgrade"            ,'general' ,'1.1','multi-value','RFC 2616, 14.42')
+,("User-Agent"         ,'request' ,'1.0','singular'   ,'RFC 2616, 14.43')
+,("Vary"               ,'response','1.1','multi-value','RFC 2616, 14.44')
+,("Via"                ,'general' ,'1.1','multi-value','RFC 2616, 14.45')
+,("Warning"            ,'general' ,'1.1','multi-entry','RFC 2616, 14.46')
+,("WWW-Authenticate"   ,'response','1.0','multi-entry','RFC 2616, 14.47')):
+    klass = {'multi-value': _MultiValueHeader,
+             'multi-entry': _MultiEntryHeader,
+             'date-header': _DateHeader,
+             'singular'   : _SingleValueHeader}[style]
+    klass(name, category, comment, version).__doc__ = comment
+    del klass
+
+for head in _headers.values():
+    headname = head.name.replace("-","_").upper()
+    locals()[headname] = head
+    __all__.append(headname)
+
+__pudge_all__ = __all__[:]
+for _name, _obj in globals().items():
+    if isinstance(_obj, type) and issubclass(_obj, HTTPHeader):
+        __pudge_all__.append(_name)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpserver.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpserver.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/httpserver.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1411 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+WSGI HTTP Server
+
+This is a minimalistic WSGI server using Python's built-in BaseHTTPServer;
+if pyOpenSSL is installed, it also provides SSL capabilities.
+"""
+
+# @@: add in protection against HTTP/1.0 clients who claim to
+#     be 1.1 but do not send a Content-Length
+
+# @@: add support for chunked encoding, this is not a 1.1 server
+#     till this is completed.
+
+import atexit
+import traceback
+import socket, sys, threading, urlparse, Queue, urllib
+import posixpath
+import time
+import thread
+import os
+from itertools import count
+from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+from SocketServer import ThreadingMixIn
+from paste.util import converters
+import logging
+try:
+    from paste.util import killthread
+except ImportError:
+    # Not available, probably no ctypes
+    killthread = None
+
+__all__ = ['WSGIHandlerMixin', 'WSGIServer', 'WSGIHandler', 'serve']
+__version__ = "0.5"
+
+class ContinueHook(object):
+    """
+    When a client request includes a 'Expect: 100-continue' header, then
+    it is the responsibility of the server to send 100 Continue when it
+    is ready for the content body.  This allows authentication, access
+    levels, and other exceptions to be detected *before* bandwith is
+    spent on the request body.
+
+    This is a rfile wrapper that implements this functionality by
+    sending 100 Continue to the client immediately after the user
+    requests the content via a read() operation on the rfile stream.
+    After this response is sent, it becomes a pass-through object.
+    """
+
+    def __init__(self, rfile, write):
+        self._ContinueFile_rfile = rfile
+        self._ContinueFile_write = write
+        for attr in ('close', 'closed', 'fileno', 'flush',
+                     'mode', 'bufsize', 'softspace'):
+            if hasattr(rfile, attr):
+                setattr(self, attr, getattr(rfile, attr))
+        for attr in ('read', 'readline', 'readlines'):
+            if hasattr(rfile, attr):
+                setattr(self, attr, getattr(self, '_ContinueFile_' + attr))
+
+    def _ContinueFile_send(self):
+        self._ContinueFile_write("HTTP/1.1 100 Continue\r\n\r\n")
+        rfile = self._ContinueFile_rfile
+        for attr in ('read', 'readline', 'readlines'):
+            if hasattr(rfile, attr):
+                setattr(self, attr, getattr(rfile, attr))
+
+    def _ContinueFile_read(self, size=-1):
+        self._ContinueFile_send()
+        return self._ContinueFile_rfile.read(size)
+
+    def _ContinueFile_readline(self, size=-1):
+        self._ContinueFile_send()
+        return self._ContinueFile_rfile.readline(size)
+
+    def _ContinueFile_readlines(self, sizehint=0):
+        self._ContinueFile_send()
+        return self._ContinueFile_rfile.readlines(sizehint)
+
+class WSGIHandlerMixin:
+    """
+    WSGI mix-in for HTTPRequestHandler
+
+    This class is a mix-in to provide WSGI functionality to any
+    HTTPRequestHandler derivative (as provided in Python's BaseHTTPServer).
+    This assumes a ``wsgi_application`` handler on ``self.server``.
+    """
+    lookup_addresses = True
+
+    def log_request(self, *args, **kwargs):
+        """ disable success request logging
+
+        Logging transactions should not be part of a WSGI server,
+        if you want logging; look at paste.translogger
+        """
+        pass
+
+    def log_message(self, *args, **kwargs):
+        """ disable error message logging
+
+        Logging transactions should not be part of a WSGI server,
+        if you want logging; look at paste.translogger
+        """
+        pass
+
+    def version_string(self):
+        """ behavior that BaseHTTPServer should have had """
+        if not self.sys_version:
+            return self.server_version
+        else:
+            return self.server_version + ' ' + self.sys_version
+
+    def wsgi_write_chunk(self, chunk):
+        """
+        Write a chunk of the output stream; send headers if they
+        have not already been sent.
+        """
+        if not self.wsgi_headers_sent and not self.wsgi_curr_headers:
+            raise RuntimeError(
+                "Content returned before start_response called")
+        if not self.wsgi_headers_sent:
+            self.wsgi_headers_sent = True
+            (status, headers) = self.wsgi_curr_headers
+            code, message = status.split(" ", 1)
+            self.send_response(int(code), message)
+            #
+            # HTTP/1.1 compliance; either send Content-Length or
+            # signal that the connection is being closed.
+            #
+            send_close = True
+            for (k, v) in  headers:
+                lk = k.lower()
+                if 'content-length' == lk:
+                    send_close = False
+                if 'connection' == lk:
+                    if 'close' == v.lower():
+                        self.close_connection = 1
+                        send_close = False
+                self.send_header(k, v)
+            if send_close:
+                self.close_connection = 1
+                self.send_header('Connection', 'close')
+
+            self.end_headers()
+        self.wfile.write(chunk)
+
+    def wsgi_start_response(self, status, response_headers, exc_info=None):
+        if exc_info:
+            try:
+                if self.wsgi_headers_sent:
+                    raise exc_info[0], exc_info[1], exc_info[2]
+                else:
+                    # In this case, we're going to assume that the
+                    # higher-level code is currently handling the
+                    # issue and returning a resonable response.
+                    # self.log_error(repr(exc_info))
+                    pass
+            finally:
+                exc_info = None
+        elif self.wsgi_curr_headers:
+            assert 0, "Attempt to set headers a second time w/o an exc_info"
+        self.wsgi_curr_headers = (status, response_headers)
+        return self.wsgi_write_chunk
+
+    def wsgi_setup(self, environ=None):
+        """
+        Setup the member variables used by this WSGI mixin, including
+        the ``environ`` and status member variables.
+
+        After the basic environment is created; the optional ``environ``
+        argument can be used to override any settings.
+        """
+
+        (scheme, netloc, path, query, fragment) = urlparse.urlsplit(self.path)
+        path = urllib.unquote(path)
+        endslash = path.endswith('/')
+        path = posixpath.normpath(path)
+        if endslash and path != '/':
+            # Put the slash back...
+            path += '/'
+        (server_name, server_port) = self.server.server_address[:2]
+
+        rfile = self.rfile
+        if 'HTTP/1.1' == self.protocol_version and \
+                '100-continue' == self.headers.get('Expect','').lower():
+            rfile = ContinueHook(rfile, self.wfile.write)
+        else:
+            # We can put in the protection to keep from over-reading the
+            # file
+            try:
+                content_length = int(self.headers.get('Content-Length', '0'))
+            except ValueError:
+                content_length = 0
+            if not hasattr(self.connection, 'get_context'):
+                # @@: LimitedLengthFile is currently broken in connection
+                # with SSL (sporatic errors that are diffcult to trace, but
+                # ones that go away when you don't use LimitedLengthFile)
+                rfile = LimitedLengthFile(rfile, content_length)
+
+        remote_address = self.client_address[0]
+        self.wsgi_environ = {
+                'wsgi.version': (1,0)
+               ,'wsgi.url_scheme': 'http'
+               ,'wsgi.input': rfile
+               ,'wsgi.errors': sys.stderr
+               ,'wsgi.multithread': True
+               ,'wsgi.multiprocess': False
+               ,'wsgi.run_once': False
+               # CGI variables required by PEP-333
+               ,'REQUEST_METHOD': self.command
+               ,'SCRIPT_NAME': '' # application is root of server
+               ,'PATH_INFO': path
+               ,'QUERY_STRING': query
+               ,'CONTENT_TYPE': self.headers.get('Content-Type', '')
+               ,'CONTENT_LENGTH': self.headers.get('Content-Length', '0')
+               ,'SERVER_NAME': server_name
+               ,'SERVER_PORT': str(server_port)
+               ,'SERVER_PROTOCOL': self.request_version
+               # CGI not required by PEP-333
+               ,'REMOTE_ADDR': remote_address
+               }
+        if scheme:
+            self.wsgi_environ['paste.httpserver.proxy.scheme'] = scheme
+        if netloc:
+            self.wsgi_environ['paste.httpserver.proxy.host'] = netloc
+
+        if self.lookup_addresses:
+            # @@: make lookup_addreses actually work, at this point
+            #     it has been address_string() is overriden down in
+            #     file and hence is a noop
+            if remote_address.startswith("192.168.") \
+            or remote_address.startswith("10.") \
+            or remote_address.startswith("172.16."):
+                pass
+            else:
+                address_string = None # self.address_string()
+                if address_string:
+                    self.wsgi_environ['REMOTE_HOST'] = address_string
+
+        if hasattr(self.server, 'thread_pool'):
+            # Now that we know what the request was for, we should
+            # tell the thread pool what its worker is working on
+            self.server.thread_pool.worker_tracker[thread.get_ident()][1] = self.wsgi_environ
+            self.wsgi_environ['paste.httpserver.thread_pool'] = self.server.thread_pool
+
+        for k, v in self.headers.items():
+            key = 'HTTP_' + k.replace("-","_").upper()
+            if key in ('HTTP_CONTENT_TYPE','HTTP_CONTENT_LENGTH'):
+                continue
+            self.wsgi_environ[key] = ','.join(self.headers.getheaders(k))
+
+        if hasattr(self.connection,'get_context'):
+            self.wsgi_environ['wsgi.url_scheme'] = 'https'
+            # @@: extract other SSL parameters from pyOpenSSL at...
+            # http://www.modssl.org/docs/2.8/ssl_reference.html#ToC25
+
+        if environ:
+            assert isinstance(environ, dict)
+            self.wsgi_environ.update(environ)
+            if 'on' == environ.get('HTTPS'):
+                self.wsgi_environ['wsgi.url_scheme'] = 'https'
+
+        self.wsgi_curr_headers = None
+        self.wsgi_headers_sent = False
+
+    def wsgi_connection_drop(self, exce, environ=None):
+        """
+        Override this if you're interested in socket exceptions, such
+        as when the user clicks 'Cancel' during a file download.
+        """
+        pass
+
+    def wsgi_execute(self, environ=None):
+        """
+        Invoke the server's ``wsgi_application``.
+        """
+
+        self.wsgi_setup(environ)
+
+        try:
+            result = self.server.wsgi_application(self.wsgi_environ,
+                                                  self.wsgi_start_response)
+            try:
+                for chunk in result:
+                    self.wsgi_write_chunk(chunk)
+                if not self.wsgi_headers_sent:
+                    self.wsgi_write_chunk('')
+            finally:
+                if hasattr(result,'close'):
+                    result.close()
+                result = None
+        except socket.error, exce:
+            self.wsgi_connection_drop(exce, environ)
+            return
+        except:
+            if not self.wsgi_headers_sent:
+                error_msg = "Internal Server Error\n"
+                self.wsgi_curr_headers = (
+                    '500 Internal Server Error',
+                    [('Content-type', 'text/plain'),
+                     ('Content-length', str(len(error_msg)))])
+                self.wsgi_write_chunk("Internal Server Error\n")
+            raise
+
+#
+# SSL Functionality
+#
+# This implementation was motivated by Sebastien Martini's SSL example
+# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473
+#
+try:
+    from OpenSSL import SSL, tsafe
+    SocketErrors = (socket.error, SSL.ZeroReturnError, SSL.SysCallError)
+except ImportError:
+    # Do not require pyOpenSSL to be installed, but disable SSL
+    # functionality in that case.
+    SSL = None
+    SocketErrors = (socket.error,)
+    class SecureHTTPServer(HTTPServer):
+        def __init__(self, server_address, RequestHandlerClass,
+                     ssl_context=None, request_queue_size=None):
+            assert not ssl_context, "pyOpenSSL not installed"
+            HTTPServer.__init__(self, server_address, RequestHandlerClass)
+            if request_queue_size:
+                self.socket.listen(request_queue_size)
+else:
+
+    class _ConnFixer(object):
+        """ wraps a socket connection so it implements makefile """
+        def __init__(self, conn):
+            self.__conn = conn
+        def makefile(self, mode, bufsize):
+            return socket._fileobject(self.__conn, mode, bufsize)
+        def __getattr__(self, attrib):
+            return getattr(self.__conn, attrib)
+
+    class SecureHTTPServer(HTTPServer):
+        """
+        Provides SSL server functionality on top of the BaseHTTPServer
+        by overriding _private_ members of Python's standard
+        distribution. The interface for this instance only changes by
+        adding a an optional ssl_context attribute to the constructor:
+
+              cntx = SSL.Context(SSL.SSLv23_METHOD)
+              cntx.use_privatekey_file("host.pem")
+              cntx.use_certificate_file("host.pem")
+
+        """
+
+        def __init__(self, server_address, RequestHandlerClass,
+                     ssl_context=None, request_queue_size=None):
+            # This overrides the implementation of __init__ in python's
+            # SocketServer.TCPServer (which BaseHTTPServer.HTTPServer
+            # does not override, thankfully).
+            HTTPServer.__init__(self, server_address, RequestHandlerClass)
+            self.socket = socket.socket(self.address_family,
+                                        self.socket_type)
+            self.ssl_context = ssl_context
+            if ssl_context:
+                class TSafeConnection(tsafe.Connection):
+                    def settimeout(self, *args):
+                        self._lock.acquire()
+                        try:
+                            return self._ssl_conn.settimeout(*args)
+                        finally:
+                            self._lock.release()
+                    def gettimeout(self):
+                        self._lock.acquire()
+                        try:
+                            return self._ssl_conn.gettimeout()
+                        finally:
+                            self._lock.release()
+                self.socket = TSafeConnection(ssl_context, self.socket)
+            self.server_bind()
+            if request_queue_size:
+                self.socket.listen(request_queue_size)
+            self.server_activate()
+
+        def get_request(self):
+            # The default SSL request object does not seem to have a
+            # ``makefile(mode, bufsize)`` method as expected by
+            # Socketserver.StreamRequestHandler.
+            (conn, info) = self.socket.accept()
+            if self.ssl_context:
+                conn = _ConnFixer(conn)
+            return (conn, info)
+
+    def _auto_ssl_context():
+        import OpenSSL, time, random
+        pkey = OpenSSL.crypto.PKey()
+        pkey.generate_key(OpenSSL.crypto.TYPE_RSA, 768)
+
+        cert = OpenSSL.crypto.X509()
+
+        cert.set_serial_number(random.randint(0, sys.maxint))
+        cert.gmtime_adj_notBefore(0)
+        cert.gmtime_adj_notAfter(60 * 60 * 24 * 365)
+        cert.get_subject().CN = '*'
+        cert.get_subject().O = 'Dummy Certificate'
+        cert.get_issuer().CN = 'Untrusted Authority'
+        cert.get_issuer().O = 'Self-Signed'
+        cert.set_pubkey(pkey)
+        cert.sign(pkey, 'md5')
+
+        ctx = SSL.Context(SSL.SSLv23_METHOD)
+        ctx.use_privatekey(pkey)
+        ctx.use_certificate(cert)
+
+        return ctx
+
+class WSGIHandler(WSGIHandlerMixin, BaseHTTPRequestHandler):
+    """
+    A WSGI handler that overrides POST, GET and HEAD to delegate
+    requests to the server's ``wsgi_application``.
+    """
+    server_version = 'PasteWSGIServer/' + __version__
+
+    def handle_one_request(self):
+        """Handle a single HTTP request.
+
+        You normally don't need to override this method; see the class
+        __doc__ string for information on how to handle specific HTTP
+        commands such as GET and POST.
+
+        """
+        self.raw_requestline = self.rfile.readline()
+        if not self.raw_requestline:
+            self.close_connection = 1
+            return
+        if not self.parse_request(): # An error code has been sent, just exit
+            return
+        self.wsgi_execute()
+
+    def handle(self):
+        # don't bother logging disconnects while handling a request
+        try:
+            BaseHTTPRequestHandler.handle(self)
+        except SocketErrors, exce:
+            self.wsgi_connection_drop(exce)
+
+    def address_string(self):
+        """Return the client address formatted for logging.
+
+        This is overridden so that no hostname lookup is done.
+        """
+        return ''
+
+class LimitedLengthFile(object):
+    def __init__(self, file, length):
+        self.file = file
+        self.length = length
+        self._consumed = 0
+        if hasattr(self.file, 'seek'):
+            self.seek = self._seek
+
+    def __repr__(self):
+        base_repr = repr(self.file)
+        return base_repr[:-1] + ' length=%s>' % self.length
+
+    def read(self, length=None):
+        left = self.length - self._consumed
+        if length is None:
+            length = left
+        else:
+            length = min(length, left)
+        # next two lines are hnecessary only if read(0) blocks
+        if not left:
+            return ''
+        data = self.file.read(length)
+        self._consumed += len(data)
+        return data
+
+    def readline(self, *args):
+        max_read = self.length - self._consumed
+        if len(args):
+            max_read = min(args[0], max_read)
+        data = self.file.readline(max_read)
+        self._consumed += len(data)
+        return data
+
+    def readlines(self, hint=None):
+        data = self.file.readlines(hint)
+        for chunk in data:
+            self._consumed += len(chunk)
+        return data
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if self.length - self._consumed <= 0:
+            raise StopIteration
+        return self.readline()
+
+    ## Optional methods ##
+
+    def _seek(self, place):
+        self.file.seek(place)
+        self._consumed = place
+
+    def tell(self):
+        if hasattr(self.file, 'tell'):
+            return self.file.tell()
+        else:
+            return self._consumed
+
+class ThreadPool(object):
+    """
+    Generic thread pool with a queue of callables to consume.
+
+    Keeps a notion of the status of its worker threads:
+
+    idle: worker thread with nothing to do
+
+    busy: worker thread doing its job
+
+    hung: worker thread that's been doing a job for too long
+
+    dying: a hung thread that has been killed, but hasn't died quite
+    yet.
+
+    zombie: what was a worker thread that we've tried to kill but
+    isn't dead yet.
+
+    At any time you can call track_threads, to get a dictionary with
+    these keys and lists of thread_ids that fall in that status.  All
+    keys will be present, even if they point to emty lists.
+
+    hung threads are threads that have been busy more than
+    hung_thread_limit seconds.  Hung threads are killed when they live
+    longer than kill_thread_limit seconds.  A thread is then
+    considered dying for dying_limit seconds, if it is still alive
+    after that it is considered a zombie.
+
+    When there are no idle workers and a request comes in, another
+    worker *may* be spawned.  If there are less than spawn_if_under
+    threads in the busy state, another thread will be spawned.  So if
+    the limit is 5, and there are 4 hung threads and 6 busy threads,
+    no thread will be spawned.
+
+    When there are more than max_zombie_threads_before_die zombie
+    threads, a SystemExit exception will be raised, stopping the
+    server.  Use 0 or None to never raise this exception.  Zombie
+    threads *should* get cleaned up, but killing threads is no
+    necessarily reliable.  This is turned off by default, since it is
+    only a good idea if you've deployed the server with some process
+    watching from above (something similar to daemontools or zdaemon).
+
+    Each worker thread only processes ``max_requests`` tasks before it
+    dies and replaces itself with a new worker thread.
+    """
+
+
+    SHUTDOWN = object()
+
+    def __init__(
+        self, nworkers, name="ThreadPool", daemon=False,
+        max_requests=100, # threads are killed after this many requests
+        hung_thread_limit=30, # when a thread is marked "hung"
+        kill_thread_limit=1800, # when you kill that hung thread
+        dying_limit=300, # seconds that a kill should take to go into effect (longer than this and the thread is a "zombie")
+        spawn_if_under=5, # spawn if there's too many hung threads
+        max_zombie_threads_before_die=0, # when to give up on the process
+        hung_check_period=100, # every 100 requests check for hung workers
+        logger=None, # Place to log messages to
+        error_email=None, # Person(s) to notify if serious problem occurs
+        ):
+        """
+        Create thread pool with `nworkers` worker threads.
+        """
+        self.nworkers = nworkers
+        self.max_requests = max_requests
+        self.name = name
+        self.queue = Queue.Queue()
+        self.workers = []
+        self.daemon = daemon
+        if logger is None:
+            logger = logging.getLogger('paste.httpserver.ThreadPool')
+        if isinstance(logger, basestring):
+            logger = logging.getLogger(logger)
+        self.logger = logger
+        self.error_email = error_email
+        self._worker_count = count()
+
+        assert (not kill_thread_limit
+                or kill_thread_limit >= hung_thread_limit), (
+            "kill_thread_limit (%s) should be higher than hung_thread_limit (%s)"
+            % (kill_thread_limit, hung_thread_limit))
+        if not killthread:
+            kill_thread_limit = 0
+            self.logger.info(
+                "Cannot use kill_thread_limit as ctypes/killthread is not available")
+        self.kill_thread_limit = kill_thread_limit
+        self.dying_limit = dying_limit
+        self.hung_thread_limit = hung_thread_limit
+        assert spawn_if_under <= nworkers, (
+            "spawn_if_under (%s) should be less than nworkers (%s)"
+            % (spawn_if_under, nworkers))
+        self.spawn_if_under = spawn_if_under
+        self.max_zombie_threads_before_die = max_zombie_threads_before_die
+        self.hung_check_period = hung_check_period
+        self.requests_since_last_hung_check = 0
+        # Used to keep track of what worker is doing what:
+        self.worker_tracker = {}
+        # Used to keep track of the workers not doing anything:
+        self.idle_workers = []
+        # Used to keep track of threads that have been killed, but maybe aren't dead yet:
+        self.dying_threads = {}
+        # This is used to track when we last had to add idle workers;
+        # we shouldn't cull extra workers until some time has passed
+        # (hung_thread_limit) since workers were added:
+        self._last_added_new_idle_workers = 0
+        if not daemon:
+            atexit.register(self.shutdown)
+        for i in range(self.nworkers):
+            self.add_worker_thread(message='Initial worker pool')
+
+    def add_task(self, task):
+        """
+        Add a task to the queue
+        """
+        self.logger.debug('Added task (%i tasks queued)', self.queue.qsize())
+        if self.hung_check_period:
+            self.requests_since_last_hung_check += 1
+            if self.requests_since_last_hung_check > self.hung_check_period:
+                self.requests_since_last_hung_check = 0
+                self.kill_hung_threads()
+        if not self.idle_workers and self.spawn_if_under:
+            # spawn_if_under can come into effect...
+            busy = 0
+            now = time.time()
+            self.logger.debug('No idle workers for task; checking if we need to make more workers')
+            for worker in self.workers:
+                if not hasattr(worker, 'thread_id'):
+                    # Not initialized
+                    continue
+                time_started, info = self.worker_tracker.get(worker.thread_id,
+                                                             (None, None))
+                if time_started is not None:
+                    if now - time_started < self.hung_thread_limit:
+                        busy += 1
+            if busy < self.spawn_if_under:
+                self.logger.info(
+                    'No idle tasks, and only %s busy tasks; adding %s more '
+                    'workers', busy, self.spawn_if_under-busy)
+                self._last_added_new_idle_workers = time.time()
+                for i in range(self.spawn_if_under - busy):
+                    self.add_worker_thread(message='Response to lack of idle workers')
+            else:
+                self.logger.debug(
+                    'No extra workers needed (%s busy workers)',
+                    busy)
+        if (len(self.workers) > self.nworkers
+            and len(self.idle_workers) > 3
+            and time.time()-self._last_added_new_idle_workers > self.hung_thread_limit):
+            # We've spawned worers in the past, but they aren't needed
+            # anymore; kill off some
+            self.logger.info(
+                'Culling %s extra workers (%s idle workers present)',
+                len(self.workers)-self.nworkers, len(self.idle_workers))
+            self.logger.debug(
+                'Idle workers: %s', self.idle_workers)
+            for i in range(len(self.workers) - self.nworkers):
+                self.queue.put(self.SHUTDOWN)
+        self.queue.put(task)
+
+    def track_threads(self):
+        """
+        Return a dict summarizing the threads in the pool (as
+        described in the ThreadPool docstring).
+        """
+        result = dict(idle=[], busy=[], hung=[], dying=[], zombie=[])
+        now = time.time()
+        for worker in self.workers:
+            if not hasattr(worker, 'thread_id'):
+                # The worker hasn't fully started up, we should just
+                # ignore it
+                continue
+            time_started, info = self.worker_tracker.get(worker.thread_id,
+                                                         (None, None))
+            if time_started is not None:
+                if now - time_started > self.hung_thread_limit:
+                    result['hung'].append(worker)
+                else:
+                    result['busy'].append(worker)
+            else:
+                result['idle'].append(worker)
+        for thread_id, (time_killed, worker) in self.dying_threads.items():
+            if not self.thread_exists(thread_id):
+                # Cull dying threads that are actually dead and gone
+                self.logger.info('Killed thread %s no longer around',
+                                 thread_id)
+                try:
+                    del self.dying_threads[thread_id]
+                except KeyError:
+                    pass
+                continue
+            if now - time_killed > self.dying_limit:
+                result['zombie'].append(worker)
+            else:
+                result['dying'].append(worker)
+        return result
+
+    def kill_worker(self, thread_id):
+        """
+        Removes the worker with the given thread_id from the pool, and
+        replaces it with a new worker thread.
+
+        This should only be done for mis-behaving workers.
+        """
+        if killthread is None:
+            raise RuntimeError(
+                "Cannot kill worker; killthread/ctypes not available")
+        thread_obj = threading._active.get(thread_id)
+        killthread.async_raise(thread_id, SystemExit)
+        try:
+            del self.worker_tracker[thread_id]
+        except KeyError:
+            pass
+        self.logger.info('Killing thread %s', thread_id)
+        if thread_obj in self.workers:
+            self.workers.remove(thread_obj)
+        self.dying_threads[thread_id] = (time.time(), thread_obj)
+        self.add_worker_thread(message='Replacement for killed thread %s' % thread_id)
+
+    def thread_exists(self, thread_id):
+        """
+        Returns true if a thread with this id is still running
+        """
+        return thread_id in threading._active
+
+    def add_worker_thread(self, *args, **kwargs):
+        index = self._worker_count.next()
+        worker = threading.Thread(target=self.worker_thread_callback,
+                                  args=args, kwargs=kwargs,
+                                  name=("worker %d" % index))
+        worker.setDaemon(self.daemon)
+        worker.start()
+
+    def kill_hung_threads(self):
+        """
+        Tries to kill any hung threads
+        """
+        if not self.kill_thread_limit:
+            # No killing should occur
+            return
+        now = time.time()
+        max_time = 0
+        total_time = 0
+        idle_workers = 0
+        starting_workers = 0
+        working_workers = 0
+        killed_workers = 0
+        for worker in self.workers:
+            if not hasattr(worker, 'thread_id'):
+                # Not setup yet
+                starting_workers += 1
+                continue
+            time_started, info = self.worker_tracker.get(worker.thread_id,
+                                                         (None, None))
+            if time_started is None:
+                # Must be idle
+                idle_workers += 1
+                continue
+            working_workers += 1
+            max_time = max(max_time, now-time_started)
+            total_time += now-time_started
+            if now - time_started > self.kill_thread_limit:
+                self.logger.warning(
+                    'Thread %s hung (working on task for %i seconds)',
+                    worker.thread_id, now - time_started)
+                try:
+                    import pprint
+                    info_desc = pprint.pformat(info)
+                except:
+                    out = StringIO()
+                    traceback.print_exc(file=out)
+                    info_desc = 'Error:\n%s' % out.getvalue()
+                self.notify_problem(
+                    "Killing worker thread (id=%(thread_id)s) because it has been \n"
+                    "working on task for %(time)s seconds (limit is %(limit)s)\n"
+                    "Info on task:\n"
+                    "%(info)s"
+                    % dict(thread_id=worker.thread_id,
+                           time=now - time_started,
+                           limit=self.kill_thread_limit,
+                           info=info_desc))
+                self.kill_worker(worker.thread_id)
+                killed_workers += 1
+        if working_workers:
+            ave_time = float(total_time) / working_workers
+            ave_time = '%.2fsec' % ave_time
+        else:
+            ave_time = 'N/A'
+        self.logger.info(
+            "kill_hung_threads status: %s threads (%s working, %s idle, %s starting) "
+            "ave time %s, max time %.2fsec, killed %s workers"
+            % (idle_workers + starting_workers + working_workers,
+               working_workers, idle_workers, starting_workers,
+               ave_time, max_time, killed_workers))
+        self.check_max_zombies()
+
+    def check_max_zombies(self):
+        """
+        Check if we've reached max_zombie_threads_before_die; if so
+        then kill the entire process.
+        """
+        if not self.max_zombie_threads_before_die:
+            return
+        found = []
+        now = time.time()
+        for thread_id, (time_killed, worker) in self.dying_threads.items():
+            if not self.thread_exists(thread_id):
+                # Cull dying threads that are actually dead and gone
+                try:
+                    del self.dying_threads[thread_id]
+                except KeyError:
+                    pass
+                continue
+            if now - time_killed > self.dying_limit:
+                found.append(thread_id)
+        if found:
+            self.logger.info('Found %s zombie threads', found)
+        if len(found) > self.max_zombie_threads_before_die:
+            self.logger.fatal(
+                'Exiting process because %s zombie threads is more than %s limit',
+                len(found), self.max_zombie_threads_before_die)
+            self.notify_problem(
+                "Exiting process because %(found)s zombie threads "
+                "(more than limit of %(limit)s)\n"
+                "Bad threads (ids):\n"
+                "  %(ids)s\n"
+                % dict(found=len(found),
+                       limit=self.max_zombie_threads_before_die,
+                       ids="\n  ".join(map(str, found))),
+                subject="Process restart (too many zombie threads)")
+            self.shutdown(10)
+            print 'Shutting down', threading.currentThread()
+            raise ServerExit(3)
+
+    def worker_thread_callback(self, message=None):
+        """
+        Worker thread should call this method to get and process queued
+        callables.
+        """
+        thread_obj = threading.currentThread()
+        thread_id = thread_obj.thread_id = thread.get_ident()
+        self.workers.append(thread_obj)
+        self.idle_workers.append(thread_id)
+        requests_processed = 0
+        add_replacement_worker = False
+        self.logger.debug('Started new worker %s: %s', thread_id, message)
+        try:
+            while True:
+                if self.max_requests and self.max_requests < requests_processed:
+                    # Replace this thread then die
+                    self.logger.debug('Thread %s processed %i requests (limit %s); stopping thread'
+                                      % (thread_id, requests_processed, self.max_requests))
+                    add_replacement_worker = True
+                    break
+                runnable = self.queue.get()
+                if runnable is ThreadPool.SHUTDOWN:
+                    self.logger.debug('Worker %s asked to SHUTDOWN', thread_id)
+                    break
+                try:
+                    self.idle_workers.remove(thread_id)
+                except ValueError:
+                    pass
+                self.worker_tracker[thread_id] = [time.time(), None]
+                requests_processed += 1
+                try:
+                    try:
+                        runnable()
+                    except:
+                        # We are later going to call sys.exc_clear(),
+                        # removing all remnants of any exception, so
+                        # we should log it now.  But ideally no
+                        # exception should reach this level
+                        print >> sys.stderr, (
+                            'Unexpected exception in worker %r' % runnable)
+                        traceback.print_exc()
+                    if thread_id in self.dying_threads:
+                        # That last exception was intended to kill me
+                        break
+                finally:
+                    try:
+                        del self.worker_tracker[thread_id]
+                    except KeyError:
+                        pass
+                    sys.exc_clear()
+                self.idle_workers.append(thread_id)
+        finally:
+            try:
+                del self.worker_tracker[thread_id]
+            except KeyError:
+                pass
+            try:
+                self.idle_workers.remove(thread_id)
+            except ValueError:
+                pass
+            try:
+                self.workers.remove(thread_obj)
+            except ValueError:
+                pass
+            try:
+                del self.dying_threads[thread_id]
+            except KeyError:
+                pass
+            if add_replacement_worker:
+                self.add_worker_thread(message='Voluntary replacement for thread %s' % thread_id)
+
+    def shutdown(self, force_quit_timeout=0):
+        """
+        Shutdown the queue (after finishing any pending requests).
+        """
+        self.logger.info('Shutting down threadpool')
+        # Add a shutdown request for every worker
+        for i in range(len(self.workers)):
+            self.queue.put(ThreadPool.SHUTDOWN)
+        # Wait for each thread to terminate
+        hung_workers = []
+        for worker in self.workers:
+            worker.join(0.5)
+            if worker.isAlive():
+                hung_workers.append(worker)
+        zombies = []
+        for thread_id in self.dying_threads:
+            if self.thread_exists(thread_id):
+                zombies.append(thread_id)
+        if hung_workers or zombies:
+            self.logger.info("%s workers didn't stop properly, and %s zombies",
+                             len(hung_workers), len(zombies))
+            if hung_workers:
+                for worker in hung_workers:
+                    self.kill_worker(worker.thread_id)
+                self.logger.info('Workers killed forcefully')
+            if force_quit_timeout:
+                hung = []
+                timed_out = False
+                need_force_quit = bool(zombies)
+                for workers in self.workers:
+                    if not timed_out and worker.isAlive():
+                        timed_out = True
+                        worker.join(force_quit_timeout)
+                    if worker.isAlive():
+                        print "Worker %s won't die" % worker
+                        need_force_quit = True
+                if need_force_quit:
+                    import atexit
+                    # Remove the threading atexit callback
+                    for callback in list(atexit._exithandlers):
+                        func = getattr(callback[0], 'im_func', None)
+                        if not func:
+                            continue
+                        globs = getattr(func, 'func_globals', {})
+                        mod = globs.get('__name__')
+                        if mod == 'threading':
+                            atexit._exithandlers.remove(callback)
+                    atexit._run_exitfuncs()
+                    print 'Forcefully exiting process'
+                    os._exit(3)
+                else:
+                    self.logger.info('All workers eventually killed')
+        else:
+            self.logger.info('All workers stopped')
+
+    def notify_problem(self, msg, subject=None, spawn_thread=True):
+        """
+        Called when there's a substantial problem.  msg contains the
+        body of the notification, subject the summary.
+
+        If spawn_thread is true, then the email will be send in
+        another thread (so this doesn't block).
+        """
+        if not self.error_email:
+            return
+        if spawn_thread:
+            t = threading.Thread(
+                target=self.notify_problem,
+                args=(msg, subject, False))
+            t.start()
+            return
+        from_address = 'errors at localhost'
+        if not subject:
+            subject = msg.strip().splitlines()[0]
+            subject = subject[:50]
+            subject = '[http threadpool] %s' % subject
+        headers = [
+            "To: %s" % self.error_email,
+            "From: %s" % from_address,
+            "Subject: %s" % subject,
+            ]
+        try:
+            system = ' '.join(os.uname())
+        except:
+            system = '(unknown)'
+        body = (
+            "An error has occurred in the paste.httpserver.ThreadPool\n"
+            "Error:\n"
+            "  %(msg)s\n"
+            "Occurred at: %(time)s\n"
+            "PID: %(pid)s\n"
+            "System: %(system)s\n"
+            "Server .py file: %(file)s\n"
+            % dict(msg=msg,
+                   time=time.strftime("%c"),
+                   pid=os.getpid(),
+                   system=system,
+                   file=os.path.abspath(__file__),
+                   ))
+        message = '\n'.join(headers) + "\n\n" + body
+        import smtplib
+        server = smtplib.SMTP('localhost')
+        error_emails = [
+            e.strip() for e in self.error_email.split(",")
+            if e.strip()]
+        server.sendmail(from_address, error_emails, message)
+        server.quit()
+        print 'email sent to', error_emails, message
+
+class ThreadPoolMixIn(object):
+    """
+    Mix-in class to process requests from a thread pool
+    """
+    def __init__(self, nworkers, daemon=False, **threadpool_options):
+        # Create and start the workers
+        self.running = True
+        assert nworkers > 0, "ThreadPoolMixIn servers must have at least one worker"
+        self.thread_pool = ThreadPool(
+            nworkers,
+            "ThreadPoolMixIn HTTP server on %s:%d"
+            % (self.server_name, self.server_port),
+            daemon,
+            **threadpool_options)
+
+    def process_request(self, request, client_address):
+        """
+        Queue the request to be processed by on of the thread pool threads
+        """
+        # This sets the socket to blocking mode (and no timeout) since it
+        # may take the thread pool a little while to get back to it. (This
+        # is the default but since we set a timeout on the parent socket so
+        # that we can trap interrupts we need to restore this,.)
+        request.setblocking(1)
+        # Queue processing of the request
+        self.thread_pool.add_task(
+             lambda: self.process_request_in_thread(request, client_address))
+
+    def handle_error(self, request, client_address):
+        exc_class, exc, tb = sys.exc_info()
+        if exc_class is ServerExit:
+            # This is actually a request to stop the server
+            raise
+        return super(ThreadPoolMixIn, self).handle_error(request, client_address)
+
+    def process_request_in_thread(self, request, client_address):
+        """
+        The worker thread should call back here to do the rest of the
+        request processing. Error handling normaller done in 'handle_request'
+        must be done here.
+        """
+        try:
+            self.finish_request(request, client_address)
+            self.close_request(request)
+        except:
+            self.handle_error(request, client_address)
+            self.close_request(request)
+            exc = sys.exc_info()[1]
+            if isinstance(exc, (MemoryError, KeyboardInterrupt)):
+                raise
+
+    def serve_forever(self):
+        """
+        Overrides `serve_forever` to shut the threadpool down cleanly.
+        """
+        try:
+            while self.running:
+                try:
+                    self.handle_request()
+                except socket.timeout:
+                    # Timeout is expected, gives interrupts a chance to
+                    # propogate, just keep handling
+                    pass
+        finally:
+            self.thread_pool.shutdown()
+
+    def server_activate(self):
+        """
+        Overrides server_activate to set timeout on our listener socket.
+        """
+        # We set the timeout here so that we can trap interrupts on windows
+        self.socket.settimeout(1)
+
+    def server_close(self):
+        """
+        Finish pending requests and shutdown the server.
+        """
+        self.running = False
+        self.socket.close()
+        self.thread_pool.shutdown(60)
+
+class WSGIServerBase(SecureHTTPServer):
+    def __init__(self, wsgi_application, server_address,
+                 RequestHandlerClass=None, ssl_context=None,
+                 request_queue_size=None):
+        SecureHTTPServer.__init__(self, server_address,
+                                  RequestHandlerClass, ssl_context,
+                                  request_queue_size=request_queue_size)
+        self.wsgi_application = wsgi_application
+        self.wsgi_socket_timeout = None
+
+    def get_request(self):
+        # If there is a socket_timeout, set it on the accepted
+        (conn,info) = SecureHTTPServer.get_request(self)
+        if self.wsgi_socket_timeout:
+            conn.settimeout(self.wsgi_socket_timeout)
+        return (conn, info)
+
+class WSGIServer(ThreadingMixIn, WSGIServerBase):
+    daemon_threads = False
+
+class WSGIThreadPoolServer(ThreadPoolMixIn, WSGIServerBase):
+    def __init__(self, wsgi_application, server_address,
+                 RequestHandlerClass=None, ssl_context=None,
+                 nworkers=10, daemon_threads=False,
+                 threadpool_options=None, request_queue_size=None):
+        WSGIServerBase.__init__(self, wsgi_application, server_address,
+                                RequestHandlerClass, ssl_context,
+                                request_queue_size=request_queue_size)
+        if threadpool_options is None:
+            threadpool_options = {}
+        ThreadPoolMixIn.__init__(self, nworkers, daemon_threads,
+                                 **threadpool_options)
+
+class ServerExit(SystemExit):
+    """
+    Raised to tell the server to really exit (SystemExit is normally
+    caught)
+    """
+
+def serve(application, host=None, port=None, handler=None, ssl_pem=None,
+          ssl_context=None, server_version=None, protocol_version=None,
+          start_loop=True, daemon_threads=None, socket_timeout=None,
+          use_threadpool=None, threadpool_workers=10,
+          threadpool_options=None, request_queue_size=5):
+    """
+    Serves your ``application`` over HTTP(S) via WSGI interface
+
+    ``host``
+
+        This is the ipaddress to bind to (or a hostname if your
+        nameserver is properly configured).  This defaults to
+        127.0.0.1, which is not a public interface.
+
+    ``port``
+
+        The port to run on, defaults to 8080 for HTTP, or 4443 for
+        HTTPS. This can be a string or an integer value.
+
+    ``handler``
+
+        This is the HTTP request handler to use, it defaults to
+        ``WSGIHandler`` in this module.
+
+    ``ssl_pem``
+
+        This an optional SSL certificate file (via OpenSSL). You can
+        supply ``*`` and a development-only certificate will be
+        created for you, or you can generate a self-signed test PEM
+        certificate file as follows::
+
+            $ openssl genrsa 1024 > host.key
+            $ chmod 400 host.key
+            $ openssl req -new -x509 -nodes -sha1 -days 365  \\
+                          -key host.key > host.cert
+            $ cat host.cert host.key > host.pem
+            $ chmod 400 host.pem
+
+    ``ssl_context``
+
+        This an optional SSL context object for the server.  A SSL
+        context will be automatically constructed for you if you supply
+        ``ssl_pem``.  Supply this to use a context of your own
+        construction.
+
+    ``server_version``
+
+        The version of the server as reported in HTTP response line. This
+        defaults to something like "PasteWSGIServer/0.5".  Many servers
+        hide their code-base identity with a name like 'Amnesiac/1.0'
+
+    ``protocol_version``
+
+        This sets the protocol used by the server, by default
+        ``HTTP/1.0``. There is some support for ``HTTP/1.1``, which
+        defaults to nicer keep-alive connections.  This server supports
+        ``100 Continue``, but does not yet support HTTP/1.1 Chunked
+        Encoding. Hence, if you use HTTP/1.1, you're somewhat in error
+        since chunked coding is a mandatory requirement of a HTTP/1.1
+        server.  If you specify HTTP/1.1, every response *must* have a
+        ``Content-Length`` and you must be careful not to read past the
+        end of the socket.
+
+    ``start_loop``
+
+        This specifies if the server loop (aka ``server.serve_forever()``)
+        should be called; it defaults to ``True``.
+
+    ``daemon_threads``
+
+        This flag specifies if when your webserver terminates all
+        in-progress client connections should be droppped.  It defaults
+        to ``False``.   You might want to set this to ``True`` if you
+        are using ``HTTP/1.1`` and don't set a ``socket_timeout``.
+
+    ``socket_timeout``
+
+        This specifies the maximum amount of time that a connection to a
+        given client will be kept open.  At this time, it is a rude
+        disconnect, but at a later time it might follow the RFC a bit
+        more closely.
+
+    ``use_threadpool``
+
+        Server requests from a pool of worker threads (``threadpool_workers``)
+        rather than creating a new thread for each request. This can
+        substantially reduce latency since there is a high cost associated
+        with thread creation.
+
+    ``threadpool_workers``
+
+        Number of worker threads to create when ``use_threadpool`` is true. This
+        can be a string or an integer value.
+
+    ``threadpool_options``
+
+        A dictionary of options to be used when instantiating the
+        threadpool.  See paste.httpserver.ThreadPool for specific
+        options (``threadpool_workers`` is a specific option that can
+        also go here).
+
+    ``request_queue_size``
+
+        The 'backlog' argument to socket.listen(); specifies the
+        maximum number of queued connections.
+
+    """
+    is_ssl = False
+    if ssl_pem or ssl_context:
+        assert SSL, "pyOpenSSL is not installed"
+        is_ssl = True
+        port = int(port or 4443)
+        if not ssl_context:
+            if ssl_pem == '*':
+                ssl_context = _auto_ssl_context()
+            else:
+                ssl_context = SSL.Context(SSL.SSLv23_METHOD)
+                ssl_context.use_privatekey_file(ssl_pem)
+                ssl_context.use_certificate_chain_file(ssl_pem)
+
+    host = host or '127.0.0.1'
+    if port is None:
+        if ':' in host:
+            host, port = host.split(':', 1)
+        else:
+            port = 8080
+    server_address = (host, int(port))
+
+    if not handler:
+        handler = WSGIHandler
+    if server_version:
+        handler.server_version = server_version
+        handler.sys_version = None
+    if protocol_version:
+        assert protocol_version in ('HTTP/0.9', 'HTTP/1.0', 'HTTP/1.1')
+        handler.protocol_version = protocol_version
+
+    if use_threadpool is None:
+        use_threadpool = True
+
+    if converters.asbool(use_threadpool):
+        server = WSGIThreadPoolServer(application, server_address, handler,
+                                      ssl_context, int(threadpool_workers),
+                                      daemon_threads,
+                                      threadpool_options=threadpool_options,
+                                      request_queue_size=request_queue_size)
+    else:
+        server = WSGIServer(application, server_address, handler, ssl_context,
+                            request_queue_size=request_queue_size)
+        if daemon_threads:
+            server.daemon_threads = daemon_threads
+
+    if socket_timeout:
+        server.wsgi_socket_timeout = int(socket_timeout)
+
+    if converters.asbool(start_loop):
+        protocol = is_ssl and 'https' or 'http'
+        host, port = server.server_address[:2]
+        if host == '0.0.0.0':
+            print 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % \
+                (port, protocol, port)
+        else:
+            print "serving on %s://%s:%s" % (protocol, host, port)
+        try:
+            server.serve_forever()
+        except KeyboardInterrupt:
+            # allow CTRL+C to shutdown
+            pass
+    return server
+
+# For paste.deploy server instantiation (egg:Paste#http)
+# Note: this gets a separate function because it has to expect string
+# arguments (though that's not much of an issue yet, ever?)
+def server_runner(wsgi_app, global_conf, **kwargs):
+    from paste.deploy.converters import asbool
+    for name in ['port', 'socket_timeout', 'threadpool_workers',
+                 'threadpool_hung_thread_limit',
+                 'threadpool_kill_thread_limit',
+                 'threadpool_dying_limit', 'threadpool_spawn_if_under',
+                 'threadpool_max_zombie_threads_before_die',
+                 'threadpool_hung_check_period',
+                 'threadpool_max_requests', 'request_queue_size']:
+        if name in kwargs:
+            kwargs[name] = int(kwargs[name])
+    for name in ['use_threadpool', 'daemon_threads']:
+        if name in kwargs:
+            kwargs[name] = asbool(kwargs[name])
+    threadpool_options = {}
+    for name, value in kwargs.items():
+        if name.startswith('threadpool_') and name != 'threadpool_workers':
+            threadpool_options[name[len('threadpool_'):]] = value
+            del kwargs[name]
+    if ('error_email' not in threadpool_options
+        and 'error_email' in global_conf):
+        threadpool_options['error_email'] = global_conf['error_email']
+    kwargs['threadpool_options'] = threadpool_options
+    serve(wsgi_app, **kwargs)
+
+server_runner.__doc__ = (serve.__doc__ or '') + """
+
+    You can also set these threadpool options:
+
+    ``threadpool_max_requests``:
+
+        The maximum number of requests a worker thread will process
+        before dying (and replacing itself with a new worker thread).
+        Default 100.
+
+    ``threadpool_hung_thread_limit``:
+
+        The number of seconds a thread can work on a task before it is
+        considered hung (stuck).  Default 30 seconds.
+
+    ``threadpool_kill_thread_limit``:
+
+        The number of seconds a thread can work before you should kill it
+        (assuming it will never finish).  Default 600 seconds (10 minutes).
+
+    ``threadpool_dying_limit``:
+
+        The length of time after killing a thread that it should actually
+        disappear.  If it lives longer than this, it is considered a
+        "zombie".  Note that even in easy situations killing a thread can
+        be very slow.  Default 300 seconds (5 minutes).
+
+    ``threadpool_spawn_if_under``:
+
+        If there are no idle threads and a request comes in, and there are
+        less than this number of *busy* threads, then add workers to the
+        pool.  Busy threads are threads that have taken less than
+        ``threadpool_hung_thread_limit`` seconds so far.  So if you get
+        *lots* of requests but they complete in a reasonable amount of time,
+        the requests will simply queue up (adding more threads probably
+        wouldn't speed them up).  But if you have lots of hung threads and
+        one more request comes in, this will add workers to handle it.
+        Default 5.
+
+    ``threadpool_max_zombie_threads_before_die``:
+
+        If there are more zombies than this, just kill the process.  This is
+        only good if you have a monitor that will automatically restart
+        the server.  This can clean up the mess.  Default 0 (disabled).
+
+    `threadpool_hung_check_period``:
+
+        Every X requests, check for hung threads that need to be killed,
+        or for zombie threads that should cause a restart.  Default 100
+        requests.
+
+    ``threadpool_logger``:
+
+        Logging messages will go the logger named here.
+
+    ``threadpool_error_email`` (or global ``error_email`` setting):
+
+        When threads are killed or the process restarted, this email
+        address will be contacted (using an SMTP server on localhost).
+
+"""
+
+
+if __name__ == '__main__':
+    from paste.wsgilib import dump_environ
+    #serve(dump_environ, ssl_pem="test.pem")
+    serve(dump_environ, server_version="Wombles/1.0",
+          protocol_version="HTTP/1.1", port="8888")

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/lint.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/lint.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/lint.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,436 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# Also licenced under the Apache License, 2.0: http://opensource.org/licenses/apache2.0.php
+# Licensed to PSF under a Contributor Agreement
+"""
+Middleware to check for obedience to the WSGI specification.
+
+Some of the things this checks:
+
+* Signature of the application and start_response (including that
+  keyword arguments are not used).
+
+* Environment checks:
+
+  - Environment is a dictionary (and not a subclass).
+
+  - That all the required keys are in the environment: REQUEST_METHOD,
+    SERVER_NAME, SERVER_PORT, wsgi.version, wsgi.input, wsgi.errors,
+    wsgi.multithread, wsgi.multiprocess, wsgi.run_once
+
+  - That HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH are not in the
+    environment (these headers should appear as CONTENT_LENGTH and
+    CONTENT_TYPE).
+
+  - Warns if QUERY_STRING is missing, as the cgi module acts
+    unpredictably in that case.
+
+  - That CGI-style variables (that don't contain a .) have
+    (non-unicode) string values
+
+  - That wsgi.version is a tuple
+
+  - That wsgi.url_scheme is 'http' or 'https' (@@: is this too
+    restrictive?)
+
+  - Warns if the REQUEST_METHOD is not known (@@: probably too
+    restrictive).
+
+  - That SCRIPT_NAME and PATH_INFO are empty or start with /
+
+  - That at least one of SCRIPT_NAME or PATH_INFO are set.
+
+  - That CONTENT_LENGTH is a positive integer.
+
+  - That SCRIPT_NAME is not '/' (it should be '', and PATH_INFO should
+    be '/').
+
+  - That wsgi.input has the methods read, readline, readlines, and
+    __iter__
+
+  - That wsgi.errors has the methods flush, write, writelines
+
+* The status is a string, contains a space, starts with an integer,
+  and that integer is in range (> 100).
+
+* That the headers is a list (not a subclass, not another kind of
+  sequence).
+
+* That the items of the headers are tuples of strings.
+
+* That there is no 'status' header (that is used in CGI, but not in
+  WSGI).
+
+* That the headers don't contain newlines or colons, end in _ or -, or
+  contain characters codes below 037.
+
+* That Content-Type is given if there is content (CGI often has a
+  default content type, but WSGI does not).
+
+* That no Content-Type is given when there is no content (@@: is this
+  too restrictive?)
+
+* That the exc_info argument to start_response is a tuple or None.
+
+* That all calls to the writer are with strings, and no other methods
+  on the writer are accessed.
+
+* That wsgi.input is used properly:
+
+  - .read() is called with zero or one argument
+
+  - That it returns a string
+
+  - That readline, readlines, and __iter__ return strings
+
+  - That .close() is not called
+
+  - No other methods are provided
+
+* That wsgi.errors is used properly:
+
+  - .write() and .writelines() is called with a string
+
+  - That .close() is not called, and no other methods are provided.
+
+* The response iterator:
+
+  - That it is not a string (it should be a list of a single string; a
+    string will work, but perform horribly).
+
+  - That .next() returns a string
+
+  - That the iterator is not iterated over until start_response has
+    been called (that can signal either a server or application
+    error).
+
+  - That .close() is called (doesn't raise exception, only prints to
+    sys.stderr, because we only know it isn't called when the object
+    is garbage collected).
+"""
+
+import re
+import sys
+from types import DictType, StringType, TupleType, ListType
+import warnings
+
+header_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9\-_]*$')
+bad_header_value_re = re.compile(r'[\000-\037]')
+
+class WSGIWarning(Warning):
+    """
+    Raised in response to WSGI-spec-related warnings
+    """
+
+def middleware(application, global_conf=None):
+
+    """
+    When applied between a WSGI server and a WSGI application, this
+    middleware will check for WSGI compliancy on a number of levels.
+    This middleware does not modify the request or response in any
+    way, but will throw an AssertionError if anything seems off
+    (except for a failure to close the application iterator, which
+    will be printed to stderr -- there's no way to throw an exception
+    at that point).
+    """
+    
+    def lint_app(*args, **kw):
+        assert len(args) == 2, "Two arguments required"
+        assert not kw, "No keyword arguments allowed"
+        environ, start_response = args
+
+        check_environ(environ)
+
+        # We use this to check if the application returns without
+        # calling start_response:
+        start_response_started = []
+
+        def start_response_wrapper(*args, **kw):
+            assert len(args) == 2 or len(args) == 3, (
+                "Invalid number of arguments: %s" % args)
+            assert not kw, "No keyword arguments allowed"
+            status = args[0]
+            headers = args[1]
+            if len(args) == 3:
+                exc_info = args[2]
+            else:
+                exc_info = None
+
+            check_status(status)
+            check_headers(headers)
+            check_content_type(status, headers)
+            check_exc_info(exc_info)
+
+            start_response_started.append(None)
+            return WriteWrapper(start_response(*args))
+
+        environ['wsgi.input'] = InputWrapper(environ['wsgi.input'])
+        environ['wsgi.errors'] = ErrorWrapper(environ['wsgi.errors'])
+
+        iterator = application(environ, start_response_wrapper)
+        assert iterator is not None and iterator != False, (
+            "The application must return an iterator, if only an empty list")
+
+        check_iterator(iterator)
+
+        return IteratorWrapper(iterator, start_response_started)
+
+    return lint_app
+
+class InputWrapper(object):
+
+    def __init__(self, wsgi_input):
+        self.input = wsgi_input
+
+    def read(self, *args):
+        assert len(args) <= 1
+        v = self.input.read(*args)
+        assert type(v) is type("")
+        return v
+
+    def readline(self, *args):
+        v = self.input.readline(*args)
+        assert type(v) is type("")
+        return v
+
+    def readlines(self, *args):
+        assert len(args) <= 1
+        lines = self.input.readlines(*args)
+        assert type(lines) is type([])
+        for line in lines:
+            assert type(line) is type("")
+        return lines
+    
+    def __iter__(self):
+        while 1:
+            line = self.readline()
+            if not line:
+                return
+            yield line
+
+    def close(self):
+        assert 0, "input.close() must not be called"
+
+class ErrorWrapper(object):
+
+    def __init__(self, wsgi_errors):
+        self.errors = wsgi_errors
+
+    def write(self, s):
+        assert type(s) is type("")
+        self.errors.write(s)
+
+    def flush(self):
+        self.errors.flush()
+
+    def writelines(self, seq):
+        for line in seq:
+            self.write(line)
+
+    def close(self):
+        assert 0, "errors.close() must not be called"
+
+class WriteWrapper(object):
+
+    def __init__(self, wsgi_writer):
+        self.writer = wsgi_writer
+
+    def __call__(self, s):
+        assert type(s) is type("")
+        self.writer(s)
+
+class PartialIteratorWrapper(object):
+
+    def __init__(self, wsgi_iterator):
+        self.iterator = wsgi_iterator
+
+    def __iter__(self):
+        # We want to make sure __iter__ is called
+        return IteratorWrapper(self.iterator)
+
+class IteratorWrapper(object):
+
+    def __init__(self, wsgi_iterator, check_start_response):
+        self.original_iterator = wsgi_iterator
+        self.iterator = iter(wsgi_iterator)
+        self.closed = False
+        self.check_start_response = check_start_response
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        assert not self.closed, (
+            "Iterator read after closed")
+        v = self.iterator.next()
+        if self.check_start_response is not None:
+            assert self.check_start_response, (
+                "The application returns and we started iterating over its body, but start_response has not yet been called")
+            self.check_start_response = None
+        return v
+        
+    def close(self):
+        self.closed = True
+        if hasattr(self.original_iterator, 'close'):
+            self.original_iterator.close()
+
+    def __del__(self):
+        if not self.closed:
+            sys.stderr.write(
+                "Iterator garbage collected without being closed")
+        assert self.closed, (
+            "Iterator garbage collected without being closed")
+
+def check_environ(environ):
+    assert type(environ) is DictType, (
+        "Environment is not of the right type: %r (environment: %r)"
+        % (type(environ), environ))
+    
+    for key in ['REQUEST_METHOD', 'SERVER_NAME', 'SERVER_PORT',
+                'wsgi.version', 'wsgi.input', 'wsgi.errors',
+                'wsgi.multithread', 'wsgi.multiprocess',
+                'wsgi.run_once']:
+        assert key in environ, (
+            "Environment missing required key: %r" % key)
+
+    for key in ['HTTP_CONTENT_TYPE', 'HTTP_CONTENT_LENGTH']:
+        assert key not in environ, (
+            "Environment should not have the key: %s "
+            "(use %s instead)" % (key, key[5:]))
+
+    if 'QUERY_STRING' not in environ:
+        warnings.warn(
+            'QUERY_STRING is not in the WSGI environment; the cgi '
+            'module will use sys.argv when this variable is missing, '
+            'so application errors are more likely',
+            WSGIWarning)
+
+    for key in environ.keys():
+        if '.' in key:
+            # Extension, we don't care about its type
+            continue
+        assert type(environ[key]) is StringType, (
+            "Environmental variable %s is not a string: %r (value: %r)"
+            % (key, type(environ[key]), environ[key]))
+        
+    assert type(environ['wsgi.version']) is TupleType, (
+        "wsgi.version should be a tuple (%r)" % environ['wsgi.version'])
+    assert environ['wsgi.url_scheme'] in ('http', 'https'), (
+        "wsgi.url_scheme unknown: %r" % environ['wsgi.url_scheme'])
+
+    check_input(environ['wsgi.input'])
+    check_errors(environ['wsgi.errors'])
+
+    # @@: these need filling out:
+    if environ['REQUEST_METHOD'] not in (
+        'GET', 'HEAD', 'POST', 'OPTIONS','PUT','DELETE','TRACE'):
+        warnings.warn(
+            "Unknown REQUEST_METHOD: %r" % environ['REQUEST_METHOD'],
+            WSGIWarning)
+
+    assert (not environ.get('SCRIPT_NAME')
+            or environ['SCRIPT_NAME'].startswith('/')), (
+        "SCRIPT_NAME doesn't start with /: %r" % environ['SCRIPT_NAME'])
+    assert (not environ.get('PATH_INFO')
+            or environ['PATH_INFO'].startswith('/')), (
+        "PATH_INFO doesn't start with /: %r" % environ['PATH_INFO'])
+    if environ.get('CONTENT_LENGTH'):
+        assert int(environ['CONTENT_LENGTH']) >= 0, (
+            "Invalid CONTENT_LENGTH: %r" % environ['CONTENT_LENGTH'])
+
+    if not environ.get('SCRIPT_NAME'):
+        assert environ.has_key('PATH_INFO'), (
+            "One of SCRIPT_NAME or PATH_INFO are required (PATH_INFO "
+            "should at least be '/' if SCRIPT_NAME is empty)")
+    assert environ.get('SCRIPT_NAME') != '/', (
+        "SCRIPT_NAME cannot be '/'; it should instead be '', and "
+        "PATH_INFO should be '/'")
+
+def check_input(wsgi_input):
+    for attr in ['read', 'readline', 'readlines', '__iter__']:
+        assert hasattr(wsgi_input, attr), (
+            "wsgi.input (%r) doesn't have the attribute %s"
+            % (wsgi_input, attr))
+
+def check_errors(wsgi_errors):
+    for attr in ['flush', 'write', 'writelines']:
+        assert hasattr(wsgi_errors, attr), (
+            "wsgi.errors (%r) doesn't have the attribute %s"
+            % (wsgi_errors, attr))
+
+def check_status(status):
+    assert type(status) is StringType, (
+        "Status must be a string (not %r)" % status)
+    # Implicitly check that we can turn it into an integer:
+    status_code = status.split(None, 1)[0]
+    assert len(status_code) == 3, (
+        "Status codes must be three characters: %r" % status_code)
+    status_int = int(status_code)
+    assert status_int >= 100, "Status code is invalid: %r" % status_int
+    if len(status) < 4 or status[3] != ' ':
+        warnings.warn(
+            "The status string (%r) should be a three-digit integer "
+            "followed by a single space and a status explanation"
+            % status, WSGIWarning)
+
+def check_headers(headers):
+    assert type(headers) is ListType, (
+        "Headers (%r) must be of type list: %r"
+        % (headers, type(headers)))
+    header_names = {}
+    for item in headers:
+        assert type(item) is TupleType, (
+            "Individual headers (%r) must be of type tuple: %r"
+            % (item, type(item)))
+        assert len(item) == 2
+        name, value = item
+        assert name.lower() != 'status', (
+            "The Status header cannot be used; it conflicts with CGI "
+            "script, and HTTP status is not given through headers "
+            "(value: %r)." % value)
+        header_names[name.lower()] = None
+        assert '\n' not in name and ':' not in name, (
+            "Header names may not contain ':' or '\\n': %r" % name)
+        assert header_re.search(name), "Bad header name: %r" % name
+        assert not name.endswith('-') and not name.endswith('_'), (
+            "Names may not end in '-' or '_': %r" % name)
+        assert not bad_header_value_re.search(value), (
+            "Bad header value: %r (bad char: %r)"
+            % (value, bad_header_value_re.search(value).group(0)))
+
+def check_content_type(status, headers):
+    code = int(status.split(None, 1)[0])
+    # @@: need one more person to verify this interpretation of RFC 2616
+    #     http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+    NO_MESSAGE_BODY = (204, 304)
+    NO_MESSAGE_TYPE = (204, 304)
+    for name, value in headers:
+        if name.lower() == 'content-type':
+            if code not in NO_MESSAGE_TYPE:
+                return
+            assert 0, (("Content-Type header found in a %s response, "
+                        "which must not return content.") % code)
+    if code not in NO_MESSAGE_BODY:
+        assert 0, "No Content-Type header found in headers (%s)" % headers
+
+def check_exc_info(exc_info):
+    assert exc_info is None or type(exc_info) is type(()), (
+        "exc_info (%r) is not a tuple: %r" % (exc_info, type(exc_info)))
+    # More exc_info checks?
+
+def check_iterator(iterator):
+    # Technically a string is legal, which is why it's a really bad
+    # idea, because it may cause the response to be returned
+    # character-by-character
+    assert not isinstance(iterator, str), (
+        "You should not return a string as your application iterator, "
+        "instead return a single-item list containing that string.")
+
+def make_middleware(application, global_conf):
+    # @@: global_conf should be taken out of the middleware function,
+    # and isolated here
+    return middleware(application)
+
+make_middleware.__doc__ = __doc__
+
+__all__ = ['middleware', 'make_middleware']

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/modpython.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/modpython.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/modpython.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,252 @@
+"""WSGI Paste wrapper for mod_python. Requires Python 2.2 or greater.
+
+
+Example httpd.conf section for a Paste app with an ini file::
+
+    <Location />
+        SetHandler python-program
+        PythonHandler paste.modpython
+        PythonOption paste.ini /some/location/your/pasteconfig.ini
+    </Location>
+    
+Or if you want to load a WSGI application under /your/homedir in the module
+``startup`` and the WSGI app is ``app``::
+
+    <Location />
+        SetHandler python-program
+        PythonHandler paste.modpython
+        PythonPath "['/virtual/project/directory'] + sys.path"
+        PythonOption wsgi.application startup::app
+    </Location>
+
+
+If you'd like to use a virtual installation, make sure to add it in the path
+like so::
+
+    <Location />
+        SetHandler python-program
+        PythonHandler paste.modpython
+        PythonPath "['/virtual/project/directory', '/virtual/lib/python2.4/'] + sys.path"
+        PythonOption paste.ini /virtual/project/directory/pasteconfig.ini
+    </Location>
+
+Some WSGI implementations assume that the SCRIPT_NAME environ variable will
+always be equal to "the root URL of the app"; Apache probably won't act as
+you expect in that case. You can add another PythonOption directive to tell
+modpython_gateway to force that behavior:
+
+    PythonOption SCRIPT_NAME /mcontrol
+
+Some WSGI applications need to be cleaned up when Apache exits. You can
+register a cleanup handler with yet another PythonOption directive:
+
+    PythonOption wsgi.cleanup module::function
+
+The module.function will be called with no arguments on server shutdown,
+once for each child process or thread.
+
+This module highly based on Robert Brewer's, here:
+http://projects.amor.org/misc/svn/modpython_gateway.py
+"""
+
+import traceback
+
+try:
+    from mod_python import apache
+except:
+    pass
+from paste.deploy import loadapp
+
+class InputWrapper(object):
+    
+    def __init__(self, req):
+        self.req = req
+    
+    def close(self):
+        pass
+    
+    def read(self, size=-1):
+        return self.req.read(size)
+    
+    def readline(self, size=-1):
+        return self.req.readline(size)
+    
+    def readlines(self, hint=-1):
+        return self.req.readlines(hint)
+    
+    def __iter__(self):
+        line = self.readline()
+        while line:
+            yield line
+            # Notice this won't prefetch the next line; it only
+            # gets called if the generator is resumed.
+            line = self.readline()
+
+
+class ErrorWrapper(object):
+    
+    def __init__(self, req):
+        self.req = req
+    
+    def flush(self):
+        pass
+    
+    def write(self, msg):
+        self.req.log_error(msg)
+    
+    def writelines(self, seq):
+        self.write(''.join(seq))
+
+
+bad_value = ("You must provide a PythonOption '%s', either 'on' or 'off', "
+             "when running a version of mod_python < 3.1")
+
+
+class Handler(object):
+    
+    def __init__(self, req):
+        self.started = False
+        
+        options = req.get_options()
+        
+        # Threading and forking
+        try:
+            q = apache.mpm_query
+            threaded = q(apache.AP_MPMQ_IS_THREADED)
+            forked = q(apache.AP_MPMQ_IS_FORKED)
+        except AttributeError:
+            threaded = options.get('multithread', '').lower()
+            if threaded == 'on':
+                threaded = True
+            elif threaded == 'off':
+                threaded = False
+            else:
+                raise ValueError(bad_value % "multithread")
+            
+            forked = options.get('multiprocess', '').lower()
+            if forked == 'on':
+                forked = True
+            elif forked == 'off':
+                forked = False
+            else:
+                raise ValueError(bad_value % "multiprocess")
+        
+        env = self.environ = dict(apache.build_cgi_env(req))
+        
+        if 'SCRIPT_NAME' in options:
+            # Override SCRIPT_NAME and PATH_INFO if requested.
+            env['SCRIPT_NAME'] = options['SCRIPT_NAME']
+            env['PATH_INFO'] = req.uri[len(options['SCRIPT_NAME']):]
+        else:
+            env['SCRIPT_NAME'] = ''
+            env['PATH_INFO'] = req.uri
+        
+        env['wsgi.input'] = InputWrapper(req)
+        env['wsgi.errors'] = ErrorWrapper(req)
+        env['wsgi.version'] = (1, 0)
+        env['wsgi.run_once'] = False
+        if env.get("HTTPS") in ('yes', 'on', '1'):
+            env['wsgi.url_scheme'] = 'https'
+        else:
+            env['wsgi.url_scheme'] = 'http'
+        env['wsgi.multithread']  = threaded
+        env['wsgi.multiprocess'] = forked
+        
+        self.request = req
+    
+    def run(self, application):
+        try:
+            result = application(self.environ, self.start_response)
+            for data in result:
+                self.write(data)
+            if not self.started:
+                self.request.set_content_length(0)
+            if hasattr(result, 'close'):
+                result.close()
+        except:
+            traceback.print_exc(None, self.environ['wsgi.errors'])
+            if not self.started:
+                self.request.status = 500
+                self.request.content_type = 'text/plain'
+                data = "A server error occurred. Please contact the administrator."
+                self.request.set_content_length(len(data))
+                self.request.write(data)
+    
+    def start_response(self, status, headers, exc_info=None):
+        if exc_info:
+            try:
+                if self.started:
+                    raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                exc_info = None
+        
+        self.request.status = int(status[:3])
+        
+        for key, val in headers:
+            if key.lower() == 'content-length':
+                self.request.set_content_length(int(val))
+            elif key.lower() == 'content-type':
+                self.request.content_type = val
+            else:
+                self.request.headers_out.add(key, val)
+        
+        return self.write
+    
+    def write(self, data):
+        if not self.started:
+            self.started = True
+        self.request.write(data)
+
+
+startup = None
+cleanup = None
+wsgiapps = {}
+
+def handler(req):
+    options = req.get_options()
+    # Run a startup function if requested.
+    global startup
+    if 'wsgi.startup' in options and not startup:
+        func = options['wsgi.startup']
+        if func:
+            module_name, object_str = func.split('::', 1)
+            module = __import__(module_name, globals(), locals(), [''])
+            startup = apache.resolve_object(module, object_str)
+            startup(req)
+    
+    # Register a cleanup function if requested.
+    global cleanup
+    if 'wsgi.cleanup' in options and not cleanup:
+        func = options['wsgi.cleanup']
+        if func:
+            module_name, object_str = func.split('::', 1)
+            module = __import__(module_name, globals(), locals(), [''])
+            cleanup = apache.resolve_object(module, object_str)
+            def cleaner(data):
+                cleanup()
+            try:
+                # apache.register_cleanup wasn't available until 3.1.4.
+                apache.register_cleanup(cleaner)
+            except AttributeError:
+                req.server.register_cleanup(req, cleaner)
+    
+    # Import the wsgi 'application' callable and pass it to Handler.run
+    global wsgiapps
+    appini = options.get('paste.ini')
+    app = None
+    if appini:
+        if appini not in wsgiapps:
+            wsgiapps[appini] = loadapp("config:%s" % appini)
+        app = wsgiapps[appini]
+    
+    # Import the wsgi 'application' callable and pass it to Handler.run
+    appwsgi = options.get('wsgi.application')
+    if appwsgi and not appini:
+        modname, objname = appwsgi.split('::', 1)
+        module = __import__(modname, globals(), locals(), [''])
+        app = getattr(module, objname)
+    
+    Handler(req).run(app)
+    
+    # status was set in Handler; always return apache.OK
+    return apache.OK

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/pony.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/pony.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/pony.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,57 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+We have a pony and/or a unicorn.
+"""
+from paste.request import construct_url
+
+PONY = """
+eJyFkkFuxCAMRfdzCisbJxK2D5D2JpbMrlI3XXQZDt9PCG0ySgcWIMT79rcN0XClUJlZRB9jVmci
+FmV19khjgRFl0RzrKmqzvY8lRUWFlXvCrD7UbAQR/17NUvGhypAF9og16vWtkC8DzUayS6pN3/dR
+ki0OnpzKjUBFpmlC7zVFRNL1rwoq6PWXXQSnIm9WoTzlM2//ke21o5g/l1ckRhiPbkDZXsKIR7l1
+36hF9uMhnRiVjI8UgYjlsIKCrXXpcA9iX5y7zMmtG0fUpW61Ssttipf6cp3WARfkMVoYFryi2a+w
+o/2dhW0OXfcMTnmh53oR9egzPs+qkpY9IKxdUVRP5wHO7UDAuI6moA2N+/z4vtc2k8B+AIBimVU=
+"""
+
+UNICORN = """
+eJyVVD1vhDAM3e9XeAtIxB5P6qlDx0OMXVBzSpZOHdsxP762E0JAnMgZ8Zn37OePAPC60eV1Dl5b
+SS7fB6DmQNGhtegpNlPIQS8HmkYGdSqNqDF9wcMYus4TuBYGsZwIPqXfEoNir5K+R3mbzhlR4JMW
+eGpikPpn9wHl2sDgEH1270guZwzKDRf3nTztMvfI5r3fJqEmNxdCyISBcWjNgjPG8Egg2hgT3mJi
+KBwNvmPB1hbWJ3TwBfMlqdTzxNyDE2H8zOD5HA4KkqJGPVY/TwnxmPA82kdSJNj7zs+R0d1pB+JO
+xn2DKgsdxAfFS2pfTSD0Fb6Uzv7dCQSvE5JmZQEQ90vNjBU1GPuGQpCPS8cGo+dQgjIKqxnJTXbw
+ucFzPFVIJXtzk6BXKGPnYsKzvFmGx7A0j6Zqvlvk5rETXbMWTGWj0RFc8QNPYVfhJfMMniCPazWJ
+lGtPZecIGJWW6oL2hpbWRZEkChe8eg5Wb7xx/MBZBFjxeZPEss+mRQ3Uhc8WQv684seSRO7i3nb4
+7HlKUg8sraz47LmXyh8S0somADvoUpoHjGWl+rUkF0H+EIf/gbyyMg58BBk6L634/fkHUCodMw==
+"""
+
+
+class PonyMiddleware(object):
+
+    def __init__(self, application):
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        path_info = environ.get('PATH_INFO', '')
+        if path_info == '/pony':
+            url = construct_url(environ, with_query_string=False)
+            if 'horn' in environ.get('QUERY_STRING', ''):
+                data = UNICORN
+                link = 'remove horn!'
+            else:
+                data = PONY
+                url += '?horn'
+                link = 'add horn!'
+            msg = data.decode('base64').decode('zlib')
+            msg = '<pre>%s\n<a href="%s">%s</a></pre>' % (
+                msg, url, link)
+            start_response('200 OK', [('content-type', 'text/html')])
+            return [msg]
+        else:
+            return self.application(environ, start_response)
+
+def make_pony(app, global_conf):
+    """
+    Adds pony power to any application, at /pony
+    """
+    return PonyMiddleware(app)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/progress.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/progress.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/progress.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,222 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# This code was written with funding by http://prometheusresearch.com
+"""
+Upload Progress Monitor
+
+This is a WSGI middleware component which monitors the status of files
+being uploaded.  It includes a small query application which will return
+a list of all files being uploaded by particular session/user.
+
+>>> from paste.httpserver import serve
+>>> from paste.urlmap import URLMap
+>>> from paste.auth.basic import AuthBasicHandler
+>>> from paste.debug.debugapp import SlowConsumer, SimpleApplication
+>>> # from paste.progress import *
+>>> realm = 'Test Realm'
+>>> def authfunc(username, password):
+...     return username == password
+>>> map = URLMap({})
+>>> ups = UploadProgressMonitor(map, threshold=1024)
+>>> map['/upload'] = SlowConsumer()
+>>> map['/simple'] = SimpleApplication()
+>>> map['/report'] = UploadProgressReporter(ups)
+>>> serve(AuthBasicHandler(ups, realm, authfunc))
+serving on...
+
+.. note::
+
+   This is experimental, and will change in the future.
+"""
+import time
+from paste.wsgilib import catch_errors
+
+DEFAULT_THRESHOLD = 1024 * 1024  # one megabyte
+DEFAULT_TIMEOUT   = 60*5         # five minutes
+ENVIRON_RECEIVED  = 'paste.bytes_received'
+REQUEST_STARTED   = 'paste.request_started'
+REQUEST_FINISHED  = 'paste.request_finished'
+
+class _ProgressFile(object):
+    """
+    This is the input-file wrapper used to record the number of
+    ``paste.bytes_received`` for the given request.
+    """
+
+    def __init__(self, environ, rfile):
+        self._ProgressFile_environ = environ
+        self._ProgressFile_rfile   = rfile
+        self.flush = rfile.flush
+        self.write = rfile.write
+        self.writelines = rfile.writelines
+
+    def __iter__(self):
+        environ = self._ProgressFile_environ
+        riter = iter(self._ProgressFile_rfile)
+        def iterwrap():
+            for chunk in riter:
+                environ[ENVIRON_RECEIVED] += len(chunk)
+                yield chunk
+        return iter(iterwrap)
+
+    def read(self, size=-1):
+        chunk = self._ProgressFile_rfile.read(size)
+        self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk)
+        return chunk
+
+    def readline(self):
+        chunk = self._ProgressFile_rfile.readline()
+        self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk)
+        return chunk
+
+    def readlines(self, hint=None):
+        chunk = self._ProgressFile_rfile.readlines(hint)
+        self._ProgressFile_environ[ENVIRON_RECEIVED] += len(chunk)
+        return chunk
+
+class UploadProgressMonitor(object):
+    """
+    monitors and reports on the status of uploads in progress
+
+    Parameters:
+
+        ``application``
+
+            This is the next application in the WSGI stack.
+
+        ``threshold``
+
+            This is the size in bytes that is needed for the
+            upload to be included in the monitor.
+
+        ``timeout``
+
+            This is the amount of time (in seconds) that a upload
+            remains in the monitor after it has finished.
+
+    Methods:
+
+        ``uploads()``
+
+            This returns a list of ``environ`` dict objects for each
+            upload being currently monitored, or finished but whose time
+            has not yet expired.
+
+    For each request ``environ`` that is monitored, there are several
+    variables that are stored:
+
+        ``paste.bytes_received``
+
+            This is the total number of bytes received for the given
+            request; it can be compared with ``CONTENT_LENGTH`` to
+            build a percentage complete.  This is an integer value.
+
+        ``paste.request_started``
+
+            This is the time (in seconds) when the request was started
+            as obtained from ``time.time()``.  One would want to format
+            this for presentation to the user, if necessary.
+
+        ``paste.request_finished``
+
+            This is the time (in seconds) when the request was finished,
+            canceled, or otherwise disconnected.  This is None while
+            the given upload is still in-progress.
+
+    TODO: turn monitor into a queue and purge queue of finished
+          requests that have passed the timeout period.
+    """
+    def __init__(self, application, threshold=None, timeout=None):
+        self.application = application
+        self.threshold = threshold or DEFAULT_THRESHOLD
+        self.timeout   = timeout   or DEFAULT_TIMEOUT
+        self.monitor   = []
+
+    def __call__(self, environ, start_response):
+        length = environ.get('CONTENT_LENGTH', 0)
+        if length and int(length) > self.threshold:
+            # replace input file object
+            self.monitor.append(environ)
+            environ[ENVIRON_RECEIVED] = 0
+            environ[REQUEST_STARTED] = time.time()
+            environ[REQUEST_FINISHED] = None
+            environ['wsgi.input'] = \
+                _ProgressFile(environ, environ['wsgi.input'])
+            def finalizer(exc_info=None):
+                environ[REQUEST_FINISHED] = time.time()
+            return catch_errors(self.application, environ,
+                       start_response, finalizer, finalizer)
+        return self.application(environ, start_response)
+
+    def uploads(self):
+        return self.monitor
+
+class UploadProgressReporter(object):
+    """
+    reports on the progress of uploads for a given user
+
+    This reporter returns a JSON file (for use in AJAX) listing the
+    uploads in progress for the given user.  By default, this reporter
+    uses the ``REMOTE_USER`` environment to compare between the current
+    request and uploads in-progress.  If they match, then a response
+    record is formed.
+
+        ``match()``
+
+            This member function can be overriden to provide alternative
+            matching criteria.  It takes two environments, the first
+            is the current request, the second is a current upload.
+
+        ``report()``
+
+            This member function takes an environment and builds a
+            ``dict`` that will be used to create a JSON mapping for
+            the given upload.  By default, this just includes the
+            percent complete and the request url.
+
+    """
+    def __init__(self, monitor):
+        self.monitor   = monitor
+
+    def match(self, search_environ, upload_environ):
+        if search_environ.get('REMOTE_USER', None) == \
+           upload_environ.get('REMOTE_USER', 0):
+            return True
+        return False
+
+    def report(self, environ):
+        retval = { 'started': time.strftime("%Y-%m-%d %H:%M:%S",
+                                time.gmtime(environ[REQUEST_STARTED])),
+                   'finished': '',
+                   'content_length': environ.get('CONTENT_LENGTH'),
+                   'bytes_received': environ[ENVIRON_RECEIVED],
+                   'path_info': environ.get('PATH_INFO',''),
+                   'query_string': environ.get('QUERY_STRING','')}
+        finished = environ[REQUEST_FINISHED]
+        if finished:
+            retval['finished'] = time.strftime("%Y:%m:%d %H:%M:%S",
+                                               time.gmtime(finished))
+        return retval
+
+    def __call__(self, environ, start_response):
+        body = []
+        for map in [self.report(env) for env in self.monitor.uploads()
+                                             if self.match(environ, env)]:
+            parts = []
+            for k, v in map.items():
+                v = str(v).replace("\\", "\\\\").replace('"', '\\"')
+                parts.append('%s: "%s"' % (k, v))
+            body.append("{ %s }" % ", ".join(parts))
+        body = "[ %s ]" % ", ".join(body)
+        start_response("200 OK", [('Content-Type', 'text/plain'),
+                                  ('Content-Length', len(body))])
+        return [body]
+
+__all__ = ['UploadProgressMonitor', 'UploadProgressReporter']
+
+if "__main__" == __name__:
+    import doctest
+    doctest.testmod(optionflags=doctest.ELLIPSIS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/proxy.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/proxy.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/proxy.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,283 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+An application that proxies WSGI requests to a remote server.
+
+TODO:
+
+* Send ``Via`` header?  It's not clear to me this is a Via in the
+  style of a typical proxy.
+
+* Other headers or metadata?  I put in X-Forwarded-For, but that's it.
+
+* Signed data of non-HTTP keys?  This would be for things like
+  REMOTE_USER.
+
+* Something to indicate what the original URL was?  The original host,
+  scheme, and base path.
+
+* Rewriting ``Location`` headers?  mod_proxy does this.
+
+* Rewriting body?  (Probably not on this one -- that can be done with
+  a different middleware that wraps this middleware)
+
+* Example::  
+    
+    use = egg:Paste#proxy
+    address = http://server3:8680/exist/rest/db/orgs/sch/config/
+    allowed_request_methods = GET
+  
+"""
+
+import httplib
+import urlparse
+import urllib
+
+from paste import httpexceptions
+from paste.util.converters import aslist
+
+# Remove these headers from response (specify lower case header
+# names):
+filtered_headers = (     
+    'transfer-encoding',
+    'connection',
+    'keep-alive',
+    'proxy-authenticate',
+    'proxy-authorization',
+    'te',
+    'trailers',
+    'upgrade',
+)
+
+class Proxy(object):
+
+    def __init__(self, address, allowed_request_methods=(),
+                 suppress_http_headers=()):
+        self.address = address
+        self.parsed = urlparse.urlsplit(address)
+        self.scheme = self.parsed[0].lower()
+        self.host = self.parsed[1]
+        self.path = self.parsed[2]
+        self.allowed_request_methods = [
+            x.lower() for x in allowed_request_methods if x]
+        
+        self.suppress_http_headers = [
+            x.lower() for x in suppress_http_headers if x]
+
+    def __call__(self, environ, start_response):
+        if (self.allowed_request_methods and 
+            environ['REQUEST_METHOD'].lower() not in self.allowed_request_methods):
+            return httpexceptions.HTTPBadRequest("Disallowed")(environ, start_response)
+
+        if self.scheme == 'http':
+            ConnClass = httplib.HTTPConnection
+        elif self.scheme == 'https':
+            ConnClass = httplib.HTTPSConnection
+        else:
+            raise ValueError(
+                "Unknown scheme for %r: %r" % (self.address, self.scheme))
+        conn = ConnClass(self.host)
+        headers = {}
+        for key, value in environ.items():
+            if key.startswith('HTTP_'):
+                key = key[5:].lower().replace('_', '-')
+                if key == 'host' or key in self.suppress_http_headers:
+                    continue
+                headers[key] = value
+        headers['host'] = self.host
+        if 'REMOTE_ADDR' in environ:
+            headers['x-forwarded-for'] = environ['REMOTE_ADDR']
+        if environ.get('CONTENT_TYPE'):
+            headers['content-type'] = environ['CONTENT_TYPE']
+        if environ.get('CONTENT_LENGTH'):
+            if environ['CONTENT_LENGTH'] == '-1':
+                # This is a special case, where the content length is basically undetermined
+                body = environ['wsgi.input'].read(-1)
+                headers['content-length'] = str(len(body))
+            else:
+                headers['content-length'] = environ['CONTENT_LENGTH'] 
+                length = int(environ['CONTENT_LENGTH'])
+                body = environ['wsgi.input'].read(length)
+        else:
+            body = ''
+            
+        path_info = urllib.quote(environ['PATH_INFO'])
+        if self.path:            
+            request_path = path_info
+            if request_path and request_path[0] == '/':
+                request_path = request_path[1:]
+                
+            path = urlparse.urljoin(self.path, request_path)
+        else:
+            path = path_info
+        if environ.get('QUERY_STRING'):
+            path += '?' + environ['QUERY_STRING']
+            
+        conn.request(environ['REQUEST_METHOD'],
+                     path,
+                     body, headers)
+        res = conn.getresponse()
+        headers_out = parse_headers(res.msg)
+        
+        status = '%s %s' % (res.status, res.reason)
+        start_response(status, headers_out)
+        # @@: Default?
+        length = res.getheader('content-length')
+        if length is not None:
+            body = res.read(int(length))
+        else:
+            body = res.read()
+        conn.close()
+        return [body]
+
+def make_proxy(global_conf, address, allowed_request_methods="",
+               suppress_http_headers=""):
+    """
+    Make a WSGI application that proxies to another address:
+    
+    ``address``
+        the full URL ending with a trailing ``/``
+        
+    ``allowed_request_methods``:
+        a space seperated list of request methods (e.g., ``GET POST``)
+        
+    ``suppress_http_headers``
+        a space seperated list of http headers (lower case, without
+        the leading ``http_``) that should not be passed on to target
+        host
+    """
+    allowed_request_methods = aslist(allowed_request_methods)
+    suppress_http_headers = aslist(suppress_http_headers)
+    return Proxy(
+        address,
+        allowed_request_methods=allowed_request_methods,
+        suppress_http_headers=suppress_http_headers)
+
+
+class TransparentProxy(object):
+
+    """
+    A proxy that sends the request just as it was given, including
+    respecting HTTP_HOST, wsgi.url_scheme, etc.
+
+    This is a way of translating WSGI requests directly to real HTTP
+    requests.  All information goes in the environment; modify it to
+    modify the way the request is made.
+
+    If you specify ``force_host`` (and optionally ``force_scheme``)
+    then HTTP_HOST won't be used to determine where to connect to;
+    instead a specific host will be connected to, but the ``Host``
+    header in the request will remain intact.
+    """
+
+    def __init__(self, force_host=None,
+                 force_scheme='http'):
+        self.force_host = force_host
+        self.force_scheme = force_scheme
+
+    def __repr__(self):
+        return '<%s %s force_host=%r force_scheme=%r>' % (
+            self.__class__.__name__,
+            hex(id(self)),
+            self.force_host, self.force_scheme)
+
+    def __call__(self, environ, start_response):
+        scheme = environ['wsgi.url_scheme']
+        if self.force_host is None:
+            conn_scheme = scheme
+        else:
+            conn_scheme = self.force_scheme
+        if conn_scheme == 'http':
+            ConnClass = httplib.HTTPConnection
+        elif conn_scheme == 'https':
+            ConnClass = httplib.HTTPSConnection
+        else:
+            raise ValueError(
+                "Unknown scheme %r" % scheme)
+        if 'HTTP_HOST' not in environ:
+            raise ValueError(
+                "WSGI environ must contain an HTTP_HOST key")
+        host = environ['HTTP_HOST']
+        if self.force_host is None:
+            conn_host = host
+        else:
+            conn_host = self.force_host
+        conn = ConnClass(conn_host)
+        headers = {}
+        for key, value in environ.items():
+            if key.startswith('HTTP_'):
+                key = key[5:].lower().replace('_', '-')
+                headers[key] = value
+        headers['host'] = host
+        if 'REMOTE_ADDR' in environ and 'HTTP_X_FORWARDED_FOR' not in environ:
+            headers['x-forwarded-for'] = environ['REMOTE_ADDR']
+        if environ.get('CONTENT_TYPE'):
+            headers['content-type'] = environ['CONTENT_TYPE']
+        if environ.get('CONTENT_LENGTH'):
+            length = int(environ['CONTENT_LENGTH'])
+            body = environ['wsgi.input'].read(length)
+            if length == -1:
+                environ['CONTENT_LENGTH'] = str(len(body))
+        elif 'CONTENT_LENGTH' not in environ:
+            body = ''
+            length = 0
+        else:
+            body = ''
+            length = 0
+        
+        path = (environ.get('SCRIPT_NAME', '')
+                + environ.get('PATH_INFO', ''))
+        path = urllib.quote(path)
+        if 'QUERY_STRING' in environ:
+            path += '?' + environ['QUERY_STRING']
+        conn.request(environ['REQUEST_METHOD'],
+                     path, body, headers)
+        res = conn.getresponse()
+        headers_out = parse_headers(res.msg)
+                
+        status = '%s %s' % (res.status, res.reason)
+        start_response(status, headers_out)
+        # @@: Default?
+        length = res.getheader('content-length')
+        if length is not None:
+            body = res.read(int(length))
+        else:
+            body = res.read()
+        conn.close()
+        return [body]
+
+def parse_headers(message):
+    """
+    Turn a Message object into a list of WSGI-style headers.
+    """
+    headers_out = []        
+    for full_header in message.headers:
+        if not full_header:            
+            # Shouldn't happen, but we'll just ignore
+            continue                     
+        if full_header[0].isspace():
+            # Continuation line, add to the last header
+            if not headers_out:                        
+                raise ValueError(
+                    "First header starts with a space (%r)" % full_header)
+            last_header, last_value = headers_out.pop()                   
+            value = last_value + ' ' + full_header.strip()
+            headers_out.append((last_header, value))      
+            continue                                
+        try:        
+            header, value = full_header.split(':', 1)
+        except:                                      
+            raise ValueError("Invalid header: %r" % full_header)
+        value = value.strip()                                   
+        if header.lower() not in filtered_headers:
+            headers_out.append((header, value))   
+    return headers_out
+
+def make_transparent_proxy(
+    global_conf, force_host=None, force_scheme='http'):
+    """
+    Create a proxy that connects to a specific host, but does
+    absolutely no other filtering, including the Host header.
+    """
+    return TransparentProxy(force_host=force_host,
+                            force_scheme=force_scheme)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/recursive.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/recursive.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/recursive.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,405 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware to make internal requests and forward requests internally.
+
+When applied, several keys are added to the environment that will allow
+you to trigger recursive redirects and forwards.
+
+  paste.recursive.include:
+      When you call
+      ``environ['paste.recursive.include'](new_path_info)`` a response
+      will be returned.  The response has a ``body`` attribute, a
+      ``status`` attribute, and a ``headers`` attribute.
+
+  paste.recursive.script_name:
+      The ``SCRIPT_NAME`` at the point that recursive lives.  Only
+      paths underneath this path can be redirected to.
+
+  paste.recursive.old_path_info:
+      A list of previous ``PATH_INFO`` values from previous redirects.
+
+Raise ``ForwardRequestException(new_path_info)`` to do a forward
+(aborting the current request).
+"""
+
+from cStringIO import StringIO
+import warnings
+
+__all__ = ['RecursiveMiddleware']
+__pudge_all__ =  ['RecursiveMiddleware', 'ForwardRequestException']
+
+class RecursionLoop(AssertionError):
+    # Subclasses AssertionError for legacy reasons
+    """Raised when a recursion enters into a loop"""
+
+class CheckForRecursionMiddleware(object):
+    def __init__(self, app, env):
+        self.app = app
+        self.env = env
+
+    def __call__(self, environ, start_response):
+        path_info = environ.get('PATH_INFO','')
+        if path_info in self.env.get(
+            'paste.recursive.old_path_info', []):
+            raise RecursionLoop(
+                "Forwarding loop detected; %r visited twice (internal "
+                "redirect path: %s)"
+                % (path_info, self.env['paste.recursive.old_path_info']))
+        old_path_info = self.env.setdefault('paste.recursive.old_path_info', [])
+        old_path_info.append(self.env.get('PATH_INFO', ''))
+        return self.app(environ, start_response)
+
+class RecursiveMiddleware(object):
+
+    """
+    A WSGI middleware that allows for recursive and forwarded calls.
+    All these calls go to the same 'application', but presumably that
+    application acts differently with different URLs.  The forwarded
+    URLs must be relative to this container.
+
+    Interface is entirely through the ``paste.recursive.forward`` and
+    ``paste.recursive.include`` environmental keys.
+    """
+
+    def __init__(self, application, global_conf=None):
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        environ['paste.recursive.forward'] = Forwarder(
+            self.application,
+            environ,
+            start_response)
+        environ['paste.recursive.include'] = Includer(
+            self.application,
+            environ,
+            start_response)
+        environ['paste.recursive.include_app_iter'] = IncluderAppIter(
+            self.application,
+            environ,
+            start_response)
+        my_script_name = environ.get('SCRIPT_NAME', '')
+        environ['paste.recursive.script_name'] = my_script_name
+        try:
+            return self.application(environ, start_response)
+        except ForwardRequestException, e:
+            middleware = CheckForRecursionMiddleware(
+                e.factory(self), environ)
+            return middleware(environ, start_response)
+
+class ForwardRequestException(Exception):
+    """
+    Used to signal that a request should be forwarded to a different location.
+
+    ``url``
+        The URL to forward to starting with a ``/`` and relative to
+        ``RecursiveMiddleware``. URL fragments can also contain query strings
+        so ``/error?code=404`` would be a valid URL fragment.
+
+    ``environ``
+        An altertative WSGI environment dictionary to use for the forwarded
+        request. If specified is used *instead* of the ``url_fragment``
+
+    ``factory``
+        If specifed ``factory`` is used instead of ``url`` or ``environ``.
+        ``factory`` is a callable that takes a WSGI application object
+        as the first argument and returns an initialised WSGI middleware
+        which can alter the forwarded response.
+
+    Basic usage (must have ``RecursiveMiddleware`` present) :
+
+    .. code-block:: python
+
+        from paste.recursive import ForwardRequestException
+        def app(environ, start_response):
+            if environ['PATH_INFO'] == '/hello':
+                start_response("200 OK", [('Content-type', 'text/plain')])
+                return ['Hello World!']
+            elif environ['PATH_INFO'] == '/error':
+                start_response("404 Not Found", [('Content-type', 'text/plain')])
+                return ['Page not found']
+            else:
+                raise ForwardRequestException('/error')
+
+        from paste.recursive import RecursiveMiddleware
+        app = RecursiveMiddleware(app)
+
+    If you ran this application and visited ``/hello`` you would get a
+    ``Hello World!`` message. If you ran the application and visited
+    ``/not_found`` a ``ForwardRequestException`` would be raised and the caught
+    by the ``RecursiveMiddleware``. The ``RecursiveMiddleware`` would then
+    return the headers and response from the ``/error`` URL but would display
+    a ``404 Not found`` status message.
+
+    You could also specify an ``environ`` dictionary instead of a url. Using
+    the same example as before:
+
+    .. code-block:: python
+
+        def app(environ, start_response):
+            ... same as previous example ...
+            else:
+                new_environ = environ.copy()
+                new_environ['PATH_INFO'] = '/error'
+                raise ForwardRequestException(environ=new_environ)
+
+    Finally, if you want complete control over every aspect of the forward you
+    can specify a middleware factory. For example to keep the old status code
+    but use the headers and resposne body from the forwarded response you might
+    do this:
+
+    .. code-block:: python
+
+        from paste.recursive import ForwardRequestException
+        from paste.recursive import RecursiveMiddleware
+        from paste.errordocument import StatusKeeper
+
+        def app(environ, start_response):
+            if environ['PATH_INFO'] == '/hello':
+                start_response("200 OK", [('Content-type', 'text/plain')])
+                return ['Hello World!']
+            elif environ['PATH_INFO'] == '/error':
+                start_response("404 Not Found", [('Content-type', 'text/plain')])
+                return ['Page not found']
+            else:
+                def factory(app):
+                    return StatusKeeper(app, status='404 Not Found', url='/error')
+                raise ForwardRequestException(factory=factory)
+
+        app = RecursiveMiddleware(app)
+    """
+
+    def __init__(
+        self,
+        url=None,
+        environ={},
+        factory=None,
+        path_info=None):
+        # Check no incompatible options have been chosen
+        if factory and url:
+            raise TypeError(
+                'You cannot specify factory and a url in '
+                'ForwardRequestException')
+        elif factory and environ:
+            raise TypeError(
+                'You cannot specify factory and environ in '
+                'ForwardRequestException')
+        if url and environ:
+            raise TypeError(
+                'You cannot specify environ and url in '
+                'ForwardRequestException')
+
+        # set the path_info or warn about its use.
+        if path_info:
+            if not url:
+                warnings.warn(
+                    "ForwardRequestException(path_info=...) has been deprecated; please "
+                    "use ForwardRequestException(url=...)",
+                    DeprecationWarning, 2)
+            else:
+                raise TypeError('You cannot use url and path_info in ForwardRequestException')
+            self.path_info = path_info
+
+        # If the url can be treated as a path_info do that
+        if url and not '?' in str(url):
+            self.path_info = url
+
+        # Base middleware
+        class ForwardRequestExceptionMiddleware(object):
+            def __init__(self, app):
+                self.app = app
+
+        # Otherwise construct the appropriate middleware factory
+        if hasattr(self, 'path_info'):
+            p = self.path_info
+            def factory_(app):
+                class PathInfoForward(ForwardRequestExceptionMiddleware):
+                    def __call__(self, environ, start_response):
+                        environ['PATH_INFO'] = p
+                        return self.app(environ, start_response)
+                return PathInfoForward(app)
+            self.factory = factory_
+        elif url:
+            def factory_(app):
+                class URLForward(ForwardRequestExceptionMiddleware):
+                    def __call__(self, environ, start_response):
+                        environ['PATH_INFO'] = url.split('?')[0]
+                        environ['QUERY_STRING'] = url.split('?')[1]
+                        return self.app(environ, start_response)
+                return URLForward(app)
+            self.factory = factory_
+        elif environ:
+            def factory_(app):
+                class EnvironForward(ForwardRequestExceptionMiddleware):
+                    def __call__(self, environ_, start_response):
+                        return self.app(environ, start_response)
+                return EnvironForward(app)
+            self.factory = factory_
+        else:
+            self.factory = factory
+
+class Recursive(object):
+
+    def __init__(self, application, environ, start_response):
+        self.application = application
+        self.original_environ = environ.copy()
+        self.previous_environ = environ
+        self.start_response = start_response
+
+    def __call__(self, path, extra_environ=None):
+        """
+        `extra_environ` is an optional dictionary that is also added
+        to the forwarded request.  E.g., ``{'HTTP_HOST': 'new.host'}``
+        could be used to forward to a different virtual host.
+        """
+        environ = self.original_environ.copy()
+        if extra_environ:
+            environ.update(extra_environ)
+        environ['paste.recursive.previous_environ'] = self.previous_environ
+        base_path = self.original_environ.get('SCRIPT_NAME')
+        if path.startswith('/'):
+            assert path.startswith(base_path), (
+                "You can only forward requests to resources under the "
+                "path %r (not %r)" % (base_path, path))
+            path = path[len(base_path)+1:]
+        assert not path.startswith('/')
+        path_info = '/' + path
+        environ['PATH_INFO'] = path_info
+        environ['REQUEST_METHOD'] = 'GET'
+        environ['CONTENT_LENGTH'] = '0'
+        environ['CONTENT_TYPE'] = ''
+        environ['wsgi.input'] = StringIO('')
+        return self.activate(environ)
+
+    def activate(self, environ):
+        raise NotImplementedError
+
+    def __repr__(self):
+        return '<%s.%s from %s>' % (
+            self.__class__.__module__,
+            self.__class__.__name__,
+            self.original_environ.get('SCRIPT_NAME') or '/')
+
+class Forwarder(Recursive):
+
+    """
+    The forwarder will try to restart the request, except with
+    the new `path` (replacing ``PATH_INFO`` in the request).
+
+    It must not be called after and headers have been returned.
+    It returns an iterator that must be returned back up the call
+    stack, so it must be used like:
+
+    .. code-block:: python
+
+        return environ['paste.recursive.forward'](path)
+
+    Meaningful transformations cannot be done, since headers are
+    sent directly to the server and cannot be inspected or
+    rewritten.
+    """
+
+    def activate(self, environ):
+        warnings.warn(
+            "recursive.Forwarder has been deprecated; please use "
+            "ForwardRequestException",
+            DeprecationWarning, 2)
+        return self.application(environ, self.start_response)
+
+
+class Includer(Recursive):
+
+    """
+    Starts another request with the given path and adding or
+    overwriting any values in the `extra_environ` dictionary.
+    Returns an IncludeResponse object.
+    """
+
+    def activate(self, environ):
+        response = IncludedResponse()
+        def start_response(status, headers, exc_info=None):
+            if exc_info:
+                raise exc_info[0], exc_info[1], exc_info[2]
+            response.status = status
+            response.headers = headers
+            return response.write
+        app_iter = self.application(environ, start_response)
+        try:
+            for s in app_iter:
+                response.write(s)
+        finally:
+            if hasattr(app_iter, 'close'):
+                app_iter.close()
+        response.close()
+        return response
+
+class IncludedResponse(object):
+
+    def __init__(self):
+        self.headers = None
+        self.status = None
+        self.output = StringIO()
+        self.str = None
+
+    def close(self):
+        self.str = self.output.getvalue()
+        self.output.close()
+        self.output = None
+
+    def write(self, s):
+        assert self.output is not None, (
+            "This response has already been closed and no further data "
+            "can be written.")
+        self.output.write(s)
+
+    def __str__(self):
+        return self.body
+
+    def body__get(self):
+        if self.str is None:
+            return self.output.getvalue()
+        else:
+            return self.str
+    body = property(body__get)
+
+
+class IncluderAppIter(Recursive):
+    """
+    Like Includer, but just stores the app_iter response
+    (be sure to call close on the response!)
+    """
+
+    def activate(self, environ):
+        response = IncludedAppIterResponse()
+        def start_response(status, headers, exc_info=None):
+            if exc_info:
+                raise exc_info[0], exc_info[1], exc_info[2]
+            response.status = status
+            response.headers = headers
+            return response.write
+        app_iter = self.application(environ, start_response)
+        response.app_iter = app_iter
+        return response
+
+class IncludedAppIterResponse(object):
+
+    def __init__(self):
+        self.status = None
+        self.headers = None
+        self.accumulated = []
+        self.app_iter = None
+        self._closed = False
+
+    def close(self):
+        assert not self._closed, (
+            "Tried to close twice")
+        if hasattr(self.app_iter, 'close'):
+            self.app_iter.close()
+
+    def write(self, s):
+        self.accumulated.append
+
+def make_recursive_middleware(app, global_conf):
+    return RecursiveMiddleware(app)
+
+make_recursive_middleware.__doc__ = __doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/registry.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/registry.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/registry.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,581 @@
+# (c) 2005 Ben Bangert
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""Registry for handling request-local module globals sanely
+
+Dealing with module globals in a thread-safe way is good if your
+application is the sole responder in a thread, however that approach fails
+to properly account for various scenarios that occur with WSGI applications
+and middleware.
+
+What is actually needed in the case where a module global is desired that
+is always set properly depending on the current request, is a stacked
+thread-local object. Such an object is popped or pushed during the request
+cycle so that it properly represents the object that should be active for
+the current request.
+
+To make it easy to deal with such variables, this module provides a special
+StackedObjectProxy class which you can instantiate and attach to your
+module where you'd like others to access it. The object you'd like this to
+actually "be" during the request is then registered with the
+RegistryManager middleware, which ensures that for the scope of the current
+WSGI application everything will work properly.
+
+Example:
+
+.. code-block:: python
+
+    #yourpackage/__init__.py
+
+    from paste.registry import RegistryManager, StackedObjectProxy
+    myglobal = StackedObjectProxy()
+
+    #wsgi app stack
+    app = RegistryManager(yourapp)
+
+    #inside your wsgi app
+    class yourapp(object):
+        def __call__(self, environ, start_response):
+            obj = someobject  # The request-local object you want to access
+                              # via yourpackage.myglobal
+            if environ.has_key('paste.registry'):
+                environ['paste.registry'].register(myglobal, obj)
+
+You will then be able to import yourpackage anywhere in your WSGI app or in
+the calling stack below it and be assured that it is using the object you
+registered with Registry.
+
+RegistryManager can be in the WSGI stack multiple times, each time it
+appears it registers a new request context.
+
+
+Performance
+===========
+
+The overhead of the proxy object is very minimal, however if you are using
+proxy objects extensively (Thousands of accesses per request or more), there
+are some ways to avoid them. A proxy object runs approximately 3-20x slower
+than direct access to the object, this is rarely your performance bottleneck
+when developing web applications.
+
+Should you be developing a system which may be accessing the proxy object
+thousands of times per request, the performance of the proxy will start to
+become more noticeable. In that circumstance, the problem can be avoided by
+getting at the actual object via the proxy with the ``_current_obj`` function:
+
+.. code-block:: python
+
+    #sessions.py
+    Session = StackedObjectProxy()
+    # ... initialization code, etc.
+
+    # somemodule.py
+    import sessions
+
+    def somefunc():
+        session = sessions.Session._current_obj()
+        # ... tons of session access
+
+This way the proxy is used only once to retrieve the object for the current
+context and the overhead is minimized while still making it easy to access
+the underlying object. The ``_current_obj`` function is preceded by an
+underscore to more likely avoid clashing with the contained object's
+attributes.
+
+**NOTE:** This is *highly* unlikely to be an issue in the vast majority of
+cases, and requires incredibly large amounts of proxy object access before
+one should consider the proxy object to be causing slow-downs. This section
+is provided solely in the extremely rare case that it is an issue so that a
+quick way to work around it is documented.
+
+"""
+import sys
+import paste.util.threadinglocal as threadinglocal
+
+__all__ = ['StackedObjectProxy', 'RegistryManager', 'StackedObjectRestorer',
+           'restorer']
+
+class NoDefault(object): pass
+
+class StackedObjectProxy(object):
+    """Track an object instance internally using a stack
+
+    The StackedObjectProxy proxies access to an object internally using a
+    stacked thread-local. This makes it safe for complex WSGI environments
+    where access to the object may be desired in multiple places without
+    having to pass the actual object around.
+
+    New objects are added to the top of the stack with _push_object while
+    objects can be removed with _pop_object.
+
+    """
+    def __init__(self, default=NoDefault, name="Default"):
+        """Create a new StackedObjectProxy
+
+        If a default is given, its used in every thread if no other object
+        has been pushed on.
+
+        """
+        self.__dict__['____name__'] = name
+        self.__dict__['____local__'] = threadinglocal.local()
+        if default is not NoDefault:
+            self.__dict__['____default_object__'] = default
+
+    def __dir__(self):
+        """Return a list of the StackedObjectProxy's and proxied
+        object's (if one exists) names.
+        """
+        dir_list = dir(self.__class__) + self.__dict__.keys()
+        try:
+            dir_list.extend(dir(self._current_obj()))
+        except TypeError:
+            pass
+        dir_list.sort()
+        return dir_list
+
+    def __getattr__(self, attr):
+        return getattr(self._current_obj(), attr)
+
+    def __setattr__(self, attr, value):
+        setattr(self._current_obj(), attr, value)
+
+    def __delattr__(self, name):
+        delattr(self._current_obj(), name)
+
+    def __getitem__(self, key):
+        return self._current_obj()[key]
+
+    def __setitem__(self, key, value):
+        self._current_obj()[key] = value
+
+    def __delitem__(self, key):
+        del self._current_obj()[key]
+
+    def __call__(self, *args, **kw):
+        return self._current_obj()(*args, **kw)
+
+    def __repr__(self):
+        try:
+            return repr(self._current_obj())
+        except (TypeError, AttributeError):
+            return '<%s.%s object at 0x%x>' % (self.__class__.__module__,
+                                               self.__class__.__name__,
+                                               id(self))
+
+    def __iter__(self):
+        return iter(self._current_obj())
+
+    def __len__(self):
+        return len(self._current_obj())
+
+    def __contains__(self, key):
+        return key in self._current_obj()
+
+    def __nonzero__(self):
+        return bool(self._current_obj())
+
+    def _current_obj(self):
+        """Returns the current active object being proxied to
+
+        In the event that no object was pushed, the default object if
+        provided will be used. Otherwise, a TypeError will be raised.
+
+        """
+        try:
+            objects = self.____local__.objects
+        except AttributeError:
+            objects = None
+        if objects:
+            return objects[-1]
+        else:
+            obj = self.__dict__.get('____default_object__', NoDefault)
+            if obj is not NoDefault:
+                return obj
+            else:
+                raise TypeError(
+                    'No object (name: %s) has been registered for this '
+                    'thread' % self.____name__)
+
+    def _push_object(self, obj):
+        """Make ``obj`` the active object for this thread-local.
+
+        This should be used like:
+
+        .. code-block:: python
+
+            obj = yourobject()
+            module.glob = StackedObjectProxy()
+            module.glob._push_object(obj)
+            try:
+                ... do stuff ...
+            finally:
+                module.glob._pop_object(conf)
+
+        """
+        try:
+            self.____local__.objects.append(obj)
+        except AttributeError:
+            self.____local__.objects = []
+            self.____local__.objects.append(obj)
+
+    def _pop_object(self, obj=None):
+        """Remove a thread-local object.
+
+        If ``obj`` is given, it is checked against the popped object and an
+        error is emitted if they don't match.
+
+        """
+        try:
+            popped = self.____local__.objects.pop()
+            if obj and popped is not obj:
+                raise AssertionError(
+                    'The object popped (%s) is not the same as the object '
+                    'expected (%s)' % (popped, obj))
+        except AttributeError:
+            raise AssertionError('No object has been registered for this thread')
+
+    def _object_stack(self):
+        """Returns all of the objects stacked in this container
+
+        (Might return [] if there are none)
+        """
+        try:
+            try:
+                objs = self.____local__.objects
+            except AttributeError:
+                return []
+            return objs[:]
+        except AssertionError:
+            return []
+
+    # The following methods will be swapped for their original versions by
+    # StackedObjectRestorer when restoration is enabled. The original
+    # functions (e.g. _current_obj) will be available at _current_obj_orig
+
+    def _current_obj_restoration(self):
+        request_id = restorer.in_restoration()
+        if request_id:
+            return restorer.get_saved_proxied_obj(self, request_id)
+        return self._current_obj_orig()
+    _current_obj_restoration.__doc__ = \
+        ('%s\n(StackedObjectRestorer restoration enabled)' % \
+         _current_obj.__doc__)
+
+    def _push_object_restoration(self, obj):
+        if not restorer.in_restoration():
+            self._push_object_orig(obj)
+    _push_object_restoration.__doc__ = \
+        ('%s\n(StackedObjectRestorer restoration enabled)' % \
+         _push_object.__doc__)
+
+    def _pop_object_restoration(self, obj=None):
+        if not restorer.in_restoration():
+            self._pop_object_orig(obj)
+    _pop_object_restoration.__doc__ = \
+        ('%s\n(StackedObjectRestorer restoration enabled)' % \
+         _pop_object.__doc__)
+
+class Registry(object):
+    """Track objects and stacked object proxies for removal
+
+    The Registry object is instantiated a single time for the request no
+    matter how many times the RegistryManager is used in a WSGI stack. Each
+    RegistryManager must call ``prepare`` before continuing the call to
+    start a new context for object registering.
+
+    Each context is tracked with a dict inside a list. The last list
+    element is the currently executing context. Each context dict is keyed
+    by the id of the StackedObjectProxy instance being proxied, the value
+    is a tuple of the StackedObjectProxy instance and the object being
+    tracked.
+
+    """
+    def __init__(self):
+        """Create a new Registry object
+
+        ``prepare`` must still be called before this Registry object can be
+        used to register objects.
+
+        """
+        self.reglist = []
+
+    def prepare(self):
+        """Used to create a new registry context
+
+        Anytime a new RegistryManager is called, ``prepare`` needs to be
+        called on the existing Registry object. This sets up a new context
+        for registering objects.
+
+        """
+        self.reglist.append({})
+
+    def register(self, stacked, obj):
+        """Register an object with a StackedObjectProxy"""
+        myreglist = self.reglist[-1]
+        stacked_id = id(stacked)
+        if stacked_id in myreglist:
+            stacked._pop_object(myreglist[stacked_id][1])
+            del myreglist[stacked_id]
+        stacked._push_object(obj)
+        myreglist[stacked_id] = (stacked, obj)
+
+    def multiregister(self, stacklist):
+        """Register a list of tuples
+
+        Similar call semantics as register, except this registers
+        multiple objects at once.
+
+        Example::
+
+            registry.multiregister([(sop, obj), (anothersop, anotherobj)])
+
+        """
+        myreglist = self.reglist[-1]
+        for stacked, obj in stacklist:
+            stacked_id = id(stacked)
+            if stacked_id in myreglist:
+                stacked._pop_object(myreglist[stacked_id][1])
+                del myreglist[stacked_id]
+            stacked._push_object(obj)
+            myreglist[stacked_id] = (stacked, obj)
+
+    # Replace now does the same thing as register
+    replace = register
+
+    def cleanup(self):
+        """Remove all objects from all StackedObjectProxy instances that
+        were tracked at this Registry context"""
+        for stacked, obj in self.reglist[-1].itervalues():
+            stacked._pop_object(obj)
+        self.reglist.pop()
+
+class RegistryManager(object):
+    """Creates and maintains a Registry context
+
+    RegistryManager creates a new registry context for the registration of
+    StackedObjectProxy instances. Multiple RegistryManager's can be in a
+    WSGI stack and will manage the context so that the StackedObjectProxies
+    always proxy to the proper object.
+
+    The object being registered can be any object sub-class, list, or dict.
+
+    Registering objects is done inside a WSGI application under the
+    RegistryManager instance, using the ``environ['paste.registry']``
+    object which is a Registry instance.
+
+    """
+    def __init__(self, application, streaming=False):
+        self.application = application
+        self.streaming = streaming
+
+    def __call__(self, environ, start_response):
+        app_iter = None
+        reg = environ.setdefault('paste.registry', Registry())
+        reg.prepare()
+        if self.streaming:
+            return self.streaming_iter(reg, environ, start_response)
+
+        try:
+            app_iter = self.application(environ, start_response)
+        except Exception, e:
+            # Regardless of if the content is an iterable, generator, list
+            # or tuple, we clean-up right now. If its an iterable/generator
+            # care should be used to ensure the generator has its own ref
+            # to the actual object
+            if environ.get('paste.evalexception'):
+                # EvalException is present in the WSGI stack
+                expected = False
+                for expect in environ.get('paste.expected_exceptions', []):
+                    if isinstance(e, expect):
+                        expected = True
+                if not expected:
+                    # An unexpected exception: save state for EvalException
+                    restorer.save_registry_state(environ)
+            reg.cleanup()
+            raise
+        except:
+            # Save state for EvalException if it's present
+            if environ.get('paste.evalexception'):
+                restorer.save_registry_state(environ)
+            reg.cleanup()
+            raise
+        else:
+            reg.cleanup()
+
+        return app_iter
+
+    def streaming_iter(self, reg, environ, start_response):
+        try:
+            for item in self.application(environ, start_response):
+                yield item
+        except Exception, e:
+            # Regardless of if the content is an iterable, generator, list
+            # or tuple, we clean-up right now. If its an iterable/generator
+            # care should be used to ensure the generator has its own ref
+            # to the actual object
+            if environ.get('paste.evalexception'):
+                # EvalException is present in the WSGI stack
+                expected = False
+                for expect in environ.get('paste.expected_exceptions', []):
+                    if isinstance(e, expect):
+                        expected = True
+                if not expected:
+                    # An unexpected exception: save state for EvalException
+                    restorer.save_registry_state(environ)
+            reg.cleanup()
+            raise
+        except:
+            # Save state for EvalException if it's present
+            if environ.get('paste.evalexception'):
+                restorer.save_registry_state(environ)
+            reg.cleanup()
+            raise
+        else:
+            reg.cleanup()
+
+
+class StackedObjectRestorer(object):
+    """Track StackedObjectProxies and their proxied objects for automatic
+    restoration within EvalException's interactive debugger.
+
+    An instance of this class tracks all StackedObjectProxy state in existence
+    when unexpected exceptions are raised by WSGI applications housed by
+    EvalException and RegistryManager. Like EvalException, this information is
+    stored for the life of the process.
+
+    When an unexpected exception occurs and EvalException is present in the
+    WSGI stack, save_registry_state is intended to be called to store the
+    Registry state and enable automatic restoration on all currently registered
+    StackedObjectProxies.
+
+    With restoration enabled, those StackedObjectProxies' _current_obj
+    (overwritten by _current_obj_restoration) method's strategy is modified:
+    it will return its appropriate proxied object from the restorer when
+    a restoration context is active in the current thread.
+
+    The StackedObjectProxies' _push/pop_object methods strategies are also
+    changed: they no-op when a restoration context is active in the current
+    thread (because the pushing/popping work is all handled by the
+    Registry/restorer).
+
+    The request's Registry objects' reglists are restored from the restorer
+    when a restoration context begins, enabling the Registry methods to work
+    while their changes are tracked by the restorer.
+
+    The overhead of enabling restoration is negligible (another threadlocal
+    access for the changed StackedObjectProxy methods) for normal use outside
+    of a restoration context, but worth mentioning when combined with
+    StackedObjectProxies normal overhead. Once enabled it does not turn off,
+    however:
+
+    o Enabling restoration only occurs after an unexpected exception is
+    detected. The server is likely to be restarted shortly after the exception
+    is raised to fix the cause
+
+    o StackedObjectRestorer is only enabled when EvalException is enabled (not
+    on a production server) and RegistryManager exists in the middleware
+    stack"""
+    def __init__(self):
+        # Registries and their saved reglists by request_id
+        self.saved_registry_states = {}
+        self.restoration_context_id = threadinglocal.local()
+
+    def save_registry_state(self, environ):
+        """Save the state of this request's Registry (if it hasn't already been
+        saved) to the saved_registry_states dict, keyed by the request's unique
+        identifier"""
+        registry = environ.get('paste.registry')
+        if not registry or not len(registry.reglist) or \
+                self.get_request_id(environ) in self.saved_registry_states:
+            # No Registry, no state to save, or this request's state has
+            # already been saved
+            return
+
+        self.saved_registry_states[self.get_request_id(environ)] = \
+            (registry, registry.reglist[:])
+
+        # Tweak the StackedObjectProxies we want to save state for -- change
+        # their methods to act differently when a restoration context is active
+        # in the current thread
+        for reglist in registry.reglist:
+            for stacked, obj in reglist.itervalues():
+                self.enable_restoration(stacked)
+
+    def get_saved_proxied_obj(self, stacked, request_id):
+        """Retrieve the saved object proxied by the specified
+        StackedObjectProxy for the request identified by request_id"""
+        # All state for the request identified by request_id
+        reglist = self.saved_registry_states[request_id][1]
+
+        # The top of the stack was current when the exception occurred
+        stack_level = len(reglist) - 1
+        stacked_id = id(stacked)
+        while True:
+            if stack_level < 0:
+                # Nothing registered: Call _current_obj_orig to raise a
+                # TypeError
+                return stacked._current_obj_orig()
+            context = reglist[stack_level]
+            if stacked_id in context:
+                break
+            # This StackedObjectProxy may not have been registered by the
+            # RegistryManager that was active when the exception was raised --
+            # continue searching down the stack until it's found
+            stack_level -= 1
+        return context[stacked_id][1]
+
+    def enable_restoration(self, stacked):
+        """Replace the specified StackedObjectProxy's methods with their
+        respective restoration versions.
+
+        _current_obj_restoration forces recovery of the saved proxied object
+        when a restoration context is active in the current thread.
+
+        _push/pop_object_restoration avoid pushing/popping data
+        (pushing/popping is only done at the Registry level) when a restoration
+        context is active in the current thread"""
+        if '_current_obj_orig' in stacked.__dict__:
+            # Restoration already enabled
+            return
+
+        for func_name in ('_current_obj', '_push_object', '_pop_object'):
+            orig_func = getattr(stacked, func_name)
+            restoration_func = getattr(stacked, func_name + '_restoration')
+            stacked.__dict__[func_name + '_orig'] = orig_func
+            stacked.__dict__[func_name] = restoration_func
+
+    def get_request_id(self, environ):
+        """Return a unique identifier for the current request"""
+        from paste.evalexception.middleware import get_debug_count
+        return get_debug_count(environ)
+
+    def restoration_begin(self, request_id):
+        """Enable a restoration context in the current thread for the specified
+        request_id"""
+        if request_id in self.saved_registry_states:
+            # Restore the old Registry object's state
+            registry, reglist = self.saved_registry_states[request_id]
+            registry.reglist = reglist
+
+        self.restoration_context_id.request_id = request_id
+
+    def restoration_end(self):
+        """Register a restoration context as finished, if one exists"""
+        try:
+            del self.restoration_context_id.request_id
+        except AttributeError:
+            pass
+
+    def in_restoration(self):
+        """Determine if a restoration context is active for the current thread.
+        Returns the request_id it's active for if so, otherwise False"""
+        return getattr(self.restoration_context_id, 'request_id', False)
+
+restorer = StackedObjectRestorer()
+
+
+# Paste Deploy entry point
+def make_registry_manager(app, global_conf):
+    return RegistryManager(app)
+
+make_registry_manager.__doc__ = RegistryManager.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/reloader.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/reloader.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/reloader.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,178 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+A file monitor and server restarter.
+
+Use this like:
+
+..code-block:: Python
+
+    import reloader
+    reloader.install()
+
+Then make sure your server is installed with a shell script like::
+
+    err=3
+    while test "$err" -eq 3 ; do
+        python server.py
+        err="$?"
+    done
+
+or is run from this .bat file (if you use Windows)::
+
+    @echo off
+    :repeat
+        python server.py
+    if %errorlevel% == 3 goto repeat
+
+or run a monitoring process in Python (``paster serve --reload`` does
+this).  
+
+Use the ``watch_file(filename)`` function to cause a reload/restart for
+other other non-Python files (e.g., configuration files).  If you have
+a dynamic set of files that grows over time you can use something like::
+
+    def watch_config_files():
+        return CONFIG_FILE_CACHE.keys()
+    paste.reloader.add_file_callback(watch_config_files)
+
+Then every time the reloader polls files it will call
+``watch_config_files`` and check all the filenames it returns.
+"""
+
+import os
+import sys
+import time
+import threading
+import traceback
+from paste.util.classinstance import classinstancemethod
+
+def install(poll_interval=1):
+    """
+    Install the reloading monitor.
+
+    On some platforms server threads may not terminate when the main
+    thread does, causing ports to remain open/locked.  The
+    ``raise_keyboard_interrupt`` option creates a unignorable signal
+    which causes the whole application to shut-down (rudely).
+    """
+    mon = Monitor(poll_interval=poll_interval)
+    t = threading.Thread(target=mon.periodic_reload)
+    t.setDaemon(True)
+    t.start()
+
+class Monitor(object):
+
+    instances = []
+    global_extra_files = []
+    global_file_callbacks = []
+
+    def __init__(self, poll_interval):
+        self.module_mtimes = {}
+        self.keep_running = True
+        self.poll_interval = poll_interval
+        self.extra_files = list(self.global_extra_files)
+        self.instances.append(self)
+        self.file_callbacks = list(self.global_file_callbacks)
+
+    def periodic_reload(self):
+        while True:
+            if not self.check_reload():
+                # use os._exit() here and not sys.exit() since within a
+                # thread sys.exit() just closes the given thread and
+                # won't kill the process; note os._exit does not call
+                # any atexit callbacks, nor does it do finally blocks,
+                # flush open files, etc.  In otherwords, it is rude.
+                os._exit(3)
+                break
+            time.sleep(self.poll_interval)
+
+    def check_reload(self):
+        filenames = list(self.extra_files)
+        for file_callback in self.file_callbacks:
+            try:
+                filenames.extend(file_callback())
+            except:
+                print >> sys.stderr, "Error calling paste.reloader callback %r:" % file_callback
+                traceback.print_exc()
+        for module in sys.modules.values():
+            try:
+                filename = module.__file__
+            except (AttributeError, ImportError), exc:
+                continue
+            if filename is not None:
+                filenames.append(filename)
+        for filename in filenames:
+            try:
+                stat = os.stat(filename)
+                if stat:
+                    mtime = stat.st_mtime
+                else:
+                    mtime = 0
+            except (OSError, IOError):
+                continue
+            if filename.endswith('.pyc') and os.path.exists(filename[:-1]):
+                mtime = max(os.stat(filename[:-1]).st_mtime, mtime)
+            elif filename.endswith('$py.class') and \
+                    os.path.exists(filename[:-9] + '.py'):
+                mtime = max(os.stat(filename[:-9] + '.py').st_mtime, mtime)
+            if not self.module_mtimes.has_key(filename):
+                self.module_mtimes[filename] = mtime
+            elif self.module_mtimes[filename] < mtime:
+                print >> sys.stderr, (
+                    "%s changed; reloading..." % filename)
+                return False
+        return True
+
+    def watch_file(self, cls, filename):
+        """Watch the named file for changes"""
+        filename = os.path.abspath(filename)
+        if self is None:
+            for instance in cls.instances:
+                instance.watch_file(filename)
+            cls.global_extra_files.append(filename)
+        else:
+            self.extra_files.append(filename)
+
+    watch_file = classinstancemethod(watch_file)
+
+    def add_file_callback(self, cls, callback):
+        """Add a callback -- a function that takes no parameters -- that will
+        return a list of filenames to watch for changes."""
+        if self is None:
+            for instance in cls.instances:
+                instance.add_file_callback(callback)
+            cls.global_file_callbacks.append(callback)
+        else:
+            self.file_callbacks.append(callback)
+
+    add_file_callback = classinstancemethod(add_file_callback)
+
+if sys.platform.startswith('java'):
+    try:
+        from _systemrestart import SystemRestart
+    except ImportError:
+        pass
+    else:
+        class JythonMonitor(Monitor):
+
+            """
+            Monitor that utilizes Jython's special
+            ``_systemrestart.SystemRestart`` exception.
+
+            When raised from the main thread it causes Jython to reload
+            the interpreter in the existing Java process (avoiding
+            startup time).
+
+            Note that this functionality of Jython is experimental and
+            may change in the future.
+            """
+
+            def periodic_reload(self):
+                while True:
+                    if not self.check_reload():
+                        raise SystemRestart()
+                    time.sleep(self.poll_interval)
+
+watch_file = Monitor.watch_file
+add_file_callback = Monitor.add_file_callback

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/request.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/request.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/request.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,411 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Ian Bicking and contributors
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""
+This module provides helper routines with work directly on a WSGI
+environment to solve common requirements.
+
+   * get_cookies(environ)
+   * parse_querystring(environ)
+   * parse_formvars(environ, include_get_vars=True)
+   * construct_url(environ, with_query_string=True, with_path_info=True,
+                   script_name=None, path_info=None, querystring=None)
+   * path_info_split(path_info)
+   * path_info_pop(environ)
+   * resolve_relative_url(url, environ)
+
+"""
+import cgi
+from Cookie import SimpleCookie, CookieError
+from StringIO import StringIO
+import urlparse
+import urllib
+try:
+    from UserDict import DictMixin
+except ImportError:
+    from paste.util.UserDict24 import DictMixin
+from paste.util.multidict import MultiDict
+
+__all__ = ['get_cookies', 'get_cookie_dict', 'parse_querystring',
+           'parse_formvars', 'construct_url', 'path_info_split',
+           'path_info_pop', 'resolve_relative_url', 'EnvironHeaders']
+
+def get_cookies(environ):
+    """
+    Gets a cookie object (which is a dictionary-like object) from the
+    request environment; caches this value in case get_cookies is
+    called again for the same request.
+
+    """
+    header = environ.get('HTTP_COOKIE', '')
+    if environ.has_key('paste.cookies'):
+        cookies, check_header = environ['paste.cookies']
+        if check_header == header:
+            return cookies
+    cookies = SimpleCookie()
+    try:
+        cookies.load(header)
+    except CookieError:
+        pass
+    environ['paste.cookies'] = (cookies, header)
+    return cookies
+
+def get_cookie_dict(environ):
+    """Return a *plain* dictionary of cookies as found in the request.
+
+    Unlike ``get_cookies`` this returns a dictionary, not a
+    ``SimpleCookie`` object.  For incoming cookies a dictionary fully
+    represents the information.  Like ``get_cookies`` this caches and
+    checks the cache.
+    """
+    header = environ.get('HTTP_COOKIE')
+    if not header:
+        return {}
+    if environ.has_key('paste.cookies.dict'):
+        cookies, check_header = environ['paste.cookies.dict']
+        if check_header == header:
+            return cookies
+    cookies = SimpleCookie()
+    try:
+        cookies.load(header)
+    except CookieError:
+        pass
+    result = {}
+    for name in cookies:
+        result[name] = cookies[name].value
+    environ['paste.cookies.dict'] = (result, header)
+    return result
+
+def parse_querystring(environ):
+    """
+    Parses a query string into a list like ``[(name, value)]``.
+    Caches this value in case parse_querystring is called again
+    for the same request.
+
+    You can pass the result to ``dict()``, but be aware that keys that
+    appear multiple times will be lost (only the last value will be
+    preserved).
+
+    """
+    source = environ.get('QUERY_STRING', '')
+    if not source:
+        return []
+    if 'paste.parsed_querystring' in environ:
+        parsed, check_source = environ['paste.parsed_querystring']
+        if check_source == source:
+            return parsed
+    parsed = cgi.parse_qsl(source, keep_blank_values=True,
+                           strict_parsing=False)
+    environ['paste.parsed_querystring'] = (parsed, source)
+    return parsed
+
+def parse_dict_querystring(environ):
+    """Parses a query string like parse_querystring, but returns a MultiDict
+
+    Caches this value in case parse_dict_querystring is called again
+    for the same request.
+
+    Example::
+
+        >>> environ = {'QUERY_STRING': 'day=Monday&user=fred&user=jane'}
+        >>> parsed = parse_dict_querystring(environ)
+
+        >>> parsed['day']
+        'Monday'
+        >>> parsed['user']
+        'fred'
+        >>> parsed.getall('user')
+        ['fred', 'jane']
+
+    """
+    source = environ.get('QUERY_STRING', '')
+    if not source:
+        return MultiDict()
+    if 'paste.parsed_dict_querystring' in environ:
+        parsed, check_source = environ['paste.parsed_dict_querystring']
+        if check_source == source:
+            return parsed
+    parsed = cgi.parse_qsl(source, keep_blank_values=True,
+                           strict_parsing=False)
+    multi = MultiDict(parsed)
+    environ['paste.parsed_dict_querystring'] = (multi, source)
+    return multi
+
+def parse_formvars(environ, include_get_vars=True):
+    """Parses the request, returning a MultiDict of form variables.
+
+    If ``include_get_vars`` is true then GET (query string) variables
+    will also be folded into the MultiDict.
+
+    All values should be strings, except for file uploads which are
+    left as ``FieldStorage`` instances.
+
+    If the request was not a normal form request (e.g., a POST with an
+    XML body) then ``environ['wsgi.input']`` won't be read.
+    """
+    source = environ['wsgi.input']
+    if 'paste.parsed_formvars' in environ:
+        parsed, check_source = environ['paste.parsed_formvars']
+        if check_source == source:
+            if include_get_vars:
+                parsed.update(parse_querystring(environ))
+            return parsed
+    # @@: Shouldn't bother FieldStorage parsing during GET/HEAD and
+    # fake_out_cgi requests
+    type = environ.get('CONTENT_TYPE', '').lower()
+    if ';' in type:
+        type = type.split(';', 1)[0]
+    fake_out_cgi = type not in ('', 'application/x-www-form-urlencoded',
+                                'multipart/form-data')
+    # FieldStorage assumes a default CONTENT_LENGTH of -1, but a
+    # default of 0 is better:
+    if not environ.get('CONTENT_LENGTH'):
+        environ['CONTENT_LENGTH'] = '0'
+    # Prevent FieldStorage from parsing QUERY_STRING during GET/HEAD
+    # requests
+    old_query_string = environ.get('QUERY_STRING','')
+    environ['QUERY_STRING'] = ''
+    if fake_out_cgi:
+        input = StringIO('')
+        old_content_type = environ.get('CONTENT_TYPE')
+        old_content_length = environ.get('CONTENT_LENGTH')
+        environ['CONTENT_LENGTH'] = '0'
+        environ['CONTENT_TYPE'] = ''    
+    else:
+        input = environ['wsgi.input']
+    fs = cgi.FieldStorage(fp=input,
+                          environ=environ,
+                          keep_blank_values=1)
+    environ['QUERY_STRING'] = old_query_string
+    if fake_out_cgi:
+        environ['CONTENT_TYPE'] = old_content_type
+        environ['CONTENT_LENGTH'] = old_content_length
+    formvars = MultiDict()
+    if isinstance(fs.value, list):
+        for name in fs.keys():
+            values = fs[name]
+            if not isinstance(values, list):
+                values = [values]
+            for value in values:
+                if not value.filename:
+                    value = value.value
+                formvars.add(name, value)
+    environ['paste.parsed_formvars'] = (formvars, source)
+    if include_get_vars:
+        formvars.update(parse_querystring(environ))
+    return formvars
+
+def construct_url(environ, with_query_string=True, with_path_info=True,
+                  script_name=None, path_info=None, querystring=None):
+    """Reconstructs the URL from the WSGI environment.
+
+    You may override SCRIPT_NAME, PATH_INFO, and QUERYSTRING with
+    the keyword arguments.
+
+    """
+    url = environ['wsgi.url_scheme']+'://'
+
+    if environ.get('HTTP_HOST'):
+        host = environ['HTTP_HOST']
+        port = None
+        if ':' in host:
+            host, port = host.split(':', 1)
+            if environ['wsgi.url_scheme'] == 'https':
+                if port == '443':
+                    port = None
+            elif environ['wsgi.url_scheme'] == 'http':
+                if port == '80':
+                    port = None
+        url += host
+        if port:
+            url += ':%s' % port
+    else:
+        url += environ['SERVER_NAME']
+        if environ['wsgi.url_scheme'] == 'https':
+            if environ['SERVER_PORT'] != '443':
+                url += ':' + environ['SERVER_PORT']
+        else:
+            if environ['SERVER_PORT'] != '80':
+                url += ':' + environ['SERVER_PORT']
+
+    if script_name is None:
+        url += urllib.quote(environ.get('SCRIPT_NAME',''))
+    else:
+        url += urllib.quote(script_name)
+    if with_path_info:
+        if path_info is None:
+            url += urllib.quote(environ.get('PATH_INFO',''))
+        else:
+            url += urllib.quote(path_info)
+    if with_query_string:
+        if querystring is None:
+            if environ.get('QUERY_STRING'):
+                url += '?' + environ['QUERY_STRING']
+        elif querystring:
+            url += '?' + querystring
+    return url
+
+def resolve_relative_url(url, environ):
+    """
+    Resolve the given relative URL as being relative to the
+    location represented by the environment.  This can be used
+    for redirecting to a relative path.  Note: if url is already
+    absolute, this function will (intentionally) have no effect
+    on it.
+
+    """
+    cur_url = construct_url(environ, with_query_string=False)
+    return urlparse.urljoin(cur_url, url)
+
+def path_info_split(path_info):
+    """
+    Splits off the first segment of the path.  Returns (first_part,
+    rest_of_path).  first_part can be None (if PATH_INFO is empty), ''
+    (if PATH_INFO is '/'), or a name without any /'s.  rest_of_path
+    can be '' or a string starting with /.
+
+    """
+    if not path_info:
+        return None, ''
+    assert path_info.startswith('/'), (
+        "PATH_INFO should start with /: %r" % path_info)
+    path_info = path_info.lstrip('/')
+    if '/' in path_info:
+        first, rest = path_info.split('/', 1)
+        return first, '/' + rest
+    else:
+        return path_info, ''
+
+def path_info_pop(environ):
+    """
+    'Pops' off the next segment of PATH_INFO, pushing it onto
+    SCRIPT_NAME, and returning that segment.
+
+    For instance::
+
+        >>> def call_it(script_name, path_info):
+        ...     env = {'SCRIPT_NAME': script_name, 'PATH_INFO': path_info}
+        ...     result = path_info_pop(env)
+        ...     print 'SCRIPT_NAME=%r; PATH_INFO=%r; returns=%r' % (
+        ...         env['SCRIPT_NAME'], env['PATH_INFO'], result)
+        >>> call_it('/foo', '/bar')
+        SCRIPT_NAME='/foo/bar'; PATH_INFO=''; returns='bar'
+        >>> call_it('/foo/bar', '')
+        SCRIPT_NAME='/foo/bar'; PATH_INFO=''; returns=None
+        >>> call_it('/foo/bar', '/')
+        SCRIPT_NAME='/foo/bar/'; PATH_INFO=''; returns=''
+        >>> call_it('', '/1/2/3')
+        SCRIPT_NAME='/1'; PATH_INFO='/2/3'; returns='1'
+        >>> call_it('', '//1/2')
+        SCRIPT_NAME='//1'; PATH_INFO='/2'; returns='1'
+
+    """
+    path = environ.get('PATH_INFO', '')
+    if not path:
+        return None
+    while path.startswith('/'):
+        environ['SCRIPT_NAME'] += '/'
+        path = path[1:]
+    if '/' not in path:
+        environ['SCRIPT_NAME'] += path
+        environ['PATH_INFO'] = ''
+        return path
+    else:
+        segment, path = path.split('/', 1)
+        environ['PATH_INFO'] = '/' + path
+        environ['SCRIPT_NAME'] += segment
+        return segment
+
+_parse_headers_special = {
+    # This is a Zope convention, but we'll allow it here:
+    'HTTP_CGI_AUTHORIZATION': 'Authorization',
+    'CONTENT_LENGTH': 'Content-Length',
+    'CONTENT_TYPE': 'Content-Type',
+    }
+
+def parse_headers(environ):
+    """
+    Parse the headers in the environment (like ``HTTP_HOST``) and
+    yield a sequence of those (header_name, value) tuples.
+    """
+    # @@: Maybe should parse out comma-separated headers?
+    for cgi_var, value in environ.iteritems():
+        if cgi_var in _parse_headers_special:
+            yield _parse_headers_special[cgi_var], value
+        elif cgi_var.startswith('HTTP_'):
+            yield cgi_var[5:].title().replace('_', '-'), value
+
+class EnvironHeaders(DictMixin):
+    """An object that represents the headers as present in a
+    WSGI environment.
+
+    This object is a wrapper (with no internal state) for a WSGI
+    request object, representing the CGI-style HTTP_* keys as a
+    dictionary.  Because a CGI environment can only hold one value for
+    each key, this dictionary is single-valued (unlike outgoing
+    headers).
+    """
+
+    def __init__(self, environ):
+        self.environ = environ
+
+    def _trans_name(self, name):
+        key = 'HTTP_'+name.replace('-', '_').upper()
+        if key == 'HTTP_CONTENT_LENGTH':
+            key = 'CONTENT_LENGTH'
+        elif key == 'HTTP_CONTENT_TYPE':
+            key = 'CONTENT_TYPE'
+        return key
+
+    def _trans_key(self, key):
+        if key == 'CONTENT_TYPE':
+            return 'Content-Type'
+        elif key == 'CONTENT_LENGTH':
+            return 'Content-Length'
+        elif key.startswith('HTTP_'):
+            return key[5:].replace('_', '-').title()
+        else:
+            return None
+        
+    def __getitem__(self, item):
+        return self.environ[self._trans_name(item)]
+
+    def __setitem__(self, item, value):
+        # @@: Should this dictionary be writable at all?
+        self.environ[self._trans_name(item)] = value
+
+    def __delitem__(self, item):
+        del self.environ[self._trans_name(item)]
+
+    def __iter__(self):
+        for key in self.environ:
+            name = self._trans_key(key)
+            if name is not None:
+                yield name
+
+    def keys(self):
+        return list(iter(self))
+
+    def __contains__(self, item):
+        return self._trans_name(item) in self.environ
+
+def _cgi_FieldStorage__repr__patch(self):
+    """ monkey patch for FieldStorage.__repr__
+
+    Unbelievely, the default __repr__ on FieldStorage reads
+    the entire file content instead of being sane about it.
+    This is a simple replacement that doesn't do that
+    """
+    if self.file:
+        return "FieldStorage(%r, %r)" % (
+                self.name, self.filename)
+    return "FieldStorage(%r, %r, %r)" % (
+             self.name, self.filename, self.value)
+
+cgi.FieldStorage.__repr__ = _cgi_FieldStorage__repr__patch
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/response.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/response.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/response.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,240 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""Routines to generate WSGI responses"""
+
+############################################################
+## Headers
+############################################################
+import warnings
+
+class HeaderDict(dict):
+
+    """
+    This represents response headers.  It handles the headers as a
+    dictionary, with case-insensitive keys.
+
+    Also there is an ``.add(key, value)`` method, which sets the key,
+    or adds the value to the current value (turning it into a list if
+    necessary).
+
+    For passing to WSGI there is a ``.headeritems()`` method which is
+    like ``.items()`` but unpacks value that are lists.  It also
+    handles encoding -- all headers are encoded in ASCII (if they are
+    unicode).
+
+    @@: Should that encoding be ISO-8859-1 or UTF-8?  I'm not sure
+    what the spec says.
+    """
+
+    def __getitem__(self, key):
+        return dict.__getitem__(self, self.normalize(key))
+
+    def __setitem__(self, key, value):
+        dict.__setitem__(self, self.normalize(key), value)
+
+    def __delitem__(self, key):
+        dict.__delitem__(self, self.normalize(key))
+
+    def __contains__(self, key):
+        return dict.__contains__(self, self.normalize(key))
+
+    has_key = __contains__
+
+    def get(self, key, failobj=None):
+        return dict.get(self, self.normalize(key), failobj)
+
+    def setdefault(self, key, failobj=None):
+        return dict.setdefault(self, self.normalize(key), failobj)
+
+    def pop(self, key, *args):
+        return dict.pop(self, self.normalize(key), *args)
+
+    def update(self, other):
+        for key in other:
+            self[self.normalize(key)] = other[key]
+
+    def normalize(self, key):
+        return str(key).lower().strip()
+
+    def add(self, key, value):
+        key = self.normalize(key)
+        if key in self:
+            if isinstance(self[key], list):
+                self[key].append(value)
+            else:
+                self[key] = [self[key], value]
+        else:
+            self[key] = value
+
+    def headeritems(self):
+        result = []
+        for key, value in self.items():
+            if isinstance(value, list):
+                for v in value:
+                    result.append((key, str(v)))
+            else:
+                result.append((key, str(value)))
+        return result
+
+    #@classmethod
+    def fromlist(cls, seq):
+        self = cls()
+        for name, value in seq:
+            self.add(name, value)
+        return self
+
+    fromlist = classmethod(fromlist)
+
+def has_header(headers, name):
+    """
+    Is header named ``name`` present in headers?
+    """
+    name = name.lower()
+    for header, value in headers:
+        if header.lower() == name:
+            return True
+    return False
+
+def header_value(headers, name):
+    """
+    Returns the header's value, or None if no such header.  If a
+    header appears more than once, all the values of the headers
+    are joined with ','.   Note that this is consistent /w RFC 2616
+    section 4.2 which states:
+
+        It MUST be possible to combine the multiple header fields
+        into one "field-name: field-value" pair, without changing
+        the semantics of the message, by appending each subsequent
+        field-value to the first, each separated by a comma.
+
+    However, note that the original netscape usage of 'Set-Cookie',
+    especially in MSIE which contains an 'expires' date will is not
+    compatible with this particular concatination method.
+    """
+    name = name.lower()
+    result = [value for header, value in headers
+              if header.lower() == name]
+    if result:
+        return ','.join(result)
+    else:
+        return None
+
+def remove_header(headers, name):
+    """
+    Removes the named header from the list of headers.  Returns the
+    value of that header, or None if no header found.  If multiple
+    headers are found, only the last one is returned.
+    """
+    name = name.lower()
+    i = 0
+    result = None
+    while i < len(headers):
+        if headers[i][0].lower() == name:
+            result = headers[i][1]
+            del headers[i]
+            continue
+        i += 1
+    return result
+
+def replace_header(headers, name, value):
+    """
+    Updates the headers replacing the first occurance of the given name
+    with the value provided; asserting that no further occurances
+    happen. Note that this is _not_ the same as remove_header and then
+    append, as two distinct operations (del followed by an append) are
+    not atomic in a threaded environment. Returns the previous header
+    value for the provided name, if any.   Clearly one should not use
+    this function with ``set-cookie`` or other names that may have more
+    than one occurance in the headers.
+    """
+    name = name.lower()
+    i = 0
+    result = None
+    while i < len(headers):
+        if headers[i][0].lower() == name:
+            assert not result, "two values for the header '%s' found" % name
+            result = headers[i][1]
+            headers[i] = (name, value)
+        i += 1
+    if not result:
+        headers.append((name, value))
+    return result
+
+
+############################################################
+## Deprecated methods
+############################################################
+
+def error_body_response(error_code, message, __warn=True):
+    """
+    Returns a standard HTML response page for an HTTP error.
+    **Note:** Deprecated
+    """
+    if __warn:
+        warnings.warn(
+            'wsgilib.error_body_response is deprecated; use the '
+            'wsgi_application method on an HTTPException object '
+            'instead', DeprecationWarning, 2)
+    return '''\
+<html>
+  <head>
+    <title>%(error_code)s</title>
+  </head>
+  <body>
+  <h1>%(error_code)s</h1>
+  %(message)s
+  </body>
+</html>''' % {
+        'error_code': error_code,
+        'message': message,
+        }
+
+
+def error_response(environ, error_code, message,
+                   debug_message=None, __warn=True):
+    """
+    Returns the status, headers, and body of an error response.
+
+    Use like:
+
+    .. code-block:: python
+
+        status, headers, body = wsgilib.error_response(
+            '301 Moved Permanently', 'Moved to <a href="%s">%s</a>'
+            % (url, url))
+        start_response(status, headers)
+        return [body]
+
+    **Note:** Deprecated
+    """
+    if __warn:
+        warnings.warn(
+            'wsgilib.error_response is deprecated; use the '
+            'wsgi_application method on an HTTPException object '
+            'instead', DeprecationWarning, 2)
+    if debug_message and environ.get('paste.config', {}).get('debug'):
+        message += '\n\n<!-- %s -->' % debug_message
+    body = error_body_response(error_code, message, __warn=False)
+    headers = [('content-type', 'text/html'),
+               ('content-length', str(len(body)))]
+    return error_code, headers, body
+
+def error_response_app(error_code, message, debug_message=None,
+                       __warn=True):
+    """
+    An application that emits the given error response.
+
+    **Note:** Deprecated
+    """
+    if __warn:
+        warnings.warn(
+            'wsgilib.error_response_app is deprecated; use the '
+            'wsgi_application method on an HTTPException object '
+            'instead', DeprecationWarning, 2)
+    def application(environ, start_response):
+        status, headers, body = error_response(
+            environ, error_code, message,
+            debug_message=debug_message, __warn=False)
+        start_response(status, headers)
+        return [body]
+    return application

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/session.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/session.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/session.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,337 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+Creates a session object in your WSGI environment.
+
+Use like:
+
+..code-block:: Python
+
+    environ['paste.session.factory']()
+
+This will return a dictionary.  The contents of this dictionary will
+be saved to disk when the request is completed.  The session will be
+created when you first fetch the session dictionary, and a cookie will
+be sent in that case.  There's current no way to use sessions without
+cookies, and there's no way to delete a session except to clear its
+data.
+
+@@: This doesn't do any locking, and may cause problems when a single
+session is accessed concurrently.  Also, it loads and saves the
+session for each request, with no caching.  Also, sessions aren't
+expired.
+"""
+
+from Cookie import SimpleCookie
+import time
+import random
+import os
+import datetime
+import threading
+import tempfile
+
+try:
+    import cPickle
+except ImportError:
+    import pickle as cPickle
+try:
+    from hashlib import md5
+except ImportError:
+    from md5 import md5
+from paste import wsgilib
+from paste import request
+
+class SessionMiddleware(object):
+
+    def __init__(self, application, global_conf=None, **factory_kw):
+        self.application = application
+        self.factory_kw = factory_kw
+
+    def __call__(self, environ, start_response):
+        session_factory = SessionFactory(environ, **self.factory_kw)
+        environ['paste.session.factory'] = session_factory
+        remember_headers = []
+
+        def session_start_response(status, headers, exc_info=None):
+            if not session_factory.created:
+                remember_headers[:] = [status, headers]
+                return start_response(status, headers)
+            headers.append(session_factory.set_cookie_header())
+            return start_response(status, headers, exc_info)
+
+        app_iter = self.application(environ, session_start_response)
+        def start():
+            if session_factory.created and remember_headers:
+                # Tricky bastard used the session after start_response
+                status, headers = remember_headers
+                headers.append(session_factory.set_cookie_header())
+                exc = ValueError(
+                    "You cannot get the session after content from the "
+                    "app_iter has been returned")
+                start_response(status, headers, (exc.__class__, exc, None))
+        def close():
+            if session_factory.used:
+                session_factory.close()
+        return wsgilib.add_start_close(app_iter, start, close)
+
+
+class SessionFactory(object):
+
+
+    def __init__(self, environ, cookie_name='_SID_',
+                 session_class=None,
+                 session_expiration=60*12, # in minutes
+                 **session_class_kw):
+
+        self.created = False
+        self.used = False
+        self.environ = environ
+        self.cookie_name = cookie_name
+        self.session = None
+        self.session_class = session_class or FileSession
+        self.session_class_kw = session_class_kw
+
+        self.expiration = session_expiration
+
+    def __call__(self):
+        self.used = True
+        if self.session is not None:
+            return self.session.data()
+        cookies = request.get_cookies(self.environ)
+        session = None
+        if cookies.has_key(self.cookie_name):
+            self.sid = cookies[self.cookie_name].value
+            try:
+                session = self.session_class(self.sid, create=False,
+                                             **self.session_class_kw)
+            except KeyError:
+                # Invalid SID
+                pass
+        if session is None:
+            self.created = True
+            self.sid = self.make_sid()
+            session = self.session_class(self.sid, create=True,
+                                         **self.session_class_kw)
+        session.clean_up()
+        self.session = session
+        return session.data()
+
+    def has_session(self):
+        if self.session is not None:
+            return True
+        cookies = request.get_cookies(self.environ)
+        if cookies.has_key(self.cookie_name):
+            return True
+        return False
+
+    def make_sid(self):
+        # @@: need better algorithm
+        return (''.join(['%02d' % x for x in time.localtime(time.time())[:6]])
+                + '-' + self.unique_id())
+
+    def unique_id(self, for_object=None):
+        """
+        Generates an opaque, identifier string that is practically
+        guaranteed to be unique.  If an object is passed, then its
+        id() is incorporated into the generation.  Relies on md5 and
+        returns a 32 character long string.
+        """
+        r = [time.time(), random.random()]
+        if hasattr(os, 'times'):
+            r.append(os.times())
+        if for_object is not None:
+            r.append(id(for_object))
+        md5_hash = md5(str(r))
+        try:
+            return md5_hash.hexdigest()
+        except AttributeError:
+            # Older versions of Python didn't have hexdigest, so we'll
+            # do it manually
+            hexdigest = []
+            for char in md5_hash.digest():
+                hexdigest.append('%02x' % ord(char))
+            return ''.join(hexdigest)
+
+    def set_cookie_header(self):
+        c = SimpleCookie()
+        c[self.cookie_name] = self.sid
+        c[self.cookie_name]['path'] = '/'
+
+        gmt_expiration_time = time.gmtime(time.time() + (self.expiration * 60))
+        c[self.cookie_name]['expires'] = time.strftime("%a, %d-%b-%Y %H:%M:%S GMT", gmt_expiration_time)
+
+        name, value = str(c).split(': ', 1)
+        return (name, value)
+
+    def close(self):
+        if self.session is not None:
+            self.session.close()
+
+
+last_cleanup = None
+cleaning_up = False
+cleanup_cycle = datetime.timedelta(seconds=15*60) #15 min
+
+class FileSession(object):
+
+    def __init__(self, sid, create=False, session_file_path=tempfile.gettempdir(),
+                 chmod=None,
+                 expiration=2880, # in minutes: 48 hours
+                 ):
+        if chmod and isinstance(chmod, basestring):
+            chmod = int(chmod, 8)
+        self.chmod = chmod
+        if not sid:
+            # Invalid...
+            raise KeyError
+        self.session_file_path = session_file_path
+        self.sid = sid
+        if not create:
+            if not os.path.exists(self.filename()):
+                raise KeyError
+        self._data = None
+
+        self.expiration = expiration
+
+
+    def filename(self):
+        return os.path.join(self.session_file_path, self.sid)
+
+    def data(self):
+        if self._data is not None:
+            return self._data
+        if os.path.exists(self.filename()):
+            f = open(self.filename(), 'rb')
+            self._data = cPickle.load(f)
+            f.close()
+        else:
+            self._data = {}
+        return self._data
+
+    def close(self):
+        if self._data is not None:
+            filename = self.filename()
+            exists = os.path.exists(filename)
+            if not self._data:
+                if exists:
+                    os.unlink(filename)
+            else:
+                f = open(filename, 'wb')
+                cPickle.dump(self._data, f)
+                f.close()
+                if not exists and self.chmod:
+                    os.chmod(filename, self.chmod)
+
+    def _clean_up(self):
+        global cleaning_up
+        try:
+            exp_time = datetime.timedelta(seconds=self.expiration*60)
+            now = datetime.datetime.now()
+
+            #Open every session and check that it isn't too old
+            for root, dirs, files in os.walk(self.session_file_path):
+                for f in files:
+                    self._clean_up_file(f, exp_time=exp_time, now=now)
+        finally:
+            cleaning_up = False
+
+    def _clean_up_file(self, f, exp_time, now):
+        t = f.split("-")
+        if len(t) != 2:
+            return
+        t = t[0]
+        try:
+            sess_time = datetime.datetime(
+                    int(t[0:4]),
+                    int(t[4:6]),
+                    int(t[6:8]),
+                    int(t[8:10]),
+                    int(t[10:12]),
+                    int(t[12:14]))
+        except ValueError:
+            # Probably not a session file at all
+            return
+
+        if sess_time + exp_time < now:
+            os.remove(os.path.join(self.session_file_path, f))
+
+    def clean_up(self):
+        global last_cleanup, cleanup_cycle, cleaning_up
+        now = datetime.datetime.now()
+
+        if cleaning_up:
+            return
+
+        if not last_cleanup or last_cleanup + cleanup_cycle < now:
+            if not cleaning_up:
+                cleaning_up = True
+                try:
+                    last_cleanup = now
+                    t = threading.Thread(target=self._clean_up)
+                    t.start()
+                except:
+                    # Normally _clean_up should set cleaning_up
+                    # to false, but if something goes wrong starting
+                    # it...
+                    cleaning_up = False
+                    raise
+
+class _NoDefault(object):
+    def __repr__(self):
+        return '<dynamic default>'
+NoDefault = _NoDefault()
+
+def make_session_middleware(
+    app, global_conf,
+    session_expiration=NoDefault,
+    expiration=NoDefault,
+    cookie_name=NoDefault,
+    session_file_path=NoDefault,
+    chmod=NoDefault):
+    """
+    Adds a middleware that handles sessions for your applications.
+    The session is a peristent dictionary.  To get this dictionary
+    in your application, use ``environ['paste.session.factory']()``
+    which returns this persistent dictionary.
+
+    Configuration:
+
+      session_expiration:
+          The time each session lives, in minutes.  This controls
+          the cookie expiration.  Default 12 hours.
+
+      expiration:
+          The time each session lives on disk.  Old sessions are
+          culled from disk based on this.  Default 48 hours.
+
+      cookie_name:
+          The cookie name used to track the session.  Use different
+          names to avoid session clashes.
+
+      session_file_path:
+          Sessions are put in this location, default /tmp.
+
+      chmod:
+          The octal chmod you want to apply to new sessions (e.g., 660
+          to make the sessions group readable/writable)
+
+    Each of these also takes from the global configuration.  cookie_name
+    and chmod take from session_cookie_name and session_chmod
+    """
+    if session_expiration is NoDefault:
+        session_expiration = global_conf.get('session_expiration', 60*12)
+    session_expiration = int(session_expiration)
+    if expiration is NoDefault:
+        expiration = global_conf.get('expiration', 60*48)
+    expiration = int(expiration)
+    if cookie_name is NoDefault:
+        cookie_name = global_conf.get('session_cookie_name', '_SID_')
+    if session_file_path is NoDefault:
+        session_file_path = global_conf.get('session_file_path', '/tmp')
+    if chmod is NoDefault:
+        chmod = global_conf.get('session_chmod', None)
+    return SessionMiddleware(
+        app, session_expiration=session_expiration,
+        expiration=expiration, cookie_name=cookie_name,
+        session_file_path=session_file_path, chmod=chmod)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/transaction.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/transaction.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/transaction.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,120 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# (c) 2005 Clark C. Evans
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware related to transactions and database connections.
+
+At this time it is very basic; but will eventually sprout all that
+two-phase commit goodness that I don't need.
+
+.. note::
+
+   This is experimental, and will change in the future.
+"""
+from paste.httpexceptions import HTTPException
+from wsgilib import catch_errors
+
+class TransactionManagerMiddleware(object):
+
+    def __init__(self, application):
+        self.application = application
+
+    def __call__(self, environ, start_response):
+        environ['paste.transaction_manager'] = manager = Manager()
+        # This makes sure nothing else traps unexpected exceptions:
+        environ['paste.throw_errors'] = True
+        return catch_errors(self.application, environ, start_response,
+                            error_callback=manager.error,
+                            ok_callback=manager.finish)
+
+class Manager(object):
+
+    def __init__(self):
+        self.aborted = False
+        self.transactions = []
+
+    def abort(self):
+        self.aborted = True
+
+    def error(self, exc_info):
+        self.aborted = True
+        self.finish()
+
+    def finish(self):
+        for trans in self.transactions:
+            if self.aborted:
+                trans.rollback()
+            else:
+                trans.commit()
+
+
+class ConnectionFactory(object):
+    """
+    Provides a callable interface for connecting to ADBAPI databases in
+    a WSGI style (using the environment).  More advanced connection
+    factories might use the REMOTE_USER and/or other environment
+    variables to make the connection returned depend upon the request.
+    """
+    def __init__(self, module, *args, **kwargs):
+        #assert getattr(module,'threadsaftey',0) > 0
+        self.module = module
+        self.args = args
+        self.kwargs = kwargs
+
+        # deal with database string quoting issues
+        self.quote = lambda s: "'%s'" % s.replace("'","''")
+        if hasattr(self.module,'PgQuoteString'):
+            self.quote = self.module.PgQuoteString
+
+    def __call__(self, environ=None):
+        conn = self.module.connect(*self.args, **self.kwargs)
+        conn.__dict__['module'] = self.module
+        conn.__dict__['quote'] = self.quote
+        return conn
+
+def BasicTransactionHandler(application, factory):
+    """
+    Provides a simple mechanism for starting a transaction based on the
+    factory; and for either committing or rolling back the transaction
+    depending on the result.  It checks for the response's current
+    status code either through the latest call to start_response; or
+    through a HTTPException's code.  If it is a 100, 200, or 300; the
+    transaction is committed; otherwise it is rolled back.
+    """
+    def basic_transaction(environ, start_response):
+        conn = factory(environ)
+        environ['paste.connection'] = conn
+        should_commit = [500]
+        def finalizer(exc_info=None):
+            if exc_info:
+                if isinstance(exc_info[1], HTTPException):
+                    should_commit.append(exc_info[1].code)
+            if should_commit.pop() < 400:
+                conn.commit()
+            else:
+                try:
+                    conn.rollback()
+                except:
+                    # TODO: check if rollback has already happened
+                    return
+            conn.close()
+        def basictrans_start_response(status, headers, exc_info = None):
+            should_commit.append(int(status.split(" ")[0]))
+            return start_response(status, headers, exc_info)
+        return catch_errors(application, environ, basictrans_start_response,
+                            finalizer, finalizer)
+    return basic_transaction
+
+__all__ = ['ConnectionFactory', 'BasicTransactionHandler']
+
+if '__main__' == __name__ and False:
+    from pyPgSQL import PgSQL
+    factory = ConnectionFactory(PgSQL, database="testing")
+    conn = factory()
+    curr = conn.cursor()
+    curr.execute("SELECT now(), %s" % conn.quote("B'n\\'gles"))
+    (time, bing) = curr.fetchone()
+    print bing, time
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/translogger.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/translogger.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/translogger.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,121 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Middleware for logging requests, using Apache combined log format
+"""
+
+import logging
+import time
+import urllib
+
+class TransLogger(object):
+    """
+    This logging middleware will log all requests as they go through.
+    They are, by default, sent to a logger named ``'wsgi'`` at the
+    INFO level.
+
+    If ``setup_console_handler`` is true, then messages for the named
+    logger will be sent to the console.
+    """
+
+    format = ('%(REMOTE_ADDR)s - %(REMOTE_USER)s [%(time)s] '
+              '"%(REQUEST_METHOD)s %(REQUEST_URI)s %(HTTP_VERSION)s" '
+              '%(status)s %(bytes)s "%(HTTP_REFERER)s" "%(HTTP_USER_AGENT)s"')
+
+    def __init__(self, application,
+                 logger=None,
+                 format=None,
+                 logging_level=logging.INFO,
+                 logger_name='wsgi',
+                 setup_console_handler=True,
+                 set_logger_level=logging.DEBUG):
+        if format is not None:
+            self.format = format
+        self.application = application
+        self.logging_level = logging_level
+        self.logger_name = logger_name
+        if logger is None:
+            self.logger = logging.getLogger(self.logger_name)
+            if setup_console_handler:
+                console = logging.StreamHandler()
+                console.setLevel(logging.DEBUG)
+                # We need to control the exact format:
+                console.setFormatter(logging.Formatter('%(message)s'))
+                self.logger.addHandler(console)
+                self.logger.propagate = False
+            if set_logger_level is not None:
+                self.logger.setLevel(set_logger_level)
+        else:
+            self.logger = logger
+
+    def __call__(self, environ, start_response):
+        start = time.localtime()
+        req_uri = urllib.quote(environ.get('SCRIPT_NAME', '')
+                               + environ.get('PATH_INFO', ''))
+        if environ.get('QUERY_STRING'):
+            req_uri += '?'+environ['QUERY_STRING']
+        method = environ['REQUEST_METHOD']
+        def replacement_start_response(status, headers, exc_info=None):
+            # @@: Ideally we would count the bytes going by if no
+            # content-length header was provided; but that does add
+            # some overhead, so at least for now we'll be lazy.
+            bytes = None
+            for name, value in headers:
+                if name.lower() == 'content-length':
+                    bytes = value
+            self.write_log(environ, method, req_uri, start, status, bytes)
+            return start_response(status, headers)
+        return self.application(environ, replacement_start_response)
+
+    def write_log(self, environ, method, req_uri, start, status, bytes):
+        if bytes is None:
+            bytes = '-'
+        if time.daylight:
+                offset = time.altzone / 60 / 60 * -100
+        else:
+                offset = time.timezone / 60 / 60 * -100
+        if offset >= 0:
+                offset = "+%0.4d" % (offset)
+        elif offset < 0:
+                offset = "%0.4d" % (offset)
+        remote_addr = '-'
+        if environ.get('HTTP_X_FORWARDED_FOR'):
+            remote_addr = environ['HTTP_X_FORWARDED_FOR']
+        elif environ.get('REMOTE_ADDR'):
+            remote_addr = environ['REMOTE_ADDR']
+        d = {
+            'REMOTE_ADDR': remote_addr,
+            'REMOTE_USER': environ.get('REMOTE_USER') or '-',
+            'REQUEST_METHOD': method,
+            'REQUEST_URI': req_uri,
+            'HTTP_VERSION': environ.get('SERVER_PROTOCOL'),
+            'time': time.strftime('%d/%b/%Y:%H:%M:%S ', start) + offset,
+            'status': status.split(None, 1)[0],
+            'bytes': bytes,
+            'HTTP_REFERER': environ.get('HTTP_REFERER', '-'),
+            'HTTP_USER_AGENT': environ.get('HTTP_USER_AGENT', '-'),
+            }
+        message = self.format % d
+        self.logger.log(self.logging_level, message)
+
+def make_filter(
+    app, global_conf,
+    logger_name='wsgi',
+    format=None,
+    logging_level=logging.INFO,
+    setup_console_handler=True,
+    set_logger_level=logging.DEBUG):
+    from paste.util.converters import asbool
+    if isinstance(logging_level, basestring):
+        logging_level = logging._levelNames[logging_level]
+    if isinstance(set_logger_level, basestring):
+        set_logger_level = logging._levelNames[set_logger_level]
+    return TransLogger(
+        app,
+        format=format or None,
+        logging_level=logging_level,
+        logger_name=logger_name,
+        setup_console_handler=asbool(setup_console_handler),
+        set_logger_level=set_logger_level)
+
+make_filter.__doc__ = TransLogger.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/url.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/url.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/url.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,475 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+This module implements a class for handling URLs.
+"""
+import urllib
+import cgi
+from paste import request
+# Imported lazily from FormEncode:
+variabledecode = None
+
+__all__ = ["URL", "Image"]
+
+def html_quote(v):
+    if v is None:
+        return ''
+    return cgi.escape(str(v), 1)
+
+def url_quote(v):
+    if v is None:
+        return ''
+    return urllib.quote(str(v))
+
+url_unquote = urllib.unquote
+
+def js_repr(v):
+    if v is None:
+        return 'null'
+    elif v is False:
+        return 'false'
+    elif v is True:
+        return 'true'
+    elif isinstance(v, list):
+        return '[%s]' % ', '.join(map(js_repr, v))
+    elif isinstance(v, dict):
+        return '{%s}' % ', '.join(
+            ['%s: %s' % (js_repr(key), js_repr(value))
+             for key, value in v])
+    elif isinstance(v, str):
+        return repr(v)
+    elif isinstance(v, unicode):
+        # @@: how do you do Unicode literals in Javascript?
+        return repr(v.encode('UTF-8'))
+    elif isinstance(v, (float, int)):
+        return repr(v)
+    elif isinstance(v, long):
+        return repr(v).lstrip('L')
+    elif hasattr(v, '__js_repr__'):
+        return v.__js_repr__()
+    else:
+        raise ValueError(
+            "I don't know how to turn %r into a Javascript representation"
+            % v)
+
+class URLResource(object):
+
+    """
+    This is an abstract superclass for different kinds of URLs
+    """
+
+    default_params = {}
+
+    def __init__(self, url, vars=None, attrs=None,
+                 params=None):
+        self.url = url or '/'
+        self.vars = vars or []
+        self.attrs = attrs or {}
+        self.params = self.default_params.copy()
+        self.original_params = params or {}
+        if params:
+            self.params.update(params)
+
+    #@classmethod
+    def from_environ(cls, environ, with_query_string=True,
+                     with_path_info=True, script_name=None,
+                     path_info=None, querystring=None):
+        url = request.construct_url(
+            environ, with_query_string=False,
+            with_path_info=with_path_info, script_name=script_name,
+            path_info=path_info)
+        if with_query_string:
+            if querystring is None:
+                vars = request.parse_querystring(environ)
+            else:
+                vars = cgi.parse_qsl(
+                    querystring,
+                    keep_blank_values=True,
+                    strict_parsing=False)
+        else:
+            vars = None
+        v = cls(url, vars=vars)
+        return v
+
+    from_environ = classmethod(from_environ)
+
+    def __call__(self, *args, **kw):
+        res = self._add_positional(args)
+        res = res._add_vars(kw)
+        return res
+
+    def __getitem__(self, item):
+        if '=' in item:
+            name, value = item.split('=', 1)
+            return self._add_vars({url_unquote(name): url_unquote(value)})
+        return self._add_positional((item,))
+
+    def attr(self, **kw):
+        for key in kw.keys():
+            if key.endswith('_'):
+                kw[key[:-1]] = kw[key]
+                del kw[key]
+        new_attrs = self.attrs.copy()
+        new_attrs.update(kw)
+        return self.__class__(self.url, vars=self.vars,
+                              attrs=new_attrs,
+                              params=self.original_params)
+
+    def param(self, **kw):
+        new_params = self.original_params.copy()
+        new_params.update(kw)
+        return self.__class__(self.url, vars=self.vars,
+                              attrs=self.attrs,
+                              params=new_params)
+
+    def coerce_vars(self, vars):
+        global variabledecode
+        need_variable_encode = False
+        for key, value in vars.items():
+            if isinstance(value, dict):
+                need_variable_encode = True
+            if key.endswith('_'):
+                vars[key[:-1]] = vars[key]
+                del vars[key]
+        if need_variable_encode:
+            if variabledecode is None:
+                from formencode import variabledecode
+            vars = variabledecode.variable_encode(vars)
+        return vars
+
+    
+    def var(self, **kw):
+        kw = self.coerce_vars(kw)
+        new_vars = self.vars + kw.items()
+        return self.__class__(self.url, vars=new_vars,
+                              attrs=self.attrs,
+                              params=self.original_params)
+
+    def setvar(self, **kw):
+        """
+        Like ``.var(...)``, except overwrites keys, where .var simply
+        extends the keys.  Setting a variable to None here will
+        effectively delete it.
+        """
+        kw = self.coerce_vars(kw)
+        new_vars = []
+        for name, values in self.vars:
+            if name in kw:
+                continue
+            new_vars.append((name, values))
+        new_vars.extend(kw.items())
+        return self.__class__(self.url, vars=new_vars,
+                              attrs=self.attrs,
+                              params=self.original_params)
+
+    def setvars(self, **kw):
+        """
+        Creates a copy of this URL, but with all the variables set/reset
+        (like .setvar(), except clears past variables at the same time)
+        """
+        return self.__class__(self.url, vars=kw.items(),
+                              attrs=self.attrs,
+                              params=self.original_params)
+
+    def addpath(self, *paths):
+        u = self
+        for path in paths:
+            path = str(path).lstrip('/')
+            new_url = u.url
+            if not new_url.endswith('/'):
+                new_url += '/'
+            u = u.__class__(new_url+path, vars=u.vars,
+                            attrs=u.attrs,
+                            params=u.original_params)
+        return u
+            
+    __div__ = addpath
+
+    def become(self, OtherClass):
+        return OtherClass(self.url, vars=self.vars,
+                          attrs=self.attrs,
+                          params=self.original_params)
+    
+    def href__get(self):
+        s = self.url
+        if self.vars:
+            s += '?'
+            vars = []
+            for name, val in self.vars:
+                if isinstance(val, (list, tuple)):
+                    val = [v for v in val if v is not None]
+                elif val is None:
+                    continue
+                vars.append((name, val))
+            s += urllib.urlencode(vars, True)
+        return s
+
+    href = property(href__get)
+
+    def __repr__(self):
+        base = '<%s %s' % (self.__class__.__name__,
+                           self.href or "''")
+        if self.attrs:
+            base += ' attrs(%s)' % (
+                ' '.join(['%s="%s"' % (html_quote(n), html_quote(v))
+                          for n, v in self.attrs.items()]))
+        if self.original_params:
+            base += ' params(%s)' % (
+                ', '.join(['%s=%r' % (n, v)
+                           for n, v in self.attrs.items()]))
+        return base + '>'
+    
+    def html__get(self):
+        if not self.params.get('tag'):
+            raise ValueError(
+                "You cannot get the HTML of %r until you set the "
+                "'tag' param'" % self)
+        content = self._get_content()
+        tag = '<%s' % self.params.get('tag')
+        attrs = ' '.join([
+            '%s="%s"' % (html_quote(n), html_quote(v))
+            for n, v in self._html_attrs()])
+        if attrs:
+            tag += ' ' + attrs
+        tag += self._html_extra()
+        if content is None:
+            return tag + ' />'
+        else:
+            return '%s>%s</%s>' % (tag, content, self.params.get('tag'))
+
+    html = property(html__get)
+
+    def _html_attrs(self):
+        return self.attrs.items()
+
+    def _html_extra(self):
+        return ''
+
+    def _get_content(self):
+        """
+        Return the content for a tag (for self.html); return None
+        for an empty tag (like ``<img />``)
+        """
+        raise NotImplementedError
+    
+    def _add_vars(self, vars):
+        raise NotImplementedError
+
+    def _add_positional(self, args):
+        raise NotImplementedError
+
+class URL(URLResource):
+
+    r"""
+    >>> u = URL('http://localhost')
+    >>> u
+    <URL http://localhost>
+    >>> u = u['view']
+    >>> str(u)
+    'http://localhost/view'
+    >>> u['//foo'].param(content='view').html
+    '<a href="http://localhost/view/foo">view</a>'
+    >>> u.param(confirm='Really?', content='goto').html
+    '<a href="http://localhost/view" onclick="return confirm(\'Really?\')">goto</a>'
+    >>> u(title='See "it"', content='goto').html
+    '<a href="http://localhost/view?title=See+%22it%22">goto</a>'
+    >>> u('another', var='fuggetaboutit', content='goto').html
+    '<a href="http://localhost/view/another?var=fuggetaboutit">goto</a>'
+    >>> u.attr(content='goto').html
+    Traceback (most recent call last):
+        ....
+    ValueError: You must give a content param to <URL http://localhost/view attrs(content="goto")> generate anchor tags
+    >>> str(u['foo=bar%20stuff'])
+    'http://localhost/view?foo=bar+stuff'
+    """
+
+    default_params = {'tag': 'a'}
+
+    def __str__(self):
+        return self.href
+
+    def _get_content(self):
+        if not self.params.get('content'):
+            raise ValueError(
+                "You must give a content param to %r generate anchor tags"
+                % self)
+        return self.params['content']
+
+    def _add_vars(self, vars):
+        url = self
+        for name in ('confirm', 'content'):
+            if name in vars:
+                url = url.param(**{name: vars.pop(name)})
+        if 'target' in vars:
+            url = url.attr(target=vars.pop('target'))
+        return url.var(**vars)
+
+    def _add_positional(self, args):
+        return self.addpath(*args)
+
+    def _html_attrs(self):
+        attrs = self.attrs.items()
+        attrs.insert(0, ('href', self.href))
+        if self.params.get('confirm'):
+            attrs.append(('onclick', 'return confirm(%s)'
+                          % js_repr(self.params['confirm'])))
+        return attrs
+
+    def onclick_goto__get(self):
+        return 'location.href=%s; return false' % js_repr(self.href)
+
+    onclick_goto = property(onclick_goto__get)
+
+    def button__get(self):
+        return self.become(Button)
+
+    button = property(button__get)
+
+    def js_popup__get(self):
+        return self.become(JSPopup)
+
+    js_popup = property(js_popup__get)
+            
+class Image(URLResource):
+
+    r"""
+    >>> i = Image('/images')
+    >>> i = i / '/foo.png'
+    >>> i.html
+    '<img src="/images/foo.png" />'
+    >>> str(i['alt=foo'])
+    '<img src="/images/foo.png" alt="foo" />'
+    >>> i.href
+    '/images/foo.png'
+    """
+    
+    default_params = {'tag': 'img'}
+
+    def __str__(self):
+        return self.html
+
+    def _get_content(self):
+        return None
+
+    def _add_vars(self, vars):
+        return self.attr(**vars)
+
+    def _add_positional(self, args):
+        return self.addpath(*args)
+
+    def _html_attrs(self):
+        attrs = self.attrs.items()
+        attrs.insert(0, ('src', self.href))
+        return attrs
+
+class Button(URLResource):
+
+    r"""
+    >>> u = URL('/')
+    >>> u = u / 'delete'
+    >>> b = u.button['confirm=Sure?'](id=5, content='del')
+    >>> str(b)
+    '<button onclick="if (confirm(\'Sure?\')) {location.href=\'/delete?id=5\'}; return false">del</button>'
+    """
+
+    default_params = {'tag': 'button'}
+
+    def __str__(self):
+        return self.html
+
+    def _get_content(self):
+        if self.params.get('content'):
+            return self.params['content']
+        if self.attrs.get('value'):
+            return self.attrs['content']
+        # @@: Error?
+        return None
+
+    def _add_vars(self, vars):
+        button = self
+        if 'confirm' in vars:
+            button = button.param(confirm=vars.pop('confirm'))
+        if 'content' in vars:
+            button = button.param(content=vars.pop('content'))
+        return button.var(**vars)
+
+    def _add_positional(self, args):
+        return self.addpath(*args)
+
+    def _html_attrs(self):
+        attrs = self.attrs.items()
+        onclick = 'location.href=%s' % js_repr(self.href)
+        if self.params.get('confirm'):
+            onclick = 'if (confirm(%s)) {%s}' % (
+                js_repr(self.params['confirm']), onclick)
+        onclick += '; return false'
+        attrs.insert(0, ('onclick', onclick))
+        return attrs
+
+class JSPopup(URLResource):
+
+    r"""
+    >>> u = URL('/')
+    >>> u = u / 'view'
+    >>> j = u.js_popup(content='view')
+    >>> j.html
+    '<a href="/view" onclick="window.open(\'/view\', \'_blank\'); return false" target="_blank">view</a>'
+    """
+
+    default_params = {'tag': 'a', 'target': '_blank'}
+
+    def _add_vars(self, vars):
+        button = self
+        for var in ('width', 'height', 'stripped', 'content'):
+            if var in vars:
+                button = button.param(**{var: vars.pop(var)})
+        return button.var(**vars)
+
+    def _window_args(self):
+        p = self.params
+        features = []
+        if p.get('stripped'):
+            p['location'] = p['status'] = p['toolbar'] = '0'
+        for param in 'channelmode directories fullscreen location menubar resizable scrollbars status titlebar'.split():
+            if param not in p:
+                continue
+            v = p[param]
+            if v not in ('yes', 'no', '1', '0'):
+                if v:
+                    v = '1'
+                else:
+                    v = '0'
+            features.append('%s=%s' % (param, v))
+        for param in 'height left top width':
+            if not p.get(param):
+                continue
+            features.append('%s=%s' % (param, p[param]))
+        args = [self.href, p['target']]
+        if features:
+            args.append(','.join(features))
+        return ', '.join(map(js_repr, args))
+
+    def _html_attrs(self):
+        attrs = self.attrs.items()
+        onclick = ('window.open(%s); return false'
+                   % self._window_args())
+        attrs.insert(0, ('target', self.params['target']))
+        attrs.insert(0, ('onclick', onclick))
+        attrs.insert(0, ('href', self.href))
+        return attrs
+
+    def _get_content(self):
+        if not self.params.get('content'):
+            raise ValueError(
+                "You must give a content param to %r generate anchor tags"
+                % self)
+        return self.params['content']
+
+    def _add_positional(self, args):
+        return self.addpath(*args)
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlmap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlmap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlmap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,250 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Map URL prefixes to WSGI applications.  See ``URLMap``
+"""
+
+from UserDict import DictMixin
+import re
+import os
+import cgi
+from paste import httpexceptions
+
+__all__ = ['URLMap', 'PathProxyURLMap']
+
+def urlmap_factory(loader, global_conf, **local_conf):
+    if 'not_found_app' in local_conf:
+        not_found_app = local_conf.pop('not_found_app')
+    else:
+        not_found_app = global_conf.get('not_found_app')
+    if not_found_app:
+        not_found_app = loader.get_app(not_found_app, global_conf=global_conf)
+    urlmap = URLMap(not_found_app=not_found_app)
+    for path, app_name in local_conf.items():
+        path = parse_path_expression(path)
+        app = loader.get_app(app_name, global_conf=global_conf)
+        urlmap[path] = app
+    return urlmap
+
+def parse_path_expression(path):
+    """
+    Parses a path expression like 'domain foobar.com port 20 /' or
+    just '/foobar' for a path alone.  Returns as an address that
+    URLMap likes.
+    """
+    parts = path.split()
+    domain = port = path = None
+    while parts:
+        if parts[0] == 'domain':
+            parts.pop(0)
+            if not parts:
+                raise ValueError("'domain' must be followed with a domain name")
+            if domain:
+                raise ValueError("'domain' given twice")
+            domain = parts.pop(0)
+        elif parts[0] == 'port':
+            parts.pop(0)
+            if not parts:
+                raise ValueError("'port' must be followed with a port number")
+            if port:
+                raise ValueError("'port' given twice")
+            port = parts.pop(0)
+        else:
+            if path:
+                raise ValueError("more than one path given (have %r, got %r)"
+                                 % (path, parts[0]))
+            path = parts.pop(0)
+    s = ''
+    if domain:
+        s = 'http://%s' % domain
+    if port:
+        if not domain:
+            raise ValueError("If you give a port, you must also give a domain")
+        s += ':' + port
+    if path:
+        if s:
+            s += '/'
+        s += path
+    return s
+
+class URLMap(DictMixin):
+
+    """
+    URLMap instances are dictionary-like object that dispatch to one
+    of several applications based on the URL.
+
+    The dictionary keys are URLs to match (like
+    ``PATH_INFO.startswith(url)``), and the values are applications to
+    dispatch to.  URLs are matched most-specific-first, i.e., longest
+    URL first.  The ``SCRIPT_NAME`` and ``PATH_INFO`` environmental
+    variables are adjusted to indicate the new context.
+
+    URLs can also include domains, like ``http://blah.com/foo``, or as
+    tuples ``('blah.com', '/foo')``.  This will match domain names; without
+    the ``http://domain`` or with a domain of ``None`` any domain will be
+    matched (so long as no other explicit domain matches).  """
+
+    def __init__(self, not_found_app=None):
+        self.applications = []
+        if not not_found_app:
+            not_found_app = self.not_found_app
+        self.not_found_application = not_found_app
+
+    norm_url_re = re.compile('//+')
+    domain_url_re = re.compile('^(http|https)://')
+
+    def not_found_app(self, environ, start_response):
+        mapper = environ.get('paste.urlmap_object')
+        if mapper:
+            matches = [p for p, a in mapper.applications]
+            extra = 'defined apps: %s' % (
+                ',\n  '.join(map(repr, matches)))
+        else:
+            extra = ''
+        extra += '\nSCRIPT_NAME: %r' % environ.get('SCRIPT_NAME')
+        extra += '\nPATH_INFO: %r' % environ.get('PATH_INFO')
+        extra += '\nHTTP_HOST: %r' % environ.get('HTTP_HOST')
+        app = httpexceptions.HTTPNotFound(
+            environ['PATH_INFO'],
+            comment=cgi.escape(extra)).wsgi_application
+        return app(environ, start_response)
+
+    def normalize_url(self, url, trim=True):
+        if isinstance(url, (list, tuple)):
+            domain = url[0]
+            url = self.normalize_url(url[1])[1]
+            return domain, url
+        assert (not url or url.startswith('/')
+                or self.domain_url_re.search(url)), (
+            "URL fragments must start with / or http:// (you gave %r)" % url)
+        match = self.domain_url_re.search(url)
+        if match:
+            url = url[match.end():]
+            if '/' in url:
+                domain, url = url.split('/', 1)
+                url = '/' + url
+            else:
+                domain, url = url, ''
+        else:
+            domain = None
+        url = self.norm_url_re.sub('/', url)
+        if trim:
+            url = url.rstrip('/')
+        return domain, url
+
+    def sort_apps(self):
+        """
+        Make sure applications are sorted with longest URLs first
+        """
+        def key(app_desc):
+            (domain, url), app = app_desc
+            if not domain:
+                # Make sure empty domains sort last:
+                return '\xff', -len(url)
+            else:
+                return domain, -len(url)
+        apps = [(key(desc), desc) for desc in self.applications]
+        apps.sort()
+        self.applications = [desc for (sortable, desc) in apps]
+
+    def __setitem__(self, url, app):
+        if app is None:
+            try:
+                del self[url]
+            except KeyError:
+                pass
+            return
+        dom_url = self.normalize_url(url)
+        if dom_url in self:
+            del self[dom_url]
+        self.applications.append((dom_url, app))
+        self.sort_apps()
+
+    def __getitem__(self, url):
+        dom_url = self.normalize_url(url)
+        for app_url, app in self.applications:
+            if app_url == dom_url:
+                return app
+        raise KeyError(
+            "No application with the url %r (domain: %r; existing: %s)"
+            % (url[1], url[0] or '*', self.applications))
+
+    def __delitem__(self, url):
+        url = self.normalize_url(url)
+        for app_url, app in self.applications:
+            if app_url == url:
+                self.applications.remove((app_url, app))
+                break
+        else:
+            raise KeyError(
+                "No application with the url %r" % (url,))
+
+    def keys(self):
+        return [app_url for app_url, app in self.applications]
+
+    def __call__(self, environ, start_response):
+        host = environ.get('HTTP_HOST', environ.get('SERVER_NAME')).lower()
+        if ':' in host:
+            host, port = host.split(':', 1)
+        else:
+            if environ['wsgi.url_scheme'] == 'http':
+                port = '80'
+            else:
+                port = '443'
+        path_info = environ.get('PATH_INFO')
+        path_info = self.normalize_url(path_info, False)[1]
+        for (domain, app_url), app in self.applications:
+            if domain and domain != host and domain != host+':'+port:
+                continue
+            if (path_info == app_url
+                or path_info.startswith(app_url + '/')):
+                environ['SCRIPT_NAME'] += app_url
+                environ['PATH_INFO'] = path_info[len(app_url):]
+                return app(environ, start_response)
+        environ['paste.urlmap_object'] = self
+        return self.not_found_application(environ, start_response)
+
+
+class PathProxyURLMap(object):
+
+    """
+    This is a wrapper for URLMap that catches any strings that
+    are passed in as applications; these strings are treated as
+    filenames (relative to `base_path`) and are passed to the
+    callable `builder`, which will return an application.
+
+    This is intended for cases when configuration files can be
+    treated as applications.
+
+    `base_paste_url` is the URL under which all applications added through
+    this wrapper must go.  Use ``""`` if you want this to not
+    change incoming URLs.
+    """
+
+    def __init__(self, map, base_paste_url, base_path, builder):
+        self.map = map
+        self.base_paste_url = self.map.normalize_url(base_paste_url)
+        self.base_path = base_path
+        self.builder = builder
+
+    def __setitem__(self, url, app):
+        if isinstance(app, (str, unicode)):
+            app_fn = os.path.join(self.base_path, app)
+            app = self.builder(app_fn)
+        url = self.map.normalize_url(url)
+        # @@: This means http://foo.com/bar will potentially
+        # match foo.com, but /base_paste_url/bar, which is unintuitive
+        url = (url[0] or self.base_paste_url[0],
+               self.base_paste_url[1] + url[1])
+        self.map[url] = app
+
+    def __getattr__(self, attr):
+        return getattr(self.map, attr)
+
+    # This is really the only settable attribute
+    def not_found_application__get(self):
+        return self.map.not_found_application
+    def not_found_application__set(self, value):
+        self.map.not_found_application = value
+    not_found_application = property(not_found_application__get,
+                                     not_found_application__set)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlparser.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlparser.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/urlparser.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,638 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+WSGI applications that parse the URL and dispatch to on-disk resources
+"""
+
+import os
+import sys
+import imp
+import mimetypes
+try:
+    import pkg_resources
+except ImportError:
+    pkg_resources = None
+from paste import request
+from paste import fileapp
+from paste.util import import_string
+from paste import httpexceptions
+from httpheaders import ETAG
+from paste.util import converters
+
+class NoDefault(object):
+    pass
+
+__all__ = ['URLParser', 'StaticURLParser', 'PkgResourcesParser']
+
+class URLParser(object):
+
+    """
+    WSGI middleware
+
+    Application dispatching, based on URL.  An instance of `URLParser` is
+    an application that loads and delegates to other applications.  It
+    looks for files in its directory that match the first part of
+    PATH_INFO; these may have an extension, but are not required to have
+    one, in which case the available files are searched to find the
+    appropriate file.  If it is ambiguous, a 404 is returned and an error
+    logged.
+
+    By default there is a constructor for .py files that loads the module,
+    and looks for an attribute ``application``, which is a ready
+    application object, or an attribute that matches the module name,
+    which is a factory for building applications, and is called with no
+    arguments.
+
+    URLParser will also look in __init__.py for special overrides.
+    These overrides are:
+
+    ``urlparser_hook(environ)``
+        This can modify the environment.  Its return value is ignored,
+        and it cannot be used to change the response in any way.  You
+        *can* use this, for example, to manipulate SCRIPT_NAME/PATH_INFO
+        (try to keep them consistent with the original URL -- but
+        consuming PATH_INFO and moving that to SCRIPT_NAME is ok).
+
+    ``urlparser_wrap(environ, start_response, app)``:
+        After URLParser finds the application, it calls this function
+        (if present).  If this function doesn't call
+        ``app(environ, start_response)`` then the application won't be
+        called at all!  This can be used to allocate resources (with
+        ``try:finally:``) or otherwise filter the output of the
+        application.
+
+    ``not_found_hook(environ, start_response)``:
+        If no file can be found (*in this directory*) to match the
+        request, then this WSGI application will be called.  You can
+        use this to change the URL and pass the request back to
+        URLParser again, or on to some other application.  This
+        doesn't catch all ``404 Not Found`` responses, just missing
+        files.
+
+    ``application(environ, start_response)``:
+        This basically overrides URLParser completely, and the given
+        application is used for all requests.  ``urlparser_wrap`` and
+        ``urlparser_hook`` are still called, but the filesystem isn't
+        searched in any way.
+    """
+
+    parsers_by_directory = {}
+
+    # This is lazily initialized
+    init_module = NoDefault
+
+    global_constructors = {}
+
+    def __init__(self, global_conf,
+                 directory, base_python_name,
+                 index_names=NoDefault,
+                 hide_extensions=NoDefault,
+                 ignore_extensions=NoDefault,
+                 constructors=None,
+                 **constructor_conf):
+        """
+        Create a URLParser object that looks at `directory`.
+        `base_python_name` is the package that this directory
+        represents, thus any Python modules in this directory will
+        be given names under this package.
+        """
+        if global_conf:
+            import warnings
+            warnings.warn(
+                'The global_conf argument to URLParser is deprecated; '
+                'either pass in None or {}, or use make_url_parser',
+                DeprecationWarning)
+        else:
+            global_conf = {}
+        if os.path.sep != '/':
+            directory = directory.replace(os.path.sep, '/')
+        self.directory = directory
+        self.base_python_name = base_python_name
+        # This logic here should be deprecated since it is in
+        # make_url_parser
+        if index_names is NoDefault:
+            index_names = global_conf.get(
+                'index_names', ('index', 'Index', 'main', 'Main'))
+        self.index_names = converters.aslist(index_names)
+        if hide_extensions is NoDefault:
+            hide_extensions = global_conf.get(
+                'hide_extensions', ('.pyc', '.bak', '.py~', '.pyo'))
+        self.hide_extensions = converters.aslist(hide_extensions)
+        if ignore_extensions is NoDefault:
+            ignore_extensions = global_conf.get(
+                'ignore_extensions', ())
+        self.ignore_extensions = converters.aslist(ignore_extensions)
+        self.constructors = self.global_constructors.copy()
+        if constructors:
+            self.constructors.update(constructors)
+        # @@: Should we also check the global options for constructors?
+        for name, value in constructor_conf.items():
+            if not name.startswith('constructor '):
+                raise ValueError(
+                    "Only extra configuration keys allowed are "
+                    "'constructor .ext = import_expr'; you gave %r "
+                    "(=%r)" % (name, value))
+            ext = name[len('constructor '):].strip()
+            if isinstance(value, (str, unicode)):
+                value = import_string.eval_import(value)
+            self.constructors[ext] = value
+
+    def __call__(self, environ, start_response):
+        environ['paste.urlparser.base_python_name'] = self.base_python_name
+        if self.init_module is NoDefault:
+            self.init_module = self.find_init_module(environ)
+        path_info = environ.get('PATH_INFO', '')
+        if not path_info:
+            return self.add_slash(environ, start_response)
+        if (self.init_module
+            and getattr(self.init_module, 'urlparser_hook', None)):
+            self.init_module.urlparser_hook(environ)
+        orig_path_info = environ['PATH_INFO']
+        orig_script_name = environ['SCRIPT_NAME']
+        application, filename = self.find_application(environ)
+        if not application:
+            if (self.init_module
+                and getattr(self.init_module, 'not_found_hook', None)
+                and environ.get('paste.urlparser.not_found_parser') is not self):
+                not_found_hook = self.init_module.not_found_hook
+                environ['paste.urlparser.not_found_parser'] = self
+                environ['PATH_INFO'] = orig_path_info
+                environ['SCRIPT_NAME'] = orig_script_name
+                return not_found_hook(environ, start_response)
+            if filename is None:
+                name, rest_of_path = request.path_info_split(environ['PATH_INFO'])
+                if not name:
+                    name = 'one of %s' % ', '.join(
+                        self.index_names or
+                        ['(no index_names defined)'])
+
+                return self.not_found(
+                    environ, start_response,
+                    'Tried to load %s from directory %s'
+                    % (name, self.directory))
+            else:
+                environ['wsgi.errors'].write(
+                    'Found resource %s, but could not construct application\n'
+                    % filename)
+                return self.not_found(
+                    environ, start_response,
+                    'Tried to load %s from directory %s'
+                    % (filename, self.directory))
+        if (self.init_module
+            and getattr(self.init_module, 'urlparser_wrap', None)):
+            return self.init_module.urlparser_wrap(
+                environ, start_response, application)
+        else:
+            return application(environ, start_response)
+
+    def find_application(self, environ):
+        if (self.init_module
+            and getattr(self.init_module, 'application', None)
+            and not environ.get('paste.urlparser.init_application') == environ['SCRIPT_NAME']):
+            environ['paste.urlparser.init_application'] = environ['SCRIPT_NAME']
+            return self.init_module.application, None
+        name, rest_of_path = request.path_info_split(environ['PATH_INFO'])
+        environ['PATH_INFO'] = rest_of_path
+        if name is not None:
+            environ['SCRIPT_NAME'] = environ.get('SCRIPT_NAME', '') + '/' + name
+        if not name:
+            names = self.index_names
+            for index_name in names:
+                filename = self.find_file(environ, index_name)
+                if filename:
+                    break
+            else:
+                # None of the index files found
+                filename = None
+        else:
+            filename = self.find_file(environ, name)
+        if filename is None:
+            return None, filename
+        else:
+            return self.get_application(environ, filename), filename
+
+    def not_found(self, environ, start_response, debug_message=None):
+        exc = httpexceptions.HTTPNotFound(
+            'The resource at %s could not be found'
+            % request.construct_url(environ),
+            comment=debug_message)
+        return exc.wsgi_application(environ, start_response)
+
+    def add_slash(self, environ, start_response):
+        """
+        This happens when you try to get to a directory
+        without a trailing /
+        """
+        url = request.construct_url(environ, with_query_string=False)
+        url += '/'
+        if environ.get('QUERY_STRING'):
+            url += '?' + environ['QUERY_STRING']
+        exc = httpexceptions.HTTPMovedPermanently(
+            'The resource has moved to %s - you should be redirected '
+            'automatically.' % url,
+            headers=[('location', url)])
+        return exc.wsgi_application(environ, start_response)
+
+    def find_file(self, environ, base_filename):
+        possible = []
+        """Cache a few values to reduce function call overhead"""
+        for filename in os.listdir(self.directory):
+            base, ext = os.path.splitext(filename)
+            full_filename = os.path.join(self.directory, filename)
+            if (ext in self.hide_extensions
+                or not base):
+                continue
+            if filename == base_filename:
+                possible.append(full_filename)
+                continue
+            if ext in self.ignore_extensions:
+                continue
+            if base == base_filename:
+                possible.append(full_filename)
+        if not possible:
+            #environ['wsgi.errors'].write(
+            #    'No file found matching %r in %s\n'
+            #    % (base_filename, self.directory))
+            return None
+        if len(possible) > 1:
+            # If there is an exact match, this isn't 'ambiguous'
+            # per se; it might mean foo.gif and foo.gif.back for
+            # instance
+            if full_filename in possible:
+                return full_filename
+            else:
+                environ['wsgi.errors'].write(
+                    'Ambiguous URL: %s; matches files %s\n'
+                    % (request.construct_url(environ),
+                       ', '.join(possible)))
+            return None
+        return possible[0]
+
+    def get_application(self, environ, filename):
+        if os.path.isdir(filename):
+            t = 'dir'
+        else:
+            t = os.path.splitext(filename)[1]
+        constructor = self.constructors.get(t, self.constructors.get('*'))
+        if constructor is None:
+            #environ['wsgi.errors'].write(
+            #    'No constructor found for %s\n' % t)
+            return constructor
+        app = constructor(self, environ, filename)
+        if app is None:
+            #environ['wsgi.errors'].write(
+            #    'Constructor %s return None for %s\n' %
+            #    (constructor, filename))
+            pass
+        return app
+
+    def register_constructor(cls, extension, constructor):
+        """
+        Register a function as a constructor.  Registered constructors
+        apply to all instances of `URLParser`.
+
+        The extension should have a leading ``.``, or the special
+        extensions ``dir`` (for directories) and ``*`` (a catch-all).
+
+        `constructor` must be a callable that takes two arguments:
+        ``environ`` and ``filename``, and returns a WSGI application.
+        """
+        d = cls.global_constructors
+        assert not d.has_key(extension), (
+            "A constructor already exists for the extension %r (%r) "
+            "when attemption to register constructor %r"
+            % (extension, d[extension], constructor))
+        d[extension] = constructor
+    register_constructor = classmethod(register_constructor)
+
+    def get_parser(self, directory, base_python_name):
+        """
+        Get a parser for the given directory, or create one if
+        necessary.  This way parsers can be cached and reused.
+
+        # @@: settings are inherited from the first caller
+        """
+        try:
+            return self.parsers_by_directory[(directory, base_python_name)]
+        except KeyError:
+            parser = self.__class__(
+                {},
+                directory, base_python_name,
+                index_names=self.index_names,
+                hide_extensions=self.hide_extensions,
+                ignore_extensions=self.ignore_extensions,
+                constructors=self.constructors)
+            self.parsers_by_directory[(directory, base_python_name)] = parser
+            return parser
+
+    def find_init_module(self, environ):
+        filename = os.path.join(self.directory, '__init__.py')
+        if not os.path.exists(filename):
+            return None
+        return load_module(environ, filename)
+
+    def __repr__(self):
+        return '<%s directory=%r; module=%s at %s>' % (
+            self.__class__.__name__,
+            self.directory,
+            self.base_python_name,
+            hex(abs(id(self))))
+
+def make_directory(parser, environ, filename):
+    base_python_name = environ['paste.urlparser.base_python_name']
+    if base_python_name:
+        base_python_name += "." + os.path.basename(filename)
+    else:
+        base_python_name = os.path.basename(filename)
+    return parser.get_parser(filename, base_python_name)
+
+URLParser.register_constructor('dir', make_directory)
+
+def make_unknown(parser, environ, filename):
+    return fileapp.FileApp(filename)
+
+URLParser.register_constructor('*', make_unknown)
+
+def load_module(environ, filename):
+    base_python_name = environ['paste.urlparser.base_python_name']
+    module_name = os.path.splitext(os.path.basename(filename))[0]
+    if base_python_name:
+        module_name = base_python_name + '.' + module_name
+    return load_module_from_name(environ, filename, module_name,
+                                 environ['wsgi.errors'])
+
+def load_module_from_name(environ, filename, module_name, errors):
+    if sys.modules.has_key(module_name):
+        return sys.modules[module_name]
+    init_filename = os.path.join(os.path.dirname(filename), '__init__.py')
+    if not os.path.exists(init_filename):
+        try:
+            f = open(init_filename, 'w')
+        except (OSError, IOError), e:
+            errors.write(
+                'Cannot write __init__.py file into directory %s (%s)\n'
+                % (os.path.dirname(filename), e))
+            return None
+        f.write('#\n')
+        f.close()
+    fp = None
+    if sys.modules.has_key(module_name):
+        return sys.modules[module_name]
+    if '.' in module_name:
+        parent_name = '.'.join(module_name.split('.')[:-1])
+        base_name = module_name.split('.')[-1]
+        parent = load_module_from_name(environ, os.path.dirname(filename),
+                                       parent_name, errors)
+    else:
+        base_name = module_name
+    fp = None
+    try:
+        fp, pathname, stuff = imp.find_module(
+            base_name, [os.path.dirname(filename)])
+        module = imp.load_module(module_name, fp, pathname, stuff)
+    finally:
+        if fp is not None:
+            fp.close()
+    return module
+
+def make_py(parser, environ, filename):
+    module = load_module(environ, filename)
+    if not module:
+        return None
+    if hasattr(module, 'application') and module.application:
+        return getattr(module.application, 'wsgi_application', module.application)
+    base_name = module.__name__.split('.')[-1]
+    if hasattr(module, base_name):
+        obj = getattr(module, base_name)
+        if hasattr(obj, 'wsgi_application'):
+            return obj.wsgi_application
+        else:
+            # @@: Old behavior; should probably be deprecated eventually:
+            return getattr(module, base_name)()
+    environ['wsgi.errors'].write(
+        "Cound not find application or %s in %s\n"
+        % (base_name, module))
+    return None
+
+URLParser.register_constructor('.py', make_py)
+
+class StaticURLParser(object):
+    """
+    Like ``URLParser`` but only serves static files.
+
+    ``cache_max_age``:
+      integer specifies Cache-Control max_age in seconds
+    """
+    # @@: Should URLParser subclass from this?
+
+    def __init__(self, directory, root_directory=None,
+                 cache_max_age=None):
+        self.directory = self.normpath(directory)
+        self.root_directory = self.normpath(root_directory or directory)
+        self.cache_max_age = cache_max_age
+
+    def normpath(path):
+        return os.path.normcase(os.path.abspath(path))
+    normpath = staticmethod(normpath)
+
+    def __call__(self, environ, start_response):
+        path_info = environ.get('PATH_INFO', '')
+        if not path_info:
+            return self.add_slash(environ, start_response)
+        if path_info == '/':
+            # @@: This should obviously be configurable
+            filename = 'index.html'
+        else:
+            filename = request.path_info_pop(environ)
+        full = self.normpath(os.path.join(self.directory, filename))
+        if not full.startswith(self.root_directory):
+            # Out of bounds
+            return self.not_found(environ, start_response)
+        if not os.path.exists(full):
+            return self.not_found(environ, start_response)
+        if os.path.isdir(full):
+            # @@: Cache?
+            return self.__class__(full, root_directory=self.root_directory,
+                                  cache_max_age=self.cache_max_age)(environ,
+                                                                   start_response)
+        if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/':
+            return self.error_extra_path(environ, start_response)
+        if_none_match = environ.get('HTTP_IF_NONE_MATCH')
+        if if_none_match:
+            mytime = os.stat(full).st_mtime
+            if str(mytime) == if_none_match:
+                headers = []
+                ## FIXME: probably should be
+                ## ETAG.update(headers, '"%s"' % mytime)
+                ETAG.update(headers, mytime)
+                start_response('304 Not Modified', headers)
+                return [''] # empty body
+
+        fa = self.make_app(full)
+        if self.cache_max_age:
+            fa.cache_control(max_age=self.cache_max_age)
+        return fa(environ, start_response)
+
+    def make_app(self, filename):
+        return fileapp.FileApp(filename)
+
+    def add_slash(self, environ, start_response):
+        """
+        This happens when you try to get to a directory
+        without a trailing /
+        """
+        url = request.construct_url(environ, with_query_string=False)
+        url += '/'
+        if environ.get('QUERY_STRING'):
+            url += '?' + environ['QUERY_STRING']
+        exc = httpexceptions.HTTPMovedPermanently(
+            'The resource has moved to %s - you should be redirected '
+            'automatically.' % url,
+            headers=[('location', url)])
+        return exc.wsgi_application(environ, start_response)
+
+    def not_found(self, environ, start_response, debug_message=None):
+        exc = httpexceptions.HTTPNotFound(
+            'The resource at %s could not be found'
+            % request.construct_url(environ),
+            comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in %r; debug: %s'
+            % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'),
+               self.directory, debug_message or '(none)'))
+        return exc.wsgi_application(environ, start_response)
+
+    def error_extra_path(self, environ, start_response):
+        exc = httpexceptions.HTTPNotFound(
+            'The trailing path %r is not allowed' % environ['PATH_INFO'])
+        return exc.wsgi_application(environ, start_response)
+
+    def __repr__(self):
+        return '<%s %r>' % (self.__class__.__name__, self.directory)
+
+def make_static(global_conf, document_root, cache_max_age=None):
+    """
+    Return a WSGI application that serves a directory (configured
+    with document_root)
+
+    cache_max_age - integer specifies CACHE_CONTROL max_age in seconds
+    """
+    if cache_max_age is not None:
+        cache_max_age = int(cache_max_age)
+    return StaticURLParser(
+        document_root, cache_max_age=cache_max_age)
+
+class PkgResourcesParser(StaticURLParser):
+
+    def __init__(self, egg_or_spec, resource_name, manager=None, root_resource=None):
+        if pkg_resources is None:
+            raise NotImplementedError("This class requires pkg_resources.")
+        if isinstance(egg_or_spec, (str, unicode)):
+            self.egg = pkg_resources.get_distribution(egg_or_spec)
+        else:
+            self.egg = egg_or_spec
+        self.resource_name = resource_name
+        if manager is None:
+            manager = pkg_resources.ResourceManager()
+        self.manager = manager
+        if root_resource is None:
+            root_resource = resource_name
+        self.root_resource = os.path.normpath(root_resource)
+
+    def __repr__(self):
+        return '<%s for %s:%r>' % (
+            self.__class__.__name__,
+            self.egg.project_name,
+            self.resource_name)
+
+    def __call__(self, environ, start_response):
+        path_info = environ.get('PATH_INFO', '')
+        if not path_info:
+            return self.add_slash(environ, start_response)
+        if path_info == '/':
+            # @@: This should obviously be configurable
+            filename = 'index.html'
+        else:
+            filename = request.path_info_pop(environ)
+        resource = os.path.normcase(os.path.normpath(
+                    self.resource_name + '/' + filename))
+        if self.root_resource is not None and not resource.startswith(self.root_resource):
+            # Out of bounds
+            return self.not_found(environ, start_response)
+        if not self.egg.has_resource(resource):
+            return self.not_found(environ, start_response)
+        if self.egg.resource_isdir(resource):
+            # @@: Cache?
+            child_root = self.root_resource is not None and self.root_resource or \
+                self.resource_name
+            return self.__class__(self.egg, resource, self.manager,
+                                  root_resource=child_root)(environ, start_response)
+        if environ.get('PATH_INFO') and environ.get('PATH_INFO') != '/':
+            return self.error_extra_path(environ, start_response)
+
+        type, encoding = mimetypes.guess_type(resource)
+        if not type:
+            type = 'application/octet-stream'
+        # @@: I don't know what to do with the encoding.
+        try:
+            file = self.egg.get_resource_stream(self.manager, resource)
+        except (IOError, OSError), e:
+            exc = httpexceptions.HTTPForbidden(
+                'You are not permitted to view this file (%s)' % e)
+            return exc.wsgi_application(environ, start_response)
+        start_response('200 OK',
+                       [('content-type', type)])
+        return fileapp._FileIter(file)
+
+    def not_found(self, environ, start_response, debug_message=None):
+        exc = httpexceptions.HTTPNotFound(
+            'The resource at %s could not be found'
+            % request.construct_url(environ),
+            comment='SCRIPT_NAME=%r; PATH_INFO=%r; looking in egg:%s#%r; debug: %s'
+            % (environ.get('SCRIPT_NAME'), environ.get('PATH_INFO'),
+               self.egg, self.resource_name, debug_message or '(none)'))
+        return exc.wsgi_application(environ, start_response)
+
+def make_pkg_resources(global_conf, egg, resource_name=''):
+    """
+    A static file parser that loads data from an egg using
+    ``pkg_resources``.  Takes a configuration value ``egg``, which is
+    an egg spec, and a base ``resource_name`` (default empty string)
+    which is the path in the egg that this starts at.
+    """
+    if pkg_resources is None:
+        raise NotImplementedError("This function requires pkg_resources.")
+    return PkgResourcesParser(egg, resource_name)
+
+def make_url_parser(global_conf, directory, base_python_name,
+                    index_names=None, hide_extensions=None,
+                    ignore_extensions=None,
+                    **constructor_conf):
+    """
+    Create a URLParser application that looks in ``directory``, which
+    should be the directory for the Python package named in
+    ``base_python_name``.  ``index_names`` are used when viewing the
+    directory (like ``'index'`` for ``'index.html'``).
+    ``hide_extensions`` are extensions that are not viewable (like
+    ``'.pyc'``) and ``ignore_extensions`` are viewable but only if an
+    explicit extension is given.
+    """
+    if index_names is None:
+        index_names = global_conf.get(
+            'index_names', ('index', 'Index', 'main', 'Main'))
+    index_names = converters.aslist(index_names)
+
+    if hide_extensions is None:
+        hide_extensions = global_conf.get(
+            'hide_extensions', ('.pyc', 'bak', 'py~'))
+    hide_extensions = converters.aslist(hide_extensions)
+
+    if ignore_extensions is None:
+        ignore_extensions = global_conf.get(
+            'ignore_extensions', ())
+    ignore_extensions = converters.aslist(ignore_extensions)
+    # There's no real way to set constructors currently...
+
+    return URLParser({}, directory, base_python_name,
+                     index_names=index_names,
+                     hide_extensions=hide_extensions,
+                     ignore_extensions=ignore_extensions,
+                     **constructor_conf)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/PySourceColor.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/PySourceColor.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/PySourceColor.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2103 @@
+# -*- coding: Latin-1 -*-
+"""
+PySourceColor: color Python source code
+"""
+
+"""
+ PySourceColor.py
+
+----------------------------------------------------------------------------
+
+ A python source to colorized html/css/xhtml converter.
+ Hacked by M.E.Farmer Jr. 2004, 2005
+ Python license
+
+----------------------------------------------------------------------------
+
+ - HTML markup does not create w3c valid html, but it works on every
+   browser i've tried so far.(I.E.,Mozilla/Firefox,Opera,Konqueror,wxHTML).
+ - CSS markup is w3c validated html 4.01 strict,
+   but will not render correctly on all browsers.
+ - XHTML markup is w3c validated xhtml 1.0 strict,
+   like html 4.01, will not render correctly on all browsers.
+
+----------------------------------------------------------------------------
+
+Features:
+
+ -Three types of markup:
+    html (default) 
+    css/html 4.01 strict
+    xhtml 1.0 strict
+
+ -Can tokenize and colorize:
+    12 types of strings
+    2 comment types
+    numbers
+    operators
+    brackets
+    math operators
+    class / name
+    def / name
+    decorator / name
+    keywords
+    arguments class/def/decorator
+    linenumbers
+    names
+    text
+
+ -Eight colorschemes built-in:
+    null
+    mono
+    lite (default)
+    dark 
+    dark2
+    idle
+    viewcvs
+    pythonwin
+
+ -Header and footer
+    set to '' for builtin header / footer.
+    give path to a file containing the html
+        you want added as header or footer.
+
+ -Arbitrary text and html
+    html markup converts all to raw (TEXT token)
+    #@# for raw -> send raw text.
+    #$# for span -> inline html and text.
+    #%# for div -> block level html and text.
+
+ -Linenumbers
+    Supports all styles. New token is called LINENUMBER.
+    Defaults to NAME if not defined.
+
+ Style options
+ 
+ -ALL markups support these text styles:
+         b = bold
+         i = italic
+         u = underline
+ -CSS and XHTML has limited support  for borders:
+     HTML markup functions will ignore these.
+     Optional: Border color in RGB hex
+     Defaults to the text forecolor.
+         #rrggbb = border color
+     Border size:
+         l = thick
+         m = medium
+         t = thin
+     Border type:
+         - = dashed
+         . = dotted
+         s = solid
+         d = double
+         g = groove
+         r = ridge
+         n = inset
+         o = outset
+     You can specify multiple sides,
+     they will all use the same style.
+     Optional: Default is full border.
+         v = bottom
+         < = left
+         > = right
+         ^ = top
+     NOTE: Specify the styles you want.
+           The markups will ignore unsupported styles
+           Also note not all browsers can show these options
+
+ -All tokens default to NAME if not defined
+     so the only absolutely critical ones to define are:
+     NAME, ERRORTOKEN, PAGEBACKGROUND
+
+----------------------------------------------------------------------------
+
+Example usage::
+
+ # import
+ import PySourceColor as psc
+ psc.convert('c:/Python22/PySourceColor.py', colors=psc.idle, show=1)
+
+ # from module import *
+ from PySourceColor import *
+ convert('c:/Python22/Lib', colors=lite, markup="css",
+          header='#$#<b>This is a simpe heading</b><hr/>')
+
+ # How to use a custom colorscheme, and most of the 'features'
+ from PySourceColor import *
+ new = {
+   ERRORTOKEN:             ('bui','#FF8080',''),
+   DECORATOR_NAME:         ('s','#AACBBC',''),
+   DECORATOR:              ('n','#333333',''),
+   NAME:                   ('t.<v','#1133AA','#DDFF22'),
+   NUMBER:                 ('','#236676','#FF5555'),
+   OPERATOR:               ('b','#454567','#BBBB11'),
+   MATH_OPERATOR:          ('','#935623','#423afb'),
+   BRACKETS:               ('b','#ac34bf','#6457a5'),
+   COMMENT:                ('t-#0022FF','#545366','#AABBFF'),
+   DOUBLECOMMENT:          ('<l#553455','#553455','#FF00FF'),
+   CLASS_NAME:             ('m^v-','#000000','#FFFFFF'),
+   DEF_NAME:               ('l=<v','#897845','#000022'),
+   KEYWORD:                ('.b','#345345','#FFFF22'),
+   SINGLEQUOTE:            ('mn','#223344','#AADDCC'),
+   SINGLEQUOTE_R:          ('','#344522',''),
+   SINGLEQUOTE_U:          ('','#234234',''),
+   DOUBLEQUOTE:            ('m#0022FF','#334421',''),
+   DOUBLEQUOTE_R:          ('','#345345',''),
+   DOUBLEQUOTE_U:          ('','#678673',''),
+   TRIPLESINGLEQUOTE:      ('tv','#FFFFFF','#000000'),
+   TRIPLESINGLEQUOTE_R:    ('tbu','#443256','#DDFFDA'),
+   TRIPLESINGLEQUOTE_U:    ('','#423454','#DDFFDA'),
+   TRIPLEDOUBLEQUOTE:      ('li#236fd3b<>','#000000','#FFFFFF'),
+   TRIPLEDOUBLEQUOTE_R:    ('tub','#000000','#FFFFFF'),
+   TRIPLEDOUBLEQUOTE_U:    ('-', '#CCAABB','#FFFAFF'),
+   LINENUMBER:             ('ib-','#ff66aa','#7733FF'),]
+   TEXT:                   ('','#546634',''), 
+   PAGEBACKGROUND:         '#FFFAAA',
+     }
+ if __name__ == '__main__':
+     import sys
+     convert(sys.argv[1], './xhtml.html', colors=new, markup='xhtml', show=1,
+             linenumbers=1)
+     convert(sys.argv[1], './html.html', colors=new, markup='html', show=1,
+             linenumbers=1)
+
+"""
+
+__all__ = ['ERRORTOKEN','DECORATOR_NAME', 'DECORATOR', 'ARGS', 'EXTRASPACE',
+       'NAME', 'NUMBER', 'OPERATOR', 'COMMENT', 'MATH_OPERATOR',
+       'DOUBLECOMMENT', 'CLASS_NAME', 'DEF_NAME', 'KEYWORD', 'BRACKETS',
+       'SINGLEQUOTE','SINGLEQUOTE_R','SINGLEQUOTE_U','DOUBLEQUOTE',
+       'DOUBLEQUOTE_R', 'DOUBLEQUOTE_U', 'TRIPLESINGLEQUOTE', 'TEXT', 
+       'TRIPLESINGLEQUOTE_R', 'TRIPLESINGLEQUOTE_U', 'TRIPLEDOUBLEQUOTE',
+       'TRIPLEDOUBLEQUOTE_R', 'TRIPLEDOUBLEQUOTE_U', 'PAGEBACKGROUND',
+       'LINENUMBER', 'CODESTART', 'CODEEND', 'PY', 'TOKEN_NAMES', 'CSSHOOK',
+       'null', 'mono', 'lite', 'dark','dark2', 'pythonwin','idle', 
+       'viewcvs', 'Usage', 'cli', 'str2stdout', 'path2stdout', 'Parser',
+       'str2file', 'str2html', 'str2css', 'str2markup', 'path2file',
+       'path2html', 'convert', 'walkdir', 'defaultColors', 'showpage',
+       'pageconvert','tagreplace', 'MARKUPDICT']
+__title__ = 'PySourceColor'
+__version__ = "2.1a"
+__date__ = '25 April 2005'
+__author__ = "M.E.Farmer Jr."
+__credits__ = '''This was originally based on a python recipe
+submitted by Jürgen Hermann to ASPN. Now based on the voices in my head.
+M.E.Farmer 2004, 2005
+Python license
+'''
+import os
+import sys
+import time
+import glob
+import getopt
+import keyword
+import token
+import tokenize
+import traceback
+try :
+    import cStringIO as StringIO
+except:
+    import StringIO
+# Do not edit
+NAME = token.NAME
+NUMBER = token.NUMBER
+COMMENT = tokenize.COMMENT
+OPERATOR = token.OP
+ERRORTOKEN = token.ERRORTOKEN
+ARGS = token.NT_OFFSET + 1
+DOUBLECOMMENT = token.NT_OFFSET + 2
+CLASS_NAME = token.NT_OFFSET + 3
+DEF_NAME = token.NT_OFFSET + 4
+KEYWORD = token.NT_OFFSET + 5
+SINGLEQUOTE = token.NT_OFFSET + 6
+SINGLEQUOTE_R = token.NT_OFFSET + 7
+SINGLEQUOTE_U = token.NT_OFFSET + 8
+DOUBLEQUOTE = token.NT_OFFSET + 9
+DOUBLEQUOTE_R = token.NT_OFFSET + 10
+DOUBLEQUOTE_U = token.NT_OFFSET + 11
+TRIPLESINGLEQUOTE = token.NT_OFFSET + 12
+TRIPLESINGLEQUOTE_R = token.NT_OFFSET + 13
+TRIPLESINGLEQUOTE_U = token.NT_OFFSET + 14
+TRIPLEDOUBLEQUOTE = token.NT_OFFSET + 15
+TRIPLEDOUBLEQUOTE_R = token.NT_OFFSET + 16
+TRIPLEDOUBLEQUOTE_U = token.NT_OFFSET + 17
+PAGEBACKGROUND = token.NT_OFFSET + 18
+DECORATOR = token.NT_OFFSET + 19
+DECORATOR_NAME = token.NT_OFFSET + 20
+BRACKETS = token.NT_OFFSET + 21
+MATH_OPERATOR = token.NT_OFFSET + 22
+LINENUMBER = token.NT_OFFSET + 23
+TEXT = token.NT_OFFSET + 24
+PY = token.NT_OFFSET + 25
+CODESTART = token.NT_OFFSET + 26
+CODEEND = token.NT_OFFSET + 27
+CSSHOOK = token.NT_OFFSET + 28
+EXTRASPACE = token.NT_OFFSET + 29
+
+# markup classname lookup
+MARKUPDICT = {
+        ERRORTOKEN:             'py_err',
+        DECORATOR_NAME:         'py_decn',
+        DECORATOR:              'py_dec',
+        ARGS:                   'py_args',
+        NAME:                   'py_name',
+        NUMBER:                 'py_num',
+        OPERATOR:               'py_op',
+        COMMENT:                'py_com',
+        DOUBLECOMMENT:          'py_dcom',
+        CLASS_NAME:             'py_clsn',
+        DEF_NAME:               'py_defn',
+        KEYWORD:                'py_key',
+        SINGLEQUOTE:            'py_sq',
+        SINGLEQUOTE_R:          'py_sqr',
+        SINGLEQUOTE_U:          'py_squ',
+        DOUBLEQUOTE:            'py_dq',
+        DOUBLEQUOTE_R:          'py_dqr',
+        DOUBLEQUOTE_U:          'py_dqu',
+        TRIPLESINGLEQUOTE:      'py_tsq',
+        TRIPLESINGLEQUOTE_R:    'py_tsqr',
+        TRIPLESINGLEQUOTE_U:    'py_tsqu',
+        TRIPLEDOUBLEQUOTE:      'py_tdq',
+        TRIPLEDOUBLEQUOTE_R:    'py_tdqr',
+        TRIPLEDOUBLEQUOTE_U:    'py_tdqu',
+        BRACKETS:               'py_bra',
+        MATH_OPERATOR:          'py_mop',
+        LINENUMBER:             'py_lnum',
+        TEXT:                   'py_text',
+        }
+# might help users that want to create custom schemes
+TOKEN_NAMES= {
+       ERRORTOKEN:'ERRORTOKEN',
+       DECORATOR_NAME:'DECORATOR_NAME',
+       DECORATOR:'DECORATOR',
+       ARGS:'ARGS',
+       NAME:'NAME',
+       NUMBER:'NUMBER',
+       OPERATOR:'OPERATOR',
+       COMMENT:'COMMENT',
+       DOUBLECOMMENT:'DOUBLECOMMENT',
+       CLASS_NAME:'CLASS_NAME',
+       DEF_NAME:'DEF_NAME',
+       KEYWORD:'KEYWORD',
+       SINGLEQUOTE:'SINGLEQUOTE',
+       SINGLEQUOTE_R:'SINGLEQUOTE_R',
+       SINGLEQUOTE_U:'SINGLEQUOTE_U',
+       DOUBLEQUOTE:'DOUBLEQUOTE',
+       DOUBLEQUOTE_R:'DOUBLEQUOTE_R',
+       DOUBLEQUOTE_U:'DOUBLEQUOTE_U',
+       TRIPLESINGLEQUOTE:'TRIPLESINGLEQUOTE',
+       TRIPLESINGLEQUOTE_R:'TRIPLESINGLEQUOTE_R',
+       TRIPLESINGLEQUOTE_U:'TRIPLESINGLEQUOTE_U',
+       TRIPLEDOUBLEQUOTE:'TRIPLEDOUBLEQUOTE',
+       TRIPLEDOUBLEQUOTE_R:'TRIPLEDOUBLEQUOTE_R',
+       TRIPLEDOUBLEQUOTE_U:'TRIPLEDOUBLEQUOTE_U',
+       BRACKETS:'BRACKETS',
+       MATH_OPERATOR:'MATH_OPERATOR',
+       LINENUMBER:'LINENUMBER',
+       TEXT:'TEXT',
+       PAGEBACKGROUND:'PAGEBACKGROUND',
+       }
+
+######################################################################
+# Edit colors and styles to taste
+# Create your own scheme, just copy one below , rename and edit.
+# Custom styles must at least define NAME, ERRORTOKEN, PAGEBACKGROUND,
+# all missing elements will default to NAME.
+# See module docstring for details on style attributes.
+######################################################################
+# Copy null and use it as a starter colorscheme.
+null = {# tokentype: ('tags border_color', 'textforecolor', 'textbackcolor')
+        ERRORTOKEN:             ('','#000000',''),# Error token
+        DECORATOR_NAME:         ('','#000000',''),# Decorator name
+        DECORATOR:              ('','#000000',''),# @ symbol
+        ARGS:                   ('','#000000',''),# class,def,deco arguments
+        NAME:                   ('','#000000',''),# All other python text
+        NUMBER:                 ('','#000000',''),# 0->10
+        OPERATOR:               ('','#000000',''),# ':','<=',';',',','.','==', etc
+        MATH_OPERATOR:          ('','#000000',''),# '+','-','=','','**',etc
+        BRACKETS:               ('','#000000',''),# '[',']','(',')','{','}'
+        COMMENT:                ('','#000000',''),# Single comment
+        DOUBLECOMMENT:          ('','#000000',''),## Double comment
+        CLASS_NAME:             ('','#000000',''),# Class name
+        DEF_NAME:               ('','#000000',''),# Def name
+        KEYWORD:                ('','#000000',''),# Python keywords
+        SINGLEQUOTE:            ('','#000000',''),# 'SINGLEQUOTE'
+        SINGLEQUOTE_R:          ('','#000000',''),# r'SINGLEQUOTE'
+        SINGLEQUOTE_U:          ('','#000000',''),# u'SINGLEQUOTE'
+        DOUBLEQUOTE:            ('','#000000',''),# "DOUBLEQUOTE"
+        DOUBLEQUOTE_R:          ('','#000000',''),# r"DOUBLEQUOTE"
+        DOUBLEQUOTE_U:          ('','#000000',''),# u"DOUBLEQUOTE"
+        TRIPLESINGLEQUOTE:      ('','#000000',''),# '''TRIPLESINGLEQUOTE'''
+        TRIPLESINGLEQUOTE_R:    ('','#000000',''),# r'''TRIPLESINGLEQUOTE'''
+        TRIPLESINGLEQUOTE_U:    ('','#000000',''),# u'''TRIPLESINGLEQUOTE'''
+        TRIPLEDOUBLEQUOTE:      ('','#000000',''),# """TRIPLEDOUBLEQUOTE"""
+        TRIPLEDOUBLEQUOTE_R:    ('','#000000',''),# r"""TRIPLEDOUBLEQUOTE"""
+        TRIPLEDOUBLEQUOTE_U:    ('','#000000',''),# u"""TRIPLEDOUBLEQUOTE"""
+        TEXT:                   ('','#000000',''),# non python text 
+        LINENUMBER:             ('>ti#555555','#000000',''),# Linenumbers
+        PAGEBACKGROUND:         '#FFFFFF'# set the page background
+        }
+
+mono = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('bu','#000000',''),
+        DECORATOR:              ('b','#000000',''),
+        ARGS:                   ('b','#555555',''),
+        NAME:                   ('','#000000',''),
+        NUMBER:                 ('b','#000000',''),
+        OPERATOR:               ('b','#000000',''),
+        MATH_OPERATOR:          ('b','#000000',''),
+        BRACKETS:               ('b','#000000',''),
+        COMMENT:                ('i','#999999',''),
+        DOUBLECOMMENT:          ('b','#999999',''),
+        CLASS_NAME:             ('bu','#000000',''),
+        DEF_NAME:               ('b','#000000',''),
+        KEYWORD:                ('b','#000000',''),
+        SINGLEQUOTE:            ('','#000000',''),
+        SINGLEQUOTE_R:          ('','#000000',''),
+        SINGLEQUOTE_U:          ('','#000000',''),
+        DOUBLEQUOTE:            ('','#000000',''),
+        DOUBLEQUOTE_R:          ('','#000000',''),
+        DOUBLEQUOTE_U:          ('','#000000',''),
+        TRIPLESINGLEQUOTE:      ('','#000000',''),
+        TRIPLESINGLEQUOTE_R:    ('','#000000',''),
+        TRIPLESINGLEQUOTE_U:    ('','#000000',''),
+        TRIPLEDOUBLEQUOTE:      ('i','#000000',''),
+        TRIPLEDOUBLEQUOTE_R:    ('i','#000000',''),
+        TRIPLEDOUBLEQUOTE_U:    ('i','#000000',''),
+        TEXT:                   ('','#000000',''),
+        LINENUMBER:             ('>ti#555555','#000000',''),
+        PAGEBACKGROUND:         '#FFFFFF'
+        }
+
+dark = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('b','#FFBBAA',''),
+        DECORATOR:              ('b','#CC5511',''),
+        ARGS:                   ('b','#DDDDFF',''),
+        NAME:                   ('','#DDDDDD',''),
+        NUMBER:                 ('','#FF0000',''),
+        OPERATOR:               ('b','#FAF785',''),
+        MATH_OPERATOR:          ('b','#FAF785',''),
+        BRACKETS:               ('b','#FAF785',''),
+        COMMENT:                ('','#45FCA0',''),
+        DOUBLECOMMENT:          ('i','#A7C7A9',''),
+        CLASS_NAME:             ('b','#B666FD',''),
+        DEF_NAME:               ('b','#EBAE5C',''),
+        KEYWORD:                ('b','#8680FF',''),
+        SINGLEQUOTE:            ('','#F8BAFE',''),
+        SINGLEQUOTE_R:          ('','#F8BAFE',''),
+        SINGLEQUOTE_U:          ('','#F8BAFE',''),
+        DOUBLEQUOTE:            ('','#FF80C0',''),
+        DOUBLEQUOTE_R:          ('','#FF80C0',''),
+        DOUBLEQUOTE_U:          ('','#FF80C0',''),
+        TRIPLESINGLEQUOTE:      ('','#FF9595',''),
+        TRIPLESINGLEQUOTE_R:    ('','#FF9595',''),
+        TRIPLESINGLEQUOTE_U:    ('','#FF9595',''),
+        TRIPLEDOUBLEQUOTE:      ('','#B3FFFF',''),
+        TRIPLEDOUBLEQUOTE_R:    ('','#B3FFFF',''),
+        TRIPLEDOUBLEQUOTE_U:    ('','#B3FFFF',''),
+        TEXT:                   ('','#FFFFFF',''),
+        LINENUMBER:             ('>mi#555555','#bbccbb','#333333'),
+        PAGEBACKGROUND:         '#000000'
+        }
+
+dark2 = {
+        ERRORTOKEN:             ('','#FF0000',''),
+        DECORATOR_NAME:         ('b','#FFBBAA',''),
+        DECORATOR:              ('b','#CC5511',''),
+        ARGS:                   ('b','#DDDDDD',''),
+        NAME:                   ('','#C0C0C0',''),
+        NUMBER:                 ('b','#00FF00',''),
+        OPERATOR:               ('b','#FF090F',''),
+        MATH_OPERATOR:          ('b','#EE7020',''),
+        BRACKETS:               ('b','#FFB90F',''),
+        COMMENT:                ('i','#D0D000','#522000'),#'#88AA88','#11111F'),
+        DOUBLECOMMENT:          ('i','#D0D000','#522000'),#'#77BB77','#11111F'),
+        CLASS_NAME:             ('b','#DD4080',''),
+        DEF_NAME:               ('b','#FF8040',''),
+        KEYWORD:                ('b','#4726d1',''),
+        SINGLEQUOTE:            ('','#8080C0',''),
+        SINGLEQUOTE_R:          ('','#8080C0',''),
+        SINGLEQUOTE_U:          ('','#8080C0',''),
+        DOUBLEQUOTE:            ('','#ADB9F1',''),
+        DOUBLEQUOTE_R:          ('','#ADB9F1',''),
+        DOUBLEQUOTE_U:          ('','#ADB9F1',''),
+        TRIPLESINGLEQUOTE:      ('','#00C1C1',''),#A050C0
+        TRIPLESINGLEQUOTE_R:    ('','#00C1C1',''),#A050C0
+        TRIPLESINGLEQUOTE_U:    ('','#00C1C1',''),#A050C0
+        TRIPLEDOUBLEQUOTE:      ('','#33E3E3',''),#B090E0
+        TRIPLEDOUBLEQUOTE_R:    ('','#33E3E3',''),#B090E0
+        TRIPLEDOUBLEQUOTE_U:    ('','#33E3E3',''),#B090E0
+        TEXT:                   ('','#C0C0C0',''),
+        LINENUMBER:             ('>mi#555555','#bbccbb','#333333'),
+        PAGEBACKGROUND:         '#000000'
+        }
+
+lite = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('b','#BB4422',''),
+        DECORATOR:              ('b','#3333AF',''),
+        ARGS:                   ('b','#000000',''),
+        NAME:                   ('','#333333',''),
+        NUMBER:                 ('b','#DD2200',''),
+        OPERATOR:               ('b','#000000',''),
+        MATH_OPERATOR:          ('b','#000000',''),
+        BRACKETS:               ('b','#000000',''),
+        COMMENT:                ('','#007F00',''),
+        DOUBLECOMMENT:          ('','#608060',''),
+        CLASS_NAME:             ('b','#0000DF',''),
+        DEF_NAME:               ('b','#9C7A00',''),#f09030
+        KEYWORD:                ('b','#0000AF',''),
+        SINGLEQUOTE:            ('','#600080',''),
+        SINGLEQUOTE_R:          ('','#600080',''),
+        SINGLEQUOTE_U:          ('','#600080',''),
+        DOUBLEQUOTE:            ('','#A0008A',''),
+        DOUBLEQUOTE_R:          ('','#A0008A',''),
+        DOUBLEQUOTE_U:          ('','#A0008A',''),
+        TRIPLESINGLEQUOTE:      ('','#337799',''),
+        TRIPLESINGLEQUOTE_R:    ('','#337799',''),
+        TRIPLESINGLEQUOTE_U:    ('','#337799',''),
+        TRIPLEDOUBLEQUOTE:      ('','#1166AA',''),
+        TRIPLEDOUBLEQUOTE_R:    ('','#1166AA',''),
+        TRIPLEDOUBLEQUOTE_U:    ('','#1166AA',''),
+        TEXT:                   ('','#000000',''),
+        LINENUMBER:             ('>ti#555555','#000000',''),
+        PAGEBACKGROUND:         '#FFFFFF'
+        }
+
+idle = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('','#900090',''),
+        DECORATOR:              ('','#FF7700',''),
+        NAME:                   ('','#000000',''),
+        NUMBER:                 ('','#000000',''),
+        OPERATOR:               ('','#000000',''),
+        MATH_OPERATOR:          ('','#000000',''),
+        BRACKETS:               ('','#000000',''),
+        COMMENT:                ('','#DD0000',''),
+        DOUBLECOMMENT:          ('','#DD0000',''),
+        CLASS_NAME:             ('','#0000FF',''),
+        DEF_NAME:               ('','#0000FF',''),
+        KEYWORD:                ('','#FF7700',''),
+        SINGLEQUOTE:            ('','#00AA00',''),
+        SINGLEQUOTE_R:          ('','#00AA00',''),
+        SINGLEQUOTE_U:          ('','#00AA00',''),
+        DOUBLEQUOTE:            ('','#00AA00',''),
+        DOUBLEQUOTE_R:          ('','#00AA00',''),
+        DOUBLEQUOTE_U:          ('','#00AA00',''),
+        TRIPLESINGLEQUOTE:      ('','#00AA00',''),
+        TRIPLESINGLEQUOTE_R:    ('','#00AA00',''),
+        TRIPLESINGLEQUOTE_U:    ('','#00AA00',''),
+        TRIPLEDOUBLEQUOTE:      ('','#00AA00',''),
+        TRIPLEDOUBLEQUOTE_R:    ('','#00AA00',''),
+        TRIPLEDOUBLEQUOTE_U:    ('','#00AA00',''),
+        TEXT:                   ('','#000000',''),
+        LINENUMBER:             ('>ti#555555','#000000',''),
+        PAGEBACKGROUND:         '#FFFFFF'
+        }
+
+pythonwin = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('b','#DD0080',''),
+        DECORATOR:              ('b','#000080',''),
+        ARGS:                   ('','#000000',''),
+        NAME:                   ('','#303030',''),
+        NUMBER:                 ('','#008080',''),
+        OPERATOR:               ('','#000000',''),
+        MATH_OPERATOR:          ('','#000000',''),
+        BRACKETS:               ('','#000000',''),
+        COMMENT:                ('','#007F00',''),
+        DOUBLECOMMENT:          ('','#7F7F7F',''),
+        CLASS_NAME:             ('b','#0000FF',''),
+        DEF_NAME:               ('b','#007F7F',''),
+        KEYWORD:                ('b','#000080',''),
+        SINGLEQUOTE:            ('','#808000',''),
+        SINGLEQUOTE_R:          ('','#808000',''),
+        SINGLEQUOTE_U:          ('','#808000',''),
+        DOUBLEQUOTE:            ('','#808000',''),
+        DOUBLEQUOTE_R:          ('','#808000',''),
+        DOUBLEQUOTE_U:          ('','#808000',''),
+        TRIPLESINGLEQUOTE:      ('','#808000',''),
+        TRIPLESINGLEQUOTE_R:    ('','#808000',''),
+        TRIPLESINGLEQUOTE_U:    ('','#808000',''),
+        TRIPLEDOUBLEQUOTE:      ('','#808000',''),
+        TRIPLEDOUBLEQUOTE_R:    ('','#808000',''),
+        TRIPLEDOUBLEQUOTE_U:    ('','#808000',''),
+        TEXT:                   ('','#303030',''),
+        LINENUMBER:             ('>ti#555555','#000000',''),
+        PAGEBACKGROUND:         '#FFFFFF'
+        }
+
+viewcvs = {
+        ERRORTOKEN:             ('s#FF0000','#FF8080',''),
+        DECORATOR_NAME:         ('','#000000',''),
+        DECORATOR:              ('','#000000',''),
+        ARGS:                   ('','#000000',''),
+        NAME:                   ('','#000000',''),
+        NUMBER:                 ('','#000000',''),
+        OPERATOR:               ('','#000000',''),
+        MATH_OPERATOR:          ('','#000000',''),
+        BRACKETS:               ('','#000000',''),
+        COMMENT:                ('i','#b22222',''),
+        DOUBLECOMMENT:          ('i','#b22222',''),
+        CLASS_NAME:             ('','#000000',''),
+        DEF_NAME:               ('b','#0000ff',''),
+        KEYWORD:                ('b','#a020f0',''),
+        SINGLEQUOTE:            ('b','#bc8f8f',''),
+        SINGLEQUOTE_R:          ('b','#bc8f8f',''),
+        SINGLEQUOTE_U:          ('b','#bc8f8f',''),
+        DOUBLEQUOTE:            ('b','#bc8f8f',''),
+        DOUBLEQUOTE_R:          ('b','#bc8f8f',''),
+        DOUBLEQUOTE_U:          ('b','#bc8f8f',''),
+        TRIPLESINGLEQUOTE:      ('b','#bc8f8f',''),
+        TRIPLESINGLEQUOTE_R:    ('b','#bc8f8f',''),
+        TRIPLESINGLEQUOTE_U:    ('b','#bc8f8f',''),
+        TRIPLEDOUBLEQUOTE:      ('b','#bc8f8f',''),
+        TRIPLEDOUBLEQUOTE_R:    ('b','#bc8f8f',''),
+        TRIPLEDOUBLEQUOTE_U:    ('b','#bc8f8f',''),
+        TEXT:                   ('','#000000',''),
+        LINENUMBER:             ('>ti#555555','#000000',''),
+        PAGEBACKGROUND:         '#FFFFFF'
+        }
+
+defaultColors = lite
+
+def Usage():
+    doc = """
+ -----------------------------------------------------------------------------
+  PySourceColor.py ver: %s
+ -----------------------------------------------------------------------------
+  Module summary:
+     This module is designed to colorize python source code.
+         Input--->python source
+         Output-->colorized (html, html4.01/css, xhtml1.0)
+     Standalone:
+         This module will work from the command line with options.
+         This module will work with redirected stdio.
+     Imported:
+         This module can be imported and used directly in your code.
+ -----------------------------------------------------------------------------
+  Command line options:
+     -h, --help
+         Optional-> Display this help message.
+     -t, --test
+         Optional-> Will ignore all others flags but  --profile
+             test all schemes and markup combinations
+     -p, --profile
+         Optional-> Works only with --test or -t
+             runs profile.py and makes the test work in quiet mode.
+     -i, --in, --input
+         Optional-> If you give input on stdin.
+         Use any of these for the current dir (.,cwd)
+         Input can be file or dir.
+         Input from stdin use one of the following (-,stdin)
+         If stdin is used as input stdout is output unless specified.
+     -o, --out, --output
+         Optional-> output dir for the colorized source.
+             default: output dir is the input dir.
+         To output html to stdout use one of the following (-,stdout)
+         Stdout can be used without stdin if you give a file as input.
+     -c, --color
+         Optional-> null, mono, dark, dark2, lite, idle, pythonwin, viewcvs
+             default: dark 
+     -s, --show
+         Optional-> Show page after creation.
+             default: no show
+     -m, --markup
+         Optional-> html, css, xhtml
+             css, xhtml also support external stylesheets (-e,--external)
+             default: HTML
+     -e, --external
+         Optional-> use with css, xhtml
+             Writes an style sheet instead of embedding it in the page
+             saves it as pystyle.css in the same directory.
+             html markup will silently ignore this flag.
+     -H, --header
+         Opional-> add a page header to the top of the output
+         -H
+             Builtin header (name,date,hrule)
+         --header
+             You must specify a filename.
+             The header file must be valid html
+             and must handle its own font colors.
+             ex. --header c:/tmp/header.txt
+     -F, --footer
+         Opional-> add a page footer to the bottom of the output
+         -F 
+             Builtin footer (hrule,name,date)
+         --footer
+             You must specify a filename.
+             The footer file must be valid html
+             and must handle its own font colors.
+             ex. --footer c:/tmp/footer.txt  
+     -l, --linenumbers
+         Optional-> default is no linenumbers
+             Adds line numbers to the start of each line in the code.
+    --convertpage
+         Given a webpage that has code embedded in tags it will
+             convert embedded code to colorized html. 
+             (see pageconvert for details)
+ -----------------------------------------------------------------------------
+  Option usage:
+   # Test and show pages
+      python PySourceColor.py -t -s
+   # Test and only show profile results
+      python PySourceColor.py -t -p
+   # Colorize all .py,.pyw files in cwdir you can also use: (.,cwd)
+      python PySourceColor.py -i .
+   # Using long options w/ =
+      python PySourceColor.py --in=c:/myDir/my.py --color=lite --show
+   # Using short options w/out =
+      python PySourceColor.py -i c:/myDir/  -c idle -m css -e
+   # Using any mix
+      python PySourceColor.py --in . -o=c:/myDir --show
+   # Place a custom header on your files
+      python PySourceColor.py -i . -o c:/tmp -m xhtml --header c:/header.txt
+ -----------------------------------------------------------------------------
+  Stdio usage:
+   # Stdio using no options
+      python PySourceColor.py < c:/MyFile.py > c:/tmp/MyFile.html
+   # Using stdin alone automatically uses stdout for output: (stdin,-)
+      python PySourceColor.py -i- < c:/MyFile.py > c:/tmp/myfile.html
+   # Stdout can also be written to directly from a file instead of stdin
+      python PySourceColor.py -i c:/MyFile.py -m css -o- > c:/tmp/myfile.html
+   # Stdin can be used as input , but output can still be specified
+      python PySourceColor.py -i- -o c:/pydoc.py.html -s < c:/Python22/my.py
+ _____________________________________________________________________________
+ """
+    print doc % (__version__)
+    sys.exit(1)
+
+###################################################### Command line interface
+
+def cli():
+    """Handle command line args and redirections"""
+    try:
+        # try to get command line args
+        opts, args = getopt.getopt(sys.argv[1:],
+              "hseqtplHFi:o:c:m:h:f:",["help", "show", "quiet", 
+              "test", "external", "linenumbers", "convertpage", "profile", 
+              "input=", "output=", "color=", "markup=","header=", "footer="])
+    except getopt.GetoptError:
+        # on error print help information and exit:
+        Usage()
+    # init some names
+    input = None
+    output = None
+    colorscheme = None
+    markup = 'html'
+    header = None
+    footer = None
+    linenumbers = 0
+    show = 0
+    quiet = 0
+    test = 0
+    profile = 0
+    convertpage = 0
+    form = None
+    # if we have args then process them
+    for o, a in opts:
+        if o in ["-h", "--help"]:
+            Usage()
+            sys.exit()
+        if o in ["-o", "--output", "--out"]:
+            output = a
+        if o in ["-i", "--input", "--in"]:
+            input = a
+            if input in [".", "cwd"]:
+                input = os.getcwd()
+        if o in ["-s", "--show"]:
+            show = 1
+        if o in ["-q", "--quiet"]:
+            quiet = 1
+        if o in ["-t", "--test"]:
+            test = 1
+        if o in ["--convertpage"]:
+            convertpage = 1
+        if o in ["-p", "--profile"]:
+            profile = 1
+        if o in ["-e", "--external"]:
+            form = 'external'
+        if o in ["-m", "--markup"]:
+            markup = str(a)
+        if o in ["-l", "--linenumbers"]:
+            linenumbers = 1
+        if o in ["--header"]:
+            header = str(a)
+        elif o == "-H":
+            header = ''
+        if o in ["--footer"]:
+            footer = str(a)
+        elif o == "-F":
+            footer = ''
+        if o in ["-c", "--color"]:
+            try:
+                colorscheme = globals().get(a.lower())
+            except:
+                traceback.print_exc()
+                Usage()
+    if test:
+        if profile:
+            import profile
+            profile.run('_test(show=%s, quiet=%s)'%(show,quiet))
+        else:
+            # Parse this script in every possible colorscheme and markup
+            _test(show,quiet)
+    elif input in [None, "-", "stdin"] or output in ["-", "stdout"]:
+        # determine if we are going to use stdio
+        if input not in [None, "-", "stdin"]:
+            if os.path.isfile(input) :
+                path2stdout(input, colors=colorscheme, markup=markup,
+                            linenumbers=linenumbers, header=header, 
+                            footer=footer, form=form)
+            else:
+                raise PathError, 'File does not exists!'
+        else:
+            try:
+                if sys.stdin.isatty():
+                    raise InputError, 'Please check input!'
+                else:
+                    if output in [None,"-","stdout"]:
+                        str2stdout(sys.stdin.read(), colors=colorscheme,
+                                   markup=markup, header=header,
+                                   footer=footer, linenumbers=linenumbers,
+                                   form=form)
+                    else:
+                        str2file(sys.stdin.read(), outfile=output, show=show, 
+                                markup=markup, header=header, footer=footer,
+                                linenumbers=linenumbers, form=form)
+            except:
+                traceback.print_exc()
+                Usage()
+    else:
+        if os.path.exists(input):
+            if convertpage:
+                # if there was at least an input given we can proceed
+                pageconvert(input, out=output, colors=colorscheme, 
+                            show=show, markup=markup,linenumbers=linenumbers)
+            else:
+                # if there was at least an input given we can proceed
+                convert(source=input, outdir=output, colors=colorscheme, 
+                        show=show, markup=markup, quiet=quiet, header=header,
+                        footer=footer, linenumbers=linenumbers, form=form)
+        else:
+            raise PathError, 'File does not exists!'
+            Usage()
+
+######################################################### Simple markup tests
+
+def _test(show=0, quiet=0):
+    """Test the parser and most of the functions.
+
+       There are 19 test total(eight colorschemes in three diffrent markups,
+       and a str2file test. Most functions are tested by this.
+    """
+    fi = sys.argv[0]
+    if not fi.endswith('.exe'):# Do not test if frozen as an archive
+        # this is a collection of test, most things are covered.
+        path2file(fi, '/tmp/null.html', null, show=show, quiet=quiet)
+        path2file(fi, '/tmp/null_css.html', null, show=show,
+                  markup='css', quiet=quiet)
+        path2file(fi, '/tmp/mono.html', mono, show=show, quiet=quiet)
+        path2file(fi, '/tmp/mono_css.html', mono, show=show,
+                  markup='css', quiet=quiet)
+        path2file(fi, '/tmp/lite.html', lite, show=show, quiet=quiet)
+        path2file(fi, '/tmp/lite_css.html', lite, show=show,
+                  markup='css', quiet=quiet, header='', footer='', 
+                  linenumbers=1)
+        path2file(fi, '/tmp/lite_xhtml.html', lite, show=show,
+                  markup='xhtml', quiet=quiet)
+        path2file(fi, '/tmp/dark.html', dark, show=show, quiet=quiet)
+        path2file(fi, '/tmp/dark_css.html', dark, show=show,
+                  markup='css', quiet=quiet, linenumbers=1)
+        path2file(fi, '/tmp/dark2.html', dark2, show=show, quiet=quiet)
+        path2file(fi, '/tmp/dark2_css.html', dark2, show=show,
+                  markup='css', quiet=quiet)
+        path2file(fi, '/tmp/dark2_xhtml.html', dark2, show=show,
+                  markup='xhtml', quiet=quiet, header='', footer='', 
+                  linenumbers=1, form='external')
+        path2file(fi, '/tmp/idle.html', idle, show=show, quiet=quiet)
+        path2file(fi, '/tmp/idle_css.html', idle, show=show,
+                  markup='css', quiet=quiet)
+        path2file(fi, '/tmp/viewcvs.html', viewcvs, show=show, 
+                  quiet=quiet, linenumbers=1)
+        path2file(fi, '/tmp/viewcvs_css.html', viewcvs, show=show,
+                  markup='css', linenumbers=1, quiet=quiet)
+        path2file(fi, '/tmp/pythonwin.html', pythonwin, show=show,
+                  quiet=quiet)
+        path2file(fi, '/tmp/pythonwin_css.html', pythonwin, show=show,
+                  markup='css', quiet=quiet)
+        teststr=r'''"""This is a test of decorators and other things"""
+# This should be line 421...
+ at whatever(arg,arg2)
+ at A @B(arghh) @C
+def LlamaSaysNi(arg='Ni!',arg2="RALPH"):
+   """This docstring is deeply disturbed by all the llama references"""
+   print '%s The Wonder Llama says %s'% (arg2,arg)
+# So I was like duh!, and he was like ya know?!,
+# and so we were both like huh...wtf!? RTFM!! LOL!!;)
+ at staticmethod## Double comments are KewL.
+def LlamasRLumpy():
+   """This docstring is too sexy to be here.
+   """
+   u"""
+=============================
+A Møøse once bit my sister...
+=============================
+   """
+   ## Relax, this won't hurt a bit, just a simple, painless procedure,
+   ## hold still while I get the anesthetizing hammer.
+   m = {'three':'1','won':'2','too':'3'}
+   o = r'fishy\fishy\fishy/fish\oh/where/is\my/little\..'
+   python = uR""" 
+ No realli! She was Karving her initials øn the møøse with the sharpened end  
+ of an interspace tøøthbrush given her by Svenge - her brother-in-law -an Oslo
+ dentist and star of many Norwegian møvies: "The Høt Hands of an Oslo         
+ Dentist", "Fillings of Passion", "The Huge Mølars of Horst Nordfink"..."""
+   RU"""142 MEXICAN WHOOPING LLAMAS"""#<-Can you fit 142 llamas in a red box?
+   n = u' HERMSGERVØRDENBRØTBØRDA ' + """ YUTTE """
+   t = """SAMALLNIATNUOMNAIRODAUCE"""+"DENIARTYLLAICEPS04"
+   ## We apologise for the fault in the
+   ## comments. Those responsible have been
+   ## sacked.
+   y = '14 NORTH CHILEAN GUANACOS \
+(CLOSELY RELATED TO THE LLAMA)'
+   rules = [0,1,2,3,4,5]
+   print y'''
+        htmlPath = os.path.abspath('/tmp/strtest_lines.html')
+        str2file(teststr, htmlPath, colors=dark, markup='xhtml',
+                 linenumbers=420, show=show)
+        _printinfo("  wrote %s" % htmlPath, quiet)
+        htmlPath = os.path.abspath('/tmp/strtest_nolines.html')
+        str2file(teststr, htmlPath, colors=dark, markup='xhtml',
+                 show=show)
+        _printinfo("  wrote %s" % htmlPath, quiet)
+    else:
+        Usage()
+    return
+
+# emacs wants this: '
+
+####################################################### User funtctions
+
+def str2stdout(sourcestring, colors=None, title='', markup='html',
+                 header=None, footer=None,
+                 linenumbers=0, form=None):
+    """Converts a code(string) to colorized HTML. Writes to stdout.
+
+       form='code',or'snip' (for "<pre>yourcode</pre>" only)
+       colors=null,mono,lite,dark,dark2,idle,or pythonwin
+    """
+    Parser(sourcestring, colors=colors, title=title, markup=markup,
+           header=header, footer=footer,
+           linenumbers=linenumbers).format(form)
+
+def path2stdout(sourcepath, title='', colors=None, markup='html',
+                   header=None, footer=None,
+                   linenumbers=0, form=None):
+    """Converts code(file) to colorized HTML. Writes to stdout.
+
+       form='code',or'snip' (for "<pre>yourcode</pre>" only)
+       colors=null,mono,lite,dark,dark2,idle,or pythonwin
+    """
+    sourcestring = open(sourcepath).read()
+    Parser(sourcestring, colors=colors, title=sourcepath, 
+           markup=markup, header=header, footer=footer,
+           linenumbers=linenumbers).format(form)
+
+def str2html(sourcestring, colors=None, title='', 
+               markup='html', header=None, footer=None,
+               linenumbers=0, form=None):
+    """Converts a code(string) to colorized HTML. Returns an HTML string.
+
+       form='code',or'snip' (for "<pre>yourcode</pre>" only)
+       colors=null,mono,lite,dark,dark2,idle,or pythonwin
+    """
+    stringIO = StringIO.StringIO()
+    Parser(sourcestring, colors=colors, title=title, out=stringIO,
+           markup=markup, header=header, footer=footer,
+           linenumbers=linenumbers).format(form)
+    stringIO.seek(0)
+    return stringIO.read()
+  
+def str2css(sourcestring, colors=None, title='',
+              markup='css', header=None, footer=None,  
+              linenumbers=0, form=None):
+    """Converts a code string to colorized CSS/HTML. Returns CSS/HTML string
+       
+       If form != None then this will return (stylesheet_str, code_str)
+       colors=null,mono,lite,dark,dark2,idle,or pythonwin
+    """
+    if markup.lower() not in ['css' ,'xhtml']:
+        markup = 'css'
+    stringIO = StringIO.StringIO()
+    parse = Parser(sourcestring, colors=colors, title=title,
+                   out=stringIO, markup=markup,
+                   header=header, footer=footer,
+                   linenumbers=linenumbers)
+    parse.format(form)
+    stringIO.seek(0)
+    if form != None:
+        return parse._sendCSSStyle(external=1), stringIO.read()
+    else:
+        return None, stringIO.read()
+
+def str2markup(sourcestring, colors=None, title = '',
+               markup='xhtml', header=None, footer=None, 
+              linenumbers=0, form=None):
+    """ Convert code strings into ([stylesheet or None], colorized string) """
+    if markup.lower() == 'html':
+        return None, str2html(sourcestring, colors=colors, title=title,
+                   header=header, footer=footer, markup=markup, 
+                   linenumbers=linenumbers, form=form)
+    else:
+        return str2css(sourcestring, colors=colors, title=title,
+                   header=header, footer=footer, markup=markup, 
+                   linenumbers=linenumbers, form=form)
+
+def str2file(sourcestring, outfile, colors=None, title='', 
+               markup='html', header=None, footer=None, 
+               linenumbers=0, show=0, dosheet=1, form=None):
+    """Converts a code string to a file.
+
+       makes no attempt at correcting bad pathnames
+    """
+    css , html = str2markup(sourcestring, colors=colors, title='',
+                    markup=markup, header=header, footer=footer,
+                    linenumbers=linenumbers, form=form)
+    # write html
+    f = open(outfile,'wt')
+    f.writelines(html)
+    f.close()
+    #write css
+    if css != None and dosheet: 
+        dir = os.path.dirname(outfile)
+        outcss = os.path.join(dir,'pystyle.css')
+        f = open(outcss,'wt')
+        f.writelines(css)
+        f.close()
+    if show:
+        showpage(outfile)
+
+def path2html(sourcepath, colors=None, markup='html',
+                header=None, footer=None,
+                linenumbers=0, form=None):
+    """Converts code(file) to colorized HTML. Returns an HTML string.
+
+       form='code',or'snip' (for "<pre>yourcode</pre>" only)
+       colors=null,mono,lite,dark,dark2,idle,or pythonwin
+    """
+    stringIO = StringIO.StringIO()
+    sourcestring = open(sourcepath).read()
+    Parser(sourcestring, colors, title=sourcepath, out=stringIO,
+           markup=markup, header=header, footer=footer,
+           linenumbers=linenumbers).format(form)
+    stringIO.seek(0)
+    return stringIO.read()
+
+def convert(source, outdir=None, colors=None,
+              show=0, markup='html', quiet=0,
+              header=None, footer=None, linenumbers=0, form=None):
+    """Takes a file or dir as input and places the html in the outdir.
+
+       If outdir is none it defaults to the input dir
+    """
+    count=0
+    # If it is a filename then path2file
+    if not os.path.isdir(source):
+        if os.path.isfile(source):
+            count+=1
+            path2file(source, outdir, colors, show, markup, 
+                     quiet, form, header, footer, linenumbers, count)
+        else:
+            raise PathError, 'File does not exist!'
+    # If we pass in a dir we need to walkdir for files.
+    # Then we need to colorize them with path2file
+    else:
+        fileList = walkdir(source)
+        if fileList != None:
+            # make sure outdir is a dir
+            if outdir != None:
+                if os.path.splitext(outdir)[1] != '':
+                    outdir = os.path.split(outdir)[0]
+            for item in fileList:
+                count+=1
+                path2file(item, outdir, colors, show, markup,
+                          quiet, form, header, footer, linenumbers, count)
+            _printinfo('Completed colorizing %s files.'%str(count), quiet)
+        else:
+            _printinfo("No files to convert in dir.", quiet)
+
+def path2file(sourcePath, out=None, colors=None, show=0,
+                markup='html', quiet=0, form=None,
+                header=None, footer=None, linenumbers=0, count=1):
+    """ Converts python source to html file"""
+    # If no outdir is given we use the sourcePath
+    if out == None:#this is a guess
+        htmlPath = sourcePath + '.html'
+    else:
+        # If we do give an out_dir, and it does
+        # not exist , it will be created.
+        if os.path.splitext(out)[1] == '':
+            if not os.path.isdir(out):
+                os.makedirs(out)
+            sourceName = os.path.basename(sourcePath)
+            htmlPath = os.path.join(out,sourceName)+'.html'
+        # If we do give an out_name, and its dir does
+        # not exist , it will be created.
+        else:
+            outdir = os.path.split(out)[0]
+            if not os.path.isdir(outdir):
+                os.makedirs(outdir)
+            htmlPath = out
+    htmlPath = os.path.abspath(htmlPath)
+    # Open the text and do the parsing.
+    source = open(sourcePath).read()
+    parse = Parser(source, colors, sourcePath, open(htmlPath, 'wt'),
+                   markup, header, footer, linenumbers)
+    parse.format(form)
+    _printinfo("  wrote %s" % htmlPath, quiet)
+    # html markup will ignore the external flag, but
+    # we need to stop the blank file from being written.
+    if form == 'external' and count == 1 and markup != 'html':
+        cssSheet = parse._sendCSSStyle(external=1)
+        cssPath = os.path.join(os.path.dirname(htmlPath),'pystyle.css')
+        css = open(cssPath, 'wt')
+        css.write(cssSheet)
+        css.close()
+        _printinfo("    wrote %s" % cssPath, quiet)
+    if show:
+        # load HTML page into the default web browser.
+        showpage(htmlPath)
+    return htmlPath
+
+def tagreplace(sourcestr, colors=lite, markup='xhtml', 
+               linenumbers=0, dosheet=1, tagstart='<PY>'.lower(),
+               tagend='</PY>'.lower(), stylesheet='pystyle.css'):
+    """This is a helper function for pageconvert. Returns css, page.
+    """
+    if markup.lower() != 'html':
+        link  = '<link rel="stylesheet" href="%s" type="text/css"/></head>'
+        css = link%stylesheet
+        if sourcestr.find(css) == -1:
+            sourcestr = sourcestr.replace('</head>', css, 1)
+    starttags = sourcestr.count(tagstart)
+    endtags = sourcestr.count(tagend)
+    if starttags:
+        if starttags == endtags:
+            for _ in range(starttags):
+               datastart = sourcestr.find(tagstart)
+               dataend = sourcestr.find(tagend)
+               data = sourcestr[datastart+len(tagstart):dataend]
+               data = unescape(data)
+               css , data = str2markup(data, colors=colors, 
+                         linenumbers=linenumbers, markup=markup, form='embed')
+               start = sourcestr[:datastart]
+               end = sourcestr[dataend+len(tagend):]
+               sourcestr =  ''.join([start,data,end])
+        else:
+            raise InputError,'Tag mismatch!\nCheck %s,%s tags'%tagstart,tagend
+    if not dosheet:
+        css = None
+    return css, sourcestr
+    
+def pageconvert(path, out=None, colors=lite, markup='xhtml', linenumbers=0,
+                  dosheet=1, tagstart='<PY>'.lower(), tagend='</PY>'.lower(),
+                  stylesheet='pystyle', show=1, returnstr=0):
+    """This function can colorize Python source
+
+       that is written in a webpage enclosed in tags.
+    """
+    if out == None:
+        out = os.path.dirname(path)
+    infile = open(path, 'r').read()
+    css,page  = tagreplace(sourcestr=infile,colors=colors, 
+                   markup=markup, linenumbers=linenumbers, dosheet=dosheet,
+                   tagstart=tagstart, tagend=tagend, stylesheet=stylesheet)
+    if not returnstr:
+        newpath = os.path.abspath(os.path.join(
+                  out,'tmp', os.path.basename(path)))
+        if not os.path.exists(newpath):
+            try:
+                os.makedirs(os.path.dirname(newpath))
+            except:
+                pass#traceback.print_exc()
+                #Usage()
+        y = open(newpath, 'w')
+        y.write(page)
+        y.close()
+        if css:
+            csspath = os.path.abspath(os.path.join(
+                      out,'tmp','%s.css'%stylesheet))
+            x = open(csspath,'w')
+            x.write(css)
+            x.close()
+        if show:
+            try:
+                os.startfile(newpath)
+            except:
+                traceback.print_exc()
+        return newpath
+    else:
+        return css, page
+
+##################################################################### helpers
+
+def walkdir(dir):
+    """Return a list of .py and .pyw files from a given directory.
+
+       This function can be written as a generator Python 2.3, or a genexp
+       in Python 2.4. But 2.2 and 2.1 would be left out....
+    """
+    # Get a list of files that match *.py*
+    GLOB_PATTERN = os.path.join(dir, "*.[p][y]*")
+    pathlist = glob.glob(GLOB_PATTERN)
+    # Now filter out all but py and pyw
+    filterlist = [x for x in pathlist
+                        if x.endswith('.py')
+                        or x.endswith('.pyw')]
+    if filterlist != []:
+        # if we have a list send it
+        return filterlist
+    else:
+        return None
+
+def showpage(path):
+    """Helper function to open webpages"""
+    try:
+        import webbrowser
+        webbrowser.open_new(os.path.abspath(path))
+    except:
+        traceback.print_exc()
+
+def _printinfo(message, quiet):
+    """Helper to print messages"""
+    if not quiet:
+        print message
+
+def escape(text):
+     """escape text for html. similar to cgi.escape"""
+     text = text.replace("&", "&amp;")
+     text = text.replace("<", "&lt;")
+     text = text.replace(">", "&gt;")
+     return text
+
+def unescape(text):
+     """unsecape escaped text"""
+     text = text.replace("&quot;", '"')
+     text = text.replace("&gt;", ">")
+     text = text.replace("&lt;", "<")
+     text = text.replace("&amp;", "&")
+     return text
+
+########################################################### Custom Exceptions
+
+class PySourceColorError(Exception):
+    # Base for custom errors
+    def __init__(self, msg=''):
+        self._msg = msg
+        Exception.__init__(self, msg)
+    def __repr__(self):
+        return self._msg
+    __str__ = __repr__
+
+class PathError(PySourceColorError):
+    def __init__(self, msg):
+       PySourceColorError.__init__(self,
+         'Path error! : %s'% msg)
+
+class InputError(PySourceColorError):
+   def __init__(self, msg):
+       PySourceColorError.__init__(self,
+         'Input error! : %s'% msg)
+
+########################################################## Python code parser
+
+class Parser(object):
+
+    """MoinMoin python parser heavily chopped :)"""
+
+    def __init__(self, raw, colors=None, title='', out=sys.stdout,
+                   markup='html', header=None, footer=None, linenumbers=0):
+        """Store the source text & set some flags"""
+        if colors == None:
+            colors = defaultColors
+        self.raw = raw.expandtabs().rstrip()
+        self.title = os.path.basename(title)
+        self.out = out
+        self.line = ''
+        self.lasttext = ''
+        self.argFlag = 0
+        self.classFlag = 0
+        self.defFlag = 0
+        self.decoratorFlag = 0
+        self.external = 0
+        self.markup = markup.upper()
+        self.colors = colors
+        self.header = header
+        self.footer = footer
+        self.doArgs = 1 #  overrides the new tokens
+        self.doNames = 1 #  overrides the new tokens
+        self.doMathOps = 1 #  overrides the new tokens
+        self.doBrackets = 1 #  overrides the new tokens
+        self.doURL = 1 # override url conversion
+        self.LINENUMHOLDER = "___line___".upper()
+        self.LINESTART = "___start___".upper()
+        self.skip = 0
+        # add space left side of code for padding.Override in color dict.
+        self.extraspace = self.colors.get(EXTRASPACE, '')
+        # Linenumbers less then zero also have numberlinks
+        self.dolinenums = self.linenum = abs(linenumbers)
+        if linenumbers < 0:
+            self.numberlinks = 1
+        else:
+            self.numberlinks = 0
+
+    def format(self, form=None):
+        """Parse and send the colorized source"""
+        if form in ('snip','code'):
+            self.addEnds = 0
+        elif form == 'embed':
+            self.addEnds = 0
+            self.external = 1
+        else:
+            if form == 'external':
+                self.external = 1
+            self.addEnds = 1
+
+        # Store line offsets in self.lines
+        self.lines = [0, 0]
+        pos = 0
+
+        # Add linenumbers
+        if self.dolinenums:
+            start=self.LINENUMHOLDER+' '+self.extraspace
+        else:
+            start=''+self.extraspace
+        newlines = []
+        lines = self.raw.splitlines(0)
+        for l in lines:
+             # span and div escape for customizing and embedding raw text 
+             if (l.startswith('#$#')
+                  or l.startswith('#%#')
+                  or l.startswith('#@#')):   
+                newlines.append(l)
+             else:
+                # kludge for line spans in css,xhtml
+                if self.markup in ['XHTML','CSS']:
+                    newlines.append(self.LINESTART+' '+start+l)
+                else:
+                    newlines.append(start+l)
+        self.raw = "\n".join(newlines)+'\n'# plus an extra newline at the end
+
+        # Gather lines
+        while 1:
+            pos = self.raw.find('\n', pos) + 1
+            if not pos: break
+            self.lines.append(pos)
+        self.lines.append(len(self.raw))
+
+        # Wrap text in a filelike object
+        self.pos = 0
+        text = StringIO.StringIO(self.raw)
+        
+        # Markup start
+        if self.addEnds:
+            self._doPageStart()
+        else:
+            self._doSnippetStart()
+
+        ## Tokenize calls the __call__
+        ## function for each token till done.
+        # Parse the source and write out the results.
+        try:
+            tokenize.tokenize(text.readline, self)
+        except tokenize.TokenError, ex:
+            msg = ex[0]
+            line = ex[1][0]
+            self.out.write("<h3>ERROR: %s</h3>%s\n"%
+                            (msg, self.raw[self.lines[line]:]))
+            #traceback.print_exc()
+
+        # Markup end
+        if self.addEnds:
+            self._doPageEnd()
+        else:
+            self._doSnippetEnd()
+
+    def __call__(self, toktype, toktext, (srow,scol), (erow,ecol), line):
+        """Token handler. Order is important do not rearrange."""
+        self.line = line
+        # Calculate new positions
+        oldpos = self.pos
+        newpos = self.lines[srow] + scol
+        self.pos = newpos + len(toktext)
+        # Handle newlines
+        if toktype in (token.NEWLINE, tokenize.NL):
+            self.decoratorFlag = self.argFlag = 0
+            # kludge for line spans in css,xhtml
+            if self.markup in ['XHTML','CSS']:
+                self.out.write('</span>')
+            self.out.write('\n')
+            return
+
+        # Send the original whitespace, and tokenize backslashes if present.
+        # Tokenizer.py just sends continued line backslashes with whitespace.
+        # This is a hack to tokenize continued line slashes as operators.
+        # Should continued line backslashes be treated as operators
+        # or some other token?
+
+        if newpos > oldpos:
+            if self.raw[oldpos:newpos].isspace():
+                # consume a single space after linestarts and linenumbers
+                # had to have them so tokenizer could seperate them.
+                # multiline strings are handled by do_Text functions
+                if self.lasttext != self.LINESTART \
+                        and self.lasttext != self.LINENUMHOLDER:
+                    self.out.write(self.raw[oldpos:newpos])
+                else:
+                    self.out.write(self.raw[oldpos+1:newpos])
+            else:
+                slash = self.raw[oldpos:newpos].find('\\')+oldpos
+                self.out.write(self.raw[oldpos:slash])
+                getattr(self, '_send%sText'%(self.markup))(OPERATOR, '\\')
+                self.linenum+=1
+                # kludge for line spans in css,xhtml
+                if self.markup in ['XHTML','CSS']:
+                    self.out.write('</span>')
+                self.out.write(self.raw[slash+1:newpos])
+
+        # Skip indenting tokens
+        if toktype in (token.INDENT, token.DEDENT):
+            self.pos = newpos
+            return
+
+        # Look for operators
+        if token.LPAR <= toktype and toktype <= token.OP:
+            # Trap decorators py2.4 >
+            if toktext == '@':
+                toktype = DECORATOR
+                # Set a flag if this was the decorator start so
+                # the decorator name and arguments can be identified
+                self.decoratorFlag = self.argFlag = 1
+            else:
+                if self.doArgs:
+                    # Find the start for arguments
+                    if toktext == '(' and self.argFlag:
+                        self.argFlag = 2
+                    # Find the end for arguments
+                    elif toktext == ':':
+                        self.argFlag = 0
+                ## Seperate the diffrent operator types
+                # Brackets
+                if self.doBrackets and toktext in ['[',']','(',')','{','}']:
+                    toktype = BRACKETS
+                # Math operators 
+                elif self.doMathOps and toktext in ['*=','**=','-=','+=','|=',
+                                                      '%=','>>=','<<=','=','^=',
+                                                      '/=', '+','-','**','*','/','%']:
+                    toktype = MATH_OPERATOR
+                # Operator 
+                else:
+                    toktype = OPERATOR
+                    # example how flags should work.
+                    # def fun(arg=argvalue,arg2=argvalue2):
+                    # 0   1  2 A 1   N    2 A  1    N     0
+                    if toktext == "=" and self.argFlag == 2:
+                         self.argFlag = 1
+                    elif toktext == "," and self.argFlag == 1:
+                        self.argFlag = 2
+        # Look for keywords
+        elif toktype == NAME and keyword.iskeyword(toktext):
+            toktype = KEYWORD
+            # Set a flag if this was the class / def start so
+            # the class / def name and arguments can be identified
+            if toktext in ['class', 'def']:
+                if toktext =='class' and \
+                         not line[:line.find('class')].endswith('.'): 
+                    self.classFlag = self.argFlag = 1
+                elif toktext == 'def' and \
+                         not line[:line.find('def')].endswith('.'):
+                    self.defFlag = self.argFlag = 1
+                else:
+                    # must have used a keyword as a name i.e. self.class
+                    toktype = ERRORTOKEN 
+
+        # Look for class, def, decorator name
+        elif (self.classFlag or self.defFlag or self.decoratorFlag) \
+                and self.doNames:
+            if self.classFlag:
+                self.classFlag = 0
+                toktype = CLASS_NAME
+            elif self.defFlag:
+                self.defFlag = 0
+                toktype = DEF_NAME
+            elif self.decoratorFlag:
+                self.decoratorFlag = 0
+                toktype = DECORATOR_NAME
+
+        # Look for strings
+        # Order of evaluation is important do not change.
+        elif toktype == token.STRING:
+            text = toktext.lower()
+            # TRIPLE DOUBLE QUOTE's
+            if (text[:3] == '"""'):
+                toktype = TRIPLEDOUBLEQUOTE
+            elif (text[:4] == 'r"""'):
+                toktype = TRIPLEDOUBLEQUOTE_R
+            elif (text[:4] == 'u"""' or
+                   text[:5] == 'ur"""'):
+                toktype = TRIPLEDOUBLEQUOTE_U
+            # DOUBLE QUOTE's
+            elif (text[:1] == '"'):
+                toktype = DOUBLEQUOTE
+            elif (text[:2] == 'r"'):
+                toktype = DOUBLEQUOTE_R
+            elif (text[:2] == 'u"' or
+                   text[:3] == 'ur"'):
+                toktype = DOUBLEQUOTE_U
+            # TRIPLE SINGLE QUOTE's
+            elif (text[:3] == "'''"):
+                 toktype = TRIPLESINGLEQUOTE
+            elif (text[:4] == "r'''"):
+                toktype = TRIPLESINGLEQUOTE_R
+            elif (text[:4] == "u'''" or
+                   text[:5] == "ur'''"):
+                toktype = TRIPLESINGLEQUOTE_U
+            # SINGLE QUOTE's
+            elif (text[:1] == "'"):
+                toktype = SINGLEQUOTE
+            elif (text[:2] == "r'"):
+                toktype = SINGLEQUOTE_R
+            elif (text[:2] == "u'" or
+                   text[:3] == "ur'"):
+                toktype = SINGLEQUOTE_U
+
+            # test for invalid string declaration
+            if self.lasttext.lower() == 'ru':
+                toktype = ERRORTOKEN
+           
+        # Look for comments
+        elif toktype == COMMENT:
+            if toktext[:2] == "##":
+                toktype = DOUBLECOMMENT
+            elif toktext[:3] == '#$#':
+                toktype = TEXT
+                self.textFlag = 'SPAN'
+                toktext = toktext[3:]
+            elif toktext[:3] == '#%#':
+                toktype = TEXT
+                self.textFlag = 'DIV'
+                toktext = toktext[3:]
+            elif toktext[:3] == '#@#':
+                toktype = TEXT
+                self.textFlag = 'RAW'
+                toktext = toktext[3:]
+            if self.doURL:
+                # this is a 'fake helper function'
+                # url(URI,Alias_name) or url(URI)
+                url_pos = toktext.find('url(')
+                if url_pos != -1:
+                    before = toktext[:url_pos]
+                    url = toktext[url_pos+4:]
+                    splitpoint = url.find(',')
+                    endpoint = url.find(')')
+                    after = url[endpoint+1:]
+                    url = url[:endpoint]
+                    if splitpoint != -1:
+                        urlparts = url.split(',',1)
+                        toktext = '%s<a href="%s">%s</a>%s'%(
+                                   before,urlparts[0],urlparts[1].lstrip(),after) 
+                    else:
+                        toktext = '%s<a href="%s">%s</a>%s'%(before,url,url,after) 
+                        
+        # Seperate errors from decorators
+        elif toktype == ERRORTOKEN:
+            # Bug fix for < py2.4
+            # space between decorators
+            if self.argFlag and toktext.isspace():
+                #toktype = NAME
+                self.out.write(toktext)
+                return
+            # Bug fix for py2.2 linenumbers with decorators
+            elif toktext.isspace():
+                # What if we have a decorator after a >>> or ...
+                #p = line.find('@')
+                #if p >= 0 and not line[:p].isspace():
+                    #self.out.write(toktext)
+                    #return
+                if self.skip:
+                    self.skip=0
+                    return
+                else:           
+                    self.out.write(toktext)
+                    return
+            # trap decorators < py2.4
+            elif toktext == '@':
+                toktype = DECORATOR
+                # Set a flag if this was the decorator start so
+                # the decorator name and arguments can be identified
+                self.decoratorFlag = self.argFlag = 1
+
+        # Seperate args from names
+        elif (self.argFlag == 2 and
+              toktype == NAME and
+              toktext != 'None' and
+              self.doArgs):
+            toktype = ARGS
+
+        # Look for line numbers
+        # The conversion code for them is in the send_text functions.
+        if toktext in [self.LINENUMHOLDER,self.LINESTART]:
+            toktype = LINENUMBER
+            # if we don't have linenumbers set flag
+            # to skip the trailing space from linestart
+            if toktext == self.LINESTART and not self.dolinenums \
+                                or toktext == self.LINENUMHOLDER:
+                self.skip=1
+
+
+        # Skip blank token that made it thru
+        ## bugfix for the last empty tag.
+        if toktext == '':
+            return
+
+        # Last token text history
+        self.lasttext = toktext
+        
+        # escape all but the urls in the comments
+        if toktype in (DOUBLECOMMENT, COMMENT):
+            if toktext.find('<a href=') == -1:
+                toktext = escape(toktext)
+            else:
+                pass
+        elif toktype == TEXT:
+            pass
+        else:
+            toktext = escape(toktext)
+
+        # Send text for any markup
+        getattr(self, '_send%sText'%(self.markup))(toktype, toktext)
+        return
+
+    ################################################################# Helpers
+
+    def _doSnippetStart(self):
+        if self.markup == 'HTML':
+            # Start of html snippet
+            self.out.write('<pre>\n')
+        else:
+            # Start of css/xhtml snippet
+            self.out.write(self.colors.get(CODESTART,'<pre class="py">\n'))
+
+    def _doSnippetEnd(self):
+        # End of html snippet
+        self.out.write(self.colors.get(CODEEND,'</pre>\n'))
+
+    ######################################################## markup selectors
+
+    def _getFile(self, filepath): 
+        try:
+            _file = open(filepath,'r')
+            content = _file.read()
+            _file.close()
+        except:
+            traceback.print_exc()
+            content = ''
+        return content
+
+    def _doPageStart(self):
+        getattr(self, '_do%sStart'%(self.markup))()
+
+    def _doPageHeader(self):
+        if self.header != None:
+            if self.header.find('#$#') != -1 or \
+                self.header.find('#$#') != -1 or \
+                self.header.find('#%#') != -1:
+                self.out.write(self.header[3:])
+            else:
+                if self.header != '':
+                    self.header = self._getFile(self.header)
+                getattr(self, '_do%sHeader'%(self.markup))()
+
+    def _doPageFooter(self):
+        if self.footer != None:
+            if self.footer.find('#$#') != -1 or \
+                self.footer.find('#@#') != -1 or \
+                self.footer.find('#%#') != -1:
+                self.out.write(self.footer[3:])
+            else:
+                if self.footer != '':
+                    self.footer = self._getFile(self.footer)
+                getattr(self, '_do%sFooter'%(self.markup))()
+
+    def _doPageEnd(self):
+        getattr(self, '_do%sEnd'%(self.markup))()
+
+    ################################################### color/style retrieval
+    ## Some of these are not used anymore but are kept for documentation
+
+    def _getLineNumber(self):
+        num = self.linenum
+        self.linenum+=1
+        return  str(num).rjust(5)+" "
+
+    def _getTags(self, key):
+        # style tags
+        return self.colors.get(key, self.colors[NAME])[0]
+
+    def _getForeColor(self, key):
+        # get text foreground color, if not set to black
+        color = self.colors.get(key, self.colors[NAME])[1]
+        if color[:1] != '#':
+            color = '#000000'
+        return color
+
+    def _getBackColor(self, key):
+        # get text background color
+        return self.colors.get(key, self.colors[NAME])[2]
+
+    def _getPageColor(self):
+        # get page background color
+        return self.colors.get(PAGEBACKGROUND, '#FFFFFF')
+
+    def _getStyle(self, key):
+        # get the token style from the color dictionary
+        return self.colors.get(key, self.colors[NAME])
+
+    def _getMarkupClass(self, key):
+        # get the markup class name from the markup dictionary
+        return MARKUPDICT.get(key, MARKUPDICT[NAME])
+
+    def _getDocumentCreatedBy(self):
+        return '<!--This document created by %s ver.%s on: %s-->\n'%(
+                  __title__,__version__,time.ctime())
+
+    ################################################### HTML markup functions
+
+    def _doHTMLStart(self):
+        # Start of html page
+        self.out.write('<!DOCTYPE html PUBLIC \
+"-//W3C//DTD HTML 4.01//EN">\n')
+        self.out.write('<html><head><title>%s</title>\n'%(self.title))
+        self.out.write(self._getDocumentCreatedBy())
+        self.out.write('<meta http-equiv="Content-Type" \
+content="text/html;charset=iso-8859-1">\n')
+        # Get background
+        self.out.write('</head><body bgcolor="%s">\n'%self._getPageColor())
+        self._doPageHeader()
+        self.out.write('<pre>')
+
+    def _getHTMLStyles(self, toktype, toktext):
+        # Get styles
+        tags, color = self.colors.get(toktype, self.colors[NAME])[:2]#
+        tagstart=[]
+        tagend=[]
+        # check for styles and set them if needed.
+        if 'b' in tags:#Bold
+            tagstart.append('<b>')
+            tagend.append('</b>')
+        if 'i' in tags:#Italics
+            tagstart.append('<i>')
+            tagend.append('</i>')
+        if 'u' in tags:#Underline
+            tagstart.append('<u>')
+            tagend.append('</u>')
+        # HTML tags should be paired like so : <b><i><u>Doh!</u></i></b>
+        tagend.reverse()
+        starttags="".join(tagstart)
+        endtags="".join(tagend)
+        return starttags,endtags,color
+
+    def _sendHTMLText(self, toktype, toktext):
+        numberlinks = self.numberlinks
+        
+        # If it is an error, set a red box around the bad tokens
+        # older browsers should ignore it
+        if toktype == ERRORTOKEN:
+            style = ' style="border: solid 1.5pt #FF0000;"'
+        else:
+            style = ''
+        # Get styles
+        starttag, endtag, color = self._getHTMLStyles(toktype, toktext)
+        # This is a hack to 'fix' multi-line  strings.
+        # Multi-line strings are treated as only one token 
+        # even though they can be several physical lines.
+        # That makes it hard to spot the start of a line,
+        # because at this level all we know about are tokens.
+        
+        if toktext.count(self.LINENUMHOLDER):
+            # rip apart the string and separate it by line.
+            # count lines and change all linenum token to line numbers.
+            # embedded all the new font tags inside the current one.
+            # Do this by ending the tag first then writing our new tags,
+            # then starting another font tag exactly like the first one.
+            if toktype == LINENUMBER:
+                splittext = toktext.split(self.LINENUMHOLDER)
+            else:    
+                splittext = toktext.split(self.LINENUMHOLDER+' ')
+            store = []
+            store.append(splittext.pop(0))
+            lstarttag, lendtag, lcolor = self._getHTMLStyles(LINENUMBER, toktext)
+            count = len(splittext)
+            for item in splittext:
+                num =  self._getLineNumber()
+                if numberlinks:
+                    numstrip = num.strip()
+                    content = '<a name="%s" href="#%s">%s</a>' \
+                              %(numstrip,numstrip,num)
+                else:
+                    content = num
+                if count <= 1:
+                    endtag,starttag = '',''
+                linenumber = ''.join([endtag,'<font color=', lcolor, '>',
+                            lstarttag, content, lendtag, '</font>' ,starttag])
+                store.append(linenumber+item)
+            toktext = ''.join(store)
+        # send text
+        ## Output optimization
+        # skip font tag if black text, but styles will still be sent. (b,u,i)
+        if color !='#000000':
+            startfont = '<font color="%s"%s>'%(color, style)
+            endfont = '</font>'
+        else:
+            startfont, endfont = ('','')
+        if toktype != LINENUMBER:
+            self.out.write(''.join([startfont,starttag,
+                                     toktext,endtag,endfont]))
+        else:
+            self.out.write(toktext)
+        return
+
+    def _doHTMLHeader(self):
+        # Optional
+        if self.header != '':
+            self.out.write('%s\n'%self.header)
+        else:
+            color = self._getForeColor(NAME)
+            self.out.write('<b><font color="%s"># %s \
+                            <br># %s</font></b><hr>\n'%
+                           (color, self.title, time.ctime()))
+
+    def _doHTMLFooter(self):
+        # Optional
+        if self.footer != '':
+            self.out.write('%s\n'%self.footer)
+        else:
+            color = self._getForeColor(NAME)
+            self.out.write('<b><font color="%s"> \
+                            <hr># %s<br># %s</font></b>\n'%
+                           (color, self.title, time.ctime()))
+
+    def _doHTMLEnd(self):
+        # End of html page
+        self.out.write('</pre>\n')
+        # Write a little info at the bottom
+        self._doPageFooter()
+        self.out.write('</body></html>\n')
+
+    #################################################### CSS markup functions
+
+    def _getCSSStyle(self, key):
+        # Get the tags and colors from the dictionary
+        tags, forecolor, backcolor = self._getStyle(key)
+        style=[]
+        border = None
+        bordercolor = None
+        tags = tags.lower()
+        if tags:
+            # get the border color if specified
+            # the border color will be appended to
+            # the list after we define a border
+            if '#' in tags:# border color 
+                start = tags.find('#')
+                end = start + 7
+                bordercolor = tags[start:end]
+                tags.replace(bordercolor,'',1)
+            # text styles
+            if 'b' in tags:# Bold
+                style.append('font-weight:bold;')
+            else:
+                style.append('font-weight:normal;')    
+            if 'i' in tags:# Italic
+                style.append('font-style:italic;')
+            if 'u' in tags:# Underline
+                style.append('text-decoration:underline;')
+            # border size
+            if 'l' in tags:# thick border
+                size='thick'
+            elif 'm' in tags:# medium border
+                size='medium'
+            elif 't' in tags:# thin border
+                size='thin'
+            else:# default
+                size='medium'
+            # border styles
+            if 'n' in tags:# inset border
+                border='inset'
+            elif 'o' in tags:# outset border
+                border='outset'
+            elif 'r' in tags:# ridge border
+                border='ridge'
+            elif 'g' in tags:# groove border
+                border='groove'
+            elif '=' in tags:# double border
+                border='double'
+            elif '.' in tags:# dotted border
+                border='dotted'
+            elif '-' in tags:# dashed border
+                border='dashed'
+            elif 's' in tags:# solid border 
+                border='solid'
+            # border type check
+            seperate_sides=0
+            for side in ['<','>','^','v']:
+                if side in tags:
+                    seperate_sides+=1
+            # border box or seperate sides
+            if seperate_sides==0 and border:
+                    style.append('border: %s %s;'%(border,size))
+            else:
+                if border == None:
+                   border = 'solid'
+                if 'v' in tags:# bottom border
+                    style.append('border-bottom:%s %s;'%(border,size))
+                if '<' in tags:# left border
+                    style.append('border-left:%s %s;'%(border,size))
+                if '>' in tags:# right border
+                    style.append('border-right:%s %s;'%(border,size))
+                if '^' in tags:# top border
+                    style.append('border-top:%s %s;'%(border,size))
+        else:
+            style.append('font-weight:normal;')# css inherited style fix    
+        # we have to define our borders before we set colors
+        if bordercolor:
+            style.append('border-color:%s;'%bordercolor)
+        # text forecolor  
+        style.append('color:%s;'% forecolor)
+        # text backcolor
+        if backcolor:
+            style.append('background-color:%s;'%backcolor)
+        return (self._getMarkupClass(key),' '.join(style))
+
+    def _sendCSSStyle(self, external=0):
+        """ create external and internal style sheets"""
+        styles = []
+        external += self.external
+        if not external:
+            styles.append('<style type="text/css">\n<!--\n')
+        # Get page background color and write styles ignore any we don't know
+        styles.append('body { background:%s; }\n'%self._getPageColor())
+        # write out the various css styles
+        for key in MARKUPDICT:
+            styles.append('.%s { %s }\n'%self._getCSSStyle(key))
+        # If you want to style the pre tag you must modify the color dict.
+        #  Example: 
+        #  lite[PY] = .py {border: solid thin #000000;background:#555555}\n''' 
+        styles.append(self.colors.get(PY, '.py { }\n'))
+        # Extra css can be added here
+        # add CSSHOOK to the color dict if you need it.
+        # Example: 
+        #lite[CSSHOOK] = """.mytag { border: solid thin #000000; } \n
+        #                   .myothertag { font-weight:bold; )\n"""
+        styles.append(self.colors.get(CSSHOOK,''))
+        if not self.external:
+             styles.append('--></style>\n')
+        return ''.join(styles)
+
+    def _doCSSStart(self):
+        # Start of css/html 4.01 page
+        self.out.write('<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">\n')
+        self.out.write('<html><head><title>%s</title>\n'%(self.title))
+        self.out.write(self._getDocumentCreatedBy())
+        self.out.write('<meta http-equiv="Content-Type" \
+content="text/html;charset=iso-8859-1">\n')
+        self._doCSSStyleSheet()
+        self.out.write('</head>\n<body>\n')
+        # Write a little info at the top.
+        self._doPageHeader()
+        self.out.write(self.colors.get(CODESTART,'<pre class="py">\n'))
+        return
+
+    def _doCSSStyleSheet(self):
+        if not self.external:
+            # write an embedded style sheet
+            self.out.write(self._sendCSSStyle())
+        else:
+            # write a link to an external style sheet
+            self.out.write('<link rel="stylesheet" \
+href="pystyle.css" type="text/css">')
+        return
+
+    def _sendCSSText(self, toktype, toktext):
+        # This is a hack to 'fix' multi-line strings.
+        # Multi-line strings are treated as only one token 
+        # even though they can be several physical lines.
+        # That makes it hard to spot the start of a line,
+        # because at this level all we know about are tokens.
+        markupclass = MARKUPDICT.get(toktype, MARKUPDICT[NAME])
+        # if it is a LINENUMBER type then we can skip the rest
+        if toktext == self.LINESTART and toktype == LINENUMBER:
+            self.out.write('<span class="py_line">')
+            return
+        if toktext.count(self.LINENUMHOLDER):
+            # rip apart the string and separate it by line
+            # count lines and change all linenum token to line numbers
+            # also convert linestart and lineend tokens
+            # <linestart> <lnumstart> lnum <lnumend> text <lineend>
+            #################################################
+            newmarkup = MARKUPDICT.get(LINENUMBER, MARKUPDICT[NAME])
+            lstartspan = '<span class="%s">'%(newmarkup)
+            if toktype == LINENUMBER:
+                splittext = toktext.split(self.LINENUMHOLDER)
+            else:    
+                splittext = toktext.split(self.LINENUMHOLDER+' ')
+            store = []
+            # we have already seen the first linenumber token
+            # so we can skip the first one
+            store.append(splittext.pop(0))
+            for item in splittext:
+                num = self._getLineNumber()
+                if self.numberlinks:
+                    numstrip = num.strip()
+                    content= '<a name="%s" href="#%s">%s</a>' \
+                              %(numstrip,numstrip,num)
+                else:
+                    content = num
+                linenumber= ''.join([lstartspan,content,'</span>'])
+                store.append(linenumber+item)
+            toktext = ''.join(store)
+        if toktext.count(self.LINESTART):
+            # wraps the textline in a line span
+            # this adds a lot of kludges, is it really worth it?
+            store = []
+            parts = toktext.split(self.LINESTART+' ')
+            # handle the first part differently
+            # the whole token gets wraqpped in a span later on
+            first = parts.pop(0)
+            # place spans before the newline
+            pos = first.rfind('\n')
+            if pos != -1:
+                first=first[:pos]+'</span></span>'+first[pos:]
+            store.append(first)
+            #process the rest of the string
+            for item in parts:
+                #handle line numbers if present
+                if self.dolinenums:
+                    item = item.replace('</span>',
+                           '</span><span class="%s">'%(markupclass))
+                else:
+                    item = '<span class="%s">%s'%(markupclass,item)
+                # add endings for line and string tokens
+                pos = item.rfind('\n')
+                if pos != -1:
+                    item=item[:pos]+'</span></span>\n'
+                store.append(item)
+            # add start tags for lines
+            toktext = '<span class="py_line">'.join(store)
+        # Send text
+        if toktype != LINENUMBER:
+            if toktype == TEXT and self.textFlag == 'DIV':
+                startspan = '<div class="%s">'%(markupclass)
+                endspan = '</div>'
+            elif toktype == TEXT and self.textFlag == 'RAW': 
+                startspan,endspan = ('','')
+            else:
+                startspan = '<span class="%s">'%(markupclass)
+                endspan = '</span>'
+            self.out.write(''.join([startspan, toktext, endspan]))
+        else:
+            self.out.write(toktext)
+        return
+
+    def _doCSSHeader(self):
+        if self.header != '':
+            self.out.write('%s\n'%self.header)
+        else:
+            name = MARKUPDICT.get(NAME)
+            self.out.write('<div class="%s"># %s <br> \
+# %s</div><hr>\n'%(name, self.title, time.ctime()))
+
+    def _doCSSFooter(self):
+        # Optional
+        if self.footer != '':
+            self.out.write('%s\n'%self.footer)
+        else:
+            self.out.write('<hr><div class="%s"># %s <br> \
+# %s</div>\n'%(MARKUPDICT.get(NAME),self.title, time.ctime()))
+
+    def _doCSSEnd(self):
+        # End of css/html page
+        self.out.write(self.colors.get(CODEEND,'</pre>\n'))
+        # Write a little info at the bottom
+        self._doPageFooter()
+        self.out.write('</body></html>\n')
+        return
+
+    ################################################## XHTML markup functions
+
+    def _doXHTMLStart(self):
+        # XHTML is really just XML + HTML 4.01.
+        # We only need to change the page headers, 
+        # and a few tags to get valid XHTML.
+        # Start of xhtml page
+        self.out.write('<?xml version="1.0"?>\n \
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"\n \
+    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n \
+<html xmlns="http://www.w3.org/1999/xhtml">\n')
+        self.out.write('<head><title>%s</title>\n'%(self.title))
+        self.out.write(self._getDocumentCreatedBy())
+        self.out.write('<meta http-equiv="Content-Type" \
+content="text/html;charset=iso-8859-1"/>\n')
+        self._doXHTMLStyleSheet()
+        self.out.write('</head>\n<body>\n')
+        # Write a little info at the top.
+        self._doPageHeader()
+        self.out.write(self.colors.get(CODESTART,'<pre class="py">\n'))
+        return
+
+    def _doXHTMLStyleSheet(self):
+        if not self.external:
+            # write an embedded style sheet
+            self.out.write(self._sendCSSStyle())
+        else:
+            # write a link to an external style sheet
+            self.out.write('<link rel="stylesheet" \
+href="pystyle.css" type="text/css"/>\n')
+        return
+
+    def _sendXHTMLText(self, toktype, toktext):
+        self._sendCSSText(toktype, toktext)
+
+    def _doXHTMLHeader(self):
+        # Optional
+        if self.header:
+            self.out.write('%s\n'%self.header)
+        else:
+            name = MARKUPDICT.get(NAME)
+            self.out.write('<div class="%s"># %s <br/> \
+# %s</div><hr/>\n '%(
+            name, self.title, time.ctime()))
+
+    def _doXHTMLFooter(self):
+        # Optional
+        if self.footer:
+            self.out.write('%s\n'%self.footer)
+        else:
+            self.out.write('<hr/><div class="%s"># %s <br/> \
+# %s</div>\n'%(MARKUPDICT.get(NAME), self.title, time.ctime()))
+
+    def _doXHTMLEnd(self):
+        self._doCSSEnd()
+
+#############################################################################
+
+if __name__ == '__main__':
+    cli()
+
+#############################################################################
+# PySourceColor.py
+# 2004, 2005 M.E.Farmer Jr.
+# Python license

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/UserDict24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/UserDict24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/UserDict24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,167 @@
+"""A more or less complete user-defined wrapper around dictionary objects."""
+
+class UserDict:
+    def __init__(self, dict=None, **kwargs):
+        self.data = {}
+        if dict is not None:
+            if not hasattr(dict,'keys'):
+                dict = type({})(dict)   # make mapping from a sequence
+            self.update(dict)
+        if len(kwargs):
+            self.update(kwargs)
+    def __repr__(self): return repr(self.data)
+    def __cmp__(self, dict):
+        if isinstance(dict, UserDict):
+            return cmp(self.data, dict.data)
+        else:
+            return cmp(self.data, dict)
+    def __len__(self): return len(self.data)
+    def __getitem__(self, key): return self.data[key]
+    def __setitem__(self, key, item): self.data[key] = item
+    def __delitem__(self, key): del self.data[key]
+    def clear(self): self.data.clear()
+    def copy(self):
+        if self.__class__ is UserDict:
+            return UserDict(self.data)
+        import copy
+        data = self.data
+        try:
+            self.data = {}
+            c = copy.copy(self)
+        finally:
+            self.data = data
+        c.update(self)
+        return c
+    def keys(self): return self.data.keys()
+    def items(self): return self.data.items()
+    def iteritems(self): return self.data.iteritems()
+    def iterkeys(self): return self.data.iterkeys()
+    def itervalues(self): return self.data.itervalues()
+    def values(self): return self.data.values()
+    def has_key(self, key): return self.data.has_key(key)
+    def update(self, dict):
+        if isinstance(dict, UserDict):
+            self.data.update(dict.data)
+        elif isinstance(dict, type(self.data)):
+            self.data.update(dict)
+        else:
+            for k, v in dict.items():
+                self[k] = v
+    def get(self, key, failobj=None):
+        if not self.has_key(key):
+            return failobj
+        return self[key]
+    def setdefault(self, key, failobj=None):
+        if not self.has_key(key):
+            self[key] = failobj
+        return self[key]
+    def pop(self, key, *args):
+        return self.data.pop(key, *args)
+    def popitem(self):
+        return self.data.popitem()
+    def __contains__(self, key):
+        return key in self.data
+    def fromkeys(cls, iterable, value=None):
+        d = cls()
+        for key in iterable:
+            d[key] = value
+        return d
+    fromkeys = classmethod(fromkeys)
+
+class IterableUserDict(UserDict):
+    def __iter__(self):
+        return iter(self.data)
+
+class DictMixin:
+    # Mixin defining all dictionary methods for classes that already have
+    # a minimum dictionary interface including getitem, setitem, delitem,
+    # and keys. Without knowledge of the subclass constructor, the mixin
+    # does not define __init__() or copy().  In addition to the four base
+    # methods, progressively more efficiency comes with defining
+    # __contains__(), __iter__(), and iteritems().
+
+    # second level definitions support higher levels
+    def __iter__(self):
+        for k in self.keys():
+            yield k
+    def has_key(self, key):
+        try:
+            value = self[key]
+        except KeyError:
+            return False
+        return True
+    def __contains__(self, key):
+        return self.has_key(key)
+
+    # third level takes advantage of second level definitions
+    def iteritems(self):
+        for k in self:
+            yield (k, self[k])
+    def iterkeys(self):
+        return self.__iter__()
+
+    # fourth level uses definitions from lower levels
+    def itervalues(self):
+        for _, v in self.iteritems():
+            yield v
+    def values(self):
+        return [v for _, v in self.iteritems()]
+    def items(self):
+        return list(self.iteritems())
+    def clear(self):
+        for key in self.keys():
+            del self[key]
+    def setdefault(self, key, default):
+        try:
+            return self[key]
+        except KeyError:
+            self[key] = default
+        return default
+    def pop(self, key, *args):
+        if len(args) > 1:
+            raise TypeError, "pop expected at most 2 arguments, got "\
+                              + repr(1 + len(args))
+        try:
+            value = self[key]
+        except KeyError:
+            if args:
+                return args[0]
+            raise
+        del self[key]
+        return value
+    def popitem(self):
+        try:
+            k, v = self.iteritems().next()
+        except StopIteration:
+            raise KeyError, 'container is empty'
+        del self[k]
+        return (k, v)
+    def update(self, other):
+        # Make progressively weaker assumptions about "other"
+        if hasattr(other, 'iteritems'):  # iteritems saves memory and lookups
+            for k, v in other.iteritems():
+                self[k] = v
+        elif hasattr(other, '__iter__'): # iter saves memory
+            for k in other:
+                self[k] = other[k]
+        else:
+            for k in other.keys():
+                self[k] = other[k]
+    def get(self, key, default=None):
+        try:
+            return self[key]
+        except KeyError:
+            return default
+    def __repr__(self):
+        return repr(dict(self.iteritems()))
+    def __cmp__(self, other):
+        if other is None:
+            return 1
+        if isinstance(other, DictMixin):
+            other = dict(other.iteritems())
+        return cmp(dict(self.iteritems()), other)
+    def __len__(self):
+        return len(self.keys())
+    
+    def __nonzero__(self):
+        return bool(self.iteritems())

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+"""
+Package for miscellaneous routines that do not depend on other parts
+of Paste
+"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinit.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinit.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinit.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,42 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+class ClassInitMeta(type):
+
+    def __new__(meta, class_name, bases, new_attrs):
+        cls = type.__new__(meta, class_name, bases, new_attrs)
+        if (new_attrs.has_key('__classinit__')
+            and not isinstance(cls.__classinit__, staticmethod)):
+            setattr(cls, '__classinit__',
+                    staticmethod(cls.__classinit__.im_func))
+        if hasattr(cls, '__classinit__'):
+            cls.__classinit__(cls, new_attrs)
+        return cls
+
+def build_properties(cls, new_attrs):
+    """
+    Given a class and a new set of attributes (as passed in by
+    __classinit__), create or modify properties based on functions
+    with special names ending in __get, __set, and __del.
+    """
+    for name, value in new_attrs.items():
+        if (name.endswith('__get') or name.endswith('__set')
+            or name.endswith('__del')):
+            base = name[:-5]
+            if hasattr(cls, base):
+                old_prop = getattr(cls, base)
+                if not isinstance(old_prop, property):
+                    raise ValueError(
+                        "Attribute %s is a %s, not a property; function %s is named like a property"
+                        % (base, type(old_prop), name))
+                attrs = {'fget': old_prop.fget,
+                         'fset': old_prop.fset,
+                         'fdel': old_prop.fdel,
+                         'doc': old_prop.__doc__}
+            else:
+                attrs = {}
+            attrs['f' + name[-3:]] = value
+            if name.endswith('__get') and value.__doc__:
+                attrs['doc'] = value.__doc__
+            new_prop = property(**attrs)
+            setattr(cls, base, new_prop)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinstance.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinstance.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/classinstance.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,38 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+class classinstancemethod(object):
+    """
+    Acts like a class method when called from a class, like an
+    instance method when called by an instance.  The method should
+    take two arguments, 'self' and 'cls'; one of these will be None
+    depending on how the method was called.
+    """
+
+    def __init__(self, func):
+        self.func = func
+        self.__doc__ = func.__doc__
+
+    def __get__(self, obj, type=None):
+        return _methodwrapper(self.func, obj=obj, type=type)
+
+class _methodwrapper(object):
+
+    def __init__(self, func, obj, type):
+        self.func = func
+        self.obj = obj
+        self.type = type
+
+    def __call__(self, *args, **kw):
+        assert not kw.has_key('self') and not kw.has_key('cls'), (
+            "You cannot use 'self' or 'cls' arguments to a "
+            "classinstancemethod")
+        return self.func(*((self.obj, self.type) + args), **kw)
+
+    def __repr__(self):
+        if self.obj is None:
+            return ('<bound class method %s.%s>'
+                    % (self.type.__name__, self.func.func_name))
+        else:
+            return ('<bound method %s.%s of %r>'
+                    % (self.type.__name__, self.func.func_name, self.obj))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/converters.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/converters.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/converters.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,26 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+def asbool(obj):
+    if isinstance(obj, (str, unicode)):
+        obj = obj.strip().lower()
+        if obj in ['true', 'yes', 'on', 'y', 't', '1']:
+            return True
+        elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
+            return False
+        else:
+            raise ValueError(
+                "String is not true/false: %r" % obj)
+    return bool(obj)
+
+def aslist(obj, sep=None, strip=True):
+    if isinstance(obj, (str, unicode)):
+        lst = obj.split(sep)
+        if strip:
+            lst = [v.strip() for v in lst]
+        return lst
+    elif isinstance(obj, (list, tuple)):
+        return obj
+    elif obj is None:
+        return []
+    else:
+        return [obj]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/dateinterval.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/dateinterval.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/dateinterval.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,103 @@
+"""
+DateInterval.py
+
+Convert interval strings (in the form of 1w2d, etc) to
+seconds, and back again.  Is not exactly about months or
+years (leap years in particular).
+
+Accepts (y)ear, (b)month, (w)eek, (d)ay, (h)our, (m)inute, (s)econd.
+
+Exports only timeEncode and timeDecode functions.  
+"""
+
+import re
+
+__all__ = ['interval_decode', 'interval_encode']
+
+second = 1
+minute = second*60
+hour = minute*60
+day = hour*24
+week = day*7
+month = day*30
+year = day*365
+timeValues = {
+    'y': year,
+    'b': month,
+    'w': week,
+    'd': day,
+    'h': hour,
+    'm': minute,
+    's': second,
+    }
+timeOrdered = timeValues.items()
+timeOrdered.sort(lambda a, b: -cmp(a[1], b[1]))
+    
+def interval_encode(seconds, include_sign=False):
+    """Encodes a number of seconds (representing a time interval)
+    into a form like 1h2d3s.
+
+    >>> interval_encode(10)
+    '10s'
+    >>> interval_encode(493939)
+    '5d17h12m19s'
+    """
+    s = ''
+    orig = seconds
+    seconds = abs(seconds)
+    for char, amount in timeOrdered:
+        if seconds >= amount:
+            i, seconds = divmod(seconds, amount)
+            s += '%i%s' % (i, char)
+    if orig < 0:
+        s = '-' + s
+    elif not orig:
+        return '0'
+    elif include_sign:
+        s = '+' + s
+    return s
+
+_timeRE = re.compile(r'[0-9]+[a-zA-Z]')
+def interval_decode(s):
+    """Decodes a number in the format 1h4d3m (1 hour, 3 days, 3 minutes)
+    into a number of seconds
+
+    >>> interval_decode('40s')
+    40
+    >>> interval_decode('10000s')
+    10000
+    >>> interval_decode('3d1w45s')
+    864045
+    """
+    time = 0
+    sign = 1
+    s = s.strip()
+    if s.startswith('-'):
+        s = s[1:]
+        sign = -1
+    elif s.startswith('+'):
+        s = s[1:]
+    for match in allMatches(s, _timeRE):
+        char = match.group(0)[-1].lower()
+        if not timeValues.has_key(char):
+            # @@: should signal error
+            continue
+        time += int(match.group(0)[:-1]) * timeValues[char]
+    return time
+
+# @@-sgd 2002-12-23 - this function does not belong in this module, find a better place.
+def allMatches(source, regex):
+    """Return a list of matches for regex in source
+    """
+    pos = 0
+    end = len(source)
+    rv = []
+    match = regex.search(source, pos)
+    while match:
+        rv.append(match)
+        match = regex.search(source, match.end() )
+    return rv
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/datetimeutil.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/datetimeutil.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/datetimeutil.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,361 @@
+# (c) 2005 Clark C. Evans and contributors
+# This module is part of the Python Paste Project and is released under
+# the MIT License: http://www.opensource.org/licenses/mit-license.php
+# Some of this code was funded by: http://prometheusresearch.com
+"""
+Date, Time, and Timespan Parsing Utilities
+
+This module contains parsing support to create "human friendly"
+``datetime`` object parsing.  The explicit goal of these routines is
+to provide a multi-format date/time support not unlike that found in
+Microsoft Excel.  In most approaches, the input is very "strict" to
+prevent errors -- however, this approach is much more liberal since we
+are assuming the user-interface is parroting back the normalized value
+and thus the user has immediate feedback if the data is not typed in
+correctly.
+
+  ``parse_date`` and ``normalize_date``
+
+     These functions take a value like '9 jan 2007' and returns either an
+     ``date`` object, or an ISO 8601 formatted date value such
+     as '2007-01-09'.  There is an option to provide an Oracle database
+     style output as well, ``09 JAN 2007``, but this is not the default.
+
+     This module always treats '/' delimiters as using US date order
+     (since the author's clients are US based), hence '1/9/2007' is
+     January 9th.  Since this module treats the '-' as following
+     European order this supports both modes of data-entry; together
+     with immediate parroting back the result to the screen, the author
+     has found this approach to work well in pratice.
+
+  ``parse_time`` and ``normalize_time``
+
+     These functions take a value like '1 pm' and returns either an
+     ``time`` object, or an ISO 8601 formatted 24h clock time
+     such as '13:00'.  There is an option to provide for US style time
+     values, '1:00 PM', however this is not the default.
+
+  ``parse_datetime`` and ``normalize_datetime``
+
+     These functions take a value like '9 jan 2007 at 1 pm' and returns
+     either an ``datetime`` object, or an ISO 8601 formatted
+     return (without the T) such as '2007-01-09 13:00'. There is an
+     option to provide for Oracle / US style, '09 JAN 2007 @ 1:00 PM',
+     however this is not the default.
+
+  ``parse_delta`` and ``normalize_delta``
+
+     These functions take a value like '1h 15m' and returns either an
+     ``timedelta`` object, or an 2-decimal fixed-point
+     numerical value in hours, such as '1.25'.  The rationale is to
+     support meeting or time-billing lengths, not to be an accurate
+     representation in mili-seconds.  As such not all valid
+     ``timedelta`` values will have a normalized representation.
+
+"""
+from datetime import timedelta, time, date
+from time import localtime
+import string
+
+__all__ = ['parse_timedelta', 'normalize_timedelta',
+           'parse_time', 'normalize_time',
+           'parse_date', 'normalize_date']
+
+def _number(val):
+    try:
+        return string.atoi(val)
+    except:
+        return None
+
+#
+# timedelta
+#
+def parse_timedelta(val):
+    """
+    returns a ``timedelta`` object, or None
+    """
+    if not val:
+        return None
+    val = string.lower(val)
+    if "." in val:
+        val = float(val)
+        return timedelta(hours=int(val), minutes=60*(val % 1.0))
+    fHour = ("h" in val or ":" in val)
+    fMin  = ("m" in val or ":" in val)
+    fFraction = "." in val
+    for noise in "minu:teshour()":
+        val = string.replace(val, noise, ' ')
+    val = string.strip(val)
+    val = string.split(val)
+    hr = 0.0
+    mi = 0
+    val.reverse()
+    if fHour:
+        hr = int(val.pop())
+    if fMin:
+        mi = int(val.pop())
+    if len(val) > 0 and not hr:
+        hr = int(val.pop())
+    return timedelta(hours=hr, minutes=mi)
+
+def normalize_timedelta(val):
+    """
+    produces a normalized string value of the timedelta
+
+    This module returns a normalized time span value consisting of the
+    number of hours in fractional form. For example '1h 15min' is
+    formatted as 01.25.
+    """
+    if type(val) == str:
+        val = parse_timedelta(val)
+    if not val:
+        return ''
+    hr = val.seconds/3600
+    mn = (val.seconds % 3600)/60
+    return "%d.%02d" % (hr, mn * 100/60)
+
+#
+# time
+#
+def parse_time(val):
+    if not val:
+        return None
+    hr = mi = 0
+    val = string.lower(val)
+    amflag = (-1 != string.find(val, 'a'))  # set if AM is found
+    pmflag = (-1 != string.find(val, 'p'))  # set if PM is found
+    for noise in ":amp.":
+        val = string.replace(val, noise, ' ')
+    val = string.split(val)
+    if len(val) > 1:
+        hr = int(val[0])
+        mi = int(val[1])
+    else:
+        val = val[0]
+        if len(val) < 1:
+            pass
+        elif 'now' == val:
+            tm = localtime()
+            hr = tm[3]
+            mi = tm[4]
+        elif 'noon' == val:
+            hr = 12
+        elif len(val) < 3:
+            hr = int(val)
+            if not amflag and not pmflag and hr < 7:
+                hr += 12
+        elif len(val) < 5:
+            hr = int(val[:-2])
+            mi = int(val[-2:])
+        else:
+            hr = int(val[:1])
+    if amflag and hr >= 12:
+        hr = hr - 12
+    if pmflag and hr < 12:
+        hr = hr + 12
+    return time(hr, mi)
+
+def normalize_time(value, ampm):
+    if not value:
+        return ''
+    if type(value) == str:
+        value = parse_time(value)
+    if not ampm:
+        return "%02d:%02d" % (value.hour, value.minute)
+    hr = value.hour
+    am = "AM"
+    if hr < 1 or hr > 23:
+        hr = 12
+    elif hr >= 12:
+        am = "PM"
+        if hr > 12:
+            hr = hr - 12
+    return "%02d:%02d %s" % (hr, value.minute, am)
+
+#
+# Date Processing
+#
+
+_one_day = timedelta(days=1)
+
+_str2num = {'jan':1, 'feb':2, 'mar':3, 'apr':4,  'may':5, 'jun':6,
+            'jul':7, 'aug':8, 'sep':9, 'oct':10, 'nov':11, 'dec':12 }
+
+def _month(val):
+    for (key, mon) in _str2num.items():
+        if key in val:
+            return mon
+    raise TypeError("unknown month '%s'" % val)
+
+_days_in_month = {1: 31, 2: 28, 3: 31, 4: 30, 5: 31, 6: 30,
+                  7: 31, 8: 31, 9: 30, 10: 31, 11: 30, 12: 31,
+                  }
+_num2str = {1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun',
+            7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec',
+            }
+_wkdy = ("mon", "tue", "wed", "thu", "fri", "sat", "sun")
+
+def parse_date(val):
+    if not(val):
+        return None
+    val = string.lower(val)
+    now = None
+
+    # optimized check for YYYY-MM-DD
+    strict = val.split("-")
+    if len(strict) == 3:
+        (y, m, d) = strict
+        if "+" in d:
+            d = d.split("+")[0]
+        if " " in d:
+            d = d.split(" ")[0]
+        try:
+            now = date(int(y), int(m), int(d))
+            val = "xxx" + val[10:]
+        except ValueError:
+            pass
+
+    # allow for 'now', 'mon', 'tue', etc.
+    if not now:
+        chk = val[:3]
+        if chk in ('now','tod'):
+            now = date.today()
+        elif chk in _wkdy:
+            now = date.today()
+            idx = list(_wkdy).index(chk) + 1
+            while now.isoweekday() != idx:
+                now += _one_day
+
+    # allow dates to be modified via + or - /w number of days, so
+    # that now+3 is three days from now
+    if now:
+        tail = val[3:].strip()
+        tail = tail.replace("+"," +").replace("-"," -")
+        for item in tail.split():
+            try:
+                days = int(item)
+            except ValueError:
+                pass
+            else:
+                now += timedelta(days=days)
+        return now
+
+    # ok, standard parsing
+    yr = mo = dy = None
+    for noise in ('/', '-', ',', '*'):
+        val = string.replace(val, noise, ' ')
+    for noise in _wkdy:
+        val = string.replace(val, noise, ' ')
+    out = []
+    last = False
+    ldig = False
+    for ch in val:
+        if ch.isdigit():
+            if last and not ldig:
+               out.append(' ')
+            last = ldig = True
+        else:
+            if ldig:
+                out.append(' ')
+                ldig = False
+            last = True
+        out.append(ch)
+    val = string.split("".join(out))
+    if 3 == len(val):
+        a = _number(val[0])
+        b = _number(val[1])
+        c = _number(val[2])
+        if len(val[0]) == 4:
+            yr = a
+            if b:  # 1999 6 23
+                mo = b
+                dy = c
+            else:  # 1999 Jun 23
+                mo = _month(val[1])
+                dy = c
+        elif a > 0:
+            yr = c
+            if len(val[2]) < 4:
+                raise TypeError("four digit year required")
+            if b: # 6 23 1999
+                dy = b
+                mo = a
+            else: # 23 Jun 1999
+                dy = a
+                mo = _month(val[1])
+        else: # Jun 23, 2000
+            dy = b
+            yr = c
+            if len(val[2]) < 4:
+                raise TypeError("four digit year required")
+            mo = _month(val[0])
+    elif 2 == len(val):
+        a = _number(val[0])
+        b = _number(val[1])
+        if a > 999:
+            yr = a
+            dy = 1
+            if b > 0: # 1999 6
+                mo = b
+            else: # 1999 Jun
+                mo = _month(val[1])
+        elif a > 0:
+            if b > 999: # 6 1999
+                mo = a
+                yr = b
+                dy = 1
+            elif b > 0: # 6 23
+                mo = a
+                dy = b
+            else: # 23 Jun
+                dy = a
+                mo = _month(val[1])
+        else:
+            if b > 999: # Jun 2001
+                yr = b
+                dy = 1
+            else:  # Jun 23
+                dy = b
+            mo = _month(val[0])
+    elif 1 == len(val):
+        val = val[0]
+        if not val.isdigit():
+            mo = _month(val)
+            if mo is not None:
+                dy = 1
+        else:
+            v = _number(val)
+            val = str(v)
+            if 8 == len(val): # 20010623
+                yr = _number(val[:4])
+                mo = _number(val[4:6])
+                dy = _number(val[6:])
+            elif len(val) in (3,4):
+                if v > 1300: # 2004
+                    yr = v
+                    mo = 1
+                    dy = 1
+                else:        # 1202
+                    mo = _number(val[:-2])
+                    dy = _number(val[-2:])
+            elif v < 32:
+                dy = v
+            else:
+                raise TypeError("four digit year required")
+    tm = localtime()
+    if mo is None:
+        mo = tm[1]
+    if dy is None:
+        dy = tm[2]
+    if yr is None:
+        yr = tm[0]
+    return date(yr, mo, dy)
+
+def normalize_date(val, iso8601=True):
+    if not val:
+        return ''
+    if type(val) == str:
+        val = parse_date(val)
+    if iso8601:
+        return "%4d-%02d-%02d" % (val.year, val.month, val.day)
+    return "%02d %s %4d" % (val.day, _num2str[val.month], val.year)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/doctest24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/doctest24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/doctest24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2665 @@
+# Module doctest.
+# Released to the public domain 16-Jan-2001, by Tim Peters (tim at python.org).
+# Major enhancements and refactoring by:
+#     Jim Fulton
+#     Edward Loper
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+r"""Module doctest -- a framework for running examples in docstrings.
+
+In simplest use, end each module M to be tested with:
+
+def _test():
+    import doctest
+    doctest.testmod()
+
+if __name__ == "__main__":
+    _test()
+
+Then running the module as a script will cause the examples in the
+docstrings to get executed and verified:
+
+python M.py
+
+This won't display anything unless an example fails, in which case the
+failing example(s) and the cause(s) of the failure(s) are printed to stdout
+(why not stderr? because stderr is a lame hack <0.2 wink>), and the final
+line of output is "Test failed.".
+
+Run it with the -v switch instead:
+
+python M.py -v
+
+and a detailed report of all examples tried is printed to stdout, along
+with assorted summaries at the end.
+
+You can force verbose mode by passing "verbose=True" to testmod, or prohibit
+it by passing "verbose=False".  In either of those cases, sys.argv is not
+examined by testmod.
+
+There are a variety of other ways to run doctests, including integration
+with the unittest framework, and support for running non-Python text
+files containing doctests.  There are also many ways to override parts
+of doctest's default behaviors.  See the Library Reference Manual for
+details.
+"""
+
+__docformat__ = 'reStructuredText en'
+
+__all__ = [
+    # 0, Option Flags
+    'register_optionflag',
+    'DONT_ACCEPT_TRUE_FOR_1',
+    'DONT_ACCEPT_BLANKLINE',
+    'NORMALIZE_WHITESPACE',
+    'ELLIPSIS',
+    'IGNORE_EXCEPTION_DETAIL',
+    'COMPARISON_FLAGS',
+    'REPORT_UDIFF',
+    'REPORT_CDIFF',
+    'REPORT_NDIFF',
+    'REPORT_ONLY_FIRST_FAILURE',
+    'REPORTING_FLAGS',
+    # 1. Utility Functions
+    'is_private',
+    # 2. Example & DocTest
+    'Example',
+    'DocTest',
+    # 3. Doctest Parser
+    'DocTestParser',
+    # 4. Doctest Finder
+    'DocTestFinder',
+    # 5. Doctest Runner
+    'DocTestRunner',
+    'OutputChecker',
+    'DocTestFailure',
+    'UnexpectedException',
+    'DebugRunner',
+    # 6. Test Functions
+    'testmod',
+    'testfile',
+    'run_docstring_examples',
+    # 7. Tester
+    'Tester',
+    # 8. Unittest Support
+    'DocTestSuite',
+    'DocFileSuite',
+    'set_unittest_reportflags',
+    # 9. Debugging Support
+    'script_from_examples',
+    'testsource',
+    'debug_src',
+    'debug',
+]
+
+import __future__
+
+import sys, traceback, inspect, linecache, os, re, types
+import unittest, difflib, pdb, tempfile
+import warnings
+from StringIO import StringIO
+
+# Don't whine about the deprecated is_private function in this
+# module's tests.
+warnings.filterwarnings("ignore", "is_private", DeprecationWarning,
+                        __name__, 0)
+
+# There are 4 basic classes:
+#  - Example: a <source, want> pair, plus an intra-docstring line number.
+#  - DocTest: a collection of examples, parsed from a docstring, plus
+#    info about where the docstring came from (name, filename, lineno).
+#  - DocTestFinder: extracts DocTests from a given object's docstring and
+#    its contained objects' docstrings.
+#  - DocTestRunner: runs DocTest cases, and accumulates statistics.
+#
+# So the basic picture is:
+#
+#                             list of:
+# +------+                   +---------+                   +-------+
+# |object| --DocTestFinder-> | DocTest | --DocTestRunner-> |results|
+# +------+                   +---------+                   +-------+
+#                            | Example |
+#                            |   ...   |
+#                            | Example |
+#                            +---------+
+
+# Option constants.
+
+OPTIONFLAGS_BY_NAME = {}
+def register_optionflag(name):
+    flag = 1 << len(OPTIONFLAGS_BY_NAME)
+    OPTIONFLAGS_BY_NAME[name] = flag
+    return flag
+
+DONT_ACCEPT_TRUE_FOR_1 = register_optionflag('DONT_ACCEPT_TRUE_FOR_1')
+DONT_ACCEPT_BLANKLINE = register_optionflag('DONT_ACCEPT_BLANKLINE')
+NORMALIZE_WHITESPACE = register_optionflag('NORMALIZE_WHITESPACE')
+ELLIPSIS = register_optionflag('ELLIPSIS')
+IGNORE_EXCEPTION_DETAIL = register_optionflag('IGNORE_EXCEPTION_DETAIL')
+
+COMPARISON_FLAGS = (DONT_ACCEPT_TRUE_FOR_1 |
+                    DONT_ACCEPT_BLANKLINE |
+                    NORMALIZE_WHITESPACE |
+                    ELLIPSIS |
+                    IGNORE_EXCEPTION_DETAIL)
+
+REPORT_UDIFF = register_optionflag('REPORT_UDIFF')
+REPORT_CDIFF = register_optionflag('REPORT_CDIFF')
+REPORT_NDIFF = register_optionflag('REPORT_NDIFF')
+REPORT_ONLY_FIRST_FAILURE = register_optionflag('REPORT_ONLY_FIRST_FAILURE')
+
+REPORTING_FLAGS = (REPORT_UDIFF |
+                   REPORT_CDIFF |
+                   REPORT_NDIFF |
+                   REPORT_ONLY_FIRST_FAILURE)
+
+# Special string markers for use in `want` strings:
+BLANKLINE_MARKER = '<BLANKLINE>'
+ELLIPSIS_MARKER = '...'
+
+######################################################################
+## Table of Contents
+######################################################################
+#  1. Utility Functions
+#  2. Example & DocTest -- store test cases
+#  3. DocTest Parser -- extracts examples from strings
+#  4. DocTest Finder -- extracts test cases from objects
+#  5. DocTest Runner -- runs test cases
+#  6. Test Functions -- convenient wrappers for testing
+#  7. Tester Class -- for backwards compatibility
+#  8. Unittest Support
+#  9. Debugging Support
+# 10. Example Usage
+
+######################################################################
+## 1. Utility Functions
+######################################################################
+
+def is_private(prefix, base):
+    """prefix, base -> true iff name prefix + "." + base is "private".
+
+    Prefix may be an empty string, and base does not contain a period.
+    Prefix is ignored (although functions you write conforming to this
+    protocol may make use of it).
+    Return true iff base begins with an (at least one) underscore, but
+    does not both begin and end with (at least) two underscores.
+
+    >>> is_private("a.b", "my_func")
+    False
+    >>> is_private("____", "_my_func")
+    True
+    >>> is_private("someclass", "__init__")
+    False
+    >>> is_private("sometypo", "__init_")
+    True
+    >>> is_private("x.y.z", "_")
+    True
+    >>> is_private("_x.y.z", "__")
+    False
+    >>> is_private("", "")  # senseless but consistent
+    False
+    """
+    warnings.warn("is_private is deprecated; it wasn't useful; "
+                  "examine DocTestFinder.find() lists instead",
+                  DeprecationWarning, stacklevel=2)
+    return base[:1] == "_" and not base[:2] == "__" == base[-2:]
+
+def _extract_future_flags(globs):
+    """
+    Return the compiler-flags associated with the future features that
+    have been imported into the given namespace (globs).
+    """
+    flags = 0
+    for fname in __future__.all_feature_names:
+        feature = globs.get(fname, None)
+        if feature is getattr(__future__, fname):
+            flags |= feature.compiler_flag
+    return flags
+
+def _normalize_module(module, depth=2):
+    """
+    Return the module specified by `module`.  In particular:
+      - If `module` is a module, then return module.
+      - If `module` is a string, then import and return the
+        module with that name.
+      - If `module` is None, then return the calling module.
+        The calling module is assumed to be the module of
+        the stack frame at the given depth in the call stack.
+    """
+    if inspect.ismodule(module):
+        return module
+    elif isinstance(module, (str, unicode)):
+        return __import__(module, globals(), locals(), ["*"])
+    elif module is None:
+        return sys.modules[sys._getframe(depth).f_globals['__name__']]
+    else:
+        raise TypeError("Expected a module, string, or None")
+
+def _indent(s, indent=4):
+    """
+    Add the given number of space characters to the beginning every
+    non-blank line in `s`, and return the result.
+    """
+    # This regexp matches the start of non-blank lines:
+    return re.sub('(?m)^(?!$)', indent*' ', s)
+
+def _exception_traceback(exc_info):
+    """
+    Return a string containing a traceback message for the given
+    exc_info tuple (as returned by sys.exc_info()).
+    """
+    # Get a traceback message.
+    excout = StringIO()
+    exc_type, exc_val, exc_tb = exc_info
+    traceback.print_exception(exc_type, exc_val, exc_tb, file=excout)
+    return excout.getvalue()
+
+# Override some StringIO methods.
+class _SpoofOut(StringIO):
+    def getvalue(self):
+        result = StringIO.getvalue(self)
+        # If anything at all was written, make sure there's a trailing
+        # newline.  There's no way for the expected output to indicate
+        # that a trailing newline is missing.
+        if result and not result.endswith("\n"):
+            result += "\n"
+        # Prevent softspace from screwing up the next test case, in
+        # case they used print with a trailing comma in an example.
+        if hasattr(self, "softspace"):
+            del self.softspace
+        return result
+
+    def truncate(self,   size=None):
+        StringIO.truncate(self, size)
+        if hasattr(self, "softspace"):
+            del self.softspace
+
+# Worst-case linear-time ellipsis matching.
+def _ellipsis_match(want, got):
+    """
+    Essentially the only subtle case:
+    >>> _ellipsis_match('aa...aa', 'aaa')
+    False
+    """
+    if ELLIPSIS_MARKER not in want:
+        return want == got
+
+    # Find "the real" strings.
+    ws = want.split(ELLIPSIS_MARKER)
+    assert len(ws) >= 2
+
+    # Deal with exact matches possibly needed at one or both ends.
+    startpos, endpos = 0, len(got)
+    w = ws[0]
+    if w:   # starts with exact match
+        if got.startswith(w):
+            startpos = len(w)
+            del ws[0]
+        else:
+            return False
+    w = ws[-1]
+    if w:   # ends with exact match
+        if got.endswith(w):
+            endpos -= len(w)
+            del ws[-1]
+        else:
+            return False
+
+    if startpos > endpos:
+        # Exact end matches required more characters than we have, as in
+        # _ellipsis_match('aa...aa', 'aaa')
+        return False
+
+    # For the rest, we only need to find the leftmost non-overlapping
+    # match for each piece.  If there's no overall match that way alone,
+    # there's no overall match period.
+    for w in ws:
+        # w may be '' at times, if there are consecutive ellipses, or
+        # due to an ellipsis at the start or end of `want`.  That's OK.
+        # Search for an empty string succeeds, and doesn't change startpos.
+        startpos = got.find(w, startpos, endpos)
+        if startpos < 0:
+            return False
+        startpos += len(w)
+
+    return True
+
+def _comment_line(line):
+    "Return a commented form of the given line"
+    line = line.rstrip()
+    if line:
+        return '# '+line
+    else:
+        return '#'
+
+class _OutputRedirectingPdb(pdb.Pdb):
+    """
+    A specialized version of the python debugger that redirects stdout
+    to a given stream when interacting with the user.  Stdout is *not*
+    redirected when traced code is executed.
+    """
+    def __init__(self, out):
+        self.__out = out
+        pdb.Pdb.__init__(self)
+
+    def trace_dispatch(self, *args):
+        # Redirect stdout to the given stream.
+        save_stdout = sys.stdout
+        sys.stdout = self.__out
+        # Call Pdb's trace dispatch method.
+        try:
+            return pdb.Pdb.trace_dispatch(self, *args)
+        finally:
+            sys.stdout = save_stdout
+
+# [XX] Normalize with respect to os.path.pardir?
+def _module_relative_path(module, path):
+    if not inspect.ismodule(module):
+        raise TypeError, 'Expected a module: %r' % module
+    if path.startswith('/'):
+        raise ValueError, 'Module-relative files may not have absolute paths'
+
+    # Find the base directory for the path.
+    if hasattr(module, '__file__'):
+        # A normal module/package
+        basedir = os.path.split(module.__file__)[0]
+    elif module.__name__ == '__main__':
+        # An interactive session.
+        if len(sys.argv)>0 and sys.argv[0] != '':
+            basedir = os.path.split(sys.argv[0])[0]
+        else:
+            basedir = os.curdir
+    else:
+        # A module w/o __file__ (this includes builtins)
+        raise ValueError("Can't resolve paths relative to the module " +
+                         module + " (it has no __file__)")
+
+    # Combine the base directory and the path.
+    return os.path.join(basedir, *(path.split('/')))
+
+######################################################################
+## 2. Example & DocTest
+######################################################################
+## - An "example" is a <source, want> pair, where "source" is a
+##   fragment of source code, and "want" is the expected output for
+##   "source."  The Example class also includes information about
+##   where the example was extracted from.
+##
+## - A "doctest" is a collection of examples, typically extracted from
+##   a string (such as an object's docstring).  The DocTest class also
+##   includes information about where the string was extracted from.
+
+class Example:
+    """
+    A single doctest example, consisting of source code and expected
+    output.  `Example` defines the following attributes:
+
+      - source: A single Python statement, always ending with a newline.
+        The constructor adds a newline if needed.
+
+      - want: The expected output from running the source code (either
+        from stdout, or a traceback in case of exception).  `want` ends
+        with a newline unless it's empty, in which case it's an empty
+        string.  The constructor adds a newline if needed.
+
+      - exc_msg: The exception message generated by the example, if
+        the example is expected to generate an exception; or `None` if
+        it is not expected to generate an exception.  This exception
+        message is compared against the return value of
+        `traceback.format_exception_only()`.  `exc_msg` ends with a
+        newline unless it's `None`.  The constructor adds a newline
+        if needed.
+
+      - lineno: The line number within the DocTest string containing
+        this Example where the Example begins.  This line number is
+        zero-based, with respect to the beginning of the DocTest.
+
+      - indent: The example's indentation in the DocTest string.
+        I.e., the number of space characters that preceed the
+        example's first prompt.
+
+      - options: A dictionary mapping from option flags to True or
+        False, which is used to override default options for this
+        example.  Any option flags not contained in this dictionary
+        are left at their default value (as specified by the
+        DocTestRunner's optionflags).  By default, no options are set.
+    """
+    def __init__(self, source, want, exc_msg=None, lineno=0, indent=0,
+                 options=None):
+        # Normalize inputs.
+        if not source.endswith('\n'):
+            source += '\n'
+        if want and not want.endswith('\n'):
+            want += '\n'
+        if exc_msg is not None and not exc_msg.endswith('\n'):
+            exc_msg += '\n'
+        # Store properties.
+        self.source = source
+        self.want = want
+        self.lineno = lineno
+        self.indent = indent
+        if options is None: options = {}
+        self.options = options
+        self.exc_msg = exc_msg
+
+class DocTest:
+    """
+    A collection of doctest examples that should be run in a single
+    namespace.  Each `DocTest` defines the following attributes:
+
+      - examples: the list of examples.
+
+      - globs: The namespace (aka globals) that the examples should
+        be run in.
+
+      - name: A name identifying the DocTest (typically, the name of
+        the object whose docstring this DocTest was extracted from).
+
+      - filename: The name of the file that this DocTest was extracted
+        from, or `None` if the filename is unknown.
+
+      - lineno: The line number within filename where this DocTest
+        begins, or `None` if the line number is unavailable.  This
+        line number is zero-based, with respect to the beginning of
+        the file.
+
+      - docstring: The string that the examples were extracted from,
+        or `None` if the string is unavailable.
+    """
+    def __init__(self, examples, globs, name, filename, lineno, docstring):
+        """
+        Create a new DocTest containing the given examples.  The
+        DocTest's globals are initialized with a copy of `globs`.
+        """
+        assert not isinstance(examples, basestring), \
+               "DocTest no longer accepts str; use DocTestParser instead"
+        self.examples = examples
+        self.docstring = docstring
+        self.globs = globs.copy()
+        self.name = name
+        self.filename = filename
+        self.lineno = lineno
+
+    def __repr__(self):
+        if len(self.examples) == 0:
+            examples = 'no examples'
+        elif len(self.examples) == 1:
+            examples = '1 example'
+        else:
+            examples = '%d examples' % len(self.examples)
+        return ('<DocTest %s from %s:%s (%s)>' %
+                (self.name, self.filename, self.lineno, examples))
+
+
+    # This lets us sort tests by name:
+    def __cmp__(self, other):
+        if not isinstance(other, DocTest):
+            return -1
+        return cmp((self.name, self.filename, self.lineno, id(self)),
+                   (other.name, other.filename, other.lineno, id(other)))
+
+######################################################################
+## 3. DocTestParser
+######################################################################
+
+class DocTestParser:
+    """
+    A class used to parse strings containing doctest examples.
+    """
+    # This regular expression is used to find doctest examples in a
+    # string.  It defines three groups: `source` is the source code
+    # (including leading indentation and prompts); `indent` is the
+    # indentation of the first (PS1) line of the source code; and
+    # `want` is the expected output (including leading indentation).
+    _EXAMPLE_RE = re.compile(r'''
+        # Source consists of a PS1 line followed by zero or more PS2 lines.
+        (?P<source>
+            (?:^(?P<indent> [ ]*) >>>    .*)    # PS1 line
+            (?:\n           [ ]*  \.\.\. .*)*)  # PS2 lines
+        \n?
+        # Want consists of any non-blank lines that do not start with PS1.
+        (?P<want> (?:(?![ ]*$)    # Not a blank line
+                     (?![ ]*>>>)  # Not a line starting with PS1
+                     .*$\n?       # But any other line
+                  )*)
+        ''', re.MULTILINE | re.VERBOSE)
+
+    # A regular expression for handling `want` strings that contain
+    # expected exceptions.  It divides `want` into three pieces:
+    #    - the traceback header line (`hdr`)
+    #    - the traceback stack (`stack`)
+    #    - the exception message (`msg`), as generated by
+    #      traceback.format_exception_only()
+    # `msg` may have multiple lines.  We assume/require that the
+    # exception message is the first non-indented line starting with a word
+    # character following the traceback header line.
+    _EXCEPTION_RE = re.compile(r"""
+        # Grab the traceback header.  Different versions of Python have
+        # said different things on the first traceback line.
+        ^(?P<hdr> Traceback\ \(
+            (?: most\ recent\ call\ last
+            |   innermost\ last
+            ) \) :
+        )
+        \s* $                # toss trailing whitespace on the header.
+        (?P<stack> .*?)      # don't blink: absorb stuff until...
+        ^ (?P<msg> \w+ .*)   #     a line *starts* with alphanum.
+        """, re.VERBOSE | re.MULTILINE | re.DOTALL)
+
+    # A callable returning a true value iff its argument is a blank line
+    # or contains a single comment.
+    _IS_BLANK_OR_COMMENT = re.compile(r'^[ ]*(#.*)?$').match
+
+    def parse(self, string, name='<string>'):
+        """
+        Divide the given string into examples and intervening text,
+        and return them as a list of alternating Examples and strings.
+        Line numbers for the Examples are 0-based.  The optional
+        argument `name` is a name identifying this string, and is only
+        used for error messages.
+        """
+        string = string.expandtabs()
+        # If all lines begin with the same indentation, then strip it.
+        min_indent = self._min_indent(string)
+        if min_indent > 0:
+            string = '\n'.join([l[min_indent:] for l in string.split('\n')])
+
+        output = []
+        charno, lineno = 0, 0
+        # Find all doctest examples in the string:
+        for m in self._EXAMPLE_RE.finditer(string):
+            # Add the pre-example text to `output`.
+            output.append(string[charno:m.start()])
+            # Update lineno (lines before this example)
+            lineno += string.count('\n', charno, m.start())
+            # Extract info from the regexp match.
+            (source, options, want, exc_msg) = \
+                     self._parse_example(m, name, lineno)
+            # Create an Example, and add it to the list.
+            if not self._IS_BLANK_OR_COMMENT(source):
+                output.append( Example(source, want, exc_msg,
+                                    lineno=lineno,
+                                    indent=min_indent+len(m.group('indent')),
+                                    options=options) )
+            # Update lineno (lines inside this example)
+            lineno += string.count('\n', m.start(), m.end())
+            # Update charno.
+            charno = m.end()
+        # Add any remaining post-example text to `output`.
+        output.append(string[charno:])
+        return output
+
+    def get_doctest(self, string, globs, name, filename, lineno):
+        """
+        Extract all doctest examples from the given string, and
+        collect them into a `DocTest` object.
+
+        `globs`, `name`, `filename`, and `lineno` are attributes for
+        the new `DocTest` object.  See the documentation for `DocTest`
+        for more information.
+        """
+        return DocTest(self.get_examples(string, name), globs,
+                       name, filename, lineno, string)
+
+    def get_examples(self, string, name='<string>'):
+        """
+        Extract all doctest examples from the given string, and return
+        them as a list of `Example` objects.  Line numbers are
+        0-based, because it's most common in doctests that nothing
+        interesting appears on the same line as opening triple-quote,
+        and so the first interesting line is called \"line 1\" then.
+
+        The optional argument `name` is a name identifying this
+        string, and is only used for error messages.
+        """
+        return [x for x in self.parse(string, name)
+                if isinstance(x, Example)]
+
+    def _parse_example(self, m, name, lineno):
+        """
+        Given a regular expression match from `_EXAMPLE_RE` (`m`),
+        return a pair `(source, want)`, where `source` is the matched
+        example's source code (with prompts and indentation stripped);
+        and `want` is the example's expected output (with indentation
+        stripped).
+
+        `name` is the string's name, and `lineno` is the line number
+        where the example starts; both are used for error messages.
+        """
+        # Get the example's indentation level.
+        indent = len(m.group('indent'))
+
+        # Divide source into lines; check that they're properly
+        # indented; and then strip their indentation & prompts.
+        source_lines = m.group('source').split('\n')
+        self._check_prompt_blank(source_lines, indent, name, lineno)
+        self._check_prefix(source_lines[1:], ' '*indent + '.', name, lineno)
+        source = '\n'.join([sl[indent+4:] for sl in source_lines])
+
+        # Divide want into lines; check that it's properly indented; and
+        # then strip the indentation.  Spaces before the last newline should
+        # be preserved, so plain rstrip() isn't good enough.
+        want = m.group('want')
+        want_lines = want.split('\n')
+        if len(want_lines) > 1 and re.match(r' *$', want_lines[-1]):
+            del want_lines[-1]  # forget final newline & spaces after it
+        self._check_prefix(want_lines, ' '*indent, name,
+                           lineno + len(source_lines))
+        want = '\n'.join([wl[indent:] for wl in want_lines])
+
+        # If `want` contains a traceback message, then extract it.
+        m = self._EXCEPTION_RE.match(want)
+        if m:
+            exc_msg = m.group('msg')
+        else:
+            exc_msg = None
+
+        # Extract options from the source.
+        options = self._find_options(source, name, lineno)
+
+        return source, options, want, exc_msg
+
+    # This regular expression looks for option directives in the
+    # source code of an example.  Option directives are comments
+    # starting with "doctest:".  Warning: this may give false
+    # positives for string-literals that contain the string
+    # "#doctest:".  Eliminating these false positives would require
+    # actually parsing the string; but we limit them by ignoring any
+    # line containing "#doctest:" that is *followed* by a quote mark.
+    _OPTION_DIRECTIVE_RE = re.compile(r'#\s*doctest:\s*([^\n\'"]*)$',
+                                      re.MULTILINE)
+
+    def _find_options(self, source, name, lineno):
+        """
+        Return a dictionary containing option overrides extracted from
+        option directives in the given source string.
+
+        `name` is the string's name, and `lineno` is the line number
+        where the example starts; both are used for error messages.
+        """
+        options = {}
+        # (note: with the current regexp, this will match at most once:)
+        for m in self._OPTION_DIRECTIVE_RE.finditer(source):
+            option_strings = m.group(1).replace(',', ' ').split()
+            for option in option_strings:
+                if (option[0] not in '+-' or
+                    option[1:] not in OPTIONFLAGS_BY_NAME):
+                    raise ValueError('line %r of the doctest for %s '
+                                     'has an invalid option: %r' %
+                                     (lineno+1, name, option))
+                flag = OPTIONFLAGS_BY_NAME[option[1:]]
+                options[flag] = (option[0] == '+')
+        if options and self._IS_BLANK_OR_COMMENT(source):
+            raise ValueError('line %r of the doctest for %s has an option '
+                             'directive on a line with no example: %r' %
+                             (lineno, name, source))
+        return options
+
+    # This regular expression finds the indentation of every non-blank
+    # line in a string.
+    _INDENT_RE = re.compile('^([ ]*)(?=\S)', re.MULTILINE)
+
+    def _min_indent(self, s):
+        "Return the minimum indentation of any non-blank line in `s`"
+        indents = [len(indent) for indent in self._INDENT_RE.findall(s)]
+        if len(indents) > 0:
+            return min(indents)
+        else:
+            return 0
+
+    def _check_prompt_blank(self, lines, indent, name, lineno):
+        """
+        Given the lines of a source string (including prompts and
+        leading indentation), check to make sure that every prompt is
+        followed by a space character.  If any line is not followed by
+        a space character, then raise ValueError.
+        """
+        for i, line in enumerate(lines):
+            if len(line) >= indent+4 and line[indent+3] != ' ':
+                raise ValueError('line %r of the docstring for %s '
+                                 'lacks blank after %s: %r' %
+                                 (lineno+i+1, name,
+                                  line[indent:indent+3], line))
+
+    def _check_prefix(self, lines, prefix, name, lineno):
+        """
+        Check that every line in the given list starts with the given
+        prefix; if any line does not, then raise a ValueError.
+        """
+        for i, line in enumerate(lines):
+            if line and not line.startswith(prefix):
+                raise ValueError('line %r of the docstring for %s has '
+                                 'inconsistent leading whitespace: %r' %
+                                 (lineno+i+1, name, line))
+
+
+######################################################################
+## 4. DocTest Finder
+######################################################################
+
+class DocTestFinder:
+    """
+    A class used to extract the DocTests that are relevant to a given
+    object, from its docstring and the docstrings of its contained
+    objects.  Doctests can currently be extracted from the following
+    object types: modules, functions, classes, methods, staticmethods,
+    classmethods, and properties.
+    """
+
+    def __init__(self, verbose=False, parser=DocTestParser(),
+                 recurse=True, _namefilter=None, exclude_empty=True):
+        """
+        Create a new doctest finder.
+
+        The optional argument `parser` specifies a class or
+        function that should be used to create new DocTest objects (or
+        objects that implement the same interface as DocTest).  The
+        signature for this factory function should match the signature
+        of the DocTest constructor.
+
+        If the optional argument `recurse` is false, then `find` will
+        only examine the given object, and not any contained objects.
+
+        If the optional argument `exclude_empty` is false, then `find`
+        will include tests for objects with empty docstrings.
+        """
+        self._parser = parser
+        self._verbose = verbose
+        self._recurse = recurse
+        self._exclude_empty = exclude_empty
+        # _namefilter is undocumented, and exists only for temporary backward-
+        # compatibility support of testmod's deprecated isprivate mess.
+        self._namefilter = _namefilter
+
+    def find(self, obj, name=None, module=None, globs=None,
+             extraglobs=None):
+        """
+        Return a list of the DocTests that are defined by the given
+        object's docstring, or by any of its contained objects'
+        docstrings.
+
+        The optional parameter `module` is the module that contains
+        the given object.  If the module is not specified or is None, then
+        the test finder will attempt to automatically determine the
+        correct module.  The object's module is used:
+
+            - As a default namespace, if `globs` is not specified.
+            - To prevent the DocTestFinder from extracting DocTests
+              from objects that are imported from other modules.
+            - To find the name of the file containing the object.
+            - To help find the line number of the object within its
+              file.
+
+        Contained objects whose module does not match `module` are ignored.
+
+        If `module` is False, no attempt to find the module will be made.
+        This is obscure, of use mostly in tests:  if `module` is False, or
+        is None but cannot be found automatically, then all objects are
+        considered to belong to the (non-existent) module, so all contained
+        objects will (recursively) be searched for doctests.
+
+        The globals for each DocTest is formed by combining `globs`
+        and `extraglobs` (bindings in `extraglobs` override bindings
+        in `globs`).  A new copy of the globals dictionary is created
+        for each DocTest.  If `globs` is not specified, then it
+        defaults to the module's `__dict__`, if specified, or {}
+        otherwise.  If `extraglobs` is not specified, then it defaults
+        to {}.
+
+        """
+        # If name was not specified, then extract it from the object.
+        if name is None:
+            name = getattr(obj, '__name__', None)
+            if name is None:
+                raise ValueError("DocTestFinder.find: name must be given "
+                        "when obj.__name__ doesn't exist: %r" %
+                                 (type(obj),))
+
+        # Find the module that contains the given object (if obj is
+        # a module, then module=obj.).  Note: this may fail, in which
+        # case module will be None.
+        if module is False:
+            module = None
+        elif module is None:
+            module = inspect.getmodule(obj)
+
+        # Read the module's source code.  This is used by
+        # DocTestFinder._find_lineno to find the line number for a
+        # given object's docstring.
+        try:
+            file = inspect.getsourcefile(obj) or inspect.getfile(obj)
+            source_lines = linecache.getlines(file)
+            if not source_lines:
+                source_lines = None
+        except TypeError:
+            source_lines = None
+
+        # Initialize globals, and merge in extraglobs.
+        if globs is None:
+            if module is None:
+                globs = {}
+            else:
+                globs = module.__dict__.copy()
+        else:
+            globs = globs.copy()
+        if extraglobs is not None:
+            globs.update(extraglobs)
+
+        # Recursively expore `obj`, extracting DocTests.
+        tests = []
+        self._find(tests, obj, name, module, source_lines, globs, {})
+        return tests
+
+    def _filter(self, obj, prefix, base):
+        """
+        Return true if the given object should not be examined.
+        """
+        return (self._namefilter is not None and
+                self._namefilter(prefix, base))
+
+    def _from_module(self, module, object):
+        """
+        Return true if the given object is defined in the given
+        module.
+        """
+        if module is None:
+            return True
+        elif inspect.isfunction(object):
+            return module.__dict__ is object.func_globals
+        elif inspect.isclass(object):
+            return module.__name__ == object.__module__
+        elif inspect.getmodule(object) is not None:
+            return module is inspect.getmodule(object)
+        elif hasattr(object, '__module__'):
+            return module.__name__ == object.__module__
+        elif isinstance(object, property):
+            return True # [XX] no way not be sure.
+        else:
+            raise ValueError("object must be a class or function")
+
+    def _find(self, tests, obj, name, module, source_lines, globs, seen):
+        """
+        Find tests for the given object and any contained objects, and
+        add them to `tests`.
+        """
+        if self._verbose:
+            print 'Finding tests in %s' % name
+
+        # If we've already processed this object, then ignore it.
+        if id(obj) in seen:
+            return
+        seen[id(obj)] = 1
+
+        # Find a test for this object, and add it to the list of tests.
+        test = self._get_test(obj, name, module, globs, source_lines)
+        if test is not None:
+            tests.append(test)
+
+        # Look for tests in a module's contained objects.
+        if inspect.ismodule(obj) and self._recurse:
+            for valname, val in obj.__dict__.items():
+                # Check if this contained object should be ignored.
+                if self._filter(val, name, valname):
+                    continue
+                valname = '%s.%s' % (name, valname)
+                # Recurse to functions & classes.
+                if ((inspect.isfunction(val) or inspect.isclass(val)) and
+                    self._from_module(module, val)):
+                    self._find(tests, val, valname, module, source_lines,
+                               globs, seen)
+
+        # Look for tests in a module's __test__ dictionary.
+        if inspect.ismodule(obj) and self._recurse:
+            for valname, val in getattr(obj, '__test__', {}).items():
+                if not isinstance(valname, basestring):
+                    raise ValueError("DocTestFinder.find: __test__ keys "
+                                     "must be strings: %r" %
+                                     (type(valname),))
+                if not (inspect.isfunction(val) or inspect.isclass(val) or
+                        inspect.ismethod(val) or inspect.ismodule(val) or
+                        isinstance(val, basestring)):
+                    raise ValueError("DocTestFinder.find: __test__ values "
+                                     "must be strings, functions, methods, "
+                                     "classes, or modules: %r" %
+                                     (type(val),))
+                valname = '%s.__test__.%s' % (name, valname)
+                self._find(tests, val, valname, module, source_lines,
+                           globs, seen)
+
+        # Look for tests in a class's contained objects.
+        if inspect.isclass(obj) and self._recurse:
+            for valname, val in obj.__dict__.items():
+                # Check if this contained object should be ignored.
+                if self._filter(val, name, valname):
+                    continue
+                # Special handling for staticmethod/classmethod.
+                if isinstance(val, staticmethod):
+                    val = getattr(obj, valname)
+                if isinstance(val, classmethod):
+                    val = getattr(obj, valname).im_func
+
+                # Recurse to methods, properties, and nested classes.
+                if ((inspect.isfunction(val) or inspect.isclass(val) or
+                      isinstance(val, property)) and
+                      self._from_module(module, val)):
+                    valname = '%s.%s' % (name, valname)
+                    self._find(tests, val, valname, module, source_lines,
+                               globs, seen)
+
+    def _get_test(self, obj, name, module, globs, source_lines):
+        """
+        Return a DocTest for the given object, if it defines a docstring;
+        otherwise, return None.
+        """
+        # Extract the object's docstring.  If it doesn't have one,
+        # then return None (no test for this object).
+        if isinstance(obj, basestring):
+            docstring = obj
+        else:
+            try:
+                if obj.__doc__ is None:
+                    docstring = ''
+                else:
+                    docstring = obj.__doc__
+                    if not isinstance(docstring, basestring):
+                        docstring = str(docstring)
+            except (TypeError, AttributeError):
+                docstring = ''
+
+        # Find the docstring's location in the file.
+        lineno = self._find_lineno(obj, source_lines)
+
+        # Don't bother if the docstring is empty.
+        if self._exclude_empty and not docstring:
+            return None
+
+        # Return a DocTest for this object.
+        if module is None:
+            filename = None
+        else:
+            filename = getattr(module, '__file__', module.__name__)
+            if filename[-4:] in (".pyc", ".pyo"):
+                filename = filename[:-1]
+        return self._parser.get_doctest(docstring, globs, name,
+                                        filename, lineno)
+
+    def _find_lineno(self, obj, source_lines):
+        """
+        Return a line number of the given object's docstring.  Note:
+        this method assumes that the object has a docstring.
+        """
+        lineno = None
+
+        # Find the line number for modules.
+        if inspect.ismodule(obj):
+            lineno = 0
+
+        # Find the line number for classes.
+        # Note: this could be fooled if a class is defined multiple
+        # times in a single file.
+        if inspect.isclass(obj):
+            if source_lines is None:
+                return None
+            pat = re.compile(r'^\s*class\s*%s\b' %
+                             getattr(obj, '__name__', '-'))
+            for i, line in enumerate(source_lines):
+                if pat.match(line):
+                    lineno = i
+                    break
+
+        # Find the line number for functions & methods.
+        if inspect.ismethod(obj): obj = obj.im_func
+        if inspect.isfunction(obj): obj = obj.func_code
+        if inspect.istraceback(obj): obj = obj.tb_frame
+        if inspect.isframe(obj): obj = obj.f_code
+        if inspect.iscode(obj):
+            lineno = getattr(obj, 'co_firstlineno', None)-1
+
+        # Find the line number where the docstring starts.  Assume
+        # that it's the first line that begins with a quote mark.
+        # Note: this could be fooled by a multiline function
+        # signature, where a continuation line begins with a quote
+        # mark.
+        if lineno is not None:
+            if source_lines is None:
+                return lineno+1
+            pat = re.compile('(^|.*:)\s*\w*("|\')')
+            for lineno in range(lineno, len(source_lines)):
+                if pat.match(source_lines[lineno]):
+                    return lineno
+
+        # We couldn't find the line number.
+        return None
+
+######################################################################
+## 5. DocTest Runner
+######################################################################
+
+class DocTestRunner:
+    """
+    A class used to run DocTest test cases, and accumulate statistics.
+    The `run` method is used to process a single DocTest case.  It
+    returns a tuple `(f, t)`, where `t` is the number of test cases
+    tried, and `f` is the number of test cases that failed.
+
+        >>> tests = DocTestFinder().find(_TestClass)
+        >>> runner = DocTestRunner(verbose=False)
+        >>> for test in tests:
+        ...     print runner.run(test)
+        (0, 2)
+        (0, 1)
+        (0, 2)
+        (0, 2)
+
+    The `summarize` method prints a summary of all the test cases that
+    have been run by the runner, and returns an aggregated `(f, t)`
+    tuple:
+
+        >>> runner.summarize(verbose=1)
+        4 items passed all tests:
+           2 tests in _TestClass
+           2 tests in _TestClass.__init__
+           2 tests in _TestClass.get
+           1 tests in _TestClass.square
+        7 tests in 4 items.
+        7 passed and 0 failed.
+        Test passed.
+        (0, 7)
+
+    The aggregated number of tried examples and failed examples is
+    also available via the `tries` and `failures` attributes:
+
+        >>> runner.tries
+        7
+        >>> runner.failures
+        0
+
+    The comparison between expected outputs and actual outputs is done
+    by an `OutputChecker`.  This comparison may be customized with a
+    number of option flags; see the documentation for `testmod` for
+    more information.  If the option flags are insufficient, then the
+    comparison may also be customized by passing a subclass of
+    `OutputChecker` to the constructor.
+
+    The test runner's display output can be controlled in two ways.
+    First, an output function (`out) can be passed to
+    `TestRunner.run`; this function will be called with strings that
+    should be displayed.  It defaults to `sys.stdout.write`.  If
+    capturing the output is not sufficient, then the display output
+    can be also customized by subclassing DocTestRunner, and
+    overriding the methods `report_start`, `report_success`,
+    `report_unexpected_exception`, and `report_failure`.
+    """
+    # This divider string is used to separate failure messages, and to
+    # separate sections of the summary.
+    DIVIDER = "*" * 70
+
+    def __init__(self, checker=None, verbose=None, optionflags=0):
+        """
+        Create a new test runner.
+
+        Optional keyword arg `checker` is the `OutputChecker` that
+        should be used to compare the expected outputs and actual
+        outputs of doctest examples.
+
+        Optional keyword arg 'verbose' prints lots of stuff if true,
+        only failures if false; by default, it's true iff '-v' is in
+        sys.argv.
+
+        Optional argument `optionflags` can be used to control how the
+        test runner compares expected output to actual output, and how
+        it displays failures.  See the documentation for `testmod` for
+        more information.
+        """
+        self._checker = checker or OutputChecker()
+        if verbose is None:
+            verbose = '-v' in sys.argv
+        self._verbose = verbose
+        self.optionflags = optionflags
+        self.original_optionflags = optionflags
+
+        # Keep track of the examples we've run.
+        self.tries = 0
+        self.failures = 0
+        self._name2ft = {}
+
+        # Create a fake output target for capturing doctest output.
+        self._fakeout = _SpoofOut()
+
+    #/////////////////////////////////////////////////////////////////
+    # Reporting methods
+    #/////////////////////////////////////////////////////////////////
+
+    def report_start(self, out, test, example):
+        """
+        Report that the test runner is about to process the given
+        example.  (Only displays a message if verbose=True)
+        """
+        if self._verbose:
+            if example.want:
+                out('Trying:\n' + _indent(example.source) +
+                    'Expecting:\n' + _indent(example.want))
+            else:
+                out('Trying:\n' + _indent(example.source) +
+                    'Expecting nothing\n')
+
+    def report_success(self, out, test, example, got):
+        """
+        Report that the given example ran successfully.  (Only
+        displays a message if verbose=True)
+        """
+        if self._verbose:
+            out("ok\n")
+
+    def report_failure(self, out, test, example, got):
+        """
+        Report that the given example failed.
+        """
+        out(self._failure_header(test, example) +
+            self._checker.output_difference(example, got, self.optionflags))
+
+    def report_unexpected_exception(self, out, test, example, exc_info):
+        """
+        Report that the given example raised an unexpected exception.
+        """
+        out(self._failure_header(test, example) +
+            'Exception raised:\n' + _indent(_exception_traceback(exc_info)))
+
+    def _failure_header(self, test, example):
+        out = [self.DIVIDER]
+        if test.filename:
+            if test.lineno is not None and example.lineno is not None:
+                lineno = test.lineno + example.lineno + 1
+            else:
+                lineno = '?'
+            out.append('File "%s", line %s, in %s' %
+                       (test.filename, lineno, test.name))
+        else:
+            out.append('Line %s, in %s' % (example.lineno+1, test.name))
+        out.append('Failed example:')
+        source = example.source
+        out.append(_indent(source))
+        return '\n'.join(out)
+
+    #/////////////////////////////////////////////////////////////////
+    # DocTest Running
+    #/////////////////////////////////////////////////////////////////
+
+    def __run(self, test, compileflags, out):
+        """
+        Run the examples in `test`.  Write the outcome of each example
+        with one of the `DocTestRunner.report_*` methods, using the
+        writer function `out`.  `compileflags` is the set of compiler
+        flags that should be used to execute examples.  Return a tuple
+        `(f, t)`, where `t` is the number of examples tried, and `f`
+        is the number of examples that failed.  The examples are run
+        in the namespace `test.globs`.
+        """
+        # Keep track of the number of failures and tries.
+        failures = tries = 0
+
+        # Save the option flags (since option directives can be used
+        # to modify them).
+        original_optionflags = self.optionflags
+
+        SUCCESS, FAILURE, BOOM = range(3) # `outcome` state
+
+        check = self._checker.check_output
+
+        # Process each example.
+        for examplenum, example in enumerate(test.examples):
+
+            # If REPORT_ONLY_FIRST_FAILURE is set, then supress
+            # reporting after the first failure.
+            quiet = (self.optionflags & REPORT_ONLY_FIRST_FAILURE and
+                     failures > 0)
+
+            # Merge in the example's options.
+            self.optionflags = original_optionflags
+            if example.options:
+                for (optionflag, val) in example.options.items():
+                    if val:
+                        self.optionflags |= optionflag
+                    else:
+                        self.optionflags &= ~optionflag
+
+            # Record that we started this example.
+            tries += 1
+            if not quiet:
+                self.report_start(out, test, example)
+
+            # Use a special filename for compile(), so we can retrieve
+            # the source code during interactive debugging (see
+            # __patched_linecache_getlines).
+            filename = '<doctest %s[%d]>' % (test.name, examplenum)
+
+            # Run the example in the given context (globs), and record
+            # any exception that gets raised.  (But don't intercept
+            # keyboard interrupts.)
+            try:
+                # Don't blink!  This is where the user's code gets run.
+                exec compile(example.source, filename, "single",
+                             compileflags, 1) in test.globs
+                self.debugger.set_continue() # ==== Example Finished ====
+                exception = None
+            except KeyboardInterrupt:
+                raise
+            except:
+                exception = sys.exc_info()
+                self.debugger.set_continue() # ==== Example Finished ====
+
+            got = self._fakeout.getvalue()  # the actual output
+            self._fakeout.truncate(0)
+            outcome = FAILURE   # guilty until proved innocent or insane
+
+            # If the example executed without raising any exceptions,
+            # verify its output.
+            if exception is None:
+                if check(example.want, got, self.optionflags):
+                    outcome = SUCCESS
+
+            # The example raised an exception:  check if it was expected.
+            else:
+                exc_info = sys.exc_info()
+                exc_msg = traceback.format_exception_only(*exc_info[:2])[-1]
+                if not quiet:
+                    got += _exception_traceback(exc_info)
+
+                # If `example.exc_msg` is None, then we weren't expecting
+                # an exception.
+                if example.exc_msg is None:
+                    outcome = BOOM
+
+                # We expected an exception:  see whether it matches.
+                elif check(example.exc_msg, exc_msg, self.optionflags):
+                    outcome = SUCCESS
+
+                # Another chance if they didn't care about the detail.
+                elif self.optionflags & IGNORE_EXCEPTION_DETAIL:
+                    m1 = re.match(r'[^:]*:', example.exc_msg)
+                    m2 = re.match(r'[^:]*:', exc_msg)
+                    if m1 and m2 and check(m1.group(0), m2.group(0),
+                                           self.optionflags):
+                        outcome = SUCCESS
+
+            # Report the outcome.
+            if outcome is SUCCESS:
+                if not quiet:
+                    self.report_success(out, test, example, got)
+            elif outcome is FAILURE:
+                if not quiet:
+                    self.report_failure(out, test, example, got)
+                failures += 1
+            elif outcome is BOOM:
+                if not quiet:
+                    self.report_unexpected_exception(out, test, example,
+                                                     exc_info)
+                failures += 1
+            else:
+                assert False, ("unknown outcome", outcome)
+
+        # Restore the option flags (in case they were modified)
+        self.optionflags = original_optionflags
+
+        # Record and return the number of failures and tries.
+        self.__record_outcome(test, failures, tries)
+        return failures, tries
+
+    def __record_outcome(self, test, f, t):
+        """
+        Record the fact that the given DocTest (`test`) generated `f`
+        failures out of `t` tried examples.
+        """
+        f2, t2 = self._name2ft.get(test.name, (0,0))
+        self._name2ft[test.name] = (f+f2, t+t2)
+        self.failures += f
+        self.tries += t
+
+    __LINECACHE_FILENAME_RE = re.compile(r'<doctest '
+                                         r'(?P<name>[\w\.]+)'
+                                         r'\[(?P<examplenum>\d+)\]>$')
+    def __patched_linecache_getlines(self, filename, module_globals=None):
+        m = self.__LINECACHE_FILENAME_RE.match(filename)
+        if m and m.group('name') == self.test.name:
+            example = self.test.examples[int(m.group('examplenum'))]
+            return example.source.splitlines(True)
+        else:
+            return self.save_linecache_getlines(filename)#?, module_globals)
+
+    def run(self, test, compileflags=None, out=None, clear_globs=True):
+        """
+        Run the examples in `test`, and display the results using the
+        writer function `out`.
+
+        The examples are run in the namespace `test.globs`.  If
+        `clear_globs` is true (the default), then this namespace will
+        be cleared after the test runs, to help with garbage
+        collection.  If you would like to examine the namespace after
+        the test completes, then use `clear_globs=False`.
+
+        `compileflags` gives the set of flags that should be used by
+        the Python compiler when running the examples.  If not
+        specified, then it will default to the set of future-import
+        flags that apply to `globs`.
+
+        The output of each example is checked using
+        `DocTestRunner.check_output`, and the results are formatted by
+        the `DocTestRunner.report_*` methods.
+        """
+        self.test = test
+
+        if compileflags is None:
+            compileflags = _extract_future_flags(test.globs)
+
+        save_stdout = sys.stdout
+        if out is None:
+            out = save_stdout.write
+        sys.stdout = self._fakeout
+
+        # Patch pdb.set_trace to restore sys.stdout during interactive
+        # debugging (so it's not still redirected to self._fakeout).
+        # Note that the interactive output will go to *our*
+        # save_stdout, even if that's not the real sys.stdout; this
+        # allows us to write test cases for the set_trace behavior.
+        save_set_trace = pdb.set_trace
+        self.debugger = _OutputRedirectingPdb(save_stdout)
+        self.debugger.reset()
+        pdb.set_trace = self.debugger.set_trace
+
+        # Patch linecache.getlines, so we can see the example's source
+        # when we're inside the debugger.
+        self.save_linecache_getlines = linecache.getlines
+        linecache.getlines = self.__patched_linecache_getlines
+
+        try:
+            return self.__run(test, compileflags, out)
+        finally:
+            sys.stdout = save_stdout
+            pdb.set_trace = save_set_trace
+            linecache.getlines = self.save_linecache_getlines
+            if clear_globs:
+                test.globs.clear()
+
+    #/////////////////////////////////////////////////////////////////
+    # Summarization
+    #/////////////////////////////////////////////////////////////////
+    def summarize(self, verbose=None):
+        """
+        Print a summary of all the test cases that have been run by
+        this DocTestRunner, and return a tuple `(f, t)`, where `f` is
+        the total number of failed examples, and `t` is the total
+        number of tried examples.
+
+        The optional `verbose` argument controls how detailed the
+        summary is.  If the verbosity is not specified, then the
+        DocTestRunner's verbosity is used.
+        """
+        if verbose is None:
+            verbose = self._verbose
+        notests = []
+        passed = []
+        failed = []
+        totalt = totalf = 0
+        for x in self._name2ft.items():
+            name, (f, t) = x
+            assert f <= t
+            totalt += t
+            totalf += f
+            if t == 0:
+                notests.append(name)
+            elif f == 0:
+                passed.append( (name, t) )
+            else:
+                failed.append(x)
+        if verbose:
+            if notests:
+                print len(notests), "items had no tests:"
+                notests.sort()
+                for thing in notests:
+                    print "   ", thing
+            if passed:
+                print len(passed), "items passed all tests:"
+                passed.sort()
+                for thing, count in passed:
+                    print " %3d tests in %s" % (count, thing)
+        if failed:
+            print self.DIVIDER
+            print len(failed), "items had failures:"
+            failed.sort()
+            for thing, (f, t) in failed:
+                print " %3d of %3d in %s" % (f, t, thing)
+        if verbose:
+            print totalt, "tests in", len(self._name2ft), "items."
+            print totalt - totalf, "passed and", totalf, "failed."
+        if totalf:
+            print "***Test Failed***", totalf, "failures."
+        elif verbose:
+            print "Test passed."
+        return totalf, totalt
+
+    #/////////////////////////////////////////////////////////////////
+    # Backward compatibility cruft to maintain doctest.master.
+    #/////////////////////////////////////////////////////////////////
+    def merge(self, other):
+        d = self._name2ft
+        for name, (f, t) in other._name2ft.items():
+            if name in d:
+                print "*** DocTestRunner.merge: '" + name + "' in both" \
+                    " testers; summing outcomes."
+                f2, t2 = d[name]
+                f = f + f2
+                t = t + t2
+            d[name] = f, t
+
+class OutputChecker:
+    """
+    A class used to check the whether the actual output from a doctest
+    example matches the expected output.  `OutputChecker` defines two
+    methods: `check_output`, which compares a given pair of outputs,
+    and returns true if they match; and `output_difference`, which
+    returns a string describing the differences between two outputs.
+    """
+    def check_output(self, want, got, optionflags):
+        """
+        Return True iff the actual output from an example (`got`)
+        matches the expected output (`want`).  These strings are
+        always considered to match if they are identical; but
+        depending on what option flags the test runner is using,
+        several non-exact match types are also possible.  See the
+        documentation for `TestRunner` for more information about
+        option flags.
+        """
+        # Handle the common case first, for efficiency:
+        # if they're string-identical, always return true.
+        if got == want:
+            return True
+
+        # The values True and False replaced 1 and 0 as the return
+        # value for boolean comparisons in Python 2.3.
+        if not (optionflags & DONT_ACCEPT_TRUE_FOR_1):
+            if (got,want) == ("True\n", "1\n"):
+                return True
+            if (got,want) == ("False\n", "0\n"):
+                return True
+
+        # <BLANKLINE> can be used as a special sequence to signify a
+        # blank line, unless the DONT_ACCEPT_BLANKLINE flag is used.
+        if not (optionflags & DONT_ACCEPT_BLANKLINE):
+            # Replace <BLANKLINE> in want with a blank line.
+            want = re.sub('(?m)^%s\s*?$' % re.escape(BLANKLINE_MARKER),
+                          '', want)
+            # If a line in got contains only spaces, then remove the
+            # spaces.
+            got = re.sub('(?m)^\s*?$', '', got)
+            if got == want:
+                return True
+
+        # This flag causes doctest to ignore any differences in the
+        # contents of whitespace strings.  Note that this can be used
+        # in conjunction with the ELLIPSIS flag.
+        if optionflags & NORMALIZE_WHITESPACE:
+            got = ' '.join(got.split())
+            want = ' '.join(want.split())
+            if got == want:
+                return True
+
+        # The ELLIPSIS flag says to let the sequence "..." in `want`
+        # match any substring in `got`.
+        if optionflags & ELLIPSIS:
+            if _ellipsis_match(want, got):
+                return True
+
+        # We didn't find any match; return false.
+        return False
+
+    # Should we do a fancy diff?
+    def _do_a_fancy_diff(self, want, got, optionflags):
+        # Not unless they asked for a fancy diff.
+        if not optionflags & (REPORT_UDIFF |
+                              REPORT_CDIFF |
+                              REPORT_NDIFF):
+            return False
+
+        # If expected output uses ellipsis, a meaningful fancy diff is
+        # too hard ... or maybe not.  In two real-life failures Tim saw,
+        # a diff was a major help anyway, so this is commented out.
+        # [todo] _ellipsis_match() knows which pieces do and don't match,
+        # and could be the basis for a kick-ass diff in this case.
+        ##if optionflags & ELLIPSIS and ELLIPSIS_MARKER in want:
+        ##    return False
+
+        # ndiff does intraline difference marking, so can be useful even
+        # for 1-line differences.
+        if optionflags & REPORT_NDIFF:
+            return True
+
+        # The other diff types need at least a few lines to be helpful.
+        return want.count('\n') > 2 and got.count('\n') > 2
+
+    def output_difference(self, example, got, optionflags):
+        """
+        Return a string describing the differences between the
+        expected output for a given example (`example`) and the actual
+        output (`got`).  `optionflags` is the set of option flags used
+        to compare `want` and `got`.
+        """
+        want = example.want
+        # If <BLANKLINE>s are being used, then replace blank lines
+        # with <BLANKLINE> in the actual output string.
+        if not (optionflags & DONT_ACCEPT_BLANKLINE):
+            got = re.sub('(?m)^[ ]*(?=\n)', BLANKLINE_MARKER, got)
+
+        # Check if we should use diff.
+        if self._do_a_fancy_diff(want, got, optionflags):
+            # Split want & got into lines.
+            want_lines = want.splitlines(True)  # True == keep line ends
+            got_lines = got.splitlines(True)
+            # Use difflib to find their differences.
+            if optionflags & REPORT_UDIFF:
+                diff = difflib.unified_diff(want_lines, got_lines, n=2)
+                diff = list(diff)[2:] # strip the diff header
+                kind = 'unified diff with -expected +actual'
+            elif optionflags & REPORT_CDIFF:
+                diff = difflib.context_diff(want_lines, got_lines, n=2)
+                diff = list(diff)[2:] # strip the diff header
+                kind = 'context diff with expected followed by actual'
+            elif optionflags & REPORT_NDIFF:
+                engine = difflib.Differ(charjunk=difflib.IS_CHARACTER_JUNK)
+                diff = list(engine.compare(want_lines, got_lines))
+                kind = 'ndiff with -expected +actual'
+            else:
+                assert 0, 'Bad diff option'
+            # Remove trailing whitespace on diff output.
+            diff = [line.rstrip() + '\n' for line in diff]
+            return 'Differences (%s):\n' % kind + _indent(''.join(diff))
+
+        # If we're not using diff, then simply list the expected
+        # output followed by the actual output.
+        if want and got:
+            return 'Expected:\n%sGot:\n%s' % (_indent(want), _indent(got))
+        elif want:
+            return 'Expected:\n%sGot nothing\n' % _indent(want)
+        elif got:
+            return 'Expected nothing\nGot:\n%s' % _indent(got)
+        else:
+            return 'Expected nothing\nGot nothing\n'
+
+class DocTestFailure(Exception):
+    """A DocTest example has failed in debugging mode.
+
+    The exception instance has variables:
+
+    - test: the DocTest object being run
+
+    - excample: the Example object that failed
+
+    - got: the actual output
+    """
+    def __init__(self, test, example, got):
+        self.test = test
+        self.example = example
+        self.got = got
+
+    def __str__(self):
+        return str(self.test)
+
+class UnexpectedException(Exception):
+    """A DocTest example has encountered an unexpected exception
+
+    The exception instance has variables:
+
+    - test: the DocTest object being run
+
+    - excample: the Example object that failed
+
+    - exc_info: the exception info
+    """
+    def __init__(self, test, example, exc_info):
+        self.test = test
+        self.example = example
+        self.exc_info = exc_info
+
+    def __str__(self):
+        return str(self.test)
+
+class DebugRunner(DocTestRunner):
+    r"""Run doc tests but raise an exception as soon as there is a failure.
+
+       If an unexpected exception occurs, an UnexpectedException is raised.
+       It contains the test, the example, and the original exception:
+
+         >>> runner = DebugRunner(verbose=False)
+         >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+         ...                                    {}, 'foo', 'foo.py', 0)
+         >>> try:
+         ...     runner.run(test)
+         ... except UnexpectedException, failure:
+         ...     pass
+
+         >>> failure.test is test
+         True
+
+         >>> failure.example.want
+         '42\n'
+
+         >>> exc_info = failure.exc_info
+         >>> raise exc_info[0], exc_info[1], exc_info[2]
+         Traceback (most recent call last):
+         ...
+         KeyError
+
+       We wrap the original exception to give the calling application
+       access to the test and example information.
+
+       If the output doesn't match, then a DocTestFailure is raised:
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 1
+         ...      >>> x
+         ...      2
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> try:
+         ...    runner.run(test)
+         ... except DocTestFailure, failure:
+         ...    pass
+
+       DocTestFailure objects provide access to the test:
+
+         >>> failure.test is test
+         True
+
+       As well as to the example:
+
+         >>> failure.example.want
+         '2\n'
+
+       and the actual output:
+
+         >>> failure.got
+         '1\n'
+
+       If a failure or error occurs, the globals are left intact:
+
+         >>> del test.globs['__builtins__']
+         >>> test.globs
+         {'x': 1}
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 2
+         ...      >>> raise KeyError
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> runner.run(test)
+         Traceback (most recent call last):
+         ...
+         UnexpectedException: <DocTest foo from foo.py:0 (2 examples)>
+
+         >>> del test.globs['__builtins__']
+         >>> test.globs
+         {'x': 2}
+
+       But the globals are cleared if there is no error:
+
+         >>> test = DocTestParser().get_doctest('''
+         ...      >>> x = 2
+         ...      ''', {}, 'foo', 'foo.py', 0)
+
+         >>> runner.run(test)
+         (0, 1)
+
+         >>> test.globs
+         {}
+
+       """
+
+    def run(self, test, compileflags=None, out=None, clear_globs=True):
+        r = DocTestRunner.run(self, test, compileflags, out, False)
+        if clear_globs:
+            test.globs.clear()
+        return r
+
+    def report_unexpected_exception(self, out, test, example, exc_info):
+        raise UnexpectedException(test, example, exc_info)
+
+    def report_failure(self, out, test, example, got):
+        raise DocTestFailure(test, example, got)
+
+######################################################################
+## 6. Test Functions
+######################################################################
+# These should be backwards compatible.
+
+# For backward compatibility, a global instance of a DocTestRunner
+# class, updated by testmod.
+master = None
+
+def testmod(m=None, name=None, globs=None, verbose=None, isprivate=None,
+            report=True, optionflags=0, extraglobs=None,
+            raise_on_error=False, exclude_empty=False):
+    """m=None, name=None, globs=None, verbose=None, isprivate=None,
+       report=True, optionflags=0, extraglobs=None, raise_on_error=False,
+       exclude_empty=False
+
+    Test examples in docstrings in functions and classes reachable
+    from module m (or the current module if m is not supplied), starting
+    with m.__doc__.  Unless isprivate is specified, private names
+    are not skipped.
+
+    Also test examples reachable from dict m.__test__ if it exists and is
+    not None.  m.__test__ maps names to functions, classes and strings;
+    function and class docstrings are tested even if the name is private;
+    strings are tested directly, as if they were docstrings.
+
+    Return (#failures, #tests).
+
+    See doctest.__doc__ for an overview.
+
+    Optional keyword arg "name" gives the name of the module; by default
+    use m.__name__.
+
+    Optional keyword arg "globs" gives a dict to be used as the globals
+    when executing examples; by default, use m.__dict__.  A copy of this
+    dict is actually used for each docstring, so that each docstring's
+    examples start with a clean slate.
+
+    Optional keyword arg "extraglobs" gives a dictionary that should be
+    merged into the globals that are used to execute examples.  By
+    default, no extra globals are used.  This is new in 2.4.
+
+    Optional keyword arg "verbose" prints lots of stuff if true, prints
+    only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+    Optional keyword arg "report" prints a summary at the end when true,
+    else prints nothing at the end.  In verbose mode, the summary is
+    detailed, else very brief (in fact, empty if all tests passed).
+
+    Optional keyword arg "optionflags" or's together module constants,
+    and defaults to 0.  This is new in 2.3.  Possible values (see the
+    docs for details):
+
+        DONT_ACCEPT_TRUE_FOR_1
+        DONT_ACCEPT_BLANKLINE
+        NORMALIZE_WHITESPACE
+        ELLIPSIS
+        IGNORE_EXCEPTION_DETAIL
+        REPORT_UDIFF
+        REPORT_CDIFF
+        REPORT_NDIFF
+        REPORT_ONLY_FIRST_FAILURE
+
+    Optional keyword arg "raise_on_error" raises an exception on the
+    first unexpected exception or failure. This allows failures to be
+    post-mortem debugged.
+
+    Deprecated in Python 2.4:
+    Optional keyword arg "isprivate" specifies a function used to
+    determine whether a name is private.  The default function is
+    treat all functions as public.  Optionally, "isprivate" can be
+    set to doctest.is_private to skip over functions marked as private
+    using the underscore naming convention; see its docs for details.
+
+    Advanced tomfoolery:  testmod runs methods of a local instance of
+    class doctest.Tester, then merges the results into (or creates)
+    global Tester instance doctest.master.  Methods of doctest.master
+    can be called directly too, if you want to do something unusual.
+    Passing report=0 to testmod is especially useful then, to delay
+    displaying a summary.  Invoke doctest.master.summarize(verbose)
+    when you're done fiddling.
+    """
+    global master
+
+    if isprivate is not None:
+        warnings.warn("the isprivate argument is deprecated; "
+                      "examine DocTestFinder.find() lists instead",
+                      DeprecationWarning)
+
+    # If no module was given, then use __main__.
+    if m is None:
+        # DWA - m will still be None if this wasn't invoked from the command
+        # line, in which case the following TypeError is about as good an error
+        # as we should expect
+        m = sys.modules.get('__main__')
+
+    # Check that we were actually given a module.
+    if not inspect.ismodule(m):
+        raise TypeError("testmod: module required; %r" % (m,))
+
+    # If no name was given, then use the module's name.
+    if name is None:
+        name = m.__name__
+
+    # Find, parse, and run all tests in the given module.
+    finder = DocTestFinder(_namefilter=isprivate, exclude_empty=exclude_empty)
+
+    if raise_on_error:
+        runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+    else:
+        runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+    for test in finder.find(m, name, globs=globs, extraglobs=extraglobs):
+        runner.run(test)
+
+    if report:
+        runner.summarize()
+
+    if master is None:
+        master = runner
+    else:
+        master.merge(runner)
+
+    return runner.failures, runner.tries
+
+def testfile(filename, module_relative=True, name=None, package=None,
+             globs=None, verbose=None, report=True, optionflags=0,
+             extraglobs=None, raise_on_error=False, parser=DocTestParser()):
+    """
+    Test examples in the given file.  Return (#failures, #tests).
+
+    Optional keyword arg "module_relative" specifies how filenames
+    should be interpreted:
+
+      - If "module_relative" is True (the default), then "filename"
+         specifies a module-relative path.  By default, this path is
+         relative to the calling module's directory; but if the
+         "package" argument is specified, then it is relative to that
+         package.  To ensure os-independence, "filename" should use
+         "/" characters to separate path segments, and should not
+         be an absolute path (i.e., it may not begin with "/").
+
+      - If "module_relative" is False, then "filename" specifies an
+        os-specific path.  The path may be absolute or relative (to
+        the current working directory).
+
+    Optional keyword arg "name" gives the name of the test; by default
+    use the file's basename.
+
+    Optional keyword argument "package" is a Python package or the
+    name of a Python package whose directory should be used as the
+    base directory for a module relative filename.  If no package is
+    specified, then the calling module's directory is used as the base
+    directory for module relative filenames.  It is an error to
+    specify "package" if "module_relative" is False.
+
+    Optional keyword arg "globs" gives a dict to be used as the globals
+    when executing examples; by default, use {}.  A copy of this dict
+    is actually used for each docstring, so that each docstring's
+    examples start with a clean slate.
+
+    Optional keyword arg "extraglobs" gives a dictionary that should be
+    merged into the globals that are used to execute examples.  By
+    default, no extra globals are used.
+
+    Optional keyword arg "verbose" prints lots of stuff if true, prints
+    only failures if false; by default, it's true iff "-v" is in sys.argv.
+
+    Optional keyword arg "report" prints a summary at the end when true,
+    else prints nothing at the end.  In verbose mode, the summary is
+    detailed, else very brief (in fact, empty if all tests passed).
+
+    Optional keyword arg "optionflags" or's together module constants,
+    and defaults to 0.  Possible values (see the docs for details):
+
+        DONT_ACCEPT_TRUE_FOR_1
+        DONT_ACCEPT_BLANKLINE
+        NORMALIZE_WHITESPACE
+        ELLIPSIS
+        IGNORE_EXCEPTION_DETAIL
+        REPORT_UDIFF
+        REPORT_CDIFF
+        REPORT_NDIFF
+        REPORT_ONLY_FIRST_FAILURE
+
+    Optional keyword arg "raise_on_error" raises an exception on the
+    first unexpected exception or failure. This allows failures to be
+    post-mortem debugged.
+
+    Optional keyword arg "parser" specifies a DocTestParser (or
+    subclass) that should be used to extract tests from the files.
+
+    Advanced tomfoolery:  testmod runs methods of a local instance of
+    class doctest.Tester, then merges the results into (or creates)
+    global Tester instance doctest.master.  Methods of doctest.master
+    can be called directly too, if you want to do something unusual.
+    Passing report=0 to testmod is especially useful then, to delay
+    displaying a summary.  Invoke doctest.master.summarize(verbose)
+    when you're done fiddling.
+    """
+    global master
+
+    if package and not module_relative:
+        raise ValueError("Package may only be specified for module-"
+                         "relative paths.")
+
+    # Relativize the path
+    if module_relative:
+        package = _normalize_module(package)
+        filename = _module_relative_path(package, filename)
+
+    # If no name was given, then use the file's name.
+    if name is None:
+        name = os.path.basename(filename)
+
+    # Assemble the globals.
+    if globs is None:
+        globs = {}
+    else:
+        globs = globs.copy()
+    if extraglobs is not None:
+        globs.update(extraglobs)
+
+    if raise_on_error:
+        runner = DebugRunner(verbose=verbose, optionflags=optionflags)
+    else:
+        runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+
+    # Read the file, convert it to a test, and run it.
+    s = open(filename).read()
+    test = parser.get_doctest(s, globs, name, filename, 0)
+    runner.run(test)
+
+    if report:
+        runner.summarize()
+
+    if master is None:
+        master = runner
+    else:
+        master.merge(runner)
+
+    return runner.failures, runner.tries
+
+def run_docstring_examples(f, globs, verbose=False, name="NoName",
+                           compileflags=None, optionflags=0):
+    """
+    Test examples in the given object's docstring (`f`), using `globs`
+    as globals.  Optional argument `name` is used in failure messages.
+    If the optional argument `verbose` is true, then generate output
+    even if there are no failures.
+
+    `compileflags` gives the set of flags that should be used by the
+    Python compiler when running the examples.  If not specified, then
+    it will default to the set of future-import flags that apply to
+    `globs`.
+
+    Optional keyword arg `optionflags` specifies options for the
+    testing and output.  See the documentation for `testmod` for more
+    information.
+    """
+    # Find, parse, and run all tests in the given module.
+    finder = DocTestFinder(verbose=verbose, recurse=False)
+    runner = DocTestRunner(verbose=verbose, optionflags=optionflags)
+    for test in finder.find(f, name, globs=globs):
+        runner.run(test, compileflags=compileflags)
+
+######################################################################
+## 7. Tester
+######################################################################
+# This is provided only for backwards compatibility.  It's not
+# actually used in any way.
+
+class Tester:
+    def __init__(self, mod=None, globs=None, verbose=None,
+                 isprivate=None, optionflags=0):
+
+        warnings.warn("class Tester is deprecated; "
+                      "use class doctest.DocTestRunner instead",
+                      DeprecationWarning, stacklevel=2)
+        if mod is None and globs is None:
+            raise TypeError("Tester.__init__: must specify mod or globs")
+        if mod is not None and not inspect.ismodule(mod):
+            raise TypeError("Tester.__init__: mod must be a module; %r" %
+                            (mod,))
+        if globs is None:
+            globs = mod.__dict__
+        self.globs = globs
+
+        self.verbose = verbose
+        self.isprivate = isprivate
+        self.optionflags = optionflags
+        self.testfinder = DocTestFinder(_namefilter=isprivate)
+        self.testrunner = DocTestRunner(verbose=verbose,
+                                        optionflags=optionflags)
+
+    def runstring(self, s, name):
+        test = DocTestParser().get_doctest(s, self.globs, name, None, None)
+        if self.verbose:
+            print "Running string", name
+        (f,t) = self.testrunner.run(test)
+        if self.verbose:
+            print f, "of", t, "examples failed in string", name
+        return (f,t)
+
+    def rundoc(self, object, name=None, module=None):
+        f = t = 0
+        tests = self.testfinder.find(object, name, module=module,
+                                     globs=self.globs)
+        for test in tests:
+            (f2, t2) = self.testrunner.run(test)
+            (f,t) = (f+f2, t+t2)
+        return (f,t)
+
+    def rundict(self, d, name, module=None):
+        import new
+        m = new.module(name)
+        m.__dict__.update(d)
+        if module is None:
+            module = False
+        return self.rundoc(m, name, module)
+
+    def run__test__(self, d, name):
+        import new
+        m = new.module(name)
+        m.__test__ = d
+        return self.rundoc(m, name)
+
+    def summarize(self, verbose=None):
+        return self.testrunner.summarize(verbose)
+
+    def merge(self, other):
+        self.testrunner.merge(other.testrunner)
+
+######################################################################
+## 8. Unittest Support
+######################################################################
+
+_unittest_reportflags = 0
+
+def set_unittest_reportflags(flags):
+    """Sets the unittest option flags.
+
+    The old flag is returned so that a runner could restore the old
+    value if it wished to:
+
+      >>> old = _unittest_reportflags
+      >>> set_unittest_reportflags(REPORT_NDIFF |
+      ...                          REPORT_ONLY_FIRST_FAILURE) == old
+      True
+
+      >>> import doctest
+      >>> doctest._unittest_reportflags == (REPORT_NDIFF |
+      ...                                   REPORT_ONLY_FIRST_FAILURE)
+      True
+
+    Only reporting flags can be set:
+
+      >>> set_unittest_reportflags(ELLIPSIS)
+      Traceback (most recent call last):
+      ...
+      ValueError: ('Only reporting flags allowed', 8)
+
+      >>> set_unittest_reportflags(old) == (REPORT_NDIFF |
+      ...                                   REPORT_ONLY_FIRST_FAILURE)
+      True
+    """
+    global _unittest_reportflags
+
+    if (flags & REPORTING_FLAGS) != flags:
+        raise ValueError("Only reporting flags allowed", flags)
+    old = _unittest_reportflags
+    _unittest_reportflags = flags
+    return old
+
+
+class DocTestCase(unittest.TestCase):
+
+    def __init__(self, test, optionflags=0, setUp=None, tearDown=None,
+                 checker=None):
+
+        unittest.TestCase.__init__(self)
+        self._dt_optionflags = optionflags
+        self._dt_checker = checker
+        self._dt_test = test
+        self._dt_setUp = setUp
+        self._dt_tearDown = tearDown
+
+    def setUp(self):
+        test = self._dt_test
+
+        if self._dt_setUp is not None:
+            self._dt_setUp(test)
+
+    def tearDown(self):
+        test = self._dt_test
+
+        if self._dt_tearDown is not None:
+            self._dt_tearDown(test)
+
+        test.globs.clear()
+
+    def runTest(self):
+        test = self._dt_test
+        old = sys.stdout
+        new = StringIO()
+        optionflags = self._dt_optionflags
+
+        if not (optionflags & REPORTING_FLAGS):
+            # The option flags don't include any reporting flags,
+            # so add the default reporting flags
+            optionflags |= _unittest_reportflags
+
+        runner = DocTestRunner(optionflags=optionflags,
+                               checker=self._dt_checker, verbose=False)
+
+        try:
+            runner.DIVIDER = "-"*70
+            failures, tries = runner.run(
+                test, out=new.write, clear_globs=False)
+        finally:
+            sys.stdout = old
+
+        if failures:
+            raise self.failureException(self.format_failure(new.getvalue()))
+
+    def format_failure(self, err):
+        test = self._dt_test
+        if test.lineno is None:
+            lineno = 'unknown line number'
+        else:
+            lineno = '%s' % test.lineno
+        lname = '.'.join(test.name.split('.')[-1:])
+        return ('Failed doctest test for %s\n'
+                '  File "%s", line %s, in %s\n\n%s'
+                % (test.name, test.filename, lineno, lname, err)
+                )
+
+    def debug(self):
+        r"""Run the test case without results and without catching exceptions
+
+           The unit test framework includes a debug method on test cases
+           and test suites to support post-mortem debugging.  The test code
+           is run in such a way that errors are not caught.  This way a
+           caller can catch the errors and initiate post-mortem debugging.
+
+           The DocTestCase provides a debug method that raises
+           UnexpectedException errors if there is an unexepcted
+           exception:
+
+             >>> test = DocTestParser().get_doctest('>>> raise KeyError\n42',
+             ...                {}, 'foo', 'foo.py', 0)
+             >>> case = DocTestCase(test)
+             >>> try:
+             ...     case.debug()
+             ... except UnexpectedException, failure:
+             ...     pass
+
+           The UnexpectedException contains the test, the example, and
+           the original exception:
+
+             >>> failure.test is test
+             True
+
+             >>> failure.example.want
+             '42\n'
+
+             >>> exc_info = failure.exc_info
+             >>> raise exc_info[0], exc_info[1], exc_info[2]
+             Traceback (most recent call last):
+             ...
+             KeyError
+
+           If the output doesn't match, then a DocTestFailure is raised:
+
+             >>> test = DocTestParser().get_doctest('''
+             ...      >>> x = 1
+             ...      >>> x
+             ...      2
+             ...      ''', {}, 'foo', 'foo.py', 0)
+             >>> case = DocTestCase(test)
+
+             >>> try:
+             ...    case.debug()
+             ... except DocTestFailure, failure:
+             ...    pass
+
+           DocTestFailure objects provide access to the test:
+
+             >>> failure.test is test
+             True
+
+           As well as to the example:
+
+             >>> failure.example.want
+             '2\n'
+
+           and the actual output:
+
+             >>> failure.got
+             '1\n'
+
+           """
+
+        self.setUp()
+        runner = DebugRunner(optionflags=self._dt_optionflags,
+                             checker=self._dt_checker, verbose=False)
+        runner.run(self._dt_test)
+        self.tearDown()
+
+    def id(self):
+        return self._dt_test.name
+
+    def __repr__(self):
+        name = self._dt_test.name.split('.')
+        return "%s (%s)" % (name[-1], '.'.join(name[:-1]))
+
+    __str__ = __repr__
+
+    def shortDescription(self):
+        return "Doctest: " + self._dt_test.name
+
+def DocTestSuite(module=None, globs=None, extraglobs=None, test_finder=None,
+                 **options):
+    """
+    Convert doctest tests for a module to a unittest test suite.
+
+    This converts each documentation string in a module that
+    contains doctest tests to a unittest test case.  If any of the
+    tests in a doc string fail, then the test case fails.  An exception
+    is raised showing the name of the file containing the test and a
+    (sometimes approximate) line number.
+
+    The `module` argument provides the module to be tested.  The argument
+    can be either a module or a module name.
+
+    If no argument is given, the calling module is used.
+
+    A number of options may be provided as keyword arguments:
+
+    setUp
+      A set-up function.  This is called before running the
+      tests in each file. The setUp function will be passed a DocTest
+      object.  The setUp function can access the test globals as the
+      globs attribute of the test passed.
+
+    tearDown
+      A tear-down function.  This is called after running the
+      tests in each file.  The tearDown function will be passed a DocTest
+      object.  The tearDown function can access the test globals as the
+      globs attribute of the test passed.
+
+    globs
+      A dictionary containing initial global variables for the tests.
+
+    optionflags
+       A set of doctest option flags expressed as an integer.
+    """
+
+    if test_finder is None:
+        test_finder = DocTestFinder()
+
+    module = _normalize_module(module)
+    tests = test_finder.find(module, globs=globs, extraglobs=extraglobs)
+    if globs is None:
+        globs = module.__dict__
+    if not tests:
+        # Why do we want to do this? Because it reveals a bug that might
+        # otherwise be hidden.
+        raise ValueError(module, "has no tests")
+
+    tests.sort()
+    suite = unittest.TestSuite()
+    for test in tests:
+        if len(test.examples) == 0:
+            continue
+        if not test.filename:
+            filename = module.__file__
+            if filename[-4:] in (".pyc", ".pyo"):
+                filename = filename[:-1]
+            test.filename = filename
+        suite.addTest(DocTestCase(test, **options))
+
+    return suite
+
+class DocFileCase(DocTestCase):
+
+    def id(self):
+        return '_'.join(self._dt_test.name.split('.'))
+
+    def __repr__(self):
+        return self._dt_test.filename
+    __str__ = __repr__
+
+    def format_failure(self, err):
+        return ('Failed doctest test for %s\n  File "%s", line 0\n\n%s'
+                % (self._dt_test.name, self._dt_test.filename, err)
+                )
+
+def DocFileTest(path, module_relative=True, package=None,
+                globs=None, parser=DocTestParser(), **options):
+    if globs is None:
+        globs = {}
+
+    if package and not module_relative:
+        raise ValueError("Package may only be specified for module-"
+                         "relative paths.")
+
+    # Relativize the path.
+    if module_relative:
+        package = _normalize_module(package)
+        path = _module_relative_path(package, path)
+
+    # Find the file and read it.
+    name = os.path.basename(path)
+    doc = open(path).read()
+
+    # Convert it to a test, and wrap it in a DocFileCase.
+    test = parser.get_doctest(doc, globs, name, path, 0)
+    return DocFileCase(test, **options)
+
+def DocFileSuite(*paths, **kw):
+    """A unittest suite for one or more doctest files.
+
+    The path to each doctest file is given as a string; the
+    interpretation of that string depends on the keyword argument
+    "module_relative".
+
+    A number of options may be provided as keyword arguments:
+
+    module_relative
+      If "module_relative" is True, then the given file paths are
+      interpreted as os-independent module-relative paths.  By
+      default, these paths are relative to the calling module's
+      directory; but if the "package" argument is specified, then
+      they are relative to that package.  To ensure os-independence,
+      "filename" should use "/" characters to separate path
+      segments, and may not be an absolute path (i.e., it may not
+      begin with "/").
+
+      If "module_relative" is False, then the given file paths are
+      interpreted as os-specific paths.  These paths may be absolute
+      or relative (to the current working directory).
+
+    package
+      A Python package or the name of a Python package whose directory
+      should be used as the base directory for module relative paths.
+      If "package" is not specified, then the calling module's
+      directory is used as the base directory for module relative
+      filenames.  It is an error to specify "package" if
+      "module_relative" is False.
+
+    setUp
+      A set-up function.  This is called before running the
+      tests in each file. The setUp function will be passed a DocTest
+      object.  The setUp function can access the test globals as the
+      globs attribute of the test passed.
+
+    tearDown
+      A tear-down function.  This is called after running the
+      tests in each file.  The tearDown function will be passed a DocTest
+      object.  The tearDown function can access the test globals as the
+      globs attribute of the test passed.
+
+    globs
+      A dictionary containing initial global variables for the tests.
+
+    optionflags
+      A set of doctest option flags expressed as an integer.
+
+    parser
+      A DocTestParser (or subclass) that should be used to extract
+      tests from the files.
+    """
+    suite = unittest.TestSuite()
+
+    # We do this here so that _normalize_module is called at the right
+    # level.  If it were called in DocFileTest, then this function
+    # would be the caller and we might guess the package incorrectly.
+    if kw.get('module_relative', True):
+        kw['package'] = _normalize_module(kw.get('package'))
+
+    for path in paths:
+        suite.addTest(DocFileTest(path, **kw))
+
+    return suite
+
+######################################################################
+## 9. Debugging Support
+######################################################################
+
+def script_from_examples(s):
+    r"""Extract script from text with examples.
+
+       Converts text with examples to a Python script.  Example input is
+       converted to regular code.  Example output and all other words
+       are converted to comments:
+
+       >>> text = '''
+       ...       Here are examples of simple math.
+       ...
+       ...           Python has super accurate integer addition
+       ...
+       ...           >>> 2 + 2
+       ...           5
+       ...
+       ...           And very friendly error messages:
+       ...
+       ...           >>> 1/0
+       ...           To Infinity
+       ...           And
+       ...           Beyond
+       ...
+       ...           You can use logic if you want:
+       ...
+       ...           >>> if 0:
+       ...           ...    blah
+       ...           ...    blah
+       ...           ...
+       ...
+       ...           Ho hum
+       ...           '''
+
+       >>> print script_from_examples(text)
+       # Here are examples of simple math.
+       #
+       #     Python has super accurate integer addition
+       #
+       2 + 2
+       # Expected:
+       ## 5
+       #
+       #     And very friendly error messages:
+       #
+       1/0
+       # Expected:
+       ## To Infinity
+       ## And
+       ## Beyond
+       #
+       #     You can use logic if you want:
+       #
+       if 0:
+          blah
+          blah
+       #
+       #     Ho hum
+       """
+    output = []
+    for piece in DocTestParser().parse(s):
+        if isinstance(piece, Example):
+            # Add the example's source code (strip trailing NL)
+            output.append(piece.source[:-1])
+            # Add the expected output:
+            want = piece.want
+            if want:
+                output.append('# Expected:')
+                output += ['## '+l for l in want.split('\n')[:-1]]
+        else:
+            # Add non-example text.
+            output += [_comment_line(l)
+                       for l in piece.split('\n')[:-1]]
+
+    # Trim junk on both ends.
+    while output and output[-1] == '#':
+        output.pop()
+    while output and output[0] == '#':
+        output.pop(0)
+    # Combine the output, and return it.
+    return '\n'.join(output)
+
+def testsource(module, name):
+    """Extract the test sources from a doctest docstring as a script.
+
+    Provide the module (or dotted name of the module) containing the
+    test to be debugged and the name (within the module) of the object
+    with the doc string with tests to be debugged.
+    """
+    module = _normalize_module(module)
+    tests = DocTestFinder().find(module)
+    test = [t for t in tests if t.name == name]
+    if not test:
+        raise ValueError(name, "not found in tests")
+    test = test[0]
+    testsrc = script_from_examples(test.docstring)
+    return testsrc
+
+def debug_src(src, pm=False, globs=None):
+    """Debug a single doctest docstring, in argument `src`'"""
+    testsrc = script_from_examples(src)
+    debug_script(testsrc, pm, globs)
+
+def debug_script(src, pm=False, globs=None):
+    "Debug a test script.  `src` is the script, as a string."
+    import pdb
+
+    # Note that tempfile.NameTemporaryFile() cannot be used.  As the
+    # docs say, a file so created cannot be opened by name a second time
+    # on modern Windows boxes, and execfile() needs to open it.
+    srcfilename = tempfile.mktemp(".py", "doctestdebug")
+    f = open(srcfilename, 'w')
+    f.write(src)
+    f.close()
+
+    try:
+        if globs:
+            globs = globs.copy()
+        else:
+            globs = {}
+
+        if pm:
+            try:
+                execfile(srcfilename, globs, globs)
+            except:
+                print sys.exc_info()[1]
+                pdb.post_mortem(sys.exc_info()[2])
+        else:
+            # Note that %r is vital here.  '%s' instead can, e.g., cause
+            # backslashes to get treated as metacharacters on Windows.
+            pdb.run("execfile(%r)" % srcfilename, globs, globs)
+
+    finally:
+        os.remove(srcfilename)
+
+def debug(module, name, pm=False):
+    """Debug a single doctest docstring.
+
+    Provide the module (or dotted name of the module) containing the
+    test to be debugged and the name (within the module) of the object
+    with the docstring with tests to be debugged.
+    """
+    module = _normalize_module(module)
+    testsrc = testsource(module, name)
+    debug_script(testsrc, pm, module.__dict__)
+
+######################################################################
+## 10. Example Usage
+######################################################################
+class _TestClass:
+    """
+    A pointless class, for sanity-checking of docstring testing.
+
+    Methods:
+        square()
+        get()
+
+    >>> _TestClass(13).get() + _TestClass(-12).get()
+    1
+    >>> hex(_TestClass(13).square().get())
+    '0xa9'
+    """
+
+    def __init__(self, val):
+        """val -> _TestClass object with associated value val.
+
+        >>> t = _TestClass(123)
+        >>> print t.get()
+        123
+        """
+
+        self.val = val
+
+    def square(self):
+        """square() -> square TestClass's associated value
+
+        >>> _TestClass(13).square().get()
+        169
+        """
+
+        self.val = self.val ** 2
+        return self
+
+    def get(self):
+        """get() -> return TestClass's associated value.
+
+        >>> x = _TestClass(-42)
+        >>> print x.get()
+        -42
+        """
+
+        return self.val
+
+__test__ = {"_TestClass": _TestClass,
+            "string": r"""
+                      Example of a string object, searched as-is.
+                      >>> x = 1; y = 2
+                      >>> x + y, x * y
+                      (3, 2)
+                      """,
+
+            "bool-int equivalence": r"""
+                                    In 2.2, boolean expressions displayed
+                                    0 or 1.  By default, we still accept
+                                    them.  This can be disabled by passing
+                                    DONT_ACCEPT_TRUE_FOR_1 to the new
+                                    optionflags argument.
+                                    >>> 4 == 4
+                                    1
+                                    >>> 4 == 4
+                                    True
+                                    >>> 4 > 4
+                                    0
+                                    >>> 4 > 4
+                                    False
+                                    """,
+
+            "blank lines": r"""
+                Blank lines can be marked with <BLANKLINE>:
+                    >>> print 'foo\n\nbar\n'
+                    foo
+                    <BLANKLINE>
+                    bar
+                    <BLANKLINE>
+            """,
+
+            "ellipsis": r"""
+                If the ellipsis flag is used, then '...' can be used to
+                elide substrings in the desired output:
+                    >>> print range(1000) #doctest: +ELLIPSIS
+                    [0, 1, 2, ..., 999]
+            """,
+
+            "whitespace normalization": r"""
+                If the whitespace normalization flag is used, then
+                differences in whitespace are ignored.
+                    >>> print range(30) #doctest: +NORMALIZE_WHITESPACE
+                    [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+                     15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
+                     27, 28, 29]
+            """,
+           }
+
+def _test():
+    r = unittest.TextTestRunner()
+    r.run(DocTestSuite())
+
+if __name__ == "__main__":
+    _test()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/filemixin.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/filemixin.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/filemixin.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,53 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+class FileMixin(object):
+
+    """
+    Used to provide auxiliary methods to objects simulating files.
+    Objects must implement write, and read if they are input files.
+    Also they should implement close.
+
+    Other methods you may wish to override:
+    * flush()
+    * seek(offset[, whence])
+    * tell()
+    * truncate([size])
+
+    Attributes you may wish to provide:
+    * closed
+    * encoding (you should also respect that in write())
+    * mode
+    * newlines (hard to support)
+    * softspace
+    """
+
+    def flush(self):
+        pass
+
+    def next(self):
+        return self.readline()
+
+    def readline(self, size=None):
+        # @@: This is a lame implementation; but a buffer would probably
+        # be necessary for a better implementation
+        output = []
+        while 1:
+            next = self.read(1)
+            if not next:
+                return ''.join(output)
+            output.append(next)
+            if size and size > 0 and len(output) >= size:
+                return ''.join(output)
+            if next == '\n':
+                # @@: also \r?
+                return ''.join(output)
+
+    def xreadlines(self):
+        return self
+
+    def writelines(self, lines):
+        for line in lines:
+            self.write(line)
+
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/finddata.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/finddata.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/finddata.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,99 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# Note: you may want to copy this into your setup.py file verbatim, as
+# you can't import this from another package, when you don't know if
+# that package is installed yet.
+
+import os
+import sys
+from fnmatch import fnmatchcase
+from distutils.util import convert_path
+
+# Provided as an attribute, so you can append to these instead
+# of replicating them:
+standard_exclude = ('*.py', '*.pyc', '*$py.class', '*~', '.*', '*.bak')
+standard_exclude_directories = ('.*', 'CVS', '_darcs', './build',
+                                './dist', 'EGG-INFO', '*.egg-info')
+
+def find_package_data(
+    where='.', package='',
+    exclude=standard_exclude,
+    exclude_directories=standard_exclude_directories,
+    only_in_packages=True,
+    show_ignored=False):
+    """
+    Return a dictionary suitable for use in ``package_data``
+    in a distutils ``setup.py`` file.
+
+    The dictionary looks like::
+
+        {'package': [files]}
+
+    Where ``files`` is a list of all the files in that package that
+    don't match anything in ``exclude``.
+
+    If ``only_in_packages`` is true, then top-level directories that
+    are not packages won't be included (but directories under packages
+    will).
+
+    Directories matching any pattern in ``exclude_directories`` will
+    be ignored; by default directories with leading ``.``, ``CVS``,
+    and ``_darcs`` will be ignored.
+
+    If ``show_ignored`` is true, then all the files that aren't
+    included in package data are shown on stderr (for debugging
+    purposes).
+
+    Note patterns use wildcards, or can be exact paths (including
+    leading ``./``), and all searching is case-insensitive.
+    """
+    
+    out = {}
+    stack = [(convert_path(where), '', package, only_in_packages)]
+    while stack:
+        where, prefix, package, only_in_packages = stack.pop(0)
+        for name in os.listdir(where):
+            fn = os.path.join(where, name)
+            if os.path.isdir(fn):
+                bad_name = False
+                for pattern in exclude_directories:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "Directory %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                if (os.path.isfile(os.path.join(fn, '__init__.py'))
+                    and not prefix):
+                    if not package:
+                        new_package = name
+                    else:
+                        new_package = package + '.' + name
+                    stack.append((fn, '', new_package, False))
+                else:
+                    stack.append((fn, prefix + name + '/', package, only_in_packages))
+            elif package or not only_in_packages:
+                # is a file
+                bad_name = False
+                for pattern in exclude:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "File %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                out.setdefault(package, []).append(prefix+name)
+    return out
+
+if __name__ == '__main__':
+    import pprint
+    pprint.pprint(
+        find_package_data(show_ignored=True))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/findpackage.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/findpackage.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/findpackage.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,26 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+import sys
+import os
+
+def find_package(dir):
+    """
+    Given a directory, finds the equivalent package name.  If it
+    is directly in sys.path, returns ''.
+    """
+    dir = os.path.abspath(dir)
+    orig_dir = dir
+    path = map(os.path.abspath, sys.path)
+    packages = []
+    last_dir = None
+    while 1:
+        if dir in path:
+            return '.'.join(packages)
+        packages.insert(0, os.path.basename(dir))
+        dir = os.path.dirname(dir)
+        if last_dir == dir:
+            raise ValueError(
+                "%s is not under any path found in sys.path" % orig_dir)
+        last_dir = dir
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/import_string.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/import_string.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/import_string.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,95 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+'imports' a string -- converts a string to a Python object, importing
+any necessary modules and evaluating the expression.  Everything
+before the : in an import expression is the module path; everything
+after is an expression to be evaluated in the namespace of that
+module.
+
+Alternately, if no : is present, then import the modules and get the
+attributes as necessary.  Arbitrary expressions are not allowed in
+that case.
+"""
+
+def eval_import(s):
+    """
+    Import a module, or import an object from a module.
+
+    A module name like ``foo.bar:baz()`` can be used, where
+    ``foo.bar`` is the module, and ``baz()`` is an expression
+    evaluated in the context of that module.  Note this is not safe on
+    arbitrary strings because of the eval.
+    """
+    if ':' not in s:
+        return simple_import(s)
+    module_name, expr = s.split(':', 1)
+    module = import_module(module_name)
+    obj = eval(expr, module.__dict__)
+    return obj
+
+def simple_import(s):
+    """
+    Import a module, or import an object from a module.
+
+    A name like ``foo.bar.baz`` can be a module ``foo.bar.baz`` or a
+    module ``foo.bar`` with an object ``baz`` in it, or a module
+    ``foo`` with an object ``bar`` with an attribute ``baz``.
+    """
+    parts = s.split('.')
+    module = import_module(parts[0])
+    name = parts[0]
+    parts = parts[1:]
+    last_import_error = None
+    while parts:
+        name += '.' + parts[0]
+        try:
+            module = import_module(name)
+            parts = parts[1:]
+        except ImportError, e:
+            last_import_error = e
+            break
+    obj = module
+    while parts:
+        try:
+            obj = getattr(module, parts[0])
+        except AttributeError:
+            raise ImportError(
+                "Cannot find %s in module %r (stopped importing modules with error %s)" % (parts[0], module, last_import_error))
+        parts = parts[1:]
+    return obj
+
+def import_module(s):
+    """
+    Import a module.
+    """
+    mod = __import__(s)
+    parts = s.split('.')
+    for part in parts[1:]:
+        mod = getattr(mod, part)
+    return mod
+
+def try_import_module(module_name):
+    """
+    Imports a module, but catches import errors.  Only catches errors
+    when that module doesn't exist; if that module itself has an
+    import error it will still get raised.  Returns None if the module
+    doesn't exist.
+    """
+    try:
+        return import_module(module_name)
+    except ImportError, e:
+        if not getattr(e, 'args', None):
+            raise
+        desc = e.args[0]
+        if not desc.startswith('No module named '):
+            raise
+        desc = desc[len('No module named '):]
+        # If you import foo.bar.baz, the bad import could be any
+        # of foo.bar.baz, bar.baz, or baz; we'll test them all:
+        parts = module_name.split('.')
+        for i in range(len(parts)):
+            if desc == '.'.join(parts[i:]):
+                return None
+        raise

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/intset.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/intset.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/intset.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,511 @@
+# -*- coding: iso-8859-15 -*-
+"""Immutable integer set type.
+
+Integer set class.
+
+Copyright (C) 2006, Heiko Wundram.
+Released under the MIT license.
+"""
+
+# Version information
+# -------------------
+
+__author__ = "Heiko Wundram <me at modelnine.org>"
+__version__ = "0.2"
+__revision__ = "6"
+__date__ = "2006-01-20"
+
+
+# Utility classes
+# ---------------
+
+class _Infinity(object):
+    """Internal type used to represent infinity values."""
+
+    __slots__ = ["_neg"]
+
+    def __init__(self,neg):
+        self._neg = neg
+
+    def __lt__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return ( self._neg and
+                 not ( isinstance(value,_Infinity) and value._neg ) )
+
+    def __le__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return self._neg
+
+    def __gt__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return not ( self._neg or
+                     ( isinstance(value,_Infinity) and not value._neg ) )
+
+    def __ge__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return not self._neg
+
+    def __eq__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return isinstance(value,_Infinity) and self._neg == value._neg
+
+    def __ne__(self,value):
+        if not isinstance(value,(int,long,_Infinity)):
+            return NotImplemented
+        return not isinstance(value,_Infinity) or self._neg <> value._neg
+
+    def __repr__(self):
+        return "None"
+
+
+# Constants
+# ---------
+
+_MININF = _Infinity(True)
+_MAXINF = _Infinity(False)
+
+
+# Integer set class
+# -----------------
+
+class IntSet(object):
+    """Integer set class with efficient storage in a RLE format of ranges.
+    Supports minus and plus infinity in the range."""
+
+    __slots__ = ["_ranges","_min","_max","_hash"]
+
+    def __init__(self,*args,**kwargs):
+        """Initialize an integer set. The constructor accepts an unlimited
+        number of arguments that may either be tuples in the form of
+        (start,stop) where either start or stop may be a number or None to
+        represent maximum/minimum in that direction. The range specified by
+        (start,stop) is always inclusive (differing from the builtin range
+        operator).
+
+        Keyword arguments that can be passed to an integer set are min and
+        max, which specify the minimum and maximum number in the set,
+        respectively. You can also pass None here to represent minus or plus
+        infinity, which is also the default.
+        """
+
+        # Special case copy constructor.
+        if len(args) == 1 and isinstance(args[0],IntSet):
+            if kwargs:
+                raise ValueError("No keyword arguments for copy constructor.")
+            self._min = args[0]._min
+            self._max = args[0]._max
+            self._ranges = args[0]._ranges
+            self._hash = args[0]._hash
+            return
+
+        # Initialize set.
+        self._ranges = []
+
+        # Process keyword arguments.
+        self._min = kwargs.pop("min",_MININF)
+        self._max = kwargs.pop("max",_MAXINF)
+        if self._min is None:
+            self._min = _MININF
+        if self._max is None:
+            self._max = _MAXINF
+
+        # Check keyword arguments.
+        if kwargs:
+            raise ValueError("Invalid keyword argument.")
+        if not ( isinstance(self._min,(int,long)) or self._min is _MININF ):
+            raise TypeError("Invalid type of min argument.")
+        if not ( isinstance(self._max,(int,long)) or self._max is _MAXINF ):
+            raise TypeError("Invalid type of max argument.")
+        if ( self._min is not _MININF and self._max is not _MAXINF and
+             self._min > self._max ):
+            raise ValueError("Minimum is not smaller than maximum.")
+        if isinstance(self._max,(int,long)):
+            self._max += 1
+
+        # Process arguments.
+        for arg in args:
+            if isinstance(arg,(int,long)):
+                start, stop = arg, arg+1
+            elif isinstance(arg,tuple):
+                if len(arg) <> 2:
+                    raise ValueError("Invalid tuple, must be (start,stop).")
+
+                # Process argument.
+                start, stop = arg
+                if start is None:
+                    start = self._min
+                if stop is None:
+                    stop = self._max
+
+                # Check arguments.
+                if not ( isinstance(start,(int,long)) or start is _MININF ):
+                    raise TypeError("Invalid type of tuple start.")
+                if not ( isinstance(stop,(int,long)) or stop is _MAXINF ):
+                    raise TypeError("Invalid type of tuple stop.")
+                if ( start is not _MININF and stop is not _MAXINF and
+                     start > stop ):
+                    continue
+                if isinstance(stop,(int,long)):
+                    stop += 1
+            else:
+                raise TypeError("Invalid argument.")
+
+            if start > self._max:
+                continue
+            elif start < self._min:
+                start = self._min
+            if stop < self._min:
+                continue
+            elif stop > self._max:
+                stop = self._max
+            self._ranges.append((start,stop))
+
+        # Normalize set.
+        self._normalize()
+
+    # Utility functions for set operations
+    # ------------------------------------
+
+    def _iterranges(self,r1,r2,minval=_MININF,maxval=_MAXINF):
+        curval = minval
+        curstates = {"r1":False,"r2":False}
+        imax, jmax = 2*len(r1), 2*len(r2)
+        i, j = 0, 0
+        while i < imax or j < jmax:
+            if i < imax and ( ( j < jmax and
+                                r1[i>>1][i&1] < r2[j>>1][j&1] ) or
+                              j == jmax ):
+                cur_r, newname, newstate = r1[i>>1][i&1], "r1", not (i&1)
+                i += 1
+            else:
+                cur_r, newname, newstate = r2[j>>1][j&1], "r2", not (j&1)
+                j += 1
+            if curval < cur_r:
+                if cur_r > maxval:
+                    break
+                yield curstates, (curval,cur_r)
+                curval = cur_r
+            curstates[newname] = newstate
+        if curval < maxval:
+            yield curstates, (curval,maxval)
+
+    def _normalize(self):
+        self._ranges.sort()
+        i = 1
+        while i < len(self._ranges):
+            if self._ranges[i][0] < self._ranges[i-1][1]:
+                self._ranges[i-1] = (self._ranges[i-1][0],
+                                     max(self._ranges[i-1][1],
+                                         self._ranges[i][1]))
+                del self._ranges[i]
+            else:
+                i += 1
+        self._ranges = tuple(self._ranges)
+        self._hash = hash(self._ranges)
+
+    def __coerce__(self,other):
+        if isinstance(other,IntSet):
+            return self, other
+        elif isinstance(other,(int,long,tuple)):
+            try:
+                return self, self.__class__(other)
+            except TypeError:
+                # Catch a type error, in that case the structure specified by
+                # other is something we can't coerce, return NotImplemented.
+                # ValueErrors are not caught, they signal that the data was
+                # invalid for the constructor. This is appropriate to signal
+                # as a ValueError to the caller.
+                return NotImplemented
+        elif isinstance(other,list):
+            try:
+                return self, self.__class__(*other)
+            except TypeError:
+                # See above.
+                return NotImplemented
+        return NotImplemented
+
+    # Set function definitions
+    # ------------------------
+
+    def _make_function(name,type,doc,pall,pany=None):
+        """Makes a function to match two ranges. Accepts two types: either
+        'set', which defines a function which returns a set with all ranges
+        matching pall (pany is ignored), or 'bool', which returns True if pall
+        matches for all ranges and pany matches for any one range. doc is the
+        dostring to give this function. pany may be none to ignore the any
+        match.
+
+        The predicates get a dict with two keys, 'r1', 'r2', which denote
+        whether the current range is present in range1 (self) and/or range2
+        (other) or none of the two, respectively."""
+
+        if type == "set":
+            def f(self,other):
+                coerced = self.__coerce__(other)
+                if coerced is NotImplemented:
+                    return NotImplemented
+                other = coerced[1]
+                newset = self.__class__.__new__(self.__class__)
+                newset._min = min(self._min,other._min)
+                newset._max = max(self._max,other._max)
+                newset._ranges = []
+                for states, (start,stop) in \
+                        self._iterranges(self._ranges,other._ranges,
+                                         newset._min,newset._max):
+                    if pall(states):
+                        if newset._ranges and newset._ranges[-1][1] == start:
+                            newset._ranges[-1] = (newset._ranges[-1][0],stop)
+                        else:
+                            newset._ranges.append((start,stop))
+                newset._ranges = tuple(newset._ranges)
+                newset._hash = hash(self._ranges)
+                return newset
+        elif type == "bool":
+            def f(self,other):
+                coerced = self.__coerce__(other)
+                if coerced is NotImplemented:
+                    return NotImplemented
+                other = coerced[1]
+                _min = min(self._min,other._min)
+                _max = max(self._max,other._max)
+                found = not pany
+                for states, (start,stop) in \
+                        self._iterranges(self._ranges,other._ranges,_min,_max):
+                    if not pall(states):
+                        return False
+                    found = found or pany(states)
+                return found
+        else:
+            raise ValueError("Invalid type of function to create.")
+        try:
+            f.func_name = name
+        except TypeError:
+            pass
+        f.func_doc = doc
+        return f
+
+    # Intersection.
+    __and__ = _make_function("__and__","set",
+                             "Intersection of two sets as a new set.",
+                             lambda s: s["r1"] and s["r2"])
+    __rand__ = _make_function("__rand__","set",
+                              "Intersection of two sets as a new set.",
+                              lambda s: s["r1"] and s["r2"])
+    intersection = _make_function("intersection","set",
+                                  "Intersection of two sets as a new set.",
+                                  lambda s: s["r1"] and s["r2"])
+
+    # Union.
+    __or__ = _make_function("__or__","set",
+                            "Union of two sets as a new set.",
+                            lambda s: s["r1"] or s["r2"])
+    __ror__ = _make_function("__ror__","set",
+                             "Union of two sets as a new set.",
+                             lambda s: s["r1"] or s["r2"])
+    union = _make_function("union","set",
+                           "Union of two sets as a new set.",
+                           lambda s: s["r1"] or s["r2"])
+
+    # Difference.
+    __sub__ = _make_function("__sub__","set",
+                             "Difference of two sets as a new set.",
+                             lambda s: s["r1"] and not s["r2"])
+    __rsub__ = _make_function("__rsub__","set",
+                              "Difference of two sets as a new set.",
+                              lambda s: s["r2"] and not s["r1"])
+    difference = _make_function("difference","set",
+                                "Difference of two sets as a new set.",
+                                lambda s: s["r1"] and not s["r2"])
+
+    # Symmetric difference.
+    __xor__ = _make_function("__xor__","set",
+                             "Symmetric difference of two sets as a new set.",
+                             lambda s: s["r1"] ^ s["r2"])
+    __rxor__ = _make_function("__rxor__","set",
+                              "Symmetric difference of two sets as a new set.",
+                              lambda s: s["r1"] ^ s["r2"])
+    symmetric_difference = _make_function("symmetric_difference","set",
+                                          "Symmetric difference of two sets as a new set.",
+                                          lambda s: s["r1"] ^ s["r2"])
+
+    # Containership testing.
+    __contains__ = _make_function("__contains__","bool",
+                                  "Returns true if self is superset of other.",
+                                  lambda s: s["r1"] or not s["r2"])
+    issubset = _make_function("issubset","bool",
+                              "Returns true if self is subset of other.",
+                              lambda s: s["r2"] or not s["r1"])
+    istruesubset = _make_function("istruesubset","bool",
+                                  "Returns true if self is true subset of other.",
+                                  lambda s: s["r2"] or not s["r1"],
+                                  lambda s: s["r2"] and not s["r1"])
+    issuperset = _make_function("issuperset","bool",
+                                "Returns true if self is superset of other.",
+                                lambda s: s["r1"] or not s["r2"])
+    istruesuperset = _make_function("istruesuperset","bool",
+                                    "Returns true if self is true superset of other.",
+                                    lambda s: s["r1"] or not s["r2"],
+                                    lambda s: s["r1"] and not s["r2"])
+    overlaps = _make_function("overlaps","bool",
+                              "Returns true if self overlaps with other.",
+                              lambda s: True,
+                              lambda s: s["r1"] and s["r2"])
+
+    # Comparison.
+    __eq__ = _make_function("__eq__","bool",
+                            "Returns true if self is equal to other.",
+                            lambda s: not ( s["r1"] ^ s["r2"] ))
+    __ne__ = _make_function("__ne__","bool",
+                            "Returns true if self is different to other.",
+                            lambda s: True,
+                            lambda s: s["r1"] ^ s["r2"])
+
+    # Clean up namespace.
+    del _make_function
+
+    # Define other functions.
+    def inverse(self):
+        """Inverse of set as a new set."""
+
+        newset = self.__class__.__new__(self.__class__)
+        newset._min = self._min
+        newset._max = self._max
+        newset._ranges = []
+        laststop = self._min
+        for r in self._ranges:
+            if laststop < r[0]:
+                newset._ranges.append((laststop,r[0]))
+                laststop = r[1]
+        if laststop < self._max:
+            newset._ranges.append((laststop,self._max))
+        return newset
+
+    __invert__ = inverse
+
+    # Hashing
+    # -------
+
+    def __hash__(self):
+        """Returns a hash value representing this integer set. As the set is
+        always stored normalized, the hash value is guaranteed to match for
+        matching ranges."""
+
+        return self._hash
+
+    # Iterating
+    # ---------
+
+    def __len__(self):
+        """Get length of this integer set. In case the length is larger than
+        2**31 (including infinitely sized integer sets), it raises an
+        OverflowError. This is due to len() restricting the size to
+        0 <= len < 2**31."""
+
+        if not self._ranges:
+            return 0
+        if self._ranges[0][0] is _MININF or self._ranges[-1][1] is _MAXINF:
+            raise OverflowError("Infinitely sized integer set.")
+        rlen = 0
+        for r in self._ranges:
+            rlen += r[1]-r[0]
+        if rlen >= 2**31:
+            raise OverflowError("Integer set bigger than 2**31.")
+        return rlen
+
+    def len(self):
+        """Returns the length of this integer set as an integer. In case the
+        length is infinite, returns -1. This function exists because of a
+        limitation of the builtin len() function which expects values in
+        the range 0 <= len < 2**31. Use this function in case your integer
+        set might be larger."""
+
+        if not self._ranges:
+            return 0
+        if self._ranges[0][0] is _MININF or self._ranges[-1][1] is _MAXINF:
+            return -1
+        rlen = 0
+        for r in self._ranges:
+            rlen += r[1]-r[0]
+        return rlen
+
+    def __nonzero__(self):
+        """Returns true if this integer set contains at least one item."""
+
+        return bool(self._ranges)
+
+    def __iter__(self):
+        """Iterate over all values in this integer set. Iteration always starts
+        by iterating from lowest to highest over the ranges that are bounded.
+        After processing these, all ranges that are unbounded (maximum 2) are
+        yielded intermixed."""
+
+        ubranges = []
+        for r in self._ranges:
+            if r[0] is _MININF:
+                if r[1] is _MAXINF:
+                    ubranges.extend(([0,1],[-1,-1]))
+                else:
+                    ubranges.append([r[1]-1,-1])
+            elif r[1] is _MAXINF:
+                ubranges.append([r[0],1])
+            else:
+                for val in xrange(r[0],r[1]):
+                    yield val
+        if ubranges:
+            while True:
+                for ubrange in ubranges:
+                    yield ubrange[0]
+                    ubrange[0] += ubrange[1]
+
+    # Printing
+    # --------
+
+    def __repr__(self):
+        """Return a representation of this integer set. The representation is
+        executable to get an equal integer set."""
+
+        rv = []
+        for start, stop in self._ranges:
+            if ( isinstance(start,(int,long)) and isinstance(stop,(int,long))
+                 and stop-start == 1 ):
+                rv.append("%r" % start)
+            elif isinstance(stop,(int,long)):
+                rv.append("(%r,%r)" % (start,stop-1))
+            else:
+                rv.append("(%r,%r)" % (start,stop))
+        if self._min is not _MININF:
+            rv.append("min=%r" % self._min)
+        if self._max is not _MAXINF:
+            rv.append("max=%r" % self._max)
+        return "%s(%s)" % (self.__class__.__name__,",".join(rv))
+
+if __name__ == "__main__":
+    # Little test script demonstrating functionality.
+    x = IntSet((10,20),30)
+    y = IntSet((10,20))
+    z = IntSet((10,20),30,(15,19),min=0,max=40)
+    print x
+    print x&110
+    print x|110
+    print x^(15,25)
+    print x-12
+    print 12 in x
+    print x.issubset(x)
+    print y.issubset(x)
+    print x.istruesubset(x)
+    print y.istruesubset(x)
+    for val in x:
+        print val
+    print x.inverse()
+    print x == z
+    print x == y
+    print x <> y
+    print hash(x)
+    print hash(z)
+    print len(x)
+    print x.len()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/ip4.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/ip4.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/ip4.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,273 @@
+# -*- coding: iso-8859-15 -*-
+"""IP4 address range set implementation.
+
+Implements an IPv4-range type.
+
+Copyright (C) 2006, Heiko Wundram.
+Released under the MIT-license.
+"""
+
+# Version information
+# -------------------
+
+__author__ = "Heiko Wundram <me at modelnine.org>"
+__version__ = "0.2"
+__revision__ = "3"
+__date__ = "2006-01-20"
+
+
+# Imports
+# -------
+
+import intset
+import socket
+
+
+# IP4Range class
+# --------------
+
+class IP4Range(intset.IntSet):
+    """IP4 address range class with efficient storage of address ranges.
+    Supports all set operations."""
+
+    _MINIP4 = 0
+    _MAXIP4 = (1<<32) - 1
+    _UNITYTRANS = "".join([chr(n) for n in range(256)])
+    _IPREMOVE = "0123456789."
+
+    def __init__(self,*args):
+        """Initialize an ip4range class. The constructor accepts an unlimited
+        number of arguments that may either be tuples in the form (start,stop),
+        integers, longs or strings, where start and stop in a tuple may
+        also be of the form integer, long or string.
+
+        Passing an integer or long means passing an IPv4-address that's already
+        been converted to integer notation, whereas passing a string specifies
+        an address where this conversion still has to be done. A string
+        address may be in the following formats:
+
+        - 1.2.3.4    - a plain address, interpreted as a single address
+        - 1.2.3      - a set of addresses, interpreted as 1.2.3.0-1.2.3.255
+        - localhost  - hostname to look up, interpreted as single address
+        - 1.2.3<->5  - a set of addresses, interpreted as 1.2.3.0-1.2.5.255
+        - 1.2.0.0/16 - a set of addresses, interpreted as 1.2.0.0-1.2.255.255
+
+        Only the first three notations are valid if you use a string address in
+        a tuple, whereby notation 2 is interpreted as 1.2.3.0 if specified as
+        lower bound and 1.2.3.255 if specified as upper bound, not as a range
+        of addresses.
+
+        Specifying a range is done with the <-> operator. This is necessary
+        because '-' might be present in a hostname. '<->' shouldn't be, ever.
+        """
+
+        # Special case copy constructor.
+        if len(args) == 1 and isinstance(args[0],IP4Range):
+            super(IP4Range,self).__init__(args[0])
+            return
+
+        # Convert arguments to tuple syntax.
+        args = list(args)
+        for i in range(len(args)):
+            argval = args[i]
+            if isinstance(argval,str):
+                if "<->" in argval:
+                    # Type 4 address.
+                    args[i] = self._parseRange(*argval.split("<->",1))
+                    continue
+                elif "/" in argval:
+                    # Type 5 address.
+                    args[i] = self._parseMask(*argval.split("/",1))
+                else:
+                    # Type 1, 2 or 3.
+                    args[i] = self._parseAddrRange(argval)
+            elif isinstance(argval,tuple):
+                if len(tuple) <> 2:
+                    raise ValueError("Tuple is of invalid length.")
+                addr1, addr2 = argval
+                if isinstance(addr1,str):
+                    addr1 = self._parseAddrRange(addr1)[0]
+                elif not isinstance(addr1,(int,long)):
+                    raise TypeError("Invalid argument.")
+                if isinstance(addr2,str):
+                    addr2 = self._parseAddrRange(addr2)[1]
+                elif not isinstance(addr2,(int,long)):
+                    raise TypeError("Invalid argument.")
+                args[i] = (addr1,addr2)
+            elif not isinstance(argval,(int,long)):
+                raise TypeError("Invalid argument.")
+
+        # Initialize the integer set.
+        super(IP4Range,self).__init__(min=self._MINIP4,max=self._MAXIP4,*args)
+
+    # Parsing functions
+    # -----------------
+
+    def _parseRange(self,addr1,addr2):
+        naddr1, naddr1len = _parseAddr(addr1)
+        naddr2, naddr2len = _parseAddr(addr2)
+        if naddr2len < naddr1len:
+            naddr2 += naddr1&(((1<<((naddr1len-naddr2len)*8))-1)<<
+                              (naddr2len*8))
+            naddr2len = naddr1len
+        elif naddr2len > naddr1len:
+            raise ValueError("Range has more dots than address.")
+        naddr1 <<= (4-naddr1len)*8
+        naddr2 <<= (4-naddr2len)*8
+        naddr2 += (1<<((4-naddr2len)*8))-1
+        return (naddr1,naddr2)
+
+    def _parseMask(self,addr,mask):
+        naddr, naddrlen = _parseAddr(addr)
+        naddr <<= (4-naddrlen)*8
+        try:
+            if not mask:
+                masklen = 0
+            else:
+                masklen = int(mask)
+            if not 0 <= masklen <= 32:
+                raise ValueError
+        except ValueError:
+            try:
+                mask = _parseAddr(mask,False)
+            except ValueError:
+                raise ValueError("Mask isn't parseable.")
+            remaining = 0
+            masklen = 0
+            if not mask:
+                masklen = 0
+            else:
+                while not (mask&1):
+                    remaining += 1
+                while (mask&1):
+                    mask >>= 1
+                    masklen += 1
+                if remaining+masklen <> 32:
+                    raise ValueError("Mask isn't a proper host mask.")
+        naddr1 = naddr & (((1<<masklen)-1)<<(32-masklen))
+        naddr2 = naddr1 + (1<<(32-masklen)) - 1
+        return (naddr1,naddr2)
+
+    def _parseAddrRange(self,addr):
+        naddr, naddrlen = _parseAddr(addr)
+        naddr1 = naddr<<((4-naddrlen)*8)
+        naddr2 = ( (naddr<<((4-naddrlen)*8)) +
+                   (1<<((4-naddrlen)*8)) - 1 )
+        return (naddr1,naddr2)
+
+    # Utility functions
+    # -----------------
+
+    def _int2ip(self,num):
+        rv = []
+        for i in range(4):
+            rv.append(str(num&255))
+            num >>= 8
+        return ".".join(reversed(rv))
+
+    # Iterating
+    # ---------
+
+    def iteraddresses(self):
+        """Returns an iterator which iterates over ips in this iprange. An
+        IP is returned in string form (e.g. '1.2.3.4')."""
+
+        for v in super(IP4Range,self).__iter__():
+            yield self._int2ip(v)
+
+    def iterranges(self):
+        """Returns an iterator which iterates over ip-ip ranges which build
+        this iprange if combined. An ip-ip pair is returned in string form
+        (e.g. '1.2.3.4-2.3.4.5')."""
+
+        for r in self._ranges:
+            if r[1]-r[0] == 1:
+                yield self._int2ip(r[0])
+            else:
+                yield '%s-%s' % (self._int2ip(r[0]),self._int2ip(r[1]-1))
+
+    def itermasks(self):
+        """Returns an iterator which iterates over ip/mask pairs which build
+        this iprange if combined. An IP/Mask pair is returned in string form
+        (e.g. '1.2.3.0/24')."""
+
+        for r in self._ranges:
+            for v in self._itermasks(r):
+                yield v
+
+    def _itermasks(self,r):
+        ranges = [r]
+        while ranges:
+            cur = ranges.pop()
+            curmask = 0
+            while True:
+                curmasklen = 1<<(32-curmask)
+                start = (cur[0]+curmasklen-1)&(((1<<curmask)-1)<<(32-curmask))
+                if start >= cur[0] and start+curmasklen <= cur[1]:
+                    break
+                else:
+                    curmask += 1
+            yield "%s/%s" % (self._int2ip(start),curmask)
+            if cur[0] < start:
+                ranges.append((cur[0],start))
+            if cur[1] > start+curmasklen:
+                ranges.append((start+curmasklen,cur[1]))
+
+    __iter__ = iteraddresses
+
+    # Printing
+    # --------
+
+    def __repr__(self):
+        """Returns a string which can be used to reconstruct this iprange."""
+
+        rv = []
+        for start, stop in self._ranges:
+            if stop-start == 1:
+                rv.append("%r" % (self._int2ip(start),))
+            else:
+                rv.append("(%r,%r)" % (self._int2ip(start),
+                                       self._int2ip(stop-1)))
+        return "%s(%s)" % (self.__class__.__name__,",".join(rv))
+
+def _parseAddr(addr,lookup=True):
+    if lookup and addr.translate(IP4Range._UNITYTRANS, IP4Range._IPREMOVE):
+        try:
+            addr = socket.gethostbyname(addr)
+        except socket.error:
+            raise ValueError("Invalid Hostname as argument.")
+    naddr = 0
+    for naddrpos, part in enumerate(addr.split(".")):
+        if naddrpos >= 4:
+            raise ValueError("Address contains more than four parts.")
+        try:
+            if not part:
+                part = 0
+            else:
+                part = int(part)
+            if not 0 <= part < 256:
+                raise ValueError
+        except ValueError:
+            raise ValueError("Address part out of range.")
+        naddr <<= 8
+        naddr += part
+    return naddr, naddrpos+1
+
+def ip2int(addr, lookup=True):
+    return _parseAddr(addr, lookup=lookup)[0]
+
+if __name__ == "__main__":
+    # Little test script.
+    x = IP4Range("172.22.162.250/24")
+    y = IP4Range("172.22.162.250","172.22.163.250","172.22.163.253<->255")
+    print x
+    for val in x.itermasks():
+        print val
+    for val in y.itermasks():
+        print val
+    for val in (x|y).itermasks():
+        print val
+    for val in (x^y).iterranges():
+        print val
+    for val in x:
+        print val

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/killthread.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/killthread.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/killthread.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+"""
+Kill a thread, from http://sebulba.wikispaces.com/recipe+thread2
+"""
+import types
+try:
+    import ctypes
+except ImportError:
+    raise ImportError(
+        "You cannot use paste.util.killthread without ctypes installed")
+if not hasattr(ctypes, 'pythonapi'):
+    raise ImportError(
+        "You cannot use paste.util.killthread without ctypes.pythonapi")
+
+def async_raise(tid, exctype):
+    """raises the exception, performs cleanup if needed.
+
+    tid is the value given by thread.get_ident() (an integer).
+    Raise SystemExit to kill a thread."""
+    if not isinstance(exctype, (types.ClassType, type)):
+        raise TypeError("Only types can be raised (not instances)")
+    if not isinstance(tid, int):
+        raise TypeError("tid must be an integer")
+    res = ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), ctypes.py_object(exctype))
+    if res == 0:
+        raise ValueError("invalid thread id")
+    elif res != 1:
+        # """if it returns a number greater than one, you're in trouble,
+        # and you should call it again with exc=NULL to revert the effect"""
+        ctypes.pythonapi.PyThreadState_SetAsyncExc(ctypes.c_long(tid), 0)
+        raise SystemError("PyThreadState_SetAsyncExc failed")

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/looper.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/looper.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/looper.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,152 @@
+"""
+Helper for looping over sequences, particular in templates.
+
+Often in a loop in a template it's handy to know what's next up,
+previously up, if this is the first or last item in the sequence, etc.
+These can be awkward to manage in a normal Python loop, but using the
+looper you can get a better sense of the context.  Use like::
+
+    >>> for loop, item in looper(['a', 'b', 'c']):
+    ...     print loop.number, item
+    ...     if not loop.last:
+    ...         print '---'
+    1 a
+    ---
+    2 b
+    ---
+    3 c
+
+"""
+
+__all__ = ['looper']
+
+class looper(object):
+    """
+    Helper for looping (particularly in templates)
+    
+    Use this like::
+    
+        for loop, item in looper(seq):
+            if loop.first:
+                ...
+    """
+
+    def __init__(self, seq):
+        self.seq = seq
+
+    def __iter__(self):
+        return looper_iter(self.seq)
+
+    def __repr__(self):
+        return '<%s for %r>' % (
+            self.__class__.__name__, self.seq)
+
+class looper_iter(object):
+
+    def __init__(self, seq):
+        self.seq = list(seq)
+        self.pos = 0
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if self.pos >= len(self.seq):
+            raise StopIteration
+        result = loop_pos(self.seq, self.pos), self.seq[self.pos]
+        self.pos += 1
+        return result
+
+class loop_pos(object):
+
+    def __init__(self, seq, pos):
+        self.seq = seq
+        self.pos = pos
+
+    def __repr__(self):
+        return '<loop pos=%r at %r>' % (
+            self.seq[pos], pos)
+
+    def index(self):
+        return self.pos
+    index = property(index)
+
+    def number(self):
+        return self.pos + 1
+    number = property(number)
+
+    def item(self):
+        return self.seq[self.pos]
+    item = property(item)
+
+    def next(self):
+        try:
+            return self.seq[self.pos+1]
+        except IndexError:
+            return None
+    next = property(next)
+
+    def previous(self):
+        if self.pos == 0:
+            return None
+        return self.seq[self.pos-1]
+    previous = property(previous)
+
+    def odd(self):
+        return not self.pos % 2
+    odd = property(odd)
+
+    def even(self):
+        return self.pos % 2
+    even = property(even)
+
+    def first(self):
+        return self.pos == 0
+    first = property(first)
+
+    def last(self):
+        return self.pos == len(self.seq)-1
+    last = property(last)
+
+    def length(self):
+        return len(self.seq)
+    length = property(length)
+
+    def first_group(self, getter=None):
+        """
+        Returns true if this item is the start of a new group,
+        where groups mean that some attribute has changed.  The getter
+        can be None (the item itself changes), an attribute name like
+        ``'.attr'``, a function, or a dict key or list index.
+        """
+        if self.first:
+            return True
+        return self._compare_group(self.item, self.previous, getter)
+
+    def last_group(self, getter=None):
+        """
+        Returns true if this item is the end of a new group,
+        where groups mean that some attribute has changed.  The getter
+        can be None (the item itself changes), an attribute name like
+        ``'.attr'``, a function, or a dict key or list index.
+        """
+        if self.last:
+            return True
+        return self._compare_group(self.item, self.next, getter)
+
+    def _compare_group(self, item, other, getter):
+        if getter is None:
+            return item != other
+        elif (isinstance(getter, basestring)
+              and getter.startswith('.')):
+            getter = getter[1:]
+            if getter.endswith('()'):
+                getter = getter[:-2]
+                return getattr(item, getter)() != getattr(other, getter)()
+            else:
+                return getattr(item, getter) != getattr(other, getter)
+        elif callable(getter):
+            return getter(item) != getter(other)
+        else:
+            return item[getter] != other[getter]
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/mimeparse.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/mimeparse.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/mimeparse.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,160 @@
+"""MIME-Type Parser
+
+This module provides basic functions for handling mime-types. It can handle
+matching mime-types against a list of media-ranges. See section 14.1 of
+the HTTP specification [RFC 2616] for a complete explanation.
+
+   http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.1
+
+Based on mimeparse 0.1.2 by Joe Gregorio:
+
+    http://code.google.com/p/mimeparse/
+
+Contents:
+    - parse_mime_type():   Parses a mime-type into its component parts.
+    - parse_media_range(): Media-ranges are mime-types with wild-cards and a 'q' quality parameter.
+    - quality():           Determines the quality ('q') of a mime-type when compared against a list of media-ranges.
+    - quality_parsed():    Just like quality() except the second parameter must be pre-parsed.
+    - best_match():        Choose the mime-type with the highest quality ('q') from a list of candidates.
+    - desired_matches():   Filter against a list of desired mime-types in the order the server prefers.
+
+"""
+
+
+def parse_mime_type(mime_type):
+    """Carves up a mime-type and returns a tuple of the
+       (type, subtype, params) where 'params' is a dictionary
+       of all the parameters for the media range.
+       For example, the media range 'application/xhtml;q=0.5' would
+       get parsed into:
+
+       ('application', 'xhtml', {'q', '0.5'})
+       """
+    type = mime_type.split(';')
+    type, plist = type[0], type[1:]
+    try:
+        type, subtype = type.split('/', 1)
+    except ValueError:
+        type, subtype = type.strip() or '*', '*'
+    else:
+        type = type.strip() or '*'
+        subtype = subtype.strip() or '*'
+    params = {}
+    for param in plist:
+        param = param.split('=', 1)
+        if len(param) == 2:
+            key, value = param[0].strip(), param[1].strip()
+            if key and value:
+                params[key] = value
+    return type, subtype, params
+
+def parse_media_range(range):
+    """Carves up a media range and returns a tuple of the
+       (type, subtype, params) where 'params' is a dictionary
+       of all the parameters for the media range.
+       For example, the media range 'application/*;q=0.5' would
+       get parsed into:
+
+       ('application', '*', {'q', '0.5'})
+
+       In addition this function also guarantees that there
+       is a value for 'q' in the params dictionary, filling it
+       in with a proper default if necessary.
+       """
+    type, subtype, params = parse_mime_type(range)
+    try:
+        if not 0 <= float(params['q']) <= 1:
+            raise ValueError
+    except (KeyError, ValueError):
+        params['q'] = '1'
+    return type, subtype, params
+
+def fitness_and_quality_parsed(mime_type, parsed_ranges):
+    """Find the best match for a given mime-type against
+       a list of media_ranges that have already been
+       parsed by parse_media_range(). Returns a tuple of
+       the fitness value and the value of the 'q' quality
+       parameter of the best match, or (-1, 0) if no match
+       was found. Just as for quality_parsed(), 'parsed_ranges'
+       must be a list of parsed media ranges."""
+    best_fitness, best_fit_q = -1, 0
+    target_type, target_subtype, target_params = parse_media_range(mime_type)
+    for type, subtype, params in parsed_ranges:
+        if (type == target_type
+                    or type == '*' or target_type == '*') and (
+                subtype == target_subtype
+                    or subtype == '*' or target_subtype == '*'):
+            fitness = 0
+            if type == target_type:
+                fitness += 100
+            if subtype == target_subtype:
+                fitness += 10
+            for key in target_params:
+                if key != 'q' and key in params:
+                    if params[key] == target_params[key]:
+                        fitness += 1
+            if fitness > best_fitness:
+                best_fitness = fitness
+                best_fit_q = params['q']
+    return best_fitness, float(best_fit_q)
+
+def quality_parsed(mime_type, parsed_ranges):
+    """Find the best match for a given mime-type against
+    a list of media_ranges that have already been
+    parsed by parse_media_range(). Returns the
+    'q' quality parameter of the best match, 0 if no
+    match was found. This function behaves the same as quality()
+    except that 'parsed_ranges' must be a list of
+    parsed media ranges."""
+    return fitness_and_quality_parsed(mime_type, parsed_ranges)[1]
+
+def quality(mime_type, ranges):
+    """Returns the quality 'q' of a mime-type when compared
+    against the media-ranges in ranges. For example:
+
+    >>> quality('text/html','text/*;q=0.3, text/html;q=0.7, text/html;level=1, text/html;level=2;q=0.4, */*;q=0.5')
+    0.7
+
+    """
+    parsed_ranges = map(parse_media_range, ranges.split(','))
+    return quality_parsed(mime_type, parsed_ranges)
+
+def best_match(supported, header):
+    """Takes a list of supported mime-types and finds the best
+    match for all the media-ranges listed in header. In case of
+    ambiguity, whatever comes first in the list will be chosen.
+    The value of header must be a string that conforms to the format
+    of the HTTP Accept: header. The value of 'supported' is a list
+    of mime-types.
+
+    >>> best_match(['application/xbel+xml', 'text/xml'], 'text/*;q=0.5,*/*; q=0.1')
+    'text/xml'
+    """
+    if not supported:
+        return ''
+    parsed_header = map(parse_media_range, header.split(','))
+    best_type = max([
+            (fitness_and_quality_parsed(mime_type, parsed_header), -n)
+            for n, mime_type in enumerate(supported)])
+    return best_type[0][1] and supported[-best_type[1]] or ''
+
+def desired_matches(desired, header):
+    """Takes a list of desired mime-types in the order the server prefers to
+    send them regardless of the browsers preference.
+
+    Browsers (such as Firefox) technically want XML over HTML depending on how
+    one reads the specification. This function is provided for a server to
+    declare a set of desired mime-types it supports, and returns a subset of
+    the desired list in the same order should each one be Accepted by the
+    browser.
+
+    >>> desired_matches(['text/html', 'application/xml'], \
+    ...     'text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png')
+    ['text/html', 'application/xml']
+    >>> desired_matches(['text/html', 'application/xml'], 'application/xml,application/json')
+    ['application/xml']
+    """
+    parsed_ranges = map(parse_media_range, header.split(','))
+    return [mimetype for mimetype in desired
+        if quality_parsed(mimetype, parsed_ranges)]
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/multidict.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/multidict.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/multidict.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,397 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import cgi
+import copy
+import sys
+from UserDict import DictMixin
+
+class MultiDict(DictMixin):
+
+    """
+    An ordered dictionary that can have multiple values for each key.
+    Adds the methods getall, getone, mixed, and add to the normal
+    dictionary interface.
+    """
+
+    def __init__(self, *args, **kw):
+        if len(args) > 1:
+            raise TypeError(
+                "MultiDict can only be called with one positional argument")
+        if args:
+            if hasattr(args[0], 'iteritems'):
+                items = list(args[0].iteritems())
+            elif hasattr(args[0], 'items'):
+                items = args[0].items()
+            else:
+                items = list(args[0])
+            self._items = items
+        else:
+            self._items = []
+        self._items.extend(kw.iteritems())
+
+    def __getitem__(self, key):
+        for k, v in self._items:
+            if k == key:
+                return v
+        raise KeyError(repr(key))
+
+    def __setitem__(self, key, value):
+        try:
+            del self[key]
+        except KeyError:
+            pass
+        self._items.append((key, value))
+
+    def add(self, key, value):
+        """
+        Add the key and value, not overwriting any previous value.
+        """
+        self._items.append((key, value))
+
+    def getall(self, key):
+        """
+        Return a list of all values matching the key (may be an empty list)
+        """
+        result = []
+        for k, v in self._items:
+            if key == k:
+                result.append(v)
+        return result
+
+    def getone(self, key):
+        """
+        Get one value matching the key, raising a KeyError if multiple
+        values were found.
+        """
+        v = self.getall(key)
+        if not v:
+            raise KeyError('Key not found: %r' % key)
+        if len(v) > 1:
+            raise KeyError('Multiple values match %r: %r' % (key, v))
+        return v[0]
+
+    def mixed(self):
+        """
+        Returns a dictionary where the values are either single
+        values, or a list of values when a key/value appears more than
+        once in this dictionary.  This is similar to the kind of
+        dictionary often used to represent the variables in a web
+        request.
+        """
+        result = {}
+        multi = {}
+        for key, value in self._items:
+            if key in result:
+                # We do this to not clobber any lists that are
+                # *actual* values in this dictionary:
+                if key in multi:
+                    result[key].append(value)
+                else:
+                    result[key] = [result[key], value]
+                    multi[key] = None
+            else:
+                result[key] = value
+        return result
+
+    def dict_of_lists(self):
+        """
+        Returns a dictionary where each key is associated with a
+        list of values.
+        """
+        result = {}
+        for key, value in self._items:
+            if key in result:
+                result[key].append(value)
+            else:
+                result[key] = [value]
+        return result
+
+    def __delitem__(self, key):
+        items = self._items
+        found = False
+        for i in range(len(items)-1, -1, -1):
+            if items[i][0] == key:
+                del items[i]
+                found = True
+        if not found:
+            raise KeyError(repr(key))
+
+    def __contains__(self, key):
+        for k, v in self._items:
+            if k == key:
+                return True
+        return False
+
+    has_key = __contains__
+
+    def clear(self):
+        self._items = []
+
+    def copy(self):
+        return MultiDict(self)
+
+    def setdefault(self, key, default=None):
+        for k, v in self._items:
+            if key == k:
+                return v
+        self._items.append((key, default))
+        return default
+
+    def pop(self, key, *args):
+        if len(args) > 1:
+            raise TypeError, "pop expected at most 2 arguments, got "\
+                              + repr(1 + len(args))
+        for i in range(len(self._items)):
+            if self._items[i][0] == key:
+                v = self._items[i][1]
+                del self._items[i]
+                return v
+        if args:
+            return args[0]
+        else:
+            raise KeyError(repr(key))
+
+    def popitem(self):
+        return self._items.pop()
+
+    def update(self, other=None, **kwargs):
+        if other is None:
+            pass
+        elif hasattr(other, 'items'):
+            self._items.extend(other.items())
+        elif hasattr(other, 'keys'):
+            for k in other.keys():
+                self._items.append((k, other[k]))
+        else:
+            for k, v in other:
+                self._items.append((k, v))
+        if kwargs:
+            self.update(kwargs)
+
+    def __repr__(self):
+        items = ', '.join(['(%r, %r)' % v for v in self._items])
+        return '%s([%s])' % (self.__class__.__name__, items)
+
+    def __len__(self):
+        return len(self._items)
+
+    ##
+    ## All the iteration:
+    ##
+
+    def keys(self):
+        return [k for k, v in self._items]
+
+    def iterkeys(self):
+        for k, v in self._items:
+            yield k
+
+    __iter__ = iterkeys
+
+    def items(self):
+        return self._items[:]
+
+    def iteritems(self):
+        return iter(self._items)
+
+    def values(self):
+        return [v for k, v in self._items]
+
+    def itervalues(self):
+        for k, v in self._items:
+            yield v
+
+class UnicodeMultiDict(DictMixin):
+    """
+    A MultiDict wrapper that decodes returned values to unicode on the
+    fly. Decoding is not applied to assigned values.
+
+    The key/value contents are assumed to be ``str``/``strs`` or
+    ``str``/``FieldStorages`` (as is returned by the ``paste.request.parse_``
+    functions).
+
+    Can optionally also decode keys when the ``decode_keys`` argument is
+    True.
+
+    ``FieldStorage`` instances are cloned, and the clone's ``filename``
+    variable is decoded. Its ``name`` variable is decoded when ``decode_keys``
+    is enabled.
+
+    """
+    def __init__(self, multi=None, encoding=None, errors='strict',
+                 decode_keys=False):
+        self.multi = multi
+        if encoding is None:
+            encoding = sys.getdefaultencoding()
+        self.encoding = encoding
+        self.errors = errors
+        self.decode_keys = decode_keys
+
+    def _decode_key(self, key):
+        if self.decode_keys:
+            try:
+                key = key.decode(self.encoding, self.errors)
+            except AttributeError:
+                pass
+        return key
+
+    def _decode_value(self, value):
+        """
+        Decode the specified value to unicode. Assumes value is a ``str`` or
+        `FieldStorage`` object.
+
+        ``FieldStorage`` objects are specially handled.
+        """
+        if isinstance(value, cgi.FieldStorage):
+            # decode FieldStorage's field name and filename
+            value = copy.copy(value)
+            if self.decode_keys:
+                value.name = value.name.decode(self.encoding, self.errors)
+            value.filename = value.filename.decode(self.encoding, self.errors)
+        else:
+            try:
+                value = value.decode(self.encoding, self.errors)
+            except AttributeError:
+                pass
+        return value
+
+    def __getitem__(self, key):
+        return self._decode_value(self.multi.__getitem__(key))
+
+    def __setitem__(self, key, value):
+        self.multi.__setitem__(key, value)
+
+    def add(self, key, value):
+        """
+        Add the key and value, not overwriting any previous value.
+        """
+        self.multi.add(key, value)
+
+    def getall(self, key):
+        """
+        Return a list of all values matching the key (may be an empty list)
+        """
+        return [self._decode_value(v) for v in self.multi.getall(key)]
+
+    def getone(self, key):
+        """
+        Get one value matching the key, raising a KeyError if multiple
+        values were found.
+        """
+        return self._decode_value(self.multi.getone(key))
+
+    def mixed(self):
+        """
+        Returns a dictionary where the values are either single
+        values, or a list of values when a key/value appears more than
+        once in this dictionary.  This is similar to the kind of
+        dictionary often used to represent the variables in a web
+        request.
+        """
+        unicode_mixed = {}
+        for key, value in self.multi.mixed().iteritems():
+            if isinstance(value, list):
+                value = [self._decode_value(value) for value in value]
+            else:
+                value = self._decode_value(value)
+            unicode_mixed[self._decode_key(key)] = value
+        return unicode_mixed
+
+    def dict_of_lists(self):
+        """
+        Returns a dictionary where each key is associated with a
+        list of values.
+        """
+        unicode_dict = {}
+        for key, value in self.multi.dict_of_lists().iteritems():
+            value = [self._decode_value(value) for value in value]
+            unicode_dict[self._decode_key(key)] = value
+        return unicode_dict
+
+    def __delitem__(self, key):
+        self.multi.__delitem__(key)
+
+    def __contains__(self, key):
+        return self.multi.__contains__(key)
+
+    has_key = __contains__
+
+    def clear(self):
+        self.multi.clear()
+
+    def copy(self):
+        return UnicodeMultiDict(self.multi.copy(), self.encoding, self.errors)
+
+    def setdefault(self, key, default=None):
+        return self._decode_value(self.multi.setdefault(key, default))
+
+    def pop(self, key, *args):
+        return self._decode_value(self.multi.pop(key, *args))
+
+    def popitem(self):
+        k, v = self.multi.popitem()
+        return (self._decode_key(k), self._decode_value(v))
+
+    def __repr__(self):
+        items = ', '.join(['(%r, %r)' % v for v in self.items()])
+        return '%s([%s])' % (self.__class__.__name__, items)
+
+    def __len__(self):
+        return self.multi.__len__()
+
+    ##
+    ## All the iteration:
+    ##
+
+    def keys(self):
+        return [self._decode_key(k) for k in self.multi.iterkeys()]
+
+    def iterkeys(self):
+        for k in self.multi.iterkeys():
+            yield self._decode_key(k)
+
+    __iter__ = iterkeys
+
+    def items(self):
+        return [(self._decode_key(k), self._decode_value(v)) for \
+                    k, v in self.multi.iteritems()]
+
+    def iteritems(self):
+        for k, v in self.multi.iteritems():
+            yield (self._decode_key(k), self._decode_value(v))
+
+    def values(self):
+        return [self._decode_value(v) for v in self.multi.itervalues()]
+
+    def itervalues(self):
+        for v in self.multi.itervalues():
+            yield self._decode_value(v)
+
+__test__ = {
+    'general': """
+    >>> d = MultiDict(a=1, b=2)
+    >>> d['a']
+    1
+    >>> d.getall('c')
+    []
+    >>> d.add('a', 2)
+    >>> d['a']
+    1
+    >>> d.getall('a')
+    [1, 2]
+    >>> d['b'] = 4
+    >>> d.getall('b')
+    [4]
+    >>> d.keys()
+    ['a', 'a', 'b']
+    >>> d.items()
+    [('a', 1), ('a', 2), ('b', 4)]
+    >>> d.mixed()
+    {'a': [1, 2], 'b': 4}
+    >>> MultiDict([('a', 'b')], c=2)
+    MultiDict([('a', 'b'), ('c', 2)])
+    """}
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/quoting.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/quoting.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/quoting.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,98 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+import cgi
+import htmlentitydefs
+import urllib
+import re
+
+__all__ = ['html_quote', 'html_unquote', 'url_quote', 'url_unquote',
+           'strip_html']
+
+default_encoding = 'UTF-8'
+
+def html_quote(v, encoding=None):
+    r"""
+    Quote the value (turned to a string) as HTML.  This quotes <, >,
+    and quotes:
+
+    >>> html_quote(1)
+    '1'
+    >>> html_quote(None)
+    ''
+    >>> html_quote('<hey!>')
+    '&lt;hey!&gt;'
+    >>> html_quote(u'\u1029')
+    '\xe1\x80\xa9'
+    """
+    encoding = encoding or default_encoding
+    if v is None:
+        return ''
+    elif isinstance(v, str):
+        return cgi.escape(v, 1)
+    elif isinstance(v, unicode):
+        return cgi.escape(v.encode(encoding), 1)
+    else:
+        return cgi.escape(unicode(v).encode(encoding), 1)
+
+_unquote_re = re.compile(r'&([a-zA-Z]+);')
+def _entity_subber(match, name2c=htmlentitydefs.name2codepoint):
+    code = name2c.get(match.group(1))
+    if code:
+        return unichr(code)
+    else:
+        return match.group(0)
+
+def html_unquote(s, encoding=None):
+    r"""
+    Decode the value.
+
+    >>> html_unquote('&lt;hey&nbsp;you&gt;')
+    u'<hey\xa0you>'
+    >>> html_unquote('')
+    u''
+    >>> html_unquote('&blahblah;')
+    u'&blahblah;'
+    >>> html_unquote('\xe1\x80\xa9')
+    u'\u1029'
+    """
+    if isinstance(s, str):
+        if s == '':
+            # workaround re.sub('', '', u'') returning '' < 2.5.2
+            # instead of u'' >= 2.5.2
+            return u''
+        s = s.decode(encoding or default_encoding)
+    return _unquote_re.sub(_entity_subber, s)
+
+def strip_html(s):
+    # should this use html_unquote?
+    s = re.sub('<.*?>', '', s)
+    s = html_unquote(s)
+    return s
+
+def no_quote(s):
+    """
+    Quoting that doesn't do anything
+    """
+    return s
+
+_comment_quote_re = re.compile(r'\-\s*\>')
+# Everything but \r, \n, \t:
+_bad_chars_re = re.compile('[\x00-\x08\x0b-\x0c\x0e-\x1f]')
+def comment_quote(s):
+    """
+    Quote that makes sure text can't escape a comment
+    """
+    comment = str(s)
+    #comment = _bad_chars_re.sub('', comment)
+    #print 'in ', repr(str(s))
+    #print 'out', repr(comment)
+    comment = _comment_quote_re.sub('-&gt;', comment)
+    return comment
+
+url_quote = urllib.quote
+url_unquote = urllib.unquote
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/scgiserver.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/scgiserver.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/scgiserver.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,171 @@
+"""
+SCGI-->WSGI application proxy, "SWAP".
+
+(Originally written by Titus Brown.)
+
+This lets an SCGI front-end like mod_scgi be used to execute WSGI
+application objects.  To use it, subclass the SWAP class like so::
+
+   class TestAppHandler(swap.SWAP):
+       def __init__(self, *args, **kwargs):
+           self.prefix = '/canal'
+           self.app_obj = TestAppClass
+           swap.SWAP.__init__(self, *args, **kwargs)
+
+where 'TestAppClass' is the application object from WSGI and '/canal'
+is the prefix for what is served by the SCGI Web-server-side process.
+
+Then execute the SCGI handler "as usual" by doing something like this::
+
+   scgi_server.SCGIServer(TestAppHandler, port=4000).serve()
+
+and point mod_scgi (or whatever your SCGI front end is) at port 4000.
+
+Kudos to the WSGI folk for writing a nice PEP & the Quixote folk for
+writing a nice extensible SCGI server for Python!
+"""
+
+import sys
+import time
+from scgi import scgi_server
+
+def debug(msg):
+    timestamp = time.strftime("%Y-%m-%d %H:%M:%S",
+                              time.localtime(time.time()))
+    sys.stderr.write("[%s] %s\n" % (timestamp, msg))
+
+class SWAP(scgi_server.SCGIHandler):
+    """
+    SCGI->WSGI application proxy: let an SCGI server execute WSGI
+    application objects.
+    """
+    app_obj = None
+    prefix = None
+    
+    def __init__(self, *args, **kwargs):
+        assert self.app_obj, "must set app_obj"
+        assert self.prefix is not None, "must set prefix"
+        args = (self,) + args
+        scgi_server.SCGIHandler.__init__(*args, **kwargs)
+
+    def handle_connection(self, conn):
+        """
+        Handle an individual connection.
+        """
+        input = conn.makefile("r")
+        output = conn.makefile("w")
+
+        environ = self.read_env(input)
+        environ['wsgi.input']        = input
+        environ['wsgi.errors']       = sys.stderr
+        environ['wsgi.version']      = (1, 0)
+        environ['wsgi.multithread']  = False
+        environ['wsgi.multiprocess'] = True
+        environ['wsgi.run_once']     = False
+
+        # dunno how SCGI does HTTPS signalling; can't test it myself... @CTB
+        if environ.get('HTTPS','off') in ('on','1'):
+            environ['wsgi.url_scheme'] = 'https'
+        else:
+            environ['wsgi.url_scheme'] = 'http'
+
+        ## SCGI does some weird environ manglement.  We need to set
+        ## SCRIPT_NAME from 'prefix' and then set PATH_INFO from
+        ## REQUEST_URI.
+
+        prefix = self.prefix
+        path = environ['REQUEST_URI'][len(prefix):].split('?', 1)[0]
+
+        environ['SCRIPT_NAME'] = prefix
+        environ['PATH_INFO'] = path
+
+        headers_set = []
+        headers_sent = []
+        chunks = []
+        def write(data):
+            chunks.append(data)
+        
+        def start_response(status, response_headers, exc_info=None):
+            if exc_info:
+                try:
+                    if headers_sent:
+                        # Re-raise original exception if headers sent
+                        raise exc_info[0], exc_info[1], exc_info[2]
+                finally:
+                    exc_info = None     # avoid dangling circular ref
+            elif headers_set:
+                raise AssertionError("Headers already set!")
+
+            headers_set[:] = [status, response_headers]
+            return write
+
+        ###
+
+        result = self.app_obj(environ, start_response)
+        try:
+            for data in result:
+                chunks.append(data)
+                
+            # Before the first output, send the stored headers
+            if not headers_set:
+                # Error -- the app never called start_response
+                status = '500 Server Error'
+                response_headers = [('Content-type', 'text/html')]
+                chunks = ["XXX start_response never called"]
+            else:
+                status, response_headers = headers_sent[:] = headers_set
+                
+            output.write('Status: %s\r\n' % status)
+            for header in response_headers:
+                output.write('%s: %s\r\n' % header)
+            output.write('\r\n')
+
+            for data in chunks:
+                output.write(data)
+        finally:
+            if hasattr(result,'close'):
+                result.close()
+
+        # SCGI backends use connection closing to signal 'fini'.
+        try:
+            input.close()
+            output.close()
+            conn.close()
+        except IOError, err:
+            debug("IOError while closing connection ignored: %s" % err)
+
+
+def serve_application(application, prefix, port=None, host=None, max_children=None):
+    """
+    Serve the specified WSGI application via SCGI proxy.
+
+    ``application``
+        The WSGI application to serve.
+
+    ``prefix``
+        The prefix for what is served by the SCGI Web-server-side process.
+
+    ``port``
+        Optional port to bind the SCGI proxy to. Defaults to SCGIServer's
+        default port value.
+
+    ``host``
+        Optional host to bind the SCGI proxy to. Defaults to SCGIServer's
+        default host value.
+
+    ``host``
+        Optional maximum number of child processes the SCGIServer will
+        spawn. Defaults to SCGIServer's default max_children value.
+    """
+    class SCGIAppHandler(SWAP):
+        def __init__ (self, *args, **kwargs):
+            self.prefix = prefix
+            self.app_obj = application
+            SWAP.__init__(self, *args, **kwargs)
+
+    kwargs = dict(handler_class=SCGIAppHandler)
+    for kwarg in ('host', 'port', 'max_children'):
+        if locals()[kwarg] is not None:
+            kwargs[kwarg] = locals()[kwarg]
+
+    scgi_server.SCGIServer(**kwargs).serve()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/string24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/string24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/string24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,531 @@
+"""A collection of string operations (most are no longer used).
+
+Warning: most of the code you see here isn't normally used nowadays.
+Beginning with Python 1.6, many of these functions are implemented as
+methods on the standard string object. They used to be implemented by
+a built-in module called strop, but strop is now obsolete itself.
+
+Public module variables:
+
+whitespace -- a string containing all characters considered whitespace
+lowercase -- a string containing all characters considered lowercase letters
+uppercase -- a string containing all characters considered uppercase letters
+letters -- a string containing all characters considered letters
+digits -- a string containing all characters considered decimal digits
+hexdigits -- a string containing all characters considered hexadecimal digits
+octdigits -- a string containing all characters considered octal digits
+punctuation -- a string containing all characters considered punctuation
+printable -- a string containing all characters considered printable
+
+"""
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n\r\v\f'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+ascii_lowercase = lowercase
+ascii_uppercase = uppercase
+ascii_letters = ascii_lowercase + ascii_uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
+printable = digits + letters + punctuation + whitespace
+
+# Case conversion helpers
+# Use str to convert Unicode literal in case of -U
+# Note that Cookie.py bogusly uses _idmap :(
+l = map(chr, xrange(256))
+_idmap = str('').join(l)
+del l
+
+# Functions which aren't available as string methods.
+
+# Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
+# See also regsub.capwords().
+def capwords(s, sep=None):
+    """capwords(s, [sep]) -> string
+
+    Split the argument into words using split, capitalize each
+    word using capitalize, and join the capitalized words using
+    join. Note that this replaces runs of whitespace characters by
+    a single space.
+
+    """
+    return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
+
+
+# Construct a translation string
+_idmapL = None
+def maketrans(fromstr, tostr):
+    """maketrans(frm, to) -> string
+
+    Return a translation table (a string of 256 bytes long)
+    suitable for use in string.translate.  The strings frm and to
+    must be of the same length.
+
+    """
+    if len(fromstr) != len(tostr):
+        raise ValueError, "maketrans arguments must have same length"
+    global _idmapL
+    if not _idmapL:
+        _idmapL = map(None, _idmap)
+    L = _idmapL[:]
+    fromstr = map(ord, fromstr)
+    for i in range(len(fromstr)):
+        L[fromstr[i]] = tostr[i]
+    return ''.join(L)
+
+
+
+####################################################################
+import re as _re
+
+class _multimap:
+    """Helper class for combining multiple mappings.
+
+    Used by .{safe_,}substitute() to combine the mapping and keyword
+    arguments.
+    """
+    def __init__(self, primary, secondary):
+        self._primary = primary
+        self._secondary = secondary
+
+    def __getitem__(self, key):
+        try:
+            return self._primary[key]
+        except KeyError:
+            return self._secondary[key]
+
+
+class _TemplateMetaclass(type):
+    pattern = r"""
+    %(delim)s(?:
+      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
+      (?P<named>%(id)s)      |   # delimiter and a Python identifier
+      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
+      (?P<invalid>)              # Other ill-formed delimiter exprs
+    )
+    """
+
+    def __init__(cls, name, bases, dct):
+        super(_TemplateMetaclass, cls).__init__(name, bases, dct)
+        if 'pattern' in dct:
+            pattern = cls.pattern
+        else:
+            pattern = _TemplateMetaclass.pattern % {
+                'delim' : _re.escape(cls.delimiter),
+                'id'    : cls.idpattern,
+                }
+        cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
+
+
+class Template:
+    """A string class for supporting $-substitutions."""
+    __metaclass__ = _TemplateMetaclass
+
+    delimiter = '$'
+    idpattern = r'[_a-z][_a-z0-9]*'
+
+    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 in string: line %d, col %d' %
+                         (lineno, colno))
+
+    def substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            # Check the most common path first.
+            named = mo.group('named') or mo.group('braced')
+            if named is not None:
+                val = mapping[named]
+                # We use this idiom instead of str() because the latter will
+                # fail if val is a Unicode containing non-ASCII characters.
+                return '%s' % val
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                self._invalid(mo)
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+    def safe_substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            named = mo.group('named')
+            if named is not None:
+                try:
+                    # We use this idiom instead of str() because the latter
+                    # will fail if val is a Unicode containing non-ASCII
+                    return '%s' % mapping[named]
+                except KeyError:
+                    return self.delimiter + named
+            braced = mo.group('braced')
+            if braced is not None:
+                try:
+                    return '%s' % mapping[braced]
+                except KeyError:
+                    return self.delimiter + '{' + braced + '}'
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                return self.delimiter
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+
+
+####################################################################
+# NOTE: Everything below here is deprecated.  Use string methods instead.
+# This stuff will go away in Python 3.0.
+
+# Backward compatible names for exceptions
+index_error = ValueError
+atoi_error = ValueError
+atof_error = ValueError
+atol_error = ValueError
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+    """lower(s) -> string
+
+    Return a copy of the string s converted to lowercase.
+
+    """
+    return s.lower()
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+    """upper(s) -> string
+
+    Return a copy of the string s converted to uppercase.
+
+    """
+    return s.upper()
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+    """swapcase(s) -> string
+
+    Return a copy of the string s with upper case characters
+    converted to lowercase and vice versa.
+
+    """
+    return s.swapcase()
+
+# Strip leading and trailing tabs and spaces
+def strip(s, chars=None):
+    """strip(s [,chars]) -> string
+
+    Return a copy of the string s with leading and trailing
+    whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+    If chars is unicode, S will be converted to unicode before stripping.
+
+    """
+    return s.strip(chars)
+
+# Strip leading tabs and spaces
+def lstrip(s, chars=None):
+    """lstrip(s [,chars]) -> string
+
+    Return a copy of the string s with leading whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.lstrip(chars)
+
+# Strip trailing tabs and spaces
+def rstrip(s, chars=None):
+    """rstrip(s [,chars]) -> string
+
+    Return a copy of the string s with trailing whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.rstrip(chars)
+
+
+# Split a string into a list of space/tab-separated words
+def split(s, sep=None, maxsplit=-1):
+    """split(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string.  If maxsplit is given, splits at no more than
+    maxsplit places (resulting in at most maxsplit+1 words).  If sep
+    is not specified or is None, any whitespace string is a separator.
+
+    (split and splitfields are synonymous)
+
+    """
+    return s.split(sep, maxsplit)
+splitfields = split
+
+# Split a string into a list of space/tab-separated words
+def rsplit(s, sep=None, maxsplit=-1):
+    """rsplit(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string, starting at the end of the string and working
+    to the front.  If maxsplit is given, at most maxsplit splits are
+    done. If sep is not specified or is None, any whitespace string
+    is a separator.
+    """
+    return s.rsplit(sep, maxsplit)
+
+# Join fields with optional separator
+def join(words, sep = ' '):
+    """join(list [,sep]) -> string
+
+    Return a string composed of the words in list, with
+    intervening occurrences of sep.  The default separator is a
+    single space.
+
+    (joinfields and join are synonymous)
+
+    """
+    return sep.join(words)
+joinfields = join
+
+# Find substring, raise exception if not found
+def index(s, *args):
+    """index(s, sub [,start [,end]]) -> int
+
+    Like find but raises ValueError when the substring is not found.
+
+    """
+    return s.index(*args)
+
+# Find last substring, raise exception if not found
+def rindex(s, *args):
+    """rindex(s, sub [,start [,end]]) -> int
+
+    Like rfind but raises ValueError when the substring is not found.
+
+    """
+    return s.rindex(*args)
+
+# Count non-overlapping occurrences of substring
+def count(s, *args):
+    """count(s, sub[, start[,end]]) -> int
+
+    Return the number of occurrences of substring sub in string
+    s[start:end].  Optional arguments start and end are
+    interpreted as in slice notation.
+
+    """
+    return s.count(*args)
+
+# Find substring, return -1 if not found
+def find(s, *args):
+    """find(s, sub [,start [,end]]) -> in
+
+    Return the lowest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.find(*args)
+
+# Find last substring, return -1 if not found
+def rfind(s, *args):
+    """rfind(s, sub [,start [,end]]) -> int
+
+    Return the highest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.rfind(*args)
+
+# for a bit of speed
+_float = float
+_int = int
+_long = long
+
+# Convert string to float
+def atof(s):
+    """atof(s) -> float
+
+    Return the floating point number represented by the string s.
+
+    """
+    return _float(s)
+
+
+# Convert string to integer
+def atoi(s , base=10):
+    """atoi(s [,base]) -> int
+
+    Return the integer represented by the string s in the given
+    base, which defaults to 10.  The string s must consist of one
+    or more digits, possibly preceded by a sign.  If base is 0, it
+    is chosen from the leading characters of s, 0 for octal, 0x or
+    0X for hexadecimal.  If base is 16, a preceding 0x or 0X is
+    accepted.
+
+    """
+    return _int(s, base)
+
+
+# Convert string to long integer
+def atol(s, base=10):
+    """atol(s [,base]) -> long
+
+    Return the long integer represented by the string s in the
+    given base, which defaults to 10.  The string s must consist
+    of one or more digits, possibly preceded by a sign.  If base
+    is 0, it is chosen from the leading characters of s, 0 for
+    octal, 0x or 0X for hexadecimal.  If base is 16, a preceding
+    0x or 0X is accepted.  A trailing L or l is not accepted,
+    unless base is 0.
+
+    """
+    return _long(s, base)
+
+
+# Left-justify a string
+def ljust(s, width, *args):
+    """ljust(s, width[, fillchar]) -> string
+
+    Return a left-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.ljust(width, *args)
+
+# Right-justify a string
+def rjust(s, width, *args):
+    """rjust(s, width[, fillchar]) -> string
+
+    Return a right-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.rjust(width, *args)
+
+# Center a string
+def center(s, width, *args):
+    """center(s, width[, fillchar]) -> string
+
+    Return a center version of s, in a field of the specified
+    width. padded with spaces as needed.  The string is never
+    truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.center(width, *args)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+    """zfill(x, width) -> string
+
+    Pad a numeric string x with zeros on the left, to fill a field
+    of the specified width.  The string x is never truncated.
+
+    """
+    if not isinstance(x, basestring):
+        x = repr(x)
+    return x.zfill(width)
+
+# Expand tabs in a string.
+# Doesn't take non-printing chars into account, but does understand \n.
+def expandtabs(s, tabsize=8):
+    """expandtabs(s [,tabsize]) -> string
+
+    Return a copy of the string s with all tab characters replaced
+    by the appropriate number of spaces, depending on the current
+    column, and the tabsize (default 8).
+
+    """
+    return s.expandtabs(tabsize)
+
+# Character translation through look-up table.
+def translate(s, table, deletions=""):
+    """translate(s,table [,deletions]) -> string
+
+    Return a copy of the string s, where all characters occurring
+    in the optional argument deletions are removed, and the
+    remaining characters have been mapped through the given
+    translation table, which must be a string of length 256.  The
+    deletions argument is not allowed for Unicode strings.
+
+    """
+    if deletions:
+        return s.translate(table, deletions)
+    else:
+        # Add s[:0] so that if s is Unicode and table is an 8-bit string,
+        # table is converted to Unicode.  This means that table *cannot*
+        # be a dictionary -- for that feature, use u.translate() directly.
+        return s.translate(table + s[:0])
+
+# Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
+def capitalize(s):
+    """capitalize(s) -> string
+
+    Return a copy of the string s with only its first character
+    capitalized.
+
+    """
+    return s.capitalize()
+
+# Substring replacement (global)
+def replace(s, old, new, maxsplit=-1):
+    """replace (str, old, new[, maxsplit]) -> string
+
+    Return a copy of string str with all occurrences of substring
+    old replaced by new. If the optional argument maxsplit is
+    given, only the first maxsplit occurrences are replaced.
+
+    """
+    return s.replace(old, new, maxsplit)
+
+
+# Try importing optional built-in module "strop" -- if it exists,
+# it redefines some string operations that are 100-1000 times faster.
+# It also defines values for whitespace, lowercase and uppercase
+# that match <ctype.h>'s definitions.
+
+try:
+    from strop import maketrans, lowercase, uppercase, whitespace
+    letters = lowercase + uppercase
+except ImportError:
+    pass                                          # Use the original versions

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/subprocess24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/subprocess24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/subprocess24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1152 @@
+# subprocess - Subprocesses with accessible I/O streams
+#
+# For more information about this module, see PEP 324.
+#
+# This module should remain compatible with Python 2.2, see PEP 291.
+#
+# Copyright (c) 2003-2005 by Peter Astrand <astrand at lysator.liu.se>
+#
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/2.4/license for licensing details.
+
+r"""subprocess - Subprocesses with accessible I/O streams
+
+This module allows you to spawn processes, connect to their
+input/output/error pipes, and obtain their return codes.  This module
+intends to replace several other, older modules and functions, like:
+
+os.system
+os.spawn*
+os.popen*
+popen2.*
+commands.*
+
+Information about how the subprocess module can be used to replace these
+modules and functions can be found below.
+
+
+
+Using the subprocess module
+===========================
+This module defines one class called Popen:
+
+class Popen(args, bufsize=0, executable=None,
+            stdin=None, stdout=None, stderr=None,
+            preexec_fn=None, close_fds=False, shell=False,
+            cwd=None, env=None, universal_newlines=False,
+            startupinfo=None, creationflags=0):
+
+
+Arguments are:
+
+args should be a string, or a sequence of program arguments.  The
+program to execute is normally the first item in the args sequence or
+string, but can be explicitly set by using the executable argument.
+
+On UNIX, with shell=False (default): In this case, the Popen class
+uses os.execvp() to execute the child program.  args should normally
+be a sequence.  A string will be treated as a sequence with the string
+as the only item (the program to execute).
+
+On UNIX, with shell=True: If args is a string, it specifies the
+command string to execute through the shell.  If args is a sequence,
+the first item specifies the command string, and any additional items
+will be treated as additional shell arguments.
+
+On Windows: the Popen class uses CreateProcess() to execute the child
+program, which operates on strings.  If args is a sequence, it will be
+converted to a string using the list2cmdline method.  Please note that
+not all MS Windows applications interpret the command line the same
+way: The list2cmdline is designed for applications using the same
+rules as the MS C runtime.
+
+bufsize, if given, has the same meaning as the corresponding argument
+to the built-in open() function: 0 means unbuffered, 1 means line
+buffered, any other positive value means use a buffer of
+(approximately) that size.  A negative bufsize means to use the system
+default, which usually means fully buffered.  The default value for
+bufsize is 0 (unbuffered).
+
+stdin, stdout and stderr specify the executed programs' standard
+input, standard output and standard error file handles, respectively.
+Valid values are PIPE, an existing file descriptor (a positive
+integer), an existing file object, and None.  PIPE indicates that a
+new pipe to the child should be created.  With None, no redirection
+will occur; the child's file handles will be inherited from the
+parent.  Additionally, stderr can be STDOUT, which indicates that the
+stderr data from the applications should be captured into the same
+file handle as for stdout.
+
+If preexec_fn is set to a callable object, this object will be called
+in the child process just before the child is executed.
+
+If close_fds is true, all file descriptors except 0, 1 and 2 will be
+closed before the child process is executed.
+
+if shell is true, the specified command will be executed through the
+shell.
+
+If cwd is not None, the current directory will be changed to cwd
+before the child is executed.
+
+If env is not None, it defines the environment variables for the new
+process.
+
+If universal_newlines is true, the file objects stdout and stderr are
+opened as a text files, but lines may be terminated by any of '\n',
+the Unix end-of-line convention, '\r', the Macintosh convention or
+'\r\n', the Windows convention.  All of these external representations
+are seen as '\n' by the Python program.  Note: This feature is only
+available if Python is built with universal newline support (the
+default).  Also, the newlines attribute of the file objects stdout,
+stdin and stderr are not updated by the communicate() method.
+
+The startupinfo and creationflags, if given, will be passed to the
+underlying CreateProcess() function.  They can specify things such as
+appearance of the main window and priority for the new process.
+(Windows only)
+
+
+This module also defines two shortcut functions:
+
+call(*args, **kwargs):
+    Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute. The arguments are the same as for
+    the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+
+
+Exceptions
+----------
+Exceptions raised in the child process, before the new program has
+started to execute, will be re-raised in the parent.  Additionally,
+the exception object will have one extra attribute called
+'child_traceback', which is a string containing traceback information
+from the childs point of view.
+
+The most common exception raised is OSError.  This occurs, for
+example, when trying to execute a non-existent file.  Applications
+should prepare for OSErrors.
+
+A ValueError will be raised if Popen is called with invalid arguments.
+
+
+Security
+--------
+Unlike some other popen functions, this implementation will never call
+/bin/sh implicitly.  This means that all characters, including shell
+metacharacters, can safely be passed to child processes.
+
+
+Popen objects
+=============
+Instances of the Popen class have the following methods:
+
+poll()
+    Check if child process has terminated.  Returns returncode
+    attribute.
+
+wait()
+    Wait for child process to terminate.  Returns returncode attribute.
+
+communicate(input=None)
+    Interact with process: Send data to stdin.  Read data from stdout
+    and stderr, until end-of-file is reached.  Wait for process to
+    terminate.  The optional stdin argument should be a string to be
+    sent to the child process, or None, if no data should be sent to
+    the child.
+
+    communicate() returns a tuple (stdout, stderr).
+
+    Note: The data read is buffered in memory, so do not use this
+    method if the data size is large or unlimited.
+
+The following attributes are also available:
+
+stdin
+    If the stdin argument is PIPE, this attribute is a file object
+    that provides input to the child process.  Otherwise, it is None.
+
+stdout
+    If the stdout argument is PIPE, this attribute is a file object
+    that provides output from the child process.  Otherwise, it is
+    None.
+
+stderr
+    If the stderr argument is PIPE, this attribute is file object that
+    provides error output from the child process.  Otherwise, it is
+    None.
+
+pid
+    The process ID of the child process.
+
+returncode
+    The child return code.  A None value indicates that the process
+    hasn't terminated yet.  A negative value -N indicates that the
+    child was terminated by signal N (UNIX only).
+
+
+Replacing older functions with the subprocess module
+====================================================
+In this section, "a ==> b" means that b can be used as a replacement
+for a.
+
+Note: All functions in this section fail (more or less) silently if
+the executed program cannot be found; this module raises an OSError
+exception.
+
+In the following examples, we assume that the subprocess module is
+imported with "from subprocess import *".
+
+
+Replacing /bin/sh shell backquote
+---------------------------------
+output=`mycmd myarg`
+==>
+output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]
+
+
+Replacing shell pipe line
+-------------------------
+output=`dmesg | grep hda`
+==>
+p1 = Popen(["dmesg"], stdout=PIPE)
+p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+output = p2.communicate()[0]
+
+
+Replacing os.system()
+---------------------
+sts = os.system("mycmd" + " myarg")
+==>
+p = Popen("mycmd" + " myarg", shell=True)
+sts = os.waitpid(p.pid, 0)
+
+Note:
+
+* Calling the program through the shell is usually not required.
+
+* It's easier to look at the returncode attribute than the
+  exitstatus.
+
+A more real-world example would look like this:
+
+try:
+    retcode = call("mycmd" + " myarg", shell=True)
+    if retcode < 0:
+        print >>sys.stderr, "Child was terminated by signal", -retcode
+    else:
+        print >>sys.stderr, "Child returned", retcode
+except OSError, e:
+    print >>sys.stderr, "Execution failed:", e
+
+
+Replacing os.spawn*
+-------------------
+P_NOWAIT example:
+
+pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+pid = Popen(["/bin/mycmd", "myarg"]).pid
+
+
+P_WAIT example:
+
+retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+retcode = call(["/bin/mycmd", "myarg"])
+
+
+Vector example:
+
+os.spawnvp(os.P_NOWAIT, path, args)
+==>
+Popen([path] + args[1:])
+
+
+Environment example:
+
+os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
+==>
+Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
+
+
+Replacing os.popen*
+-------------------
+pipe = os.popen(cmd, mode='r', bufsize)
+==>
+pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout
+
+pipe = os.popen(cmd, mode='w', bufsize)
+==>
+pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin
+
+
+(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdin, child_stdout) = (p.stdin, p.stdout)
+
+
+(child_stdin,
+ child_stdout,
+ child_stderr) = os.popen3(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+(child_stdin,
+ child_stdout,
+ child_stderr) = (p.stdin, p.stdout, p.stderr)
+
+
+(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
+(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
+
+
+Replacing popen2.*
+------------------
+Note: If the cmd argument to popen2 functions is a string, the command
+is executed through /bin/sh.  If it is a list, the command is directly
+executed.
+
+(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
+==>
+p = Popen(["somestring"], shell=True, bufsize=bufsize
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+
+(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
+==>
+p = Popen(["mycmd", "myarg"], bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen,
+except that:
+
+* subprocess.Popen raises an exception if the execution fails
+* the capturestderr argument is replaced with the stderr argument.
+* stdin=PIPE and stdout=PIPE must be specified.
+* popen2 closes all filedescriptors by default, but you have to specify
+  close_fds=True with subprocess.Popen.
+
+
+"""
+
+import sys
+mswindows = (sys.platform == "win32")
+
+import os
+import types
+import traceback
+
+if mswindows:
+    import threading
+    import msvcrt
+    ## @@: Changed in Paste
+    ## Since this module is only used on pre-python-2.4 systems, they probably
+    ## don't have _subprocess installed, but hopefully have the win32 stuff
+    ## installed.
+    if 1: # <-- change this to use pywin32 instead of the _subprocess driver
+        import pywintypes
+        from win32api import GetStdHandle, STD_INPUT_HANDLE, \
+                             STD_OUTPUT_HANDLE, STD_ERROR_HANDLE
+        from win32api import GetCurrentProcess, DuplicateHandle, \
+                             GetModuleFileName, GetVersion
+        from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE
+        from win32pipe import CreatePipe
+        from win32process import CreateProcess, STARTUPINFO, \
+                                 GetExitCodeProcess, STARTF_USESTDHANDLES, \
+                                 STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
+        from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
+    else:
+        from _subprocess import *
+        class STARTUPINFO:
+            dwFlags = 0
+            hStdInput = None
+            hStdOutput = None
+            hStdError = None
+        class pywintypes:
+            error = IOError
+else:
+    import select
+    import errno
+    import fcntl
+    import pickle
+
+__all__ = ["Popen", "PIPE", "STDOUT", "call"]
+
+try:
+    MAXFD = os.sysconf("SC_OPEN_MAX")
+except:
+    MAXFD = 256
+
+# True/False does not exist on 2.2.0
+try:
+    False
+except NameError:
+    False = 0
+    True = 1
+
+_active = []
+
+def _cleanup():
+    for inst in _active[:]:
+        inst.poll()
+
+PIPE = -1
+STDOUT = -2
+
+
+def call(*args, **kwargs):
+    """Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+    """
+    return Popen(*args, **kwargs).wait()
+
+
+def list2cmdline(seq):
+    """
+    Translate a sequence of arguments into a command line
+    string, using the same rules as the MS C runtime:
+
+    1) Arguments are delimited by white space, which is either a
+       space or a tab.
+
+    2) A string surrounded by double quotation marks is
+       interpreted as a single argument, regardless of white space
+       contained within.  A quoted string can be embedded in an
+       argument.
+
+    3) A double quotation mark preceded by a backslash is
+       interpreted as a literal double quotation mark.
+
+    4) Backslashes are interpreted literally, unless they
+       immediately precede a double quotation mark.
+
+    5) If backslashes immediately precede a double quotation mark,
+       every pair of backslashes is interpreted as a literal
+       backslash.  If the number of backslashes is odd, the last
+       backslash escapes the next double quotation mark as
+       described in rule 3.
+    """
+
+    # See
+    # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
+    result = []
+    needquote = False
+    for arg in seq:
+        bs_buf = []
+
+        # Add a space to separate this argument from the others
+        if result:
+            result.append(' ')
+
+        needquote = (" " in arg) or ("\t" in arg)
+        if needquote:
+            result.append('"')
+
+        for c in arg:
+            if c == '\\':
+                # Don't know if we need to double yet.
+                bs_buf.append(c)
+            elif c == '"':
+                # Double backspaces.
+                result.append('\\' * len(bs_buf)*2)
+                bs_buf = []
+                result.append('\\"')
+            else:
+                # Normal char
+                if bs_buf:
+                    result.extend(bs_buf)
+                    bs_buf = []
+                result.append(c)
+
+        # Add remaining backspaces, if any.
+        if bs_buf:
+            result.extend(bs_buf)
+
+        if needquote:
+            result.extend(bs_buf)
+            result.append('"')
+
+    return ''.join(result)
+
+
+class Popen(object):
+    def __init__(self, args, bufsize=0, executable=None,
+                 stdin=None, stdout=None, stderr=None,
+                 preexec_fn=None, close_fds=False, shell=False,
+                 cwd=None, env=None, universal_newlines=False,
+                 startupinfo=None, creationflags=0):
+        """Create new Popen instance."""
+        _cleanup()
+
+        if not isinstance(bufsize, (int, long)):
+            raise TypeError("bufsize must be an integer")
+
+        if mswindows:
+            if preexec_fn is not None:
+                raise ValueError("preexec_fn is not supported on Windows "
+                                 "platforms")
+            if close_fds:
+                raise ValueError("close_fds is not supported on Windows "
+                                 "platforms")
+        else:
+            # POSIX
+            if startupinfo is not None:
+                raise ValueError("startupinfo is only supported on Windows "
+                                 "platforms")
+            if creationflags != 0:
+                raise ValueError("creationflags is only supported on Windows "
+                                 "platforms")
+
+        self.stdin = None
+        self.stdout = None
+        self.stderr = None
+        self.pid = None
+        self.returncode = None
+        self.universal_newlines = universal_newlines
+
+        # Input and output objects. The general principle is like
+        # this:
+        #
+        # Parent                   Child
+        # ------                   -----
+        # p2cwrite   ---stdin--->  p2cread
+        # c2pread    <--stdout---  c2pwrite
+        # errread    <--stderr---  errwrite
+        #
+        # On POSIX, the child objects are file descriptors.  On
+        # Windows, these are Windows file handles.  The parent objects
+        # are file descriptors on both platforms.  The parent objects
+        # are None when not using PIPEs. The child objects are None
+        # when not redirecting.
+
+        (p2cread, p2cwrite,
+         c2pread, c2pwrite,
+         errread, errwrite) = self._get_handles(stdin, stdout, stderr)
+
+        self._execute_child(args, executable, preexec_fn, close_fds,
+                            cwd, env, universal_newlines,
+                            startupinfo, creationflags, shell,
+                            p2cread, p2cwrite,
+                            c2pread, c2pwrite,
+                            errread, errwrite)
+
+        if p2cwrite:
+            self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
+        if c2pread:
+            if universal_newlines:
+                self.stdout = os.fdopen(c2pread, 'rU', bufsize)
+            else:
+                self.stdout = os.fdopen(c2pread, 'rb', bufsize)
+        if errread:
+            if universal_newlines:
+                self.stderr = os.fdopen(errread, 'rU', bufsize)
+            else:
+                self.stderr = os.fdopen(errread, 'rb', bufsize)
+
+        _active.append(self)
+
+
+    def _translate_newlines(self, data):
+        data = data.replace("\r\n", "\n")
+        data = data.replace("\r", "\n")
+        return data
+
+
+    if mswindows:
+        #
+        # Windows methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tupel with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            if stdin == None and stdout == None and stderr == None:
+                return (None, None, None, None, None, None)
+
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin == None:
+                p2cread = GetStdHandle(STD_INPUT_HANDLE)
+            elif stdin == PIPE:
+                p2cread, p2cwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                p2cwrite = p2cwrite.Detach()
+                p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0)
+            elif type(stdin) == types.IntType:
+                p2cread = msvcrt.get_osfhandle(stdin)
+            else:
+                # Assuming file-like object
+                p2cread = msvcrt.get_osfhandle(stdin.fileno())
+            p2cread = self._make_inheritable(p2cread)
+
+            if stdout == None:
+                c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)
+            elif stdout == PIPE:
+                c2pread, c2pwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                c2pread = c2pread.Detach()
+                c2pread = msvcrt.open_osfhandle(c2pread, 0)
+            elif type(stdout) == types.IntType:
+                c2pwrite = msvcrt.get_osfhandle(stdout)
+            else:
+                # Assuming file-like object
+                c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
+            c2pwrite = self._make_inheritable(c2pwrite)
+
+            if stderr == None:
+                errwrite = GetStdHandle(STD_ERROR_HANDLE)
+            elif stderr == PIPE:
+                errread, errwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                errread = errread.Detach()
+                errread = msvcrt.open_osfhandle(errread, 0)
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif type(stderr) == types.IntType:
+                errwrite = msvcrt.get_osfhandle(stderr)
+            else:
+                # Assuming file-like object
+                errwrite = msvcrt.get_osfhandle(stderr.fileno())
+            errwrite = self._make_inheritable(errwrite)
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _make_inheritable(self, handle):
+            """Return a duplicate of handle, which is inheritable"""
+            return DuplicateHandle(GetCurrentProcess(), handle,
+                                   GetCurrentProcess(), 0, 1,
+                                   DUPLICATE_SAME_ACCESS)
+
+
+        def _find_w9xpopen(self):
+            """Find and return absolut path to w9xpopen.exe"""
+            w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)),
+                                    "w9xpopen.exe")
+            if not os.path.exists(w9xpopen):
+                # Eeek - file-not-found - possibly an embedding
+                # situation - see if we can locate it in sys.exec_prefix
+                w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix),
+                                        "w9xpopen.exe")
+                if not os.path.exists(w9xpopen):
+                    raise RuntimeError("Cannot locate w9xpopen.exe, which is "
+                                       "needed for Popen to work with your "
+                                       "shell or platform.")
+            return w9xpopen
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (MS Windows version)"""
+
+            if not isinstance(args, types.StringTypes):
+                args = list2cmdline(args)
+
+            # Process startup details
+            default_startupinfo = STARTUPINFO()
+            if startupinfo == None:
+                startupinfo = default_startupinfo
+            if not None in (p2cread, c2pwrite, errwrite):
+                startupinfo.dwFlags |= STARTF_USESTDHANDLES
+                startupinfo.hStdInput = p2cread
+                startupinfo.hStdOutput = c2pwrite
+                startupinfo.hStdError = errwrite
+
+            if shell:
+                default_startupinfo.dwFlags |= STARTF_USESHOWWINDOW
+                default_startupinfo.wShowWindow = SW_HIDE
+                comspec = os.environ.get("COMSPEC", "cmd.exe")
+                args = comspec + " /c " + args
+                if (GetVersion() >= 0x80000000L or
+                        os.path.basename(comspec).lower() == "command.com"):
+                    # Win9x, or using command.com on NT. We need to
+                    # use the w9xpopen intermediate program. For more
+                    # information, see KB Q150956
+                    # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp)
+                    w9xpopen = self._find_w9xpopen()
+                    args = '"%s" %s' % (w9xpopen, args)
+                    # Not passing CREATE_NEW_CONSOLE has been known to
+                    # cause random failures on win9x.  Specifically a
+                    # dialog: "Your program accessed mem currently in
+                    # use at xxx" and a hopeful warning about the
+                    # stability of your system.  Cost is Ctrl+C wont
+                    # kill children.
+                    creationflags |= CREATE_NEW_CONSOLE
+
+            # Start the process
+            try:
+                hp, ht, pid, tid = CreateProcess(executable, args,
+                                         # no special security
+                                         None, None,
+                                         # must inherit handles to pass std
+                                         # handles
+                                         1,
+                                         creationflags,
+                                         env,
+                                         cwd,
+                                         startupinfo)
+            except pywintypes.error, e:
+                # Translate pywintypes.error to WindowsError, which is
+                # a subclass of OSError.  FIXME: We should really
+                # translate errno using _sys_errlist (or simliar), but
+                # how can this be done from Python?
+                raise WindowsError(*e.args)
+
+            # Retain the process handle, but close the thread handle
+            self._handle = hp
+            self.pid = pid
+            ht.Close()
+
+            # Child is launched. Close the parent's copy of those pipe
+            # handles that only the child should have open.  You need
+            # to make sure that no handles to the write end of the
+            # output pipe are maintained in this process or else the
+            # pipe will not close when the child process exits and the
+            # ReadFile will hang.
+            if p2cread != None:
+                p2cread.Close()
+            if c2pwrite != None:
+                c2pwrite.Close()
+            if errwrite != None:
+                errwrite.Close()
+
+
+        def poll(self):
+            """Check if child process has terminated.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0:
+                    self.returncode = GetExitCodeProcess(self._handle)
+                    _active.remove(self)
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                obj = WaitForSingleObject(self._handle, INFINITE)
+                self.returncode = GetExitCodeProcess(self._handle)
+                _active.remove(self)
+            return self.returncode
+
+
+        def _readerthread(self, fh, buffer):
+            buffer.append(fh.read())
+
+
+        def communicate(self, input=None):
+            """Interact with process: Send data to stdin.  Read data from
+            stdout and stderr, until end-of-file is reached.  Wait for
+            process to terminate.  The optional input argument should be a
+            string to be sent to the child process, or None, if no data
+            should be sent to the child.
+
+            communicate() returns a tuple (stdout, stderr)."""
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdout:
+                stdout = []
+                stdout_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stdout, stdout))
+                stdout_thread.setDaemon(True)
+                stdout_thread.start()
+            if self.stderr:
+                stderr = []
+                stderr_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stderr, stderr))
+                stderr_thread.setDaemon(True)
+                stderr_thread.start()
+
+            if self.stdin:
+                if input != None:
+                    self.stdin.write(input)
+                self.stdin.close()
+
+            if self.stdout:
+                stdout_thread.join()
+            if self.stderr:
+                stderr_thread.join()
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout != None:
+                stdout = stdout[0]
+            if stderr != None:
+                stderr = stderr[0]
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(open, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+    else:
+        #
+        # POSIX methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tupel with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin == None:
+                pass
+            elif stdin == PIPE:
+                p2cread, p2cwrite = os.pipe()
+            elif type(stdin) == types.IntType:
+                p2cread = stdin
+            else:
+                # Assuming file-like object
+                p2cread = stdin.fileno()
+
+            if stdout == None:
+                pass
+            elif stdout == PIPE:
+                c2pread, c2pwrite = os.pipe()
+            elif type(stdout) == types.IntType:
+                c2pwrite = stdout
+            else:
+                # Assuming file-like object
+                c2pwrite = stdout.fileno()
+
+            if stderr == None:
+                pass
+            elif stderr == PIPE:
+                errread, errwrite = os.pipe()
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif type(stderr) == types.IntType:
+                errwrite = stderr
+            else:
+                # Assuming file-like object
+                errwrite = stderr.fileno()
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _set_cloexec_flag(self, fd):
+            try:
+                cloexec_flag = fcntl.FD_CLOEXEC
+            except AttributeError:
+                cloexec_flag = 1
+
+            old = fcntl.fcntl(fd, fcntl.F_GETFD)
+            fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)
+
+
+        def _close_fds(self, but):
+            for i in range(3, MAXFD):
+                if i == but:
+                    continue
+                try:
+                    os.close(i)
+                except:
+                    pass
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (POSIX version)"""
+
+            if isinstance(args, types.StringTypes):
+                args = [args]
+
+            if shell:
+                args = ["/bin/sh", "-c"] + args
+
+            if executable == None:
+                executable = args[0]
+
+            # For transferring possible exec failure from child to parent
+            # The first char specifies the exception type: 0 means
+            # OSError, 1 means some other error.
+            errpipe_read, errpipe_write = os.pipe()
+            self._set_cloexec_flag(errpipe_write)
+
+            self.pid = os.fork()
+            if self.pid == 0:
+                # Child
+                try:
+                    # Close parent's pipe ends
+                    if p2cwrite:
+                        os.close(p2cwrite)
+                    if c2pread:
+                        os.close(c2pread)
+                    if errread:
+                        os.close(errread)
+                    os.close(errpipe_read)
+
+                    # Dup fds for child
+                    if p2cread:
+                        os.dup2(p2cread, 0)
+                    if c2pwrite:
+                        os.dup2(c2pwrite, 1)
+                    if errwrite:
+                        os.dup2(errwrite, 2)
+
+                    # Close pipe fds.  Make sure we doesn't close the same
+                    # fd more than once.
+                    if p2cread:
+                        os.close(p2cread)
+                    if c2pwrite and c2pwrite not in (p2cread,):
+                        os.close(c2pwrite)
+                    if errwrite and errwrite not in (p2cread, c2pwrite):
+                        os.close(errwrite)
+
+                    # Close all other fds, if asked for
+                    if close_fds:
+                        self._close_fds(but=errpipe_write)
+
+                    if cwd != None:
+                        os.chdir(cwd)
+
+                    if preexec_fn:
+                        apply(preexec_fn)
+
+                    if env == None:
+                        os.execvp(executable, args)
+                    else:
+                        os.execvpe(executable, args, env)
+
+                except:
+                    exc_type, exc_value, tb = sys.exc_info()
+                    # Save the traceback and attach it to the exception object
+                    exc_lines = traceback.format_exception(exc_type,
+                                                           exc_value,
+                                                           tb)
+                    exc_value.child_traceback = ''.join(exc_lines)
+                    os.write(errpipe_write, pickle.dumps(exc_value))
+
+                # This exitcode won't be reported to applications, so it
+                # really doesn't matter what we return.
+                os._exit(255)
+
+            # Parent
+            os.close(errpipe_write)
+            if p2cread and p2cwrite:
+                os.close(p2cread)
+            if c2pwrite and c2pread:
+                os.close(c2pwrite)
+            if errwrite and errread:
+                os.close(errwrite)
+
+            # Wait for exec to fail or succeed; possibly raising exception
+            data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB
+            os.close(errpipe_read)
+            if data != "":
+                os.waitpid(self.pid, 0)
+                child_exception = pickle.loads(data)
+                raise child_exception
+
+
+        def _handle_exitstatus(self, sts):
+            if os.WIFSIGNALED(sts):
+                self.returncode = -os.WTERMSIG(sts)
+            elif os.WIFEXITED(sts):
+                self.returncode = os.WEXITSTATUS(sts)
+            else:
+                # Should never happen
+                raise RuntimeError("Unknown child exit status!")
+
+            _active.remove(self)
+
+
+        def poll(self):
+            """Check if child process has terminated.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                try:
+                    pid, sts = os.waitpid(self.pid, os.WNOHANG)
+                    if pid == self.pid:
+                        self._handle_exitstatus(sts)
+                except os.error:
+                    pass
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                pid, sts = os.waitpid(self.pid, 0)
+                self._handle_exitstatus(sts)
+            return self.returncode
+
+
+        def communicate(self, input=None):
+            """Interact with process: Send data to stdin.  Read data from
+            stdout and stderr, until end-of-file is reached.  Wait for
+            process to terminate.  The optional input argument should be a
+            string to be sent to the child process, or None, if no data
+            should be sent to the child.
+
+            communicate() returns a tuple (stdout, stderr)."""
+            read_set = []
+            write_set = []
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdin:
+                # Flush stdio buffer.  This might block, if the user has
+                # been writing to .stdin in an uncontrolled fashion.
+                self.stdin.flush()
+                if input:
+                    write_set.append(self.stdin)
+                else:
+                    self.stdin.close()
+            if self.stdout:
+                read_set.append(self.stdout)
+                stdout = []
+            if self.stderr:
+                read_set.append(self.stderr)
+                stderr = []
+
+            while read_set or write_set:
+                rlist, wlist, xlist = select.select(read_set, write_set, [])
+
+                if self.stdin in wlist:
+                    # When select has indicated that the file is writable,
+                    # we can write up to PIPE_BUF bytes without risk
+                    # blocking.  POSIX defines PIPE_BUF >= 512
+                    bytes_written = os.write(self.stdin.fileno(), input[:512])
+                    input = input[bytes_written:]
+                    if not input:
+                        self.stdin.close()
+                        write_set.remove(self.stdin)
+
+                if self.stdout in rlist:
+                    data = os.read(self.stdout.fileno(), 1024)
+                    if data == "":
+                        self.stdout.close()
+                        read_set.remove(self.stdout)
+                    stdout.append(data)
+
+                if self.stderr in rlist:
+                    data = os.read(self.stderr.fileno(), 1024)
+                    if data == "":
+                        self.stderr.close()
+                        read_set.remove(self.stderr)
+                    stderr.append(data)
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout != None:
+                stdout = ''.join(stdout)
+            if stderr != None:
+                stderr = ''.join(stderr)
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(open, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+
+def _demo_posix():
+    #
+    # Example 1: Simple redirection: Get process list
+    #
+    plist = Popen(["ps"], stdout=PIPE).communicate()[0]
+    print "Process list:"
+    print plist
+
+    #
+    # Example 2: Change uid before executing child
+    #
+    if os.getuid() == 0:
+        p = Popen(["id"], preexec_fn=lambda: os.setuid(100))
+        p.wait()
+
+    #
+    # Example 3: Connecting several subprocesses
+    #
+    print "Looking for 'hda'..."
+    p1 = Popen(["dmesg"], stdout=PIPE)
+    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 4: Catch execution error
+    #
+    print
+    print "Trying a weird file..."
+    try:
+        print Popen(["/this/path/does/not/exist"]).communicate()
+    except OSError, e:
+        if e.errno == errno.ENOENT:
+            print "The file didn't exist.  I thought so..."
+            print "Child traceback:"
+            print e.child_traceback
+        else:
+            print "Error", e.errno
+    else:
+        print >>sys.stderr, "Gosh.  No error."
+
+
+def _demo_windows():
+    #
+    # Example 1: Connecting several subprocesses
+    #
+    print "Looking for 'PROMPT' in set output..."
+    p1 = Popen("set", stdout=PIPE, shell=True)
+    p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 2: Simple execution of program
+    #
+    print "Executing calc..."
+    p = Popen("calc")
+    p.wait()
+
+
+if __name__ == "__main__":
+    if mswindows:
+        _demo_windows()
+    else:
+        _demo_posix()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/template.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/template.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/template.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,758 @@
+"""
+A small templating language
+
+This implements a small templating language for use internally in
+Paste and Paste Script.  This language implements if/elif/else,
+for/continue/break, expressions, and blocks of Python code.  The
+syntax is::
+
+  {{any expression (function calls etc)}}
+  {{any expression | filter}}
+  {{for x in y}}...{{endfor}}
+  {{if x}}x{{elif y}}y{{else}}z{{endif}}
+  {{py:x=1}}
+  {{py:
+  def foo(bar):
+      return 'baz'
+  }}
+  {{default var = default_value}}
+  {{# comment}}
+
+You use this with the ``Template`` class or the ``sub`` shortcut.
+The ``Template`` class takes the template string and the name of
+the template (for errors) and a default namespace.  Then (like
+``string.Template``) you can call the ``tmpl.substitute(**kw)``
+method to make a substitution (or ``tmpl.substitute(a_dict)``).
+
+``sub(content, **kw)`` substitutes the template immediately.  You
+can use ``__name='tmpl.html'`` to set the name of the template.
+
+If there are syntax errors ``TemplateError`` will be raised.
+"""
+
+import re
+import sys
+import cgi
+import urllib
+from paste.util.looper import looper
+
+__all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
+           'sub_html', 'html', 'bunch']
+
+token_re = re.compile(r'\{\{|\}\}')
+in_re = re.compile(r'\s+in\s+')
+var_re = re.compile(r'^[a-z_][a-z0-9_]*$', re.I)
+
+class TemplateError(Exception):
+    """Exception raised while parsing a template
+    """
+
+    def __init__(self, message, position, name=None):
+        self.message = message
+        self.position = position
+        self.name = name
+
+    def __str__(self):
+        msg = '%s at line %s column %s' % (
+            self.message, self.position[0], self.position[1])
+        if self.name:
+            msg += ' in %s' % self.name
+        return msg
+
+class _TemplateContinue(Exception):
+    pass
+
+class _TemplateBreak(Exception):
+    pass
+
+class Template(object):
+
+    default_namespace = {
+        'start_braces': '{{',
+        'end_braces': '}}',
+        'looper': looper,
+        }
+
+    default_encoding = 'utf8'
+
+    def __init__(self, content, name=None, namespace=None):
+        self.content = content
+        self._unicode = isinstance(content, unicode)
+        self.name = name
+        self._parsed = parse(content, name=name)
+        if namespace is None:
+            namespace = {}
+        self.namespace = namespace
+
+    def from_filename(cls, filename, namespace=None, encoding=None):
+        f = open(filename, 'rb')
+        c = f.read()
+        f.close()
+        if encoding:
+            c = c.decode(encoding)
+        return cls(content=c, name=filename, namespace=namespace)
+
+    from_filename = classmethod(from_filename)
+
+    def __repr__(self):
+        return '<%s %s name=%r>' % (
+            self.__class__.__name__,
+            hex(id(self))[2:], self.name)
+
+    def substitute(self, *args, **kw):
+        if args:
+            if kw:
+                raise TypeError(
+                    "You can only give positional *or* keyword arguments")
+            if len(args) > 1:
+                raise TypeError(
+                    "You can only give on positional argument")
+            kw = args[0]
+        ns = self.default_namespace.copy()
+        ns.update(self.namespace)
+        ns.update(kw)
+        result = self._interpret(ns)
+        return result
+
+    def _interpret(self, ns):
+        __traceback_hide__ = True
+        parts = []
+        self._interpret_codes(self._parsed, ns, out=parts)
+        return ''.join(parts)
+
+    def _interpret_codes(self, codes, ns, out):
+        __traceback_hide__ = True
+        for item in codes:
+            if isinstance(item, basestring):
+                out.append(item)
+            else:
+                self._interpret_code(item, ns, out)
+
+    def _interpret_code(self, code, ns, out):
+        __traceback_hide__ = True
+        name, pos = code[0], code[1]
+        if name == 'py':
+            self._exec(code[2], ns, pos)
+        elif name == 'continue':
+            raise _TemplateContinue()
+        elif name == 'break':
+            raise _TemplateBreak()
+        elif name == 'for':
+            vars, expr, content = code[2], code[3], code[4]
+            expr = self._eval(expr, ns, pos)
+            self._interpret_for(vars, expr, content, ns, out)
+        elif name == 'cond':
+            parts = code[2:]
+            self._interpret_if(parts, ns, out)
+        elif name == 'expr':
+            parts = code[2].split('|')
+            base = self._eval(parts[0], ns, pos)
+            for part in parts[1:]:
+                func = self._eval(part, ns, pos)
+                base = func(base)
+            out.append(self._repr(base, pos))
+        elif name == 'default':
+            var, expr = code[2], code[3]
+            if var not in ns:
+                result = self._eval(expr, ns, pos)
+                ns[var] = result
+        elif name == 'comment':
+            return
+        else:
+            assert 0, "Unknown code: %r" % name
+
+    def _interpret_for(self, vars, expr, content, ns, out):
+        __traceback_hide__ = True
+        for item in expr:
+            if len(vars) == 1:
+                ns[vars[0]] = item
+            else:
+                if len(vars) != len(item):
+                    raise ValueError(
+                        'Need %i items to unpack (got %i items)'
+                        % (len(vars), len(item)))
+                for name, value in zip(vars, item):
+                    ns[name] = value
+            try:
+                self._interpret_codes(content, ns, out)
+            except _TemplateContinue:
+                continue
+            except _TemplateBreak:
+                break
+
+    def _interpret_if(self, parts, ns, out):
+        __traceback_hide__ = True
+        # @@: if/else/else gets through
+        for part in parts:
+            assert not isinstance(part, basestring)
+            name, pos = part[0], part[1]
+            if name == 'else':
+                result = True
+            else:
+                result = self._eval(part[2], ns, pos)
+            if result:
+                self._interpret_codes(part[3], ns, out)
+                break
+
+    def _eval(self, code, ns, pos):
+        __traceback_hide__ = True
+        try:
+            value = eval(code, ns)
+            return value
+        except:
+            exc_info = sys.exc_info()
+            e = exc_info[1]
+            if getattr(e, 'args'):
+                arg0 = e.args[0]
+            else:
+                arg0 = str(e)
+            e.args = (self._add_line_info(arg0, pos),)
+            raise exc_info[0], e, exc_info[2]
+
+    def _exec(self, code, ns, pos):
+        __traceback_hide__ = True
+        try:
+            exec code in ns
+        except:
+            exc_info = sys.exc_info()
+            e = exc_info[1]
+            e.args = (self._add_line_info(e.args[0], pos),)
+            raise exc_info[0], e, exc_info[2]
+
+    def _repr(self, value, pos):
+        __traceback_hide__ = True
+        try:
+            if value is None:
+                return ''
+            if self._unicode:
+                try:
+                    value = unicode(value)
+                except UnicodeDecodeError:
+                    value = str(value)
+            else:
+                value = str(value)
+        except:
+            exc_info = sys.exc_info()
+            e = exc_info[1]
+            e.args = (self._add_line_info(e.args[0], pos),)
+            raise exc_info[0], e, exc_info[2]
+        else:
+            if self._unicode and isinstance(value, str):
+                if not self.decode_encoding:
+                    raise UnicodeDecodeError(
+                        'Cannot decode str value %r into unicode '
+                        '(no default_encoding provided)' % value)
+                value = value.decode(self.default_encoding)
+            elif not self._unicode and isinstance(value, unicode):
+                if not self.decode_encoding:
+                    raise UnicodeEncodeError(
+                        'Cannot encode unicode value %r into str '
+                        '(no default_encoding provided)' % value)
+                value = value.encode(self.default_encoding)
+            return value
+        
+
+    def _add_line_info(self, msg, pos):
+        msg = "%s at line %s column %s" % (
+            msg, pos[0], pos[1])
+        if self.name:
+            msg += " in file %s" % self.name
+        return msg
+
+def sub(content, **kw):
+    name = kw.get('__name')
+    tmpl = Template(content, name=name)
+    return tmpl.substitute(kw)
+    return result
+
+def paste_script_template_renderer(content, vars, filename=None):
+    tmpl = Template(content, name=filename)
+    return tmpl.substitute(vars)
+
+class bunch(dict):
+
+    def __init__(self, **kw):
+        for name, value in kw.items():
+            setattr(self, name, value)
+
+    def __setattr__(self, name, value):
+        self[name] = value
+
+    def __getattr__(self, name):
+        try:
+            return self[name]
+        except KeyError:
+            raise AttributeError(name)
+
+    def __getitem__(self, key):
+        if 'default' in self:
+            try:
+                return dict.__getitem__(self, key)
+            except KeyError:
+                return dict.__getitem__(self, 'default')
+        else:
+            return dict.__getitem__(self, key)
+
+    def __repr__(self):
+        items = [
+            (k, v) for k, v in self.items()]
+        items.sort()
+        return '<%s %s>' % (
+            self.__class__.__name__,
+            ' '.join(['%s=%r' % (k, v) for k, v in items]))
+
+############################################################
+## HTML Templating
+############################################################
+
+class html(object):
+    def __init__(self, value):
+        self.value = value
+    def __str__(self):
+        return self.value
+    def __repr__(self):
+        return '<%s %r>' % (
+            self.__class__.__name__, self.value)
+
+def html_quote(value):
+    if value is None:
+        return ''
+    if not isinstance(value, basestring):
+        if hasattr(value, '__unicode__'):
+            value = unicode(value)
+        else:
+            value = str(value)
+    value = cgi.escape(value, 1)
+    if isinstance(value, unicode):
+        value = value.encode('ascii', 'xmlcharrefreplace')
+    return value
+
+def url(v):
+    if not isinstance(v, basestring):
+        if hasattr(v, '__unicode__'):
+            v = unicode(v)
+        else:
+            v = str(v)
+    if isinstance(v, unicode):
+        v = v.encode('utf8')
+    return urllib.quote(v)
+
+def attr(**kw):
+    kw = kw.items()
+    kw.sort()
+    parts = []
+    for name, value in kw:
+        if value is None:
+            continue
+        if name.endswith('_'):
+            name = name[:-1]
+        parts.append('%s="%s"' % (html_quote(name), html_quote(value)))
+    return html(' '.join(parts))
+
+class HTMLTemplate(Template):
+
+    default_namespace = Template.default_namespace.copy()
+    default_namespace.update(dict(
+        html=html,
+        attr=attr,
+        url=url,
+        ))
+
+    def _repr(self, value, pos):
+        plain = Template._repr(self, value, pos)
+        if isinstance(value, html):
+            return plain
+        else:
+            return html_quote(plain)
+
+def sub_html(content, **kw):
+    name = kw.get('__name')
+    tmpl = HTMLTemplate(content, name=name)
+    return tmpl.substitute(kw)
+    return result
+
+
+############################################################
+## Lexing and Parsing
+############################################################
+
+def lex(s, name=None, trim_whitespace=True):
+    """
+    Lex a string into chunks:
+
+        >>> lex('hey')
+        ['hey']
+        >>> lex('hey {{you}}')
+        ['hey ', ('you', (1, 7))]
+        >>> lex('hey {{')
+        Traceback (most recent call last):
+            ...
+        TemplateError: No }} to finish last expression at line 1 column 7
+        >>> lex('hey }}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: }} outside expression at line 1 column 7
+        >>> lex('hey {{ {{')
+        Traceback (most recent call last):
+            ...
+        TemplateError: {{ inside expression at line 1 column 10
+
+    """
+    in_expr = False
+    chunks = []
+    last = 0
+    last_pos = (1, 1)
+    for match in token_re.finditer(s):
+        expr = match.group(0)
+        pos = find_position(s, match.end())
+        if expr == '{{' and in_expr:
+            raise TemplateError('{{ inside expression', position=pos,
+                                name=name)
+        elif expr == '}}' and not in_expr:
+            raise TemplateError('}} outside expression', position=pos,
+                                name=name)
+        if expr == '{{':
+            part = s[last:match.start()]
+            if part:
+                chunks.append(part)
+            in_expr = True
+        else:
+            chunks.append((s[last:match.start()], last_pos))
+            in_expr = False
+        last = match.end()
+        last_pos = pos
+    if in_expr:
+        raise TemplateError('No }} to finish last expression',
+                            name=name, position=last_pos)
+    part = s[last:]
+    if part:
+        chunks.append(part)
+    if trim_whitespace:
+        chunks = trim_lex(chunks)
+    return chunks
+
+statement_re = re.compile(r'^(?:if |elif |else |for |py:)')
+single_statements = ['endif', 'endfor', 'continue', 'break']
+trail_whitespace_re = re.compile(r'\n[\t ]*$')
+lead_whitespace_re = re.compile(r'^[\t ]*\n')
+
+def trim_lex(tokens):
+    r"""
+    Takes a lexed set of tokens, and removes whitespace when there is
+    a directive on a line by itself:
+
+       >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
+       >>> tokens
+       [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
+       >>> trim_lex(tokens)
+       [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
+    """
+    for i in range(len(tokens)):
+        current = tokens[i]
+        if isinstance(tokens[i], basestring):
+            # we don't trim this
+            continue
+        item = current[0]
+        if not statement_re.search(item) and item not in single_statements:
+            continue
+        if not i:
+            prev = ''
+        else:
+            prev = tokens[i-1]
+        if i+1 >= len(tokens):
+            next = ''
+        else:
+            next = tokens[i+1]
+        if (not isinstance(next, basestring)
+            or not isinstance(prev, basestring)):
+            continue
+        if ((not prev or trail_whitespace_re.search(prev))
+            and (not next or lead_whitespace_re.search(next))):
+            if prev:
+                m = trail_whitespace_re.search(prev)
+                # +1 to leave the leading \n on:
+                prev = prev[:m.start()+1]
+                tokens[i-1] = prev
+            if next:
+                m = lead_whitespace_re.search(next)
+                next = next[m.end():]
+                tokens[i+1] = next
+    return tokens
+        
+
+def find_position(string, index):
+    """Given a string and index, return (line, column)"""
+    leading = string[:index].splitlines()
+    return (len(leading), len(leading[-1])+1)
+
+def parse(s, name=None):
+    r"""
+    Parses a string into a kind of AST
+
+        >>> parse('{{x}}')
+        [('expr', (1, 3), 'x')]
+        >>> parse('foo')
+        ['foo']
+        >>> parse('{{if x}}test{{endif}}')
+        [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
+        >>> parse('series->{{for x in y}}x={{x}}{{endfor}}')
+        ['series->', ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
+        >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
+        [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
+        >>> parse('{{py:x=1}}')
+        [('py', (1, 3), 'x=1')]
+        >>> parse('{{if x}}a{{elif y}}b{{else}}c{{endif}}')
+        [('cond', (1, 3), ('if', (1, 3), 'x', ['a']), ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
+
+    Some exceptions::
+        
+        >>> parse('{{continue}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: continue outside of for loop at line 1 column 3
+        >>> parse('{{if x}}foo')
+        Traceback (most recent call last):
+            ...
+        TemplateError: No {{endif}} at line 1 column 3
+        >>> parse('{{else}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: else outside of an if block at line 1 column 3
+        >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: Unexpected endif at line 1 column 25
+        >>> parse('{{if}}{{endif}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: if with no expression at line 1 column 3
+        >>> parse('{{for x y}}{{endfor}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
+        >>> parse('{{py:x=1\ny=2}}')
+        Traceback (most recent call last):
+            ...
+        TemplateError: Multi-line py blocks must start with a newline at line 1 column 3
+    """
+    tokens = lex(s, name=name)
+    result = []
+    while tokens:
+        next, tokens = parse_expr(tokens, name)
+        result.append(next)
+    return result
+
+def parse_expr(tokens, name, context=()):
+    if isinstance(tokens[0], basestring):
+        return tokens[0], tokens[1:]
+    expr, pos = tokens[0]
+    expr = expr.strip()
+    if expr.startswith('py:'):
+        expr = expr[3:].lstrip(' \t')
+        if expr.startswith('\n'):
+            expr = expr[1:]
+        else:
+            if '\n' in expr:
+                raise TemplateError(
+                    'Multi-line py blocks must start with a newline',
+                    position=pos, name=name)
+        return ('py', pos, expr), tokens[1:]
+    elif expr in ('continue', 'break'):
+        if 'for' not in context:
+            raise TemplateError(
+                'continue outside of for loop',
+                position=pos, name=name)
+        return (expr, pos), tokens[1:]
+    elif expr.startswith('if '):
+        return parse_cond(tokens, name, context)
+    elif (expr.startswith('elif ')
+          or expr == 'else'):
+        raise TemplateError(
+            '%s outside of an if block' % expr.split()[0],
+            position=pos, name=name)
+    elif expr in ('if', 'elif', 'for'):
+        raise TemplateError(
+            '%s with no expression' % expr,
+            position=pos, name=name)
+    elif expr in ('endif', 'endfor'):
+        raise TemplateError(
+            'Unexpected %s' % expr,
+            position=pos, name=name)
+    elif expr.startswith('for '):
+        return parse_for(tokens, name, context)
+    elif expr.startswith('default '):
+        return parse_default(tokens, name, context)
+    elif expr.startswith('#'):
+        return ('comment', pos, tokens[0][0]), tokens[1:]
+    return ('expr', pos, tokens[0][0]), tokens[1:]
+
+def parse_cond(tokens, name, context):
+    start = tokens[0][1]
+    pieces = []
+    context = context + ('if',)
+    while 1:
+        if not tokens:
+            raise TemplateError(
+                'Missing {{endif}}',
+                position=start, name=name)
+        if (isinstance(tokens[0], tuple)
+            and tokens[0][0] == 'endif'):
+            return ('cond', start) + tuple(pieces), tokens[1:]
+        next, tokens = parse_one_cond(tokens, name, context)
+        pieces.append(next)
+
+def parse_one_cond(tokens, name, context):
+    (first, pos), tokens = tokens[0], tokens[1:]
+    content = []
+    if first.endswith(':'):
+        first = first[:-1]
+    if first.startswith('if '):
+        part = ('if', pos, first[3:].lstrip(), content)
+    elif first.startswith('elif '):
+        part = ('elif', pos, first[5:].lstrip(), content)
+    elif first == 'else':
+        part = ('else', pos, None, content)
+    else:
+        assert 0, "Unexpected token %r at %s" % (first, pos)
+    while 1:
+        if not tokens:
+            raise TemplateError(
+                'No {{endif}}',
+                position=pos, name=name)
+        if (isinstance(tokens[0], tuple)
+            and (tokens[0][0] == 'endif'
+                 or tokens[0][0].startswith('elif ')
+                 or tokens[0][0] == 'else')):
+            return part, tokens
+        next, tokens = parse_expr(tokens, name, context)
+        content.append(next)
+        
+def parse_for(tokens, name, context):
+    first, pos = tokens[0]
+    tokens = tokens[1:]
+    context = ('for',) + context
+    content = []
+    assert first.startswith('for ')
+    if first.endswith(':'):
+        first = first[:-1]
+    first = first[3:].strip()
+    match = in_re.search(first)
+    if not match:
+        raise TemplateError(
+            'Bad for (no "in") in %r' % first,
+            position=pos, name=name)
+    vars = first[:match.start()]
+    if '(' in vars:
+        raise TemplateError(
+            'You cannot have () in the variable section of a for loop (%r)'
+            % vars, position=pos, name=name)
+    vars = tuple([
+        v.strip() for v in first[:match.start()].split(',')
+        if v.strip()])
+    expr = first[match.end():]
+    while 1:
+        if not tokens:
+            raise TemplateError(
+                'No {{endfor}}',
+                position=pos, name=name)
+        if (isinstance(tokens[0], tuple)
+            and tokens[0][0] == 'endfor'):
+            return ('for', pos, vars, expr, content), tokens[1:]
+        next, tokens = parse_expr(tokens, name, context)
+        content.append(next)
+
+def parse_default(tokens, name, context):
+    first, pos = tokens[0]
+    assert first.startswith('default ')
+    first = first.split(None, 1)[1]
+    parts = first.split('=', 1)
+    if len(parts) == 1:
+        raise TemplateError(
+            "Expression must be {{default var=value}}; no = found in %r" % first,
+            position=pos, name=name)
+    var = parts[0].strip()
+    if ',' in var:
+        raise TemplateError(
+            "{{default x, y = ...}} is not supported",
+            position=pos, name=name)
+    if not var_re.search(var):
+        raise TemplateError(
+            "Not a valid variable name for {{default}}: %r"
+            % var, position=pos, name=name)
+    expr = parts[1].strip()
+    return ('default', pos, var, expr), tokens[1:]
+
+_fill_command_usage = """\
+%prog [OPTIONS] TEMPLATE arg=value
+
+Use py:arg=value to set a Python value; otherwise all values are
+strings.
+"""
+
+def fill_command(args=None):
+    import sys, optparse, pkg_resources, os
+    if args is None:
+        args = sys.argv[1:]
+    dist = pkg_resources.get_distribution('Paste')
+    parser = optparse.OptionParser(
+        version=str(dist),
+        usage=_fill_command_usage)
+    parser.add_option(
+        '-o', '--output',
+        dest='output',
+        metavar="FILENAME",
+        help="File to write output to (default stdout)")
+    parser.add_option(
+        '--html',
+        dest='use_html',
+        action='store_true',
+        help="Use HTML style filling (including automatic HTML quoting)")
+    parser.add_option(
+        '--env',
+        dest='use_env',
+        action='store_true',
+        help="Put the environment in as top-level variables")
+    options, args = parser.parse_args(args)
+    if len(args) < 1:
+        print 'You must give a template filename'
+        print dir(parser)
+        assert 0
+    template_name = args[0]
+    args = args[1:]
+    vars = {}
+    if options.use_env:
+        vars.update(os.environ)
+    for value in args:
+        if '=' not in value:
+            print 'Bad argument: %r' % value
+            sys.exit(2)
+        name, value = value.split('=', 1)
+        if name.startswith('py:'):
+            name = name[:3]
+            value = eval(value)
+        vars[name] = value
+    if template_name == '-':
+        template_content = sys.stdin.read()
+        template_name = '<stdin>'
+    else:
+        f = open(template_name, 'rb')
+        template_content = f.read()
+        f.close()
+    if options.use_html:
+        TemplateClass = HTMLTemplate
+    else:
+        TemplateClass = Template
+    template = TemplateClass(template_content, name=template_name)
+    result = template.substitute(vars)
+    if options.output:
+        f = open(options.output, 'wb')
+        f.write(result)
+        f.close()
+    else:
+        sys.stdout.write(result)
+
+if __name__ == '__main__':
+    from paste.util.template import fill_command
+    fill_command()
+        
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadedprint.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadedprint.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadedprint.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,250 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+threadedprint.py
+================
+
+:author: Ian Bicking
+:date: 12 Jul 2004
+
+Multi-threaded printing; allows the output produced via print to be
+separated according to the thread.
+
+To use this, you must install the catcher, like::
+
+    threadedprint.install()
+
+The installation optionally takes one of three parameters:
+
+default
+    The default destination for print statements (e.g., ``sys.stdout``).
+factory
+    A function that will produce the stream for a thread, given the
+    thread's name.
+paramwriter
+    Instead of writing to a file-like stream, this function will be
+    called like ``paramwriter(thread_name, text)`` for every write.
+
+The thread name is the value returned by
+``threading.currentThread().getName()``, a string (typically something
+like Thread-N).
+
+You can also submit file-like objects for specific threads, which will
+override any of these parameters.  To do this, call ``register(stream,
+[threadName])``.  ``threadName`` is optional, and if not provided the
+stream will be registered for the current thread.
+
+If no specific stream is registered for a thread, and no default has
+been provided, then an error will occur when anything is written to
+``sys.stdout`` (or printed).
+
+Note: the stream's ``write`` method will be called in the thread the
+text came from, so you should consider thread safety, especially if
+multiple threads share the same writer.
+
+Note: if you want access to the original standard out, use
+``sys.__stdout__``.
+
+You may also uninstall this, via::
+
+    threadedprint.uninstall()
+
+TODO
+----
+
+* Something with ``sys.stderr``.
+* Some default handlers.  Maybe something that hooks into `logging`.
+* Possibly cache the results of ``factory`` calls.  This would be a
+  semantic change.
+
+"""
+
+import threading
+import sys
+from paste.util import filemixin
+
+class PrintCatcher(filemixin.FileMixin):
+
+    def __init__(self, default=None, factory=None, paramwriter=None,
+                 leave_stdout=False):
+        assert len(filter(lambda x: x is not None,
+                          [default, factory, paramwriter])) <= 1, (
+            "You can only provide one of default, factory, or paramwriter")
+        if leave_stdout:
+            assert not default, (
+                "You cannot pass in both default (%r) and "
+                "leave_stdout=True" % default)
+            default = sys.stdout
+        if default:
+            self._defaultfunc = self._writedefault
+        elif factory:
+            self._defaultfunc = self._writefactory
+        elif paramwriter:
+            self._defaultfunc = self._writeparam
+        else:
+            self._defaultfunc = self._writeerror
+        self._default = default
+        self._factory = factory
+        self._paramwriter = paramwriter
+        self._catchers = {}
+
+    def write(self, v, currentThread=threading.currentThread):
+        name = currentThread().getName()
+        catchers = self._catchers
+        if not catchers.has_key(name):
+            self._defaultfunc(name, v)
+        else:
+            catcher = catchers[name]
+            catcher.write(v)
+
+    def seek(self, *args):
+        # Weird, but Google App Engine is seeking on stdout
+        name = threading.currentThread().getName()
+        catchers = self._catchers
+        if not name in catchers:
+            self._default.seek(*args)
+        else:
+            catchers[name].seek(*args)
+
+    def read(self, *args):
+        name = threading.currentThread().getName()
+        catchers = self._catchers
+        if not name in catchers:
+            self._default.read(*args)
+        else:
+            catchers[name].read(*args)
+        
+
+    def _writedefault(self, name, v):
+        self._default.write(v)
+
+    def _writefactory(self, name, v):
+        self._factory(name).write(v)
+
+    def _writeparam(self, name, v):
+        self._paramwriter(name, v)
+
+    def _writeerror(self, name, v):
+        assert False, (
+            "There is no PrintCatcher output stream for the thread %r"
+            % name)
+
+    def register(self, catcher, name=None,
+                 currentThread=threading.currentThread):
+        if name is None:
+            name = currentThread().getName()
+        self._catchers[name] = catcher
+
+    def deregister(self, name=None,
+                   currentThread=threading.currentThread):
+        if name is None:
+            name = currentThread().getName()
+        assert self._catchers.has_key(name), (
+            "There is no PrintCatcher catcher for the thread %r" % name)
+        del self._catchers[name]
+
+_printcatcher = None
+_oldstdout = None
+
+def install(**kw):
+    global _printcatcher, _oldstdout, register, deregister
+    if (not _printcatcher or sys.stdout is not _printcatcher):
+        _oldstdout = sys.stdout
+        _printcatcher = sys.stdout = PrintCatcher(**kw)
+        register = _printcatcher.register
+        deregister = _printcatcher.deregister
+
+def uninstall():
+    global _printcatcher, _oldstdout, register, deregister
+    if _printcatcher:
+        sys.stdout = _oldstdout
+        _printcatcher = _oldstdout = None
+        register = not_installed_error
+        deregister = not_installed_error
+
+def not_installed_error(*args, **kw):
+    assert False, (
+        "threadedprint has not yet been installed (call "
+        "threadedprint.install())")
+
+register = deregister = not_installed_error
+
+class StdinCatcher(filemixin.FileMixin):
+
+    def __init__(self, default=None, factory=None, paramwriter=None):
+        assert len(filter(lambda x: x is not None,
+                          [default, factory, paramwriter])) <= 1, (
+            "You can only provide one of default, factory, or paramwriter")
+        if default:
+            self._defaultfunc = self._readdefault
+        elif factory:
+            self._defaultfunc = self._readfactory
+        elif paramwriter:
+            self._defaultfunc = self._readparam
+        else:
+            self._defaultfunc = self._readerror
+        self._default = default
+        self._factory = factory
+        self._paramwriter = paramwriter
+        self._catchers = {}
+
+    def read(self, size=None, currentThread=threading.currentThread):
+        name = currentThread().getName()
+        catchers = self._catchers
+        if not catchers.has_key(name):
+            return self._defaultfunc(name, size)
+        else:
+            catcher = catchers[name]
+            return catcher.read(size)
+
+    def _readdefault(self, name, size):
+        self._default.read(size)
+
+    def _readfactory(self, name, size):
+        self._factory(name).read(size)
+
+    def _readparam(self, name, size):
+        self._paramreader(name, size)
+
+    def _readerror(self, name, size):
+        assert False, (
+            "There is no StdinCatcher output stream for the thread %r"
+            % name)
+
+    def register(self, catcher, name=None,
+                 currentThread=threading.currentThread):
+        if name is None:
+            name = currentThread().getName()
+        self._catchers[name] = catcher
+
+    def deregister(self, catcher, name=None,
+                   currentThread=threading.currentThread):
+        if name is None:
+            name = currentThread().getName()
+        assert self._catchers.has_key(name), (
+            "There is no StdinCatcher catcher for the thread %r" % name)
+        del self._catchers[name]
+
+_stdincatcher = None
+_oldstdin = None
+
+def install_stdin(**kw):
+    global _stdincatcher, _oldstdin, register_stdin, deregister_stdin
+    if not _stdincatcher:
+        _oldstdin = sys.stdin
+        _stdincatcher = sys.stdin = StdinCatcher(**kw)
+        register_stdin = _stdincatcher.register
+        deregister_stdin = _stdincatcher.deregister
+
+def uninstall():
+    global _stdincatcher, _oldstin, register_stdin, deregister_stdin
+    if _stdincatcher:
+        sys.stdin = _oldstdin
+        _stdincatcher = _oldstdin = None
+        register_stdin = deregister_stdin = not_installed_error_stdin
+
+def not_installed_error_stdin(*args, **kw):
+    assert False, (
+        "threadedprint has not yet been installed for stdin (call "
+        "threadedprint.install_stdin())")

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadinglocal.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadinglocal.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/util/threadinglocal.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,43 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Implementation of thread-local storage, for Python versions that don't
+have thread local storage natively.
+"""
+
+try:
+    import threading
+except ImportError:
+    # No threads, so "thread local" means process-global
+    class local(object):
+        pass
+else:
+    try:
+        local = threading.local
+    except AttributeError:
+        # Added in 2.4, but now we'll have to define it ourselves
+        import thread
+        class local(object):
+
+            def __init__(self):
+                self.__dict__['__objs'] = {}
+
+            def __getattr__(self, attr, g=thread.get_ident):
+                try:
+                    return self.__dict__['__objs'][g()][attr]
+                except KeyError:
+                    raise AttributeError(
+                        "No variable %s defined for the thread %s"
+                        % (attr, g()))
+
+            def __setattr__(self, attr, value, g=thread.get_ident):
+                self.__dict__['__objs'].setdefault(g(), {})[attr] = value
+
+            def __delattr__(self, attr, g=thread.get_ident):
+                try:
+                    del self.__dict__['__objs'][g()][attr]
+                except KeyError:
+                    raise AttributeError(
+                        "No variable %s defined for thread %s"
+                        % (attr, g()))
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgilib.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgilib.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgilib.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,597 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+"""
+A module of many disparate routines.
+"""
+
+# functions which moved to paste.request and paste.response
+# Deprecated around 15 Dec 2005
+from paste.request import get_cookies, parse_querystring, parse_formvars
+from paste.request import construct_url, path_info_split, path_info_pop
+from paste.response import HeaderDict, has_header, header_value, remove_header
+from paste.response import error_body_response, error_response, error_response_app
+
+from traceback import print_exception
+import urllib
+from cStringIO import StringIO
+import sys
+from urlparse import urlsplit
+import warnings
+
+__all__ = ['add_close', 'add_start_close', 'capture_output', 'catch_errors',
+           'catch_errors_app', 'chained_app_iters', 'construct_url',
+           'dump_environ', 'encode_unicode_app_iter', 'error_body_response',
+           'error_response', 'get_cookies', 'has_header', 'header_value',
+           'interactive', 'intercept_output', 'path_info_pop',
+           'path_info_split', 'raw_interactive', 'send_file']
+
+class add_close(object):
+    """
+    An an iterable that iterates over app_iter, then calls
+    close_func.
+    """
+
+    def __init__(self, app_iterable, close_func):
+        self.app_iterable = app_iterable
+        self.app_iter = iter(app_iterable)
+        self.close_func = close_func
+        self._closed = False
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        return self.app_iter.next()
+
+    def close(self):
+        self._closed = True
+        if hasattr(self.app_iterable, 'close'):
+            self.app_iterable.close()
+        self.close_func()
+
+    def __del__(self):
+        if not self._closed:
+            # We can't raise an error or anything at this stage
+            print >> sys.stderr, (
+                "Error: app_iter.close() was not called when finishing "
+                "WSGI request. finalization function %s not called"
+                % self.close_func)
+
+class add_start_close(object):
+    """
+    An an iterable that iterates over app_iter, calls start_func
+    before the first item is returned, then calls close_func at the
+    end.
+    """
+
+    def __init__(self, app_iterable, start_func, close_func=None):
+        self.app_iterable = app_iterable
+        self.app_iter = iter(app_iterable)
+        self.first = True
+        self.start_func = start_func
+        self.close_func = close_func
+        self._closed = False
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if self.first:
+            self.start_func()
+            self.first = False
+        return self.app_iter.next()
+
+    def close(self):
+        self._closed = True
+        if hasattr(self.app_iterable, 'close'):
+            self.app_iterable.close()
+        if self.close_func is not None:
+            self.close_func()
+
+    def __del__(self):
+        if not self._closed:
+            # We can't raise an error or anything at this stage
+            print >> sys.stderr, (
+                "Error: app_iter.close() was not called when finishing "
+                "WSGI request. finalization function %s not called"
+                % self.close_func)
+
+class chained_app_iters(object):
+
+    """
+    Chains several app_iters together, also delegating .close() to each
+    of them.
+    """
+
+    def __init__(self, *chained):
+        self.app_iters = chained
+        self.chained = [iter(item) for item in chained]
+        self._closed = False
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        if len(self.chained) == 1:
+            return self.chained[0].next()
+        else:
+            try:
+                return self.chained[0].next()
+            except StopIteration:
+                self.chained.pop(0)
+                return self.next()
+
+    def close(self):
+        self._closed = True
+        got_exc = None
+        for app_iter in self.app_iters:
+            try:
+                if hasattr(app_iter, 'close'):
+                    app_iter.close()
+            except:
+                got_exc = sys.exc_info()
+        if got_exc:
+            raise got_exc[0], got_exc[1], got_exc[2]
+
+    def __del__(self):
+        if not self._closed:
+            # We can't raise an error or anything at this stage
+            print >> sys.stderr, (
+                "Error: app_iter.close() was not called when finishing "
+                "WSGI request. finalization function %s not called"
+                % self.close_func)
+
+class encode_unicode_app_iter(object):
+    """
+    Encodes an app_iterable's unicode responses as strings
+    """
+
+    def __init__(self, app_iterable, encoding=sys.getdefaultencoding(),
+                 errors='strict'):
+        self.app_iterable = app_iterable
+        self.app_iter = iter(app_iterable)
+        self.encoding = encoding
+        self.errors = errors
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        content = self.app_iter.next()
+        if isinstance(content, unicode):
+            content = content.encode(self.encoding, self.errors)
+        return content
+
+    def close(self):
+        if hasattr(self.app_iterable, 'close'):
+            self.app_iterable.close()
+
+def catch_errors(application, environ, start_response, error_callback,
+                 ok_callback=None):
+    """
+    Runs the application, and returns the application iterator (which should be
+    passed upstream).  If an error occurs then error_callback will be called with
+    exc_info as its sole argument.  If no errors occur and ok_callback is given,
+    then it will be called with no arguments.
+    """
+    try:
+        app_iter = application(environ, start_response)
+    except:
+        error_callback(sys.exc_info())
+        raise
+    if type(app_iter) in (list, tuple):
+        # These won't produce exceptions
+        if ok_callback:
+            ok_callback()
+        return app_iter
+    else:
+        return _wrap_app_iter(app_iter, error_callback, ok_callback)
+
+class _wrap_app_iter(object):
+
+    def __init__(self, app_iterable, error_callback, ok_callback):
+        self.app_iterable = app_iterable
+        self.app_iter = iter(app_iterable)
+        self.error_callback = error_callback
+        self.ok_callback = ok_callback
+        if hasattr(self.app_iterable, 'close'):
+            self.close = self.app_iterable.close
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        try:
+            return self.app_iter.next()
+        except StopIteration:
+            if self.ok_callback:
+                self.ok_callback()
+            raise
+        except:
+            self.error_callback(sys.exc_info())
+            raise
+
+def catch_errors_app(application, environ, start_response, error_callback_app,
+                     ok_callback=None, catch=Exception):
+    """
+    Like ``catch_errors``, except error_callback_app should be a
+    callable that will receive *three* arguments -- ``environ``,
+    ``start_response``, and ``exc_info``.  It should call
+    ``start_response`` (*with* the exc_info argument!) and return an
+    iterator.
+    """
+    try:
+        app_iter = application(environ, start_response)
+    except catch:
+        return error_callback_app(environ, start_response, sys.exc_info())
+    if type(app_iter) in (list, tuple):
+        # These won't produce exceptions
+        if ok_callback is not None:
+            ok_callback()
+        return app_iter
+    else:
+        return _wrap_app_iter_app(
+            environ, start_response, app_iter,
+            error_callback_app, ok_callback, catch=catch)
+
+class _wrap_app_iter_app(object):
+
+    def __init__(self, environ, start_response, app_iterable,
+                 error_callback_app, ok_callback, catch=Exception):
+        self.environ = environ
+        self.start_response = start_response
+        self.app_iterable = app_iterable
+        self.app_iter = iter(app_iterable)
+        self.error_callback_app = error_callback_app
+        self.ok_callback = ok_callback
+        self.catch = catch
+        if hasattr(self.app_iterable, 'close'):
+            self.close = self.app_iterable.close
+
+    def __iter__(self):
+        return self
+
+    def next(self):
+        try:
+            return self.app_iter.next()
+        except StopIteration:
+            if self.ok_callback:
+                self.ok_callback()
+            raise
+        except self.catch:
+            if hasattr(self.app_iterable, 'close'):
+                try:
+                    self.app_iterable.close()
+                except:
+                    # @@: Print to wsgi.errors?
+                    pass
+            new_app_iterable = self.error_callback_app(
+                self.environ, self.start_response, sys.exc_info())
+            app_iter = iter(new_app_iterable)
+            if hasattr(new_app_iterable, 'close'):
+                self.close = new_app_iterable.close
+            self.next = app_iter.next
+            return self.next()
+
+def raw_interactive(application, path='', raise_on_wsgi_error=False,
+                    **environ):
+    """
+    Runs the application in a fake environment.
+    """
+    assert "path_info" not in environ, "argument list changed"
+    if raise_on_wsgi_error:
+        errors = ErrorRaiser()
+    else:
+        errors = StringIO()
+    basic_environ = {
+        # mandatory CGI variables
+        'REQUEST_METHOD': 'GET',     # always mandatory
+        'SCRIPT_NAME': '',           # may be empty if app is at the root
+        'PATH_INFO': '',             # may be empty if at root of app
+        'SERVER_NAME': 'localhost',  # always mandatory
+        'SERVER_PORT': '80',         # always mandatory 
+        'SERVER_PROTOCOL': 'HTTP/1.0',
+        # mandatory wsgi variables
+        'wsgi.version': (1, 0),
+        'wsgi.url_scheme': 'http',
+        'wsgi.input': StringIO(''),
+        'wsgi.errors': errors,
+        'wsgi.multithread': False,
+        'wsgi.multiprocess': False,
+        'wsgi.run_once': False,
+        }
+    if path:
+        (_, _, path_info, query, fragment) = urlsplit(str(path))
+        path_info = urllib.unquote(path_info)
+        # urlsplit returns unicode so coerce it back to str
+        path_info, query = str(path_info), str(query)
+        basic_environ['PATH_INFO'] = path_info
+        if query:
+            basic_environ['QUERY_STRING'] = query
+    for name, value in environ.items():
+        name = name.replace('__', '.')
+        basic_environ[name] = value
+    if ('SERVER_NAME' in basic_environ
+        and 'HTTP_HOST' not in basic_environ):
+        basic_environ['HTTP_HOST'] = basic_environ['SERVER_NAME']
+    istream = basic_environ['wsgi.input']
+    if isinstance(istream, str):
+        basic_environ['wsgi.input'] = StringIO(istream)
+        basic_environ['CONTENT_LENGTH'] = len(istream)
+    data = {}
+    output = []
+    headers_set = []
+    headers_sent = []
+    def start_response(status, headers, exc_info=None):
+        if exc_info:
+            try:
+                if headers_sent:
+                    # Re-raise original exception only if headers sent
+                    raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                # avoid dangling circular reference
+                exc_info = None
+        elif headers_set:
+            # You cannot set the headers more than once, unless the
+            # exc_info is provided.
+            raise AssertionError("Headers already set and no exc_info!")
+        headers_set.append(True)
+        data['status'] = status
+        data['headers'] = headers
+        return output.append
+    app_iter = application(basic_environ, start_response)
+    try:
+        try:
+            for s in app_iter:
+                if not isinstance(s, str):
+                    raise ValueError(
+                        "The app_iter response can only contain str (not "
+                        "unicode); got: %r" % s)
+                headers_sent.append(True)
+                if not headers_set:
+                    raise AssertionError("Content sent w/o headers!")
+                output.append(s)
+        except TypeError, e:
+            # Typically "iteration over non-sequence", so we want
+            # to give better debugging information...
+            e.args = ((e.args[0] + ' iterable: %r' % app_iter),) + e.args[1:]
+            raise
+    finally:
+        if hasattr(app_iter, 'close'):
+            app_iter.close()
+    return (data['status'], data['headers'], ''.join(output),
+            errors.getvalue())
+
+class ErrorRaiser(object):
+
+    def flush(self):
+        pass
+
+    def write(self, value):
+        if not value:
+            return
+        raise AssertionError(
+            "No errors should be written (got: %r)" % value)
+
+    def writelines(self, seq):
+        raise AssertionError(
+            "No errors should be written (got lines: %s)" % list(seq))
+
+    def getvalue(self):
+        return ''
+
+def interactive(*args, **kw):
+    """
+    Runs the application interatively, wrapping `raw_interactive` but
+    returning the output in a formatted way.
+    """
+    status, headers, content, errors = raw_interactive(*args, **kw)
+    full = StringIO()
+    if errors:
+        full.write('Errors:\n')
+        full.write(errors.strip())
+        full.write('\n----------end errors\n')
+    full.write(status + '\n')
+    for name, value in headers:
+        full.write('%s: %s\n' % (name, value))
+    full.write('\n')
+    full.write(content)
+    return full.getvalue()
+interactive.proxy = 'raw_interactive'
+
+def dump_environ(environ, start_response):
+    """
+    Application which simply dumps the current environment
+    variables out as a plain text response.
+    """
+    output = []
+    keys = environ.keys()
+    keys.sort()
+    for k in keys:
+        v = str(environ[k]).replace("\n","\n    ")
+        output.append("%s: %s\n" % (k, v))
+    output.append("\n")
+    content_length = environ.get("CONTENT_LENGTH", '')
+    if content_length:
+        output.append(environ['wsgi.input'].read(int(content_length)))
+        output.append("\n")
+    output = "".join(output)
+    headers = [('Content-Type', 'text/plain'),
+               ('Content-Length', str(len(output)))]
+    start_response("200 OK", headers)
+    return [output]
+
+def send_file(filename):
+    warnings.warn(
+        "wsgilib.send_file has been moved to paste.fileapp.FileApp",
+        DeprecationWarning, 2)
+    from paste import fileapp
+    return fileapp.FileApp(filename)
+
+def capture_output(environ, start_response, application):
+    """
+    Runs application with environ and start_response, and captures
+    status, headers, and body.
+
+    Sends status and header, but *not* body.  Returns (status,
+    headers, body).  Typically this is used like:
+    
+    .. code-block:: python
+
+        def dehtmlifying_middleware(application):
+            def replacement_app(environ, start_response):
+                status, headers, body = capture_output(
+                    environ, start_response, application)
+                content_type = header_value(headers, 'content-type')
+                if (not content_type
+                    or not content_type.startswith('text/html')):
+                    return [body]
+                body = re.sub(r'<.*?>', '', body)
+                return [body]
+            return replacement_app
+
+    """
+    warnings.warn(
+        'wsgilib.capture_output has been deprecated in favor '
+        'of wsgilib.intercept_output',
+        DeprecationWarning, 2)
+    data = []
+    output = StringIO()
+    def replacement_start_response(status, headers, exc_info=None):
+        if data:
+            data[:] = []
+        data.append(status)
+        data.append(headers)
+        start_response(status, headers, exc_info)
+        return output.write
+    app_iter = application(environ, replacement_start_response)
+    try:
+        for item in app_iter:
+            output.write(item)
+    finally:
+        if hasattr(app_iter, 'close'):
+            app_iter.close()
+    if not data:
+        data.append(None)
+    if len(data) < 2:
+        data.append(None)
+    data.append(output.getvalue())
+    return data
+
+def intercept_output(environ, application, conditional=None,
+                     start_response=None):
+    """
+    Runs application with environ and captures status, headers, and
+    body.  None are sent on; you must send them on yourself (unlike
+    ``capture_output``)
+
+    Typically this is used like:
+    
+    .. code-block:: python
+
+        def dehtmlifying_middleware(application):
+            def replacement_app(environ, start_response):
+                status, headers, body = intercept_output(
+                    environ, application)
+                start_response(status, headers)
+                content_type = header_value(headers, 'content-type')
+                if (not content_type
+                    or not content_type.startswith('text/html')):
+                    return [body]
+                body = re.sub(r'<.*?>', '', body)
+                return [body]
+            return replacement_app
+
+    A third optional argument ``conditional`` should be a function
+    that takes ``conditional(status, headers)`` and returns False if
+    the request should not be intercepted.  In that case
+    ``start_response`` will be called and ``(None, None, app_iter)``
+    will be returned.  You must detect that in your code and return
+    the app_iter, like:
+    
+    .. code-block:: python
+
+        def dehtmlifying_middleware(application):
+            def replacement_app(environ, start_response):
+                status, headers, body = intercept_output(
+                    environ, application,
+                    lambda s, h: header_value(headers, 'content-type').startswith('text/html'),
+                    start_response)
+                if status is None:
+                    return body
+                start_response(status, headers)
+                body = re.sub(r'<.*?>', '', body)
+                return [body]
+            return replacement_app
+    """
+    if conditional is not None and start_response is None:
+        raise TypeError(
+            "If you provide conditional you must also provide "
+            "start_response")
+    data = []
+    output = StringIO()
+    def replacement_start_response(status, headers, exc_info=None):
+        if conditional is not None and not conditional(status, headers):
+            data.append(None)
+            return start_response(status, headers, exc_info)
+        if data:
+            data[:] = []
+        data.append(status)
+        data.append(headers)
+        return output.write
+    app_iter = application(environ, replacement_start_response)
+    if data[0] is None:
+        return (None, None, app_iter)
+    try:
+        for item in app_iter:
+            output.write(item)
+    finally:
+        if hasattr(app_iter, 'close'):
+            app_iter.close()
+    if not data:
+        data.append(None)
+    if len(data) < 2:
+        data.append(None)
+    data.append(output.getvalue())
+    return data
+
+## Deprecation warning wrapper:
+
+class ResponseHeaderDict(HeaderDict):
+
+    def __init__(self, *args, **kw):
+        warnings.warn(
+            "The class wsgilib.ResponseHeaderDict has been moved "
+            "to paste.response.HeaderDict",
+            DeprecationWarning, 2)
+        HeaderDict.__init__(self, *args, **kw)
+
+def _warn_deprecated(new_func):
+    new_name = new_func.func_name
+    new_path = new_func.func_globals['__name__'] + '.' + new_name
+    def replacement(*args, **kw):
+        warnings.warn(
+            "The function wsgilib.%s has been moved to %s"
+            % (new_name, new_path),
+            DeprecationWarning, 2)
+        return new_func(*args, **kw)
+    try:
+        replacement.func_name = new_func.func_name
+    except:
+        pass
+    return replacement
+
+# Put warnings wrapper in place for all public functions that
+# were imported from elsewhere:
+
+for _name in __all__:
+    _func = globals()[_name]
+    if (hasattr(_func, 'func_globals')
+        and _func.func_globals['__name__'] != __name__):
+        globals()[_name] = _warn_deprecated(_func)
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgiwrappers.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgiwrappers.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/Paste-1.7.5.1-py2.6.egg/paste/wsgiwrappers.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,581 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""WSGI Wrappers for a Request and Response
+
+The WSGIRequest and WSGIResponse objects are light wrappers to make it easier
+to deal with an incoming request and sending a response.
+"""
+import re
+import warnings
+from pprint import pformat
+from Cookie import SimpleCookie
+from paste.request import EnvironHeaders, get_cookie_dict, \
+    parse_dict_querystring, parse_formvars
+from paste.util.multidict import MultiDict, UnicodeMultiDict
+from paste.registry import StackedObjectProxy
+from paste.response import HeaderDict
+from paste.wsgilib import encode_unicode_app_iter
+from paste.httpheaders import ACCEPT_LANGUAGE
+from paste.util.mimeparse import desired_matches
+
+__all__ = ['WSGIRequest', 'WSGIResponse']
+
+_CHARSET_RE = re.compile(r';\s*charset=([^;]*)', re.I)
+
+class DeprecatedSettings(StackedObjectProxy):
+    def _push_object(self, obj):
+        warnings.warn('paste.wsgiwrappers.settings is deprecated: Please use '
+                      'paste.wsgiwrappers.WSGIRequest.defaults instead',
+                      DeprecationWarning, 3)
+        WSGIResponse.defaults._push_object(obj)
+        StackedObjectProxy._push_object(self, obj)
+
+# settings is deprecated: use WSGIResponse.defaults instead
+settings = DeprecatedSettings(default=dict())
+
+class environ_getter(object):
+    """For delegating an attribute to a key in self.environ."""
+    # @@: Also __set__?  Should setting be allowed?
+    def __init__(self, key, default='', default_factory=None):
+        self.key = key
+        self.default = default
+        self.default_factory = default_factory
+    def __get__(self, obj, type=None):
+        if type is None:
+            return self
+        if self.key not in obj.environ:
+            if self.default_factory:
+                val = obj.environ[self.key] = self.default_factory()
+                return val
+            else:
+                return self.default
+        return obj.environ[self.key]
+
+    def __repr__(self):
+        return '<Proxy for WSGI environ %r key>' % self.key
+
+class WSGIRequest(object):
+    """WSGI Request API Object
+
+    This object represents a WSGI request with a more friendly interface.
+    This does not expose every detail of the WSGI environment, and attempts
+    to express nothing beyond what is available in the environment
+    dictionary.
+
+    The only state maintained in this object is the desired ``charset``,
+    its associated ``errors`` handler, and the ``decode_param_names``
+    option.
+
+    The incoming parameter values will be automatically coerced to unicode
+    objects of the ``charset`` encoding when ``charset`` is set. The
+    incoming parameter names are not decoded to unicode unless the
+    ``decode_param_names`` option is enabled.
+
+    When unicode is expected, ``charset`` will overridden by the the
+    value of the ``Content-Type`` header's charset parameter if one was
+    specified by the client.
+
+    The class variable ``defaults`` specifies default values for
+    ``charset``, ``errors``, and ``langauge``. These can be overridden for the
+    current request via the registry.
+        
+    The ``language`` default value is considered the fallback during i18n
+    translations to ensure in odd cases that mixed languages don't occur should
+    the ``language`` file contain the string but not another language in the
+    accepted languages list. The ``language`` value only applies when getting
+    a list of accepted languages from the HTTP Accept header.
+    
+    This behavior is duplicated from Aquarium, and may seem strange but is
+    very useful. Normally, everything in the code is in "en-us".  However, 
+    the "en-us" translation catalog is usually empty.  If the user requests
+    ``["en-us", "zh-cn"]`` and a translation isn't found for a string in
+    "en-us", you don't want gettext to fallback to "zh-cn".  You want it to 
+    just use the string itself.  Hence, if a string isn't found in the
+    ``language`` catalog, the string in the source code will be used.
+
+    *All* other state is kept in the environment dictionary; this is
+    essential for interoperability.
+
+    You are free to subclass this object.
+
+    """
+    defaults = StackedObjectProxy(default=dict(charset=None, errors='replace',
+                                               decode_param_names=False,
+                                               language='en-us'))
+    def __init__(self, environ):
+        self.environ = environ
+        # This isn't "state" really, since the object is derivative:
+        self.headers = EnvironHeaders(environ)
+        
+        defaults = self.defaults._current_obj()
+        self.charset = defaults.get('charset')
+        if self.charset:
+            # There's a charset: params will be coerced to unicode. In that
+            # case, attempt to use the charset specified by the browser
+            browser_charset = self.determine_browser_charset()
+            if browser_charset:
+                self.charset = browser_charset
+        self.errors = defaults.get('errors', 'strict')
+        self.decode_param_names = defaults.get('decode_param_names', False)
+        self._languages = None
+    
+    body = environ_getter('wsgi.input')
+    scheme = environ_getter('wsgi.url_scheme')
+    method = environ_getter('REQUEST_METHOD')
+    script_name = environ_getter('SCRIPT_NAME')
+    path_info = environ_getter('PATH_INFO')
+
+    def urlvars(self):
+        """
+        Return any variables matched in the URL (e.g.,
+        ``wsgiorg.routing_args``).
+        """
+        if 'paste.urlvars' in self.environ:
+            return self.environ['paste.urlvars']
+        elif 'wsgiorg.routing_args' in self.environ:
+            return self.environ['wsgiorg.routing_args'][1]
+        else:
+            return {}
+    urlvars = property(urlvars, doc=urlvars.__doc__)
+    
+    def is_xhr(self):
+        """Returns a boolean if X-Requested-With is present and a XMLHttpRequest"""
+        return self.environ.get('HTTP_X_REQUESTED_WITH', '') == 'XMLHttpRequest'
+    is_xhr = property(is_xhr, doc=is_xhr.__doc__)
+    
+    def host(self):
+        """Host name provided in HTTP_HOST, with fall-back to SERVER_NAME"""
+        return self.environ.get('HTTP_HOST', self.environ.get('SERVER_NAME'))
+    host = property(host, doc=host.__doc__)
+
+    def languages(self):
+        """Return a list of preferred languages, most preferred first.
+        
+        The list may be empty.
+        """
+        if self._languages is not None:
+            return self._languages
+        acceptLanguage = self.environ.get('HTTP_ACCEPT_LANGUAGE')
+        langs = ACCEPT_LANGUAGE.parse(self.environ)
+        fallback = self.defaults.get('language', 'en-us')
+        if not fallback:
+            return langs
+        if fallback not in langs:
+            langs.append(fallback)
+        index = langs.index(fallback)
+        langs[index+1:] = []
+        self._languages = langs
+        return self._languages
+    languages = property(languages, doc=languages.__doc__)
+    
+    def _GET(self):
+        return parse_dict_querystring(self.environ)
+
+    def GET(self):
+        """
+        Dictionary-like object representing the QUERY_STRING
+        parameters. Always present, if possibly empty.
+
+        If the same key is present in the query string multiple times, a
+        list of its values can be retrieved from the ``MultiDict`` via
+        the ``getall`` method.
+
+        Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when
+        ``charset`` is set.
+        """
+        params = self._GET()
+        if self.charset:
+            params = UnicodeMultiDict(params, encoding=self.charset,
+                                      errors=self.errors,
+                                      decode_keys=self.decode_param_names)
+        return params
+    GET = property(GET, doc=GET.__doc__)
+
+    def _POST(self):
+        return parse_formvars(self.environ, include_get_vars=False)
+
+    def POST(self):
+        """Dictionary-like object representing the POST body.
+
+        Most values are encoded strings, or unicode strings when
+        ``charset`` is set. There may also be FieldStorage objects
+        representing file uploads. If this is not a POST request, or the
+        body is not encoded fields (e.g., an XMLRPC request) then this
+        will be empty.
+
+        This will consume wsgi.input when first accessed if applicable,
+        but the raw version will be put in
+        environ['paste.parsed_formvars'].
+
+        Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when
+        ``charset`` is set.
+        """
+        params = self._POST()
+        if self.charset:
+            params = UnicodeMultiDict(params, encoding=self.charset,
+                                      errors=self.errors,
+                                      decode_keys=self.decode_param_names)
+        return params
+    POST = property(POST, doc=POST.__doc__)
+
+    def params(self):
+        """Dictionary-like object of keys from POST, GET, URL dicts
+
+        Return a key value from the parameters, they are checked in the
+        following order: POST, GET, URL
+
+        Additional methods supported:
+
+        ``getlist(key)``
+            Returns a list of all the values by that key, collected from
+            POST, GET, URL dicts
+
+        Returns a ``MultiDict`` container or a ``UnicodeMultiDict`` when
+        ``charset`` is set.
+        """
+        params = MultiDict()
+        params.update(self._POST())
+        params.update(self._GET())
+        if self.charset:
+            params = UnicodeMultiDict(params, encoding=self.charset,
+                                      errors=self.errors,
+                                      decode_keys=self.decode_param_names)
+        return params
+    params = property(params, doc=params.__doc__)
+
+    def cookies(self):
+        """Dictionary of cookies keyed by cookie name.
+
+        Just a plain dictionary, may be empty but not None.
+        
+        """
+        return get_cookie_dict(self.environ)
+    cookies = property(cookies, doc=cookies.__doc__)
+
+    def determine_browser_charset(self):
+        """
+        Determine the encoding as specified by the browser via the
+        Content-Type's charset parameter, if one is set
+        """
+        charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', ''))
+        if charset_match:
+            return charset_match.group(1)
+
+    def match_accept(self, mimetypes):
+        """Return a list of specified mime-types that the browser's HTTP Accept
+        header allows in the order provided."""
+        return desired_matches(mimetypes, 
+                               self.environ.get('HTTP_ACCEPT', '*/*'))
+
+    def __repr__(self):
+        """Show important attributes of the WSGIRequest"""
+        pf = pformat
+        msg = '<%s.%s object at 0x%x method=%s,' % \
+            (self.__class__.__module__, self.__class__.__name__,
+             id(self), pf(self.method))
+        msg += '\nscheme=%s, host=%s, script_name=%s, path_info=%s,' % \
+            (pf(self.scheme), pf(self.host), pf(self.script_name),
+             pf(self.path_info))
+        msg += '\nlanguages=%s,' % pf(self.languages)
+        if self.charset:
+            msg += ' charset=%s, errors=%s,' % (pf(self.charset),
+                                                pf(self.errors))
+        msg += '\nGET=%s,' % pf(self.GET)
+        msg += '\nPOST=%s,' % pf(self.POST)
+        msg += '\ncookies=%s>' % pf(self.cookies)
+        return msg
+
+class WSGIResponse(object):
+    """A basic HTTP response with content, headers, and out-bound cookies
+
+    The class variable ``defaults`` specifies default values for
+    ``content_type``, ``charset`` and ``errors``. These can be overridden
+    for the current request via the registry.
+
+    """
+    defaults = StackedObjectProxy(
+        default=dict(content_type='text/html', charset='utf-8', 
+                     errors='strict', headers={'Cache-Control':'no-cache'})
+        )
+    def __init__(self, content='', mimetype=None, code=200):
+        self._iter = None
+        self._is_str_iter = True
+
+        self.content = content
+        self.headers = HeaderDict()
+        self.cookies = SimpleCookie()
+        self.status_code = code
+
+        defaults = self.defaults._current_obj()
+        if not mimetype:
+            mimetype = defaults.get('content_type', 'text/html')
+            charset = defaults.get('charset')
+            if charset:
+                mimetype = '%s; charset=%s' % (mimetype, charset)
+        self.headers.update(defaults.get('headers', {}))
+        self.headers['Content-Type'] = mimetype
+        self.errors = defaults.get('errors', 'strict')
+
+    def __str__(self):
+        """Returns a rendition of the full HTTP message, including headers.
+
+        When the content is an iterator, the actual content is replaced with the
+        output of str(iterator) (to avoid exhausting the iterator).
+        """
+        if self._is_str_iter:
+            content = ''.join(self.get_content())
+        else:
+            content = str(self.content)
+        return '\n'.join(['%s: %s' % (key, value)
+            for key, value in self.headers.headeritems()]) \
+            + '\n\n' + content
+    
+    def __call__(self, environ, start_response):
+        """Convenience call to return output and set status information
+        
+        Conforms to the WSGI interface for calling purposes only.
+        
+        Example usage:
+        
+        .. code-block:: python
+
+            def wsgi_app(environ, start_response):
+                response = WSGIResponse()
+                response.write("Hello world")
+                response.headers['Content-Type'] = 'latin1'
+                return response(environ, start_response)
+        
+        """
+        status_text = STATUS_CODE_TEXT[self.status_code]
+        status = '%s %s' % (self.status_code, status_text)
+        response_headers = self.headers.headeritems()
+        for c in self.cookies.values():
+            response_headers.append(('Set-Cookie', c.output(header='')))
+        start_response(status, response_headers)
+        is_file = isinstance(self.content, file)
+        if 'wsgi.file_wrapper' in environ and is_file:
+            return environ['wsgi.file_wrapper'](self.content)
+        elif is_file:
+            return iter(lambda: self.content.read(), '')
+        return self.get_content()
+    
+    def determine_charset(self):
+        """
+        Determine the encoding as specified by the Content-Type's charset
+        parameter, if one is set
+        """
+        charset_match = _CHARSET_RE.search(self.headers.get('Content-Type', ''))
+        if charset_match:
+            return charset_match.group(1)
+    
+    def has_header(self, header):
+        """
+        Case-insensitive check for a header
+        """
+        warnings.warn('WSGIResponse.has_header is deprecated, use '
+                      'WSGIResponse.headers.has_key instead', DeprecationWarning,
+                      2)
+        return self.headers.has_key(header)
+
+    def set_cookie(self, key, value='', max_age=None, expires=None, path='/',
+                   domain=None, secure=None, httponly=None):
+        """
+        Define a cookie to be sent via the outgoing HTTP headers
+        """
+        self.cookies[key] = value
+        for var_name, var_value in [
+            ('max_age', max_age), ('path', path), ('domain', domain),
+            ('secure', secure), ('expires', expires), ('httponly', httponly)]:
+            if var_value is not None and var_value is not False:
+                self.cookies[key][var_name.replace('_', '-')] = var_value
+
+    def delete_cookie(self, key, path='/', domain=None):
+        """
+        Notify the browser the specified cookie has expired and should be
+        deleted (via the outgoing HTTP headers)
+        """
+        self.cookies[key] = ''
+        if path is not None:
+            self.cookies[key]['path'] = path
+        if domain is not None:
+            self.cookies[key]['domain'] = domain
+        self.cookies[key]['expires'] = 0
+        self.cookies[key]['max-age'] = 0
+
+    def _set_content(self, content):
+        if hasattr(content, '__iter__'):
+            self._iter = content
+            if isinstance(content, list):
+                self._is_str_iter = True
+            else:
+                self._is_str_iter = False
+        else:
+            self._iter = [content]
+            self._is_str_iter = True
+    content = property(lambda self: self._iter, _set_content,
+                       doc='Get/set the specified content, where content can '
+                       'be: a string, a list of strings, a generator function '
+                       'that yields strings, or an iterable object that '
+                       'produces strings.')
+
+    def get_content(self):
+        """
+        Returns the content as an iterable of strings, encoding each element of
+        the iterator from a Unicode object if necessary.
+        """
+        charset = self.determine_charset()
+        if charset:
+            return encode_unicode_app_iter(self.content, charset, self.errors)
+        else:
+            return self.content
+    
+    def wsgi_response(self):
+        """
+        Return this WSGIResponse as a tuple of WSGI formatted data, including:
+        (status, headers, iterable)
+        """
+        status_text = STATUS_CODE_TEXT[self.status_code]
+        status = '%s %s' % (self.status_code, status_text)
+        response_headers = self.headers.headeritems()
+        for c in self.cookies.values():
+            response_headers.append(('Set-Cookie', c.output(header='')))
+        return status, response_headers, self.get_content()
+    
+    # The remaining methods partially implement the file-like object interface.
+    # See http://docs.python.org/lib/bltin-file-objects.html
+    def write(self, content):
+        if not self._is_str_iter:
+            raise IOError, "This %s instance's content is not writable: (content " \
+                'is an iterator)' % self.__class__.__name__
+        self.content.append(content)
+
+    def flush(self):
+        pass
+
+    def tell(self):
+        if not self._is_str_iter:
+            raise IOError, 'This %s instance cannot tell its position: (content ' \
+                'is an iterator)' % self.__class__.__name__
+        return sum([len(chunk) for chunk in self._iter])
+
+    ########################################
+    ## Content-type and charset
+
+    def charset__get(self):
+        """
+        Get/set the charset (in the Content-Type)
+        """
+        header = self.headers.get('content-type')
+        if not header:
+            return None
+        match = _CHARSET_RE.search(header)
+        if match:
+            return match.group(1)
+        return None
+
+    def charset__set(self, charset):
+        if charset is None:
+            del self.charset
+            return
+        try:
+            header = self.headers.pop('content-type')
+        except KeyError:
+            raise AttributeError(
+                "You cannot set the charset when no content-type is defined")
+        match = _CHARSET_RE.search(header)
+        if match:
+            header = header[:match.start()] + header[match.end():]
+        header += '; charset=%s' % charset
+        self.headers['content-type'] = header
+
+    def charset__del(self):
+        try:
+            header = self.headers.pop('content-type')
+        except KeyError:
+            # Don't need to remove anything
+            return
+        match = _CHARSET_RE.search(header)
+        if match:
+            header = header[:match.start()] + header[match.end():]
+        self.headers['content-type'] = header
+
+    charset = property(charset__get, charset__set, charset__del, doc=charset__get.__doc__)
+
+    def content_type__get(self):
+        """
+        Get/set the Content-Type header (or None), *without* the
+        charset or any parameters.
+
+        If you include parameters (or ``;`` at all) when setting the
+        content_type, any existing parameters will be deleted;
+        otherwise they will be preserved.
+        """
+        header = self.headers.get('content-type')
+        if not header:
+            return None
+        return header.split(';', 1)[0]
+
+    def content_type__set(self, value):
+        if ';' not in value:
+            header = self.headers.get('content-type', '')
+            if ';' in header:
+                params = header.split(';', 1)[1]
+                value += ';' + params
+        self.headers['content-type'] = value
+
+    def content_type__del(self):
+        try:
+            del self.headers['content-type']
+        except KeyError:
+            pass
+
+    content_type = property(content_type__get, content_type__set,
+                            content_type__del, doc=content_type__get.__doc__)
+
+## @@ I'd love to remove this, but paste.httpexceptions.get_exception
+##    doesn't seem to work...
+# See http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
+STATUS_CODE_TEXT = {
+    100: 'CONTINUE',
+    101: 'SWITCHING PROTOCOLS',
+    200: 'OK',
+    201: 'CREATED',
+    202: 'ACCEPTED',
+    203: 'NON-AUTHORITATIVE INFORMATION',
+    204: 'NO CONTENT',
+    205: 'RESET CONTENT',
+    206: 'PARTIAL CONTENT',
+    226: 'IM USED',
+    300: 'MULTIPLE CHOICES',
+    301: 'MOVED PERMANENTLY',
+    302: 'FOUND',
+    303: 'SEE OTHER',
+    304: 'NOT MODIFIED',
+    305: 'USE PROXY',
+    306: 'RESERVED',
+    307: 'TEMPORARY REDIRECT',
+    400: 'BAD REQUEST',
+    401: 'UNAUTHORIZED',
+    402: 'PAYMENT REQUIRED',
+    403: 'FORBIDDEN',
+    404: 'NOT FOUND',
+    405: 'METHOD NOT ALLOWED',
+    406: 'NOT ACCEPTABLE',
+    407: 'PROXY AUTHENTICATION REQUIRED',
+    408: 'REQUEST TIMEOUT',
+    409: 'CONFLICT',
+    410: 'GONE',
+    411: 'LENGTH REQUIRED',
+    412: 'PRECONDITION FAILED',
+    413: 'REQUEST ENTITY TOO LARGE',
+    414: 'REQUEST-URI TOO LONG',
+    415: 'UNSUPPORTED MEDIA TYPE',
+    416: 'REQUESTED RANGE NOT SATISFIABLE',
+    417: 'EXPECTATION FAILED',
+    500: 'INTERNAL SERVER ERROR',
+    501: 'NOT IMPLEMENTED',
+    502: 'BAD GATEWAY',
+    503: 'SERVICE UNAVAILABLE',
+    504: 'GATEWAY TIMEOUT',
+    505: 'HTTP VERSION NOT SUPPORTED',
+}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+Metadata-Version: 1.0
+Name: PasteDeploy
+Version: 1.3.4
+Summary: Load, configure, and compose WSGI applications and servers
+Home-page: http://pythonpaste.org/deploy/
+Author: Ian Bicking
+Author-email: ianb at colorstudy.com
+License: MIT
+Description: This tool provides code to load WSGI applications and servers from
+        URIs; these URIs can refer to Python Eggs for INI-style configuration
+        files.  `Paste Script <http://pythonpaste.org/script>`_ provides
+        commands to serve applications based on this configuration file.
+        
+        The latest version is available in a `Mercurial repository
+        <http://bitbucket.org/ianb/pastedeploy>`_ (or a `tarball
+        <http://bitbucket.org/ianb/pastedeploy/get/tip.gz#egg=PasteDeploy-dev>`_).
+        
+        For the latest changes see the `news file
+        <http://pythonpaste.org/deploy/news.html>`_.
+        
+Keywords: web wsgi application server
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
+Classifier: Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware
+Classifier: Framework :: Paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+MANIFEST.in
+setup.cfg
+setup.py
+PasteDeploy.egg-info/PKG-INFO
+PasteDeploy.egg-info/SOURCES.txt
+PasteDeploy.egg-info/dependency_links.txt
+PasteDeploy.egg-info/entry_points.txt
+PasteDeploy.egg-info/namespace_packages.txt
+PasteDeploy.egg-info/not-zip-safe
+PasteDeploy.egg-info/requires.txt
+PasteDeploy.egg-info/top_level.txt
+docs/index.txt
+docs/license.txt
+docs/news.txt
+paste/__init__.py
+paste/deploy/__init__.py
+paste/deploy/config.py
+paste/deploy/converters.py
+paste/deploy/epdesc.py
+paste/deploy/interfaces.py
+paste/deploy/loadwsgi.py
+paste/deploy/paster_templates.py
+paste/deploy/util/__init__.py
+paste/deploy/util/fixtypeerror.py
+paste/deploy/util/threadinglocal.py
+tests/__init__.py
+tests/finddata.py
+tests/fixture.py
+tests/test_basic_app.py
+tests/test_config.py
+tests/test_config_middleware.py
+tests/test_filter.py
+tests/test_load_package.py
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/entry_points.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/entry_points.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/entry_points.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+
+    [paste.filter_app_factory]
+    config = paste.deploy.config:make_config_filter [Config]
+    prefix = paste.deploy.config:make_prefix_middleware
+
+    [paste.paster_create_template]
+    paste_deploy=paste.deploy.paster_templates:PasteDeploy
+
+    [paste.entry_point_description]
+    paste.app_factory = paste.deploy.epdesc:AppFactoryDescription
+    paste.composit_factory = paste.deploy.epdesc:CompositeFactoryDescription
+    paste.composite_factory = paste.deploy.epdesc:CompositeFactoryDescription
+    paste.filter_app_factory = paste.deploy.epdesc:FilterAppFactoryDescription
+    paste.filter_factory = paste.deploy.epdesc:FilterFactoryDescription
+    paste.server_factory = paste.deploy.epdesc:ServerFactoryDescription
+    paste.server_runner = paste.deploy.epdesc:ServerRunnerDescription
+    
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/namespace_packages.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/namespace_packages.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/namespace_packages.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/requires.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/requires.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/requires.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+
+
+[Paste]
+Paste
+
+[Config]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+tests
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    # don't prevent use of paste if pkg_resources isn't installed
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__) 
+
+try:
+    import modulefinder
+except ImportError:
+    pass
+else:
+    for p in __path__:
+        modulefinder.AddPackagePath(__name__, p)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+from loadwsgi import *
+try:
+    from config import CONFIG
+except ImportError:
+    # @@: Or should we require Paste?  Or should we put threadlocal
+    # into this package too?
+    pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/config.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/config.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/config.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,298 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""Paste Configuration Middleware and Objects"""
+import threading
+import re
+# Loaded lazily
+wsgilib = None
+local = None
+
+__all__ = ['DispatchingConfig', 'CONFIG', 'ConfigMiddleware', 'PrefixMiddleware']
+
+def local_dict():
+    global config_local, local
+    try:
+        return config_local.wsgi_dict
+    except NameError:
+        from paste.deploy.util.threadinglocal import local
+        config_local = local()
+        config_local.wsgi_dict = result = {}
+        return result
+    except AttributeError:
+        config_local.wsgi_dict = result = {}
+        return result
+
+class DispatchingConfig(object):
+
+    """
+    This is a configuration object that can be used globally,
+    imported, have references held onto.  The configuration may differ
+    by thread (or may not).
+
+    Specific configurations are registered (and deregistered) either
+    for the process or for threads.
+    """
+
+    # @@: What should happen when someone tries to add this
+    # configuration to itself?  Probably the conf should become
+    # resolved, and get rid of this delegation wrapper
+
+    _constructor_lock = threading.Lock()
+
+    def __init__(self):
+        self._constructor_lock.acquire()
+        try:
+            self.dispatching_id = 0
+            while 1:
+                self._local_key = 'paste.processconfig_%i' % self.dispatching_id
+                if not local_dict().has_key(self._local_key):
+                    break
+                self.dispatching_id += 1
+        finally:
+            self._constructor_lock.release()
+        self._process_configs = []
+
+    def push_thread_config(self, conf):
+        """
+        Make ``conf`` the active configuration for this thread.
+        Thread-local configuration always overrides process-wide
+        configuration.
+
+        This should be used like::
+
+            conf = make_conf()
+            dispatching_config.push_thread_config(conf)
+            try:
+                ... do stuff ...
+            finally:
+                dispatching_config.pop_thread_config(conf)
+        """
+        local_dict().setdefault(self._local_key, []).append(conf)
+
+    def pop_thread_config(self, conf=None):
+        """
+        Remove a thread-local configuration.  If ``conf`` is given,
+        it is checked against the popped configuration and an error
+        is emitted if they don't match.
+        """
+        self._pop_from(local_dict()[self._local_key], conf)
+
+    def _pop_from(self, lst, conf):
+        popped = lst.pop()
+        if conf is not None and popped is not conf:
+            raise AssertionError(
+                "The config popped (%s) is not the same as the config "
+                "expected (%s)"
+                % (popped, conf))
+
+    def push_process_config(self, conf):
+        """
+        Like push_thread_config, but applies the configuration to
+        the entire process.
+        """
+        self._process_configs.append(conf)
+
+    def pop_process_config(self, conf=None):
+        self._pop_from(self._process_configs, conf)
+            
+    def __getattr__(self, attr):
+        conf = self.current_conf()
+        if conf is None:
+            raise AttributeError(
+                "No configuration has been registered for this process "
+                "or thread")
+        return getattr(conf, attr)
+
+    def current_conf(self):
+        thread_configs = local_dict().get(self._local_key)
+        if thread_configs:
+            return thread_configs[-1]
+        elif self._process_configs:
+            return self._process_configs[-1]
+        else:
+            return None
+
+    def __getitem__(self, key):
+        # I thought __getattr__ would catch this, but apparently not
+        conf = self.current_conf()
+        if conf is None:
+            raise TypeError(
+                "No configuration has been registered for this process "
+                "or thread")
+        return conf[key]
+
+    def __contains__(self, key):
+        # I thought __getattr__ would catch this, but apparently not
+        return self.has_key(key)
+
+    def __setitem__(self, key, value):
+        # I thought __getattr__ would catch this, but apparently not
+        conf = self.current_conf()
+        conf[key] = value
+
+CONFIG = DispatchingConfig()
+
+class ConfigMiddleware(object):
+
+    """
+    A WSGI middleware that adds a ``paste.config`` key to the request
+    environment, as well as registering the configuration temporarily
+    (for the length of the request) with ``paste.CONFIG``.
+    """
+
+    def __init__(self, application, config):
+        """
+        This delegates all requests to `application`, adding a *copy*
+        of the configuration `config`.
+        """
+        self.application = application
+        self.config = config
+
+    def __call__(self, environ, start_response):
+        global wsgilib
+        if wsgilib is None:
+            import pkg_resources
+            pkg_resources.require('Paste')
+            from paste import wsgilib
+        popped_config = None
+        if 'paste.config' in environ:
+            popped_config = environ['paste.config']        
+        conf = environ['paste.config'] = self.config.copy()
+        app_iter = None
+        CONFIG.push_thread_config(conf)
+        try:
+            app_iter = self.application(environ, start_response)
+        finally:
+            if app_iter is None:
+                # An error occurred...
+                CONFIG.pop_thread_config(conf)
+                if popped_config is not None:
+                    environ['paste.config'] = popped_config
+        if type(app_iter) in (list, tuple):
+            # Because it is a concrete iterator (not a generator) we
+            # know the configuration for this thread is no longer
+            # needed:
+            CONFIG.pop_thread_config(conf)
+            if popped_config is not None:
+                environ['paste.config'] = popped_config
+            return app_iter
+        else:
+            def close_config():
+                CONFIG.pop_thread_config(conf)
+            new_app_iter = wsgilib.add_close(app_iter, close_config)
+            return new_app_iter
+
+def make_config_filter(app, global_conf, **local_conf):
+    conf = global_conf.copy()
+    conf.update(local_conf)
+    return ConfigMiddleware(app, conf)
+
+make_config_middleware = ConfigMiddleware.__doc__
+
+class PrefixMiddleware(object):
+    """Translate a given prefix into a SCRIPT_NAME for the filtered
+    application.
+    
+    PrefixMiddleware provides a way to manually override the root prefix 
+    (SCRIPT_NAME) of your application for certain, rare situations.
+
+    When running an application under a prefix (such as '/james') in 
+    FastCGI/apache, the SCRIPT_NAME environment variable is automatically
+    set to to the appropriate value: '/james'. Pylons' URL generating 
+    functions, such as url_for, always take the SCRIPT_NAME value into account.
+
+    One situation where PrefixMiddleware is required is when an application
+    is accessed via a reverse proxy with a prefix. The application is accessed
+    through the reverse proxy via the the URL prefix '/james', whereas the
+    reverse proxy forwards those requests to the application at the prefix '/'.
+
+    The reverse proxy, being an entirely separate web server, has no way of
+    specifying the SCRIPT_NAME variable; it must be manually set by a
+    PrefixMiddleware instance. Without setting SCRIPT_NAME, url_for will
+    generate URLs such as: '/purchase_orders/1', when it should be
+    generating: '/james/purchase_orders/1'.
+
+    To filter your application through a PrefixMiddleware instance, add the
+    following to the '[app:main]' section of your .ini file:
+    
+    .. code-block:: ini
+        
+        filter-with = proxy-prefix
+
+        [filter:proxy-prefix]
+        use = egg:PasteDeploy#prefix
+        prefix = /james
+
+    The name ``proxy-prefix`` simply acts as an identifier of the filter
+    section; feel free to rename it.
+
+    Also, unless disabled, the ``X-Forwarded-Server`` header will be
+    translated to the ``Host`` header, for cases when that header is
+    lost in the proxying.  Also ``X-Forwarded-Host``, 
+    ``X-Forwarded-Scheme``, and ``X-Forwarded-Proto`` are translated.
+
+    If ``force_port`` is set, SERVER_PORT and HTTP_HOST will be
+    rewritten with the given port.  You can use a number, string (like
+    '80') or the empty string (whatever is the default port for the
+    scheme).  This is useful in situations where there is port
+    forwarding going on, and the server believes itself to be on a
+    different port than what the outside world sees.
+
+    You can also use ``scheme`` to explicitly set the scheme (like
+    ``scheme = https``).
+    """
+    def __init__(self, app, global_conf=None, prefix='/',
+                 translate_forwarded_server=True,
+                 force_port=None, scheme=None):
+        self.app = app
+        self.prefix = prefix.rstrip('/')
+        self.translate_forwarded_server = translate_forwarded_server
+        self.regprefix = re.compile("^%s(.*)$" % self.prefix)
+        self.force_port = force_port
+        self.scheme = scheme
+    
+    def __call__(self, environ, start_response):
+        url = environ['PATH_INFO']
+        url = re.sub(self.regprefix, r'\1', url)
+        if not url: url = '/'
+        environ['PATH_INFO'] = url
+        environ['SCRIPT_NAME'] = self.prefix
+        if self.translate_forwarded_server:
+            if 'HTTP_X_FORWARDED_SERVER' in environ:
+                environ['SERVER_NAME'] = environ['HTTP_HOST'] = environ.pop('HTTP_X_FORWARDED_SERVER').split(',')[0]
+            if 'HTTP_X_FORWARDED_HOST' in environ:
+                environ['HTTP_HOST'] = environ.pop('HTTP_X_FORWARDED_HOST').split(',')[0]
+            if 'HTTP_X_FORWARDED_FOR' in environ:
+                environ['REMOTE_ADDR'] = environ.pop('HTTP_X_FORWARDED_FOR')
+            if 'HTTP_X_FORWARDED_SCHEME' in environ:
+                environ['wsgi.url_scheme'] = environ.pop('HTTP_X_FORWARDED_SCHEME')
+            elif 'HTTP_X_FORWARDED_PROTO' in environ:
+                environ['wsgi.url_scheme'] = environ.pop('HTTP_X_FORWARDED_PROTO')
+        if self.force_port is not None:
+            host = environ.get('HTTP_HOST', '').split(':', 1)[0]
+            if self.force_port:
+                host = '%s:%s' % (host, self.force_port)
+                environ['SERVER_PORT'] = str(self.force_port)
+            else:
+                if environ['wsgi.url_scheme'] == 'http':
+                    port = '80'
+                else:
+                    port = '443'
+                environ['SERVER_PORT'] = port
+            environ['HTTP_HOST'] = host
+        if self.scheme is not None:
+            environ['wsgi.url_scheme'] = self.scheme
+        return self.app(environ, start_response)
+
+def make_prefix_middleware(
+    app, global_conf, prefix='/',
+    translate_forwarded_server=True,
+    force_port=None, scheme=None):
+    from paste.deploy.converters import asbool
+    translate_forwarded_server = asbool(translate_forwarded_server)
+    return PrefixMiddleware(
+        app, prefix=prefix,
+        translate_forwarded_server=translate_forwarded_server,
+        force_port=force_port, scheme=scheme)
+
+make_prefix_middleware.__doc__ = PrefixMiddleware.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/converters.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/converters.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/converters.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+def asbool(obj):
+    if isinstance(obj, (str, unicode)):
+        obj = obj.strip().lower()
+        if obj in ['true', 'yes', 'on', 'y', 't', '1']:
+            return True
+        elif obj in ['false', 'no', 'off', 'n', 'f', '0']:
+            return False
+        else:
+            raise ValueError(
+                "String is not true/false: %r" % obj)
+    return bool(obj)
+
+def asint(obj):
+    try:
+        return int(obj)
+    except (TypeError, ValueError), e:
+        raise ValueError(
+            "Bad integer value: %r" % obj)
+
+def aslist(obj, sep=None, strip=True):
+    if isinstance(obj, (str, unicode)):
+        lst = obj.split(sep)
+        if strip:
+            lst = [v.strip() for v in lst]
+        return lst
+    elif isinstance(obj, (list, tuple)):
+        return obj
+    elif obj is None:
+        return []
+    else:
+        return [obj]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/epdesc.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/epdesc.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/epdesc.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,37 @@
+class AppFactoryDescription(object):
+    description = """
+    This gives a factory/function that can create WSGI apps
+    """
+
+class CompositeFactoryDescription(object):
+    description = """
+    This gives a factory/function that can create WSGI apps, and has
+    access to the application creator so that it can in turn fetch
+    apps based on name.
+    """
+
+class FilterAppFactoryDescription(object):
+    description = """
+    This gives a factory/function that wraps a WSGI application to
+    create another WSGI application (typically applying middleware)
+    """
+
+class FilterFactoryDescription(object):
+    description = """
+    This gives a factory/function that return a function that can wrap
+    a WSGI application and returns another WSGI application.
+    paste.filter_app_factory is the same thing with less layers.
+    """
+
+class ServerFactoryDescription(object):
+    description = """
+    This gives a factory/function that creates a server, that can be
+    called with a WSGI application to run indefinitely.
+    paste.server_runner is the same thing with less layers.
+    """
+
+class ServerRunnerDescription(object):
+    description = """
+    This gives a factory/function that, given a WSGI application and
+    configuration, will serve the application indefinitely.
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/interfaces.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/interfaces.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/interfaces.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,202 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+############################################################
+## Functions
+############################################################
+
+def loadapp(uri, name=None, relative_to=None, global_conf=None):
+    """
+    Provided by ``paste.deploy.loadapp``.
+    
+    Load the specified URI as a WSGI application (returning IWSGIApp).
+    The ``name`` can be in the URI (typically as ``#name``).  If it is
+    and ``name`` is given, the keyword argument overrides the URI.
+
+    If the URI contains a relative filename, then ``relative_to`` is
+    used (if ``relative_to`` is not provided, then it is an error).
+
+    ``global_conf`` is used to load the configuration (additions
+    override the values).  ``global_conf`` is copied before modifying.
+    """
+
+def loadfilter(uri, name=None, relative_to=None, global_conf=None):
+    """
+    Provided by ``paste.deploy.loadfilter``.
+
+    Like ``loadapp()``, except returns in IFilter object.
+    """
+
+def loadserver(uri, name=None, relative_to=None, global_conf=None):
+    """
+    Provided by ``paste.deploy.loadserver``.
+
+    Like ``loadapp()``, except returns in IServer object.
+    """
+
+############################################################
+## Factories
+############################################################
+
+class IPasteAppFactory(object):
+
+    """
+    This is the spec for the ``paste.app_factory``
+    protocol/entry_point.
+    """
+
+    def __call__(global_conf, **local_conf):
+        """
+        Returns a WSGI application (IWSGIAPP) given the global
+        configuration and the local configuration passed in as keyword
+        arguments.
+
+        All keys are strings, but values in local_conf may not be
+        valid Python identifiers (if you use ``**kw`` you can still
+        capture these values).
+        """
+
+class IPasteCompositFactory(object):
+
+    """
+    This is the spec for the ``paste.composit_factory``
+    protocol/entry_point.
+
+    This also produces WSGI applications, like ``paste.app_factory``,
+    but is given more access to the context in which it is loaded.
+    """
+
+    def __call__(loader, global_conf, **local_conf):
+        """
+        Like IPasteAppFactory this returns a WSGI application
+        (IWSGIApp).  The ``loader`` value conforms to the ``ILoader``
+        interface, and can be used to load (contextually) more
+        applications.
+        """
+
+class IPasteFilterFactory(object):
+
+    """
+    This is the spec for the ``paste.filter_factory``
+    protocol/entry_point.
+    """
+
+    def __call__(global_conf, **local_conf):
+        """
+        Returns a IFilter object.
+        """
+
+class IPasteFilterAppFactory(object):
+
+    """
+    This is the spec for the ``paste.filter_app_factory``
+    protocol/entry_point.
+    """
+    
+    def __call__(wsgi_app, global_conf, **local_conf):
+        """
+        Returns a WSGI application that wraps ``wsgi_app``.
+
+        Note that paste.deploy creates a wrapper for these
+        objects that implement the IFilter interface.
+        """
+
+class IPasteServerFactory(object):
+
+    """
+    This is the spec for the ``paste.server_factory``
+    protocol/entry_point.
+    """
+
+    def __call__(global_conf, **local_conf):
+        """
+        Returns a IServer object.
+        """
+
+class IPasteServerRunner(object):
+
+    """
+    This is the spec for the ``paste.server_runner``
+    protocol/entry_point.
+    """
+
+    def __call__(wsgi_app, global_conf, **local_conf):
+        """
+        Serves the given WSGI application.  May serve once, many
+        times, forever; nothing about how the server works is
+        specified here.
+
+        Note that paste.deploy creates a wrapper for these
+        objects that implement the IServer interface.
+        """
+
+class ILoader(object):
+
+    """
+    This is an object passed into ``IPasteCompositFactory``.  It is
+    currently implemented in ``paste.deploy.loadwsgi`` by
+    ``ConfigLoader`` and ``EggLoader``.
+    """
+
+    def get_app(name_or_uri, global_conf=None):
+        """
+        Return an IWSGIApp object.  If the loader supports named
+        applications, then you can use a simple name; otherwise
+        you must use a full URI.
+
+        Any global configuration you pass in will be added; you should
+        generally pass through the global configuration you received.
+        """
+
+    def get_filter(name_or_uri, global_conf=None):
+        """
+        Return an IFilter object, like ``get_app``.
+        """
+                   
+    def get_server(name_or_uri, global_conf=None):
+        """
+        Return an IServer object, like ``get_app``.
+        """
+
+############################################################
+## Objects
+############################################################
+
+class IWSGIApp(object):
+
+    """
+    This is an application that conforms to `PEP 333
+    <http://www.python.org/peps/pep-0333.html>`_: Python Web Server
+    Gateway Interface v1.0
+    """
+
+    def __call__(environ, start_response):
+        """
+        Calls ``start_response(status_code, header_list)`` and returns
+        an iterator for the body of the response.
+        """
+
+class IFilter(object):
+
+    """
+    A filter is a simple case of middleware, where an object
+    wraps a single WSGI application (IWSGIApp).
+    """
+
+    def __call__(wsgi_app):
+        """
+        Returns an IWSGIApp object, typically one that wraps the
+        ``wsgi_app`` passed in.
+        """
+
+class IServer(object):
+
+    """
+    A simple server interface.
+    """
+
+    def __call__(wsgi_app):
+        """
+        Serves the given WSGI application.  May serve once, many
+        times, forever; nothing about how the server works is
+        specified here.
+        """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/loadwsgi.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/loadwsgi.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/loadwsgi.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,631 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import re
+import urllib
+from ConfigParser import ConfigParser
+import pkg_resources
+from paste.deploy.util.fixtypeerror import fix_call
+
+__all__ = ['loadapp', 'loadserver', 'loadfilter', 'appconfig']
+
+############################################################
+## Utility functions
+############################################################
+
+def import_string(s):
+    return pkg_resources.EntryPoint.parse("x="+s).load(False)
+
+def _aslist(obj):
+    """
+    Turn object into a list; lists and tuples are left as-is, None
+    becomes [], and everything else turns into a one-element list.
+    """
+    if obj is None:
+        return []
+    elif isinstance(obj, (list, tuple)):
+        return obj
+    else:
+        return [obj]
+
+def _flatten(lst):
+    """
+    Flatten a nested list.
+    """
+    if not isinstance(lst, (list, tuple)):
+        return [lst]
+    result = []
+    for item in lst:
+        result.extend(_flatten(item))
+    return result
+
+class NicerConfigParser(ConfigParser):
+
+    def __init__(self, filename, *args, **kw):
+        ConfigParser.__init__(self, *args, **kw)
+        self.filename = filename
+
+    def defaults(self):
+        """Return the defaults, with their values interpolated (with the
+        defaults dict itself)
+
+        Mainly to support defaults using values such as %(here)s
+        """
+        defaults = ConfigParser.defaults(self).copy()
+        for key, val in defaults.iteritems():
+            defaults[key] = self._interpolate('DEFAULT', key, val, defaults)
+        return defaults
+
+    def _interpolate(self, section, option, rawval, vars):
+        try:
+            return ConfigParser._interpolate(
+                self, section, option, rawval, vars)
+        except Exception, e:
+            args = list(e.args)
+            args[0] = 'Error in file %s, [%s] %s=%r: %s' % (
+                self.filename, section, option, rawval, e)
+            e.args = tuple(args)
+            raise
+
+############################################################
+## Object types
+############################################################
+
+class _ObjectType(object):
+
+    name = None
+    egg_protocols = None
+    config_prefixes = None
+
+    def __init__(self):
+        # Normalize these variables:
+        self.egg_protocols = map(_aslist, _aslist(self.egg_protocols))
+        self.config_prefixes = map(_aslist, _aslist(self.config_prefixes))
+
+    def __repr__(self):
+        return '<%s protocols=%r prefixes=%r>' % (
+            self.name, self.egg_protocols, self.config_prefixes)
+
+    def invoke(self, context):
+        assert context.protocol in _flatten(self.egg_protocols)
+        return fix_call(context.object,
+                        context.global_conf, **context.local_conf)
+
+class _App(_ObjectType):
+
+    name = 'application'
+    egg_protocols = ['paste.app_factory', 'paste.composite_factory',
+                     'paste.composit_factory']
+    config_prefixes = [['app', 'application'], ['composite', 'composit'],
+                       'pipeline', 'filter-app']
+
+    def invoke(self, context):
+        if context.protocol in ('paste.composit_factory',
+                                'paste.composite_factory'):
+            return fix_call(context.object,
+                            context.loader, context.global_conf,
+                            **context.local_conf)
+        elif context.protocol == 'paste.app_factory':
+            return fix_call(context.object, context.global_conf, **context.local_conf)
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+APP = _App()
+
+class _Filter(_ObjectType):
+    name = 'filter'
+    egg_protocols = [['paste.filter_factory', 'paste.filter_app_factory']]
+    config_prefixes = ['filter']
+
+    def invoke(self, context):
+        if context.protocol == 'paste.filter_factory':
+            return fix_call(context.object,
+                            context.global_conf, **context.local_conf)
+        elif context.protocol == 'paste.filter_app_factory':
+            def filter_wrapper(wsgi_app):
+                # This should be an object, so it has a nicer __repr__
+                return fix_call(context.object,
+                                wsgi_app, context.global_conf,
+                                **context.local_conf)
+            return filter_wrapper
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+FILTER = _Filter()
+
+class _Server(_ObjectType):
+    name = 'server'
+    egg_protocols = [['paste.server_factory', 'paste.server_runner']]
+    config_prefixes = ['server']
+
+    def invoke(self, context):
+        if context.protocol == 'paste.server_factory':
+            return fix_call(context.object,
+                            context.global_conf, **context.local_conf)
+        elif context.protocol == 'paste.server_runner':
+            def server_wrapper(wsgi_app):
+                # This should be an object, so it has a nicer __repr__
+                return fix_call(context.object,
+                                wsgi_app, context.global_conf,
+                                **context.local_conf)
+            return server_wrapper
+        else:
+            assert 0, "Protocol %r unknown" % context.protocol
+
+SERVER = _Server()
+
+# Virtual type: (@@: There's clearly something crufty here;
+# this probably could be more elegant)
+class _PipeLine(_ObjectType):
+    name = 'pipeline'
+
+    def invoke(self, context):
+        app = context.app_context.create()
+        filters = [c.create() for c in context.filter_contexts]
+        filters.reverse()
+        for filter in filters:
+            app = filter(app)
+        return app
+
+PIPELINE = _PipeLine()
+
+class _FilterApp(_ObjectType):
+    name = 'filter_app'
+
+    def invoke(self, context):
+        next_app = context.next_context.create()
+        filter = context.filter_context.create()
+        return filter(next_app)
+
+FILTER_APP = _FilterApp()
+
+class _FilterWith(_App):
+    name = 'filtered_with'
+
+    def invoke(self, context):
+        filter = context.filter_context.create()
+        filtered = context.next_context.create()
+        if context.next_context.object_type is APP:
+            return filter(filtered)
+        else:
+            # filtering a filter
+            def composed(app):
+                return filter(filtered(app))
+            return composed
+
+FILTER_WITH = _FilterWith()
+
+############################################################
+## Loaders
+############################################################
+
+def loadapp(uri, name=None, **kw):
+    return loadobj(APP, uri, name=name, **kw)
+
+def loadfilter(uri, name=None, **kw):
+    return loadobj(FILTER, uri, name=name, **kw)
+
+def loadserver(uri, name=None, **kw):
+    return loadobj(SERVER, uri, name=name, **kw)
+
+def appconfig(uri, name=None, relative_to=None, global_conf=None):
+    context = loadcontext(APP, uri, name=name,
+                          relative_to=relative_to,
+                          global_conf=global_conf)
+    return context.config()
+
+_loaders = {}
+
+def loadobj(object_type, uri, name=None, relative_to=None,
+            global_conf=None):
+    context = loadcontext(
+        object_type, uri, name=name, relative_to=relative_to,
+        global_conf=global_conf)
+    return context.create()
+
+def loadcontext(object_type, uri, name=None, relative_to=None,
+                global_conf=None):
+    if '#' in uri:
+        if name is None:
+            uri, name = uri.split('#', 1)
+        else:
+            # @@: Ignore fragment or error?
+            uri = uri.split('#', 1)[0]
+    if name is None:
+        name = 'main'
+    if ':' not in uri:
+        raise LookupError("URI has no scheme: %r" % uri)
+    scheme, path = uri.split(':', 1)
+    scheme = scheme.lower()
+    if scheme not in _loaders:
+        raise LookupError(
+            "URI scheme not known: %r (from %s)"
+            % (scheme, ', '.join(_loaders.keys())))
+    return _loaders[scheme](
+        object_type,
+        uri, path, name=name, relative_to=relative_to,
+        global_conf=global_conf)
+
+def _loadconfig(object_type, uri, path, name, relative_to,
+                global_conf):
+    isabs = os.path.isabs(path)
+    # De-Windowsify the paths:
+    path = path.replace('\\', '/')
+    if not isabs:
+        if not relative_to:
+            raise ValueError(
+                "Cannot resolve relative uri %r; no relative_to keyword "
+                "argument given" % uri)
+        relative_to = relative_to.replace('\\', '/')
+        if relative_to.endswith('/'):
+            path = relative_to + path
+        else:
+            path = relative_to + '/' + path
+    if path.startswith('///'):
+        path = path[2:]
+    path = urllib.unquote(path)
+    loader = ConfigLoader(path)
+    if global_conf:
+        loader.update_defaults(global_conf, overwrite=False)
+    return loader.get_context(object_type, name, global_conf)
+
+_loaders['config'] = _loadconfig
+
+def _loadegg(object_type, uri, spec, name, relative_to,
+             global_conf):
+    loader = EggLoader(spec)
+    return loader.get_context(object_type, name, global_conf)
+
+_loaders['egg'] = _loadegg
+
+############################################################
+## Loaders
+############################################################
+
+class _Loader(object):
+
+    def get_app(self, name=None, global_conf=None):
+        return self.app_context(
+            name=name, global_conf=global_conf).create()
+
+    def get_filter(self, name=None, global_conf=None):
+        return self.filter_context(
+            name=name, global_conf=global_conf).create()
+
+    def get_server(self, name=None, global_conf=None):
+        return self.server_context(
+            name=name, global_conf=global_conf).create()
+
+    def app_context(self, name=None, global_conf=None):
+        return self.get_context(
+            APP, name=name, global_conf=global_conf)
+
+    def filter_context(self, name=None, global_conf=None):
+        return self.get_context(
+            FILTER, name=name, global_conf=global_conf)
+
+    def server_context(self, name=None, global_conf=None):
+        return self.get_context(
+            SERVER, name=name, global_conf=global_conf)
+
+    _absolute_re = re.compile(r'^[a-zA-Z]+:')
+    def absolute_name(self, name):
+        """
+        Returns true if the name includes a scheme
+        """
+        if name is None:
+            return False
+        return self._absolute_re.search(name)
+
+class ConfigLoader(_Loader):
+
+    def __init__(self, filename):
+        self.filename = filename = filename.strip()
+        self.parser = NicerConfigParser(self.filename)
+        # Don't lower-case keys:
+        self.parser.optionxform = str
+        # Stupid ConfigParser ignores files that aren't found, so
+        # we have to add an extra check:
+        if not os.path.exists(filename):
+            if filename.strip() != filename:
+                raise IOError(
+                    "File %r not found; trailing whitespace: "
+                    "did you try to use a # on the same line as a filename? "
+                    "(comments must be on their own line)" % filename)
+            raise IOError(
+                "File %r not found" % filename)
+        self.parser.read(filename)
+        self.parser._defaults.setdefault(
+            'here', os.path.dirname(os.path.abspath(filename)))
+        self.parser._defaults.setdefault(
+            '__file__', os.path.abspath(filename))
+
+    def update_defaults(self, new_defaults, overwrite=True):
+        for key, value in new_defaults.items():
+            if not overwrite and key in self.parser._defaults:
+                continue
+            self.parser._defaults[key] = value
+
+    def get_context(self, object_type, name=None, global_conf=None):
+        if self.absolute_name(name):
+            return loadcontext(object_type, name,
+                               relative_to=os.path.dirname(self.filename),
+                               global_conf=global_conf)
+        section = self.find_config_section(
+            object_type, name=name)
+        if global_conf is None:
+            global_conf = {}
+        else:
+            global_conf = global_conf.copy()
+        defaults = self.parser.defaults()
+        global_conf.update(defaults)
+        local_conf = {}
+        global_additions = {}
+        get_from_globals = {}
+        for option in self.parser.options(section):
+            if option.startswith('set '):
+                name = option[4:].strip()
+                global_additions[name] = global_conf[name] = (
+                    self.parser.get(section, option))
+            elif option.startswith('get '):
+                name = option[4:].strip()
+                get_from_globals[name] = self.parser.get(section, option)
+            else:
+                if option in defaults:
+                    # @@: It's a global option (?), so skip it
+                    continue
+                local_conf[option] = self.parser.get(section, option)
+        for local_var, glob_var in get_from_globals.items():
+            local_conf[local_var] = global_conf[glob_var]
+        if object_type in (APP, FILTER) and 'filter-with' in local_conf:
+            filter_with = local_conf.pop('filter-with')
+        else:
+            filter_with = None
+        if 'require' in local_conf:
+            for spec in local_conf['require'].split():
+                pkg_resources.require(spec)
+            del local_conf['require']
+        if section.startswith('filter-app:'):
+            context = self._filter_app_context(
+                object_type, section, name=name,
+                global_conf=global_conf, local_conf=local_conf,
+                global_additions=global_additions)
+        elif section.startswith('pipeline:'):
+            context = self._pipeline_app_context(
+                object_type, section, name=name,
+                global_conf=global_conf, local_conf=local_conf,
+                global_additions=global_additions)
+        elif 'use' in local_conf:
+            context = self._context_from_use(
+                object_type, local_conf, global_conf, global_additions,
+                section)
+        else:
+            context = self._context_from_explicit(
+                object_type, local_conf, global_conf, global_additions,
+                section)
+        if filter_with is not None:
+            filter_with_context = LoaderContext(
+                obj=None,
+                object_type=FILTER_WITH,
+                protocol=None,
+                global_conf=global_conf, local_conf=local_conf,
+                loader=self)
+            filter_with_context.filter_context = self.filter_context(
+                name=filter_with, global_conf=global_conf)
+            filter_with_context.next_context = context
+            return filter_with_context
+        return context
+
+    def _context_from_use(self, object_type, local_conf, global_conf,
+                          global_additions, section):
+        use = local_conf.pop('use')
+        context = self.get_context(
+            object_type, name=use, global_conf=global_conf)
+        context.global_conf.update(global_additions)
+        context.local_conf.update(local_conf)
+        if '__file__' in global_conf:
+            # use sections shouldn't overwrite the original __file__
+            context.global_conf['__file__'] = global_conf['__file__']
+        # @@: Should loader be overwritten?
+        context.loader = self
+        return context
+
+    def _context_from_explicit(self, object_type, local_conf, global_conf,
+                               global_addition, section):
+        possible = []
+        for protocol_options in object_type.egg_protocols:
+            for protocol in protocol_options:
+                if protocol in local_conf:
+                    possible.append((protocol, local_conf[protocol]))
+                    break
+        if len(possible) > 1:
+            raise LookupError(
+                "Multiple protocols given in section %r: %s"
+                % (section, possible))
+        if not possible:
+            raise LookupError(
+                "No loader given in section %r" % section)
+        found_protocol, found_expr = possible[0]
+        del local_conf[found_protocol]
+        value = import_string(found_expr)
+        context = LoaderContext(
+            value, object_type, found_protocol,
+            global_conf, local_conf, self)
+        return context
+
+    def _filter_app_context(self, object_type, section, name,
+                            global_conf, local_conf, global_additions):
+        if 'next' not in local_conf:
+            raise LookupError(
+                "The [%s] section in %s is missing a 'next' setting"
+                % (section, self.filename))
+        next_name = local_conf.pop('next')
+        context = LoaderContext(None, FILTER_APP, None, global_conf,
+                                local_conf, self)
+        context.next_context = self.get_context(
+            APP, next_name, global_conf)
+        if 'use' in local_conf:
+            context.filter_context = self._context_from_use(
+                FILTER, local_conf, global_conf, global_additions,
+                section)
+        else:
+            context.filter_context = self._context_from_explicit(
+                FILTER, local_conf, global_conf, global_additions,
+                section)
+        return context
+
+    def _pipeline_app_context(self, object_type, section, name,
+                              global_conf, local_conf, global_additions):
+        if 'pipeline' not in local_conf:
+            raise LookupError(
+                "The [%s] section in %s is missing a 'pipeline' setting"
+                % (section, self.filename))
+        pipeline = local_conf.pop('pipeline').split()
+        if local_conf:
+            raise LookupError(
+                "The [%s] pipeline section in %s has extra "
+                "(disallowed) settings: %s"
+                % (', '.join(local_conf.keys())))
+        context = LoaderContext(None, PIPELINE, None, global_conf,
+                                local_conf, self)
+        context.app_context = self.get_context(
+            APP, pipeline[-1], global_conf)
+        context.filter_contexts = [
+            self.get_context(FILTER, name, global_conf)
+            for name in pipeline[:-1]]
+        return context
+
+    def find_config_section(self, object_type, name=None):
+        """
+        Return the section name with the given name prefix (following the
+        same pattern as ``protocol_desc`` in ``config``.  It must have the
+        given name, or for ``'main'`` an empty name is allowed.  The
+        prefix must be followed by a ``:``.
+
+        Case is *not* ignored.
+        """
+        possible = []
+        for name_options in object_type.config_prefixes:
+            for name_prefix in name_options:
+                found = self._find_sections(
+                    self.parser.sections(), name_prefix, name)
+                if found:
+                    possible.extend(found)
+                    break
+        if not possible:
+            raise LookupError(
+                "No section %r (prefixed by %s) found in config %s"
+                % (name,
+                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
+                   self.filename))
+        if len(possible) > 1:
+            raise LookupError(
+                "Ambiguous section names %r for section %r (prefixed by %s) "
+                "found in config %s"
+                % (possible, name,
+                   ' or '.join(map(repr, _flatten(object_type.config_prefixes))),
+                   self.filename))
+        return possible[0]
+
+    def _find_sections(self, sections, name_prefix, name):
+        found = []
+        if name is None:
+            if name_prefix in sections:
+                found.append(name_prefix)
+            name = 'main'
+        for section in sections:
+            if section.startswith(name_prefix+':'):
+                if section[len(name_prefix)+1:].strip() == name:
+                    found.append(section)
+        return found
+
+
+class EggLoader(_Loader):
+
+    def __init__(self, spec):
+        self.spec = spec
+
+    def get_context(self, object_type, name=None, global_conf=None):
+        if self.absolute_name(name):
+            return loadcontext(object_type, name,
+                               global_conf=global_conf)
+        entry_point, protocol, ep_name = self.find_egg_entry_point(
+            object_type, name=name)
+        return LoaderContext(
+            entry_point,
+            object_type,
+            protocol,
+            global_conf or {}, {},
+            self,
+            distribution=pkg_resources.get_distribution(self.spec),
+            entry_point_name=ep_name)
+
+    def find_egg_entry_point(self, object_type, name=None):
+        """
+        Returns the (entry_point, protocol) for the with the given
+        ``name``.
+        """
+        if name is None:
+            name = 'main'
+        possible = []
+        for protocol_options in object_type.egg_protocols:
+            for protocol in protocol_options:
+                pkg_resources.require(self.spec)
+                entry = pkg_resources.get_entry_info(
+                    self.spec,
+                    protocol,
+                    name)
+                if entry is not None:
+                    possible.append((entry.load(), protocol, entry.name))
+                    break
+        if not possible:
+            # Better exception
+            dist = pkg_resources.get_distribution(self.spec)
+            raise LookupError(
+                "Entry point %r not found in egg %r (dir: %s; protocols: %s; "
+                "entry_points: %s)"
+                % (name, self.spec,
+                   dist.location,
+                   ', '.join(_flatten(object_type.egg_protocols)),
+                   ', '.join(_flatten([
+                (pkg_resources.get_entry_info(self.spec, prot, name) or {}).keys()
+                for prot in protocol_options] or '(no entry points)'))))
+        if len(possible) > 1:
+            raise LookupError(
+                "Ambiguous entry points for %r in egg %r (protocols: %s)"
+                % (name, self.spec, ', '.join(_flatten(protocol_options))))
+        return possible[0]
+
+class LoaderContext(object):
+
+    def __init__(self, obj, object_type, protocol,
+                 global_conf, local_conf, loader,
+                 distribution=None, entry_point_name=None):
+        self.object = obj
+        self.object_type = object_type
+        self.protocol = protocol
+        #assert protocol in _flatten(object_type.egg_protocols), (
+        #    "Bad protocol %r; should be one of %s"
+        #    % (protocol, ', '.join(map(repr, _flatten(object_type.egg_protocols)))))
+        self.global_conf = global_conf
+        self.local_conf = local_conf
+        self.loader = loader
+        self.distribution = distribution
+        self.entry_point_name = entry_point_name
+
+    def create(self):
+        return self.object_type.invoke(self)
+
+    def config(self):
+        conf = AttrDict(self.global_conf)
+        conf.update(self.local_conf)
+        conf.local_conf = self.local_conf
+        conf.global_conf = self.global_conf
+        conf.context = self
+        return conf
+
+class AttrDict(dict):
+    """
+    A dictionary that can be assigned to.
+    """
+    pass

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/paster_templates.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/paster_templates.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/paster_templates.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+from paste.script.templates import Template
+
+class PasteDeploy(Template):
+
+    _template_dir = 'paster_templates/paste_deploy'
+    summary = "A web application deployed through paste.deploy"
+    
+    egg_plugins = ['PasteDeploy']
+    
+    required_templates = ['PasteScript#basic_package']
+
+    def post(self, command, output_dir, vars):
+        for prereq in ['PasteDeploy']:
+            command.insert_into_file(
+                os.path.join(output_dir, 'setup.py'),
+                'Extra requirements',
+                '%r,\n' % prereq,
+                indent=True)
+        command.insert_into_file(
+            os.path.join(output_dir, 'setup.py'),
+            'Entry points',
+            ('      [paste.app_factory]\n'
+             '      main = %(package)s.wsgiapp:make_app\n') % vars,
+            indent=False)
+        if command.verbose:
+            print '*'*72
+            print '* Run "paster serve docs/devel_config.ini" to run the sample application'
+            print '* on http://localhost:8080'
+            print '*'*72
+        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/fixtypeerror.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/fixtypeerror.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/fixtypeerror.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,61 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Fixes the vague error message that you get when calling a function
+with the wrong arguments.
+"""
+import inspect
+import sys
+
+def fix_type_error(exc_info, callable, varargs, kwargs):
+    """
+    Given an exception, this will test if the exception was due to a
+    signature error, and annotate the error with better information if
+    so.
+    
+    Usage::
+
+      try:
+          val = callable(*args, **kw)
+      except TypeError:
+          exc_info = fix_type_error(None, callable, args, kw)
+          raise exc_info[0], exc_info[1], exc_info[2]
+    """
+    if exc_info is None:
+        exc_info = sys.exc_info()
+    if (exc_info[0] != TypeError
+        or str(exc_info[1]).find('arguments') == -1
+        or getattr(exc_info[1], '_type_error_fixed', False)):
+        return exc_info
+    exc_info[1]._type_error_fixed = True
+    import inspect
+    argspec = inspect.formatargspec(*inspect.getargspec(callable))
+    args = ', '.join(map(_short_repr, varargs))
+    if kwargs and args:
+        args += ', '
+    if kwargs:
+        kwargs = kwargs.items()
+        kwargs.sort()
+        args += ', '.join(['%s=...' % n for n, v in kwargs])
+    gotspec = '(%s)' % args
+    msg = '%s; got %s, wanted %s' % (exc_info[1], gotspec, argspec)
+    exc_info[1].args = (msg,)
+    return exc_info
+
+def _short_repr(v):
+    v = repr(v)
+    if len(v) > 12:
+        v = v[:8]+'...'+v[-4:]
+    return v
+
+def fix_call(callable, *args, **kw):
+    """
+    Call ``callable(*args, **kw)`` fixing any type errors that come
+    out.
+    """
+    try:
+        val = callable(*args, **kw)
+    except TypeError:
+        exc_info = fix_type_error(None, callable, args, kw)
+        raise exc_info[0], exc_info[1], exc_info[2]
+    return val

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/threadinglocal.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/threadinglocal.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/paste/deploy/util/threadinglocal.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,39 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+
+try:
+    import threading
+except ImportError:
+    # No threads, so "thread local" means process-global
+    class local(object):
+        pass
+else:
+    try:
+        local = threading.local
+    except AttributeError:
+        # Added in 2.4, but now we'll have to define it ourselves
+        import thread
+        class local(object):
+
+            def __init__(self):
+                self.__dict__['__objs'] = {}
+
+            def __getattr__(self, attr, g=thread.get_ident):
+                try:
+                    return self.__dict__['__objs'][g()][attr]
+                except KeyError:
+                    raise AttributeError(
+                        "No variable %s defined for the thread %s"
+                        % (attr, g()))
+
+            def __setattr__(self, attr, value, g=thread.get_ident):
+                self.__dict__['__objs'].setdefault(g(), {})[attr] = value
+
+            def __delattr__(self, attr, g=thread.get_ident):
+                try:
+                    del self.__dict__['__objs'][g()][attr]
+                except KeyError:
+                    raise AttributeError(
+                        "No variable %s defined for thread %s"
+                        % (attr, g()))
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+import os
+import sys
+
+here = os.path.dirname(__file__)
+base = os.path.dirname(here)
+sys.path.insert(0, base)
+
+# We can only import this after we adjust the paths
+import pkg_resources
+
+# Make absolutely sure we're testing *this* package, not
+# some other installed package
+pkg_resources.require('PasteDeploy')
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/finddata.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/finddata.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/finddata.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,99 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# Note: you may want to copy this into your setup.py file verbatim, as
+# you can't import this from another package, when you don't know if
+# that package is installed yet.
+
+import os
+import sys
+from fnmatch import fnmatchcase
+from distutils.util import convert_path
+
+# Provided as an attribute, so you can append to these instead
+# of replicating them:
+standard_exclude = ('*.py', '*.pyc', '*$py.class', '*~', '.*', '*.bak')
+standard_exclude_directories = ('.*', 'CVS', '_darcs', './build',
+                                './dist', 'EGG-INFO', '*.egg-info')
+
+def find_package_data(
+    where='.', package='',
+    exclude=standard_exclude,
+    exclude_directories=standard_exclude_directories,
+    only_in_packages=True,
+    show_ignored=False):
+    """
+    Return a dictionary suitable for use in ``package_data``
+    in a distutils ``setup.py`` file.
+
+    The dictionary looks like::
+
+        {'package': [files]}
+
+    Where ``files`` is a list of all the files in that package that
+    don't match anything in ``exclude``.
+
+    If ``only_in_packages`` is true, then top-level directories that
+    are not packages won't be included (but directories under packages
+    will).
+
+    Directories matching any pattern in ``exclude_directories`` will
+    be ignored; by default directories with leading ``.``, ``CVS``,
+    and ``_darcs`` will be ignored.
+
+    If ``show_ignored`` is true, then all the files that aren't
+    included in package data are shown on stderr (for debugging
+    purposes).
+
+    Note patterns use wildcards, or can be exact paths (including
+    leading ``./``), and all searching is case-insensitive.
+    """
+
+    out = {}
+    stack = [(convert_path(where), '', package, only_in_packages)]
+    while stack:
+        where, prefix, package, only_in_packages = stack.pop(0)
+        for name in os.listdir(where):
+            fn = os.path.join(where, name)
+            if os.path.isdir(fn):
+                bad_name = False
+                for pattern in exclude_directories:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "Directory %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                if (os.path.isfile(os.path.join(fn, '__init__.py'))
+                    and not prefix):
+                    if not package:
+                        new_package = name
+                    else:
+                        new_package = package + '.' + name
+                    stack.append((fn, '', new_package, False))
+                else:
+                    stack.append((fn, prefix + name + '/', package, only_in_packages))
+            elif package or not only_in_packages:
+                # is a file
+                bad_name = False
+                for pattern in exclude:
+                    if (fnmatchcase(name, pattern)
+                        or fn.lower() == pattern.lower()):
+                        bad_name = True
+                        if show_ignored:
+                            print >> sys.stderr, (
+                                "File %s ignored by pattern %s"
+                                % (fn, pattern))
+                        break
+                if bad_name:
+                    continue
+                out.setdefault(package, []).append(prefix+name)
+    return out
+
+if __name__ == '__main__':
+    import pprint
+    pprint.pprint(
+        find_package_data(show_ignored=True))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/fixture.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/fixture.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/fixture.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+import os
+import sys
+import shutil
+
+test_dir = os.path.dirname(__file__)
+egg_info_dir = os.path.join(test_dir, 'fake_packages', 'FakeApp.egg',
+                            'EGG-INFO')
+info_dir = os.path.join(test_dir, 'fake_packages', 'FakeApp.egg',
+                        'FakeApp.egg-info')
+if not os.path.exists(egg_info_dir):
+    try:
+        os.symlink(info_dir, egg_info_dir)
+    except:
+        shutil.copytree(info_dir, egg_info_dir)
+        
+sys.path.append(os.path.dirname(egg_info_dir))
+
+from pkg_resources import *
+working_set.add_entry(os.path.dirname(egg_info_dir))
+require('FakeApp')
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_basic_app.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_basic_app.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_basic_app.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,34 @@
+from paste.deploy import loadapp, loadfilter, appconfig
+from fixture import *
+import fakeapp.apps
+
+here = os.path.dirname(__file__)
+
+def test_main():
+    app = loadapp('config:sample_configs/basic_app.ini',
+                  relative_to=here)
+    assert app is fakeapp.apps.basic_app
+    app = loadapp('config:sample_configs/basic_app.ini#main',
+                  relative_to=here)
+    assert app is fakeapp.apps.basic_app
+    app = loadapp('config:sample_configs/basic_app.ini',
+                  relative_to=here, name='main')
+    assert app is fakeapp.apps.basic_app
+    app = loadapp('config:sample_configs/basic_app.ini#ignored',
+                  relative_to=here, name='main')
+    assert app is fakeapp.apps.basic_app
+
+def test_other():
+    app = loadapp('config:sample_configs/basic_app.ini#other',
+                  relative_to=here)
+    assert app is fakeapp.apps.basic_app2
+    
+
+def test_composit():
+    app = loadapp('config:sample_configs/basic_app.ini#remote_addr',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.RemoteAddrDispatch)
+    assert app.map['127.0.0.1'] is fakeapp.apps.basic_app
+    assert app.map['0.0.0.0'] is fakeapp.apps.basic_app2
+    
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,116 @@
+import os
+from paste.deploy import loadapp, loadfilter, appconfig
+from fixture import *
+import fakeapp.configapps as fc
+from pprint import pprint
+
+ini_file = 'config:sample_configs/test_config.ini'
+here = os.path.dirname(__file__)
+config_path = os.path.join(here, 'sample_configs')
+config_filename = os.path.join(config_path, 'test_config.ini')
+
+def test_config_egg():
+    app = loadapp('egg:FakeApp#configed')
+    assert isinstance(app, fc.SimpleApp)
+    
+def test_config1():
+    app = loadapp(ini_file, relative_to=here, name='test1')
+    assert app.local_conf == {
+        'setting1': 'foo', 'setting2': 'bar'}
+    assert app.global_conf == {
+        'def1': 'a', 'def2': 'b',
+        'here': config_path,
+        '__file__': config_filename}
+
+def test_config2():
+    app = loadapp(ini_file, relative_to=here, name='test2')
+    assert app.local_conf == {
+        'local conf': 'something'}
+    assert app.global_conf == {
+        'def1': 'test2',
+        'def2': 'b',
+        'another': 'TEST',
+        'here': config_path,
+        '__file__': config_filename}
+    # Run this to make sure the global-conf-modified test2
+    # didn't mess up the general global conf
+    test_config1()
+
+def test_config3():
+    app = loadapp(ini_file, relative_to=here, name='test3')
+    assert isinstance(app, fc.SimpleApp)
+    assert app.local_conf == {
+        'local conf': 'something',
+        'another': 'something more\nacross several\nlines'}
+    assert app.global_conf == {
+        'def1': 'test3',
+        'def2': 'b',
+        'another': 'TEST',
+        'here': config_path,
+        '__file__': config_filename}
+    test_config2()
+    
+def test_foreign_config():
+    app = loadapp(ini_file, relative_to=here, name='test_foreign_config')
+    assert isinstance(app, fc.SimpleApp)
+    assert app.local_conf == {
+        'another': 'FOO',
+        'bob': 'your uncle'}
+    pprint(app.global_conf)
+    assert app.global_conf == {
+        'def1': 'a',
+        'def2': 'from include',
+        'def3': 'c',
+        'glob': 'override',
+        'here': config_path,
+        '__file__': os.path.join(config_path, 'test_config.ini')}
+    
+def test_config_get():
+    app = loadapp(ini_file, relative_to=here, name='test_get')
+    assert isinstance(app, fc.SimpleApp)
+    assert app.local_conf == {
+        'def1': 'a',
+        'foo': 'TEST'}
+    assert app.global_conf == {
+        'def1': 'a',
+        'def2': 'TEST',
+        'here': config_path,
+        '__file__': config_filename}
+
+def test_appconfig():
+    conf = appconfig(ini_file, relative_to=here, name='test_get')
+    assert conf == {
+        'def1': 'a',
+        'def2': 'TEST',
+        'here': config_path,
+        '__file__': config_filename,
+        'foo': 'TEST'}
+    assert conf.local_conf == {
+        'def1': 'a',
+        'foo': 'TEST'}
+    assert conf.global_conf == {
+        'def1': 'a',
+        'def2': 'TEST',
+        'here': config_path,
+        '__file__': config_filename,}
+
+def test_appconfig_filter_with():
+    conf = appconfig('config:test_filter_with.ini', relative_to=config_path)
+    assert conf['example'] == 'test'
+
+def test_global_conf():
+    conf = appconfig(ini_file, relative_to=here, name='test_global_conf', global_conf={'def2': 'TEST DEF 2', 'inherit': 'bazbar'})
+    pprint(conf)
+    assert conf == {
+        'def1': 'a',
+        # Note that this gets overwritten:
+        'def2': 'b',
+        'here': config_path,
+        'inherit': 'bazbar',
+        '__file__': config_filename,
+        'test_interp': 'this:bazbar',
+        }
+    assert conf.local_conf == {
+        'test_interp': 'this:bazbar',
+        }
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config_middleware.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config_middleware.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_config_middleware.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+from nose.tools import assert_raises
+from paste.deploy.config import ConfigMiddleware
+from paste.fixture import TestApp
+
+class Bug(Exception): pass
+
+def app_with_exception(environ, start_response):
+    def cont():
+        yield "something"
+        raise Bug
+    start_response('200 OK', [('Content-type', 'text/html')])
+    return cont()
+
+def test_error():
+    wrapped = ConfigMiddleware(app_with_exception, {'test': 1})
+    test_app = TestApp(wrapped)
+    assert_raises(Bug, test_app.get, '/')
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_filter.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_filter.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_filter.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,46 @@
+from paste.deploy import loadapp, loadfilter
+from fixture import *
+import fakeapp.apps
+
+here = os.path.dirname(__file__)
+
+def test_filter_app():
+    app = loadapp('config:sample_configs/test_filter.ini#filt',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert app.app is fakeapp.apps.basic_app
+    assert app.method_to_call == 'lower'
+
+def test_pipeline():
+    app = loadapp('config:sample_configs/test_filter.ini#piped',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert app.app is fakeapp.apps.basic_app
+    assert app.method_to_call == 'upper'
+
+def test_filter_app2():
+    app = loadapp('config:sample_configs/test_filter.ini#filt2',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert app.app is fakeapp.apps.basic_app
+    assert app.method_to_call == 'lower'
+
+def test_pipeline2():
+    app = loadapp('config:sample_configs/test_filter.ini#piped2',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert app.app is fakeapp.apps.basic_app
+    assert app.method_to_call == 'upper'
+
+def test_filter_app_inverted():
+    app = loadapp('config:sample_configs/test_filter.ini#inv',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert app.app is fakeapp.apps.basic_app
+
+def test_filter_with_filter_with():
+    app = loadapp('config:sample_configs/test_filter_with.ini',
+                  relative_to=here)
+    assert isinstance(app, fakeapp.apps.CapFilter)
+    assert isinstance(app.app, fakeapp.apps.CapFilter)
+    assert app.app.app is fakeapp.apps.basic_app

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_load_package.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_load_package.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteDeploy-1.3.4-py2.6.egg/tests/test_load_package.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+import sys, os
+import pkg_resources
+import site
+from pprint import pprint
+
+def test_load_package():
+    print 'Path:'
+    pprint(sys.path)
+    print pkg_resources.require('FakeApp')
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,43 @@
+Metadata-Version: 1.0
+Name: PasteScript
+Version: 1.7.3
+Summary: A pluggable command-line frontend, including commands to setup package file layouts
+Home-page: http://pythonpaste.org/script/
+Author: Ian Bicking
+Author-email: ianb at colorstudy.com
+License: MIT
+Description: This is a pluggable command-line tool.
+        
+        It includes some built-in features;
+        
+        * Create file layouts for packages.  For instance, ``paste create
+          --template=basic_package MyPackage`` will create a `setuptools
+          <http://peak.telecommunity.com/DevCenter/setuptools>`_-ready
+          file layout.
+        
+        * Serving up web applications, with configuration based on
+          `paste.deploy <http://pythonpaste.org/deploy/paste-deploy.html>`_.
+        
+        The latest version is available in a `Subversion repository
+        <http://svn.pythonpaste.org/Paste/Script/trunk#egg=PasteScript-dev>`_.
+        
+        For the latest changes see the `news file
+        <http://pythonpaste.org/script/news.html>`_.
+        
+        Changes in 1.7.3
+        ----------------
+        
+        * CherryPy wsgiserver updated to 3.1.1, fixes a regression in Python
+          2.5 plus a couple other small fixes.
+        
+        
+Keywords: web wsgi setuptools framework command-line setup
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content
+Classifier: Topic :: Software Development :: Libraries :: Python Modules
+Classifier: Framework :: Paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,86 @@
+ez_setup.py
+regen-docs
+setup.cfg
+setup.py
+PasteScript.egg-info/PKG-INFO
+PasteScript.egg-info/SOURCES.txt
+PasteScript.egg-info/dependency_links.txt
+PasteScript.egg-info/entry_points.txt
+PasteScript.egg-info/namespace_packages.txt
+PasteScript.egg-info/not-zip-safe
+PasteScript.egg-info/requires.txt
+PasteScript.egg-info/top_level.txt
+docs/conf.py
+docs/developer.txt
+docs/example_app.ini
+docs/example_cgi_app.ini
+docs/index.txt
+docs/license.txt
+docs/news.txt
+docs/_static/paste.css
+docs/_templates/layout.html
+docs/modules/checkperms.txt
+docs/modules/command.txt
+docs/modules/copydir.txt
+docs/modules/filemaker.txt
+docs/modules/templates.txt
+docs/modules/testapp.txt
+docs/modules/util.secret.txt
+paste/__init__.py
+paste/script/__init__.py
+paste/script/appinstall.py
+paste/script/bool_optparse.py
+paste/script/cgi_server.py
+paste/script/checkperms.py
+paste/script/cherrypy_server.py
+paste/script/command.py
+paste/script/copydir.py
+paste/script/create_distro.py
+paste/script/default_sysconfig.py
+paste/script/entrypoints.py
+paste/script/epdesc.py
+paste/script/exe.py
+paste/script/filemaker.py
+paste/script/flup_server.py
+paste/script/grep.py
+paste/script/help.py
+paste/script/interfaces.py
+paste/script/pluginlib.py
+paste/script/request.py
+paste/script/serve.py
+paste/script/templates.py
+paste/script/testapp.py
+paste/script/twisted_web2_server.py
+paste/script/wsgiutils_server.py
+paste/script/paster-templates/basic_package/setup.cfg
+paste/script/paster-templates/basic_package/setup.py_tmpl
+paste/script/paster-templates/basic_package/+package+/__init__.py
+paste/script/paster-templates/basic_package/docs/license.txt_tmpl
+paste/script/util/__init__.py
+paste/script/util/logging_config.py
+paste/script/util/secret.py
+paste/script/util/string24.py
+paste/script/util/subprocess24.py
+paste/script/util/uuid.py
+paste/script/wsgiserver/__init__.py
+scripts/paster
+tests/conftest.py
+tests/test_egg_finder.py
+tests/test_logging_config.py
+tests/test_plugin_adder.py
+tests/test_template_introspect.py
+tests/appsetup/test_make_project.py
+tests/appsetup/testfiles/admin_index.py
+tests/appsetup/testfiles/conftest.py
+tests/appsetup/testfiles/iscape.txt
+tests/appsetup/testfiles/test_forbidden.py
+tests/fake_packages/FakePlugin.egg/setup.py
+tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/PKG-INFO
+tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/entry_points.txt
+tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/paster_plugins.txt
+tests/fake_packages/FakePlugin.egg/FakePlugin.egg-info/top_level.txt
+tests/fake_packages/FakePlugin.egg/fakeplugin/__init__.py
+tests/sample_templates/test1.txt
+tests/sample_templates/test2.py_tmpl
+tests/sample_templates/test3.ini_tmpl
+tests/sample_templates/test4.html_tmpl
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/entry_points.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/entry_points.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/entry_points.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,59 @@
+
+    [paste.global_paster_command]
+    help=paste.script.help:HelpCommand
+    create=paste.script.create_distro:CreateDistroCommand [Templating]
+    serve=paste.script.serve:ServeCommand [Config]
+    request=paste.script.request:RequestCommand [Config]
+    post=paste.script.request:RequestCommand [Config]
+    exe=paste.script.exe:ExeCommand
+    points=paste.script.entrypoints:EntryPointCommand
+    make-config=paste.script.appinstall:MakeConfigCommand
+    setup-app=paste.script.appinstall:SetupCommand
+
+    [paste.paster_command]
+    grep = paste.script.grep:GrepCommand
+
+    [paste.paster_create_template]
+    basic_package=paste.script.templates:BasicPackage
+
+    [paste.server_runner]
+    wsgiutils=paste.script.wsgiutils_server:run_server [WSGIUtils]
+    flup_ajp_thread=paste.script.flup_server:run_ajp_thread [Flup]
+    flup_ajp_fork=paste.script.flup_server:run_ajp_fork [Flup]
+    flup_fcgi_thread=paste.script.flup_server:run_fcgi_thread [Flup]
+    flup_fcgi_fork=paste.script.flup_server:run_fcgi_fork [Flup]
+    flup_scgi_thread=paste.script.flup_server:run_scgi_thread [Flup]
+    flup_scgi_fork=paste.script.flup_server:run_scgi_fork [Flup]
+    cgi=paste.script.cgi_server:paste_run_cgi
+    cherrypy=paste.script.cherrypy_server:cpwsgi_server
+    twisted=paste.script.twisted_web2_server:run_twisted
+
+    [paste.app_factory]
+    test=paste.script.testapp:make_test_application
+
+    [paste.entry_point_description]
+    paste.entry_point_description = paste.script.epdesc:MetaEntryPointDescription
+    paste.paster_create_template = paste.script.epdesc:CreateTemplateDescription
+    paste.paster_command = paste.script.epdesc:PasterCommandDescription
+    paste.global_paster_command = paste.script.epdesc:GlobalPasterCommandDescription
+    paste.app_install = paste.script.epdesc:AppInstallDescription
+
+    # These aren't part of Paste Script particularly, but
+    # we'll document them here
+    console_scripts = paste.script.epdesc:ConsoleScriptsDescription
+    # @@: Need non-console scripts...
+    distutils.commands = paste.script.epdesc:DistutilsCommandsDescription
+    distutils.setup_keywords = paste.script.epdesc:SetupKeywordsDescription
+    egg_info.writers = paste.script.epdesc:EggInfoWriters
+    # @@: Not sure what this does:
+    #setuptools.file_finders = paste.script.epdesc:SetuptoolsFileFinders
+    
+    [console_scripts]
+    paster=paste.script.command:run
+
+    [distutils.setup_keywords]
+    paster_plugins = setuptools.dist:assert_string_list
+
+    [egg_info.writers]
+    paster_plugins.txt = setuptools.command.egg_info:write_arg
+    
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/namespace_packages.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/namespace_packages.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/namespace_packages.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/requires.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/requires.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/requires.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+Paste>=1.3
+PasteDeploy
+
+[Templating]
+
+
+[Config]
+PasteDeploy
+
+[WSGIUtils]
+WSGIUtils
+
+[Flup]
+Flup
+
+[Cheetah]
+Cheetah
+
+[Paste]
+PasteDeploy
+Cheetah
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/scripts/paster
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/scripts/paster	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/scripts/paster	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+#!/work/develop/repository/svn.zope.org/zopeorg.buildout/branches/beta.zope.org/bin/python
+import os
+import sys
+
+try:
+    here = __file__
+except NameError:
+    # Python 2.2
+    here = sys.argv[0]
+
+relative_paste = os.path.join(
+    os.path.dirname(os.path.dirname(os.path.abspath(here))), 'paste')
+
+if os.path.exists(relative_paste):
+    sys.path.insert(0, os.path.dirname(relative_paste))
+
+from paste.script import command
+command.run()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+paste

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+try:
+    import pkg_resources
+    pkg_resources.declare_namespace(__name__)
+except ImportError:
+    # don't prevent use of paste if pkg_resources isn't installed
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__) 
+
+try:
+    import modulefinder
+except ImportError:
+    pass
+else:
+    for p in __path__:
+        modulefinder.AddPackagePath(__name__, p)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/appinstall.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/appinstall.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/appinstall.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,613 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Provides the two commands for preparing an application:
+``prepare-app`` and ``setup-app``
+"""
+
+import os
+import sys
+if sys.version_info < (2, 4):
+    from paste.script.util import string24 as string
+else:
+    import string
+import new
+from cStringIO import StringIO
+from paste.script.command import Command, BadCommand, run as run_command
+import paste.script.templates
+from paste.script import copydir
+import pkg_resources
+Cheetah = None
+from ConfigParser import ConfigParser
+from paste.util import import_string
+from paste.deploy import appconfig
+from paste.script.util import uuid
+from paste.script.util import secret
+
+class AbstractInstallCommand(Command):
+
+    default_interactive = 1
+
+    default_sysconfigs = [
+        (False, '/etc/paste/sysconfig.py'),
+        (False, '/usr/local/etc/paste/sysconfig.py'),
+        (True, 'paste.script.default_sysconfig'),
+        ]
+    if os.environ.get('HOME'):
+        default_sysconfigs.insert(
+            0, (False, os.path.join(os.environ['HOME'], '.paste', 'config',
+                                    'sysconfig.py')))
+    if os.environ.get('PASTE_SYSCONFIG'):
+        default_sysconfigs.insert(
+            0, (False, os.environ['PASTE_SYSCONFIG']))
+
+    def run(self, args):
+        # This is overridden so we can parse sys-config before we pass
+        # it to optparse
+        self.sysconfigs = self.default_sysconfigs
+        new_args = []
+        while args:
+            if args[0].startswith('--no-default-sysconfig'):
+                self.sysconfigs = []
+                args.pop(0)
+                continue
+            if args[0].startswith('--sysconfig='):
+                self.sysconfigs.insert(
+                    0, (True, args.pop(0)[len('--sysconfig='):]))
+                continue
+            if args[0] == '--sysconfig':
+                args.pop(0)
+                if not args:
+                    raise BadCommand, (
+                        "You gave --sysconfig as the last argument without "
+                        "a value")
+                self.sysconfigs.insert(0, (True, args.pop(0)))
+                continue
+            new_args.append(args.pop(0))
+        self.load_sysconfigs()
+        return super(AbstractInstallCommand, self).run(new_args)
+
+    #@classmethod
+    def standard_parser(cls, **kw):
+        parser = super(AbstractInstallCommand, cls).standard_parser(**kw)
+        parser.add_option('--sysconfig',
+                          action="append",
+                          dest="sysconfigs",
+                          help="System configuration file")
+        parser.add_option('--no-default-sysconfig',
+                          action='store_true',
+                          dest='no_default_sysconfig',
+                          help="Don't load the default sysconfig files")
+        parser.add_option(
+            '--easy-install',
+            action='append',
+            dest='easy_install_op',
+            metavar='OP',
+            help='An option to add if invoking easy_install (like --easy-install=exclude-scripts)')
+        parser.add_option(
+            '--no-install',
+            action='store_true',
+            dest='no_install',
+            help="Don't try to install the package (it must already be installed)")
+        parser.add_option(
+            '-f', '--find-links',
+            action='append',
+            dest='easy_install_find_links',
+            metavar='URL',
+            help='Passed through to easy_install')
+
+        return parser
+
+    standard_parser = classmethod(standard_parser)
+
+    ########################################
+    ## Sysconfig Handling
+    ########################################
+
+    def load_sysconfigs(self):
+        configs = self.sysconfigs[:]
+        configs.reverse()
+        self.sysconfig_modules = []
+        for index, (explicit, name) in enumerate(configs):
+            # @@: At some point I'd like to give the specialized
+            # modules some access to the values in earlier modules,
+            # e.g., to specialize those values or functions.  That's
+            # why these modules are loaded backwards.
+            if name.endswith('.py'):
+                if not os.path.exists(name):
+                    if explicit:
+                        raise BadCommand, (
+                            "sysconfig file %s does not exist"
+                            % name)
+                    else:
+                        continue
+                globs = {}
+                execfile(name, globs)
+                mod = new.module('__sysconfig_%i__' % index)
+                for name, value in globs.items():
+                    setattr(mod, name, value)
+                mod.__file__ = name
+            else:
+                try:
+                    mod = import_string.simple_import(name)
+                except ImportError, e:
+                    if explicit:
+                        raise
+                    else:
+                        continue
+            mod.paste_command = self
+            self.sysconfig_modules.insert(0, mod)
+        # @@: I'd really prefer to clone the parser here somehow,
+        # not to modify it in place
+        parser = self.parser
+        self.call_sysconfig_functions('add_custom_options', parser)
+
+    def get_sysconfig_option(self, name, default=None):
+        """
+        Return the value of the given option in the first sysconfig
+        module in which it is found, or ``default`` (None) if not
+        found in any.
+        """
+        for mod in self.sysconfig_modules:
+            if hasattr(mod, name):
+                return getattr(mod, name)
+        return default
+
+    def get_sysconfig_options(self, name):
+        """
+        Return the option value for the given name in all the
+        sysconfig modules in which is is found (``[]`` if none).
+        """
+        return [getattr(mod, name) for mod in self.sysconfig_modules
+                if hasattr(mod, name)]
+
+    def call_sysconfig_function(self, name, *args, **kw):
+        """
+        Call the specified function in the first sysconfig module it
+        is defined in.  ``NameError`` if no function is found.
+        """
+        val = self.get_sysconfig_option(name)
+        if val is None:
+            raise NameError, (
+                "Method %s not found in any sysconfig module" % name)
+        return val(*args, **kw)
+
+    def call_sysconfig_functions(self, name, *args, **kw):
+        """
+        Call all the named functions in the sysconfig modules,
+        returning a list of the return values.
+        """
+        return [method(*args, **kw) for method in
+                self.get_sysconfig_options(name)]
+
+    def sysconfig_install_vars(self, installer):
+        """
+        Return the folded results of calling the
+        ``install_variables()`` functions.
+        """
+        result = {}
+        all_vars = self.call_sysconfig_functions(
+            'install_variables', installer)
+        all_vars.reverse()
+        for vardict in all_vars:
+            result.update(vardict)
+        return result
+
+    ########################################
+    ## Distributions
+    ########################################
+
+    def get_distribution(self, req):
+        """
+        This gets a distribution object, and installs the distribution
+        if required.
+        """
+        try:
+            dist = pkg_resources.get_distribution(req)
+            if self.verbose:
+                print 'Distribution already installed:'
+                print ' ', dist, 'from', dist.location
+            return dist
+        except pkg_resources.DistributionNotFound:
+            if self.options.no_install:
+                print "Because --no-install was given, we won't try to install the package %s" % req
+                raise
+            options = ['-v', '-m']
+            for op in self.options.easy_install_op or []:
+                if not op.startswith('-'):
+                    op = '--'+op
+                options.append(op)
+            for op in self.options.easy_install_find_links or []:
+                options.append('--find-links=%s' % op)
+            if self.simulate:
+                raise BadCommand(
+                    "Must install %s, but in simulation mode" % req)
+            print "Must install %s" % req
+            from setuptools.command import easy_install
+            from setuptools import setup
+            setup(script_args=['-q', 'easy_install']
+                  + options + [req])
+            return pkg_resources.get_distribution(req)
+
+    def get_installer(self, distro, ep_group, ep_name):
+        installer_class = distro.load_entry_point(
+            'paste.app_install', ep_name)
+        installer = installer_class(
+            distro, ep_group, ep_name)
+        return installer
+    
+
+class MakeConfigCommand(AbstractInstallCommand):
+
+    default_verbosity = 1
+    max_args = None
+    min_args = 1
+    summary = "Install a package and create a fresh config file/directory"
+    usage = "PACKAGE_NAME [CONFIG_FILE] [VAR=VALUE]"
+
+    description = """\
+    Note: this is an experimental command, and it will probably change
+    in several ways by the next release.
+
+    make-config is part of a two-phase installation process (the
+    second phase is setup-app).  make-config installs the package
+    (using easy_install) and asks it to create a bare configuration
+    file or directory (possibly filling in defaults from the extra
+    variables you give).
+    """
+
+    parser = AbstractInstallCommand.standard_parser(
+        simulate=True, quiet=True, no_interactive=True)
+    parser.add_option('--info',
+                      action="store_true",
+                      dest="show_info",
+                      help="Show information on the package (after installing it), but do not write a config.")
+    parser.add_option('--name',
+                      action='store',
+                      dest='ep_name',
+                      help='The name of the application contained in the distribution (default "main")')
+    parser.add_option('--entry-group',
+                      action='store',
+                      dest='ep_group',
+                      default='paste.app_factory',
+                      help='The entry point group to install (i.e., the kind of application; default paste.app_factory')
+    parser.add_option('--edit',
+                      action='store_true',
+                      dest='edit',
+                      help='Edit the configuration file after generating it (using $EDITOR)')
+    parser.add_option('--setup',
+                      action='store_true',
+                      dest='run_setup',
+                      help='Run setup-app immediately after generating (and possibly editing) the configuration file')
+
+    def command(self):
+        self.requirement = self.args[0]
+        if '#' in self.requirement:
+            if self.options.ep_name is not None:
+                raise BadCommand(
+                    "You may not give both --name and a requirement with "
+                    "#name")
+            self.requirement, self.options.ep_name = self.requirement.split('#', 1)
+        if not self.options.ep_name:
+            self.options.ep_name = 'main'
+        self.distro = self.get_distribution(self.requirement)
+        self.installer = self.get_installer(
+            self.distro, self.options.ep_group, self.options.ep_name)
+        if self.options.show_info:
+            if len(self.args) > 1:
+                raise BadCommand(
+                    "With --info you can only give one argument")
+            return self.show_info()
+        if len(self.args) < 2:
+            # See if sysconfig can give us a default filename
+            options = filter(None, self.call_sysconfig_functions(
+                'default_config_filename', self.installer))
+            if not options:
+                raise BadCommand(
+                    "You must give a configuration filename")
+            self.config_file = options[0]
+        else:
+            self.config_file = self.args[1]
+        self.check_config_file()
+        self.project_name = self.distro.project_name
+        self.vars = self.sysconfig_install_vars(self.installer)
+        self.vars.update(self.parse_vars(self.args[2:]))
+        self.vars['project_name'] = self.project_name
+        self.vars['requirement'] = self.requirement
+        self.vars['ep_name'] = self.options.ep_name
+        self.vars['ep_group'] = self.options.ep_group
+        self.vars.setdefault('app_name', self.project_name.lower())
+        self.vars.setdefault('app_instance_uuid', uuid.uuid4())
+        self.vars.setdefault('app_instance_secret', secret.secret_string())
+        if self.verbose > 1:
+            print_vars = self.vars.items()
+            print_vars.sort()
+            print 'Variables for installation:'
+            for name, value in print_vars:
+                print '  %s: %r' % (name, value)
+        self.installer.write_config(self, self.config_file, self.vars)
+        edit_success = True
+        if self.options.edit:
+            edit_success = self.run_editor()
+        setup_configs = self.installer.editable_config_files(self.config_file)
+        # @@: We'll just assume the first file in the list is the one
+        # that works with setup-app...
+        setup_config = setup_configs[0]
+        if self.options.run_setup:
+            if not edit_success:
+                print 'Config-file editing was not successful.'
+                if self.ask('Run setup-app anyway?', default=False):
+                    self.run_setup(setup_config)
+            else:
+                self.run_setup(setup_config)
+        else:
+            filenames = self.installer.editable_config_files(self.config_file)
+            assert not isinstance(filenames, basestring), (
+                "editable_config_files returned a string, not a list")
+            if not filenames and filenames is not None:
+                print 'No config files need editing'
+            else:
+                print 'Now you should edit the config files'
+                if filenames:
+                    for fn in filenames:
+                        print '  %s' % fn
+
+    def show_info(self):
+        text = self.installer.description(None)
+        print text
+
+    def check_config_file(self):
+        if self.installer.expect_config_directory is None:
+            return
+        fn = self.config_file
+        if self.installer.expect_config_directory:
+            if os.path.splitext(fn)[1]:
+                raise BadCommand(
+                    "The CONFIG_FILE argument %r looks like a filename, "
+                    "and a directory name is expected" % fn)
+        else:
+            if fn.endswith('/') or not os.path.splitext(fn):
+                raise BadCommand(
+                    "The CONFIG_FILE argument %r looks like a directory "
+                    "name and a filename is expected" % fn)
+
+    def run_setup(self, filename):
+        run_command(['setup-app', filename])
+
+    def run_editor(self):
+        filenames = self.installer.editable_config_files(self.config_file)
+        if filenames is None:
+            print 'Warning: the config file is not known (--edit ignored)'
+            return False
+        if not filenames:
+            print 'Warning: no config files need editing (--edit ignored)'
+            return True
+        if len(filenames) > 1:
+            print 'Warning: there is more than one editable config file (--edit ignored)'
+            return False
+        if not os.environ.get('EDITOR'):
+            print 'Error: you must set $EDITOR if using --edit'
+            return False
+        if self.verbose:
+            print '%s %s' % (os.environ['EDITOR'], filenames[0])
+        retval = os.system('$EDITOR %s' % filenames[0])
+        if retval:
+            print 'Warning: editor %s returned with error code %i' % (
+                os.environ['EDITOR'], retval)
+            return False
+        return True
+        
+class SetupCommand(AbstractInstallCommand):
+
+    default_verbosity = 1
+    max_args = 1
+    min_args = 1
+    summary = "Setup an application, given a config file"
+    usage = "CONFIG_FILE"
+
+    description = """\
+    Note: this is an experimental command, and it will probably change
+    in several ways by the next release.
+
+    Setup an application according to its configuration file.  This is
+    the second part of a two-phase web application installation
+    process (the first phase is prepare-app).  The setup process may
+    consist of things like creating directories and setting up
+    databases.
+    """
+
+    parser = AbstractInstallCommand.standard_parser(
+        simulate=True, quiet=True, interactive=True)
+    parser.add_option('--name',
+                      action='store',
+                      dest='section_name',
+                      default=None,
+                      help='The name of the section to set up (default: app:main)')
+
+    def command(self):
+        config_spec = self.args[0]
+        section = self.options.section_name
+        if section is None:
+            if '#' in config_spec:
+                config_spec, section = config_spec.split('#', 1)
+            else:
+                section = 'main'
+        if not ':' in section:
+            plain_section = section
+            section = 'app:'+section
+        else:
+            plain_section = section.split(':', 1)[0]
+        if not config_spec.startswith('config:'):
+            config_spec = 'config:' + config_spec
+        if plain_section != 'main':
+            config_spec += '#' + plain_section
+        config_file = config_spec[len('config:'):].split('#', 1)[0]
+        config_file = os.path.join(os.getcwd(), config_file)
+        self.logging_file_config(config_file)
+        conf = appconfig(config_spec, relative_to=os.getcwd())
+        ep_name = conf.context.entry_point_name
+        ep_group = conf.context.protocol
+        dist = conf.context.distribution
+        if dist is None:
+            raise BadCommand(
+                "The section %r is not the application (probably a filter).  You should add #section_name, where section_name is the section that configures your application" % plain_section)
+        installer = self.get_installer(dist, ep_group, ep_name)
+        installer.setup_config(
+            self, config_file, section, self.sysconfig_install_vars(installer))
+        self.call_sysconfig_functions(
+            'post_setup_hook', installer, config_file)
+        
+        
+class Installer(object):
+
+    """
+    Abstract base class for installers, and also a generic
+    installer that will run off config files in the .egg-info
+    directory of a distribution.
+
+    Packages that simply refer to this installer can provide a file
+    ``*.egg-info/paste_deploy_config.ini_tmpl`` that will be
+    interpreted by Cheetah.  They can also provide ``websetup``
+    modules with a ``setup_app(command, conf, vars)`` (or the
+    now-deprecated ``setup_config(command, filename, section, vars)``)
+    function, that will be called.
+
+    In the future other functions or configuration files may be
+    called.
+    """
+
+    # If this is true, then try to detect filename-looking config_file
+    # values, and reject them.  Conversely, if false try to detect
+    # directory-looking values and reject them.  None means don't
+    # check.
+    expect_config_directory = False
+    
+    # Set this to give a default config filename when none is
+    # specified:
+    default_config_filename = None
+
+    # Set this to true to use Cheetah to fill your templates, or false
+    # to not do so:
+    use_cheetah = True
+
+    def __init__(self, dist, ep_group, ep_name):
+        self.dist = dist
+        self.ep_group = ep_group
+        self.ep_name = ep_name
+
+    def description(self, config):
+        return 'An application'
+        
+    def write_config(self, command, filename, vars):
+        """
+        Writes the content to the filename (directory or single file).
+        You should use the ``command`` object, which respects things
+        like simulation and interactive.  ``vars`` is a dictionary
+        of user-provided variables.
+        """
+        command.ensure_file(filename, self.config_content(command, vars))
+
+    def editable_config_files(self, filename):
+        """
+        Return a list of filenames; this is primarily used when the
+        filename is treated as a directory and several configuration
+        files are created.  The default implementation returns the
+        file itself.  Return None if you don't know what files should
+        be edited on installation.
+        """
+        if not self.expect_config_directory:
+            return [filename]
+        else:
+            return None
+
+    def config_content(self, command, vars):
+        """
+        Called by ``self.write_config``, this returns the text content
+        for the config file, given the provided variables.
+
+        The default implementation reads
+        ``Package.egg-info/paste_deploy_config.ini_tmpl`` and fills it
+        with the variables.
+        """
+        global Cheetah
+        meta_name = 'paste_deploy_config.ini_tmpl'
+        if not self.dist.has_metadata(meta_name):
+            if command.verbose:
+                print 'No %s found' % meta_name
+            return self.simple_config(vars)
+        return self.template_renderer(
+            self.dist.get_metadata(meta_name), vars, filename=meta_name)
+
+    def template_renderer(self, content, vars, filename=None):
+        """
+        Subclasses may override this to provide different template
+        substitution (e.g., use a different template engine).
+        """
+        if self.use_cheetah:
+            import Cheetah.Template
+            tmpl = Cheetah.Template.Template(content,
+                                             searchList=[vars])
+            return copydir.careful_sub(
+                tmpl, vars, filename)
+        else:
+            tmpl = string.Template(content)
+            return tmpl.substitute(vars)
+
+    def simple_config(self, vars):
+        """
+        Return a very simple configuration file for this application.
+        """
+        if self.ep_name != 'main':
+            ep_name = '#'+self.ep_name
+        else:
+            ep_name = ''
+        return ('[app:main]\n'
+                'use = egg:%s%s\n'
+                % (self.dist.project_name, ep_name))
+
+    def setup_config(self, command, filename, section, vars):
+        """
+        Called to setup an application, given its configuration
+        file/directory.
+
+        The default implementation calls
+        ``package.websetup.setup_config(command, filename, section,
+        vars)`` or ``package.websetup.setup_app(command, config,
+        vars)``
+
+        With ``setup_app`` the ``config`` object is a dictionary with
+        the extra attributes ``global_conf``, ``local_conf`` and
+        ``filename``
+        """
+        modules = [
+            line.strip()
+            for line in self.dist.get_metadata_lines('top_level.txt')
+            if line.strip() and not line.strip().startswith('#')]
+        if not modules:
+            print 'No modules are listed in top_level.txt'
+            print 'Try running python setup.py egg_info to regenerate that file'
+        for mod_name in modules:
+            mod_name = mod_name + '.websetup'
+            mod = import_string.try_import_module(mod_name)
+            if mod is None:
+                continue
+            if command.verbose:
+                print 'Running setup_config() from %s' % mod_name
+            if hasattr(mod, 'setup_app'):
+                self._call_setup_app(
+                    mod.setup_app, command, filename, section, vars)
+            elif hasattr(mod, 'setup_config'):
+                mod.setup_config(command, filename, section, vars)
+            else:
+                print 'No setup_app() or setup_config() function in %s (%s)' % (
+                    mod.__name__, mod.__file__)
+
+    def _call_setup_app(self, func, command, filename, section, vars):
+        filename = os.path.abspath(filename)
+        if ':' in section:
+            section = section.split(':', 1)[1]
+        conf = 'config:%s#%s' % (filename, section)
+        conf = appconfig(conf)
+        conf.filename = filename
+        func(command, conf, vars)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/bool_optparse.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/bool_optparse.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/bool_optparse.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,60 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+A subclass of ``optparse.OptionParser`` that allows boolean long
+options (like ``--verbose``) to also take arguments (like
+``--verbose=true``).  Arguments *must* use ``=``.
+"""
+
+import optparse
+try:
+    _ = optparse._
+except AttributeError:
+    from gettext import gettext as _
+
+class BoolOptionParser(optparse.OptionParser):
+
+    def _process_long_opt(self, rargs, values):
+        arg = rargs.pop(0)
+
+        # Value explicitly attached to arg?  Pretend it's the next
+        # argument.
+        if "=" in arg:
+            (opt, next_arg) = arg.split("=", 1)
+            rargs.insert(0, next_arg)
+            had_explicit_value = True
+        else:
+            opt = arg
+            had_explicit_value = False
+
+        opt = self._match_long_opt(opt)
+        option = self._long_opt[opt]
+        if option.takes_value():
+            nargs = option.nargs
+            if len(rargs) < nargs:
+                if nargs == 1:
+                    self.error(_("%s option requires an argument") % opt)
+                else:
+                    self.error(_("%s option requires %d arguments")
+                               % (opt, nargs))
+            elif nargs == 1:
+                value = rargs.pop(0)
+            else:
+                value = tuple(rargs[0:nargs])
+                del rargs[0:nargs]
+
+        elif had_explicit_value:
+            value = rargs[0].lower().strip()
+            del rargs[0:1]
+            if value in ('true', 'yes', 'on', '1', 'y', 't'):
+                value = None
+            elif value in ('false', 'no', 'off', '0', 'n', 'f'):
+                # Don't process
+                return
+            else:
+                self.error(_('%s option takes a boolean value only (true/false)') % opt)
+
+        else:
+            value = None
+
+        option.process(opt, value, values, self)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cgi_server.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cgi_server.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cgi_server.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,71 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import sys
+
+## FIXME: this should be deprecated in favor of wsgiref
+
+def paste_run_cgi(wsgi_app, global_conf):
+    run_with_cgi(wsgi_app)
+
+stdout = sys.__stdout__
+
+# Taken from the WSGI spec:
+
+def run_with_cgi(application):
+
+    environ = dict(os.environ.items())
+    environ['wsgi.input']        = sys.stdin
+    environ['wsgi.errors']       = sys.stderr
+    environ['wsgi.version']      = (1,0)
+    environ['wsgi.multithread']  = False
+    environ['wsgi.multiprocess'] = True
+    environ['wsgi.run_once']    = True
+
+    if environ.get('HTTPS','off') in ('on','1'):
+        environ['wsgi.url_scheme'] = 'https'
+    else:
+        environ['wsgi.url_scheme'] = 'http'
+
+    headers_set = []
+    headers_sent = []
+
+    def write(data):
+        if not headers_set:
+             raise AssertionError("write() before start_response()")
+
+        elif not headers_sent:
+             # Before the first output, send the stored headers
+             status, response_headers = headers_sent[:] = headers_set
+             stdout.write('Status: %s\r\n' % status)
+             for header in response_headers:
+                 stdout.write('%s: %s\r\n' % header)
+             stdout.write('\r\n')
+
+        stdout.write(data)
+        stdout.flush()
+
+    def start_response(status,response_headers,exc_info=None):
+        if exc_info:
+            try:
+                if headers_sent:
+                    # Re-raise original exception if headers sent
+                    raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                exc_info = None     # avoid dangling circular ref
+        elif headers_set:
+            raise AssertionError("Headers already set!")
+            
+        headers_set[:] = [status,response_headers]
+        return write
+
+    result = application(environ, start_response)
+    try:
+        for data in result:
+            if data:    # don't send headers until body appears
+                write(data)
+        if not headers_sent:
+            write('')   # send headers now if body was empty
+    finally:
+        if hasattr(result,'close'):
+            result.close()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/checkperms.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/checkperms.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/checkperms.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,441 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+This is a module to check the filesystem for the presence and
+permissions of certain files.  It can also be used to correct the
+permissions (but not existance) of those files.
+
+Currently only supports Posix systems (with Posixy permissions).
+Permission stuff can probably be stubbed out later.
+"""
+import os
+
+def read_perm_spec(spec):
+    """
+    Reads a spec like 'rw-r--r--' into a octal number suitable for
+    chmod.  That is characters in groups of three -- first group is
+    user, second for group, third for other (all other people).  The
+    characters are r (read), w (write), and x (executable), though the
+    executable can also be s (sticky).  Files in sticky directories
+    get the directories permission setting.
+
+    Examples::
+
+      >>> print oct(read_perm_spec('rw-r--r--'))
+      0644
+      >>> print oct(read_perm_spec('rw-rwsr--'))
+      02664
+      >>> print oct(read_perm_spec('r-xr--r--'))
+      0544
+      >>> print oct(read_perm_spec('r--------'))
+      0400
+    """
+    total_mask = 0
+    # suid/sgid modes give this mask in user, group, other mode:
+    set_bits = (04000, 02000, 0)
+    pieces = (spec[0:3], spec[3:6], spec[6:9])
+    for i, (mode, set_bit) in enumerate(zip(pieces, set_bits)):
+        mask = 0
+        read, write, exe = list(mode)
+        if read == 'r':
+            mask = mask | 4
+        elif read != '-':
+            raise ValueError, (
+                "Character %r unexpected (should be '-' or 'r')"
+                % read)
+        if write == 'w':
+            mask = mask | 2
+        elif write != '-':
+            raise ValueError, (
+                "Character %r unexpected (should be '-' or 'w')"
+                % write)
+        if exe == 'x':
+            mask = mask | 1
+        elif exe not in ('s', '-'):
+            raise ValueError, (
+                "Character %r unexpected (should be '-', 'x', or 's')"
+                % exe)
+        if exe == 's' and i == 2:
+            raise ValueError, (
+                "The 'other' executable setting cannot be suid/sgid ('s')")
+        mask = mask << ((2-i)*3)
+        if exe == 's':
+            mask = mask | set_bit
+        total_mask = total_mask | mask
+    return total_mask
+
+modes = [
+    (04000, 'setuid bit',
+     'setuid bit: make contents owned by directory owner'),
+    (02000, 'setgid bit',
+     'setgid bit: make contents inherit permissions from directory'),
+    (01000, 'sticky bit',
+     'sticky bit: append-only directory'),
+    (00400, 'read by owner', 'read by owner'),
+    (00200, 'write by owner', 'write by owner'),
+    (00100, 'execute by owner', 'owner can search directory'),
+    (00040, 'allow read by group members',
+     'allow read by group members',),
+    (00020, 'allow write by group members',
+     'allow write by group members'),
+    (00010, 'execute by group members',
+     'group members can search directory'),
+    (00004, 'read by others', 'read by others'),
+    (00002, 'write by others', 'write by others'),
+    (00001, 'execution by others', 'others can search directory'),
+    ]
+
+exe_bits = [0100, 0010, 0001]
+exe_mask = 0111
+full_mask = 07777
+
+def mode_diff(filename, mode, **kw):
+    """
+    Returns the differences calculated using ``calc_mode_diff``
+    """
+    cur_mode = os.stat(filename).st_mode
+    return calc_mode_diff(cur_mode, mode, **kw)
+
+def calc_mode_diff(cur_mode, mode, keep_exe=True,
+                   not_set='not set: ',
+                   set='set: '):
+    """
+    Gives the difference between the actual mode of the file and the
+    given mode.  If ``keep_exe`` is true, then if the mode doesn't
+    include any executable information the executable information will
+    simply be ignored.  High bits are also always ignored (except
+    suid/sgid and sticky bit).
+
+    Returns a list of differences (empty list if no differences)
+    """
+    for exe_bit in exe_bits:
+        if mode & exe_bit:
+            keep_exe = False
+    diffs = []
+    isdir = os.path.isdir(filename)
+    for bit, file_desc, dir_desc in modes:
+        if keep_exe and bit in exe_bits:
+            continue
+        if isdir:
+            desc = dir_desc
+        else:
+            desc = file_desc
+        if (mode & bit) and not (cur_mode & bit):
+            diffs.append(not_set + desc)
+        if not (mode & bit) and (cur_mode & bit):
+            diffs.append(set + desc)
+    return diffs
+
+def calc_set_mode(cur_mode, mode, keep_exe=True):
+    """
+    Calculates the new mode given the current node ``cur_mode`` and
+    the mode spec ``mode`` and if ``keep_exe`` is true then also keep
+    the executable bits in ``cur_mode`` if ``mode`` has no executable
+    bits in it.  Return the new mode.
+
+    Examples::
+
+      >>> print oct(calc_set_mode(0775, 0644))
+      0755
+      >>> print oct(calc_set_mode(0775, 0744))
+      0744
+      >>> print oct(calc_set_mode(010600, 0644))
+      010644
+      >>> print oct(calc_set_mode(0775, 0644, False))
+      0644
+    """
+    for exe_bit in exe_bits:
+        if mode & exe_bit:
+            keep_exe = False
+    # This zeros-out full_mask parts of the current mode:
+    keep_parts = (cur_mode | full_mask) ^ full_mask
+    if keep_exe:
+        keep_parts = keep_parts | (cur_mode & exe_mask)
+    new_mode = keep_parts | mode
+    return new_mode
+
+def set_mode(filename, mode, **kw):
+    """
+    Sets the mode on ``filename`` using ``calc_set_mode``
+    """
+    cur_mode = os.stat(filename).st_mode
+    new_mode = calc_set_mode(cur_mode, mode, **kw)
+    os.chmod(filename, new_mode)
+
+def calc_ownership_spec(spec):
+    """
+    Calculates what a string spec means, returning (uid, username,
+    gid, groupname), where there can be None values meaning no
+    preference.
+
+    The spec is a string like ``owner:group``.  It may use numbers
+    instead of user/group names.  It may leave out ``:group``.  It may
+    use '-' to mean any-user/any-group.
+
+    """
+    import grp
+    import pwd
+    user = group = None
+    uid = gid = None
+    if ':' in spec:
+        user_spec, group_spec = spec.split(':', 1)
+    else:
+        user_spec, group_spec = spec, '-'
+    if user_spec == '-':
+        user_spec = '0'
+    if group_spec == '-':
+        group_spec = '0'
+    try:
+        uid = int(user_spec)
+    except ValueError:
+        uid = pwd.getpwnam(user_spec)
+        user = user_spec
+    else:
+        if not uid:
+            uid = user = None
+        else:
+            user = pwd.getpwuid(uid).pw_name
+    try:
+        gid = int(group_spec)
+    except ValueError:
+        gid = grp.getgrnam(group_spec)
+        group = group_spec
+    else:
+        if not gid:
+            gid = group = None
+        else:
+            group = grp.getgrgid(gid).gr_name
+    return (uid, user, gid, group)
+
+def ownership_diff(filename, spec):
+    """
+    Return a list of differences between the ownership of ``filename``
+    and the spec given.
+    """
+    import grp
+    import pwd
+    diffs = []
+    uid, user, gid, group = calc_ownership_spec(spec)
+    st = os.stat(filename)
+    if uid and uid != st.st_uid:
+        diffs.append('owned by %s (should be %s)' %
+                     (pwd.getpwuid(st.st_uid).pw_name, user))
+    if gid and gid != st.st_gid:
+        diffs.append('group %s (should be %s)' %
+                     (grp.getgrgid(st.st_gid).gr_name, group))
+    return diffs
+
+def set_ownership(filename, spec):
+    """
+    Set the ownership of ``filename`` given the spec.
+    """
+    uid, user, gid, group = calc_ownership_spec(spec)
+    st = os.stat(filename)
+    if not uid:
+        uid = st.st_uid
+    if not gid:
+        gid = st.st_gid
+    os.chmod(filename, uid, gid)
+
+class PermissionSpec(object):
+    """
+    Represents a set of specifications for permissions.
+
+    Typically reads from a file that looks like this::
+
+      rwxrwxrwx user:group filename
+
+    If the filename ends in /, then it expected to be a directory, and
+    the directory is made executable automatically, and the contents
+    of the directory are given the same permission (recursively).  By
+    default the executable bit on files is left as-is, unless the
+    permissions specifically say it should be on in some way.
+
+    You can use 'nomodify filename' for permissions to say that any
+    permission is okay, and permissions should not be changed.
+
+    Use 'noexist filename' to say that a specific file should not
+    exist.
+
+    Use 'symlink filename symlinked_to' to assert a symlink destination
+
+    The entire file is read, and most specific rules are used for each
+    file (i.e., a rule for a subdirectory overrides the rule for a
+    superdirectory).  Order does not matter.
+    """
+
+    def __init__(self):
+        self.paths = {}
+
+    def parsefile(self, filename):
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+        self.parselines(lines, filename=filename)
+
+    commands = {}
+
+    def parselines(self, lines, filename=None):
+        for lineindex, line in enumerate(lines):
+            line = line.strip()
+            if not line or line.startswith('#'):
+                continue
+            parts = line.split()
+            command = parts[0]
+            if command in self.commands:
+                cmd = self.commands[command](*parts[1:])
+            else:
+                cmd = self.commands['*'](*parts)
+            self.paths[cmd.path] = cmd
+
+    def check(self):
+        action = _Check(self)
+        self.traverse(action)
+
+    def fix(self):
+        action = _Fixer(self)
+        self.traverse(action)
+
+    def traverse(self, action):
+        paths = self.paths_sorted()
+        checked = {}
+        for path, checker in list(paths)[::-1]:
+            self.check_tree(action, path, paths, checked)
+        for path, checker in paths:
+            if path not in checked:
+                action.noexists(path, checker)
+
+    def traverse_tree(self, action, path, paths, checked):
+        if path in checked:
+            return
+        self.traverse_path(action, path, paths, checked)
+        if os.path.isdir(path):
+            for fn in os.listdir(path):
+                fn = os.path.join(path, fn)
+                self.traverse_tree(action, fn, paths, checked)
+
+    def traverse_path(self, action, path, paths, checked):
+        checked[path] = None
+        for check_path, checker in paths:
+            if path.startswith(check_path):
+                action.check(check_path, checker)
+                if not checker.inherit:
+                    break 
+
+    def paths_sorted(self):
+        paths = self.paths.items()
+        paths.sort(lambda a, b: -cmp(len(a[0]), len(b[0])))
+                  
+class _Rule(object):
+    class __metaclass__(type):
+        def __new__(meta, class_name, bases, d):
+            cls = type.__new__(meta, class_name, bases, d)
+            PermissionSpec.commands[cls.__name__] = cls
+            return cls
+
+    inherit = False
+    def noexists(self):
+        return ['Path %s does not exist' % path]
+
+class _NoModify(_Rule):
+
+    name = 'nomodify'
+                
+    def __init__(self, path):
+        self.path = path
+
+    def fix(self, path):
+        pass
+
+class _NoExist(_Rule):
+
+    name = 'noexist'
+
+    def __init__(self, path):
+        self.path = path
+
+    def check(self, path):
+        return ['Path %s should not exist' % path]
+
+    def noexists(self, path):
+        return []
+
+    def fix(self, path):
+        # @@: Should delete?
+        pass
+
+class _SymLink(_Rule):
+
+    name = 'symlink'
+    inherit = True
+
+    def __init__(self, path, dest):
+        self.path = path
+        self.dest = dest
+
+    def check(self, path):
+        assert path == self.path, (
+            "_Symlink should only be passed specific path %s (not %s)"
+            % (self.path, path))
+        try:
+            link = os.path.readlink(path)
+        except OSError:
+            if e.errno != 22:
+                raise
+            return ['Path %s is not a symlink (should point to %s)'
+                    % (path, self.dest)]
+        if link != self.dest:
+            return ['Path %s should symlink to %s, not %s'
+                    % (path, self.dest, link)]
+        return []
+
+    def fix(self, path):
+        assert path == self.path, (
+            "_Symlink should only be passed specific path %s (not %s)"
+            % (self.path, path))
+        if not os.path.exists(path):
+            os.symlink(path, self.dest)
+        else:
+            # @@: This should correct the symlink or something:
+            print 'Not symlinking %s' % path
+
+class _Permission(_Rule):
+
+    name = '*'
+
+    def __init__(self, perm, owner, dir):
+        self.perm_spec = read_perm_spec(perm)
+        self.owner = owner
+        self.dir = dir
+
+    def check(self, path):
+        return mode_diff(path, self.perm_spec)
+
+    def fix(self, path):
+        set_mode(path, self.perm_spec)
+
+class _Strategy(object):
+
+    def __init__(self, spec):
+        self.spec = spec
+
+class _Check(_Strategy):
+    
+    def noexists(self, path, checker):
+        checker.noexists(path)
+
+    def check(self, path, checker):
+        checker.check(path)
+
+class _Fixer(_Strategy):
+
+    def noexists(self, path, checker):
+        pass
+
+    def check(self, path, checker):
+        checker.fix(path)
+
+if __name__ == '__main__':
+    import doctest
+    doctest.testmod()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cherrypy_server.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cherrypy_server.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/cherrypy_server.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,101 @@
+"""
+Entry point for CherryPy's WSGI server
+"""
+import paste.script.wsgiserver as wsgiserver
+
+def cpwsgi_server(app, global_conf=None, host='127.0.0.1', port=None,
+                  ssl_pem=None, protocol_version=None, numthreads=None,
+                  server_name=None, max=None, request_queue_size=None,
+                  timeout=None):
+    """
+    Serves the specified WSGI app via CherryPyWSGIServer.
+
+    ``app``
+
+        The WSGI 'application callable'; multiple WSGI applications
+        may be passed as (script_name, callable) pairs.
+
+    ``host``
+
+        This is the ipaddress to bind to (or a hostname if your
+        nameserver is properly configured).  This defaults to
+        127.0.0.1, which is not a public interface.
+
+    ``port``
+
+        The port to run on, defaults to 8080 for HTTP, or 4443 for
+        HTTPS. This can be a string or an integer value.
+
+    ``ssl_pem``
+
+        This an optional SSL certificate file (via OpenSSL) You can
+        generate a self-signed test PEM certificate file as follows:
+
+            $ openssl genrsa 1024 > host.key
+            $ chmod 400 host.key
+            $ openssl req -new -x509 -nodes -sha1 -days 365  \\
+                          -key host.key > host.cert
+            $ cat host.cert host.key > host.pem
+            $ chmod 400 host.pem
+
+    ``protocol_version``
+
+        The protocol used by the server, by default ``HTTP/1.1``.
+
+    ``numthreads``
+
+        The number of worker threads to create.
+
+    ``server_name``
+
+        The string to set for WSGI's SERVER_NAME environ entry.
+
+    ``max``
+
+        The maximum number of queued requests. (defaults to -1 = no
+        limit).
+
+    ``request_queue_size``
+
+        The 'backlog' argument to socket.listen(); specifies the
+        maximum number of queued connections.
+
+    ``timeout``
+
+        The timeout in seconds for accepted connections.
+    """
+    is_ssl = False
+    if ssl_pem:
+        port = port or 4443
+        is_ssl = True
+
+    if not port:
+        if ':' in host:
+            host, port = host.split(':', 1)
+        else:
+            port = 8080
+    bind_addr = (host, int(port))
+
+    kwargs = {}
+    for var_name in ('numthreads', 'max', 'request_queue_size', 'timeout'):
+        var = locals()[var_name]
+        if var is not None:
+            kwargs[var_name] = int(var)
+
+    server = wsgiserver.CherryPyWSGIServer(bind_addr, app,
+                                           server_name=server_name, **kwargs)
+    server.ssl_certificate = server.ssl_private_key = ssl_pem
+    if protocol_version:
+        server.protocol = protocol_version
+
+    try:
+        protocol = is_ssl and 'https' or 'http'
+        if host == '0.0.0.0':
+            print 'serving on 0.0.0.0:%s view at %s://127.0.0.1:%s' % \
+                (port, protocol, port)
+        else:
+            print "serving on %s://%s:%s" % (protocol, host, port)
+        server.start()
+    except (KeyboardInterrupt, SystemExit):
+        server.stop()
+    return server

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/command.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,787 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import pkg_resources
+import sys
+import optparse
+import bool_optparse
+import os
+import re
+import textwrap
+import pluginlib
+import ConfigParser
+import getpass
+try:
+    import subprocess
+except ImportError:
+    from paste.script.util import subprocess24 as subprocess
+difflib = None
+
+if sys.version_info >= (2, 6):
+    from logging.config import fileConfig
+else:
+    # Use our custom fileConfig -- 2.5.1's with a custom Formatter class
+    # and less strict whitespace (which were incorporated into 2.6's)
+    from paste.script.util.logging_config import fileConfig
+
+class BadCommand(Exception):
+
+    def __init__(self, message, exit_code=2):
+        self.message = message
+        self.exit_code = exit_code
+        Exception.__init__(self, message)
+
+class NoDefault(object):
+    pass
+
+dist = pkg_resources.get_distribution('PasteScript')
+
+python_version = sys.version.splitlines()[0].strip()
+
+parser = optparse.OptionParser(add_help_option=False,
+                               version='%s from %s (python %s)'
+                               % (dist, dist.location, python_version),
+                               usage='%prog [paster_options] COMMAND [command_options]')
+
+parser.add_option(
+    '--plugin',
+    action='append',
+    dest='plugins',
+    help="Add a plugin to the list of commands (plugins are Egg specs; will also require() the Egg)")
+parser.add_option(
+    '-h', '--help',
+    action='store_true',
+    dest='do_help',
+    help="Show this help message")
+parser.disable_interspersed_args()
+
+# @@: Add an option to run this in another Python interpreter
+
+system_plugins = []
+
+def run(args=None):
+    if (not args and
+        len(sys.argv) >= 2
+        and os.environ.get('_') and sys.argv[0] != os.environ['_']
+        and os.environ['_'] == sys.argv[1]):
+        # probably it's an exe execution
+        args = ['exe', os.environ['_']] + sys.argv[2:]
+    if args is None:
+        args = sys.argv[1:]
+    options, args = parser.parse_args(args)
+    options.base_parser = parser
+    system_plugins.extend(options.plugins or [])
+    commands = get_commands()
+    if options.do_help:
+        args = ['help'] + args
+    if not args:
+        print 'Usage: %s COMMAND' % sys.argv[0]
+        args = ['help']
+    command_name = args[0]
+    if command_name not in commands:
+        command = NotFoundCommand
+    else:
+        command = commands[command_name].load()
+    invoke(command, command_name, options, args[1:])
+
+def parse_exe_file(config):
+    import shlex
+    p = ConfigParser.RawConfigParser()
+    p.read([config])
+    command_name = 'exe'
+    options = []
+    if p.has_option('exe', 'command'):
+        command_name = p.get('exe', 'command')
+    if p.has_option('exe', 'options'):
+        options = shlex.split(p.get('exe', 'options'))
+    if p.has_option('exe', 'sys.path'):
+        paths = shlex.split(p.get('exe', 'sys.path'))
+        paths = [os.path.abspath(os.path.join(os.path.dirname(config), p))
+                 for p in paths]
+        for path in paths:
+            pkg_resources.working_set.add_entry(path)
+            sys.path.insert(0, path)
+    args = [command_name, config] + options
+    return args
+
+def get_commands():
+    plugins = system_plugins[:]
+    egg_info_dir = pluginlib.find_egg_info_dir(os.getcwd())
+    if egg_info_dir:
+        plugins.append(os.path.splitext(os.path.basename(egg_info_dir))[0])
+        base_dir = os.path.dirname(egg_info_dir)
+        if base_dir not in sys.path:
+            sys.path.insert(0, base_dir)
+            pkg_resources.working_set.add_entry(base_dir)
+    plugins = pluginlib.resolve_plugins(plugins)
+    commands = pluginlib.load_commands_from_plugins(plugins)
+    commands.update(pluginlib.load_global_commands())
+    return commands
+
+def invoke(command, command_name, options, args):
+    try:
+        runner = command(command_name)
+        exit_code = runner.run(args)
+    except BadCommand, e:
+        print e.message
+        exit_code = e.exit_code
+    sys.exit(exit_code)
+
+
+class Command(object):
+
+    def __init__(self, name):
+        self.command_name = name
+
+    max_args = None
+    max_args_error = 'You must provide no more than %(max_args)s arguments'
+    min_args = None
+    min_args_error = 'You must provide at least %(min_args)s arguments'
+    required_args = None
+    # If this command takes a configuration file, set this to 1 or -1
+    # Then if invoked through #! the config file will be put into the positional
+    # arguments -- at the beginning with 1, at the end with -1
+    takes_config_file = None
+
+    # Grouped in help messages by this:
+    group_name = ''
+
+    required_args = ()
+    description = None
+    usage = ''
+    hidden = False
+    # This is the default verbosity level; --quiet subtracts,
+    # --verbose adds:
+    default_verbosity = 0
+    # This is the default interactive state:
+    default_interactive = 0
+    return_code = 0
+
+    BadCommand = BadCommand
+
+    # Must define:
+    #   parser
+    #   summary
+    #   command()
+
+    def run(self, args):
+        self.parse_args(args)
+        
+        # Setup defaults:
+        for name, default in [('verbose', 0),
+                              ('quiet', 0),
+                              ('interactive', False),
+                              ('overwrite', False)]:
+            if not hasattr(self.options, name):
+                setattr(self.options, name, default)
+        if getattr(self.options, 'simulate', False):
+            self.options.verbose = max(self.options.verbose, 1)
+        self.interactive = self.default_interactive
+        if getattr(self.options, 'interactive', False):
+            self.interactive += self.options.interactive
+        if getattr(self.options, 'no_interactive', False):
+            self.interactive = False
+        self.verbose = self.default_verbosity
+        self.verbose += self.options.verbose
+        self.verbose -= self.options.quiet
+        self.simulate = getattr(self.options, 'simulate', False)
+
+        # For #! situations:
+        if (os.environ.get('PASTE_CONFIG_FILE')
+            and self.takes_config_file is not None):
+            take = self.takes_config_file
+            filename = os.environ.get('PASTE_CONFIG_FILE')
+            if take == 1:
+                self.args.insert(0, filename)
+            elif take == -1:
+                self.args.append(filename)
+            else:
+                assert 0, (
+                    "Value takes_config_file must be None, 1, or -1 (not %r)"
+                    % take)
+
+        if (os.environ.get('PASTE_DEFAULT_QUIET')):
+            self.verbose = 0
+
+        # Validate:
+        if self.min_args is not None and len(self.args) < self.min_args:
+            raise BadCommand(
+                self.min_args_error % {'min_args': self.min_args,
+                                       'actual_args': len(self.args)})
+        if self.max_args is not None and len(self.args) > self.max_args:
+            raise BadCommand(
+                self.max_args_error % {'max_args': self.max_args,
+                                       'actual_args': len(self.args)})
+        for var_name, option_name in self.required_args:
+            if not getattr(self.options, var_name, None):
+                raise BadCommand(
+                    'You must provide the option %s' % option_name)
+        result = self.command()
+        if result is None:
+            return self.return_code
+        else:
+            return result
+
+    def parse_args(self, args):
+        if self.usage:
+            usage = ' '+self.usage
+        else:
+            usage = ''
+        self.parser.usage = "%%prog [options]%s\n%s" % (
+            usage, self.summary)
+        self.parser.prog = '%s %s' % (sys.argv[0], self.command_name)
+        if self.description:
+            desc = self.description
+            desc = textwrap.dedent(desc)
+            self.parser.description = desc
+        self.options, self.args = self.parser.parse_args(args)
+
+    ########################################
+    ## Utility methods
+    ########################################
+
+    def here(cls):
+        mod = sys.modules[cls.__module__]
+        return os.path.dirname(mod.__file__)
+
+    here = classmethod(here)
+
+    def ask(self, prompt, safe=False, default=True):
+        """
+        Prompt the user.  Default can be true, false, ``'careful'`` or
+        ``'none'``.  If ``'none'`` then the user must enter y/n.  If
+        ``'careful'`` then the user must enter yes/no (long form).
+
+        If the interactive option is over two (``-ii``) then ``safe``
+        will be used as a default.  This option should be the
+        do-nothing option.
+        """
+        # @@: Should careful be a separate argument?
+
+        if self.options.interactive >= 2:
+            default = safe
+        if default == 'careful':
+            prompt += ' [yes/no]?'
+        elif default == 'none':
+            prompt += ' [y/n]?'
+        elif default:
+            prompt += ' [Y/n]? '
+        else:
+            prompt += ' [y/N]? '
+        while 1:
+            response = raw_input(prompt).strip().lower()
+            if not response:
+                if default in ('careful', 'none'):
+                    print 'Please enter yes or no'
+                    continue
+                return default
+            if default == 'careful':
+                if response in ('yes', 'no'):
+                    return response == 'yes'
+                print 'Please enter "yes" or "no"'
+                continue
+            if response[0].lower() in ('y', 'n'):
+                return response[0].lower() == 'y'
+            print 'Y or N please'
+
+    def challenge(self, prompt, default=NoDefault, should_echo=True):
+        """
+        Prompt the user for a variable.
+        """
+        if default is not NoDefault:
+            prompt += ' [%r]' % default
+        prompt += ': '
+        while 1:
+            if should_echo:
+                prompt_method = raw_input
+            else:
+                prompt_method = getpass.getpass
+            response = prompt_method(prompt).strip()
+            if not response:
+                if default is not NoDefault:
+                    return default
+                else:
+                    continue
+            else:
+                return response
+        
+    def pad(self, s, length, dir='left'):
+        if len(s) >= length:
+            return s
+        if dir == 'left':
+            return s + ' '*(length-len(s))
+        else:
+            return ' '*(length-len(s)) + s
+
+    def standard_parser(cls, verbose=True,
+                        interactive=False,
+                        no_interactive=False,
+                        simulate=False,
+                        quiet=False,
+                        overwrite=False):
+        """
+        Create a standard ``OptionParser`` instance.
+        
+        Typically used like::
+
+            class MyCommand(Command):
+                parser = Command.standard_parser()
+
+        Subclasses may redefine ``standard_parser``, so use the
+        nearest superclass's class method.
+        """
+        parser = bool_optparse.BoolOptionParser()
+        if verbose:
+            parser.add_option('-v', '--verbose',
+                              action='count',
+                              dest='verbose',
+                              default=0)
+        if quiet:
+            parser.add_option('-q', '--quiet',
+                              action='count',
+                              dest='quiet',
+                              default=0)
+        if no_interactive:
+            parser.add_option('--no-interactive',
+                              action="count",
+                              dest="no_interactive",
+                              default=0)
+        if interactive:
+            parser.add_option('-i', '--interactive',
+                              action='count',
+                              dest='interactive',
+                              default=0)
+        if simulate:
+            parser.add_option('-n', '--simulate',
+                              action='store_true',
+                              dest='simulate',
+                              default=False)
+        if overwrite:
+            parser.add_option('-f', '--overwrite',
+                              dest="overwrite",
+                              action="store_true",
+                              help="Overwrite files (warnings will be emitted for non-matching files otherwise)")
+        return parser
+
+    standard_parser = classmethod(standard_parser)
+
+    def shorten(self, fn, *paths):
+        """
+        Return a shorted form of the filename (relative to the current
+        directory), typically for displaying in messages.  If
+        ``*paths`` are present, then use os.path.join to create the
+        full filename before shortening.
+        """
+        if paths:
+            fn = os.path.join(fn, *paths)
+        if fn.startswith(os.getcwd()):
+            return fn[len(os.getcwd()):].lstrip(os.path.sep)
+        else:
+            return fn
+
+    def ensure_dir(self, dir, svn_add=True):
+        """
+        Ensure that the directory exists, creating it if necessary.
+        Respects verbosity and simulation.
+
+        Adds directory to subversion if ``.svn/`` directory exists in
+        parent, and directory was created.
+        """
+        dir = dir.rstrip(os.sep)
+        if not dir:
+            # we either reached the parent-most directory, or we got
+            # a relative directory
+            # @@: Should we make sure we resolve relative directories
+            # first?  Though presumably the current directory always
+            # exists.
+            return
+        if not os.path.exists(dir):
+            self.ensure_dir(os.path.dirname(dir))
+            if self.verbose:
+                print 'Creating %s' % self.shorten(dir)
+            if not self.simulate:
+                os.mkdir(dir)
+            if (svn_add and
+                os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))):
+                self.svn_command('add', dir)
+        else:
+            if self.verbose > 1:
+                print "Directory already exists: %s" % self.shorten(dir)
+
+    def ensure_file(self, filename, content, svn_add=True):
+        """
+        Ensure a file named ``filename`` exists with the given
+        content.  If ``--interactive`` has been enabled, this will ask
+        the user what to do if a file exists with different content.
+        """
+        global difflib
+        assert content is not None, (
+            "You cannot pass a content of None")
+        self.ensure_dir(os.path.dirname(filename), svn_add=svn_add)
+        if not os.path.exists(filename):
+            if self.verbose:
+                print 'Creating %s' % filename
+            if not self.simulate:
+                f = open(filename, 'wb')
+                f.write(content)
+                f.close()
+            if svn_add and os.path.exists(os.path.join(os.path.dirname(filename), '.svn')):
+                self.svn_command('add', filename,
+                                 warn_returncode=True)
+            return
+        f = open(filename, 'rb')
+        old_content = f.read()
+        f.close()
+        if content == old_content:
+            if self.verbose > 1:
+                print 'File %s matches expected content' % filename
+            return
+        if not self.options.overwrite:
+            print 'Warning: file %s does not match expected content' % filename
+            if difflib is None:
+                import difflib
+            diff = difflib.context_diff(
+                content.splitlines(),
+                old_content.splitlines(),
+                'expected ' + filename,
+                filename)
+            print '\n'.join(diff)
+            if self.interactive:
+                while 1:
+                    s = raw_input(
+                        'Overwrite file with new content? [y/N] ').strip().lower()
+                    if not s:
+                        s = 'n'
+                    if s.startswith('y'):
+                        break
+                    if s.startswith('n'):
+                        return
+                    print 'Unknown response; Y or N please'
+            else:
+                return
+                    
+        if self.verbose:
+            print 'Overwriting %s with new content' % filename
+        if not self.simulate:
+            f = open(filename, 'wb')
+            f.write(content)
+            f.close()
+
+    def insert_into_file(self, filename, marker_name, text,
+                         indent=False):
+        """
+        Inserts ``text`` into the file, right after the given marker.
+        Markers look like: ``-*- <marker_name>[:]? -*-``, and the text
+        will go on the immediately following line.
+
+        Raises ``ValueError`` if the marker is not found.
+
+        If ``indent`` is true, then the text will be indented at the
+        same level as the marker.
+        """
+        if not text.endswith('\n'):
+            raise ValueError(
+                "The text must end with a newline: %r" % text)
+        if not os.path.exists(filename) and self.simulate:
+            # If we are doing a simulation, it's expected that some
+            # files won't exist...
+            if self.verbose:
+                print 'Would (if not simulating) insert text into %s' % (
+                    self.shorten(filename))
+            return
+                
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+        regex = re.compile(r'-\*-\s+%s:?\s+-\*-' % re.escape(marker_name),
+                           re.I)
+        for i in range(len(lines)):
+            if regex.search(lines[i]):
+                # Found it!
+                if (lines[i:] and len(lines[i:]) > 1 and
+                    ''.join(lines[i+1:]).strip().startswith(text.strip())):
+                    # Already have it!
+                    print 'Warning: line already found in %s (not inserting' % filename
+                    print '  %s' % lines[i]
+                    return
+                
+                if indent:
+                    text = text.lstrip()
+                    match = re.search(r'^[ \t]*', lines[i])
+                    text = match.group(0) + text
+                lines[i+1:i+1] = [text]
+                break
+        else:
+            errstr = (
+                "Marker '-*- %s -*-' not found in %s"
+                % (marker_name, filename))
+            if 1 or self.simulate: # @@: being permissive right now
+                print 'Warning: %s' % errstr
+            else:
+                raise ValueError(errstr)
+        if self.verbose:
+            print 'Updating %s' % self.shorten(filename)
+        if not self.simulate:
+            f = open(filename, 'w')
+            f.write(''.join(lines))
+            f.close()
+
+    def run_command(self, cmd, *args, **kw):
+        """
+        Runs the command, respecting verbosity and simulation.
+        Returns stdout, or None if simulating.
+        
+        Keyword arguments:
+        
+        cwd: 
+            the current working directory to run the command in
+        capture_stderr: 
+            if true, then both stdout and stderr will be returned
+        expect_returncode: 
+            if true, then don't fail if the return code is not 0
+        force_no_simulate:
+            if true, run the command even if --simulate
+        """
+        cmd = self.quote_first_command_arg(cmd)
+        cwd = popdefault(kw, 'cwd', os.getcwd())
+        capture_stderr = popdefault(kw, 'capture_stderr', False)
+        expect_returncode = popdefault(kw, 'expect_returncode', False)
+        force = popdefault(kw, 'force_no_simulate', False)
+        warn_returncode = popdefault(kw, 'warn_returncode', False)
+        if warn_returncode:
+            expect_returncode = True
+        simulate = self.simulate
+        if force:
+            simulate = False
+        assert not kw, ("Arguments not expected: %s" % kw)
+        if capture_stderr:
+            stderr_pipe = subprocess.STDOUT
+        else:
+            stderr_pipe = subprocess.PIPE
+        try:
+            proc = subprocess.Popen([cmd] + list(args),
+                                    cwd=cwd,
+                                    stderr=stderr_pipe,
+                                    stdout=subprocess.PIPE)
+        except OSError, e:
+            if e.errno != 2:
+                # File not found
+                raise
+            raise OSError(
+                "The expected executable %s was not found (%s)"
+                % (cmd, e))
+        if self.verbose:
+            print 'Running %s %s' % (cmd, ' '.join(args))
+        if simulate:
+            return None
+        stdout, stderr = proc.communicate()
+        if proc.returncode and not expect_returncode:
+            if not self.verbose:
+                print 'Running %s %s' % (cmd, ' '.join(args))
+            print 'Error (exit code: %s)' % proc.returncode
+            if stderr:
+                print stderr
+            raise OSError("Error executing command %s" % cmd)
+        if self.verbose > 2:
+            if stderr:
+                print 'Command error output:'
+                print stderr
+            if stdout:
+                print 'Command output:'
+                print stdout
+        elif proc.returncode and warn_returncode:
+            print 'Warning: command failed (%s %s)' % (cmd, ' '.join(args))
+            print 'Exited with code %s' % proc.returncode
+        return stdout
+
+    def quote_first_command_arg(self, arg):
+        """
+        There's a bug in Windows when running an executable that's
+        located inside a path with a space in it.  This method handles
+        that case, or on non-Windows systems or an executable with no
+        spaces, it just leaves well enough alone.
+        """
+        if (sys.platform != 'win32'
+            or ' ' not in arg):
+            # Problem does not apply:
+            return arg
+        try:
+            import win32api
+        except ImportError:
+            raise ValueError(
+                "The executable %r contains a space, and in order to "
+                "handle this issue you must have the win32api module "
+                "installed" % arg)
+        arg = win32api.GetShortPathName(arg)
+        return arg
+
+    _svn_failed = False
+
+    def svn_command(self, *args, **kw):
+        """
+        Run an svn command, but don't raise an exception if it fails.
+        """
+        try:
+            return self.run_command('svn', *args, **kw)
+        except OSError, e:
+            if not self._svn_failed:
+                print 'Unable to run svn command (%s); proceeding anyway' % e
+                self._svn_failed = True
+
+    def write_file(self, filename, content, source=None,
+                   binary=True, svn_add=True):
+        """
+        Like ``ensure_file``, but without the interactivity.  Mostly
+        deprecated.  (I think I forgot it existed)
+        """
+        import warnings
+        warnings.warn(
+            "command.write_file has been replaced with "
+            "command.ensure_file",
+            DeprecationWarning, 2)
+        if os.path.exists(filename):
+            if binary:
+                f = open(filename, 'rb')
+            else:
+                f = open(filename, 'r')
+            old_content = f.read()
+            f.close()
+            if content == old_content:
+                if self.verbose:
+                    print 'File %s exists with same content' % (
+                        self.shorten(filename))
+                return
+            if (not self.simulate and self.options.interactive):
+                if not self.ask('Overwrite file %s?' % filename):
+                    return
+        if self.verbose > 1 and source:
+            print 'Writing %s from %s' % (self.shorten(filename),
+                                          self.shorten(source))
+        elif self.verbose:
+            print 'Writing %s' % self.shorten(filename)
+        if not self.simulate:
+            already_existed = os.path.exists(filename)
+            if binary:
+                f = open(filename, 'wb')
+            else:
+                f = open(filename, 'w')
+            f.write(content)
+            f.close()
+            if (not already_existed
+                and svn_add
+                and os.path.exists(os.path.join(os.path.dirname(filename), '.svn'))):
+                self.svn_command('add', filename)
+
+    def parse_vars(self, args):
+        """
+        Given variables like ``['a=b', 'c=d']`` turns it into ``{'a':
+        'b', 'c': 'd'}``
+        """
+        result = {}
+        for arg in args:
+            if '=' not in arg:
+                raise BadCommand(
+                    'Variable assignment %r invalid (no "=")'
+                    % arg)
+            name, value = arg.split('=', 1)
+            result[name] = value
+        return result
+    
+    def read_vars(self, config, section='pastescript'):
+        """
+        Given a configuration filename, this will return a map of values.
+        """
+        result = {}
+        p = ConfigParser.RawConfigParser()
+        p.read([config])
+        if p.has_section(section):
+            for key, value in p.items(section):
+                if key.endswith('__eval__'):
+                    result[key[:-len('__eval__')]] = eval(value)
+                else:
+                    result[key] = value
+        return result
+
+    def write_vars(self, config, vars, section='pastescript'):
+        """
+        Given a configuration filename, this will add items in the
+        vars mapping to the configuration file.  Will create the
+        configuration file if it doesn't exist.
+        """
+        modified = False
+
+        p = ConfigParser.RawConfigParser()
+        if not os.path.exists(config):
+            f = open(config, 'w')
+            f.write('')
+            f.close()
+            modified = True
+        p.read([config])
+        if not p.has_section(section):
+            p.add_section(section)
+            modified = True
+
+        existing_options = p.options(section)
+        for key, value in vars.items():
+            if (key not in existing_options and
+                '%s__eval__' % key not in existing_options):
+                if not isinstance(value, str):
+                    p.set(section, '%s__eval__' % key, repr(value))
+                else:
+                    p.set(section, key, value)
+                modified = True
+
+        if modified:
+            p.write(open(config, 'w'))
+        
+    def indent_block(self, text, indent=2, initial=None):
+        """
+        Indent the block of text (each line is indented).  If you give
+        ``initial``, then that is used in lieue of ``indent`` for the
+        first line.
+        """
+        if initial is None:
+            initial = indent
+        lines = text.splitlines()
+        first = (' '*initial) + lines[0]
+        rest = [(' '*indent)+l for l in lines[1:]]
+        return '\n'.join([first]+rest)
+
+    def logging_file_config(self, config_file):
+        """
+        Setup logging via the logging module's fileConfig function with the
+        specified ``config_file``, if applicable.
+        """
+        parser = ConfigParser.ConfigParser()
+        parser.read([config_file])
+        if parser.has_section('loggers'):
+            fileConfig(config_file)
+
+class NotFoundCommand(Command):
+
+    def run(self, args):
+        #for name, value in os.environ.items():
+        #    print '%s: %s' % (name, value)
+        #print sys.argv
+        print ('Command %r not known (you may need to run setup.py egg_info)'
+               % self.command_name)
+        commands = get_commands().items()
+        commands.sort()
+        if not commands:
+            print 'No commands registered.'
+            print 'Have you installed Paste Script?'
+            print '(try running python setup.py develop)'
+            return 2
+        print 'Known commands:'
+        longest = max([len(n) for n, c in commands])
+        for name, command in commands:
+            print '  %s  %s' % (self.pad(name, length=longest),
+                                command.load().summary)
+        return 2
+
+def popdefault(dict, name, default=None):
+    if name not in dict:
+        return default
+    else:
+        v = dict[name]
+        del dict[name]
+        return v

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/copydir.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/copydir.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/copydir.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,431 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import pkg_resources
+import sys
+if sys.version_info < (2, 4):
+    from paste.script.util import string24 as string
+else:
+    import string
+import cgi
+import urllib
+import re
+Cheetah = None
+try:
+    import subprocess
+except ImportError:
+    from paste.script.util import subprocess24 as subprocess
+import inspect
+
+class SkipTemplate(Exception):
+    """
+    Raised to indicate that the template should not be copied over.
+    Raise this exception during the substitution of your template
+    """
+
+def copy_dir(source, dest, vars, verbosity, simulate, indent=0,
+             use_cheetah=False, sub_vars=True, interactive=False,
+             svn_add=True, overwrite=True, template_renderer=None):
+    """
+    Copies the ``source`` directory to the ``dest`` directory.
+
+    ``vars``: A dictionary of variables to use in any substitutions.
+
+    ``verbosity``: Higher numbers will show more about what is happening.
+
+    ``simulate``: If true, then don't actually *do* anything.
+
+    ``indent``: Indent any messages by this amount.
+
+    ``sub_vars``: If true, variables in ``_tmpl`` files and ``+var+``
+    in filenames will be substituted.
+
+    ``use_cheetah``: If true, then any templates encountered will be
+    substituted with Cheetah.  Otherwise ``template_renderer`` or
+    ``string.Template`` will be used for templates.
+
+    ``svn_add``: If true, any files written out in directories with
+    ``.svn/`` directories will be added (via ``svn add``).
+
+    ``overwrite``: If false, then don't every overwrite anything.
+
+    ``interactive``: If you are overwriting a file and interactive is
+    true, then ask before overwriting.
+
+    ``template_renderer``: This is a function for rendering templates
+    (if you don't want to use Cheetah or string.Template).  It should
+    have the signature ``template_renderer(content_as_string,
+    vars_as_dict, filename=filename)``.
+    """
+    # This allows you to use a leading +dot+ in filenames which would
+    # otherwise be skipped because leading dots make the file hidden:
+    vars.setdefault('dot', '.')
+    vars.setdefault('plus', '+')
+    use_pkg_resources = isinstance(source, tuple)
+    if use_pkg_resources:
+        names = pkg_resources.resource_listdir(source[0], source[1])
+    else:
+        names = os.listdir(source)
+    names.sort()
+    pad = ' '*(indent*2)
+    if not os.path.exists(dest):
+        if verbosity >= 1:
+            print '%sCreating %s/' % (pad, dest)
+        if not simulate:
+            svn_makedirs(dest, svn_add=svn_add, verbosity=verbosity,
+                         pad=pad)
+    elif verbosity >= 2:
+        print '%sDirectory %s exists' % (pad, dest)
+    for name in names:
+        if use_pkg_resources:
+            full = '/'.join([source[1], name])
+        else:
+            full = os.path.join(source, name)
+        reason = should_skip_file(name)
+        if reason:
+            if verbosity >= 2:
+                reason = pad + reason % {'filename': full}
+                print reason
+            continue
+        if sub_vars:
+            dest_full = os.path.join(dest, substitute_filename(name, vars))
+        sub_file = False
+        if dest_full.endswith('_tmpl'):
+            dest_full = dest_full[:-5]
+            sub_file = sub_vars
+        if use_pkg_resources and pkg_resources.resource_isdir(source[0], full):
+            if verbosity:
+                print '%sRecursing into %s' % (pad, os.path.basename(full))
+            copy_dir((source[0], full), dest_full, vars, verbosity, simulate,
+                     indent=indent+1, use_cheetah=use_cheetah,
+                     sub_vars=sub_vars, interactive=interactive,
+                     svn_add=svn_add, template_renderer=template_renderer)
+            continue
+        elif not use_pkg_resources and os.path.isdir(full):
+            if verbosity:
+                print '%sRecursing into %s' % (pad, os.path.basename(full))
+            copy_dir(full, dest_full, vars, verbosity, simulate,
+                     indent=indent+1, use_cheetah=use_cheetah,
+                     sub_vars=sub_vars, interactive=interactive,
+                     svn_add=svn_add, template_renderer=template_renderer)
+            continue
+        elif use_pkg_resources:
+            content = pkg_resources.resource_string(source[0], full)
+        else:
+            f = open(full, 'rb')
+            content = f.read()
+            f.close()
+        if sub_file:
+            try:
+                content = substitute_content(content, vars, filename=full,
+                                             use_cheetah=use_cheetah,
+                                             template_renderer=template_renderer)
+            except SkipTemplate:
+                continue
+            if content is None:
+                continue
+        already_exists = os.path.exists(dest_full)
+        if already_exists:
+            f = open(dest_full, 'rb')
+            old_content = f.read()
+            f.close()
+            if old_content == content:
+                if verbosity:
+                    print '%s%s already exists (same content)' % (pad, dest_full)
+                continue
+            if interactive:
+                if not query_interactive(
+                    full, dest_full, content, old_content,
+                    simulate=simulate):
+                    continue
+            elif not overwrite:
+                continue
+        if verbosity and use_pkg_resources:
+            print '%sCopying %s to %s' % (pad, full, dest_full)
+        elif verbosity:
+            print '%sCopying %s to %s' % (pad, os.path.basename(full), dest_full)
+        if not simulate:
+            f = open(dest_full, 'wb')
+            f.write(content)
+            f.close()
+        if svn_add and not already_exists:
+            if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(dest_full)), '.svn')):
+                if verbosity > 1:
+                    print '%s.svn/ does not exist; cannot add file' % pad
+            else:
+                cmd = ['svn', 'add', dest_full]
+                if verbosity > 1:
+                    print '%sRunning: %s' % (pad, ' '.join(cmd))
+                if not simulate:
+                    # @@: Should
+                    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+                    stdout, stderr = proc.communicate()
+                    if verbosity > 1 and stdout:
+                        print 'Script output:'
+                        print stdout
+        elif svn_add and already_exists and verbosity > 1:
+            print '%sFile already exists (not doing svn add)' % pad
+
+def should_skip_file(name):
+    """
+    Checks if a file should be skipped based on its name.
+
+    If it should be skipped, returns the reason, otherwise returns
+    None.
+    """
+    if name.startswith('.'):
+        return 'Skipping hidden file %(filename)s'
+    if name.endswith('~') or name.endswith('.bak'):
+        return 'Skipping backup file %(filename)s'
+    if name.endswith('.pyc'):
+        return 'Skipping .pyc file %(filename)s'
+    if name.endswith('$py.class'):
+        return 'Skipping $py.class file %(filename)s'
+    if name in ('CVS', '_darcs'):
+        return 'Skipping version control directory %(filename)s'
+    return None
+
+# Overridden on user's request:
+all_answer = None
+
+def query_interactive(src_fn, dest_fn, src_content, dest_content,
+                      simulate):
+    global all_answer
+    from difflib import unified_diff, context_diff
+    u_diff = list(unified_diff(
+        dest_content.splitlines(),
+        src_content.splitlines(),
+        dest_fn, src_fn))
+    c_diff = list(context_diff(
+        dest_content.splitlines(),
+        src_content.splitlines(),
+        dest_fn, src_fn))
+    added = len([l for l in u_diff if l.startswith('+')
+                   and not l.startswith('+++')])
+    removed = len([l for l in u_diff if l.startswith('-')
+                   and not l.startswith('---')])
+    if added > removed:
+        msg = '; %i lines added' % (added-removed)
+    elif removed > added:
+        msg = '; %i lines removed' % (removed-added)
+    else:
+        msg = ''
+    print 'Replace %i bytes with %i bytes (%i/%i lines changed%s)' % (
+        len(dest_content), len(src_content),
+        removed, len(dest_content.splitlines()), msg)
+    prompt = 'Overwrite %s [y/n/d/B/?] ' % dest_fn
+    while 1:
+        if all_answer is None:
+            response = raw_input(prompt).strip().lower()
+        else:
+            response = all_answer
+        if not response or response[0] == 'b':
+            import shutil
+            new_dest_fn = dest_fn + '.bak'
+            n = 0
+            while os.path.exists(new_dest_fn):
+                n += 1
+                new_dest_fn = dest_fn + '.bak' + str(n)
+            print 'Backing up %s to %s' % (dest_fn, new_dest_fn)
+            if not simulate:
+                shutil.copyfile(dest_fn, new_dest_fn)
+            return True
+        elif response.startswith('all '):
+            rest = response[4:].strip()
+            if not rest or rest[0] not in ('y', 'n', 'b'):
+                print query_usage
+                continue
+            response = all_answer = rest[0]
+        if response[0] == 'y':
+            return True
+        elif response[0] == 'n':
+            return False
+        elif response == 'dc':
+            print '\n'.join(c_diff)
+        elif response[0] == 'd':
+            print '\n'.join(u_diff)
+        else:
+            print query_usage
+
+query_usage = """\
+Responses:
+  Y(es):    Overwrite the file with the new content.
+  N(o):     Do not overwrite the file.
+  D(iff):   Show a unified diff of the proposed changes (dc=context diff)
+  B(ackup): Save the current file contents to a .bak file
+            (and overwrite)
+  Type "all Y/N/B" to use Y/N/B for answer to all future questions
+"""
+
+def svn_makedirs(dir, svn_add, verbosity, pad):
+    parent = os.path.dirname(os.path.abspath(dir))
+    if not os.path.exists(parent):
+        svn_makedirs(parent, svn_add, verbosity, pad)
+    os.mkdir(dir)
+    if not svn_add:
+        return
+    if not os.path.exists(os.path.join(parent, '.svn')):
+        if verbosity > 1:
+            print '%s.svn/ does not exist; cannot add directory' % pad
+        return
+    cmd = ['svn', 'add', dir]
+    if verbosity > 1:
+        print '%sRunning: %s' % (pad, ' '.join(cmd))
+    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+    stdout, stderr = proc.communicate()
+    if verbosity > 1 and stdout:
+        print 'Script output:'
+        print stdout
+
+def substitute_filename(fn, vars):
+    for var, value in vars.items():
+        fn = fn.replace('+%s+' % var, str(value))
+    return fn
+
+def substitute_content(content, vars, filename='<string>',
+                       use_cheetah=False, template_renderer=None):
+    global Cheetah
+    v = standard_vars.copy()
+    v.update(vars)
+    vars = v
+    if template_renderer is not None:
+        return template_renderer(content, vars, filename=filename)
+    if not use_cheetah:
+        tmpl = LaxTemplate(content)
+        try:
+            return tmpl.substitute(TypeMapper(v))
+        except Exception, e:
+            _add_except(e, ' in file %s' % filename)
+            raise
+    if Cheetah is None:
+        import Cheetah.Template
+    tmpl = Cheetah.Template.Template(source=content,
+                                     searchList=[vars])
+    return careful_sub(tmpl, vars, filename)
+
+def careful_sub(cheetah_template, vars, filename):
+    """
+    Substitutes the template with the variables, using the
+    .body() method if it exists.  It assumes that the variables
+    were also passed in via the searchList.
+    """
+    if not hasattr(cheetah_template, 'body'):
+        return sub_catcher(filename, vars, str, cheetah_template)
+    body = cheetah_template.body
+    args, varargs, varkw, defaults = inspect.getargspec(body)
+    call_vars = {}
+    for arg in args:
+        if arg in vars:
+            call_vars[arg] = vars[arg]
+    return sub_catcher(filename, vars, body, **call_vars)
+
+def sub_catcher(filename, vars, func, *args, **kw):
+    """
+    Run a substitution, returning the value.  If an error occurs, show
+    the filename.  If the error is a NameError, show the variables.
+    """
+    try:
+        return func(*args, **kw)
+    except SkipTemplate, e:
+        print 'Skipping file %s' % filename
+        if str(e):
+            print str(e)
+        raise
+    except Exception, e:
+        print 'Error in file %s:' % filename
+        if isinstance(e, NameError):
+            items = vars.items()
+            items.sort()
+            for name, value in items:
+                print '%s = %r' % (name, value)
+        raise
+
+def html_quote(s):
+    if s is None:
+        return ''
+    return cgi.escape(str(s), 1)
+
+def url_quote(s):
+    if s is None:
+        return ''
+    return urllib.quote(str(s))
+
+def test(conf, true_cond, false_cond=None):
+    if conf:
+        return true_cond
+    else:
+        return false_cond
+
+def skip_template(condition=True, *args):
+    """
+    Raise SkipTemplate, which causes copydir to skip the template
+    being processed.  If you pass in a condition, only raise if that
+    condition is true (allows you to use this with string.Template)
+
+    If you pass any additional arguments, they will be used to
+    instantiate SkipTemplate (generally use like
+    ``skip_template(license=='GPL', 'Skipping file; not using GPL')``)
+    """
+    if condition:
+        raise SkipTemplate(*args)
+
+def _add_except(exc, info):
+    if not hasattr(exc, 'args') or exc.args is None:
+        return
+    args = list(exc.args)
+    if args:
+        args[0] += ' ' + info
+    else:
+        args = [info]
+    exc.args = tuple(args)
+    return
+    
+
+standard_vars = {
+    'nothing': None,
+    'html_quote': html_quote,
+    'url_quote': url_quote,
+    'empty': '""',
+    'test': test,
+    'repr': repr,
+    'str': str,
+    'bool': bool,
+    'SkipTemplate': SkipTemplate,
+    'skip_template': skip_template,
+    }
+
+class TypeMapper(dict):
+
+    def __getitem__(self, item):
+        options = item.split('|')
+        for op in options[:-1]:
+            try:
+                value = eval_with_catch(op, dict(self.items()))
+                break
+            except (NameError, KeyError):
+                pass
+        else:
+            value = eval(options[-1], dict(self.items()))
+        if value is None:
+            return ''
+        else:
+            return str(value)
+
+def eval_with_catch(expr, vars):
+    try:
+        return eval(expr, vars)
+    except Exception, e:
+        _add_except(e, 'in expression %r' % expr)
+        raise
+        
+class LaxTemplate(string.Template):
+    # This change of pattern allows for anything in braces, but
+    # only identifiers outside of braces:
+    pattern = r"""
+    \$(?:
+      (?P<escaped>\$)             |   # Escape sequence of two delimiters
+      (?P<named>[_a-z][_a-z0-9]*) |   # delimiter and a Python identifier
+      {(?P<braced>.*?)}           |   # delimiter and a braced identifier
+      (?P<invalid>)                   # Other ill-formed delimiter exprs
+    )
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/create_distro.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/create_distro.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/create_distro.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,417 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import re
+import sys
+import os
+import pkg_resources
+from command import Command, BadCommand
+import copydir
+import pluginlib
+import fnmatch
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+class CreateDistroCommand(Command):
+
+    usage = 'PACKAGE_NAME [VAR=VALUE VAR2=VALUE2 ...]'
+    summary = "Create the file layout for a Python distribution"
+    short_description = summary
+
+    description = """\
+    Create a new project.  Projects are typically Python packages,
+    ready for distribution.  Projects are created from templates, and
+    represent different kinds of projects -- associated with a
+    particular framework for instance.
+    """
+
+    parser = Command.standard_parser(
+        simulate=True, no_interactive=True, quiet=True, overwrite=True)
+    parser.add_option('-t', '--template',
+                      dest='templates',
+                      metavar='TEMPLATE',
+                      action='append',
+                      help="Add a template to the create process")
+    parser.add_option('-o', '--output-dir',
+                      dest='output_dir',
+                      metavar='DIR',
+                      default='.',
+                      help="Write put the directory into DIR (default current directory)")
+    parser.add_option('--svn-repository',
+                      dest='svn_repository',
+                      metavar='REPOS',
+                      help="Create package at given repository location (this will create the standard trunk/ tags/ branches/ hierarchy)")
+    parser.add_option('--list-templates',
+                      dest='list_templates',
+                      action='store_true',
+                      help="List all templates available")
+    parser.add_option('--list-variables',
+                      dest="list_variables",
+                      action="store_true",
+                      help="List all variables expected by the given template (does not create a package)")
+    parser.add_option('--inspect-files',
+                      dest='inspect_files',
+                      action='store_true',
+                      help="Show where the files in the given (already created) directory came from (useful when using multiple templates)")
+    parser.add_option('--config',
+                      action='store',
+                      dest='config',
+                      help="Template variables file")
+
+    _bad_chars_re = re.compile('[^a-zA-Z0-9_]')
+
+    default_verbosity = 1
+    default_interactive = 1
+
+    def command(self):
+        if self.options.list_templates:
+            return self.list_templates()
+        asked_tmpls = self.options.templates or ['basic_package']
+        templates = []
+        for tmpl_name in asked_tmpls:
+            self.extend_templates(templates, tmpl_name)
+        if self.options.list_variables:
+            return self.list_variables(templates)
+        if self.verbose:
+            print 'Selected and implied templates:'
+            max_tmpl_name = max([len(tmpl_name) for tmpl_name, tmpl in templates])
+            for tmpl_name, tmpl in templates:
+                print '  %s%s  %s' % (
+                    tmpl_name, ' '*(max_tmpl_name-len(tmpl_name)),
+                    tmpl.summary)
+            print
+        if not self.args:
+            if self.interactive:
+                dist_name = self.challenge('Enter project name')
+            else:
+                raise BadCommand('You must provide a PACKAGE_NAME')
+        else:
+            dist_name = self.args[0].lstrip(os.path.sep)
+
+        templates = [tmpl for name, tmpl in templates]
+        output_dir = os.path.join(self.options.output_dir, dist_name)
+        
+        pkg_name = self._bad_chars_re.sub('', dist_name.lower())
+        vars = {'project': dist_name,
+                'package': pkg_name,
+                'egg': pluginlib.egg_name(dist_name),
+                }
+        vars.update(self.parse_vars(self.args[1:]))
+        if self.options.config and os.path.exists(self.options.config):
+            for key, value in self.read_vars(self.options.config).items():
+                vars.setdefault(key, value)
+        
+        if self.verbose: # @@: > 1?
+            self.display_vars(vars)
+
+        if self.options.inspect_files:
+            self.inspect_files(
+                output_dir, templates, vars)
+            return
+        if not os.path.exists(output_dir):
+            # We want to avoid asking questions in copydir if the path
+            # doesn't exist yet
+            copydir.all_answer = 'y'
+        
+        if self.options.svn_repository:
+            self.setup_svn_repository(output_dir, dist_name)
+
+        # First we want to make sure all the templates get a chance to
+        # set their variables, all at once, with the most specialized
+        # template going first (the last template is the most
+        # specialized)...
+        for template in templates[::-1]:
+            vars = template.check_vars(vars, self)
+
+        # Gather all the templates egg_plugins into one var
+        egg_plugins = set()
+        for template in templates:
+            egg_plugins.update(template.egg_plugins)
+        egg_plugins = list(egg_plugins)
+        egg_plugins.sort()
+        vars['egg_plugins'] = egg_plugins
+            
+        for template in templates:
+            self.create_template(
+                template, output_dir, vars)
+
+        found_setup_py = False
+        paster_plugins_mtime = None
+        if os.path.exists(os.path.join(output_dir, 'setup.py')):
+            # Grab paster_plugins.txt's mtime; used to determine if the
+            # egg_info command wrote to it
+            try:
+                egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
+            except IOError:
+                egg_info_dir = None
+            if egg_info_dir is not None:
+                plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
+                if os.path.exists(plugins_path):
+                    paster_plugins_mtime = os.path.getmtime(plugins_path)
+
+            self.run_command(sys.executable, 'setup.py', 'egg_info',
+                             cwd=output_dir,
+                             # This shouldn't be necessary, but a bug in setuptools 0.6c3 is causing a (not entirely fatal) problem that I don't want to fix right now:
+                             expect_returncode=True)
+            found_setup_py = True
+        elif self.verbose > 1:
+            print 'No setup.py (cannot run egg_info)'
+
+        package_dir = vars.get('package_dir', None)
+        if package_dir:
+            output_dir = os.path.join(output_dir, package_dir)
+
+        # With no setup.py this doesn't make sense:
+        if found_setup_py:
+            # Only write paster_plugins.txt if it wasn't written by
+            # egg_info (the correct way). leaving us to do it is
+            # deprecated and you'll get warned
+            egg_info_dir = pluginlib.egg_info_dir(output_dir, dist_name)
+            plugins_path = os.path.join(egg_info_dir, 'paster_plugins.txt')
+            if len(egg_plugins) and (not os.path.exists(plugins_path) or \
+                    os.path.getmtime(plugins_path) == paster_plugins_mtime):
+                if self.verbose:
+                    print >> sys.stderr, \
+                        ('Manually creating paster_plugins.txt (deprecated! '
+                         'pass a paster_plugins keyword to setup() instead)')
+                for plugin in egg_plugins:
+                    if self.verbose:
+                        print 'Adding %s to paster_plugins.txt' % plugin
+                    if not self.simulate:
+                        pluginlib.add_plugin(egg_info_dir, plugin)
+        
+        if self.options.svn_repository:
+            self.add_svn_repository(vars, output_dir)
+
+        if self.options.config:
+            write_vars = vars.copy()
+            del write_vars['project']
+            del write_vars['package']
+            self.write_vars(self.options.config, write_vars)
+        
+    def create_template(self, template, output_dir, vars):
+        if self.verbose:
+            print 'Creating template %s' % template.name
+        template.run(self, output_dir, vars)
+
+    def setup_svn_repository(self, output_dir, dist_name):
+        # @@: Use subprocess
+        svn_repos = self.options.svn_repository
+        svn_repos_path = os.path.join(svn_repos, dist_name).replace('\\','/')
+        svn_command = 'svn'
+        if sys.platform == 'win32':
+            svn_command += '.exe'
+        # @@: The previous method of formatting this string using \ doesn't work on Windows
+        cmd = '%(svn_command)s mkdir %(svn_repos_path)s' + \
+            ' %(svn_repos_path)s/trunk %(svn_repos_path)s/tags' + \
+            ' %(svn_repos_path)s/branches -m "New project %(dist_name)s"'
+        cmd = cmd % {
+            'svn_repos_path': svn_repos_path, 
+            'dist_name': dist_name,
+            'svn_command':svn_command,
+        }
+        if self.verbose:
+            print "Running:"
+            print cmd
+        if not self.simulate:
+            os.system(cmd)
+        svn_repos_path_trunk = os.path.join(svn_repos_path,'trunk').replace('\\','/')
+        cmd = svn_command+' co "%s" "%s"' % (svn_repos_path_trunk, output_dir)
+        if self.verbose:
+            print "Running %s" % cmd
+        if not self.simulate:
+            os.system(cmd)
+
+    ignore_egg_info_files = [
+        'top_level.txt',
+        'entry_points.txt',
+        'requires.txt',
+        'PKG-INFO',
+        'namespace_packages.txt',
+        'SOURCES.txt',
+        'dependency_links.txt',
+        'not-zip-safe']
+
+    def add_svn_repository(self, vars, output_dir):
+        svn_repos = self.options.svn_repository
+        egg_info_dir = pluginlib.egg_info_dir(output_dir, vars['project'])
+        svn_command = 'svn'
+        if sys.platform == 'win32':
+            svn_command += '.exe'
+        self.run_command(svn_command, 'add', '-N', egg_info_dir)
+        paster_plugins_file = os.path.join(
+            egg_info_dir, 'paster_plugins.txt')
+        if os.path.exists(paster_plugins_file):
+            self.run_command(svn_command, 'add', paster_plugins_file)
+        self.run_command(svn_command, 'ps', 'svn:ignore',
+                         '\n'.join(self.ignore_egg_info_files),
+                         egg_info_dir)
+        if self.verbose:
+            print ("You must next run 'svn commit' to commit the "
+                   "files to repository")
+
+    def extend_templates(self, templates, tmpl_name):
+        if '#' in tmpl_name:
+            dist_name, tmpl_name = tmpl_name.split('#', 1)
+        else:
+            dist_name, tmpl_name = None, tmpl_name
+        if dist_name is None:
+            for entry in self.all_entry_points():
+                if entry.name == tmpl_name:
+                    tmpl = entry.load()(entry.name)
+                    dist_name = entry.dist.project_name
+                    break
+            else:
+                raise LookupError(
+                    'Template by name %r not found' % tmpl_name)
+        else:
+            dist = pkg_resources.get_distribution(dist_name)
+            entry = dist.get_entry_info(
+                'paste.paster_create_template', tmpl_name)
+            tmpl = entry.load()(entry.name)
+        full_name = '%s#%s' % (dist_name, tmpl_name)
+        for item_full_name, item_tmpl in templates:
+            if item_full_name == full_name:
+                # Already loaded
+                return
+        for req_name in tmpl.required_templates:
+            self.extend_templates(templates, req_name)
+        templates.append((full_name, tmpl))
+        
+    def all_entry_points(self):
+        if not hasattr(self, '_entry_points'):
+            self._entry_points = list(pkg_resources.iter_entry_points(
+            'paste.paster_create_template'))
+        return self._entry_points
+
+    def display_vars(self, vars):
+        vars = vars.items()
+        vars.sort()
+        print 'Variables:'
+        max_var = max([len(n) for n, v in vars])
+        for name, value in vars:
+            print '  %s:%s  %s' % (
+                name, ' '*(max_var-len(name)), value)
+        
+    def list_templates(self):
+        templates = []
+        for entry in self.all_entry_points():
+            try:
+                templates.append(entry.load()(entry.name))
+            except Exception, e:
+                # We will not be stopped!
+                print 'Warning: could not load entry point %s (%s: %s)' % (
+                    entry.name, e.__class__.__name__, e)
+        max_name = max([len(t.name) for t in templates])
+        templates.sort(lambda a, b: cmp(a.name, b.name))
+        print 'Available templates:'
+        for template in templates:
+            # @@: Wrap description
+            print '  %s:%s  %s' % (
+                template.name,
+                ' '*(max_name-len(template.name)),
+                template.summary)
+        
+    def inspect_files(self, output_dir, templates, vars):
+        file_sources = {}
+        for template in templates:
+            self._find_files(template, vars, file_sources)
+        self._show_files(output_dir, file_sources)
+        self._show_leftovers(output_dir, file_sources)
+
+    def _find_files(self, template, vars, file_sources):
+        tmpl_dir = template.template_dir()
+        self._find_template_files(
+            template, tmpl_dir, vars, file_sources)
+
+    def _find_template_files(self, template, tmpl_dir, vars,
+                             file_sources, join=''):
+        full_dir = os.path.join(tmpl_dir, join)
+        for name in os.listdir(full_dir):
+            if name.startswith('.'):
+                continue
+            if os.path.isdir(os.path.join(full_dir, name)):
+                self._find_template_files(
+                    template, tmpl_dir, vars, file_sources,
+                    join=os.path.join(join, name))
+                continue
+            partial = os.path.join(join, name)
+            for name, value in vars.items():
+                partial = partial.replace('+%s+' % name, value)
+            if partial.endswith('_tmpl'):
+                partial = partial[:-5]
+            file_sources.setdefault(partial, []).append(template)
+
+    _ignore_filenames = ['.*', '*.pyc', '*.bak*']
+    _ignore_dirs = ['CVS', '_darcs', '.svn']
+
+    def _show_files(self, output_dir, file_sources, join='', indent=0):
+        pad = ' '*(2*indent)
+        full_dir = os.path.join(output_dir, join)
+        names = os.listdir(full_dir)
+        dirs = [n for n in names
+                if os.path.isdir(os.path.join(full_dir, n))]
+        fns = [n for n in names
+               if not os.path.isdir(os.path.join(full_dir, n))]
+        dirs.sort()
+        names.sort()
+        for name in names:
+            skip_this = False
+            for ext in self._ignore_filenames:
+                if fnmatch.fnmatch(name, ext):
+                    if self.verbose > 1:
+                        print '%sIgnoring %s' % (pad, name)
+                    skip_this = True
+                    break
+            if skip_this:
+                continue
+            partial = os.path.join(join, name)
+            if partial not in file_sources:
+                if self.verbose > 1:
+                    print '%s%s (not from template)' % (pad, name)
+                continue
+            templates = file_sources.pop(partial)
+            print '%s%s from:' % (pad, name)
+            for template in templates:
+                print '%s  %s' % (pad, template.name)
+        for dir in dirs:
+            if dir in self._ignore_dirs:
+                continue
+            print '%sRecursing into %s/' % (pad, dir)
+            self._show_files(
+                output_dir, file_sources,
+                join=os.path.join(join, dir),
+                indent=indent+1)
+
+    def _show_leftovers(self, output_dir, file_sources):
+        if not file_sources:
+            return
+        print 
+        print 'These files were supposed to be generated by templates'
+        print 'but were not found:'
+        file_sources = file_sources.items()
+        file_sources.sort()
+        for partial, templates in file_sources:
+            print '  %s from:' % partial
+            for template in templates:
+                print '    %s' % template.name
+
+    def list_variables(self, templates):
+        for tmpl_name, tmpl in templates:
+            if not tmpl.read_vars():
+                if self.verbose > 1:
+                    self._show_template_vars(
+                        tmpl_name, tmpl, 'No variables found')
+                continue
+            self._show_template_vars(tmpl_name, tmpl)
+
+    def _show_template_vars(self, tmpl_name, tmpl, message=None):
+        title = '%s (from %s)' % (tmpl.name, tmpl_name)
+        print title
+        print '-'*len(title)
+        if message is not None:
+            print '  %s' % message
+            print
+            return
+        tmpl.print_vars(indent=2)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/default_sysconfig.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/default_sysconfig.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/default_sysconfig.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+This module contains default sysconfig settings.
+
+The command object is inserted into this module as a global variable
+``paste_command``, and can be used inside functions.
+"""
+
+def add_custom_options(parser):
+    """
+    This method can modify the ``parser`` object (which is an
+    ``optparse.OptionParser`` instance).  This can be used to add new
+    options to the command.
+    """
+    pass
+
+def default_config_filename(installer):
+    """
+    This function can return a default filename or directory for the
+    configuration file, if none was explicitly given.
+
+    Return None to mean no preference.  The first non-None returning
+    value will be used.
+
+    Pay attention to ``installer.expect_config_directory`` here,
+    and to ``installer.default_config_filename``.  
+    """
+    return installer.default_config_filename
+
+def install_variables(installer):
+    """
+    Returns a dictionary of variables for use later in the process
+    (e.g., filling a configuration file).  These are combined from all
+    sysconfig files.
+    """
+    return {}
+
+def post_setup_hook(installer, config_file):
+    """
+    This is called at the very end of ``paster setup-app``.  You
+    might use it to register an application globally.
+    """
+    pass

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/entrypoints.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/entrypoints.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/entrypoints.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,269 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import textwrap
+import os
+import pkg_resources
+from command import Command, BadCommand
+import fnmatch
+import re
+import traceback
+from cStringIO import StringIO
+import inspect
+import types
+
+class EntryPointCommand(Command):
+
+    usage = "ENTRY_POINT"
+    summary = "Show information about entry points"
+    
+    description = """\
+    Shows information about one or many entry points (you can use
+    wildcards for entry point names).  Entry points are used for Egg
+    plugins, and are named resources -- like an application, template
+    plugin, or other resource.  Entry points have a [group] which
+    defines what kind of object they describe, and inside groups each
+    entry point is named.
+    """
+    
+    max_args = 2
+
+    parser = Command.standard_parser(verbose=False)
+    parser.add_option('--list', '-l',
+                      dest='list_entry_points',
+                      action='store_true',
+                      help='List all the kinds of entry points on the system')
+    parser.add_option('--egg', '-e',
+                      dest='show_egg',
+                      help="Show all the entry points for the given Egg")
+    parser.add_option('--regex',
+                      dest='use_regex',
+                      action='store_true',
+                      help="Make pattern match as regular expression, not just a wildcard pattern")
+
+    def command(self):
+        if self.options.list_entry_points:
+            return self.list_entry_points()
+        if self.options.show_egg:
+            return self.show_egg(self.options.show_egg)
+        if not self.args:
+            raise BadCommand("You must give an entry point (or --list)")
+        pattern = self.get_pattern(self.args[0])
+        groups = self.get_groups_by_pattern(pattern)
+        if not groups:
+            raise BadCommand('No group matched %s' % self.args[0])
+        ep_pat = None
+        if len(self.args) > 1:
+            ep_pat = self.get_pattern(self.args[1])
+        for group in groups:
+            desc = self.get_group_description(group)
+            print '[%s]' % group
+            if desc:
+                print self.wrap(desc)
+                print
+            by_dist = {}
+            self.print_entry_points_by_group(group, ep_pat)
+
+    def print_entry_points_by_group(self, group, ep_pat):
+        env = pkg_resources.Environment()
+        project_names = list(env)
+        project_names.sort()
+        for project_name in project_names:
+            dists = list(env[project_name])
+            assert dists
+            dist = dists[0]
+            entries = dist.get_entry_map(group).values()
+            if ep_pat:
+                entries = [e for e in entries
+                           if ep_pat.search(e.name)]
+            if not entries:
+                continue
+            if len(dists) > 1:
+                print '%s (+ %i older versions)' % (
+                    dist, len(dists)-1)
+            else:
+                print '%s' % dist
+            entries.sort(lambda a, b: cmp(a.name, b.name))
+            for entry in entries:
+                print self._ep_description(entry)
+                desc = self.get_entry_point_description(entry, group)
+                if desc and desc.description:
+                    print self.wrap(desc.description, indent=4)
+
+    def show_egg(self, egg_name):
+        group_pat = None
+        if self.args:
+            group_pat = self.get_pattern(self.args[0])
+        ep_pat = None
+        if len(self.args) > 1:
+            ep_pat = self.get_pattern(self.args[1])
+        if egg_name.startswith('egg:'):
+            egg_name = egg_name[4:]
+        dist = pkg_resources.get_distribution(egg_name)
+        entry_map = dist.get_entry_map()
+        entry_groups = entry_map.items()
+        entry_groups.sort()
+        for group, points in entry_groups:
+            if group_pat and not group_pat.search(group):
+                continue
+            print '[%s]' % group
+            points = points.items()
+            points.sort()
+            for name, entry in points:
+                if ep_pat:
+                    if not ep_pat.search(name):
+                        continue
+                print self._ep_description(entry)
+                desc = self.get_entry_point_description(entry, group)
+                if desc and desc.description:
+                    print self.wrap(desc.description, indent=2)
+                print
+
+    def wrap(self, text, indent=0):
+        text = dedent(text)
+        width = int(os.environ.get('COLUMNS', 70)) - indent
+        text = '\n'.join([line.rstrip() for line in text.splitlines()])
+        paras = text.split('\n\n')
+        new_paras = []
+        for para in paras:
+            if para.lstrip() == para:
+                # leading whitespace means don't rewrap
+                para = '\n'.join(textwrap.wrap(para, width))
+            new_paras.append(para)
+        text = '\n\n'.join(new_paras)
+        lines = [' '*indent + line
+                 for line in text.splitlines()]
+        return '\n'.join(lines)
+
+    def _ep_description(self, ep, pad_name=None):
+        name = ep.name
+        if pad_name is not None:
+            name = name + ' '*(pad_name-len(name))
+        dest = ep.module_name
+        if ep.attrs:
+            dest = dest + ':' + '.'.join(ep.attrs)
+        return '%s = %s' % (name, dest)
+
+    def get_pattern(self, s):
+        if not s:
+            return None
+        if self.options.use_regex:
+            return re.compile(s)
+        else:
+            return re.compile(fnmatch.translate(s), re.I)
+
+    def list_entry_points(self):
+        pattern = self.get_pattern(self.args and self.args[0])
+        groups = self.get_groups_by_pattern(pattern)
+        print '%i entry point groups found:' % len(groups)
+        for group in groups:
+            desc = self.get_group_description(group)
+            print '[%s]' % group
+            if desc:
+                if hasattr(desc, 'description'):
+                    desc = desc.description
+                print self.wrap(desc, indent=2)
+
+    def get_groups_by_pattern(self, pattern):
+        env = pkg_resources.Environment()
+        eps = {}
+        for project_name in env:
+            for dist in env[project_name]:
+                for name in pkg_resources.get_entry_map(dist):
+                    if pattern and not pattern.search(name):
+                        continue
+                    if (not pattern
+                        and name.startswith('paste.description.')):
+                        continue
+                    eps[name] = None
+        eps = eps.keys()
+        eps.sort()
+        return eps
+    
+    def get_group_description(self, group):
+        for entry in pkg_resources.iter_entry_points('paste.entry_point_description'):
+            if entry.name == group:
+                ep = entry.load()
+                if hasattr(ep, 'description'):
+                    return ep.description
+                else:
+                    return ep
+        return None
+
+    def get_entry_point_description(self, ep, group):
+        try:
+            return self._safe_get_entry_point_description(ep, group)
+        except Exception, e:
+            out = StringIO()
+            traceback.print_exc(file=out)
+            return ErrorDescription(e, out.getvalue())
+
+    def _safe_get_entry_point_description(self, ep, group):
+        ep.dist.activate()
+        meta_group = 'paste.description.'+group
+        meta = ep.dist.get_entry_info(meta_group, ep.name)
+        if not meta:
+            generic = list(pkg_resources.iter_entry_points(
+                meta_group, 'generic'))
+            if not generic:
+                return super_generic(ep.load())
+            # @@: Error if len(generic) > 1?
+            obj = generic[0].load()
+            desc = obj(ep, group)
+        else:
+            desc = meta.load()
+        return desc
+    
+class EntryPointDescription(object):
+
+    def __init__(self, group):
+        self.group = group
+
+    # Should define:
+    # * description
+
+class SuperGeneric(object):
+
+    def __init__(self, doc_object):
+        self.doc_object = doc_object
+        self.description = dedent(self.doc_object.__doc__)
+        try:
+            if isinstance(self.doc_object, (type, types.ClassType)):
+                func = self.doc_object.__init__.im_func
+            elif (hasattr(self.doc_object, '__call__')
+                  and not isinstance(self.doc_object, types.FunctionType)):
+                func = self.doc_object.__call__
+            else:
+                func = self.doc_object
+            if hasattr(func, '__paste_sig__'):
+                sig = func.__paste_sig__
+            else:
+                sig = inspect.getargspec(func)
+                sig = inspect.formatargspec(*sig)
+        except TypeError:
+            sig = None
+        if sig:
+            if self.description:
+                self.description = '%s\n\n%s' % (
+                    sig, self.description)
+            else:
+                self.description = sig
+
+def dedent(s):
+    if s is None:
+        return s
+    s = s.strip('\n').strip('\r')
+    return textwrap.dedent(s)
+
+def super_generic(obj):
+    desc = SuperGeneric(obj)
+    if not desc.description:
+        return None
+    return desc
+
+class ErrorDescription(object):
+
+    def __init__(self, exc, tb):
+        self.exc = exc
+        self.tb = '\n'.join(tb)
+        self.description = 'Error loading: %s' % exc
+        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/epdesc.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/epdesc.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/epdesc.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,57 @@
+class MetaEntryPointDescription(object):
+    description = """
+    This is an entry point that describes other entry points.
+    """
+
+class CreateTemplateDescription(object):
+    description = """
+    Entry point for creating the file layout for a new project
+    from a template.
+    """
+
+class PasterCommandDescription(object):
+    description = """
+    Entry point that adds a command to the ``paster`` script
+    to a project that has specifically enabled the command.
+    """
+
+class GlobalPasterCommandDescription(object):
+    description = """
+    Entry point that adds a command to the ``paster`` script
+    globally.
+    """
+
+class AppInstallDescription(object):
+    description = """
+    This defines a runner that can install the application given a
+    configuration file.
+    """
+
+##################################################
+## Not in Paste per se, but we'll document
+## them...
+
+class ConsoleScriptsDescription(object):
+    description = """
+    When a package is installed, any entry point listed here will be
+    turned into a command-line script.
+    """
+
+class DistutilsCommandsDescription(object):
+    description = """
+    This will add a new command when running
+    ``python setup.py entry-point-name`` if the
+    package uses setuptools.
+    """
+
+class SetupKeywordsDescription(object):
+    description = """
+    This adds a new keyword to setup.py's setup() function, and a
+    validator to validate the value.
+    """
+
+class EggInfoWriters(object):
+    description = """
+    This adds a new writer that creates files in the PkgName.egg-info/
+    directory.
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/exe.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/exe.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/exe.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,107 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import re
+import os
+import sys
+import shlex
+import pkg_resources
+import command
+
+class ExeCommand(command.Command):
+
+    parser = command.Command.standard_parser(verbose=False)
+    summary = "Run #! executable files"
+    description = """\
+Use this at the top of files like:
+
+  #!/usr/bin/env /path/to/paster exe subcommand <command options>
+
+The rest of the file will be used as a config file for the given
+command, if it wants a config file.
+
+You can also include an [exe] section in the file, which looks
+like:
+
+  [exe]
+  command = serve
+  log_file = /path/to/log
+  add = /path/to/other/config.ini
+
+Which translates to:
+
+  paster serve --log-file=/path/to/log /path/to/other/config.ini
+"""
+    
+    hidden = True
+
+    _exe_section_re = re.compile(r'^\s*\[\s*exe\s*\]\s*$')
+    _section_re = re.compile(r'^\s*\[')
+
+    def run(self, argv):
+        if argv and argv[0] in ('-h', '--help'):
+            print self.description
+            return
+        
+        if os.environ.get('REQUEST_METHOD'):
+            # We're probably in a CGI environment
+            sys.stdout = sys.stderr
+            os.environ['PASTE_DEFAULT_QUIET'] = 'true'
+            # Maybe import cgitb or something?
+            
+        if '_' not in os.environ:
+            print "Warning: this command is intended to be run with a #! like:"
+            print "  #!/usr/bin/env paster exe"
+            print "It only works with /usr/bin/env, and only as a #! line."
+            # Should I actually shlex.split the args?
+            filename = argv[-1]
+            args = argv[:-1]
+            extra_args = []
+        else:
+            filename = os.environ['_']
+            extra_args = argv[:]
+            args = []
+            while extra_args:
+                if extra_args[0] == filename:
+                    extra_args.pop(0)
+                    break
+                args.append(extra_args.pop(0))
+        vars = {'here': os.path.dirname(filename),
+                '__file__': filename}
+        f = open(filename)
+        lines = f.readlines()
+        f.close()
+        options = {}
+        lineno = 1
+        while lines:
+            if self._exe_section_re.search(lines[0]):
+                lines.pop(0)
+                break
+            lines.pop(0)
+            lineno += 1
+        pre_options = []
+        options = args
+        for line in lines:
+            lineno += 1
+            line = line.strip()
+            if not line or line.startswith('#'):
+                continue
+            if self._section_re.search(line):
+                break
+            if '=' not in line:
+                raise command.BadCommand('Missing = in %s at %s: %r'
+                                         % (filename, lineno, line))
+            name, value = line.split('=', 1)
+            name = name.strip()
+            value = value.strip()
+            if name == 'require':
+                pkg_resources.require(value)
+            elif name == 'command' or name == 'add':
+                options.extend(shlex.split(value))
+            elif name == 'plugin':
+                options[:0] = ['--plugin', value]
+            else:
+                value = value % vars
+                options.append('--%s=%s' % (name.replace('_', '-'), value))
+        os.environ['PASTE_CONFIG_FILE'] = filename
+        options.extend(extra_args)
+        command.run(options)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/filemaker.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/filemaker.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/filemaker.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,362 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import glob
+import pkg_resources
+from paste.script import pluginlib, copydir
+from paste.script.command import BadCommand
+difflib = None
+try:
+    import subprocess
+except ImportError:
+    from paste.script.util import subprocess24 as subprocess
+
+class FileOp(object):
+    """
+    Enhance the ease of file copying/processing from a package into a target
+    project
+    """
+    
+    def __init__(self, simulate=False, 
+                       verbose=True, 
+                       interactive=True,
+                       source_dir=None,
+                       template_vars=None):
+        """
+        Initialize our File operation helper object
+        
+        source_dir
+            Should refer to the directory within the package
+            that contains the templates to be used for the other copy
+            operations. It is assumed that packages will keep all their
+            templates under a hierarchy starting here.
+          
+            This should be an absolute path passed in, for example::
+          
+                FileOp(source_dir=os.path.dirname(__file__) + '/templates')
+        """
+        self.simulate = simulate
+        self.verbose = verbose
+        self.interactive = interactive
+        if template_vars is None:
+            template_vars = {}
+        self.template_vars = template_vars
+        self.source_dir = source_dir
+        self.use_pkg_resources = isinstance(source_dir, tuple)
+    
+    def copy_file(self, template, dest, filename=None, add_py=True, package=True,
+                  template_renderer=None):
+        """
+        Copy a file from the source location to somewhere in the
+        destination.
+        
+        template
+            The filename underneath self.source_dir to copy/process
+        dest
+            The destination directory in the project relative to where
+            this command is being run
+        filename
+            What to name the file in the target project, use the same name
+            as the template if not provided
+        add_py
+            Add a .py extension to all files copied
+        package
+            Whether or not this file is part of a Python package, and any
+            directories created should contain a __init__.py file as well.
+        template_renderer
+            An optional template renderer
+        
+        """
+        if not filename:
+            filename = template.split('/')[0]
+            if filename.endswith('_tmpl'):
+                filename = filename[:-5]
+        base_package, cdir = self.find_dir(dest, package)
+        self.template_vars['base_package'] = base_package
+        content = self.load_content(base_package, cdir, filename, template,
+                                    template_renderer=template_renderer)
+        if add_py:
+            # @@: Why is it a default to add a .py extension? 
+            filename = '%s.py' % filename
+        dest = os.path.join(cdir, filename)
+        self.ensure_file(dest, content, package)
+    
+    def copy_dir(self, template_dir, dest, destname=None, package=True):
+        """
+        Copy a directory recursively, processing any files within it
+        that need to be processed (end in _tmpl).
+        
+        template_dir
+            Directory under self.source_dir to copy/process
+        dest
+            Destination directory into which this directory will be copied
+            to.
+        destname
+            Use this name instead of the original template_dir name for
+            creating the directory
+        package
+            This directory will be a Python package and needs to have a
+            __init__.py file.
+        """
+        # @@: This should actually be implemented
+        raise NotImplementedError
+
+    def load_content(self, base_package, base, name, template,
+                     template_renderer=None):
+        blank = os.path.join(base, name + '.py')
+        read_content = True
+        if not os.path.exists(blank):
+            if self.use_pkg_resources:
+                fullpath = '/'.join([self.source_dir[1], template])
+                content = pkg_resources.resource_string(
+                    self.source_dir[0], fullpath)
+                read_content = False
+                blank = fullpath
+            else:
+                blank = os.path.join(self.source_dir,
+                                     template)
+        if read_content:
+            f = open(blank, 'r')
+            content = f.read()
+            f.close()
+        if blank.endswith('_tmpl'):
+            content = copydir.substitute_content(
+                content, self.template_vars, filename=blank,
+                template_renderer=template_renderer)
+        return content
+
+    def find_dir(self, dirname, package=False):
+        egg_info = pluginlib.find_egg_info_dir(os.getcwd())
+        # @@: Should give error about egg_info when top_level.txt missing
+        f = open(os.path.join(egg_info, 'top_level.txt'))
+        packages = [l.strip() for l in f.readlines()
+                    if l.strip() and not l.strip().startswith('#')]
+        f.close()
+        if not len(packages):
+            raise BadCommand("No top level dir found for %s" % dirname)
+        # @@: This doesn't support deeper servlet directories,
+        # or packages not kept at the top level.
+        base = os.path.dirname(egg_info)
+        possible = []
+        for pkg in packages:
+            d = os.path.join(base, pkg, dirname)
+            if os.path.exists(d):
+                possible.append((pkg, d))
+        if not possible:
+            self.ensure_dir(os.path.join(base, packages[0], dirname),
+                            package=package)
+            return self.find_dir(dirname)
+        if len(possible) > 1:
+            raise BadCommand(
+                "Multiple %s dirs found (%s)" % (dirname, possible))
+        return possible[0]
+    
+    def parse_path_name_args(self, name):
+        """
+        Given the name, assume that the first argument is a path/filename
+        combination. Return the name and dir of this. If the name ends with
+        '.py' that will be erased.
+        
+        Examples:
+            comments             ->          comments, ''
+            admin/comments       ->          comments, 'admin'
+            h/ab/fred            ->          fred, 'h/ab'
+        """
+        if name.endswith('.py'):
+            # Erase extensions
+            name = name[:-3]
+        if '.' in name:
+            # Turn into directory name:
+            name = name.replace('.', os.path.sep)
+        if '/' != os.path.sep:
+            name = name.replace('/', os.path.sep)
+        parts = name.split(os.path.sep)
+        name = parts[-1]
+        if not parts[:-1]:
+            dir = ''
+        elif len(parts[:-1]) == 1:
+            dir = parts[0]
+        else:
+            dir = os.path.join(*parts[:-1])
+        return name, dir
+    
+    def ensure_dir(self, dir, svn_add=True, package=False):
+        """
+        Ensure that the directory exists, creating it if necessary.
+        Respects verbosity and simulation.
+
+        Adds directory to subversion if ``.svn/`` directory exists in
+        parent, and directory was created.
+        
+        package
+            If package is True, any directories created will contain a
+            __init__.py file.
+        
+        """
+        dir = dir.rstrip(os.sep)
+        if not dir:
+            # we either reached the parent-most directory, or we got
+            # a relative directory
+            # @@: Should we make sure we resolve relative directories
+            # first?  Though presumably the current directory always
+            # exists.
+            return
+        if not os.path.exists(dir):
+            self.ensure_dir(os.path.dirname(dir), svn_add=svn_add, package=package)
+            if self.verbose:
+                print 'Creating %s' % self.shorten(dir)
+            if not self.simulate:
+                os.mkdir(dir)
+            if (svn_add and
+                os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))):
+                self.svn_command('add', dir)
+            if package:
+                initfile = os.path.join(dir, '__init__.py')
+                f = open(initfile, 'wb')
+                f.write("#\n")
+                f.close()
+                print 'Creating %s' % self.shorten(initfile)
+                if (svn_add and
+                    os.path.exists(os.path.join(os.path.dirname(dir), '.svn'))):
+                    self.svn_command('add', initfile)
+        else:
+            if self.verbose > 1:
+                print "Directory already exists: %s" % self.shorten(dir)
+
+    def ensure_file(self, filename, content, svn_add=True, package=False):
+        """
+        Ensure a file named ``filename`` exists with the given
+        content.  If ``--interactive`` has been enabled, this will ask
+        the user what to do if a file exists with different content.
+        """
+        global difflib
+        self.ensure_dir(os.path.dirname(filename), svn_add=svn_add, package=package)
+        if not os.path.exists(filename):
+            if self.verbose:
+                print 'Creating %s' % filename
+            if not self.simulate:
+                f = open(filename, 'wb')
+                f.write(content)
+                f.close()
+            if svn_add and os.path.exists(os.path.join(os.path.dirname(filename), '.svn')):
+                self.svn_command('add', filename)
+            return
+        f = open(filename, 'rb')
+        old_content = f.read()
+        f.close()
+        if content == old_content:
+            if self.verbose > 1:
+                print 'File %s matches expected content' % filename
+            return
+        if self.interactive:
+            print 'Warning: file %s does not match expected content' % filename
+            if difflib is None:
+                import difflib
+            diff = difflib.context_diff(
+                content.splitlines(),
+                old_content.splitlines(),
+                'expected ' + filename,
+                filename)
+            print '\n'.join(diff)
+            if self.interactive:
+                while 1:
+                    s = raw_input(
+                        'Overwrite file with new content? [y/N] ').strip().lower()
+                    if not s:
+                        s = 'n'
+                    if s.startswith('y'):
+                        break
+                    if s.startswith('n'):
+                        return
+                    print 'Unknown response; Y or N please'
+            else:
+                return
+                    
+        if self.verbose:
+            print 'Overwriting %s with new content' % filename
+        if not self.simulate:
+            f = open(filename, 'wb')
+            f.write(content)
+            f.close()
+
+    def shorten(self, fn, *paths):
+        """
+        Return a shorted form of the filename (relative to the current
+        directory), typically for displaying in messages.  If
+        ``*paths`` are present, then use os.path.join to create the
+        full filename before shortening.
+        """
+        if paths:
+            fn = os.path.join(fn, *paths)
+        if fn.startswith(os.getcwd()):
+            return fn[len(os.getcwd()):].lstrip(os.path.sep)
+        else:
+            return fn
+
+    _svn_failed = False
+
+    def svn_command(self, *args, **kw):
+        """
+        Run an svn command, but don't raise an exception if it fails.
+        """
+        try:
+            return self.run_command('svn', *args, **kw)
+        except OSError, e:
+            if not self._svn_failed:
+                print 'Unable to run svn command (%s); proceeding anyway' % e
+                self._svn_failed = True
+
+    def run_command(self, cmd, *args, **kw):
+        """
+        Runs the command, respecting verbosity and simulation.
+        Returns stdout, or None if simulating.
+        """
+        cwd = popdefault(kw, 'cwd', os.getcwd())
+        capture_stderr = popdefault(kw, 'capture_stderr', False)
+        expect_returncode = popdefault(kw, 'expect_returncode', False)
+        assert not kw, ("Arguments not expected: %s" % kw)
+        if capture_stderr:
+            stderr_pipe = subprocess.STDOUT
+        else:
+            stderr_pipe = subprocess.PIPE
+        try:
+            proc = subprocess.Popen([cmd] + list(args),
+                                    cwd=cwd,
+                                    stderr=stderr_pipe,
+                                    stdout=subprocess.PIPE)
+        except OSError, e:
+            if e.errno != 2:
+                # File not found
+                raise
+            raise OSError(
+                "The expected executable %s was not found (%s)"
+                % (cmd, e))
+        if self.verbose:
+            print 'Running %s %s' % (cmd, ' '.join(args))
+        if self.simulate:
+            return None
+        stdout, stderr = proc.communicate()
+        if proc.returncode and not expect_returncode:
+            if not self.verbose:
+                print 'Running %s %s' % (cmd, ' '.join(args))
+            print 'Error (exit code: %s)' % proc.returncode
+            if stderr:
+                print stderr
+            raise OSError("Error executing command %s" % cmd)
+        if self.verbose > 2:
+            if stderr:
+                print 'Command error output:'
+                print stderr
+            if stdout:
+                print 'Command output:'
+                print stdout
+        return stdout
+
+def popdefault(dict, name, default=None):
+    if name not in dict:
+        return default
+    else:
+        v = dict[name]
+        del dict[name]
+        return v
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/flup_server.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/flup_server.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/flup_server.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,119 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+from paste.deploy.converters import aslist, asbool
+from paste.script.serve import ensure_port_cleanup
+import warnings
+
+def warn(name, stacklevel=3):
+    # Deprecated 2007-12-17
+    warnings.warn(
+        'The egg:PasteScript#flup_%s entry point is deprecated; please use egg:Flup#%s instead'
+        % (name, name),
+        DeprecationWarning, stacklevel=stacklevel)
+
+def run_ajp_thread(wsgi_app, global_conf,
+                   scriptName='', host='localhost', port='8009',
+                   allowedServers='127.0.0.1'):
+    import flup.server.ajp
+    warn('ajp_thread')
+    addr = (host, int(port))
+    ensure_port_cleanup([addr])
+    s = flup.server.ajp.WSGIServer(
+        wsgi_app,
+        scriptName=scriptName,
+        bindAddress=addr,
+        allowedServers=aslist(allowedServers),
+        )
+    s.run()
+    
+def run_ajp_fork(wsgi_app, global_conf,
+                 scriptName='', host='localhost', port='8009',
+                 allowedServers='127.0.0.1'):
+    import flup.server.ajp_fork
+    warn('ajp_fork')
+    addr = (host, int(port))
+    ensure_port_cleanup([addr])
+    s = flup.server.ajp_fork.WSGIServer(
+        wsgi_app,
+        scriptName=scriptName,
+        bindAddress=addr,
+        allowedServers=aslist(allowedServers),
+        )
+    s.run()
+
+def run_fcgi_thread(wsgi_app, global_conf,
+                    host=None, port=None,
+                    socket=None, umask=None,
+                    multiplexed=False):
+    import flup.server.fcgi
+    warn('fcgi_thread')
+    if socket:
+        assert host is None and port is None
+        sock = socket
+    elif host:
+        assert host is not None and port is not None
+        sock = (host, int(port))
+        ensure_port_cleanup([sock])
+    else:
+        sock = None
+    if umask is not None:
+        umask = int(umask)
+    s = flup.server.fcgi.WSGIServer(
+        wsgi_app,
+        bindAddress=sock, umask=umask,
+        multiplexed=asbool(multiplexed))
+    s.run()
+
+def run_fcgi_fork(wsgi_app, global_conf,
+                  host=None, port=None,
+                  socket=None, umask=None,
+                  multiplexed=False):
+    import flup.server.fcgi_fork
+    warn('fcgi_fork')
+    if socket:
+        assert host is None and port is None
+        sock = socket
+    elif host:
+        assert host is not None and port is not None
+        sock = (host, int(port))
+        ensure_port_cleanup([sock])
+    else:
+        sock = None
+    if umask is not None:
+        umask = int(umask)
+    s = flup.server.fcgi_fork.WSGIServer(
+        wsgi_app,
+        bindAddress=sock, umask=umask,
+        multiplexed=asbool(multiplexed))
+    s.run()
+
+def run_scgi_thread(wsgi_app, global_conf,
+                    scriptName='', host='localhost', port='4000',
+                    allowedServers='127.0.0.1'):
+    import flup.server.scgi
+    warn('scgi_thread')
+    addr = (host, int(port))
+    ensure_port_cleanup([addr])
+    s = flup.server.scgi.WSGIServer(
+        wsgi_app,
+        scriptName=scriptName,
+        bindAddress=addr,
+        allowedServers=aslist(allowedServers),
+        )
+    s.run()
+
+def run_scgi_fork(wsgi_app, global_conf,
+                  scriptName='', host='localhost', port='4000',
+                  allowedServers='127.0.0.1'):
+    import flup.server.scgi_fork
+    warn('scgi_fork')
+    addr = (host, int(port))
+    ensure_port_cleanup([addr])
+    s = flup.server.scgi_fork.WSGIServer(
+        wsgi_app,
+        scriptName=scriptName,
+        bindAddress=addr,
+        allowedServers=aslist(allowedServers),
+        )
+    s.run()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/grep.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/grep.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/grep.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,168 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import py_compile
+import marshal
+import inspect
+import re
+from command import Command
+import pluginlib
+
+class GrepCommand(Command):
+
+    summary = 'Search project for symbol'
+    usage = 'SYMBOL'
+
+    max_args = 1
+    min_args = 1
+
+    bad_names = ['.svn', 'CVS', '_darcs']
+
+    parser = Command.standard_parser()
+
+    parser.add_option(
+        '-x', '--exclude-module',
+        metavar="module.name",
+        dest="exclude_modules",
+        action="append",
+        help="Don't search the given module")
+
+    parser.add_option(
+        '-t', '--add-type',
+        metavar=".ext",
+        dest="add_types",
+        action="append",
+        help="Search the given type of files")
+
+    def command(self):
+        self.exclude_modules = self.options.exclude_modules or []
+        self.add_types = self.options.add_types or []
+        self.symbol = self.args[0]
+        self.basedir = os.path.dirname(
+            pluginlib.find_egg_info_dir(os.getcwd()))
+        if self.verbose:
+            print "Searching in %s" % self.basedir
+        self.total_files = 0
+        self.search_dir(self.basedir)
+        if self.verbose > 1:
+            print "Searched %i files" % self.total_files
+
+    def search_dir(self, dir):
+        names = os.listdir(dir)
+        names.sort()
+        dirs = []
+        for name in names:
+            full = os.path.join(dir, name)
+            if name in self.bad_names:
+                continue
+            if os.path.isdir(full):
+                # Breadth-first; we'll do this later...
+                dirs.append(full)
+                continue
+            for t in self.add_types:
+                if name.lower().endswith(t.lower()):
+                    self.search_text(full)
+            if not name.endswith('.py'):
+                continue
+            self.search_file(full)
+        for dir in dirs:
+            self.search_dir(dir)
+
+    def search_file(self, filename):
+        self.total_files += 1
+        if not filename.endswith('.py'):
+            self.search_text(filename)
+            return
+        pyc = filename[:-2]+'pyc'
+        if not os.path.exists(pyc):
+            py_compile.compile(filename)
+        if not os.path.exists(pyc):
+            # Invalid syntax...
+            self.search_text(filename, as_module=True)
+            return
+        f = open(pyc, 'rb')
+        # .pyc Header:
+        f.read(8)
+        code = marshal.load(f)
+        f.close()
+        self.search_code(code, filename, [])
+        
+    def search_code(self, code, filename, path):
+        if code.co_name != "?":
+            path = path + [code.co_name]
+        else:
+            path = path
+        sym = self.symbol
+        if sym in code.co_varnames:
+            self.found(code, filename, path)
+        elif sym in code.co_names:
+            self.found(code, filename, path)
+        for const in code.co_consts:
+            if const == sym:
+                self.found(code, filename, path)
+            if inspect.iscode(const):
+                if not const.co_filename == filename:
+                    continue
+                self.search_code(const, filename, path)
+
+    def search_text(self, filename, as_module=False):
+        f = open(filename, 'rb')
+        lineno = 0
+        any = False
+        for line in f:
+            lineno += 1
+            if line.find(self.symbol) != -1:
+                if not any:
+                    any = True
+                    if as_module:
+                        print '%s (unloadable)' % self.module_name(filename)
+                    else:
+                        print self.relative_name(filename)
+                print '  %3i  %s' % (lineno, line)
+                if not self.verbose:
+                    break
+        f.close()
+                
+    def found(self, code, filename, path):
+        print self.display(filename, path)
+        self.find_occurance(code)
+
+    def find_occurance(self, code):
+        f = open(code.co_filename, 'rb')
+        lineno = 0
+        for index, line in zip(xrange(code.co_firstlineno), f):
+            lineno += 1
+            pass
+        lines = []
+        first_indent = None
+        for line in f:
+            lineno += 1
+            if line.find(self.symbol) != -1:
+                this_indent = len(re.match(r'^[ \t]*', line).group(0))
+                if first_indent is None:
+                    first_indent = this_indent
+                else:
+                    if this_indent < first_indent:
+                        break
+                print '  %3i  %s' % (lineno, line[first_indent:].rstrip())
+                if not self.verbose:
+                    break
+
+    def module_name(self, filename):
+        assert filename, startswith(self.basedir)
+        mod = filename[len(self.basedir):].strip('/').strip(os.path.sep)
+        mod = os.path.splitext(mod)[0]
+        mod = mod.replace(os.path.sep, '.').replace('/', '.')
+        return mod
+
+    def relative_name(self, filename):
+        assert filename, startswith(self.basedir)
+        name = filename[len(self.basedir):].strip('/').strip(os.path.sep)
+        return name
+
+    def display(self, filename, path):
+        parts = '.'.join(path)
+        if parts:
+            parts = ':' + parts
+        return self.module_name(filename) + parts
+        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/help.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/help.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/help.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,60 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+from command import Command, get_commands
+from command import parser as base_parser
+
+class HelpCommand(Command):
+
+    summary = "Display help"
+    usage = '[COMMAND]'
+
+    max_args = 1
+
+    parser = Command.standard_parser()
+
+    def command(self):
+        if not self.args:
+            self.generic_help()
+            return
+
+        name = self.args[0]
+        commands = get_commands()
+        if name not in commands:
+            print 'No such command: %s' % name
+            self.generic_help()
+            return
+
+        command = commands[name].load()
+        runner = command(name)
+        runner.run(['-h'])
+        
+    def generic_help(self):
+        base_parser.print_help()
+        print
+        commands_grouped = {}
+        commands = get_commands()
+        longest = max([len(n) for n in commands.keys()])
+        for name, command in commands.items():
+            try:
+                command = command.load()
+            except Exception, e:
+                print 'Cannot load command %s: %s' % (name, e)
+                continue
+            if getattr(command, 'hidden', False):
+                continue
+            commands_grouped.setdefault(
+                command.group_name, []).append((name, command))
+        commands_grouped = commands_grouped.items()
+        commands_grouped.sort()
+        print 'Commands:'
+        for group, commands in commands_grouped:
+            if group:
+                print group + ':'
+            commands.sort()
+            for name, command in commands:
+                print '  %s  %s' % (self.pad(name, length=longest),
+                                    command.summary)
+                #if command.description:
+                #    print self.indent_block(command.description, 4)
+            print
+        

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/interfaces.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/interfaces.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/interfaces.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,49 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+class IAppInstall(object):
+
+    """
+    The interface for objects in the entry point group
+    ``paste.app_install``
+    """
+
+    def __init__(distribution, entry_group, entry_name):
+        """
+        An object representing a specific application (the
+        distribution is a pkg_resource.Distribution object), for the
+        given entry point name in the given group.  Right now the only
+        group used for this is ``'paste.app_factory'``.
+        """
+                 
+    def description(sys_config):
+        """
+        Return a text description of the application and its
+        configuration.  ``sys_config`` is a dictionary representing
+        the system configuration, and can be used for giving more
+        explicit defaults if the application preparation uses the
+        system configuration.  It may be None, in which case the
+        description should be more abstract.
+
+        Applications are free to ignore ``sys_config``.
+        """
+
+    def write_config(command, filename, sys_config):
+        """
+        Write a fresh config file to ``filename``.  ``command`` is a
+        ``paste.script.command.Command`` object, and should be used
+        for the actual operations.  It handles things like simulation
+        and verbosity.
+
+        ``sys_config`` is (if given) a dictionary of system-wide
+        configuration options.
+        """
+
+    def setup_config(command, config_filename,
+                     config_section, sys_config):
+        """
+        Set up the application, using ``command`` (to ensure simulate,
+        etc).  The application is described by the configuration file
+        ``config_filename``.  ``sys_config`` is the system
+        configuration (though probably the values from it should have
+        already been encorporated into the configuration file).
+        """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/+package+/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/+package+/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/+package+/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.cfg
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.cfg	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.cfg	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+[egg_info]
+tag_build = dev
+tag_svn_revision = true

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/paster-templates/basic_package/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,26 @@
+from setuptools import setup, find_packages
+import sys, os
+
+version = {{repr(version or "0.0")}}
+
+setup(name={{repr(project)}},
+      version=version,
+      description="{{description or ''}}",
+      long_description="""\
+{{long_description or ''}}""",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords={{repr(keywords or '')}},
+      author={{repr(author or '')}},
+      author_email={{repr(author_email or '')}},
+      url={{repr(url or '')}},
+      license={{repr(license_name or '')}},
+      packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+      include_package_data=True,
+      zip_safe={{repr(bool(zip_safe or False))}},
+      install_requires=[
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/pluginlib.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/pluginlib.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/pluginlib.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,134 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import pkg_resources
+
+def add_plugin(egg_info_dir, plugin_name):
+    """
+    Add the plugin to the given distribution (or spec), in
+    .egg-info/paster_plugins.txt
+    """
+    fn = os.path.join(egg_info_dir, 'paster_plugins.txt')
+    if not os.path.exists(fn):
+        lines = []
+    else:
+        f = open(fn)
+        lines = [l.strip() for l in f.readlines() if l.strip()]
+        f.close()
+    if plugin_name in lines:
+        # Nothing to do
+        return
+    lines.append(plugin_name)
+    if not os.path.exists(os.path.dirname(fn)):
+        os.makedirs(os.path.dirname(fn))
+    f = open(fn, 'w')
+    for line in lines:
+        f.write(line)
+        f.write('\n')
+    f.close()
+
+def remove_plugin(egg_info_dir, plugin_name):
+    """
+    Remove the plugin to the given distribution (or spec), in
+    .egg-info/paster_plugins.txt.  Raises ValueError if the
+    plugin is not in the file.
+    """
+    fn = os.path.join(egg_info_dir, 'paster_plugins.txt')
+    if not os.path.exists(fn):
+        raise ValueError(
+            "Cannot remove plugin from %s; file does not exist"
+            % fn)
+    f = open(fn)
+    lines = [l.strip() for l in f.readlines() if l.strip()]
+    f.close()
+    for line in lines:
+        # What about version specs?
+        if line.lower() == plugin_name.lower():
+            break
+    else:
+        raise ValueError(
+            "Plugin %s not found in file %s (from: %s)"
+            % (plugin_name, fn, lines))
+    lines.remove(line)
+    print 'writing', lines
+    f = open(fn, 'w')
+    for line in lines:
+        f.write(line)
+        f.write('\n')
+    f.close()
+    
+def find_egg_info_dir(dir):
+    while 1:
+        try:
+            filenames = os.listdir(dir)
+        except OSError:
+            # Probably permission denied or something
+            return None
+        for fn in filenames:
+            if fn.endswith('.egg-info'):
+                return os.path.join(dir, fn)
+        parent = os.path.dirname(dir)
+        if parent == dir:
+            # Top-most directory
+            return None
+        dir = parent
+
+def resolve_plugins(plugin_list):
+    found = []
+    while plugin_list:
+        plugin = plugin_list.pop()
+        try:
+            pkg_resources.require(plugin)
+        except pkg_resources.DistributionNotFound, e:
+            msg = '%sNot Found%s: %s (did you run python setup.py develop?)'
+            if str(e) != plugin:
+                e.args = (msg % (str(e) + ': ', ' for', plugin)),
+            else:
+                e.args = (msg % ('', '', plugin)),
+            raise
+        found.append(plugin)
+        dist = get_distro(plugin)
+        if dist.has_metadata('paster_plugins.txt'):
+            data = dist.get_metadata('paster_plugins.txt')
+            for add_plugin in parse_lines(data):
+                if add_plugin not in found:
+                    plugin_list.append(add_plugin)
+    return map(get_distro, found)
+
+def get_distro(spec):
+    return pkg_resources.get_distribution(spec)
+
+def load_commands_from_plugins(plugins):
+    commands = {}
+    for plugin in plugins:
+        commands.update(pkg_resources.get_entry_map(
+            plugin, group='paste.paster_command'))
+    return commands
+
+def parse_lines(data):
+    result = []
+    for line in data.splitlines():
+        line = line.strip()
+        if line and not line.startswith('#'):
+            result.append(line)
+    return result
+
+def load_global_commands():
+    commands = {}
+    for p in pkg_resources.iter_entry_points('paste.global_paster_command'):
+        commands[p.name] = p
+    return commands
+
+def egg_name(dist_name):
+    return pkg_resources.to_filename(pkg_resources.safe_name(dist_name))
+
+def egg_info_dir(base_dir, dist_name):
+    all = []
+    for dir_extension in ['.'] + os.listdir(base_dir):
+        full = os.path.join(base_dir, dir_extension,
+                            egg_name(dist_name)+'.egg-info')
+        all.append(full)
+        if os.path.exists(full):
+            return full
+    raise IOError("No egg-info directory found (looked in %s)"
+                  % ', '.join(all))

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/request.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/request.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/request.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,189 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import os
+import re
+import sys
+import urlparse
+import urllib
+from command import Command, BadCommand
+from paste.deploy import loadapp, loadserver
+from paste.wsgilib import raw_interactive
+
+class RequestCommand(Command):
+
+    min_args = 2
+    usage = 'CONFIG_FILE URL [OPTIONS/ARGUMENTS]'
+    takes_config_file = 1
+    summary = "Run a request for the described application"
+    description = """\
+    This command makes an artifical request to a web application that
+    uses a paste.deploy configuration file for the server and
+    application.
+
+    Use 'paster request config.ini /url' to request /url.  Use
+    'paster post config.ini /url < data' to do a POST with the given
+    request body.
+
+    If the URL is relative (doesn't begin with /) it is interpreted as
+    relative to /.command/.  The variable environ['paste.command_request']
+    will be set to True in the request, so your application can distinguish
+    these calls from normal requests.
+
+    Note that you can pass options besides the options listed here; any unknown
+    options will be passed to the application in environ['QUERY_STRING'].
+    """
+    
+    parser = Command.standard_parser(quiet=True)
+    parser.add_option('-n', '--app-name',
+                      dest='app_name',
+                      metavar='NAME',
+                      help="Load the named application (default main)")
+    parser.add_option('--config-var',
+                      dest='config_vars',
+                      metavar='NAME:VALUE',
+                      action='append',
+                      help="Variable to make available in the config for %()s substitution "
+                      "(you can use this option multiple times)")
+    parser.add_option('--header',
+                      dest='headers',
+                      metavar='NAME:VALUE',
+                      action='append',
+                      help="Header to add to request (you can use this option multiple times)")
+    parser.add_option('--display-headers',
+                      dest='display_headers',
+                      action='store_true',
+                      help='Display headers before the response body')
+
+    ARG_OPTIONS = ['-n', '--app-name', '--config-var', '--header']
+    OTHER_OPTIONS = ['--display-headers']
+    
+    ## FIXME: some kind of verbosity?
+    ## FIXME: allow other methods than POST and GET?
+
+    _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
+
+    def command(self):
+        vars = {}
+        app_spec = self.args[0]
+        url = self.args[1]
+        url = urlparse.urljoin('/.command/', url)
+        if self.options.config_vars:
+            for item in self.option.config_vars:
+                if ':' not in item:
+                    raise BadCommand(
+                        "Bad option, should be name:value : --config-var=%s" % item)
+                name, value = item.split(':', 1)
+                vars[name] = value
+        headers = {}
+        if self.options.headers:
+            for item in self.options.headers:
+                if ':' not in item:
+                    raise BadCommand(
+                        "Bad option, should be name:value : --header=%s" % item)
+                name, value = item.split(':', 1)
+                headers[name] = value.strip()
+        if not self._scheme_re.search(app_spec):
+            app_spec = 'config:'+app_spec
+        if self.options.app_name:
+            if '#' in app_spec:
+                app_spec = app_spec.split('#', 1)[0]
+            app_spec = app_spec + '#' + options.app_name
+        app = loadapp(app_spec, relative_to=os.getcwd(), global_conf=vars)
+        if self.command_name.lower() == 'post':
+            request_method = 'POST'
+        else:
+            request_method = 'GET'
+        qs = []
+        for item in self.args[2:]:
+            if '=' in item:
+                item = urllib.quote(item.split('=', 1)[0]) + '=' + urllib.quote(item.split('=', 1)[1])
+            else:
+                item = urllib.quote(item)
+            qs.append(item)
+        qs = '&'.join(qs)
+        
+        environ = {
+            'REQUEST_METHOD': request_method,
+            ## FIXME: shouldn't be static (an option?):
+            'CONTENT_TYPE': 'text/plain',
+            'wsgi.run_once': True,
+            'wsgi.multithread': False,
+            'wsgi.multiprocess': False,
+            'wsgi.errors': sys.stderr,
+            'QUERY_STRING': qs,
+            'HTTP_ACCEPT': 'text/plain;q=1.0, */*;q=0.1',
+            'paste.command_request': True,
+            }
+        if request_method == 'POST':
+            environ['wsgi.input'] = sys.stdin
+            environ['CONTENT_LENGTH'] = '-1'
+        for name, value in headers.items():
+            if name.lower() == 'content-type':
+                name = 'CONTENT_TYPE'
+            else:
+                name = 'HTTP_'+name.upper().replace('-', '_')
+            environ[name] = value
+            
+        status, headers, output, errors = raw_interactive(app, url, **environ)
+        assert not errors, "errors should be printed directly to sys.stderr"
+        if self.options.display_headers:
+            for name, value in headers:
+                sys.stdout.write('%s: %s\n' % (name, value))
+            sys.stdout.write('\n')
+        sys.stdout.write(output)
+        sys.stdout.flush()
+        status_int = int(status.split()[0])
+        if status_int != 200:
+            return status_int
+
+    def parse_args(self, args):
+        if args == ['-h']:
+            Command.parse_args(self, args)
+            return
+        # These are the arguments parsed normally:
+        normal_args = []
+        # And these are arguments passed to the URL:
+        extra_args = []
+        # This keeps track of whether we have the two required positional arguments:
+        pos_args = 0
+        while args:
+            start = args[0]
+            if not start.startswith('-'):
+                if pos_args < 2:
+                    pos_args += 1
+                    normal_args.append(start)
+                    args.pop(0)
+                    continue
+                else:
+                    normal_args.append(start)
+                    args.pop(0)
+                    continue
+            else:
+                found = False
+                for option in self.ARG_OPTIONS:
+                    if start == option:
+                        normal_args.append(start)
+                        args.pop(0)
+                        if not args:
+                            raise BadCommand(
+                                "Option %s takes an argument" % option)
+                        normal_args.append(args.pop(0))
+                        found = True
+                        break
+                    elif start.startswith(option+'='):
+                        normal_args.append(start)
+                        args.pop(0)
+                        found = True
+                        break
+                if found:
+                    continue
+                if start in self.OTHER_OPTIONS:
+                    normal_args.append(start)
+                    args.pop(0)
+                    continue
+                extra_args.append(start)
+                args.pop(0)
+        Command.parse_args(self, normal_args)
+        # Add the extra arguments back in:
+        self.args = self.args + extra_args
+            

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/serve.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,643 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# @@: This should be moved to paste.deploy
+# For discussion of daemonizing:
+#   http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/278731
+# Code taken also from QP:
+#   http://www.mems-exchange.org/software/qp/
+#   From lib/site.py
+import re
+import os
+import errno
+import sys
+import time
+try:
+    import subprocess
+except ImportError:
+    from paste.util import subprocess24 as subprocess
+from command import Command, BadCommand
+from paste.deploy import loadapp, loadserver
+import threading
+import atexit
+import logging
+import ConfigParser
+
+MAXFD = 1024
+
+jython = sys.platform.startswith('java')
+
+class DaemonizeException(Exception):
+    pass
+
+
+class ServeCommand(Command):
+
+    min_args = 0
+    usage = 'CONFIG_FILE [start|stop|restart|status] [var=value]'
+    takes_config_file = 1
+    summary = "Serve the described application"
+    description = """\
+    This command serves a web application that uses a paste.deploy
+    configuration file for the server and application.  
+    
+    If start/stop/restart is given, then --daemon is implied, and it will
+    start (normal operation), stop (--stop-daemon), or do both.
+
+    You can also include variable assignments like 'http_port=8080'
+    and then use %(http_port)s in your config files.
+    """
+    
+    # used by subclasses that configure apps and servers differently
+    requires_config_file = True
+
+    parser = Command.standard_parser(quiet=True)
+    parser.add_option('-n', '--app-name',
+                      dest='app_name',
+                      metavar='NAME',
+                      help="Load the named application (default main)")
+    parser.add_option('-s', '--server',
+                      dest='server',
+                      metavar='SERVER_TYPE',
+                      help="Use the named server.")
+    parser.add_option('--server-name',
+                      dest='server_name',
+                      metavar='SECTION_NAME',
+                      help="Use the named server as defined in the configuration file (default: main)")
+    if hasattr(os, 'fork'):
+        parser.add_option('--daemon',
+                          dest="daemon",
+                          action="store_true",
+                          help="Run in daemon (background) mode")
+    parser.add_option('--pid-file',
+                      dest='pid_file',
+                      metavar='FILENAME',
+                      help="Save PID to file (default to paster.pid if running in daemon mode)")
+    parser.add_option('--log-file',
+                      dest='log_file',
+                      metavar='LOG_FILE',
+                      help="Save output to the given log file (redirects stdout)")
+    parser.add_option('--reload',
+                      dest='reload',
+                      action='store_true',
+                      help="Use auto-restart file monitor")
+    parser.add_option('--reload-interval',
+                      dest='reload_interval',
+                      default=1,
+                      help="Seconds between checking files (low number can cause significant CPU usage)")
+    parser.add_option('--monitor-restart',
+                      dest='monitor_restart',
+                      action='store_true',
+                      help="Auto-restart server if it dies")
+    parser.add_option('--status',
+                      action='store_true',
+                      dest='show_status',
+                      help="Show the status of the (presumably daemonized) server")
+
+
+    if hasattr(os, 'setuid'):
+        # I don't think these are available on Windows
+        parser.add_option('--user',
+                          dest='set_user',
+                          metavar="USERNAME",
+                          help="Set the user (usually only possible when run as root)")
+        parser.add_option('--group',
+                          dest='set_group',
+                          metavar="GROUP",
+                          help="Set the group (usually only possible when run as root)")
+
+    parser.add_option('--stop-daemon',
+                      dest='stop_daemon',
+                      action='store_true',
+                      help='Stop a daemonized server (given a PID file, or default paster.pid file)')
+
+    if jython:
+        parser.add_option('--disable-jython-reloader',
+                          action='store_true',
+                          dest='disable_jython_reloader',
+                          help="Disable the Jython reloader")
+
+
+    _scheme_re = re.compile(r'^[a-z][a-z]+:', re.I)
+
+    default_verbosity = 1
+
+    _reloader_environ_key = 'PYTHON_RELOADER_SHOULD_RUN'
+    _monitor_environ_key = 'PASTE_MONITOR_SHOULD_RUN'
+
+    possible_subcommands = ('start', 'stop', 'restart', 'status')
+    def command(self):
+        if self.options.stop_daemon:
+            return self.stop_daemon()
+
+        if not hasattr(self.options, 'set_user'):
+            # Windows case:
+            self.options.set_user = self.options.set_group = None
+        # @@: Is this the right stage to set the user at?
+        self.change_user_group(
+            self.options.set_user, self.options.set_group)
+
+        if self.requires_config_file:
+            if not self.args:
+                raise BadCommand('You must give a config file')
+            app_spec = self.args[0]
+            if (len(self.args) > 1
+                and self.args[1] in self.possible_subcommands):
+                cmd = self.args[1]
+                restvars = self.args[2:]
+            else:
+                cmd = None
+                restvars = self.args[1:]
+        else:
+            app_spec = ""
+            if (self.args
+                and self.args[0] in self.possible_subcommands):
+                cmd = self.args[0]
+                restvars = self.args[1:]
+            else:
+                cmd = None
+                restvars = self.args[:]
+
+        jython_monitor = False
+        if self.options.reload:
+            if jython and not self.options.disable_jython_reloader:
+                # JythonMonitor raises the special SystemRestart
+                # exception that'll cause the Jython interpreter to
+                # reload in the existing Java process (avoiding
+                # subprocess startup time)
+                try:
+                    from paste.reloader import JythonMonitor
+                except ImportError:
+                    pass
+                else:
+                    jython_monitor = JythonMonitor(poll_interval=int(
+                            self.options.reload_interval))
+                    if self.requires_config_file:
+                        jython_monitor.watch_file(self.args[0])
+
+            if not jython_monitor:
+                if os.environ.get(self._reloader_environ_key):
+                    from paste import reloader
+                    if self.verbose > 1:
+                        print 'Running reloading file monitor'
+                    reloader.install(int(self.options.reload_interval))
+                    if self.requires_config_file:
+                        reloader.watch_file(self.args[0])
+                else:
+                    return self.restart_with_reloader()
+
+        if cmd not in (None, 'start', 'stop', 'restart', 'status'):
+            raise BadCommand(
+                'Error: must give start|stop|restart (not %s)' % cmd)
+
+        if cmd == 'status' or self.options.show_status:
+            return self.show_status()
+
+        if cmd == 'restart' or cmd == 'stop':
+            result = self.stop_daemon()
+            if result:
+                if cmd == 'restart':
+                    print "Could not stop daemon; aborting"
+                else:
+                    print "Could not stop daemon"
+                return result
+            if cmd == 'stop':
+                return result
+
+        app_name = self.options.app_name
+        vars = self.parse_vars(restvars)
+        if not self._scheme_re.search(app_spec):
+            app_spec = 'config:' + app_spec
+        server_name = self.options.server_name
+        if self.options.server:
+            server_spec = 'egg:PasteScript'
+            assert server_name is None
+            server_name = self.options.server
+        else:
+            server_spec = app_spec
+        base = os.getcwd()
+
+        if getattr(self.options, 'daemon', False):
+            if not self.options.pid_file:
+                self.options.pid_file = 'paster.pid'
+            if not self.options.log_file:
+                self.options.log_file = 'paster.log'
+
+        # Ensure the log file is writeable
+        if self.options.log_file:
+            try:
+                writeable_log_file = open(self.options.log_file, 'a')
+            except IOError, ioe:
+                msg = 'Error: Unable to write to log file: %s' % ioe
+                raise BadCommand(msg)
+            writeable_log_file.close()
+
+        # Ensure the pid file is writeable
+        if self.options.pid_file:
+            try:
+                writeable_pid_file = open(self.options.pid_file, 'a')
+            except IOError, ioe:
+                msg = 'Error: Unable to write to pid file: %s' % ioe
+                raise BadCommand(msg)
+            writeable_pid_file.close()
+
+        if getattr(self.options, 'daemon', False):
+            try:
+                self.daemonize()
+            except DaemonizeException, ex:
+                if self.verbose > 0:
+                    print str(ex)
+                return
+
+        if (self.options.monitor_restart
+            and not os.environ.get(self._monitor_environ_key)):
+            return self.restart_with_monitor()
+
+        if self.options.pid_file:
+            self.record_pid(self.options.pid_file)
+
+        if self.options.log_file:
+            stdout_log = LazyWriter(self.options.log_file, 'a')
+            sys.stdout = stdout_log
+            sys.stderr = stdout_log
+            logging.basicConfig(stream=stdout_log)
+
+        log_fn = app_spec
+        if log_fn.startswith('config:'):
+            log_fn = app_spec[len('config:'):]
+        elif log_fn.startswith('egg:'):
+            log_fn = None
+        if log_fn:
+            log_fn = os.path.join(base, log_fn)
+            self.logging_file_config(log_fn)
+
+        server = self.loadserver(server_spec, name=server_name,
+                                 relative_to=base, global_conf=vars)
+        app = self.loadapp(app_spec, name=app_name,
+                           relative_to=base, global_conf=vars)
+
+        if self.verbose > 0:
+            if hasattr(os, 'getpid'):
+                msg = 'Starting server in PID %i.' % os.getpid()
+            else:
+                msg = 'Starting server.'
+            print msg
+
+        def serve():
+            try:
+                server(app)
+            except (SystemExit, KeyboardInterrupt), e:
+                if self.verbose > 1:
+                    raise
+                if str(e):
+                    msg = ' '+str(e)
+                else:
+                    msg = ''
+                print 'Exiting%s (-v to see traceback)' % msg
+
+        if jython_monitor:
+            # JythonMonitor has to be ran from the main thread
+            threading.Thread(target=serve).start()
+            print 'Starting Jython file monitor'
+            jython_monitor.periodic_reload()
+        else:
+            serve()
+    
+    def loadserver(self, server_spec, name, relative_to, **kw):
+            return loadserver(
+                server_spec, name=name,
+                relative_to=relative_to, **kw)
+    
+    def loadapp(self, app_spec, name, relative_to, **kw):
+            return loadapp(
+                app_spec, name=name, relative_to=relative_to,
+                **kw)
+
+    def daemonize(self):
+        pid = live_pidfile(self.options.pid_file)
+        if pid:
+            raise DaemonizeException(
+                "Daemon is already running (PID: %s from PID file %s)"
+                % (pid, self.options.pid_file))
+
+        if self.verbose > 0:
+            print 'Entering daemon mode'
+        pid = os.fork()
+        if pid:
+            # The forked process also has a handle on resources, so we
+            # *don't* want proper termination of the process, we just
+            # want to exit quick (which os._exit() does)
+            os._exit(0)
+        # Make this the session leader
+        os.setsid()
+        # Fork again for good measure!
+        pid = os.fork()
+        if pid:
+            os._exit(0)
+
+        # @@: Should we set the umask and cwd now?
+
+        import resource  # Resource usage information.
+        maxfd = resource.getrlimit(resource.RLIMIT_NOFILE)[1]
+        if (maxfd == resource.RLIM_INFINITY):
+            maxfd = MAXFD
+        # Iterate through and close all file descriptors.
+        for fd in range(0, maxfd):
+            try:
+                os.close(fd)
+            except OSError:  # ERROR, fd wasn't open to begin with (ignored)
+                pass
+
+        if (hasattr(os, "devnull")):
+            REDIRECT_TO = os.devnull
+        else:
+            REDIRECT_TO = "/dev/null"
+        os.open(REDIRECT_TO, os.O_RDWR)  # standard input (0)
+        # Duplicate standard input to standard output and standard error.
+        os.dup2(0, 1)  # standard output (1)
+        os.dup2(0, 2)  # standard error (2)
+        
+    def record_pid(self, pid_file):
+        pid = os.getpid()
+        if self.verbose > 1:
+            print 'Writing PID %s to %s' % (pid, pid_file)
+        f = open(pid_file, 'w')
+        f.write(str(pid))
+        f.close()
+        atexit.register(_remove_pid_file, pid, pid_file, self.verbose)
+
+    def stop_daemon(self):
+        pid_file = self.options.pid_file or 'paster.pid'
+        if not os.path.exists(pid_file):
+            print 'No PID file exists in %s' % pid_file
+            return 1
+        pid = read_pidfile(pid_file)
+        if not pid:
+            print "Not a valid PID file in %s" % pid_file
+            return 1
+        pid = live_pidfile(pid_file)
+        if not pid:
+            print "PID in %s is not valid (deleting)" % pid_file
+            try:
+                os.unlink(pid_file)
+            except (OSError, IOError), e:
+                print "Could not delete: %s" % e
+                return 2
+            return 1
+        for j in range(10):
+            if not live_pidfile(pid_file):
+                break
+            import signal
+            os.kill(pid, signal.SIGTERM)
+            time.sleep(1)
+        else:
+            print "failed to kill web process %s" % pid
+            return 3
+        if os.path.exists(pid_file):
+            os.unlink(pid_file)
+        return 0
+
+    def show_status(self):
+        pid_file = self.options.pid_file or 'paster.pid'
+        if not os.path.exists(pid_file):
+            print 'No PID file %s' % pid_file
+            return 1
+        pid = read_pidfile(pid_file)
+        if not pid:
+            print 'No PID in file %s' % pid_file
+            return 1
+        pid = live_pidfile(pid_file)
+        if not pid:
+            print 'PID %s in %s is not running' % (pid, pid_file)
+            return 1
+        print 'Server running in PID %s' % pid
+        return 0
+
+    def restart_with_reloader(self):
+        self.restart_with_monitor(reloader=True)
+
+    def restart_with_monitor(self, reloader=False):
+        if self.verbose > 0:
+            if reloader:
+                print 'Starting subprocess with file monitor'
+            else:
+                print 'Starting subprocess with monitor parent'
+        while 1:
+            args = [self.quote_first_command_arg(sys.executable)] + sys.argv
+            new_environ = os.environ.copy()
+            if reloader:
+                new_environ[self._reloader_environ_key] = 'true'
+            else:
+                new_environ[self._monitor_environ_key] = 'true'
+            proc = None
+            try:
+                try:
+                    _turn_sigterm_into_systemexit()
+                    proc = subprocess.Popen(args, env=new_environ)
+                    exit_code = proc.wait()
+                    proc = None
+                except KeyboardInterrupt:
+                    print '^C caught in monitor process'
+                    if self.verbose > 1:
+                        raise
+                    return 1
+            finally:
+                if (proc is not None
+                    and hasattr(os, 'kill')):
+                    import signal
+                    try:
+                        os.kill(proc.pid, signal.SIGTERM)
+                    except (OSError, IOError):
+                        pass
+                
+            if reloader:
+                # Reloader always exits with code 3; but if we are
+                # a monitor, any exit code will restart
+                if exit_code != 3:
+                    return exit_code
+            if self.verbose > 0:
+                print '-'*20, 'Restarting', '-'*20
+
+    def change_user_group(self, user, group):
+        if not user and not group:
+            return
+        import pwd, grp
+        uid = gid = None
+        if group:
+            try:
+                gid = int(group)
+                group = grp.getgrgid(gid).gr_name
+            except ValueError:
+                import grp
+                try:
+                    entry = grp.getgrnam(group)
+                except KeyError:
+                    raise BadCommand(
+                        "Bad group: %r; no such group exists" % group)
+                gid = entry.gr_gid
+        try:
+            uid = int(user)
+            user = pwd.getpwuid(uid).pw_name
+        except ValueError:
+            try:
+                entry = pwd.getpwnam(user)
+            except KeyError:
+                raise BadCommand(
+                    "Bad username: %r; no such user exists" % user)
+            if not gid:
+                gid = entry.pw_gid
+            uid = entry.pw_uid
+        if self.verbose > 0:
+            print 'Changing user to %s:%s (%s:%s)' % (
+                user, group or '(unknown)', uid, gid)
+        if gid:
+            os.setgid(gid)
+        if uid:
+            os.setuid(uid)
+            
+class LazyWriter(object):
+
+    """
+    File-like object that opens a file lazily when it is first written
+    to.
+    """
+
+    def __init__(self, filename, mode='w'):
+        self.filename = filename
+        self.fileobj = None
+        self.lock = threading.Lock()
+        self.mode = mode
+        
+    def open(self):
+        if self.fileobj is None:
+            self.lock.acquire()
+            try:
+                if self.fileobj is None:
+                    self.fileobj = open(self.filename, self.mode)
+            finally:
+                self.lock.release()
+        return self.fileobj
+
+    def write(self, text):
+        fileobj = self.open()
+        fileobj.write(text)
+        fileobj.flush()
+
+    def writelines(self, text):
+        fileobj = self.open()
+        fileobj.writelines(text)
+        fileobj.flush()
+
+    def flush(self):
+        self.open().flush()
+
+def live_pidfile(pidfile):
+    """(pidfile:str) -> int | None
+    Returns an int found in the named file, if there is one,
+    and if there is a running process with that process id.
+    Return None if no such process exists.
+    """
+    pid = read_pidfile(pidfile)
+    if pid:
+        try:
+            os.kill(int(pid), 0)
+            return pid
+        except OSError, e:
+            if e.errno == errno.EPERM:
+                return pid
+    return None
+
+def read_pidfile(filename):
+    if os.path.exists(filename):
+        try:
+            f = open(filename)
+            content = f.read()
+            f.close()
+            return int(content.strip())
+        except (ValueError, IOError):
+            return None
+    else:
+        return None
+        
+def _remove_pid_file(written_pid, filename, verbosity):
+    current_pid = os.getpid()
+    if written_pid != current_pid:
+        # A forked process must be exiting, not the process that
+        # wrote the PID file
+        return
+    if not os.path.exists(filename):
+        return
+    f = open(filename)
+    content = f.read().strip()
+    f.close()
+    try:
+        pid_in_file = int(content)
+    except ValueError:
+        pass
+    else:
+        if pid_in_file != current_pid:
+            print "PID file %s contains %s, not expected PID %s" % (
+                filename, pid_in_file, current_pid)
+            return
+    if verbosity > 0:
+        print "Removing PID file %s" % filename
+    try:
+        os.unlink(filename)
+        return
+    except OSError, e:
+        # Record, but don't give traceback
+        print "Cannot remove PID file: %s" % e
+    # well, at least lets not leave the invalid PID around...
+    try:
+        f = open(filename, 'w')
+        f.write('')
+        f.close()
+    except OSError, e:
+        print 'Stale PID left in file: %s (%e)' % (filename, e)
+    else:
+        print 'Stale PID removed'
+        
+            
+def ensure_port_cleanup(bound_addresses, maxtries=30, sleeptime=2):
+    """
+    This makes sure any open ports are closed.
+
+    Does this by connecting to them until they give connection
+    refused.  Servers should call like::
+
+        import paste.script
+        ensure_port_cleanup([80, 443])
+    """
+    atexit.register(_cleanup_ports, bound_addresses, maxtries=maxtries,
+                    sleeptime=sleeptime)
+
+def _cleanup_ports(bound_addresses, maxtries=30, sleeptime=2):
+    # Wait for the server to bind to the port.
+    import socket
+    import errno
+    for bound_address in bound_addresses:
+        for attempt in range(maxtries):
+            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            try:
+                sock.connect(bound_address)
+            except socket.error, e:
+                if e.args[0] != errno.ECONNREFUSED:
+                    raise
+                break
+            else:
+                time.sleep(sleeptime)
+        else:
+            raise SystemExit('Timeout waiting for port.')
+        sock.close()
+
+def _turn_sigterm_into_systemexit():
+    """
+    Attempts to turn a SIGTERM exception into a SystemExit exception.
+    """
+    try:
+        import signal
+    except ImportError:
+        return
+    def handle_term(signo, frame):
+        raise SystemExit
+    signal.signal(signal.SIGTERM, handle_term)
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/templates.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/templates.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/templates.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,278 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import sys
+import os
+import inspect
+import copydir
+import command
+
+from paste.util.template import paste_script_template_renderer
+
+class Template(object):
+
+    # Subclasses must define:
+    # _template_dir (or template_dir())
+    # summary
+
+    # Variables this template uses (mostly for documentation now)
+    # a list of instances of var()
+    vars = []
+
+    # Eggs that should be added as plugins:
+    egg_plugins = []
+
+    # Templates that must be applied first:
+    required_templates = []
+
+    # Use Cheetah for substituting templates:
+    use_cheetah = False
+    # If true, then read all the templates to find the variables:
+    read_vars_from_templates = False
+
+    # You can also give this function/method to use something other
+    # than Cheetah or string.Template.  The function should be of the
+    # signature template_renderer(content, vars, filename=filename).
+    # Careful you don't turn this into a method by putting a function
+    # here (without staticmethod)!
+    template_renderer = None
+
+    def __init__(self, name):
+        self.name = name
+        self._read_vars = None
+    
+    def module_dir(self):
+        """Returns the module directory of this template."""
+        mod = sys.modules[self.__class__.__module__]
+        return os.path.dirname(mod.__file__)
+
+    def template_dir(self):
+        assert self._template_dir is not None, (
+            "Template %r didn't set _template_dir" % self)
+        if isinstance( self._template_dir, tuple):
+            return self._template_dir
+        else:
+            return os.path.join(self.module_dir(), self._template_dir)
+
+    def run(self, command, output_dir, vars):
+        self.pre(command, output_dir, vars)
+        self.write_files(command, output_dir, vars)
+        self.post(command, output_dir, vars)
+
+    def check_vars(self, vars, cmd):
+        expect_vars = self.read_vars(cmd)
+        if not expect_vars:
+            # Assume that variables aren't defined
+            return vars
+        converted_vars = {}
+        unused_vars = vars.copy()
+        errors = []
+        for var in expect_vars:
+            if var.name not in unused_vars:
+                if cmd.interactive:
+                    prompt = 'Enter %s' % var.full_description()
+                    response = cmd.challenge(prompt, var.default, var.should_echo)
+                    converted_vars[var.name] = response
+                elif var.default is command.NoDefault:
+                    errors.append('Required variable missing: %s'
+                                  % var.full_description())
+                else:
+                    converted_vars[var.name] = var.default
+            else:
+                converted_vars[var.name] = unused_vars.pop(var.name)
+        if errors:
+            raise command.BadCommand(
+                'Errors in variables:\n%s' % '\n'.join(errors))
+        converted_vars.update(unused_vars)
+        vars.update(converted_vars)
+        return converted_vars
+        
+    def read_vars(self, command=None):
+        if self._read_vars is not None:
+            return self._read_vars
+        assert (not self.read_vars_from_templates
+                or self.use_cheetah), (
+            "You can only read variables from templates if using Cheetah")
+        if not self.read_vars_from_templates:
+            self._read_vars = self.vars
+            return self.vars
+        
+        vars = self.vars[:]
+        var_names = [var.name for var in self.vars]
+        read_vars = find_args_in_dir(
+            self.template_dir(),
+            verbose=command and command.verbose > 1).items()
+        read_vars.sort()
+        for var_name, var in read_vars:
+            if var_name not in var_names:
+                vars.append(var)
+        self._read_vars = vars
+        return vars
+
+    def write_files(self, command, output_dir, vars):
+        template_dir = self.template_dir()
+        if not os.path.exists(output_dir):
+            print "Creating directory %s" % output_dir
+            if not command.simulate:
+                # Don't let copydir create this top-level directory,
+                # since copydir will svn add it sometimes:
+                os.makedirs(output_dir)
+        copydir.copy_dir(template_dir, output_dir,
+                         vars,
+                         verbosity=command.verbose,
+                         simulate=command.options.simulate,
+                         interactive=command.interactive,
+                         overwrite=command.options.overwrite,
+                         indent=1,
+                         use_cheetah=self.use_cheetah,
+                         template_renderer=self.template_renderer)
+
+    def print_vars(self, indent=0):
+        vars = self.read_vars()
+        var.print_vars(vars)
+        
+    def pre(self, command, output_dir, vars):
+        """
+        Called before template is applied.
+        """
+        pass
+
+    def post(self, command, output_dir, vars):
+        """
+        Called after template is applied.
+        """
+        pass
+
+NoDefault = command.NoDefault
+
+class var(object):
+
+    def __init__(self, name, description,
+                 default='', should_echo=True):
+        self.name = name
+        self.description = description
+        self.default = default
+        self.should_echo = should_echo
+
+    def __repr__(self):
+        return '<%s %s default=%r should_echo=%s>' % (
+            self.__class__.__name__,
+            self.name, self.default, self.should_echo)
+
+    def full_description(self):
+        if self.description:
+            return '%s (%s)' % (self.name, self.description)
+        else:
+            return self.name
+
+    def print_vars(cls, vars, indent=0):
+        max_name = max([len(v.name) for v in vars])
+        for var in vars:
+            if var.description:
+                print '%s%s%s  %s' % (
+                    ' '*indent,
+                    var.name,
+                    ' '*(max_name-len(var.name)),
+                    var.description)
+            else:
+                print '  %s' % var.name
+            if var.default is not command.NoDefault:
+                print '      default: %r' % var.default
+            if var.should_echo is True:
+                print '      should_echo: %s' % var.should_echo
+        print
+
+    print_vars = classmethod(print_vars)
+
+class BasicPackage(Template):
+
+    _template_dir = 'paster-templates/basic_package'
+    summary = "A basic setuptools-enabled package"
+    vars = [
+        var('version', 'Version (like 0.1)'),
+        var('description', 'One-line description of the package'),
+        var('long_description', 'Multi-line description (in reST)'),
+        var('keywords', 'Space-separated keywords/tags'),
+        var('author', 'Author name'),
+        var('author_email', 'Author email'),
+        var('url', 'URL of homepage'),
+        var('license_name', 'License name'),
+        var('zip_safe', 'True/False: if the package can be distributed as a .zip file', default=False),
+        ]
+
+    template_renderer = staticmethod(paste_script_template_renderer)
+    
+_skip_variables = ['VFN', 'currentTime', 'self', 'VFFSL', 'dummyTrans',
+                   'getmtime', 'trans']
+
+def find_args_in_template(template):
+    if isinstance(template, (str, unicode)):
+        # Treat as filename:
+        import Cheetah.Template
+        template = Cheetah.Template.Template(file=template)
+    if not hasattr(template, 'body'):
+        # Don't know...
+        return None
+    method = template.body
+    args, varargs, varkw, defaults = inspect.getargspec(method)
+    defaults=list(defaults or [])
+    vars = []
+    while args:
+        if len(args) == len(defaults):
+            default = defaults.pop(0)
+        else:
+            default = command.NoDefault
+        arg = args.pop(0)
+        if arg in _skip_variables:
+            continue
+        # @@: No way to get description yet
+        vars.append(
+            var(arg, description=None,
+                default=default))
+    return vars
+
+def find_args_in_dir(dir, verbose=False):
+    all_vars = {}
+    for fn in os.listdir(dir):
+        if fn.startswith('.') or fn == 'CVS' or fn == '_darcs':
+            continue
+        full = os.path.join(dir, fn)
+        if os.path.isdir(full):
+            inner_vars = find_args_in_dir(full)
+        elif full.endswith('_tmpl'):
+            inner_vars = {}
+            found = find_args_in_template(full)
+            if found is None:
+                # Couldn't read variables
+                if verbose:
+                    print 'Template %s has no parseable variables' % full
+                continue
+            for var in found:
+                inner_vars[var.name] = var
+        else:
+            # Not a template, don't read it
+            continue
+        if verbose:
+            print 'Found variable(s) %s in Template %s' % (
+                ', '.join(inner_vars.keys()), full)
+        for var_name, var in inner_vars.items():
+            # Easy case:
+            if var_name not in all_vars:
+                all_vars[var_name] = var
+                continue
+            # Emit warnings if the variables don't match well:
+            cur_var = all_vars[var_name]
+            if not cur_var.description:
+                cur_var.description = var.description
+            elif (cur_var.description and var.description
+                  and var.description != cur_var.description):
+                print >> sys.stderr, (
+                    "Variable descriptions do not match: %s: %s and %s"
+                    % (var_name, cur_var.description, var.description))
+            if (cur_var.default is not command.NoDefault
+                and var.default is not command.NoDefault
+                and cur_var.default != var.default):
+                print >> sys.stderr, (
+                    "Variable defaults do not match: %s: %r and %r"
+                    % (var_name, cur_var.default, var.default))
+    return all_vars
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/testapp.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/testapp.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/testapp.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,101 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+import cgi
+import os
+
+html_page_template = '''
+<html>
+<head>
+  <title>Test Application</title>
+</head>
+<body>
+<h1>Test Application: Working!</h1>
+
+<table border="1">
+%(environ)s
+</table>
+
+<p>
+Note: to see an error report, append <code>?error=true</code>
+to the URL
+</p>
+
+</body>
+</html>
+'''
+
+html_row_template = '''
+<tr>
+ <td><b>%(key)s</b></td>
+ <td><tt>%(value_literal)s</b></td>
+</tr>
+'''
+
+text_page_template = '%(environ)s'
+text_row_template = '%(key)s: %(value_repr)s\n'
+
+def make_literal(value):
+    value = cgi.escape(value, 1)
+    value = value.replace('\n\r', '\n')
+    value = value.replace('\r', '\n')
+    value = value.replace('\n', '<br>\n')
+    return value
+
+class TestApplication(object):
+
+    """
+    A test WSGI application, that prints out all the environmental
+    variables, and if you add ``?error=t`` to the URL it will
+    deliberately throw an exception.
+    """
+
+    def __init__(self, global_conf=None, text=False):
+        self.global_conf = global_conf
+        self.text = text
+
+    def __call__(self, environ, start_response):
+        if environ.get('QUERY_STRING', '').find('error=') >= 0:
+            assert 0, "Here is your error report, ordered and delivered"
+        if self.text:
+            page_template = text_page_template
+            row_template = text_row_template
+            content_type = 'text/plain; charset=utf8'
+        else:
+            page_template = html_page_template
+            row_template = html_row_template
+            content_type = 'text/html; charset=utf8'
+        keys = environ.keys()
+        keys.sort()
+        rows = []
+        for key in keys:
+            data = {'key': key}
+            value = environ[key]
+            data['value'] = value
+            try:
+                value = repr(value)
+            except Exception, e:
+                value = 'Cannot use repr(): %s' % e
+            data['value_repr'] = value
+            data['value_literal'] = make_literal(value)
+            row = row_template % data
+            rows.append(row)
+        rows = ''.join(rows)
+        page = page_template % {'environ': rows}
+        if isinstance(page, unicode):
+            page = page.encode('utf8')
+        headers = [('Content-type', content_type)]
+        start_response('200 OK', headers)
+        return [page]
+    
+
+def make_test_application(global_conf, text=False, lint=False):
+    from paste.deploy.converters import asbool
+    text = asbool(text)
+    lint = asbool(lint)
+    app = TestApplication(global_conf=global_conf, text=text)
+    if lint:
+        from paste.lint import middleware
+        app = middleware(app)
+    return app
+
+make_test_application.__doc__ = TestApplication.__doc__

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/twisted_web2_server.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/twisted_web2_server.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/twisted_web2_server.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# @@: THIS IS INCOMPLETE!
+
+def run_twisted(wsgi_app, global_conf,
+                host='127.0.0.1', port='8080'):
+    host = host or None
+    import twisted.web2.wsgi
+    import twisted.web2.log
+    import twisted.web2.channel
+    import twisted.web2.server
+    import twisted.internet.reactor
+    wsgi_resource = twisted.web2.wsgi.WSGIResource(wsgi_app)
+    resource = twisted.web2.log.LogWrapperResource(wsgi_resource)
+    twisted.web2.log.DefaultCommonAccessLoggingObserver().start()
+    site = twisted.web2.server.Site(resource)
+    factory = twisted.web2.channel.HTTPFactory(site)
+    # --- start reactor for listen port
+    twisted.internet.reactor.listenTCP(int(port), factory, interface=host)
+    twisted.internet.reactor.run()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/logging_config.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/logging_config.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/logging_config.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,354 @@
+# Copyright 2001-2005 by Vinay Sajip. All Rights Reserved.
+#
+# Permission to use, copy, modify, and distribute this software and its
+# documentation for any purpose and without fee is hereby granted,
+# provided that the above copyright notice appear in all copies and that
+# both that copyright notice and this permission notice appear in
+# supporting documentation, and that the name of Vinay Sajip
+# not be used in advertising or publicity pertaining to distribution
+# of the software without specific, written prior permission.
+# VINAY SAJIP DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+# ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+# VINAY SAJIP BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+# ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+# IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+# OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+"""
+Configuration functions for the logging package for Python. The core package
+is based on PEP 282 and comments thereto in comp.lang.python, and influenced
+by Apache's log4j system.
+
+Should work under Python versions >= 1.5.2, except that source line
+information is not available unless 'sys._getframe()' is.
+
+Copyright (C) 2001-2004 Vinay Sajip. All Rights Reserved.
+
+To use, simply 'import logging' and log away!
+"""
+
+import sys, logging, logging.handlers, string, socket, struct, os, traceback, types
+
+try:
+    import thread
+    import threading
+except ImportError:
+    thread = None
+
+from SocketServer import ThreadingTCPServer, StreamRequestHandler
+
+
+DEFAULT_LOGGING_CONFIG_PORT = 9030
+
+if sys.platform == "win32":
+    RESET_ERROR = 10054   #WSAECONNRESET
+else:
+    RESET_ERROR = 104     #ECONNRESET
+
+#
+#   The following code implements a socket listener for on-the-fly
+#   reconfiguration of logging.
+#
+#   _listener holds the server object doing the listening
+_listener = None
+
+def fileConfig(fname, defaults=None):
+    """
+    Read the logging configuration from a ConfigParser-format file.
+
+    This can be called several times from an application, allowing an end user
+    the ability to select from various pre-canned configurations (if the
+    developer provides a mechanism to present the choices and load the chosen
+    configuration).
+    In versions of ConfigParser which have the readfp method [typically
+    shipped in 2.x versions of Python], you can pass in a file-like object
+    rather than a filename, in which case the file-like object will be read
+    using readfp.
+    """
+    import ConfigParser
+
+    cp = ConfigParser.ConfigParser(defaults)
+    if hasattr(cp, 'readfp') and hasattr(fname, 'readline'):
+        cp.readfp(fname)
+    else:
+        cp.read(fname)
+
+    formatters = _create_formatters(cp)
+
+    # critical section
+    logging._acquireLock()
+    try:
+        logging._handlers.clear()
+        if hasattr(logging, '_handlerList'):
+            del logging._handlerList[:]
+        # Handlers add themselves to logging._handlers
+        handlers = _install_handlers(cp, formatters)
+        _install_loggers(cp, handlers)
+    finally:
+        logging._releaseLock()
+
+
+def _resolve(name):
+    """Resolve a dotted name to a global object."""
+    name = string.split(name, '.')
+    used = name.pop(0)
+    found = __import__(used)
+    for n in name:
+        used = used + '.' + n
+        try:
+            found = getattr(found, n)
+        except AttributeError:
+            __import__(used)
+            found = getattr(found, n)
+    return found
+
+
+def _create_formatters(cp):
+    """Create and return formatters"""
+    flist = cp.get("formatters", "keys")
+    if not len(flist):
+        return {}
+    flist = string.split(flist, ",")
+    formatters = {}
+    for form in flist:
+        form = string.strip(form)
+        sectname = "formatter_%s" % form
+        opts = cp.options(sectname)
+        if "format" in opts:
+            fs = cp.get(sectname, "format", 1)
+        else:
+            fs = None
+        if "datefmt" in opts:
+            dfs = cp.get(sectname, "datefmt", 1)
+        else:
+            dfs = None
+        c = logging.Formatter
+        if "class" in opts:
+            class_name = cp.get(sectname, "class")
+            if class_name:
+                c = _resolve(class_name)
+        f = c(fs, dfs)
+        formatters[form] = f
+    return formatters
+
+
+def _install_handlers(cp, formatters):
+    """Install and return handlers"""
+    hlist = cp.get("handlers", "keys")
+    if not len(hlist):
+        return {}
+    hlist = string.split(hlist, ",")
+    handlers = {}
+    fixups = [] #for inter-handler references
+    for hand in hlist:
+        hand = string.strip(hand)
+        sectname = "handler_%s" % hand
+        klass = cp.get(sectname, "class")
+        opts = cp.options(sectname)
+        if "formatter" in opts:
+            fmt = cp.get(sectname, "formatter")
+        else:
+            fmt = ""
+        try:
+            klass = eval(klass, vars(logging))
+        except (AttributeError, NameError):
+            klass = _resolve(klass)
+        args = cp.get(sectname, "args")
+        args = eval(args, vars(logging))
+        h = apply(klass, args)
+        if "level" in opts:
+            level = cp.get(sectname, "level")
+            h.setLevel(logging._levelNames[level])
+        if len(fmt):
+            h.setFormatter(formatters[fmt])
+        #temporary hack for FileHandler and MemoryHandler.
+        if klass == logging.handlers.MemoryHandler:
+            if "target" in opts:
+                target = cp.get(sectname,"target")
+            else:
+                target = ""
+            if len(target): #the target handler may not be loaded yet, so keep for later...
+                fixups.append((h, target))
+        handlers[hand] = h
+    #now all handlers are loaded, fixup inter-handler references...
+    for h, t in fixups:
+        h.setTarget(handlers[t])
+    return handlers
+
+
+def _install_loggers(cp, handlers):
+    """Create and install loggers"""
+
+    # configure the root first
+    llist = cp.get("loggers", "keys")
+    llist = string.split(llist, ",")
+    llist = map(lambda x: string.strip(x), llist)
+    llist.remove("root")
+    sectname = "logger_root"
+    root = logging.root
+    log = root
+    opts = cp.options(sectname)
+    if "level" in opts:
+        level = cp.get(sectname, "level")
+        log.setLevel(logging._levelNames[level])
+    for h in root.handlers[:]:
+        root.removeHandler(h)
+    hlist = cp.get(sectname, "handlers")
+    if len(hlist):
+        hlist = string.split(hlist, ",")
+        for hand in hlist:
+            log.addHandler(handlers[string.strip(hand)])
+
+    #and now the others...
+    #we don't want to lose the existing loggers,
+    #since other threads may have pointers to them.
+    #existing is set to contain all existing loggers,
+    #and as we go through the new configuration we
+    #remove any which are configured. At the end,
+    #what's left in existing is the set of loggers
+    #which were in the previous configuration but
+    #which are not in the new configuration.
+    existing = root.manager.loggerDict.keys()
+    #now set up the new ones...
+    for log in llist:
+        sectname = "logger_%s" % log
+        qn = cp.get(sectname, "qualname")
+        opts = cp.options(sectname)
+        if "propagate" in opts:
+            propagate = cp.getint(sectname, "propagate")
+        else:
+            propagate = 1
+        logger = logging.getLogger(qn)
+        if qn in existing:
+            existing.remove(qn)
+        if "level" in opts:
+            level = cp.get(sectname, "level")
+            logger.setLevel(logging._levelNames[level])
+        for h in logger.handlers[:]:
+            logger.removeHandler(h)
+        logger.propagate = propagate
+        logger.disabled = 0
+        hlist = cp.get(sectname, "handlers")
+        if len(hlist):
+            hlist = string.split(hlist, ",")
+            for hand in hlist:
+                logger.addHandler(handlers[string.strip(hand)])
+
+    #Disable any old loggers. There's no point deleting
+    #them as other threads may continue to hold references
+    #and by disabling them, you stop them doing any logging.
+    for log in existing:
+        root.manager.loggerDict[log].disabled = 1
+
+
+def listen(port=DEFAULT_LOGGING_CONFIG_PORT):
+    """
+    Start up a socket server on the specified port, and listen for new
+    configurations.
+
+    These will be sent as a file suitable for processing by fileConfig().
+    Returns a Thread object on which you can call start() to start the server,
+    and which you can join() when appropriate. To stop the server, call
+    stopListening().
+    """
+    if not thread:
+        raise NotImplementedError, "listen() needs threading to work"
+
+    class ConfigStreamHandler(StreamRequestHandler):
+        """
+        Handler for a logging configuration request.
+
+        It expects a completely new logging configuration and uses fileConfig
+        to install it.
+        """
+        def handle(self):
+            """
+            Handle a request.
+
+            Each request is expected to be a 4-byte length, packed using
+            struct.pack(">L", n), followed by the config file.
+            Uses fileConfig() to do the grunt work.
+            """
+            import tempfile
+            try:
+                conn = self.connection
+                chunk = conn.recv(4)
+                if len(chunk) == 4:
+                    slen = struct.unpack(">L", chunk)[0]
+                    chunk = self.connection.recv(slen)
+                    while len(chunk) < slen:
+                        chunk = chunk + conn.recv(slen - len(chunk))
+                    #Apply new configuration. We'd like to be able to
+                    #create a StringIO and pass that in, but unfortunately
+                    #1.5.2 ConfigParser does not support reading file
+                    #objects, only actual files. So we create a temporary
+                    #file and remove it later.
+                    file = tempfile.mktemp(".ini")
+                    f = open(file, "w")
+                    f.write(chunk)
+                    f.close()
+                    try:
+                        fileConfig(file)
+                    except (KeyboardInterrupt, SystemExit):
+                        raise
+                    except:
+                        traceback.print_exc()
+                    os.remove(file)
+            except socket.error, e:
+                if type(e.args) != types.TupleType:
+                    raise
+                else:
+                    errcode = e.args[0]
+                    if errcode != RESET_ERROR:
+                        raise
+
+    class ConfigSocketReceiver(ThreadingTCPServer):
+        """
+        A simple TCP socket-based logging config receiver.
+        """
+
+        allow_reuse_address = 1
+
+        def __init__(self, host='localhost', port=DEFAULT_LOGGING_CONFIG_PORT,
+                     handler=None):
+            ThreadingTCPServer.__init__(self, (host, port), handler)
+            logging._acquireLock()
+            self.abort = 0
+            logging._releaseLock()
+            self.timeout = 1
+
+        def serve_until_stopped(self):
+            import select
+            abort = 0
+            while not abort:
+                rd, wr, ex = select.select([self.socket.fileno()],
+                                           [], [],
+                                           self.timeout)
+                if rd:
+                    self.handle_request()
+                logging._acquireLock()
+                abort = self.abort
+                logging._releaseLock()
+
+    def serve(rcvr, hdlr, port):
+        server = rcvr(port=port, handler=hdlr)
+        global _listener
+        logging._acquireLock()
+        _listener = server
+        logging._releaseLock()
+        server.serve_until_stopped()
+
+    return threading.Thread(target=serve,
+                            args=(ConfigSocketReceiver,
+                                  ConfigStreamHandler, port))
+
+def stopListening():
+    """
+    Stop the listening server which was created with a call to listen().
+    """
+    global _listener
+    if _listener:
+        logging._acquireLock()
+        _listener.abort = 1
+        _listener = None
+        logging._releaseLock()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/secret.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/secret.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/secret.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""
+Create random secrets.
+"""
+
+import os
+import random
+
+def random_bytes(length):
+    """
+    Return a string of the given length.  Uses ``os.urandom`` if it
+    can, or just pseudo-random numbers otherwise.
+    """
+    try:
+        return os.urandom(length)
+    except AttributeError:
+        return ''.join([
+            chr(random.randrange(256)) for i in xrange(length)])
+
+def secret_string(length=25):
+    """
+    Returns a random string of the given length.  The string
+    is a base64-encoded version of a set of random bytes, truncated
+    to the given length (and without any newlines).
+    """
+    s = random_bytes(length).encode('base64')
+    for badchar in '\n\r=':
+        s = s.replace(badchar, '')
+    # We're wasting some characters here.  But random characters are
+    # cheap ;)
+    return s[:length]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/string24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/string24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/string24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,533 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""A collection of string operations (most are no longer used).
+
+Warning: most of the code you see here isn't normally used nowadays.
+Beginning with Python 1.6, many of these functions are implemented as
+methods on the standard string object. They used to be implemented by
+a built-in module called strop, but strop is now obsolete itself.
+
+Public module variables:
+
+whitespace -- a string containing all characters considered whitespace
+lowercase -- a string containing all characters considered lowercase letters
+uppercase -- a string containing all characters considered uppercase letters
+letters -- a string containing all characters considered letters
+digits -- a string containing all characters considered decimal digits
+hexdigits -- a string containing all characters considered hexadecimal digits
+octdigits -- a string containing all characters considered octal digits
+punctuation -- a string containing all characters considered punctuation
+printable -- a string containing all characters considered printable
+
+"""
+
+# Some strings for ctype-style character classification
+whitespace = ' \t\n\r\v\f'
+lowercase = 'abcdefghijklmnopqrstuvwxyz'
+uppercase = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+letters = lowercase + uppercase
+ascii_lowercase = lowercase
+ascii_uppercase = uppercase
+ascii_letters = ascii_lowercase + ascii_uppercase
+digits = '0123456789'
+hexdigits = digits + 'abcdef' + 'ABCDEF'
+octdigits = '01234567'
+punctuation = """!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~"""
+printable = digits + letters + punctuation + whitespace
+
+# Case conversion helpers
+# Use str to convert Unicode literal in case of -U
+# Note that Cookie.py bogusly uses _idmap :(
+l = map(chr, xrange(256))
+_idmap = str('').join(l)
+del l
+
+# Functions which aren't available as string methods.
+
+# Capitalize the words in a string, e.g. " aBc  dEf " -> "Abc Def".
+# See also regsub.capwords().
+def capwords(s, sep=None):
+    """capwords(s, [sep]) -> string
+
+    Split the argument into words using split, capitalize each
+    word using capitalize, and join the capitalized words using
+    join. Note that this replaces runs of whitespace characters by
+    a single space.
+
+    """
+    return (sep or ' ').join([x.capitalize() for x in s.split(sep)])
+
+
+# Construct a translation string
+_idmapL = None
+def maketrans(fromstr, tostr):
+    """maketrans(frm, to) -> string
+
+    Return a translation table (a string of 256 bytes long)
+    suitable for use in string.translate.  The strings frm and to
+    must be of the same length.
+
+    """
+    if len(fromstr) != len(tostr):
+        raise ValueError, "maketrans arguments must have same length"
+    global _idmapL
+    if not _idmapL:
+        _idmapL = map(None, _idmap)
+    L = _idmapL[:]
+    fromstr = map(ord, fromstr)
+    for i in range(len(fromstr)):
+        L[fromstr[i]] = tostr[i]
+    return ''.join(L)
+
+
+
+####################################################################
+import re as _re
+
+class _multimap:
+    """Helper class for combining multiple mappings.
+
+    Used by .{safe_,}substitute() to combine the mapping and keyword
+    arguments.
+    """
+    def __init__(self, primary, secondary):
+        self._primary = primary
+        self._secondary = secondary
+
+    def __getitem__(self, key):
+        try:
+            return self._primary[key]
+        except KeyError:
+            return self._secondary[key]
+
+
+class _TemplateMetaclass(type):
+    pattern = r"""
+    %(delim)s(?:
+      (?P<escaped>%(delim)s) |   # Escape sequence of two delimiters
+      (?P<named>%(id)s)      |   # delimiter and a Python identifier
+      {(?P<braced>%(id)s)}   |   # delimiter and a braced identifier
+      (?P<invalid>)              # Other ill-formed delimiter exprs
+    )
+    """
+
+    def __init__(cls, name, bases, dct):
+        super(_TemplateMetaclass, cls).__init__(name, bases, dct)
+        if 'pattern' in dct:
+            pattern = cls.pattern
+        else:
+            pattern = _TemplateMetaclass.pattern % {
+                'delim' : _re.escape(cls.delimiter),
+                'id'    : cls.idpattern,
+                }
+        cls.pattern = _re.compile(pattern, _re.IGNORECASE | _re.VERBOSE)
+
+
+class Template:
+    """A string class for supporting $-substitutions."""
+    __metaclass__ = _TemplateMetaclass
+
+    delimiter = '$'
+    idpattern = r'[_a-z][_a-z0-9]*'
+
+    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 in string: line %d, col %d' %
+                         (lineno, colno))
+
+    def substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            # Check the most common path first.
+            named = mo.group('named') or mo.group('braced')
+            if named is not None:
+                val = mapping[named]
+                # We use this idiom instead of str() because the latter will
+                # fail if val is a Unicode containing non-ASCII characters.
+                return '%s' % val
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                self._invalid(mo)
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+    def safe_substitute(self, *args, **kws):
+        if len(args) > 1:
+            raise TypeError('Too many positional arguments')
+        if not args:
+            mapping = kws
+        elif kws:
+            mapping = _multimap(kws, args[0])
+        else:
+            mapping = args[0]
+        # Helper function for .sub()
+        def convert(mo):
+            named = mo.group('named')
+            if named is not None:
+                try:
+                    # We use this idiom instead of str() because the latter
+                    # will fail if val is a Unicode containing non-ASCII
+                    return '%s' % mapping[named]
+                except KeyError:
+                    return self.delimiter + named
+            braced = mo.group('braced')
+            if braced is not None:
+                try:
+                    return '%s' % mapping[braced]
+                except KeyError:
+                    return self.delimiter + '{' + braced + '}'
+            if mo.group('escaped') is not None:
+                return self.delimiter
+            if mo.group('invalid') is not None:
+                return self.delimiter
+            raise ValueError('Unrecognized named group in pattern',
+                             self.pattern)
+        return self.pattern.sub(convert, self.template)
+
+
+
+####################################################################
+# NOTE: Everything below here is deprecated.  Use string methods instead.
+# This stuff will go away in Python 3.0.
+
+# Backward compatible names for exceptions
+index_error = ValueError
+atoi_error = ValueError
+atof_error = ValueError
+atol_error = ValueError
+
+# convert UPPER CASE letters to lower case
+def lower(s):
+    """lower(s) -> string
+
+    Return a copy of the string s converted to lowercase.
+
+    """
+    return s.lower()
+
+# Convert lower case letters to UPPER CASE
+def upper(s):
+    """upper(s) -> string
+
+    Return a copy of the string s converted to uppercase.
+
+    """
+    return s.upper()
+
+# Swap lower case letters and UPPER CASE
+def swapcase(s):
+    """swapcase(s) -> string
+
+    Return a copy of the string s with upper case characters
+    converted to lowercase and vice versa.
+
+    """
+    return s.swapcase()
+
+# Strip leading and trailing tabs and spaces
+def strip(s, chars=None):
+    """strip(s [,chars]) -> string
+
+    Return a copy of the string s with leading and trailing
+    whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+    If chars is unicode, S will be converted to unicode before stripping.
+
+    """
+    return s.strip(chars)
+
+# Strip leading tabs and spaces
+def lstrip(s, chars=None):
+    """lstrip(s [,chars]) -> string
+
+    Return a copy of the string s with leading whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.lstrip(chars)
+
+# Strip trailing tabs and spaces
+def rstrip(s, chars=None):
+    """rstrip(s [,chars]) -> string
+
+    Return a copy of the string s with trailing whitespace removed.
+    If chars is given and not None, remove characters in chars instead.
+
+    """
+    return s.rstrip(chars)
+
+
+# Split a string into a list of space/tab-separated words
+def split(s, sep=None, maxsplit=-1):
+    """split(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string.  If maxsplit is given, splits at no more than
+    maxsplit places (resulting in at most maxsplit+1 words).  If sep
+    is not specified or is None, any whitespace string is a separator.
+
+    (split and splitfields are synonymous)
+
+    """
+    return s.split(sep, maxsplit)
+splitfields = split
+
+# Split a string into a list of space/tab-separated words
+def rsplit(s, sep=None, maxsplit=-1):
+    """rsplit(s [,sep [,maxsplit]]) -> list of strings
+
+    Return a list of the words in the string s, using sep as the
+    delimiter string, starting at the end of the string and working
+    to the front.  If maxsplit is given, at most maxsplit splits are
+    done. If sep is not specified or is None, any whitespace string
+    is a separator.
+    """
+    return s.rsplit(sep, maxsplit)
+
+# Join fields with optional separator
+def join(words, sep = ' '):
+    """join(list [,sep]) -> string
+
+    Return a string composed of the words in list, with
+    intervening occurrences of sep.  The default separator is a
+    single space.
+
+    (joinfields and join are synonymous)
+
+    """
+    return sep.join(words)
+joinfields = join
+
+# Find substring, raise exception if not found
+def index(s, *args):
+    """index(s, sub [,start [,end]]) -> int
+
+    Like find but raises ValueError when the substring is not found.
+
+    """
+    return s.index(*args)
+
+# Find last substring, raise exception if not found
+def rindex(s, *args):
+    """rindex(s, sub [,start [,end]]) -> int
+
+    Like rfind but raises ValueError when the substring is not found.
+
+    """
+    return s.rindex(*args)
+
+# Count non-overlapping occurrences of substring
+def count(s, *args):
+    """count(s, sub[, start[,end]]) -> int
+
+    Return the number of occurrences of substring sub in string
+    s[start:end].  Optional arguments start and end are
+    interpreted as in slice notation.
+
+    """
+    return s.count(*args)
+
+# Find substring, return -1 if not found
+def find(s, *args):
+    """find(s, sub [,start [,end]]) -> in
+
+    Return the lowest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.find(*args)
+
+# Find last substring, return -1 if not found
+def rfind(s, *args):
+    """rfind(s, sub [,start [,end]]) -> int
+
+    Return the highest index in s where substring sub is found,
+    such that sub is contained within s[start,end].  Optional
+    arguments start and end are interpreted as in slice notation.
+
+    Return -1 on failure.
+
+    """
+    return s.rfind(*args)
+
+# for a bit of speed
+_float = float
+_int = int
+_long = long
+
+# Convert string to float
+def atof(s):
+    """atof(s) -> float
+
+    Return the floating point number represented by the string s.
+
+    """
+    return _float(s)
+
+
+# Convert string to integer
+def atoi(s , base=10):
+    """atoi(s [,base]) -> int
+
+    Return the integer represented by the string s in the given
+    base, which defaults to 10.  The string s must consist of one
+    or more digits, possibly preceded by a sign.  If base is 0, it
+    is chosen from the leading characters of s, 0 for octal, 0x or
+    0X for hexadecimal.  If base is 16, a preceding 0x or 0X is
+    accepted.
+
+    """
+    return _int(s, base)
+
+
+# Convert string to long integer
+def atol(s, base=10):
+    """atol(s [,base]) -> long
+
+    Return the long integer represented by the string s in the
+    given base, which defaults to 10.  The string s must consist
+    of one or more digits, possibly preceded by a sign.  If base
+    is 0, it is chosen from the leading characters of s, 0 for
+    octal, 0x or 0X for hexadecimal.  If base is 16, a preceding
+    0x or 0X is accepted.  A trailing L or l is not accepted,
+    unless base is 0.
+
+    """
+    return _long(s, base)
+
+
+# Left-justify a string
+def ljust(s, width, *args):
+    """ljust(s, width[, fillchar]) -> string
+
+    Return a left-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.ljust(width, *args)
+
+# Right-justify a string
+def rjust(s, width, *args):
+    """rjust(s, width[, fillchar]) -> string
+
+    Return a right-justified version of s, in a field of the
+    specified width, padded with spaces as needed.  The string is
+    never truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.rjust(width, *args)
+
+# Center a string
+def center(s, width, *args):
+    """center(s, width[, fillchar]) -> string
+
+    Return a center version of s, in a field of the specified
+    width. padded with spaces as needed.  The string is never
+    truncated.  If specified the fillchar is used instead of spaces.
+
+    """
+    return s.center(width, *args)
+
+# Zero-fill a number, e.g., (12, 3) --> '012' and (-3, 3) --> '-03'
+# Decadent feature: the argument may be a string or a number
+# (Use of this is deprecated; it should be a string as with ljust c.s.)
+def zfill(x, width):
+    """zfill(x, width) -> string
+
+    Pad a numeric string x with zeros on the left, to fill a field
+    of the specified width.  The string x is never truncated.
+
+    """
+    if not isinstance(x, basestring):
+        x = repr(x)
+    return x.zfill(width)
+
+# Expand tabs in a string.
+# Doesn't take non-printing chars into account, but does understand \n.
+def expandtabs(s, tabsize=8):
+    """expandtabs(s [,tabsize]) -> string
+
+    Return a copy of the string s with all tab characters replaced
+    by the appropriate number of spaces, depending on the current
+    column, and the tabsize (default 8).
+
+    """
+    return s.expandtabs(tabsize)
+
+# Character translation through look-up table.
+def translate(s, table, deletions=""):
+    """translate(s,table [,deletions]) -> string
+
+    Return a copy of the string s, where all characters occurring
+    in the optional argument deletions are removed, and the
+    remaining characters have been mapped through the given
+    translation table, which must be a string of length 256.  The
+    deletions argument is not allowed for Unicode strings.
+
+    """
+    if deletions:
+        return s.translate(table, deletions)
+    else:
+        # Add s[:0] so that if s is Unicode and table is an 8-bit string,
+        # table is converted to Unicode.  This means that table *cannot*
+        # be a dictionary -- for that feature, use u.translate() directly.
+        return s.translate(table + s[:0])
+
+# Capitalize a string, e.g. "aBc  dEf" -> "Abc  def".
+def capitalize(s):
+    """capitalize(s) -> string
+
+    Return a copy of the string s with only its first character
+    capitalized.
+
+    """
+    return s.capitalize()
+
+# Substring replacement (global)
+def replace(s, old, new, maxsplit=-1):
+    """replace (str, old, new[, maxsplit]) -> string
+
+    Return a copy of string str with all occurrences of substring
+    old replaced by new. If the optional argument maxsplit is
+    given, only the first maxsplit occurrences are replaced.
+
+    """
+    return s.replace(old, new, maxsplit)
+
+
+# Try importing optional built-in module "strop" -- if it exists,
+# it redefines some string operations that are 100-1000 times faster.
+# It also defines values for whitespace, lowercase and uppercase
+# that match <ctype.h>'s definitions.
+
+try:
+    from strop import maketrans, lowercase, uppercase, whitespace
+    letters = lowercase + uppercase
+except ImportError:
+    pass                                          # Use the original versions

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/subprocess24.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/subprocess24.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/subprocess24.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1154 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+# subprocess - Subprocesses with accessible I/O streams
+#
+# For more information about this module, see PEP 324.
+#
+# This module should remain compatible with Python 2.2, see PEP 291.
+#
+# Copyright (c) 2003-2005 by Peter Astrand <astrand at lysator.liu.se>
+#
+# Licensed to PSF under a Contributor Agreement.
+# See http://www.python.org/2.4/license for licensing details.
+
+r"""subprocess - Subprocesses with accessible I/O streams
+
+This module allows you to spawn processes, connect to their
+input/output/error pipes, and obtain their return codes.  This module
+intends to replace several other, older modules and functions, like:
+
+os.system
+os.spawn*
+os.popen*
+popen2.*
+commands.*
+
+Information about how the subprocess module can be used to replace these
+modules and functions can be found below.
+
+
+
+Using the subprocess module
+===========================
+This module defines one class called Popen:
+
+class Popen(args, bufsize=0, executable=None,
+            stdin=None, stdout=None, stderr=None,
+            preexec_fn=None, close_fds=False, shell=False,
+            cwd=None, env=None, universal_newlines=False,
+            startupinfo=None, creationflags=0):
+
+
+Arguments are:
+
+args should be a string, or a sequence of program arguments.  The
+program to execute is normally the first item in the args sequence or
+string, but can be explicitly set by using the executable argument.
+
+On UNIX, with shell=False (default): In this case, the Popen class
+uses os.execvp() to execute the child program.  args should normally
+be a sequence.  A string will be treated as a sequence with the string
+as the only item (the program to execute).
+
+On UNIX, with shell=True: If args is a string, it specifies the
+command string to execute through the shell.  If args is a sequence,
+the first item specifies the command string, and any additional items
+will be treated as additional shell arguments.
+
+On Windows: the Popen class uses CreateProcess() to execute the child
+program, which operates on strings.  If args is a sequence, it will be
+converted to a string using the list2cmdline method.  Please note that
+not all MS Windows applications interpret the command line the same
+way: The list2cmdline is designed for applications using the same
+rules as the MS C runtime.
+
+bufsize, if given, has the same meaning as the corresponding argument
+to the built-in open() function: 0 means unbuffered, 1 means line
+buffered, any other positive value means use a buffer of
+(approximately) that size.  A negative bufsize means to use the system
+default, which usually means fully buffered.  The default value for
+bufsize is 0 (unbuffered).
+
+stdin, stdout and stderr specify the executed programs' standard
+input, standard output and standard error file handles, respectively.
+Valid values are PIPE, an existing file descriptor (a positive
+integer), an existing file object, and None.  PIPE indicates that a
+new pipe to the child should be created.  With None, no redirection
+will occur; the child's file handles will be inherited from the
+parent.  Additionally, stderr can be STDOUT, which indicates that the
+stderr data from the applications should be captured into the same
+file handle as for stdout.
+
+If preexec_fn is set to a callable object, this object will be called
+in the child process just before the child is executed.
+
+If close_fds is true, all file descriptors except 0, 1 and 2 will be
+closed before the child process is executed.
+
+if shell is true, the specified command will be executed through the
+shell.
+
+If cwd is not None, the current directory will be changed to cwd
+before the child is executed.
+
+If env is not None, it defines the environment variables for the new
+process.
+
+If universal_newlines is true, the file objects stdout and stderr are
+opened as a text files, but lines may be terminated by any of '\n',
+the Unix end-of-line convention, '\r', the Macintosh convention or
+'\r\n', the Windows convention.  All of these external representations
+are seen as '\n' by the Python program.  Note: This feature is only
+available if Python is built with universal newline support (the
+default).  Also, the newlines attribute of the file objects stdout,
+stdin and stderr are not updated by the communicate() method.
+
+The startupinfo and creationflags, if given, will be passed to the
+underlying CreateProcess() function.  They can specify things such as
+appearance of the main window and priority for the new process.
+(Windows only)
+
+
+This module also defines two shortcut functions:
+
+call(*args, **kwargs):
+    Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+
+
+Exceptions
+----------
+Exceptions raised in the child process, before the new program has
+started to execute, will be re-raised in the parent.  Additionally,
+the exception object will have one extra attribute called
+'child_traceback', which is a string containing traceback information
+from the childs point of view.
+
+The most common exception raised is OSError.  This occurs, for
+example, when trying to execute a non-existent file.  Applications
+should prepare for OSErrors.
+
+A ValueError will be raised if Popen is called with invalid arguments.
+
+
+Security
+--------
+Unlike some other popen functions, this implementation will never call
+/bin/sh implicitly.  This means that all characters, including shell
+metacharacters, can safely be passed to child processes.
+
+
+Popen objects
+=============
+Instances of the Popen class have the following methods:
+
+poll()
+    Check if child process has terminated.  Returns returncode
+    attribute.
+
+wait()
+    Wait for child process to terminate.  Returns returncode attribute.
+
+communicate(input=None)
+    Interact with process: Send data to stdin.  Read data from stdout
+    and stderr, until end-of-file is reached.  Wait for process to
+    terminate.  The optional stdin argument should be a string to be
+    sent to the child process, or None, if no data should be sent to
+    the child.
+
+    communicate() returns a tuple (stdout, stderr).
+
+    Note: The data read is buffered in memory, so do not use this
+    method if the data size is large or unlimited.
+
+The following attributes are also available:
+
+stdin
+    If the stdin argument is PIPE, this attribute is a file object
+    that provides input to the child process.  Otherwise, it is None.
+
+stdout
+    If the stdout argument is PIPE, this attribute is a file object
+    that provides output from the child process.  Otherwise, it is
+    None.
+
+stderr
+    If the stderr argument is PIPE, this attribute is file object that
+    provides error output from the child process.  Otherwise, it is
+    None.
+
+pid
+    The process ID of the child process.
+
+returncode
+    The child return code.  A None value indicates that the process
+    hasn't terminated yet.  A negative value -N indicates that the
+    child was terminated by signal N (UNIX only).
+
+
+Replacing older functions with the subprocess module
+====================================================
+In this section, "a ==> b" means that b can be used as a replacement
+for a.
+
+Note: All functions in this section fail (more or less) silently if
+the executed program cannot be found; this module raises an OSError
+exception.
+
+In the following examples, we assume that the subprocess module is
+imported with "from subprocess import *".
+
+
+Replacing /bin/sh shell backquote
+---------------------------------
+output=`mycmd myarg`
+==>
+output = Popen(["mycmd", "myarg"], stdout=PIPE).communicate()[0]
+
+
+Replacing shell pipe line
+-------------------------
+output=`dmesg | grep hda`
+==>
+p1 = Popen(["dmesg"], stdout=PIPE)
+p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+output = p2.communicate()[0]
+
+
+Replacing os.system()
+---------------------
+sts = os.system("mycmd" + " myarg")
+==>
+p = Popen("mycmd" + " myarg", shell=True)
+sts = os.waitpid(p.pid, 0)
+
+Note:
+
+* Calling the program through the shell is usually not required.
+
+* It's easier to look at the returncode attribute than the
+  exitstatus.
+
+A more real-world example would look like this:
+
+try:
+    retcode = call("mycmd" + " myarg", shell=True)
+    if retcode < 0:
+        print >>sys.stderr, "Child was terminated by signal", -retcode
+    else:
+        print >>sys.stderr, "Child returned", retcode
+except OSError, e:
+    print >>sys.stderr, "Execution failed:", e
+
+
+Replacing os.spawn*
+-------------------
+P_NOWAIT example:
+
+pid = os.spawnlp(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+pid = Popen(["/bin/mycmd", "myarg"]).pid
+
+
+P_WAIT example:
+
+retcode = os.spawnlp(os.P_WAIT, "/bin/mycmd", "mycmd", "myarg")
+==>
+retcode = call(["/bin/mycmd", "myarg"])
+
+
+Vector example:
+
+os.spawnvp(os.P_NOWAIT, path, args)
+==>
+Popen([path] + args[1:])
+
+
+Environment example:
+
+os.spawnlpe(os.P_NOWAIT, "/bin/mycmd", "mycmd", "myarg", env)
+==>
+Popen(["/bin/mycmd", "myarg"], env={"PATH": "/usr/bin"})
+
+
+Replacing os.popen*
+-------------------
+pipe = os.popen(cmd, mode='r', bufsize)
+==>
+pipe = Popen(cmd, shell=True, bufsize=bufsize, stdout=PIPE).stdout
+
+pipe = os.popen(cmd, mode='w', bufsize)
+==>
+pipe = Popen(cmd, shell=True, bufsize=bufsize, stdin=PIPE).stdin
+
+
+(child_stdin, child_stdout) = os.popen2(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdin, child_stdout) = (p.stdin, p.stdout)
+
+
+(child_stdin,
+ child_stdout,
+ child_stderr) = os.popen3(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
+(child_stdin,
+ child_stdout,
+ child_stderr) = (p.stdin, p.stdout, p.stderr)
+
+
+(child_stdin, child_stdout_and_stderr) = os.popen4(cmd, mode, bufsize)
+==>
+p = Popen(cmd, shell=True, bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, stderr=STDOUT, close_fds=True)
+(child_stdin, child_stdout_and_stderr) = (p.stdin, p.stdout)
+
+
+Replacing popen2.*
+------------------
+Note: If the cmd argument to popen2 functions is a string, the command
+is executed through /bin/sh.  If it is a list, the command is directly
+executed.
+
+(child_stdout, child_stdin) = popen2.popen2("somestring", bufsize, mode)
+==>
+p = Popen(["somestring"], shell=True, bufsize=bufsize
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+
+(child_stdout, child_stdin) = popen2.popen2(["mycmd", "myarg"], bufsize, mode)
+==>
+p = Popen(["mycmd", "myarg"], bufsize=bufsize,
+          stdin=PIPE, stdout=PIPE, close_fds=True)
+(child_stdout, child_stdin) = (p.stdout, p.stdin)
+
+The popen2.Popen3 and popen3.Popen4 basically works as subprocess.Popen,
+except that:
+
+* subprocess.Popen raises an exception if the execution fails
+* the capturestderr argument is replaced with the stderr argument.
+* stdin=PIPE and stdout=PIPE must be specified.
+* popen2 closes all filedescriptors by default, but you have to specify
+  close_fds=True with subprocess.Popen.
+
+
+"""
+
+import sys
+mswindows = (sys.platform == "win32")
+
+import os
+import types
+import traceback
+
+if mswindows:
+    import threading
+    import msvcrt
+    if 0: # <-- change this to use pywin32 instead of the _subprocess driver
+        import pywintypes
+        from win32api import GetStdHandle, STD_INPUT_HANDLE, \
+                             STD_OUTPUT_HANDLE, STD_ERROR_HANDLE
+        from win32api import GetCurrentProcess, DuplicateHandle, \
+                             GetModuleFileName, GetVersion
+        from win32con import DUPLICATE_SAME_ACCESS, SW_HIDE
+        from win32pipe import CreatePipe
+        from win32process import CreateProcess, STARTUPINFO, \
+                                 GetExitCodeProcess, STARTF_USESTDHANDLES, \
+                                 STARTF_USESHOWWINDOW, CREATE_NEW_CONSOLE
+        from win32event import WaitForSingleObject, INFINITE, WAIT_OBJECT_0
+    else:
+        raise ImportError(
+            "Windows subprocess module must be installed: see "
+            "http://effbot.org/downloads/#subprocess")
+        from _subprocess import *
+        class STARTUPINFO:
+            dwFlags = 0
+            hStdInput = None
+            hStdOutput = None
+            hStdError = None
+        class pywintypes:
+            error = IOError
+else:
+    import select
+    import errno
+    import fcntl
+    import pickle
+
+__all__ = ["Popen", "PIPE", "STDOUT", "call"]
+
+try:
+    MAXFD = os.sysconf("SC_OPEN_MAX")
+except:
+    MAXFD = 256
+
+# True/False does not exist on 2.2.0
+try:
+    False
+except NameError:
+    False = 0
+    True = 1
+
+_active = []
+
+def _cleanup():
+    for inst in _active[:]:
+        inst.poll()
+
+PIPE = -1
+STDOUT = -2
+
+
+def call(*args, **kwargs):
+    """Run command with arguments.  Wait for command to complete, then
+    return the returncode attribute.
+
+    The arguments are the same as for the Popen constructor.  Example:
+
+    retcode = call(["ls", "-l"])
+    """
+    return Popen(*args, **kwargs).wait()
+
+
+def list2cmdline(seq):
+    """
+    Translate a sequence of arguments into a command line
+    string, using the same rules as the MS C runtime:
+
+    1) Arguments are delimited by white space, which is either a
+       space or a tab.
+
+    2) A string surrounded by double quotation marks is
+       interpreted as a single argument, regardless of white space
+       contained within.  A quoted string can be embedded in an
+       argument.
+
+    3) A double quotation mark preceded by a backslash is
+       interpreted as a literal double quotation mark.
+
+    4) Backslashes are interpreted literally, unless they
+       immediately precede a double quotation mark.
+
+    5) If backslashes immediately precede a double quotation mark,
+       every pair of backslashes is interpreted as a literal
+       backslash.  If the number of backslashes is odd, the last
+       backslash escapes the next double quotation mark as
+       described in rule 3.
+    """
+
+    # See
+    # http://msdn.microsoft.com/library/en-us/vccelng/htm/progs_12.asp
+    result = []
+    needquote = False
+    for arg in seq:
+        bs_buf = []
+
+        # Add a space to separate this argument from the others
+        if result:
+            result.append(' ')
+
+        needquote = (" " in arg) or ("\t" in arg)
+        if needquote:
+            result.append('"')
+
+        for c in arg:
+            if c == '\\':
+                # Don't know if we need to double yet.
+                bs_buf.append(c)
+            elif c == '"':
+                # Double backspaces.
+                result.append('\\' * len(bs_buf)*2)
+                bs_buf = []
+                result.append('\\"')
+            else:
+                # Normal char
+                if bs_buf:
+                    result.extend(bs_buf)
+                    bs_buf = []
+                result.append(c)
+
+        # Add remaining backspaces, if any.
+        if bs_buf:
+            result.extend(bs_buf)
+
+        if needquote:
+            result.extend(bs_buf)
+            result.append('"')
+
+    return ''.join(result)
+
+
+class Popen(object):
+    def __init__(self, args, bufsize=0, executable=None,
+                 stdin=None, stdout=None, stderr=None,
+                 preexec_fn=None, close_fds=False, shell=False,
+                 cwd=None, env=None, universal_newlines=False,
+                 startupinfo=None, creationflags=0):
+        """Create new Popen instance."""
+        _cleanup()
+
+        if not isinstance(bufsize, (int, long)):
+            raise TypeError("bufsize must be an integer")
+
+        if mswindows:
+            if preexec_fn is not None:
+                raise ValueError("preexec_fn is not supported on Windows "
+                                 "platforms")
+            if close_fds:
+                raise ValueError("close_fds is not supported on Windows "
+                                 "platforms")
+        else:
+            # POSIX
+            if startupinfo is not None:
+                raise ValueError("startupinfo is only supported on Windows "
+                                 "platforms")
+            if creationflags != 0:
+                raise ValueError("creationflags is only supported on Windows "
+                                 "platforms")
+
+        self.stdin = None
+        self.stdout = None
+        self.stderr = None
+        self.pid = None
+        self.returncode = None
+        self.universal_newlines = universal_newlines
+
+        # Input and output objects. The general principle is like
+        # this:
+        #
+        # Parent                   Child
+        # ------                   -----
+        # p2cwrite   ---stdin--->  p2cread
+        # c2pread    <--stdout---  c2pwrite
+        # errread    <--stderr---  errwrite
+        #
+        # On POSIX, the child objects are file descriptors.  On
+        # Windows, these are Windows file handles.  The parent objects
+        # are file descriptors on both platforms.  The parent objects
+        # are None when not using PIPEs. The child objects are None
+        # when not redirecting.
+
+        (p2cread, p2cwrite,
+         c2pread, c2pwrite,
+         errread, errwrite) = self._get_handles(stdin, stdout, stderr)
+
+        self._execute_child(args, executable, preexec_fn, close_fds,
+                            cwd, env, universal_newlines,
+                            startupinfo, creationflags, shell,
+                            p2cread, p2cwrite,
+                            c2pread, c2pwrite,
+                            errread, errwrite)
+
+        if p2cwrite:
+            self.stdin = os.fdopen(p2cwrite, 'wb', bufsize)
+        if c2pread:
+            if universal_newlines:
+                self.stdout = os.fdopen(c2pread, 'rU', bufsize)
+            else:
+                self.stdout = os.fdopen(c2pread, 'rb', bufsize)
+        if errread:
+            if universal_newlines:
+                self.stderr = os.fdopen(errread, 'rU', bufsize)
+            else:
+                self.stderr = os.fdopen(errread, 'rb', bufsize)
+
+        _active.append(self)
+
+
+    def _translate_newlines(self, data):
+        data = data.replace("\r\n", "\n")
+        data = data.replace("\r", "\n")
+        return data
+
+
+    if mswindows:
+        #
+        # Windows methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tupel with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            if stdin == None and stdout == None and stderr == None:
+                return (None, None, None, None, None, None)
+
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin == None:
+                p2cread = GetStdHandle(STD_INPUT_HANDLE)
+            elif stdin == PIPE:
+                p2cread, p2cwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                p2cwrite = p2cwrite.Detach()
+                p2cwrite = msvcrt.open_osfhandle(p2cwrite, 0)
+            elif type(stdin) == types.IntType:
+                p2cread = msvcrt.get_osfhandle(stdin)
+            else:
+                # Assuming file-like object
+                p2cread = msvcrt.get_osfhandle(stdin.fileno())
+            p2cread = self._make_inheritable(p2cread)
+
+            if stdout == None:
+                c2pwrite = GetStdHandle(STD_OUTPUT_HANDLE)
+            elif stdout == PIPE:
+                c2pread, c2pwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                c2pread = c2pread.Detach()
+                c2pread = msvcrt.open_osfhandle(c2pread, 0)
+            elif type(stdout) == types.IntType:
+                c2pwrite = msvcrt.get_osfhandle(stdout)
+            else:
+                # Assuming file-like object
+                c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
+            c2pwrite = self._make_inheritable(c2pwrite)
+
+            if stderr == None:
+                errwrite = GetStdHandle(STD_ERROR_HANDLE)
+            elif stderr == PIPE:
+                errread, errwrite = CreatePipe(None, 0)
+                # Detach and turn into fd
+                errread = errread.Detach()
+                errread = msvcrt.open_osfhandle(errread, 0)
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif type(stderr) == types.IntType:
+                errwrite = msvcrt.get_osfhandle(stderr)
+            else:
+                # Assuming file-like object
+                errwrite = msvcrt.get_osfhandle(stderr.fileno())
+            errwrite = self._make_inheritable(errwrite)
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _make_inheritable(self, handle):
+            """Return a duplicate of handle, which is inheritable"""
+            return DuplicateHandle(GetCurrentProcess(), handle,
+                                   GetCurrentProcess(), 0, 1,
+                                   DUPLICATE_SAME_ACCESS)
+
+
+        def _find_w9xpopen(self):
+            """Find and return absolut path to w9xpopen.exe"""
+            w9xpopen = os.path.join(os.path.dirname(GetModuleFileName(0)),
+                                    "w9xpopen.exe")
+            if not os.path.exists(w9xpopen):
+                # Eeek - file-not-found - possibly an embedding
+                # situation - see if we can locate it in sys.exec_prefix
+                w9xpopen = os.path.join(os.path.dirname(sys.exec_prefix),
+                                        "w9xpopen.exe")
+                if not os.path.exists(w9xpopen):
+                    raise RuntimeError("Cannot locate w9xpopen.exe, which is "
+                                       "needed for Popen to work with your "
+                                       "shell or platform.")
+            return w9xpopen
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (MS Windows version)"""
+
+            if not isinstance(args, types.StringTypes):
+                args = list2cmdline(args)
+
+            # Process startup details
+            default_startupinfo = STARTUPINFO()
+            if startupinfo == None:
+                startupinfo = default_startupinfo
+            if not None in (p2cread, c2pwrite, errwrite):
+                startupinfo.dwFlags |= STARTF_USESTDHANDLES
+                startupinfo.hStdInput = p2cread
+                startupinfo.hStdOutput = c2pwrite
+                startupinfo.hStdError = errwrite
+
+            if shell:
+                default_startupinfo.dwFlags |= STARTF_USESHOWWINDOW
+                default_startupinfo.wShowWindow = SW_HIDE
+                comspec = os.environ.get("COMSPEC", "cmd.exe")
+                args = comspec + " /c " + args
+                if (GetVersion() >= 0x80000000L or
+                        os.path.basename(comspec).lower() == "command.com"):
+                    # Win9x, or using command.com on NT. We need to
+                    # use the w9xpopen intermediate program. For more
+                    # information, see KB Q150956
+                    # (http://web.archive.org/web/20011105084002/http://support.microsoft.com/support/kb/articles/Q150/9/56.asp)
+                    w9xpopen = self._find_w9xpopen()
+                    args = '"%s" %s' % (w9xpopen, args)
+                    # Not passing CREATE_NEW_CONSOLE has been known to
+                    # cause random failures on win9x.  Specifically a
+                    # dialog: "Your program accessed mem currently in
+                    # use at xxx" and a hopeful warning about the
+                    # stability of your system.  Cost is Ctrl+C wont
+                    # kill children.
+                    creationflags |= CREATE_NEW_CONSOLE
+
+            # Start the process
+            try:
+                hp, ht, pid, tid = CreateProcess(executable, args,
+                                         # no special security
+                                         None, None,
+                                         # must inherit handles to pass std
+                                         # handles
+                                         1,
+                                         creationflags,
+                                         env,
+                                         cwd,
+                                         startupinfo)
+            except pywintypes.error, e:
+                # Translate pywintypes.error to WindowsError, which is
+                # a subclass of OSError.  FIXME: We should really
+                # translate errno using _sys_errlist (or simliar), but
+                # how can this be done from Python?
+                raise WindowsError(*e.args)
+
+            # Retain the process handle, but close the thread handle
+            self._handle = hp
+            self.pid = pid
+            ht.Close()
+
+            # Child is launched. Close the parent's copy of those pipe
+            # handles that only the child should have open.  You need
+            # to make sure that no handles to the write end of the
+            # output pipe are maintained in this process or else the
+            # pipe will not close when the child process exits and the
+            # ReadFile will hang.
+            if p2cread != None:
+                p2cread.Close()
+            if c2pwrite != None:
+                c2pwrite.Close()
+            if errwrite != None:
+                errwrite.Close()
+
+
+        def poll(self):
+            """Check if child process has terminated.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                if WaitForSingleObject(self._handle, 0) == WAIT_OBJECT_0:
+                    self.returncode = GetExitCodeProcess(self._handle)
+                    _active.remove(self)
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                obj = WaitForSingleObject(self._handle, INFINITE)
+                self.returncode = GetExitCodeProcess(self._handle)
+                _active.remove(self)
+            return self.returncode
+
+
+        def _readerthread(self, fh, buffer):
+            buffer.append(fh.read())
+
+
+        def communicate(self, input=None):
+            """Interact with process: Send data to stdin.  Read data from
+            stdout and stderr, until end-of-file is reached.  Wait for
+            process to terminate.  The optional input argument should be a
+            string to be sent to the child process, or None, if no data
+            should be sent to the child.
+
+            communicate() returns a tuple (stdout, stderr)."""
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdout:
+                stdout = []
+                stdout_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stdout, stdout))
+                stdout_thread.setDaemon(True)
+                stdout_thread.start()
+            if self.stderr:
+                stderr = []
+                stderr_thread = threading.Thread(target=self._readerthread,
+                                                 args=(self.stderr, stderr))
+                stderr_thread.setDaemon(True)
+                stderr_thread.start()
+
+            if self.stdin:
+                if input != None:
+                    self.stdin.write(input)
+                self.stdin.close()
+
+            if self.stdout:
+                stdout_thread.join()
+            if self.stderr:
+                stderr_thread.join()
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout != None:
+                stdout = stdout[0]
+            if stderr != None:
+                stderr = stderr[0]
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(open, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+    else:
+        #
+        # POSIX methods
+        #
+        def _get_handles(self, stdin, stdout, stderr):
+            """Construct and return tupel with IO objects:
+            p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite
+            """
+            p2cread, p2cwrite = None, None
+            c2pread, c2pwrite = None, None
+            errread, errwrite = None, None
+
+            if stdin == None:
+                pass
+            elif stdin == PIPE:
+                p2cread, p2cwrite = os.pipe()
+            elif type(stdin) == types.IntType:
+                p2cread = stdin
+            else:
+                # Assuming file-like object
+                p2cread = stdin.fileno()
+
+            if stdout == None:
+                pass
+            elif stdout == PIPE:
+                c2pread, c2pwrite = os.pipe()
+            elif type(stdout) == types.IntType:
+                c2pwrite = stdout
+            else:
+                # Assuming file-like object
+                c2pwrite = stdout.fileno()
+
+            if stderr == None:
+                pass
+            elif stderr == PIPE:
+                errread, errwrite = os.pipe()
+            elif stderr == STDOUT:
+                errwrite = c2pwrite
+            elif type(stderr) == types.IntType:
+                errwrite = stderr
+            else:
+                # Assuming file-like object
+                errwrite = stderr.fileno()
+
+            return (p2cread, p2cwrite,
+                    c2pread, c2pwrite,
+                    errread, errwrite)
+
+
+        def _set_cloexec_flag(self, fd):
+            try:
+                cloexec_flag = fcntl.FD_CLOEXEC
+            except AttributeError:
+                cloexec_flag = 1
+
+            old = fcntl.fcntl(fd, fcntl.F_GETFD)
+            fcntl.fcntl(fd, fcntl.F_SETFD, old | cloexec_flag)
+
+
+        def _close_fds(self, but):
+            for i in range(3, MAXFD):
+                if i == but:
+                    continue
+                try:
+                    os.close(i)
+                except:
+                    pass
+
+
+        def _execute_child(self, args, executable, preexec_fn, close_fds,
+                           cwd, env, universal_newlines,
+                           startupinfo, creationflags, shell,
+                           p2cread, p2cwrite,
+                           c2pread, c2pwrite,
+                           errread, errwrite):
+            """Execute program (POSIX version)"""
+
+            if isinstance(args, types.StringTypes):
+                args = [args]
+
+            if shell:
+                args = ["/bin/sh", "-c"] + args
+
+            if executable == None:
+                executable = args[0]
+
+            # For transferring possible exec failure from child to parent
+            # The first char specifies the exception type: 0 means
+            # OSError, 1 means some other error.
+            errpipe_read, errpipe_write = os.pipe()
+            self._set_cloexec_flag(errpipe_write)
+
+            self.pid = os.fork()
+            if self.pid == 0:
+                # Child
+                try:
+                    # Close parent's pipe ends
+                    if p2cwrite:
+                        os.close(p2cwrite)
+                    if c2pread:
+                        os.close(c2pread)
+                    if errread:
+                        os.close(errread)
+                    os.close(errpipe_read)
+
+                    # Dup fds for child
+                    if p2cread:
+                        os.dup2(p2cread, 0)
+                    if c2pwrite:
+                        os.dup2(c2pwrite, 1)
+                    if errwrite:
+                        os.dup2(errwrite, 2)
+
+                    # Close pipe fds.  Make sure we doesn't close the same
+                    # fd more than once.
+                    if p2cread:
+                        os.close(p2cread)
+                    if c2pwrite and c2pwrite not in (p2cread,):
+                        os.close(c2pwrite)
+                    if errwrite and errwrite not in (p2cread, c2pwrite):
+                        os.close(errwrite)
+
+                    # Close all other fds, if asked for
+                    if close_fds:
+                        self._close_fds(but=errpipe_write)
+
+                    if cwd != None:
+                        os.chdir(cwd)
+
+                    if preexec_fn:
+                        apply(preexec_fn)
+
+                    if env == None:
+                        os.execvp(executable, args)
+                    else:
+                        os.execvpe(executable, args, env)
+
+                except:
+                    exc_type, exc_value, tb = sys.exc_info()
+                    # Save the traceback and attach it to the exception object
+                    exc_lines = traceback.format_exception(exc_type,
+                                                           exc_value,
+                                                           tb)
+                    exc_value.child_traceback = ''.join(exc_lines)
+                    os.write(errpipe_write, pickle.dumps(exc_value))
+
+                # This exitcode won't be reported to applications, so it
+                # really doesn't matter what we return.
+                os._exit(255)
+
+            # Parent
+            os.close(errpipe_write)
+            if p2cread and p2cwrite:
+                os.close(p2cread)
+            if c2pwrite and c2pread:
+                os.close(c2pwrite)
+            if errwrite and errread:
+                os.close(errwrite)
+
+            # Wait for exec to fail or succeed; possibly raising exception
+            data = os.read(errpipe_read, 1048576) # Exceptions limited to 1 MB
+            os.close(errpipe_read)
+            if data != "":
+                os.waitpid(self.pid, 0)
+                child_exception = pickle.loads(data)
+                raise child_exception
+
+
+        def _handle_exitstatus(self, sts):
+            if os.WIFSIGNALED(sts):
+                self.returncode = -os.WTERMSIG(sts)
+            elif os.WIFEXITED(sts):
+                self.returncode = os.WEXITSTATUS(sts)
+            else:
+                # Should never happen
+                raise RuntimeError("Unknown child exit status!")
+
+            _active.remove(self)
+
+
+        def poll(self):
+            """Check if child process has terminated.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                try:
+                    pid, sts = os.waitpid(self.pid, os.WNOHANG)
+                    if pid == self.pid:
+                        self._handle_exitstatus(sts)
+                except os.error:
+                    pass
+            return self.returncode
+
+
+        def wait(self):
+            """Wait for child process to terminate.  Returns returncode
+            attribute."""
+            if self.returncode == None:
+                pid, sts = os.waitpid(self.pid, 0)
+                self._handle_exitstatus(sts)
+            return self.returncode
+
+
+        def communicate(self, input=None):
+            """Interact with process: Send data to stdin.  Read data from
+            stdout and stderr, until end-of-file is reached.  Wait for
+            process to terminate.  The optional input argument should be a
+            string to be sent to the child process, or None, if no data
+            should be sent to the child.
+
+            communicate() returns a tuple (stdout, stderr)."""
+            read_set = []
+            write_set = []
+            stdout = None # Return
+            stderr = None # Return
+
+            if self.stdin:
+                # Flush stdio buffer.  This might block, if the user has
+                # been writing to .stdin in an uncontrolled fashion.
+                self.stdin.flush()
+                if input:
+                    write_set.append(self.stdin)
+                else:
+                    self.stdin.close()
+            if self.stdout:
+                read_set.append(self.stdout)
+                stdout = []
+            if self.stderr:
+                read_set.append(self.stderr)
+                stderr = []
+
+            while read_set or write_set:
+                rlist, wlist, xlist = select.select(read_set, write_set, [])
+
+                if self.stdin in wlist:
+                    # When select has indicated that the file is writable,
+                    # we can write up to PIPE_BUF bytes without risk
+                    # blocking.  POSIX defines PIPE_BUF >= 512
+                    bytes_written = os.write(self.stdin.fileno(), input[:512])
+                    input = input[bytes_written:]
+                    if not input:
+                        self.stdin.close()
+                        write_set.remove(self.stdin)
+
+                if self.stdout in rlist:
+                    data = os.read(self.stdout.fileno(), 1024)
+                    if data == "":
+                        self.stdout.close()
+                        read_set.remove(self.stdout)
+                    stdout.append(data)
+
+                if self.stderr in rlist:
+                    data = os.read(self.stderr.fileno(), 1024)
+                    if data == "":
+                        self.stderr.close()
+                        read_set.remove(self.stderr)
+                    stderr.append(data)
+
+            # All data exchanged.  Translate lists into strings.
+            if stdout != None:
+                stdout = ''.join(stdout)
+            if stderr != None:
+                stderr = ''.join(stderr)
+
+            # Translate newlines, if requested.  We cannot let the file
+            # object do the translation: It is based on stdio, which is
+            # impossible to combine with select (unless forcing no
+            # buffering).
+            if self.universal_newlines and hasattr(open, 'newlines'):
+                if stdout:
+                    stdout = self._translate_newlines(stdout)
+                if stderr:
+                    stderr = self._translate_newlines(stderr)
+
+            self.wait()
+            return (stdout, stderr)
+
+
+def _demo_posix():
+    #
+    # Example 1: Simple redirection: Get process list
+    #
+    plist = Popen(["ps"], stdout=PIPE).communicate()[0]
+    print "Process list:"
+    print plist
+
+    #
+    # Example 2: Change uid before executing child
+    #
+    if os.getuid() == 0:
+        p = Popen(["id"], preexec_fn=lambda: os.setuid(100))
+        p.wait()
+
+    #
+    # Example 3: Connecting several subprocesses
+    #
+    print "Looking for 'hda'..."
+    p1 = Popen(["dmesg"], stdout=PIPE)
+    p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 4: Catch execution error
+    #
+    print
+    print "Trying a weird file..."
+    try:
+        print Popen(["/this/path/does/not/exist"]).communicate()
+    except OSError, e:
+        if e.errno == errno.ENOENT:
+            print "The file didn't exist.  I thought so..."
+            print "Child traceback:"
+            print e.child_traceback
+        else:
+            print "Error", e.errno
+    else:
+        print >>sys.stderr, "Gosh.  No error."
+
+
+def _demo_windows():
+    #
+    # Example 1: Connecting several subprocesses
+    #
+    print "Looking for 'PROMPT' in set output..."
+    p1 = Popen("set", stdout=PIPE, shell=True)
+    p2 = Popen('find "PROMPT"', stdin=p1.stdout, stdout=PIPE)
+    print repr(p2.communicate()[0])
+
+    #
+    # Example 2: Simple execution of program
+    #
+    print "Executing calc..."
+    p = Popen("calc")
+    p.wait()
+
+
+if __name__ == "__main__":
+    if mswindows:
+        _demo_windows()
+    else:
+        _demo_posix()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/uuid.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/uuid.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/util/uuid.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,240 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+"""UUID (universally unique identifiers) as specified in RFC 4122.
+
+This module provides the UUID class and the functions uuid1(), uuid3(),
+uuid4(), uuid5() for generating version 1, 3, 4, and 5 UUIDs respectively.
+
+This module works with Python 2.3 or higher."""
+
+__author__ = 'Ka-Ping Yee <ping at zesty.ca>'
+__date__ = '$Date: 2005/11/30 11:51:58 $'.split()[1].replace('/', '-')
+__version__ = '$Revision: 1.10 $'
+
+RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE = [
+    'reserved for NCS compatibility', 'specified in RFC 4122',
+    'reserved for Microsoft compatibility', 'reserved for future definition']
+
+class UUID(object):
+    """Instances of the UUID class represent UUIDs as specified in RFC 4122.
+    Converting a UUID to a string using str() produces a string in the form
+    "{12345678-1234-1234-1234-123456789abc}".  The UUID constructor accepts
+    a similar string (braces and hyphens optional), or six integer arguments
+    (with 32-bit, 16-bit, 16-bit, 8-bit, 8-bit, and 48-bit values
+    respectively).  UUID objects have the following attributes:
+
+        bytes       gets or sets the UUID as a 16-byte string
+
+        urn         gets the UUID as a URN as specified in RFC 4122
+
+        variant     gets or sets the UUID variant as one of the constants
+                    RESERVED_NCS, RFC_4122, RESERVED_MICROSOFT, RESERVED_FUTURE
+
+        version     gets or sets the UUID version number (1 through 5)
+    """
+
+    def __init__(self, *args):
+        """Create a UUID either from a string representation in hexadecimal
+        or from six integers (32-bit time_low, 16-bit time_mid, 16-bit
+        time_hi_ver, 8-bit clock_hi_res, 8-bit clock_low, 48-bit node)."""
+        if len(args) == 1:
+            digits = args[0].replace('urn:', '').replace('uuid:', '')
+            digits = digits.replace('{', '').replace('}', '').replace('-', '')
+            assert len(digits) == 32, ValueError('badly formed UUID string')
+            time_low = int(digits[:8], 16)
+            time_mid = int(digits[8:12], 16)
+            time_hi_ver = int(digits[12:16], 16)
+            clock_hi_res = int(digits[16:18], 16)
+            clock_low = int(digits[18:20], 16)
+            node = int(digits[20:32], 16)
+        else:
+            (time_low, time_mid, time_hi_ver,
+             clock_hi_res, clock_low, node) = args
+        assert 0 <= time_low < 0x100000000, ValueError('time_low out of range')
+        assert 0 <= time_mid < 1<<16, ValueError('time_mid out of range')
+        assert 0 <= time_hi_ver < 1<<16, ValueError('time_hi_ver out of range')
+        assert 0 <= clock_hi_res < 1<<8, ValueError('clock_hi_res out of range')
+        assert 0 <= clock_low < 1<<8, ValueError('clock_low out of range')
+        assert 0 <= node < 0x1000000000000, ValueError('node out of range')
+        self.time_low = time_low
+        self.time_mid = time_mid
+        self.time_hi_ver = time_hi_ver
+        self.clock_hi_res = clock_hi_res
+        self.clock_low = clock_low
+        self.node = node
+
+    def __cmp__(self, other):
+        return cmp(self.bytes, getattr(other, 'bytes', other))
+
+    def __str__(self):
+        return '{%08x-%04x-%04x-%02x%02x-%012x}' % (
+            self.time_low, self.time_mid, self.time_hi_ver,
+            self.clock_hi_res, self.clock_low, self.node)
+
+    def __repr__(self):
+        return 'UUID(%r)' % str(self)
+
+    def get_bytes(self):
+        def byte(n):
+            return chr(n & 0xff)
+
+        return (byte(self.time_low >> 24) + byte(self.time_low >> 16) +
+                byte(self.time_low >> 8) + byte(self.time_low) +
+                byte(self.time_mid >> 8) + byte(self.time_mid) +
+                byte(self.time_hi_ver >> 8) + byte(self.time_hi_ver) +
+                byte(self.clock_hi_res) + byte(self.clock_low) +
+                byte(self.node >> 40) + byte(self.node >> 32) +
+                byte(self.node >> 24) + byte(self.node >> 16) +
+                byte(self.node >> 8) + byte(self.node))
+
+    def set_bytes(self, bytes):
+        values = map(ord, bytes)
+        self.time_low = ((values[0] << 24) + (values[1] << 16) +
+                         (values[2] << 8) + values[3])
+        self.time_mid = (values[4] << 8) + values[5]
+        self.time_hi_ver = (values[6] << 8) + values[7]
+        self.clock_hi_res = values[8]
+        self.clock_low = values[9]
+        self.node = ((values[10] << 40) + (values[11] << 32) +
+                     (values[12] << 24) + (values[13] << 16) +
+                     (values[14] << 8) + values[15])
+
+    bytes = property(get_bytes, set_bytes)
+
+    def get_urn(self):
+        return 'urn:uuid:%08x-%04x-%04x-%02x%02x-%012x' % (
+            self.time_low, self.time_mid, self.time_hi_ver,
+            self.clock_hi_res, self.clock_low, self.node)
+
+    urn = property(get_urn)
+
+    def get_variant(self):
+        if not self.clock_hi_res & 0x80:
+            return RESERVED_NCS
+        elif not self.clock_hi_res & 0x40:
+            return RFC_4122
+        elif not self.clock_hi_res & 0x20:
+            return RESERVED_MICROSOFT
+        else:
+            return RESERVED_FUTURE
+
+    def set_variant(self, variant):
+        if variant == RESERVED_NCS:
+            self.clock_hi_res &= 0x7f
+        elif variant == RFC_4122:
+            self.clock_hi_res &= 0x3f
+            self.clock_hi_res |= 0x80
+        elif variant == RESERVED_MICROSOFT:
+            self.clock_hi_res &= 0x1f
+            self.clock_hi_res |= 0xc0
+        elif variant == RESERVED_FUTURE:
+            self.clock_hi_res &= 0x1f
+            self.clock_hi_res |= 0xe0
+        else:
+            raise ValueError('illegal variant identifier')
+
+    variant = property(get_variant, set_variant)
+
+    def get_version(self):
+        return self.time_hi_ver >> 12
+
+    def set_version(self, version):
+        assert 1 <= version <= 5, ValueError('illegal version number')
+        self.time_hi_ver &= 0x0fff
+        self.time_hi_ver |= (version << 12)
+
+    version = property(get_version, set_version)
+
+def unixgetaddr(program):
+    """Get the hardware address on a Unix machine."""
+    from os import popen
+    for line in popen(program):
+        words = line.lower().split()
+        if 'hwaddr' in words:
+            addr = words[words.index('hwaddr') + 1]
+            return int(addr.replace(':', ''), 16)
+        if 'ether' in words:
+            addr = words[words.index('ether') + 1]
+            return int(addr.replace(':', ''), 16)
+
+def wingetaddr(program):
+    """Get the hardware address on a Windows machine."""
+    from os import popen
+    for line in popen(program + ' /all'):
+        if line.strip().lower().startswith('physical address'):
+            addr = line.split(':')[-1].strip()
+            return int(addr.replace('-', ''), 16)
+
+def getaddr():
+    """Get the hardware address as a 48-bit integer."""
+    from os.path import join, isfile
+    for dir in ['/sbin', '/usr/sbin', r'c:\windows',
+                r'c:\windows\system', r'c:\windows\system32']:
+        if isfile(join(dir, 'ifconfig')):
+            return unixgetaddr(join(dir, 'ifconfig'))
+        if isfile(join(dir, 'ipconfig.exe')):
+            return wingetaddr(join(dir, 'ipconfig.exe'))
+
+def uuid1():
+    """Generate a UUID based on the time and hardware address."""
+    from time import time
+    from random import randrange
+    nanoseconds = int(time() * 1e9)
+    # 0x01b21dd213814000 is the number of 100-ns intervals between the
+    # UUID epoch 1582-10-15 00:00:00 and the Unix epoch 1970-01-01 00:00:00.
+    timestamp = int(nanoseconds/100) + 0x01b21dd213814000
+    clock = randrange(1<<16) # don't use stable storage
+    time_low = timestamp & (0x100000000 - 1)
+    time_mid = (timestamp >> 32) & 0xffff
+    time_hi_ver = (timestamp >> 48) & 0x0fff
+    clock_low = clock & 0xff
+    clock_hi_res = (clock >> 8) & 0x3f
+    node = getaddr()
+    uuid = UUID(time_low, time_mid, time_hi_ver, clock_low, clock_hi_res, node)
+    uuid.variant = RFC_4122
+    uuid.version = 1
+    return uuid
+
+def uuid3(namespace, name):
+    """Generate a UUID from the MD5 hash of a namespace UUID and a name."""
+    try:
+        from hashlib import md5
+    except ImportError:
+        from md5 import md5
+    uuid = UUID(0, 0, 0, 0, 0, 0)
+    uuid.bytes = md5(namespace.bytes + name).digest()[:16]
+    uuid.variant = RFC_4122
+    uuid.version = 3
+    return uuid
+
+def uuid4():
+    """Generate a random UUID."""
+    try:
+        from os import urandom
+    except:
+        from random import randrange
+        uuid = UUID(randrange(1<<32L), randrange(1<<16), randrange(1<<16),
+                    randrange(1<<8), randrange(1<<8), randrange(1<<48L))
+    else:
+        uuid = UUID(0, 0, 0, 0, 0, 0)
+        uuid.bytes = urandom(16)
+    uuid.variant = RFC_4122
+    uuid.version = 4
+    return uuid
+
+def uuid5(namespace, name):
+    """Generate a UUID from the SHA-1 hash of a namespace UUID and a name."""
+    try:
+        from hashlib import sha1
+    except ImportError:
+        from sha import sha as sha1
+    uuid = UUID(0, 0, 0, 0, 0, 0)
+    uuid.bytes = sha1(namespace.bytes + name).digest()[:16]
+    uuid.variant = RFC_4122
+    uuid.version = 5
+    return uuid
+
+NAMESPACE_DNS = UUID('{6ba7b810-9dad-11d1-80b4-00c04fd430c8}')
+NAMESPACE_URL = UUID('{6ba7b811-9dad-11d1-80b4-00c04fd430c8}')
+NAMESPACE_OID = UUID('{6ba7b812-9dad-11d1-80b4-00c04fd430c8}')
+NAMESPACE_X500 = UUID('{6ba7b814-9dad-11d1-80b4-00c04fd430c8}')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiserver/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiserver/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiserver/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1783 @@
+"""A high-speed, production ready, thread pooled, generic WSGI server.
+
+Simplest example on how to use this module directly
+(without using CherryPy's application machinery):
+
+    from cherrypy import wsgiserver
+    
+    def my_crazy_app(environ, start_response):
+        status = '200 OK'
+        response_headers = [('Content-type','text/plain')]
+        start_response(status, response_headers)
+        return ['Hello world!\n']
+    
+    server = wsgiserver.CherryPyWSGIServer(
+                ('0.0.0.0', 8070), my_crazy_app,
+                server_name='www.cherrypy.example')
+    
+The CherryPy WSGI server can serve as many WSGI applications 
+as you want in one instance by using a WSGIPathInfoDispatcher:
+    
+    d = WSGIPathInfoDispatcher({'/': my_crazy_app, '/blog': my_blog_app})
+    server = wsgiserver.CherryPyWSGIServer(('0.0.0.0', 80), d)
+    
+Want SSL support? Just set these attributes:
+    
+    server.ssl_certificate = <filename>
+    server.ssl_private_key = <filename>
+    
+    if __name__ == '__main__':
+        try:
+            server.start()
+        except KeyboardInterrupt:
+            server.stop()
+
+This won't call the CherryPy engine (application side) at all, only the
+WSGI server, which is independant from the rest of CherryPy. Don't
+let the name "CherryPyWSGIServer" throw you; the name merely reflects
+its origin, not its coupling.
+
+For those of you wanting to understand internals of this module, here's the
+basic call flow. The server's listening thread runs a very tight loop,
+sticking incoming connections onto a Queue:
+
+    server = CherryPyWSGIServer(...)
+    server.start()
+    while True:
+        tick()
+        # This blocks until a request comes in:
+        child = socket.accept()
+        conn = HTTPConnection(child, ...)
+        server.requests.put(conn)
+
+Worker threads are kept in a pool and poll the Queue, popping off and then
+handling each connection in turn. Each connection can consist of an arbitrary
+number of requests and their responses, so we run a nested loop:
+
+    while True:
+        conn = server.requests.get()
+        conn.communicate()
+        ->  while True:
+                req = HTTPRequest(...)
+                req.parse_request()
+                ->  # Read the Request-Line, e.g. "GET /page HTTP/1.1"
+                    req.rfile.readline()
+                    req.read_headers()
+                req.respond()
+                ->  response = wsgi_app(...)
+                    try:
+                        for chunk in response:
+                            if chunk:
+                                req.write(chunk)
+                    finally:
+                        if hasattr(response, "close"):
+                            response.close()
+                if req.close_connection:
+                    return
+"""
+
+
+import base64
+import os
+import Queue
+import re
+quoted_slash = re.compile("(?i)%2F")
+import rfc822
+import socket
+try:
+    import cStringIO as StringIO
+except ImportError:
+    import StringIO
+
+_fileobject_uses_str_type = isinstance(socket._fileobject(None)._rbuf, basestring)
+
+import sys
+import threading
+import time
+import traceback
+from urllib import unquote
+from urlparse import urlparse
+import warnings
+
+try:
+    from OpenSSL import SSL
+    from OpenSSL import crypto
+except ImportError:
+    SSL = None
+
+import errno
+
+def plat_specific_errors(*errnames):
+    """Return error numbers for all errors in errnames on this platform.
+    
+    The 'errno' module contains different global constants depending on
+    the specific platform (OS). This function will return the list of
+    numeric values for a given list of potential names.
+    """
+    errno_names = dir(errno)
+    nums = [getattr(errno, k) for k in errnames if k in errno_names]
+    # de-dupe the list
+    return dict.fromkeys(nums).keys()
+
+socket_error_eintr = plat_specific_errors("EINTR", "WSAEINTR")
+
+socket_errors_to_ignore = plat_specific_errors(
+    "EPIPE",
+    "EBADF", "WSAEBADF",
+    "ENOTSOCK", "WSAENOTSOCK",
+    "ETIMEDOUT", "WSAETIMEDOUT",
+    "ECONNREFUSED", "WSAECONNREFUSED",
+    "ECONNRESET", "WSAECONNRESET",
+    "ECONNABORTED", "WSAECONNABORTED",
+    "ENETRESET", "WSAENETRESET",
+    "EHOSTDOWN", "EHOSTUNREACH",
+    )
+socket_errors_to_ignore.append("timed out")
+
+socket_errors_nonblocking = plat_specific_errors(
+    'EAGAIN', 'EWOULDBLOCK', 'WSAEWOULDBLOCK')
+
+comma_separated_headers = ['ACCEPT', 'ACCEPT-CHARSET', 'ACCEPT-ENCODING',
+    'ACCEPT-LANGUAGE', 'ACCEPT-RANGES', 'ALLOW', 'CACHE-CONTROL',
+    'CONNECTION', 'CONTENT-ENCODING', 'CONTENT-LANGUAGE', 'EXPECT',
+    'IF-MATCH', 'IF-NONE-MATCH', 'PRAGMA', 'PROXY-AUTHENTICATE', 'TE',
+    'TRAILER', 'TRANSFER-ENCODING', 'UPGRADE', 'VARY', 'VIA', 'WARNING',
+    'WWW-AUTHENTICATE']
+
+
+class WSGIPathInfoDispatcher(object):
+    """A WSGI dispatcher for dispatch based on the PATH_INFO.
+    
+    apps: a dict or list of (path_prefix, app) pairs.
+    """
+    
+    def __init__(self, apps):
+        try:
+            apps = apps.items()
+        except AttributeError:
+            pass
+        
+        # Sort the apps by len(path), descending
+        apps.sort()
+        apps.reverse()
+        
+        # The path_prefix strings must start, but not end, with a slash.
+        # Use "" instead of "/".
+        self.apps = [(p.rstrip("/"), a) for p, a in apps]
+    
+    def __call__(self, environ, start_response):
+        path = environ["PATH_INFO"] or "/"
+        for p, app in self.apps:
+            # The apps list should be sorted by length, descending.
+            if path.startswith(p + "/") or path == p:
+                environ = environ.copy()
+                environ["SCRIPT_NAME"] = environ["SCRIPT_NAME"] + p
+                environ["PATH_INFO"] = path[len(p):]
+                return app(environ, start_response)
+        
+        start_response('404 Not Found', [('Content-Type', 'text/plain'),
+                                         ('Content-Length', '0')])
+        return ['']
+
+
+class MaxSizeExceeded(Exception):
+    pass
+
+class SizeCheckWrapper(object):
+    """Wraps a file-like object, raising MaxSizeExceeded if too large."""
+    
+    def __init__(self, rfile, maxlen):
+        self.rfile = rfile
+        self.maxlen = maxlen
+        self.bytes_read = 0
+    
+    def _check_length(self):
+        if self.maxlen and self.bytes_read > self.maxlen:
+            raise MaxSizeExceeded()
+    
+    def read(self, size=None):
+        data = self.rfile.read(size)
+        self.bytes_read += len(data)
+        self._check_length()
+        return data
+    
+    def readline(self, size=None):
+        if size is not None:
+            data = self.rfile.readline(size)
+            self.bytes_read += len(data)
+            self._check_length()
+            return data
+        
+        # User didn't specify a size ...
+        # We read the line in chunks to make sure it's not a 100MB line !
+        res = []
+        while True:
+            data = self.rfile.readline(256)
+            self.bytes_read += len(data)
+            self._check_length()
+            res.append(data)
+            # See http://www.cherrypy.org/ticket/421
+            if len(data) < 256 or data[-1:] == "\n":
+                return ''.join(res)
+    
+    def readlines(self, sizehint=0):
+        # Shamelessly stolen from StringIO
+        total = 0
+        lines = []
+        line = self.readline()
+        while line:
+            lines.append(line)
+            total += len(line)
+            if 0 < sizehint <= total:
+                break
+            line = self.readline()
+        return lines
+    
+    def close(self):
+        self.rfile.close()
+    
+    def __iter__(self):
+        return self
+    
+    def next(self):
+        data = self.rfile.next()
+        self.bytes_read += len(data)
+        self._check_length()
+        return data
+
+
+class HTTPRequest(object):
+    """An HTTP Request (and response).
+    
+    A single HTTP connection may consist of multiple request/response pairs.
+    
+    send: the 'send' method from the connection's socket object.
+    wsgi_app: the WSGI application to call.
+    environ: a partial WSGI environ (server and connection entries).
+        The caller MUST set the following entries:
+        * All wsgi.* entries, including .input
+        * SERVER_NAME and SERVER_PORT
+        * Any SSL_* entries
+        * Any custom entries like REMOTE_ADDR and REMOTE_PORT
+        * SERVER_SOFTWARE: the value to write in the "Server" response header.
+        * ACTUAL_SERVER_PROTOCOL: the value to write in the Status-Line of
+            the response. From RFC 2145: "An HTTP server SHOULD send a
+            response version equal to the highest version for which the
+            server is at least conditionally compliant, and whose major
+            version is less than or equal to the one received in the
+            request.  An HTTP server MUST NOT send a version for which
+            it is not at least conditionally compliant."
+    
+    outheaders: a list of header tuples to write in the response.
+    ready: when True, the request has been parsed and is ready to begin
+        generating the response. When False, signals the calling Connection
+        that the response should not be generated and the connection should
+        close.
+    close_connection: signals the calling Connection that the request
+        should close. This does not imply an error! The client and/or
+        server may each request that the connection be closed.
+    chunked_write: if True, output will be encoded with the "chunked"
+        transfer-coding. This value is set automatically inside
+        send_headers.
+    """
+    
+    max_request_header_size = 0
+    max_request_body_size = 0
+    
+    def __init__(self, wfile, environ, wsgi_app):
+        self.rfile = environ['wsgi.input']
+        self.wfile = wfile
+        self.environ = environ.copy()
+        self.wsgi_app = wsgi_app
+        
+        self.ready = False
+        self.started_response = False
+        self.status = ""
+        self.outheaders = []
+        self.sent_headers = False
+        self.close_connection = False
+        self.chunked_write = False
+    
+    def parse_request(self):
+        """Parse the next HTTP request start-line and message-headers."""
+        self.rfile.maxlen = self.max_request_header_size
+        self.rfile.bytes_read = 0
+        
+        try:
+            self._parse_request()
+        except MaxSizeExceeded:
+            self.simple_response("413 Request Entity Too Large")
+            return
+    
+    def _parse_request(self):
+        # HTTP/1.1 connections are persistent by default. If a client
+        # requests a page, then idles (leaves the connection open),
+        # then rfile.readline() will raise socket.error("timed out").
+        # Note that it does this based on the value given to settimeout(),
+        # and doesn't need the client to request or acknowledge the close
+        # (although your TCP stack might suffer for it: cf Apache's history
+        # with FIN_WAIT_2).
+        request_line = self.rfile.readline()
+        if not request_line:
+            # Force self.ready = False so the connection will close.
+            self.ready = False
+            return
+        
+        if request_line == "\r\n":
+            # RFC 2616 sec 4.1: "...if the server is reading the protocol
+            # stream at the beginning of a message and receives a CRLF
+            # first, it should ignore the CRLF."
+            # But only ignore one leading line! else we enable a DoS.
+            request_line = self.rfile.readline()
+            if not request_line:
+                self.ready = False
+                return
+        
+        environ = self.environ
+        
+        try:
+            method, path, req_protocol = request_line.strip().split(" ", 2)
+        except ValueError:
+            self.simple_response(400, "Malformed Request-Line")
+            return
+        
+        environ["REQUEST_METHOD"] = method
+        
+        # path may be an abs_path (including "http://host.domain.tld");
+        scheme, location, path, params, qs, frag = urlparse(path)
+        
+        if frag:
+            self.simple_response("400 Bad Request",
+                                 "Illegal #fragment in Request-URI.")
+            return
+        
+        if scheme:
+            environ["wsgi.url_scheme"] = scheme
+        if params:
+            path = path + ";" + params
+        
+        environ["SCRIPT_NAME"] = ""
+        
+        # Unquote the path+params (e.g. "/this%20path" -> "this path").
+        # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
+        #
+        # But note that "...a URI must be separated into its components
+        # before the escaped characters within those components can be
+        # safely decoded." http://www.ietf.org/rfc/rfc2396.txt, sec 2.4.2
+        atoms = [unquote(x) for x in quoted_slash.split(path)]
+        path = "%2F".join(atoms)
+        environ["PATH_INFO"] = path
+        
+        # Note that, like wsgiref and most other WSGI servers,
+        # we unquote the path but not the query string.
+        environ["QUERY_STRING"] = qs
+        
+        # Compare request and server HTTP protocol versions, in case our
+        # server does not support the requested protocol. Limit our output
+        # to min(req, server). We want the following output:
+        #     request    server     actual written   supported response
+        #     protocol   protocol  response protocol    feature set
+        # a     1.0        1.0           1.0                1.0
+        # b     1.0        1.1           1.1                1.0
+        # c     1.1        1.0           1.0                1.0
+        # d     1.1        1.1           1.1                1.1
+        # Notice that, in (b), the response will be "HTTP/1.1" even though
+        # the client only understands 1.0. RFC 2616 10.5.6 says we should
+        # only return 505 if the _major_ version is different.
+        rp = int(req_protocol[5]), int(req_protocol[7])
+        server_protocol = environ["ACTUAL_SERVER_PROTOCOL"]
+        sp = int(server_protocol[5]), int(server_protocol[7])
+        if sp[0] != rp[0]:
+            self.simple_response("505 HTTP Version Not Supported")
+            return
+        # Bah. "SERVER_PROTOCOL" is actually the REQUEST protocol.
+        environ["SERVER_PROTOCOL"] = req_protocol
+        self.response_protocol = "HTTP/%s.%s" % min(rp, sp)
+        
+        # If the Request-URI was an absoluteURI, use its location atom.
+        if location:
+            environ["SERVER_NAME"] = location
+        
+        # then all the http headers
+        try:
+            self.read_headers()
+        except ValueError, ex:
+            self.simple_response("400 Bad Request", repr(ex.args))
+            return
+        
+        mrbs = self.max_request_body_size
+        if mrbs and int(environ.get("CONTENT_LENGTH", 0)) > mrbs:
+            self.simple_response("413 Request Entity Too Large")
+            return
+        
+        # Persistent connection support
+        if self.response_protocol == "HTTP/1.1":
+            # Both server and client are HTTP/1.1
+            if environ.get("HTTP_CONNECTION", "") == "close":
+                self.close_connection = True
+        else:
+            # Either the server or client (or both) are HTTP/1.0
+            if environ.get("HTTP_CONNECTION", "") != "Keep-Alive":
+                self.close_connection = True
+        
+        # Transfer-Encoding support
+        te = None
+        if self.response_protocol == "HTTP/1.1":
+            te = environ.get("HTTP_TRANSFER_ENCODING")
+            if te:
+                te = [x.strip().lower() for x in te.split(",") if x.strip()]
+        
+        self.chunked_read = False
+        
+        if te:
+            for enc in te:
+                if enc == "chunked":
+                    self.chunked_read = True
+                else:
+                    # Note that, even if we see "chunked", we must reject
+                    # if there is an extension we don't recognize.
+                    self.simple_response("501 Unimplemented")
+                    self.close_connection = True
+                    return
+        
+        # From PEP 333:
+        # "Servers and gateways that implement HTTP 1.1 must provide
+        # transparent support for HTTP 1.1's "expect/continue" mechanism.
+        # This may be done in any of several ways:
+        #   1. Respond to requests containing an Expect: 100-continue request
+        #      with an immediate "100 Continue" response, and proceed normally.
+        #   2. Proceed with the request normally, but provide the application
+        #      with a wsgi.input stream that will send the "100 Continue"
+        #      response if/when the application first attempts to read from
+        #      the input stream. The read request must then remain blocked
+        #      until the client responds.
+        #   3. Wait until the client decides that the server does not support
+        #      expect/continue, and sends the request body on its own.
+        #      (This is suboptimal, and is not recommended.)
+        #
+        # We used to do 3, but are now doing 1. Maybe we'll do 2 someday,
+        # but it seems like it would be a big slowdown for such a rare case.
+        if environ.get("HTTP_EXPECT", "") == "100-continue":
+            self.simple_response(100)
+        
+        self.ready = True
+    
+    def read_headers(self):
+        """Read header lines from the incoming stream."""
+        environ = self.environ
+        
+        while True:
+            line = self.rfile.readline()
+            if not line:
+                # No more data--illegal end of headers
+                raise ValueError("Illegal end of headers.")
+            
+            if line == '\r\n':
+                # Normal end of headers
+                break
+            
+            if line[0] in ' \t':
+                # It's a continuation line.
+                v = line.strip()
+            else:
+                k, v = line.split(":", 1)
+                k, v = k.strip().upper(), v.strip()
+                envname = "HTTP_" + k.replace("-", "_")
+            
+            if k in comma_separated_headers:
+                existing = environ.get(envname)
+                if existing:
+                    v = ", ".join((existing, v))
+            environ[envname] = v
+        
+        ct = environ.pop("HTTP_CONTENT_TYPE", None)
+        if ct is not None:
+            environ["CONTENT_TYPE"] = ct
+        cl = environ.pop("HTTP_CONTENT_LENGTH", None)
+        if cl is not None:
+            environ["CONTENT_LENGTH"] = cl
+    
+    def decode_chunked(self):
+        """Decode the 'chunked' transfer coding."""
+        cl = 0
+        data = StringIO.StringIO()
+        while True:
+            line = self.rfile.readline().strip().split(";", 1)
+            chunk_size = int(line.pop(0), 16)
+            if chunk_size <= 0:
+                break
+##            if line: chunk_extension = line[0]
+            cl += chunk_size
+            data.write(self.rfile.read(chunk_size))
+            crlf = self.rfile.read(2)
+            if crlf != "\r\n":
+                self.simple_response("400 Bad Request",
+                                     "Bad chunked transfer coding "
+                                     "(expected '\\r\\n', got %r)" % crlf)
+                return
+        
+        # Grab any trailer headers
+        self.read_headers()
+        
+        data.seek(0)
+        self.environ["wsgi.input"] = data
+        self.environ["CONTENT_LENGTH"] = str(cl) or ""
+        return True
+    
+    def respond(self):
+        """Call the appropriate WSGI app and write its iterable output."""
+        # Set rfile.maxlen to ensure we don't read past Content-Length.
+        # This will also be used to read the entire request body if errors
+        # are raised before the app can read the body.
+        if self.chunked_read:
+            # If chunked, Content-Length will be 0.
+            self.rfile.maxlen = self.max_request_body_size
+        else:
+            cl = int(self.environ.get("CONTENT_LENGTH", 0))
+            if self.max_request_body_size:
+                self.rfile.maxlen = min(cl, self.max_request_body_size)
+            else:
+                self.rfile.maxlen = cl
+        self.rfile.bytes_read = 0
+        
+        try:
+            self._respond()
+        except MaxSizeExceeded:
+            if not self.sent_headers:
+                self.simple_response("413 Request Entity Too Large")
+            return
+    
+    def _respond(self):
+        if self.chunked_read:
+            if not self.decode_chunked():
+                self.close_connection = True
+                return
+        
+        response = self.wsgi_app(self.environ, self.start_response)
+        try:
+            for chunk in response:
+                # "The start_response callable must not actually transmit
+                # the response headers. Instead, it must store them for the
+                # server or gateway to transmit only after the first
+                # iteration of the application return value that yields
+                # a NON-EMPTY string, or upon the application's first
+                # invocation of the write() callable." (PEP 333)
+                if chunk:
+                    self.write(chunk)
+        finally:
+            if hasattr(response, "close"):
+                response.close()
+        
+        if (self.ready and not self.sent_headers):
+            self.sent_headers = True
+            self.send_headers()
+        if self.chunked_write:
+            self.wfile.sendall("0\r\n\r\n")
+    
+    def simple_response(self, status, msg=""):
+        """Write a simple response back to the client."""
+        status = str(status)
+        buf = ["%s %s\r\n" % (self.environ['ACTUAL_SERVER_PROTOCOL'], status),
+               "Content-Length: %s\r\n" % len(msg),
+               "Content-Type: text/plain\r\n"]
+        
+        if status[:3] == "413" and self.response_protocol == 'HTTP/1.1':
+            # Request Entity Too Large
+            self.close_connection = True
+            buf.append("Connection: close\r\n")
+        
+        buf.append("\r\n")
+        if msg:
+            buf.append(msg)
+        
+        try:
+            self.wfile.sendall("".join(buf))
+        except socket.error, x:
+            if x.args[0] not in socket_errors_to_ignore:
+                raise
+    
+    def start_response(self, status, headers, exc_info = None):
+        """WSGI callable to begin the HTTP response."""
+        # "The application may call start_response more than once,
+        # if and only if the exc_info argument is provided."
+        if self.started_response and not exc_info:
+            raise AssertionError("WSGI start_response called a second "
+                                 "time with no exc_info.")
+        
+        # "if exc_info is provided, and the HTTP headers have already been
+        # sent, start_response must raise an error, and should raise the
+        # exc_info tuple."
+        if self.sent_headers:
+            try:
+                raise exc_info[0], exc_info[1], exc_info[2]
+            finally:
+                exc_info = None
+        
+        self.started_response = True
+        self.status = status
+        self.outheaders.extend(headers)
+        return self.write
+    
+    def write(self, chunk):
+        """WSGI callable to write unbuffered data to the client.
+        
+        This method is also used internally by start_response (to write
+        data from the iterable returned by the WSGI application).
+        """
+        if not self.started_response:
+            raise AssertionError("WSGI write called before start_response.")
+        
+        if not self.sent_headers:
+            self.sent_headers = True
+            self.send_headers()
+        
+        if self.chunked_write and chunk:
+            buf = [hex(len(chunk))[2:], "\r\n", chunk, "\r\n"]
+            self.wfile.sendall("".join(buf))
+        else:
+            self.wfile.sendall(chunk)
+    
+    def send_headers(self):
+        """Assert, process, and send the HTTP response message-headers."""
+        hkeys = [key.lower() for key, value in self.outheaders]
+        status = int(self.status[:3])
+        
+        if status == 413:
+            # Request Entity Too Large. Close conn to avoid garbage.
+            self.close_connection = True
+        elif "content-length" not in hkeys:
+            # "All 1xx (informational), 204 (no content),
+            # and 304 (not modified) responses MUST NOT
+            # include a message-body." So no point chunking.
+            if status < 200 or status in (204, 205, 304):
+                pass
+            else:
+                if (self.response_protocol == 'HTTP/1.1'
+                    and self.environ["REQUEST_METHOD"] != 'HEAD'):
+                    # Use the chunked transfer-coding
+                    self.chunked_write = True
+                    self.outheaders.append(("Transfer-Encoding", "chunked"))
+                else:
+                    # Closing the conn is the only way to determine len.
+                    self.close_connection = True
+        
+        if "connection" not in hkeys:
+            if self.response_protocol == 'HTTP/1.1':
+                # Both server and client are HTTP/1.1 or better
+                if self.close_connection:
+                    self.outheaders.append(("Connection", "close"))
+            else:
+                # Server and/or client are HTTP/1.0
+                if not self.close_connection:
+                    self.outheaders.append(("Connection", "Keep-Alive"))
+        
+        if (not self.close_connection) and (not self.chunked_read):
+            # Read any remaining request body data on the socket.
+            # "If an origin server receives a request that does not include an
+            # Expect request-header field with the "100-continue" expectation,
+            # the request includes a request body, and the server responds
+            # with a final status code before reading the entire request body
+            # from the transport connection, then the server SHOULD NOT close
+            # the transport connection until it has read the entire request,
+            # or until the client closes the connection. Otherwise, the client
+            # might not reliably receive the response message. However, this
+            # requirement is not be construed as preventing a server from
+            # defending itself against denial-of-service attacks, or from
+            # badly broken client implementations."
+            size = self.rfile.maxlen - self.rfile.bytes_read
+            if size > 0:
+                self.rfile.read(size)
+        
+        if "date" not in hkeys:
+            self.outheaders.append(("Date", rfc822.formatdate()))
+        
+        if "server" not in hkeys:
+            self.outheaders.append(("Server", self.environ['SERVER_SOFTWARE']))
+        
+        buf = [self.environ['ACTUAL_SERVER_PROTOCOL'], " ", self.status, "\r\n"]
+        try:
+            buf += [k + ": " + v + "\r\n" for k, v in self.outheaders]
+        except TypeError:
+            if not isinstance(k, str):
+                raise TypeError("WSGI response header key %r is not a string.")
+            if not isinstance(v, str):
+                raise TypeError("WSGI response header value %r is not a string.")
+            else:
+                raise
+        buf.append("\r\n")
+        self.wfile.sendall("".join(buf))
+
+
+class NoSSLError(Exception):
+    """Exception raised when a client speaks HTTP to an HTTPS socket."""
+    pass
+
+
+class FatalSSLAlert(Exception):
+    """Exception raised when the SSL implementation signals a fatal alert."""
+    pass
+
+
+if not _fileobject_uses_str_type:
+    class CP_fileobject(socket._fileobject):
+        """Faux file object attached to a socket object."""
+
+        def sendall(self, data):
+            """Sendall for non-blocking sockets."""
+            while data:
+                try:
+                    bytes_sent = self.send(data)
+                    data = data[bytes_sent:]
+                except socket.error, e:
+                    if e.args[0] not in socket_errors_nonblocking:
+                        raise
+
+        def send(self, data):
+            return self._sock.send(data)
+
+        def flush(self):
+            if self._wbuf:
+                buffer = "".join(self._wbuf)
+                self._wbuf = []
+                self.sendall(buffer)
+
+        def recv(self, size):
+            while True:
+                try:
+                    return self._sock.recv(size)
+                except socket.error, e:
+                    if (e.args[0] not in socket_errors_nonblocking
+                        and e.args[0] not in socket_error_eintr):
+                        raise
+
+        def read(self, size=-1):
+            # Use max, disallow tiny reads in a loop as they are very inefficient.
+            # We never leave read() with any leftover data from a new recv() call
+            # in our internal buffer.
+            rbufsize = max(self._rbufsize, self.default_bufsize)
+            # Our use of StringIO rather than lists of string objects returned by
+            # recv() minimizes memory usage and fragmentation that occurs when
+            # rbufsize is large compared to the typical return value of recv().
+            buf = self._rbuf
+            buf.seek(0, 2)  # seek end
+            if size < 0:
+                # Read until EOF
+                self._rbuf = StringIO.StringIO()  # reset _rbuf.  we consume it via buf.
+                while True:
+                    data = self.recv(rbufsize)
+                    if not data:
+                        break
+                    buf.write(data)
+                return buf.getvalue()
+            else:
+                # Read until size bytes or EOF seen, whichever comes first
+                buf_len = buf.tell()
+                if buf_len >= size:
+                    # Already have size bytes in our buffer?  Extract and return.
+                    buf.seek(0)
+                    rv = buf.read(size)
+                    self._rbuf = StringIO.StringIO()
+                    self._rbuf.write(buf.read())
+                    return rv
+
+                self._rbuf = StringIO.StringIO()  # reset _rbuf.  we consume it via buf.
+                while True:
+                    left = size - buf_len
+                    # recv() will malloc the amount of memory given as its
+                    # parameter even though it often returns much less data
+                    # than that.  The returned data string is short lived
+                    # as we copy it into a StringIO and free it.  This avoids
+                    # fragmentation issues on many platforms.
+                    data = self.recv(left)
+                    if not data:
+                        break
+                    n = len(data)
+                    if n == size and not buf_len:
+                        # Shortcut.  Avoid buffer data copies when:
+                        # - We have no data in our buffer.
+                        # AND
+                        # - Our call to recv returned exactly the
+                        #   number of bytes we were asked to read.
+                        return data
+                    if n == left:
+                        buf.write(data)
+                        del data  # explicit free
+                        break
+                    assert n <= left, "recv(%d) returned %d bytes" % (left, n)
+                    buf.write(data)
+                    buf_len += n
+                    del data  # explicit free
+                    #assert buf_len == buf.tell()
+                return buf.getvalue()
+
+        def readline(self, size=-1):
+            buf = self._rbuf
+            buf.seek(0, 2)  # seek end
+            if buf.tell() > 0:
+                # check if we already have it in our buffer
+                buf.seek(0)
+                bline = buf.readline(size)
+                if bline.endswith('\n') or len(bline) == size:
+                    self._rbuf = StringIO.StringIO()
+                    self._rbuf.write(buf.read())
+                    return bline
+                del bline
+            if size < 0:
+                # Read until \n or EOF, whichever comes first
+                if self._rbufsize <= 1:
+                    # Speed up unbuffered case
+                    buf.seek(0)
+                    buffers = [buf.read()]
+                    self._rbuf = StringIO.StringIO()  # reset _rbuf.  we consume it via buf.
+                    data = None
+                    recv = self.recv
+                    while data != "\n":
+                        data = recv(1)
+                        if not data:
+                            break
+                        buffers.append(data)
+                    return "".join(buffers)
+
+                buf.seek(0, 2)  # seek end
+                self._rbuf = StringIO.StringIO()  # reset _rbuf.  we consume it via buf.
+                while True:
+                    data = self.recv(self._rbufsize)
+                    if not data:
+                        break
+                    nl = data.find('\n')
+                    if nl >= 0:
+                        nl += 1
+                        buf.write(data[:nl])
+                        self._rbuf.write(data[nl:])
+                        del data
+                        break
+                    buf.write(data)
+                return buf.getvalue()
+            else:
+                # Read until size bytes or \n or EOF seen, whichever comes first
+                buf.seek(0, 2)  # seek end
+                buf_len = buf.tell()
+                if buf_len >= size:
+                    buf.seek(0)
+                    rv = buf.read(size)
+                    self._rbuf = StringIO.StringIO()
+                    self._rbuf.write(buf.read())
+                    return rv
+                self._rbuf = StringIO.StringIO()  # reset _rbuf.  we consume it via buf.
+                while True:
+                    data = self.recv(self._rbufsize)
+                    if not data:
+                        break
+                    left = size - buf_len
+                    # did we just receive a newline?
+                    nl = data.find('\n', 0, left)
+                    if nl >= 0:
+                        nl += 1
+                        # save the excess data to _rbuf
+                        self._rbuf.write(data[nl:])
+                        if buf_len:
+                            buf.write(data[:nl])
+                            break
+                        else:
+                            # Shortcut.  Avoid data copy through buf when returning
+                            # a substring of our first recv().
+                            return data[:nl]
+                    n = len(data)
+                    if n == size and not buf_len:
+                        # Shortcut.  Avoid data copy through buf when
+                        # returning exactly all of our first recv().
+                        return data
+                    if n >= left:
+                        buf.write(data[:left])
+                        self._rbuf.write(data[left:])
+                        break
+                    buf.write(data)
+                    buf_len += n
+                    #assert buf_len == buf.tell()
+                return buf.getvalue()
+
+else:
+    class CP_fileobject(socket._fileobject):
+        """Faux file object attached to a socket object."""
+
+        def sendall(self, data):
+            """Sendall for non-blocking sockets."""
+            while data:
+                try:
+                    bytes_sent = self.send(data)
+                    data = data[bytes_sent:]
+                except socket.error, e:
+                    if e.args[0] not in socket_errors_nonblocking:
+                        raise
+
+        def send(self, data):
+            return self._sock.send(data)
+
+        def flush(self):
+            if self._wbuf:
+                buffer = "".join(self._wbuf)
+                self._wbuf = []
+                self.sendall(buffer)
+
+        def recv(self, size):
+            while True:
+                try:
+                    return self._sock.recv(size)
+                except socket.error, e:
+                    if (e.args[0] not in socket_errors_nonblocking
+                        and e.args[0] not in socket_error_eintr):
+                        raise
+
+        def read(self, size=-1):
+            if size < 0:
+                # Read until EOF
+                buffers = [self._rbuf]
+                self._rbuf = ""
+                if self._rbufsize <= 1:
+                    recv_size = self.default_bufsize
+                else:
+                    recv_size = self._rbufsize
+
+                while True:
+                    data = self.recv(recv_size)
+                    if not data:
+                        break
+                    buffers.append(data)
+                return "".join(buffers)
+            else:
+                # Read until size bytes or EOF seen, whichever comes first
+                data = self._rbuf
+                buf_len = len(data)
+                if buf_len >= size:
+                    self._rbuf = data[size:]
+                    return data[:size]
+                buffers = []
+                if data:
+                    buffers.append(data)
+                self._rbuf = ""
+                while True:
+                    left = size - buf_len
+                    recv_size = max(self._rbufsize, left)
+                    data = self.recv(recv_size)
+                    if not data:
+                        break
+                    buffers.append(data)
+                    n = len(data)
+                    if n >= left:
+                        self._rbuf = data[left:]
+                        buffers[-1] = data[:left]
+                        break
+                    buf_len += n
+                return "".join(buffers)
+
+        def readline(self, size=-1):
+            data = self._rbuf
+            if size < 0:
+                # Read until \n or EOF, whichever comes first
+                if self._rbufsize <= 1:
+                    # Speed up unbuffered case
+                    assert data == ""
+                    buffers = []
+                    while data != "\n":
+                        data = self.recv(1)
+                        if not data:
+                            break
+                        buffers.append(data)
+                    return "".join(buffers)
+                nl = data.find('\n')
+                if nl >= 0:
+                    nl += 1
+                    self._rbuf = data[nl:]
+                    return data[:nl]
+                buffers = []
+                if data:
+                    buffers.append(data)
+                self._rbuf = ""
+                while True:
+                    data = self.recv(self._rbufsize)
+                    if not data:
+                        break
+                    buffers.append(data)
+                    nl = data.find('\n')
+                    if nl >= 0:
+                        nl += 1
+                        self._rbuf = data[nl:]
+                        buffers[-1] = data[:nl]
+                        break
+                return "".join(buffers)
+            else:
+                # Read until size bytes or \n or EOF seen, whichever comes first
+                nl = data.find('\n', 0, size)
+                if nl >= 0:
+                    nl += 1
+                    self._rbuf = data[nl:]
+                    return data[:nl]
+                buf_len = len(data)
+                if buf_len >= size:
+                    self._rbuf = data[size:]
+                    return data[:size]
+                buffers = []
+                if data:
+                    buffers.append(data)
+                self._rbuf = ""
+                while True:
+                    data = self.recv(self._rbufsize)
+                    if not data:
+                        break
+                    buffers.append(data)
+                    left = size - buf_len
+                    nl = data.find('\n', 0, left)
+                    if nl >= 0:
+                        nl += 1
+                        self._rbuf = data[nl:]
+                        buffers[-1] = data[:nl]
+                        break
+                    n = len(data)
+                    if n >= left:
+                        self._rbuf = data[left:]
+                        buffers[-1] = data[:left]
+                        break
+                    buf_len += n
+                return "".join(buffers)
+    
+
+class SSL_fileobject(CP_fileobject):
+    """SSL file object attached to a socket object."""
+    
+    ssl_timeout = 3
+    ssl_retry = .01
+    
+    def _safe_call(self, is_reader, call, *args, **kwargs):
+        """Wrap the given call with SSL error-trapping.
+        
+        is_reader: if False EOF errors will be raised. If True, EOF errors
+            will return "" (to emulate normal sockets).
+        """
+        start = time.time()
+        while True:
+            try:
+                return call(*args, **kwargs)
+            except SSL.WantReadError:
+                # Sleep and try again. This is dangerous, because it means
+                # the rest of the stack has no way of differentiating
+                # between a "new handshake" error and "client dropped".
+                # Note this isn't an endless loop: there's a timeout below.
+                time.sleep(self.ssl_retry)
+            except SSL.WantWriteError:
+                time.sleep(self.ssl_retry)
+            except SSL.SysCallError, e:
+                if is_reader and e.args == (-1, 'Unexpected EOF'):
+                    return ""
+                
+                errnum = e.args[0]
+                if is_reader and errnum in socket_errors_to_ignore:
+                    return ""
+                raise socket.error(errnum)
+            except SSL.Error, e:
+                if is_reader and e.args == (-1, 'Unexpected EOF'):
+                    return ""
+                
+                thirdarg = None
+                try:
+                    thirdarg = e.args[0][0][2]
+                except IndexError:
+                    pass
+                
+                if thirdarg == 'http request':
+                    # The client is talking HTTP to an HTTPS server.
+                    raise NoSSLError()
+                raise FatalSSLAlert(*e.args)
+            except:
+                raise
+            
+            if time.time() - start > self.ssl_timeout:
+                raise socket.timeout("timed out")
+
+    def recv(self, *args, **kwargs):
+        buf = []
+        r = super(SSL_fileobject, self).recv
+        while True:
+            data = self._safe_call(True, r, *args, **kwargs)
+            buf.append(data)
+            p = self._sock.pending()
+            if not p:
+                return "".join(buf)
+    
+    def sendall(self, *args, **kwargs):
+        return self._safe_call(False, super(SSL_fileobject, self).sendall, *args, **kwargs)
+
+    def send(self, *args, **kwargs):
+        return self._safe_call(False, super(SSL_fileobject, self).send, *args, **kwargs)
+
+
+class HTTPConnection(object):
+    """An HTTP connection (active socket).
+    
+    socket: the raw socket object (usually TCP) for this connection.
+    wsgi_app: the WSGI application for this server/connection.
+    environ: a WSGI environ template. This will be copied for each request.
+    
+    rfile: a fileobject for reading from the socket.
+    send: a function for writing (+ flush) to the socket.
+    """
+    
+    rbufsize = -1
+    RequestHandlerClass = HTTPRequest
+    environ = {"wsgi.version": (1, 0),
+               "wsgi.url_scheme": "http",
+               "wsgi.multithread": True,
+               "wsgi.multiprocess": False,
+               "wsgi.run_once": False,
+               "wsgi.errors": sys.stderr,
+               }
+    
+    def __init__(self, sock, wsgi_app, environ):
+        self.socket = sock
+        self.wsgi_app = wsgi_app
+        
+        # Copy the class environ into self.
+        self.environ = self.environ.copy()
+        self.environ.update(environ)
+        
+        if SSL and isinstance(sock, SSL.ConnectionType):
+            timeout = sock.gettimeout()
+            self.rfile = SSL_fileobject(sock, "rb", self.rbufsize)
+            self.rfile.ssl_timeout = timeout
+            self.wfile = SSL_fileobject(sock, "wb", -1)
+            self.wfile.ssl_timeout = timeout
+        else:
+            self.rfile = CP_fileobject(sock, "rb", self.rbufsize)
+            self.wfile = CP_fileobject(sock, "wb", -1)
+        
+        # Wrap wsgi.input but not HTTPConnection.rfile itself.
+        # We're also not setting maxlen yet; we'll do that separately
+        # for headers and body for each iteration of self.communicate
+        # (if maxlen is 0 the wrapper doesn't check length).
+        self.environ["wsgi.input"] = SizeCheckWrapper(self.rfile, 0)
+    
+    def communicate(self):
+        """Read each request and respond appropriately."""
+        try:
+            while True:
+                # (re)set req to None so that if something goes wrong in
+                # the RequestHandlerClass constructor, the error doesn't
+                # get written to the previous request.
+                req = None
+                req = self.RequestHandlerClass(self.wfile, self.environ,
+                                               self.wsgi_app)
+                
+                # This order of operations should guarantee correct pipelining.
+                req.parse_request()
+                if not req.ready:
+                    return
+                
+                req.respond()
+                if req.close_connection:
+                    return
+        
+        except socket.error, e:
+            errnum = e.args[0]
+            if errnum == 'timed out':
+                if req and not req.sent_headers:
+                    req.simple_response("408 Request Timeout")
+            elif errnum not in socket_errors_to_ignore:
+                if req and not req.sent_headers:
+                    req.simple_response("500 Internal Server Error",
+                                        format_exc())
+            return
+        except (KeyboardInterrupt, SystemExit):
+            raise
+        except FatalSSLAlert, e:
+            # Close the connection.
+            return
+        except NoSSLError:
+            # Unwrap our wfile
+            req.wfile = CP_fileobject(self.socket, "wb", -1)
+            if req and not req.sent_headers:
+                req.simple_response("400 Bad Request",
+                    "The client sent a plain HTTP request, but "
+                    "this server only speaks HTTPS on this port.")
+        except Exception, e:
+            if req and not req.sent_headers:
+                req.simple_response("500 Internal Server Error", format_exc())
+    
+    def close(self):
+        """Close the socket underlying this connection."""
+        self.rfile.close()
+        
+        # Python's socket module does NOT call close on the kernel socket
+        # when you call socket.close(). We do so manually here because we
+        # want this server to send a FIN TCP segment immediately. Note this
+        # must be called *before* calling socket.close(), because the latter
+        # drops its reference to the kernel socket.
+        self.socket._sock.close()
+        
+        self.socket.close()
+
+
+def format_exc(limit=None):
+    """Like print_exc() but return a string. Backport for Python 2.3."""
+    try:
+        etype, value, tb = sys.exc_info()
+        return ''.join(traceback.format_exception(etype, value, tb, limit))
+    finally:
+        etype = value = tb = None
+
+
+_SHUTDOWNREQUEST = None
+
+class WorkerThread(threading.Thread):
+    """Thread which continuously polls a Queue for Connection objects.
+    
+    server: the HTTP Server which spawned this thread, and which owns the
+        Queue and is placing active connections into it.
+    ready: a simple flag for the calling server to know when this thread
+        has begun polling the Queue.
+    
+    Due to the timing issues of polling a Queue, a WorkerThread does not
+    check its own 'ready' flag after it has started. To stop the thread,
+    it is necessary to stick a _SHUTDOWNREQUEST object onto the Queue
+    (one for each running WorkerThread).
+    """
+    
+    conn = None
+    
+    def __init__(self, server):
+        self.ready = False
+        self.server = server
+        threading.Thread.__init__(self)
+    
+    def run(self):
+        try:
+            self.ready = True
+            while True:
+                conn = self.server.requests.get()
+                if conn is _SHUTDOWNREQUEST:
+                    return
+                
+                self.conn = conn
+                try:
+                    conn.communicate()
+                finally:
+                    conn.close()
+                    self.conn = None
+        except (KeyboardInterrupt, SystemExit), exc:
+            self.server.interrupt = exc
+
+
+class ThreadPool(object):
+    """A Request Queue for the CherryPyWSGIServer which pools threads.
+    
+    ThreadPool objects must provide min, get(), put(obj), start()
+    and stop(timeout) attributes.
+    """
+    
+    def __init__(self, server, min=10, max=-1):
+        self.server = server
+        self.min = min
+        self.max = max
+        self._threads = []
+        self._queue = Queue.Queue()
+        self.get = self._queue.get
+    
+    def start(self):
+        """Start the pool of threads."""
+        for i in xrange(self.min):
+            self._threads.append(WorkerThread(self.server))
+        for worker in self._threads:
+            worker.setName("CP WSGIServer " + worker.getName())
+            worker.start()
+        for worker in self._threads:
+            while not worker.ready:
+                time.sleep(.1)
+    
+    def _get_idle(self):
+        """Number of worker threads which are idle. Read-only."""
+        return len([t for t in self._threads if t.conn is None])
+    idle = property(_get_idle, doc=_get_idle.__doc__)
+    
+    def put(self, obj):
+        self._queue.put(obj)
+        if obj is _SHUTDOWNREQUEST:
+            return
+    
+    def grow(self, amount):
+        """Spawn new worker threads (not above self.max)."""
+        for i in xrange(amount):
+            if self.max > 0 and len(self._threads) >= self.max:
+                break
+            worker = WorkerThread(self.server)
+            worker.setName("CP WSGIServer " + worker.getName())
+            self._threads.append(worker)
+            worker.start()
+    
+    def shrink(self, amount):
+        """Kill off worker threads (not below self.min)."""
+        # Grow/shrink the pool if necessary.
+        # Remove any dead threads from our list
+        for t in self._threads:
+            if not t.isAlive():
+                self._threads.remove(t)
+                amount -= 1
+        
+        if amount > 0:
+            for i in xrange(min(amount, len(self._threads) - self.min)):
+                # Put a number of shutdown requests on the queue equal
+                # to 'amount'. Once each of those is processed by a worker,
+                # that worker will terminate and be culled from our list
+                # in self.put.
+                self._queue.put(_SHUTDOWNREQUEST)
+    
+    def stop(self, timeout=5):
+        # Must shut down threads here so the code that calls
+        # this method can know when all threads are stopped.
+        for worker in self._threads:
+            self._queue.put(_SHUTDOWNREQUEST)
+        
+        # Don't join currentThread (when stop is called inside a request).
+        current = threading.currentThread()
+        while self._threads:
+            worker = self._threads.pop()
+            if worker is not current and worker.isAlive():
+                try:
+                    if timeout is None or timeout < 0:
+                        worker.join()
+                    else:
+                        worker.join(timeout)
+                        if worker.isAlive():
+                            # We exhausted the timeout.
+                            # Forcibly shut down the socket.
+                            c = worker.conn
+                            if c and not c.rfile.closed:
+                                if SSL and isinstance(c.socket, SSL.ConnectionType):
+                                    # pyOpenSSL.socket.shutdown takes no args
+                                    c.socket.shutdown()
+                                else:
+                                    c.socket.shutdown(socket.SHUT_RD)
+                            worker.join()
+                except (AssertionError,
+                        # Ignore repeated Ctrl-C.
+                        # See http://www.cherrypy.org/ticket/691.
+                        KeyboardInterrupt), exc1:
+                    pass
+
+
+
+class SSLConnection:
+    """A thread-safe wrapper for an SSL.Connection.
+    
+    *args: the arguments to create the wrapped SSL.Connection(*args).
+    """
+    
+    def __init__(self, *args):
+        self._ssl_conn = SSL.Connection(*args)
+        self._lock = threading.RLock()
+    
+    for f in ('get_context', 'pending', 'send', 'write', 'recv', 'read',
+              'renegotiate', 'bind', 'listen', 'connect', 'accept',
+              'setblocking', 'fileno', 'shutdown', 'close', 'get_cipher_list',
+              'getpeername', 'getsockname', 'getsockopt', 'setsockopt',
+              'makefile', 'get_app_data', 'set_app_data', 'state_string',
+              'sock_shutdown', 'get_peer_certificate', 'want_read',
+              'want_write', 'set_connect_state', 'set_accept_state',
+              'connect_ex', 'sendall', 'settimeout'):
+        exec """def %s(self, *args):
+        self._lock.acquire()
+        try:
+            return self._ssl_conn.%s(*args)
+        finally:
+            self._lock.release()
+""" % (f, f)
+
+
+try:
+    import fcntl
+except ImportError:
+    try:
+        from ctypes import windll, WinError
+    except ImportError:
+        def prevent_socket_inheritance(sock):
+            """Dummy function, since neither fcntl nor ctypes are available."""
+            pass
+    else:
+        def prevent_socket_inheritance(sock):
+            """Mark the given socket fd as non-inheritable (Windows)."""
+            if not windll.kernel32.SetHandleInformation(sock.fileno(), 1, 0):
+                raise WinError()
+else:
+    def prevent_socket_inheritance(sock):
+        """Mark the given socket fd as non-inheritable (POSIX)."""
+        fd = sock.fileno()
+        old_flags = fcntl.fcntl(fd, fcntl.F_GETFD)
+        fcntl.fcntl(fd, fcntl.F_SETFD, old_flags | fcntl.FD_CLOEXEC)
+
+
+class CherryPyWSGIServer(object):
+    """An HTTP server for WSGI.
+    
+    bind_addr: The interface on which to listen for connections.
+        For TCP sockets, a (host, port) tuple. Host values may be any IPv4
+        or IPv6 address, or any valid hostname. The string 'localhost' is a
+        synonym for '127.0.0.1' (or '::1', if your hosts file prefers IPv6).
+        The string '0.0.0.0' is a special IPv4 entry meaning "any active
+        interface" (INADDR_ANY), and '::' is the similar IN6ADDR_ANY for
+        IPv6. The empty string or None are not allowed.
+        
+        For UNIX sockets, supply the filename as a string.
+    wsgi_app: the WSGI 'application callable'; multiple WSGI applications
+        may be passed as (path_prefix, app) pairs.
+    numthreads: the number of worker threads to create (default 10).
+    server_name: the string to set for WSGI's SERVER_NAME environ entry.
+        Defaults to socket.gethostname().
+    max: the maximum number of queued requests (defaults to -1 = no limit).
+    request_queue_size: the 'backlog' argument to socket.listen();
+        specifies the maximum number of queued connections (default 5).
+    timeout: the timeout in seconds for accepted connections (default 10).
+    
+    nodelay: if True (the default since 3.1), sets the TCP_NODELAY socket
+        option.
+    
+    protocol: the version string to write in the Status-Line of all
+        HTTP responses. For example, "HTTP/1.1" (the default). This
+        also limits the supported features used in the response.
+    
+    
+    SSL/HTTPS
+    ---------
+    The OpenSSL module must be importable for SSL functionality.
+    You can obtain it from http://pyopenssl.sourceforge.net/
+    
+    ssl_certificate: the filename of the server SSL certificate.
+    ssl_privatekey: the filename of the server's private key file.
+    
+    If either of these is None (both are None by default), this server
+    will not use SSL. If both are given and are valid, they will be read
+    on server start and used in the SSL context for the listening socket.
+    """
+    
+    protocol = "HTTP/1.1"
+    _bind_addr = "127.0.0.1"
+    version = "CherryPy/3.1.1"
+    ready = False
+    _interrupt = None
+    
+    nodelay = True
+    
+    ConnectionClass = HTTPConnection
+    environ = {}
+    
+    # Paths to certificate and private key files
+    ssl_certificate = None
+    ssl_private_key = None
+    
+    def __init__(self, bind_addr, wsgi_app, numthreads=10, server_name=None,
+                 max=-1, request_queue_size=5, timeout=10, shutdown_timeout=5):
+        self.requests = ThreadPool(self, min=numthreads or 1, max=max)
+        
+        if callable(wsgi_app):
+            # We've been handed a single wsgi_app, in CP-2.1 style.
+            # Assume it's mounted at "".
+            self.wsgi_app = wsgi_app
+        else:
+            # We've been handed a list of (path_prefix, wsgi_app) tuples,
+            # so that the server can call different wsgi_apps, and also
+            # correctly set SCRIPT_NAME.
+            warnings.warn("The ability to pass multiple apps is deprecated "
+                          "and will be removed in 3.2. You should explicitly "
+                          "include a WSGIPathInfoDispatcher instead.",
+                          DeprecationWarning)
+            self.wsgi_app = WSGIPathInfoDispatcher(wsgi_app)
+        
+        self.bind_addr = bind_addr
+        if not server_name:
+            server_name = socket.gethostname()
+        self.server_name = server_name
+        self.request_queue_size = request_queue_size
+        
+        self.timeout = timeout
+        self.shutdown_timeout = shutdown_timeout
+    
+    def _get_numthreads(self):
+        return self.requests.min
+    def _set_numthreads(self, value):
+        self.requests.min = value
+    numthreads = property(_get_numthreads, _set_numthreads)
+    
+    def __str__(self):
+        return "%s.%s(%r)" % (self.__module__, self.__class__.__name__,
+                              self.bind_addr)
+    
+    def _get_bind_addr(self):
+        return self._bind_addr
+    def _set_bind_addr(self, value):
+        if isinstance(value, tuple) and value[0] in ('', None):
+            # Despite the socket module docs, using '' does not
+            # allow AI_PASSIVE to work. Passing None instead
+            # returns '0.0.0.0' like we want. In other words:
+            #     host    AI_PASSIVE     result
+            #      ''         Y         192.168.x.y
+            #      ''         N         192.168.x.y
+            #     None        Y         0.0.0.0
+            #     None        N         127.0.0.1
+            # But since you can get the same effect with an explicit
+            # '0.0.0.0', we deny both the empty string and None as values.
+            raise ValueError("Host values of '' or None are not allowed. "
+                             "Use '0.0.0.0' (IPv4) or '::' (IPv6) instead "
+                             "to listen on all active interfaces.")
+        self._bind_addr = value
+    bind_addr = property(_get_bind_addr, _set_bind_addr,
+        doc="""The interface on which to listen for connections.
+        
+        For TCP sockets, a (host, port) tuple. Host values may be any IPv4
+        or IPv6 address, or any valid hostname. The string 'localhost' is a
+        synonym for '127.0.0.1' (or '::1', if your hosts file prefers IPv6).
+        The string '0.0.0.0' is a special IPv4 entry meaning "any active
+        interface" (INADDR_ANY), and '::' is the similar IN6ADDR_ANY for
+        IPv6. The empty string or None are not allowed.
+        
+        For UNIX sockets, supply the filename as a string.""")
+    
+    def start(self):
+        """Run the server forever."""
+        # We don't have to trap KeyboardInterrupt or SystemExit here,
+        # because cherrpy.server already does so, calling self.stop() for us.
+        # If you're using this server with another framework, you should
+        # trap those exceptions in whatever code block calls start().
+        self._interrupt = None
+        
+        # Select the appropriate socket
+        if isinstance(self.bind_addr, basestring):
+            # AF_UNIX socket
+            
+            # So we can reuse the socket...
+            try: os.unlink(self.bind_addr)
+            except: pass
+            
+            # So everyone can access the socket...
+            try: os.chmod(self.bind_addr, 0777)
+            except: pass
+            
+            info = [(socket.AF_UNIX, socket.SOCK_STREAM, 0, "", self.bind_addr)]
+        else:
+            # AF_INET or AF_INET6 socket
+            # Get the correct address family for our host (allows IPv6 addresses)
+            host, port = self.bind_addr
+            try:
+                info = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
+                                          socket.SOCK_STREAM, 0, socket.AI_PASSIVE)
+            except socket.gaierror:
+                # Probably a DNS issue. Assume IPv4.
+                info = [(socket.AF_INET, socket.SOCK_STREAM, 0, "", self.bind_addr)]
+        
+        self.socket = None
+        msg = "No socket could be created"
+        for res in info:
+            af, socktype, proto, canonname, sa = res
+            try:
+                self.bind(af, socktype, proto)
+            except socket.error, msg:
+                if self.socket:
+                    self.socket.close()
+                self.socket = None
+                continue
+            break
+        if not self.socket:
+            raise socket.error, msg
+        
+        # Timeout so KeyboardInterrupt can be caught on Win32
+        self.socket.settimeout(1)
+        self.socket.listen(self.request_queue_size)
+        
+        # Create worker threads
+        self.requests.start()
+        
+        self.ready = True
+        while self.ready:
+            self.tick()
+            if self.interrupt:
+                while self.interrupt is True:
+                    # Wait for self.stop() to complete. See _set_interrupt.
+                    time.sleep(0.1)
+                if self.interrupt:
+                    raise self.interrupt
+    
+    def bind(self, family, type, proto=0):
+        """Create (or recreate) the actual socket object."""
+        self.socket = socket.socket(family, type, proto)
+        prevent_socket_inheritance(self.socket)
+        self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+        if self.nodelay:
+            self.socket.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
+        if self.ssl_certificate and self.ssl_private_key:
+            if SSL is None:
+                raise ImportError("You must install pyOpenSSL to use HTTPS.")
+            
+            # See http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/442473
+            ctx = SSL.Context(SSL.SSLv23_METHOD)
+            ctx.use_privatekey_file(self.ssl_private_key)
+            ctx.use_certificate_file(self.ssl_certificate)
+            self.socket = SSLConnection(ctx, self.socket)
+            self.populate_ssl_environ()
+            
+            # If listening on the IPV6 any address ('::' = IN6ADDR_ANY),
+            # activate dual-stack. See http://www.cherrypy.org/ticket/871.
+            if (not isinstance(self.bind_addr, basestring)
+                and self.bind_addr[0] == '::' and family == socket.AF_INET6):
+                try:
+                    self.socket.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 0)
+                except (AttributeError, socket.error):
+                    # Apparently, the socket option is not available in
+                    # this machine's TCP stack
+                    pass
+        
+        self.socket.bind(self.bind_addr)
+    
+    def tick(self):
+        """Accept a new connection and put it on the Queue."""
+        try:
+            s, addr = self.socket.accept()
+            prevent_socket_inheritance(s)
+            if not self.ready:
+                return
+            if hasattr(s, 'settimeout'):
+                s.settimeout(self.timeout)
+            
+            environ = self.environ.copy()
+            # SERVER_SOFTWARE is common for IIS. It's also helpful for
+            # us to pass a default value for the "Server" response header.
+            if environ.get("SERVER_SOFTWARE") is None:
+                environ["SERVER_SOFTWARE"] = "%s WSGI Server" % self.version
+            # set a non-standard environ entry so the WSGI app can know what
+            # the *real* server protocol is (and what features to support).
+            # See http://www.faqs.org/rfcs/rfc2145.html.
+            environ["ACTUAL_SERVER_PROTOCOL"] = self.protocol
+            environ["SERVER_NAME"] = self.server_name
+            
+            if isinstance(self.bind_addr, basestring):
+                # AF_UNIX. This isn't really allowed by WSGI, which doesn't
+                # address unix domain sockets. But it's better than nothing.
+                environ["SERVER_PORT"] = ""
+            else:
+                environ["SERVER_PORT"] = str(self.bind_addr[1])
+                # optional values
+                # Until we do DNS lookups, omit REMOTE_HOST
+                environ["REMOTE_ADDR"] = addr[0]
+                environ["REMOTE_PORT"] = str(addr[1])
+            
+            conn = self.ConnectionClass(s, self.wsgi_app, environ)
+            self.requests.put(conn)
+        except socket.timeout:
+            # The only reason for the timeout in start() is so we can
+            # notice keyboard interrupts on Win32, which don't interrupt
+            # accept() by default
+            return
+        except socket.error, x:
+            if x.args[0] in socket_error_eintr:
+                # I *think* this is right. EINTR should occur when a signal
+                # is received during the accept() call; all docs say retry
+                # the call, and I *think* I'm reading it right that Python
+                # will then go ahead and poll for and handle the signal
+                # elsewhere. See http://www.cherrypy.org/ticket/707.
+                return
+            if x.args[0] in socket_errors_nonblocking:
+                # Just try again. See http://www.cherrypy.org/ticket/479.
+                return
+            if x.args[0] in socket_errors_to_ignore:
+                # Our socket was closed.
+                # See http://www.cherrypy.org/ticket/686.
+                return
+            raise
+    
+    def _get_interrupt(self):
+        return self._interrupt
+    def _set_interrupt(self, interrupt):
+        self._interrupt = True
+        self.stop()
+        self._interrupt = interrupt
+    interrupt = property(_get_interrupt, _set_interrupt,
+                         doc="Set this to an Exception instance to "
+                             "interrupt the server.")
+    
+    def stop(self):
+        """Gracefully shutdown a server that is serving forever."""
+        self.ready = False
+        
+        sock = getattr(self, "socket", None)
+        if sock:
+            if not isinstance(self.bind_addr, basestring):
+                # Touch our own socket to make accept() return immediately.
+                try:
+                    host, port = sock.getsockname()[:2]
+                except socket.error, x:
+                    if x.args[1] != "Bad file descriptor":
+                        raise
+                else:
+                    # Note that we're explicitly NOT using AI_PASSIVE,
+                    # here, because we want an actual IP to touch.
+                    # localhost won't work if we've bound to a public IP,
+                    # but it will if we bound to '0.0.0.0' (INADDR_ANY).
+                    for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC,
+                                                  socket.SOCK_STREAM):
+                        af, socktype, proto, canonname, sa = res
+                        s = None
+                        try:
+                            s = socket.socket(af, socktype, proto)
+                            # See http://groups.google.com/group/cherrypy-users/
+                            #        browse_frm/thread/bbfe5eb39c904fe0
+                            s.settimeout(1.0)
+                            s.connect((host, port))
+                            s.close()
+                        except socket.error:
+                            if s:
+                                s.close()
+            if hasattr(sock, "close"):
+                sock.close()
+            self.socket = None
+        
+        self.requests.stop(self.shutdown_timeout)
+    
+    def populate_ssl_environ(self):
+        """Create WSGI environ entries to be merged into each request."""
+        cert = open(self.ssl_certificate, 'rb').read()
+        cert = crypto.load_certificate(crypto.FILETYPE_PEM, cert)
+        ssl_environ = {
+            "wsgi.url_scheme": "https",
+            "HTTPS": "on",
+            # pyOpenSSL doesn't provide access to any of these AFAICT
+##            'SSL_PROTOCOL': 'SSLv2',
+##            SSL_CIPHER 	string 	The cipher specification name
+##            SSL_VERSION_INTERFACE 	string 	The mod_ssl program version
+##            SSL_VERSION_LIBRARY 	string 	The OpenSSL program version
+            }
+        
+        # Server certificate attributes
+        ssl_environ.update({
+            'SSL_SERVER_M_VERSION': cert.get_version(),
+            'SSL_SERVER_M_SERIAL': cert.get_serial_number(),
+##            'SSL_SERVER_V_START': Validity of server's certificate (start time),
+##            'SSL_SERVER_V_END': Validity of server's certificate (end time),
+            })
+        
+        for prefix, dn in [("I", cert.get_issuer()),
+                           ("S", cert.get_subject())]:
+            # X509Name objects don't seem to have a way to get the
+            # complete DN string. Use str() and slice it instead,
+            # because str(dn) == "<X509Name object '/C=US/ST=...'>"
+            dnstr = str(dn)[18:-2]
+            
+            wsgikey = 'SSL_SERVER_%s_DN' % prefix
+            ssl_environ[wsgikey] = dnstr
+            
+            # The DN should be of the form: /k1=v1/k2=v2, but we must allow
+            # for any value to contain slashes itself (in a URL).
+            while dnstr:
+                pos = dnstr.rfind("=")
+                dnstr, value = dnstr[:pos], dnstr[pos + 1:]
+                pos = dnstr.rfind("/")
+                dnstr, key = dnstr[:pos], dnstr[pos + 1:]
+                if key and value:
+                    wsgikey = 'SSL_SERVER_%s_DN_%s' % (prefix, key)
+                    ssl_environ[wsgikey] = value
+        
+        self.environ.update(ssl_environ)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiutils_server.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiutils_server.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/PasteScript-1.7.3-py2.6.egg/paste/script/wsgiutils_server.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,19 @@
+# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
+# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
+from paste.script.serve import ensure_port_cleanup
+from paste.translogger import TransLogger
+
+def run_server(wsgi_app, global_conf, host='localhost',
+               port=8080):
+    from wsgiutils import wsgiServer
+    import logging
+    logged_app = TransLogger(wsgi_app)
+    port = int(port)
+    # For some reason this is problematic on this server:
+    ensure_port_cleanup([(host, port)], maxtries=2, sleeptime=0.5)
+    app_map = {'': logged_app}
+    server = wsgiServer.WSGIServer((host, port), app_map)
+    logged_app.logger.info('Starting HTTP server on http://%s:%s',
+                           host, port)
+    server.serve_forever()
+    

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1119 @@
+Metadata-Version: 1.0
+Name: ZopeSkel
+Version: 2.19
+Summary: A collection of skeletons for quickstarting Zope projects.
+Home-page: http://svn.plone.org/svn/collective/ZopeSkel/trunk
+Author: Cris Ewing
+Author-email: cewing at uw.edu
+License: MIT
+Description: .. contents :: 
+        
+        Introduction
+        ============
+        
+        ZopeSkel provides a collection of project templates for Plone 
+        and Zope development projects.
+        
+        ZopeSkel uses the `paster <http://pythonpaste.org/script/>`_ Python library
+        internally.
+        
+        Installing ZopeSkel
+        ===================
+        
+        ZopeSkel can be installed in one of two ways: with `buildout
+        <http://www.buildout.org/>`_ or with `virtualenv
+        <http://virtualenv.openplans.org/>`_. Despite existing documentation to the
+        contrary, it is not recommended to install ZopeSkel in your system python.
+        
+        Buildout installation 
+        ---------------------------
+        
+        Add to your ``buildout.cfg``::
+                
+            parts =
+                ...
+                zopeskel
+            
+        
+            [zopeskel]
+            recipe = zc.recipe.egg
+            eggs = 
+                    ZopeSkel 
+                    ${instance:eggs}
+        
+        After building your buildout, this will leave ``zopeskel`` and ``paster`` 
+        commands in the ``bin`` directory of your buildout.
+        
+        Virtualenv installation
+        -----------------------------
+        
+        First, install virtualenv into your system::
+        
+            easy_install virtualenv
+        
+        Next, create a virtual environment with the new ``virtualenv`` command::
+        
+            virtualenv --no-site-packages --distribute zopeskelenv
+        
+        Once virtualenv is finished, you can install zopeskel to your new virtual 
+        environment::
+        
+            zopeskelenv/bin/easy_install zopeskel
+        
+        Once this is complete, you will be left with ``zopeskel`` and ``paster``
+        commands in the ``bin`` directory inside your virtualenv.
+        
+        
+        Available Templates
+        ===================
+        
+        To see details of the available templates::
+        
+            zopeskel --list
+            
+        ... or more info about how zopekskel works::
+        
+        	zopeskel --help
+        		    
+        Using Templates
+        ===============
+        
+        Creating a Plone 4 buildout using virtualenv ZopeSkel installation::
+            
+            source zopeskelenv/bin/activate
+        	zopeskel plone4_buildout yourfoldername
+        
+        The folder created, ``yourfoldername``, can be checked into the versioning
+        system of your choice.  It is now a portable, self-contained, ready-to-build 
+        Plone site.  You can build the system at any time using the following::
+        
+        	cd yourfoldername
+        	python bootstrap.py 
+        	bin/buildout
+        
+        The ``plone4_buildout`` recipe results in a self-contained version of ZopeSkel
+        installed via the buildout method described above. It thus provides the 
+        ``zopeskel`` and ``paster`` commands inside its ``bin`` folder. You can use these
+        commands inside the buildout to create packages for your new Plone site::
+        
+            bin/zopeskel plone3_theme src/plonetheme.yourcompanyid
+        
+        The command will ask a few questions such as desired package name and a
+        description and output a complete package you can immediately start using.
+        Interactive help is available by entering "?" as a response to any question.
+        
+        .. note ::
+        
+            Because ZopeSkel is built on paster you can do anything we describe here
+            using the ``paster`` command directly.  If you do so, you can gain access to 
+            certain features of ``paster`` that have been disabled for ``zopeskel``, but
+            you also will lose access to many of the nicer features of ``zopeskel``, 
+            including validation and in-line help.
+        
+        Local Commands
+        ==============
+        
+        In addition to project templates, the ZopeSkel system provides local commands.
+        Local commands are context aware commands that help you to add more
+        functionality to an existing ZopeSkel generated project.
+        
+        .. note ::
+        
+        	Local commands require using the ``paster`` command directly - the 
+        	``zopeskel`` command does not support them yet.
+        
+        .. note ::
+        
+            Not all ZopeSkel templates provide local commands.  In general, if local
+            commands are available, you will be informed of the fact as your new
+            package is generated.
+        
+        Using local commands to create a content type package
+        -----------------------------------------------------
+        
+        Starting inside your Plone buildout, first create an archetypes package::
+        
+            cd src
+            ../bin/zopeskel archetype mycompanyid.mycustomcontenttypes
+        
+        Next, change directories into your new package and invoke ``paster`` to add a
+        content type::
+        
+            cd mycompanyid.mycustomcontenttypes
+            ../../bin/paster
+            
+            Usage: ../../bin/paster COMMAND
+            usage: paster [paster_options] COMMAND [command_options]
+            
+            ...
+            
+            Commands:
+            ...
+        
+            ZopeSkel local commands:
+        	    addcontent   Adds plone content types to your project
+                        
+        
+        As you can see from the ``paster`` command output, your new package supports a
+        local command called ``addcontent``. Tou can use ``addcontent`` command to add
+        new code to your package. As with both ``zopskel`` and ``paster``, you can use
+        the ``--list`` option to see what local commands are available in the context of
+        the package you've created.
+        
+            ../../bin/paster addcontent --list
+            
+            Available templates:
+                atschema:      A handy AT schema builder
+                browserlayer:  A Plone browserlayer
+                contenttype:   A content type skeleton
+                form:          A form skeleton
+                formfield:     Schema field for a form
+                i18nlocale:    An i18n locale directory structure
+                portlet:       A Plone 3 portlet
+                view:          A browser view skeleton
+                zcmlmeta:      A ZCML meta directive skeleton
+        
+        You can add an archetypes content type for managing lectures::
+        
+                ../../bin/paster addcontent -t contenttype LectureInfo
+        
+        Then you can add schema fields to that content type::
+        
+                ../../bin/paster addcontent -t atschema
+        
+        local commands can be run as many times as needed to create your package.  You 
+        can iteratively develop your content type, other content types, and more.
+        
+        .. note ::
+        
+            When changing the your package code local commands will often change
+            GenericSetup XML files (found in the in ``profiles/default`` folder of your
+            package). These changes will not appear in Plone/Zope simply by restarting your
+            instance. You will usually need to re-install your package in your development
+            Plone site if you run any local commands in a package you've already installed.
+        
+        More info
+        
+        * http://collective-docs.plone.org/tutorials/paste.html
+        
+        Testing
+        =======
+        
+        Since version 1.5, ZopeSkel has tests.  It's required to run these
+        before you check in any changes you make. They can be run like so::
+        
+            python setup.py test
+        
+        More info
+        =========
+        
+        Issue tracker
+        
+        * http://plone.org/products/zopeskel/issues
+        
+        Source code
+        
+        * http://svn.plone.org/svn/collective/ZopeSkel/trunk
+        
+        Mailing List
+        
+        * https://lists.plone.org/mailman/listinfo/zopeskel
+        
+        Please contribute by submitting patches for what you consider 'best of
+        breed' file layouts for starting Zope projects.
+        
+        Changelog
+        =========
+        
+        2.19 - January 21, 2011
+        --------------------------
+        
+        * In every setup.py, replace '%3A' with ':', making list_classifier url an url
+          which can actually be used.
+          [thet]
+        
+        * Added plone4_buildout [miohtama]
+        
+        * Improvements to README [miohtama]
+        
+        2.18 - September 30, 2010
+        -------------------------
+        
+        * Add bin/zopeskel --version flag.  Reports current version of zopeskel
+          (http://plone.org/products/zopeskel/issues/48)
+          [cewing]
+        
+        * plone3_buildout: use Plone 3.3.5 by default.
+          [maurits]
+        
+        * Fixed a problem with the generic setup profile in plone templates in which a
+          profile was registered in zcml, but no profiles directory was created.
+          (http://plone.org/products/zopeskel/issues/46)
+          [cewing]
+        
+        * use i18n:domain plone for portlet title so it need not be translated twice
+          (http://plone.org/products/zopeskel/issues/44)
+          [fRiSi]
+        
+        * use the correct name of package, so it can be used in package with 2 dots or
+          1 dots in package name
+          [lucmult]
+        
+        2.17 - June 14, 2010
+        --------------------
+        
+        * Added a pin for PasteScript>=1.7.2.  This solves an issue where using zopeskel
+          with an early version of PasteScript resulted in a method signature mismatch
+          on the paster command 'challenge' method.  Fixes issue #42
+          (http://plone.org/products/zopeskel/issues/42)
+          [cewing]
+        
+        * Fixed lingering problem in Archetypes template with registering a 'locales'
+          directory before one is created.  Users now need to add an i18nlocale via
+          addcontent in order to get this directory and have it registered via zcml.
+          [cewing]
+        
+        * Fixed dependency in Archetypes template doctests on the presence of the log-in
+          portlet.  Tests now open the 'login_form' instead.  Resolves issue #40
+          (http://plone.org/products/zopeskel/issues/40)
+          [cewing]
+        
+        * Added new browserlayer localcommand for plone and archetype templates.
+          [marcosfromero]
+        
+        * Added stub locales directory for plone3_theme template, resolving issue #33
+          (http://plone.org/products/zopeskel/issues/33)
+          [cewing]
+        
+        * Set the GenericSetup profile version number in the generated
+          metadata.xml to 1000, which is better for the alphabetical ordering
+          that GS does.
+          [maurits]
+        
+        * Added "environment-vars = zope_i18n_compile_mo_files true" to
+          plone3_buildout template. This is enabled only for Plone 4 (eggifiedzope is
+          true).
+          [vincentfretin]
+        
+        2.16 - March 22, 2010
+        ---------------------
+        
+        * Fixed syntax error in generated portlet constructor code
+          [ajung]
+        
+        * Added a new 'BoundedIntVar' variable type.  It validates that the provided
+          argument is both an integer and between provided min and max values (inclusive
+          on both ends).
+          [cewing]
+        
+        * Updated archetype and plone3_portlet templates to comply with pep8 and
+          pyflakes validation at all stages of a skeleton build process.  Resolves the
+          issue here: (http://plone.org/products/zopeskel/issues/24)
+          [cewing]
+        
+        * Added explanatory text to the plone_hosting template regarding the fact that
+          it is unsuitable for use with plone versions later than 3.1.7, fixed
+          http://plone.org/products/zopeskel/issues/25
+          [cewing]
+        
+        * Fixed the problem with generated archetypes content type meta_type names
+          documented here:
+          (http://plone.org/products/zopeskel/issues/22)
+          [cewing]
+        
+        * Updated tests for the plone template to include tests for the fixes to message
+          factory, zcml sub-package include and i18n translation registration problems
+          below
+          [cewing]
+        
+        * Cleaned up a number of issues with defining and importing a package-wide
+          MessageFactory in plone template local commands:
+          (http://plone.org/products/zopeskel/issues/29)
+          [cewing]
+        
+        * Cleaned up a number of issues with importing sub-package zcml files after
+          using local commands in the plone template:
+          (http://plone.org/products/zopeskel/issues/28)
+          [cewing]
+        
+        * Fixed an issue with the plone template zcmlmeta local command to ensure that
+          the proper directive was inserted into the top-level configure.zcml
+          [cewing]
+        
+        * Fixed the bug in the plone template that caused zcml errors when the
+          i18nlocale local command had not been run:
+          (http://plone.org/products/zopeskel/issues/26)
+          [cewing]
+        
+        * Improved i18n for portlets
+          (http://plone.org/products/zopeskel/issues/31)
+          [fRiSi]
+        
+        * Improved test coverage of the zopeskel script
+          [cewing]
+        
+        * Disallowed use of the paster --svn-repository command due to some basic
+          incompatibilities with the way zopeskel is used.  The argument is still
+          allowed for users via 'paster create'.
+          (http://plone.org/products/zopeskel/issues/34
+          http://plone.org/products/zopeskel/issues/35)
+          [cewing]
+        
+        * Added a 'Register Profile' question to the plone template so that users can
+          have a Generic Setup profile registered in the case that they plan on adding
+          things (like portlets) that require a GS Profile to install.  Adapted
+          downstream templates archetype, plone25_theme and plone3_theme to use the new
+          question
+          [cewing]
+        
+        2.15 - January 22, 2010
+        -----------------------
+        
+        * Backed out a few changes from jaroel in favor of retaining working templates
+          OOTB
+          [cewing]
+        
+        * Made archetype, plone3_theme and plone3_portlet pass the PEP8 validator and
+          pyflakes.
+          [jaroel]
+        
+        * Template summaries (one-line descriptions) were improved.
+          [pupq]
+        
+        * Templates now have an optional help attribute, which is a rich description of
+          the template and its purpose. Help has been provided for all the ZopeSkel
+          templates.
+          [pupq/cewing]
+        
+        * Variables (questions in templates) now have a human-facing "title" attribute
+          which can be shown instead of the (uglier + more opaque) actual variable
+          name. Titles have been written for questions.
+          [pupq]
+        
+        * Variables now have optional help attribute, which is a rich description of
+          the variable. This can be shown in pastescript UIs.
+          [pupq]
+        
+        * Interactive help has been added, so that you can enter "?" at any question to
+          receive the rich help for that question.
+          [cewing]
+        
+        * "Modes" have been implemented--easy, expert, and all--to reduce the number of
+          questions posed to beginning users. For example, technical questions (like
+          "namespace package 2") are now shown only in expert mode.
+          [cewing/pupq]
+        
+        * The project name (eg, "plone.app.example") is now split into pieces to become
+          the default values for namespace packages names ("plone", "app", "example").
+          [pupq]
+        
+        * Templates can provide an ndot attribute that signals how many namespaces
+          ("dots") are expected in the project name. When invoked through new zopeskel
+          front-end script, names that don't support that pattern are rejected with
+          help (eg, creating a plone_app with "plone.example" would be rejected, as a
+          2-namespaced-name, "plone.foo.example", is expected)
+          [pupq]
+        
+        * Rather than having to use the checkvar() and post() methods, templates can
+          now support messages that appear pre-questions and post-generation.
+          Appropriate warnings and where-to-go help has been added.
+          [cewing]
+        
+        * Abstract classes for zope2 products and buildouts have been added; this
+          simplifies inheritance of common attrs, and provides appropriate places for
+          future common logic.
+          [pupq]
+        
+        * A front-end script, 'zopeskel', has been added. This has high-level, friendly
+          help, and an improved command line interface for the task of template usage.
+          It can provide a friendly list of templates and a verbosely-detailed list of
+          templates.
+          [pupq/cewing/chrisrossi]
+        
+        * Users can have a "$HOME/.zopeskel" script with default values for questions,
+          either on a all-template or template-by-template basis.
+          [pupq]
+        
+        * The "zopeskel" script can emit a sample ".zopeskel" file, for editing.
+          [pupq/cbc]
+        
+        * A simple HTML help generator can produce a listing of templates, fields, and
+          subtemplates. This will be useful for maintaining an HTML "reference guide"
+          to the ZopeSkel templates. Find this in the zopeskel.doctools package.
+          [pupq/cbc]
+        
+        * Currently-failing unit tests were fixed.
+          [pupq/cewing]
+        
+        * New unit tests were written for new features.
+          [cewing]
+        
+        * New and repaired unit tests were added into the default test suite
+          [cewing]
+        
+        * Rather than using a generic var() class for all variables ("questions"),
+          subclasses for different types of variables--string, boolean, choices,
+          etc.--were added. These normalize their own values and provide validation.
+          Therefore, users will get earlier/better feedback on inappropriate values.
+          [pupq/cewing]
+        
+        * A proposal for splitting the project into zopeskel.* packages was added.
+          [pupq/cbc]
+        
+        * Where questions were duplicated across different templates, they were
+          consolidated for consistency into one place, and referred to from other
+          places.
+          [pupq]
+        
+        * A real-time tool for generating graphs of dependencies and template
+          inheritance was written, suitable for including in high-level documentation.
+          Find this in the zopeskel.doctools package.
+          [cbc]
+        
+        * Use the eggified Zope 2.12.3 for buildouts targeting Plone 4.x.
+          Use 2.9.12 for buildouts targeting Plone 2.x.
+          [maurits]
+        
+        * Remove unnecessary 'title' argument from jsregistry.xml example.
+          This fixes http://plone.org/products/zopeskel/issues/18.
+          [dukebody]
+        
+        2.14.2 - December 8th, 2009
+        ---------------------------
+        
+        * Back out untested, undocumented changes from paris sprint that broke some
+          templates
+          [MatthewWilkes]
+        
+        2.14.1 - November 19th, 2009
+        ----------------------------
+        
+        * Fix packaging error
+          [MatthewWilkes]
+        
+        2.14 - November 19th, 2009
+        --------------------------
+        
+        * Use the eggified Zope 2.12.1 for buildouts targeting Plone 4.x. Bump 3.x
+          default version to 3.3.2.
+          [MatthewWilkes]
+        
+        * Use distribute for Plone buildouts
+          [MatthewWilkes]
+        
+        * Remove extra quotes in a plone_pas template file, which were
+          generating a syntax error.
+          [dukebody]
+        
+        
+        2.13 - October 3rd, 2009
+        ------------------------
+        
+        * Pinned Cheetah to <= 2.2.1 and eliminated install_requires for elementtree
+          (markdown not a requirement for Cheetah 2.2.1). Allows zopeskel to easy_install
+          with python 2.4. Can remove pinning when markdown is fixed.
+          [cbcunc]
+        
+        * plone3_buildout: added 'fake-zope-eggs = true' to the zope2 part, as
+          otherwise you get e.g. 'ImportError: No module named ImplPython'
+          when using a plone.recipe.zope2install < 3.0, like pinned by Plone
+          3.2 versions.cfg.
+          [maurits]
+        
+        * Make the Plone 3 buildout template default to Plone 3.3.1.
+          [dukebody]
+        
+        * Modify HISTORY.txt convention in basic_namespace and nested_namespace
+          templates. Use now "1.0dev (unreleased)" and '-' for changelog items.
+          [vincentfretin]
+        
+        * Fix trove classifiers list url in all setup.py_tmpl
+          [vincentfretin]
+        
+        * Remove old import_steps.xml from profiles/default/ in plone3_theme template,
+          the various import step in registered in profile.zcml now.
+          [vincentfretin]
+        
+        * For plone3_theme, plone3_portlet an archetype templates,
+          start profile version at 1 to follow current convention.
+          [vincentfretin]
+        
+        * Remove http://download.zope.org/ppix/,
+          http://download.zope.org/distribution/, and
+          http://effbot.org/downloads from find-links in the plone3_buildout template.
+          Only Pypi or http://dist.plone.org/release/${plone_version}
+          is really needed.
+          Add http://dist.plone.org/thirdparty for alternative location for
+          elementree, PILwoTk, markdown, python-ldap.
+          [vincentfretin]
+        
+        
+        2.12 - September 23rd, 2009
+        ---------------------------
+        
+        * Remove the options fake-zope-eggs=true and
+          additional-fake-eggs=ZODB3 in the plone3_buildout template since
+          fake-zope-eggs is enabled by default in
+          plone.recipe.zope2install>=3.0, with ZODB3 among the default "fake
+          zope eggs".  [dukebody]
+        
+        * Declare a dependency on elementtree.  It's not a direct dependency
+          of ZopeSkel, but ZopeSkel depends on Cheetah which depends on
+          Markdown, which has an install-time dependency on elementtree but
+          doesn't declare that.
+          [davisagli]
+        
+        * remove the custom `egg_info.writer` and keywords for `paster_plugins`
+          since this has been an entry point of PasteScript since 1.6.3, using
+          the `setup_requires` as per the change log found here:
+          http://pythonpaste.org/script/news.html#id4
+        
+          This solves an issue where the distutils would go into an infinite
+          loop when you add a new `install_requires` package
+          [claytron]
+        
+        * plone3_theme: made the generated viewlet.pt not crash when the
+          accompanying view has not been changed so has no computed_value.
+          Added some inline documentation there and fixed example
+          registration.  [maurits]
+        
+        * In the plone3_theme say that we are creating a theme for Plone 3,
+          not specifically for 3.0.
+          [maurits]
+        
+        * In the plone template fix the generated INSTALL.txt: when telling
+          users to add $project to the eggs, the example snippet should indeed
+          add $project and not the $full_package_name.
+          [maurits]
+        
+        * In the plone_app and plone3_portlet templates use the full package
+          name instead of the project name in zcml lines in the generated
+          INSTALL.txt.  The project/package/egg name may be 'silly' when the
+          package structure is far/better/name, which means the zcml needs to
+          be 'far.better.name'.  Thanks to Espen Moe-Nilssen for spotting this.
+          [maurits]
+        
+        * Make the Plone 3 buildout default to Plone 3.2.2.
+          [maurits]
+        
+        * Removed the setup.cfg from all templates. It makes the common operation of
+          tagging and releasing packages harder with little benefit. It can be easily
+          added by those who know about this particular feature.
+          [hannosch]
+        
+        * Removed the useless `Python Modules` trove classifier from all templates.
+          [hannosch]
+        
+        2.11 - February 5th, 2009
+        -------------------------
+        
+        * Make the Plone 3 buildout default to Plone 3.2.1, and pick up
+          ${versions:zope2-url} for Plone > 3.1
+          [MatthewWilkes]
+        
+        * added a version requirement for Cheetah (>1.0)
+          [tarek]
+        
+        * fix zopeskel/docs/localcommands.txt
+          [yboussard]
+        
+        * Modify zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl
+          to init egg as product if it is a Zope2 product.
+          [yboussard]
+        
+        * Modify plone3_buildout template to ask for a Plone version. If the version
+          is 3.0 or 3.1 it uses the plone install recipe, otherwise it uses the Plone
+          egg from the cheeseshop.
+          [MatthewWilkes]
+        
+        * Link to appropriate PyPI pages for recipes used.
+          [MatthewWilkes]
+        
+        * Add a Zope 2 without Plone buildout template.
+          [evilbungle]
+        
+        * Reconciling HISTORY.txt to mirror what can be found at the following:
+          http://pypi.python.org/pypi/ZopeSkel/2.10. Release of 2.10 was clobbered
+          due to what looks like a merge at r74790.
+          [andrewb]
+        
+        * Update plone2.5_template's buildout.cfg_tmpl to use Zope 2.9.10. This
+          release incorporates Hotfix-2008-08-12. Defaulting to a known insecure
+          Zope seems unwise for people that may be updating legacy environments into
+          buildout, since they're likely to forget to include the hotfix. Url to
+          2.9.10 hard-coded (as opposed to the more elegantly self-aware
+          plone.recipe.plone approach) per the practice of a plone.recipe.distros
+          plone part.
+          [andrewb]
+        
+        * Nearly at the end of the creation of a ZopeSkel template, the local
+          commands available for that template are displayed.
+          [jaraco, markvl]
+        
+        * The Plone template now has local commands. (Basically moved them
+          from the archetype templates to plone templates and made them
+          available for both.
+          [markvl]
+        
+        * Added base test setup to the archetype template. Added wiring code that
+          runs README.txt as a doctest.
+          [esartor]
+        
+        * Added tests to the addcontent contenttype command. These ammend the
+          README.txt file for each content type providing basic tests for creating,
+          editing and removing instances of the added content type.
+          [esartor]
+        
+        
+        2.10 - September 17th, 2008
+        ---------------------------
+        
+        * Fixed a small bug that made most templates create a package that was
+        * showing twice in the Plone quick
+          installer is the top level namespace package was called 'Products'. Bug
+          was fixed in the 'plone' template (since version 1.5), now in other ones
+          where needed too.
+          [davconvent]
+        
+        
+        2.9 - September 1st, 2008
+        -------------------------
+        
+        * Update silva buildout to reflect changes in Silva 2.1 as stable
+          version, and 2.2 as development: SilvaLayout is not shipped anymore
+          as an extra distribution but integrated in Silva all. Remove
+          question, and update buildout.cfg template.
+          [thefunny]
+        
+        
+        2.8 - July 31, 2008
+        -------------------
+        
+        * Generate logrotate configuration file using collective.recipe.template
+          so it does not need to contain absolute paths. This makes it possible
+          to move the generated buildout around, or install it on other machines
+          with different filesystem layouts.
+          [wichert]
+        
+        * Also rotate instance1-Z2.log.
+          [wichert]
+        
+        * Update documentation for hosting template to note that logrotate needs
+          to be told where to put its status file.
+          [wichert]
+        
+        
+        2.7 - July 25, 2008
+        -------------------
+        
+        * Hosting template:
+        
+          - Switch default Plone version to 3.1.4.
+            [wichert]
+        
+          - Corrected a typo in the logrotate template, which prevented the zeo log
+            to be rotated.
+            [hannosch]
+        
+        
+        2.6.2 - July 16, 2008
+        ---------------------
+        
+        * Hosting template:
+        
+          - Corrected even more references of instance to instance1 in proxy support
+            and logrotate handling.
+            [hannosch]
+        
+        
+        2.6.1 - July 16, 2008
+        ---------------------
+        
+        * Hosting template:
+        
+          - Changed the http_port to start at base_port + 10, to make room for
+            additional services.
+            [hannosch]
+        
+          - Corrected hide_summary option, to not show the summary twice.
+            [hannosch]
+        
+        2.6 - July 15, 2008
+        -------------------
+        
+        * Hosting template:
+        
+          - Corrected one last reference of instance to instance1 in the zopepy eggs
+            option of the plone_hosting template.
+            [hannosch]
+        
+        2.5 - July 15, 2008
+        -------------------
+        
+        * Hosting template:
+        
+          - fix test for Varnish-support in the supervisord configuration.
+            [wichert]
+        
+          - Rename the instance part to instance1 and add an instances group. This
+            makes it possible to upgrade to multiple instances later on without
+            having to break invocations.
+            [wichert]
+        
+        2.4 - July 9, 2008
+        ------------------
+        
+        * Restore the cwd after running buildout in the hosting recipe so further
+          processing works correctly.
+          [wichert]
+        
+        * Add a hook in the hosting template to not show the summary. This
+          can be used by derived templates that want to show their own summary
+          or show it at a later point.
+          [wichert]
+        
+        * Set default Plone version to 3.1.3.
+          [wichert]
+        
+        * Added kss plugin template
+          [gotcha, jfroche, adrien01]
+        
+        * Silva layout have been merged with Silva all in the development
+          buildout.
+          [thefunny]
+        
+        2.3 - June 24, 2008
+        -------------------
+        
+        * Fix problem in the hosting template: varnish was always enabled
+          even if not desired.
+          [wichert]
+        
+        * Added ZopeSkel test layer with the apropriate testSetup and testTearDown.
+          The steps in the top of each test file is not anymore needed: delete
+          tempdir/plone.example and then cd to tempdir.
+          [mustapha]
+        
+        * Make the zope2product option in the archetype template default to true.
+          [mustapha]
+        
+        * Modified buildout.cf to only test zopeskel.
+          [mustapha]
+        
+        * Fixed the paster test function: overwrite option should default to True for
+          the create command.
+          [mustapha]
+        
+        * Added ``use_local_commands`` attribute (a la use_cheetah). A zopeskel
+          template that wants to use local commands has to set it to True .
+          [mustapha]
+        
+        * Get rid of zopeskel.txt and use setup.cfg to store the parent template name.
+          [mustapha]
+        
+        * Sub-templates may define a parent_template attribute with the list of
+          templates that can use it.
+          [mustapha]
+        
+        * Fixed tests and updated docs.
+          [mustapha]
+        
+        Version 2.2
+        -----------
+        
+        * Install Plone 3.1.2 by default.
+          [wichert]
+        
+        * Remove useless spans from the portlet template.
+          [wichert]
+        
+        * Add supervisorctl configuration.
+          [wichert]
+        
+        
+        Version 2.1
+        -----------
+        
+        * Revert BaseTemplate usage from the hosting template (changeset
+          57368 from Tarek). It was not used and broke the buildout. This fixes
+          http://plone.org/products/zopeskel/issues/8
+          [wichert]
+        
+        * Replace the generic README in the plone_hosting template with documentation
+          that is important for deployments.
+          [wichert]
+        
+        * Add log rotation support to the hosting buildout. Merged from Jarn's
+          bones package.
+          [wichert]
+        
+        
+        Version 2.0
+        -----------
+        
+        * Switch plone_hosting template to using supervisord to manage processes.
+          Merged from Jarn's bones package.
+          [wichert]
+        
+        * Reduced the number of questions to generate an atschema and used
+          the MessageFactory instead of declaring an i18n_domain attribute
+          [mustapha]
+        
+        * Fixed missing imports in plone2_theme
+          [mustapha]
+        
+        * Removed unused imports in plone_pas
+          [mustapha]
+        
+        * In plone2.5_theme: when the skinname is empty, replace it with a
+          default text, otherwise adding a Plone Site will throw an error when
+          displaying the extension profiles.
+          [maurits]
+        
+        * Added note to profiles.zcml of plone2.5_theme that
+          five.registerPackage needs Five version 1.4.
+          [maurits]
+        
+        * Added a BUILDBOT.txt file.
+          [tarek]
+        
+        * plone3_portlet: added commented out alternative AddForm for when
+          there are no configurable parameters.  That was shorter than listing
+          all the changes (where we forgot one).
+          [maurits]
+        
+        * Fixed typos in archetyps and plone3 portlets: 'portletBotomLeft'
+          should have been 'portletBottomLeft' with two 't's.
+          [maurits]
+        
+        * Made plone3_portlet respect pep8 (and pyflakes).
+          [maurits]
+        
+        * Use 1.0 as default version number for all templates. This is a more sensible
+          default than 0.1 since we start of with dev-versions anyway.
+          [wichert]
+        
+        * sub-templates per ZopeSkel template: Only sub-templates related to the parent
+          template is visible with the -l option
+          [mustapha]
+        
+        * added -a (--list-all) option to show all subtemplates regardless of the
+          current project. Subtemplates that are not for the type of the current
+          project are prefixed with N
+          [mustapha]
+        
+        * Fixed the recreation of the paster_plugins.txt metadata file for archetype.
+          For now we have to run 2 times the egg_info command to get the paster_plugins
+          file recreated (setuptools problem: nice task to fix)
+          [mustapha]
+        
+        * fixed the case of many inner packages: ask the user to choose a packe to
+          inject content into if the command is run outside of an inner package
+          [mustapha]
+        
+        * make all ZopeSkel templates that inherits from BaseTemplate addcontent aware
+          [mustapha]
+        
+        * Added plone_pas template for PlonePas projects and many subtemplates
+          [mustapha]
+        
+        * regrouped archetype subtemplates in templates/archetype
+          [mustapha]
+        
+        * added and fixed tests
+          [mustapha]
+        
+        
+        Version 1.10
+        ------------
+        
+        * Install Plone 3.1.1 as default option.
+          [wichert]
+        
+        * Fixed a problem with ZopeSkel localcommands when we have multiple
+          projects, it was getting the first directory always and sometimes
+          the package dir was not the first directory, so when running the
+          addcontent in the package it was creating the contents in the wrong
+          dir. Thanks to wichert for pointing me this file.
+          [dsa]
+        
+        * Update the hosting template to make running of buildout optional.
+          [wichert]
+        
+        * Update the hosting template to test if a port is already in use and
+          abort if so.
+          [wichert]
+        
+        * Update the hosting template to only ask for a single base port number.
+          [wichert]
+        
+        * Fix broken creation of Plone 3.1(.x) sites.
+          [wichert]
+        
+        
+        Version 1.9
+        -----------
+        
+        * Install Plone 3.1 as default option.
+          [wichert]
+        
+        * Fixed a missing 'import os' in the plone2_theme template. [davisagli]
+        
+        * Fix an ambiguous question in the silva_buildout template, and update
+          the generated README file. [thefunny]
+        
+        
+        Version 1.8
+        -----------
+        
+        * fixed the recipe template buildout.cfg generation, thanks Kai ;)
+          [tarek]
+        
+        Version 1.7
+        -----------
+        
+        * Update the templates to have README.txt and HISTORY.txt in valid
+          restructured format and use those as the package's long description.
+          This automatically gives packages a more readable page on PyPI
+          (and PSC with Tarek's excellent changes).
+          [wichert]
+        
+        * Adjust the trove classifiers on the packages to not claim incorrect
+          frameworks: we should only claim frameworks on which the package
+          can run directly. So, for example, do not claim Zope2 of we also need
+          Plone on top of Zope2.
+          [wichert]
+        
+        
+        Version 1.6
+        -----------
+        
+        * Add templates for a Silva buildout.
+          [thefunny]
+        
+        * Add a metadata.xml to all generated GenericSetup profiles. This is
+          required by new versions of GenericSetup.
+          [wichert]
+        
+        * For nested namespace packages we need to declare both namespace
+          levels as namespace packages. This is a requirement for current
+          versions of setuptools.
+          [wichert]
+        
+        * Use Plone 3.0.6 as default version for new Plone hosting buildouts
+          [wichert]
+        
+        
+        Version 1.5.1
+        -------------
+        
+        * Fix #2 (missing import in 'hosting.py') at
+          http://plone.org/products/zopeskel/issues/2
+          [nouri]
+        
+        Version 1.5
+        -----------
+        
+        * added a new local command into archetype template to inject
+          new content types [spanky]
+        
+        * added a doctest for each template, and refactored the package
+          so we have one python module per template [tarek]
+        
+        * Refactored the zc.buildout recipe to provide structured documention
+          that will render nicely on PyPI, added comments for recipe authors
+          to help writing documentation and tests and added a working doctest
+          skeleton. Implemented automatic license classifiers for common
+          licenses in the generated setup.py. The mapping is in zopeskel.base
+          and can be used for other templates also.
+          [dokai]
+        
+        * The 'five:registerPackage' ZCML directive is added in a project based on the
+          'plone' template only if the top level namespace package is not
+          called 'Products'. This avoids having the product loaded twice in Zope.
+          [davconvent]
+        
+        * Added paragraph about old style Zope 2 Product installation in the
+          INSTALL.txt_tmpl file of the plone template.
+          The paragraph will be added to the installation instructions if the top
+          level namespace package is called 'Products'.
+          [davconvent]
+        
+        Version 1.4
+        -----------
+        
+        * Set the version number for plone.recipe.plone in a new versions part in
+          buildout.cfg. That works around a buildout bug: buildout breaks if you change
+          the revision pin for a recipe.
+          [wichert]
+        
+        * Fixed bug: when running 'paster create' with --no-interactive option,
+          the package variable given in the command line is ignored.
+          [Mustapha]
+        
+        Version 1.3.4
+        -------------
+        
+        * Added MANIFEST.in to prevent bad releases from svn exports.
+          [fschulze]
+        
+        Version 1.3.3
+        -------------
+        
+        * Move to the newly released Varnish 1.1.2.
+          [wichert]
+        
+        * Remove bad import which broke localcommand support.
+          [deo]
+        
+        * Remove unneeded imports and whitespace cleanup.
+          [deo]
+        
+        Version 1.3.2
+        -------------
+        
+        * Small fix in plone3_theme that did not install correctly with easy_install
+          because of some files missing the the egg informations (added MANIFEST.in).
+          [davconvent]
+        
+        Version 1.3.1
+        -------------
+        
+        * Added 'addcontent' local command to make possible injecting content types
+          in ZopeSkel projects and make the Archetype template 'addcontent' aware.
+          [mustapha]
+        
+        * Updated to Plone 3.0.4.
+          [fschulze]
+        
+        * Rerelease because of a bad egg.
+          [fschulze]
+        
+        Version 1.3
+        -----------
+        
+        * added the `recipe` template
+          [tarek]
+        
+        * Add Plone 2.5.5.
+          [wichert]
+        
+        Version 1.2
+        -----------
+        
+        * Merge a slightly stripped down version of the Jarn Plone hosting template.
+          This provides a convenient way to create a buildout for all Plone 2.5 and
+          3.0 versions with ZEO and optional Varnish based caching.
+          [wichert]
+        
+Keywords: web zope command-line skeleton project
+Platform: UNKNOWN
+Classifier: Development Status :: 5 - Production/Stable
+Classifier: Framework :: Zope2
+Classifier: Framework :: Zope3
+Classifier: Framework :: Plone
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Topic :: Internet :: WWW/HTTP :: Dynamic Content

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,417 @@
+BUILDBOT.txt
+CONTRIBUTORS.txt
+HISTORY.txt
+LICENSE
+MANIFEST.in
+README.txt
+setup.cfg
+setup.py
+ZopeSkel.egg-info/PKG-INFO
+ZopeSkel.egg-info/SOURCES.txt
+ZopeSkel.egg-info/dependency_links.txt
+ZopeSkel.egg-info/entry_points.txt
+ZopeSkel.egg-info/not-zip-safe
+ZopeSkel.egg-info/requires.txt
+ZopeSkel.egg-info/top_level.txt
+ez_setup/README.txt
+ez_setup/__init__.py
+zopeskel/__init__.py
+zopeskel/abstract_buildout.py
+zopeskel/abstract_zope.py
+zopeskel/archetype.py
+zopeskel/base.py
+zopeskel/basic_namespace.py
+zopeskel/basic_zope.py
+zopeskel/hosting.py
+zopeskel/interfaces.py
+zopeskel/kss_plugin.py
+zopeskel/nested_namespace.py
+zopeskel/plone.py
+zopeskel/plone25_buildout.py
+zopeskel/plone25_theme.py
+zopeskel/plone2_theme.py
+zopeskel/plone3_buildout.py
+zopeskel/plone3_portlet.py
+zopeskel/plone3_theme.py
+zopeskel/plone4_buildout.py
+zopeskel/plone_app.py
+zopeskel/plone_pas.py
+zopeskel/recipe.py
+zopeskel/silva_buildout.py
+zopeskel/ui.py
+zopeskel/vars.py
+zopeskel/zope2_buildout.py
+zopeskel/zopeskel_script.py
+zopeskel/docs/archetypes.txt
+zopeskel/docs/atschema.txt
+zopeskel/docs/basic_namespace.txt
+zopeskel/docs/basic_zope.txt
+zopeskel/docs/kss_plugin.txt
+zopeskel/docs/localcommands.txt
+zopeskel/docs/nested_namespace.txt
+zopeskel/docs/plone.txt
+zopeskel/docs/plone25_buildout.txt
+zopeskel/docs/plone25_theme.txt
+zopeskel/docs/plone2_theme.txt
+zopeskel/docs/plone3_buildout.txt
+zopeskel/docs/plone3_portlet.txt
+zopeskel/docs/plone3_theme.txt
+zopeskel/docs/plone4_buildout.txt
+zopeskel/docs/plone_app.txt
+zopeskel/docs/plone_pas.txt
+zopeskel/docs/recipe.txt
+zopeskel/docs/silva_buildout.txt
+zopeskel/localcommands/README.txt
+zopeskel/localcommands/__init__.py
+zopeskel/localcommands/archetype.py
+zopeskel/localcommands/plone.py
+zopeskel/localcommands/plone_pas.py
+zopeskel/localcommands/templates/archetype/atschema/content/+content_class_filename+.py_insert
+zopeskel/localcommands/templates/archetype/atschema/content/messagefactory_insert.txt_insert
+zopeskel/localcommands/templates/archetype/atschema/content/schema_field_bridge.txt_insert
+zopeskel/localcommands/templates/archetype/atschema/interfaces/+interface_name+.py_insert
+zopeskel/localcommands/templates/archetype/atschema/interfaces/__init__.py_insert
+zopeskel/localcommands/templates/archetype/atschema/interfaces/additional_imports.txt_insert
+zopeskel/localcommands/templates/archetype/contenttype/README.txt_insert
+zopeskel/localcommands/templates/archetype/contenttype/config.py_insert
+zopeskel/localcommands/templates/archetype/contenttype/content/+content_class_filename+.py_tmpl
+zopeskel/localcommands/templates/archetype/contenttype/content/configure.zcml_insert
+zopeskel/localcommands/templates/archetype/contenttype/interfaces/+content_class_filename+.py_tmpl
+zopeskel/localcommands/templates/archetype/contenttype/interfaces/__init__.py_insert
+zopeskel/localcommands/templates/archetype/contenttype/profiles/default/factorytool.xml_insert
+zopeskel/localcommands/templates/archetype/contenttype/profiles/default/rolemap.xml_insert
+zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types.xml_insert
+zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/+types_xml_filename+.xml_tmpl
+zopeskel/localcommands/templates/plone/browserlayer/browser/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/browserlayer/browser/configure.zcml_insert
+zopeskel/localcommands/templates/plone/browserlayer/interfaces/+interface_filename+.py_tmpl
+zopeskel/localcommands/templates/plone/browserlayer/interfaces/__init__.py_insert
+zopeskel/localcommands/templates/plone/browserlayer/profiles/default/browserlayer.xml_insert
+zopeskel/localcommands/templates/plone/form/__init__.py_insert
+zopeskel/localcommands/templates/plone/form/configure.zcml_insert
+zopeskel/localcommands/templates/plone/form/form.py
+zopeskel/localcommands/templates/plone/form/browser/+form_filename+.py_tmpl
+zopeskel/localcommands/templates/plone/form/browser/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/form/browser/configure.zcml_insert
+zopeskel/localcommands/templates/plone/formfield/browser/+form_filename+.py_insert
+zopeskel/localcommands/templates/plone/i18nlocales/configure.zcml_insert
+zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/README.txt
+zopeskel/localcommands/templates/plone/portlet/__init__.py_insert
+zopeskel/localcommands/templates/plone/portlet/configure.zcml_insert
+zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.pt_tmpl
+zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.py_tmpl
+zopeskel/localcommands/templates/plone/portlet/portlets/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/portlet/portlets/configure.zcml_insert
+zopeskel/localcommands/templates/plone/portlet/profiles/default/metadata.xml_tmpl
+zopeskel/localcommands/templates/plone/portlet/profiles/default/portlets.xml_insert
+zopeskel/localcommands/templates/plone/portlet/tests/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/portlet/tests/base_+portlet_filename+.py_tmpl
+zopeskel/localcommands/templates/plone/portlet/tests/test_+portlet_filename+.py_tmpl
+zopeskel/localcommands/templates/plone/view/__init__.py_insert
+zopeskel/localcommands/templates/plone/view/configure.zcml_insert
+zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.pt_tmpl
+zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.py_tmpl
+zopeskel/localcommands/templates/plone/view/browser/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/view/browser/configure.zcml_insert
+zopeskel/localcommands/templates/plone/zcmlmeta/configure.zcml_insert
+zopeskel/localcommands/templates/plone/zcmlmeta/meta/__init__.py_tmpl
+zopeskel/localcommands/templates/plone/zcmlmeta/meta/meta.zcml_insert
+zopeskel/localcommands/templates/plone/zcmlmeta/meta/metaconfigure.py_insert
+zopeskel/localcommands/templates/plone/zcmlmeta/meta/metadirectives.py_insert
+zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/anonymous_user_factory.py_tmpl
+zopeskel/localcommands/templates/plone_pas/authentication/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/authentication/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/authentication/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/authentication/plugins/authentication.py_tmpl
+zopeskel/localcommands/templates/plone_pas/challenge/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/challenge/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/challenge/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/challenge/plugins/challenge.py_tmpl
+zopeskel/localcommands/templates/plone_pas/credentials_reset/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_reset/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/credentials_reset.py_tmpl
+zopeskel/localcommands/templates/plone_pas/credentials_update/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_update/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/credentials_update.py_tmpl
+zopeskel/localcommands/templates/plone_pas/extraction/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/extraction/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/extraction/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/extraction/plugins/extraction.py_tmpl
+zopeskel/localcommands/templates/plone_pas/group_enumeration/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/group_enumeration/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/group_enumeration.py_tmpl
+zopeskel/localcommands/templates/plone_pas/groups/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/groups/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/groups/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/groups/plugins/groups.py_tmpl
+zopeskel/localcommands/templates/plone_pas/properties/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/properties/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/properties/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/properties/plugins/properties.py_tmpl
+zopeskel/localcommands/templates/plone_pas/role_assigner/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/role_assigner/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/role_assigner.py_tmpl
+zopeskel/localcommands/templates/plone_pas/role_enumeration/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/role_enumeration/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/role_enumeration.py_tmpl
+zopeskel/localcommands/templates/plone_pas/roles/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/roles/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/roles/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/roles/plugins/roles.py_tmpl
+zopeskel/localcommands/templates/plone_pas/update/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/update/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/update/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/update/plugins/update.py_tmpl
+zopeskel/localcommands/templates/plone_pas/user_adder/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/user_adder/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/user_adder/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/user_adder/plugins/user_adder.py_tmpl
+zopeskel/localcommands/templates/plone_pas/user_enumeration/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/user_enumeration/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/user_enumeration.py_tmpl
+zopeskel/localcommands/templates/plone_pas/user_factory/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/user_factory/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/user_factory/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/user_factory/plugins/user_factory.py_tmpl
+zopeskel/localcommands/templates/plone_pas/validation/interface.py_insert
+zopeskel/localcommands/templates/plone_pas/validation/plugin.py_insert
+zopeskel/localcommands/templates/plone_pas/validation/plugins/__init__.py_insert
+zopeskel/localcommands/templates/plone_pas/validation/plugins/validation.py_tmpl
+zopeskel/templates/archetype/CHANGES.txt_tmpl
+zopeskel/templates/archetype/CONTRIBUTORS.txt_tmpl
+zopeskel/templates/archetype/MANIFEST.in_tmpl
+zopeskel/templates/archetype/README.txt_tmpl
+zopeskel/templates/archetype/setup.py_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/README.txt_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/__init__.py_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/config.py_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/configure.zcml_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/browser/__init__.py
+zopeskel/templates/archetype/+namespace_package+/+package+/browser/configure.zcml_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/content/__init__.py
+zopeskel/templates/archetype/+namespace_package+/+package+/content/configure.zcml_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/__init__.py
+zopeskel/templates/archetype/+namespace_package+/+package+/portlets/__init__.py
+zopeskel/templates/archetype/+namespace_package+/+package+/portlets/configure.zcml_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/factorytool.xml
+zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/portlets.xml
+zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/types.xml
+zopeskel/templates/archetype/+namespace_package+/+package+/tests/__init__.py
+zopeskel/templates/archetype/+namespace_package+/+package+/tests/base.py_tmpl
+zopeskel/templates/archetype/+namespace_package+/+package+/tests/test_doctest.py_tmpl
+zopeskel/templates/basic_namespace/README.txt_tmpl
+zopeskel/templates/basic_namespace/setup.py_tmpl
+zopeskel/templates/basic_namespace/+namespace_package+/__init__.py_tmpl
+zopeskel/templates/basic_namespace/+namespace_package+/+package+/__init__.py_tmpl
+zopeskel/templates/basic_namespace/docs/HISTORY.txt_tmpl
+zopeskel/templates/basic_zope/+project+-configure.zcml_tmpl
+zopeskel/templates/basic_zope/+namespace_package+/__init__.py
+zopeskel/templates/basic_zope/+namespace_package+/+package+/README.txt_tmpl
+zopeskel/templates/basic_zope/+namespace_package+/+package+/__init__.py
+zopeskel/templates/basic_zope/+namespace_package+/+package+/configure.zcml_tmpl
+zopeskel/templates/basic_zope/+namespace_package+/+package+/tests.py_tmpl
+zopeskel/templates/basic_zope/+namespace_package+/+package+/zope2.py_tmpl
+zopeskel/templates/kss_plugin/README.txt
+zopeskel/templates/kss_plugin/setup.py_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/__init__.py
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/__init__.py
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/+namespace_package+.+namespace_package2+.+package+-configure.zcml_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/__init__.py
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.kss
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.pt_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/__init__.py
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/configure.zcml_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/zopeconfig.py_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/+package+.js_tmpl
+zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py
+zopeskel/templates/kss_plugin/docs/HISTORY.txt
+zopeskel/templates/nested_namespace/README.txt_tmpl
+zopeskel/templates/nested_namespace/setup.py_tmpl
+zopeskel/templates/nested_namespace/+namespace_package+/__init__.py_tmpl
+zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/__init__.py_tmpl
+zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
+zopeskel/templates/nested_namespace/docs/HISTORY.txt_tmpl
+zopeskel/templates/plone/setup.py_tmpl
+zopeskel/templates/plone/+namespace_package+/+package+/__init__.py_tmpl
+zopeskel/templates/plone/+namespace_package+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl
+zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
+zopeskel/templates/plone/docs/INSTALL.txt_tmpl
+zopeskel/templates/plone/docs/LICENSE.GPL
+zopeskel/templates/plone/docs/LICENSE.txt_tmpl
+zopeskel/templates/plone2.5_buildout/README.txt
+zopeskel/templates/plone2.5_theme/MANIFEST.in_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/__init__.py_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/config.py_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles.zcml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/setuphandlers.py
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/version.txt_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/Install.py_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/__init__.py
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/import_steps.xml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/CONTENT.txt_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/CONTENT.txt_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base.css.dtml
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base_properties.props_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/generated.css.dtml
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/portlets.css.dtml
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/public.css.dtml
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/CONTENT.txt_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/CONTENT.txt
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/+package+.css.dtml_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/CONTENT.txt_tmpl
+zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/CONTENT.txt
+zopeskel/templates/plone2_theme/HISTORY.txt_tmpl
+zopeskel/templates/plone2_theme/README.txt_tmpl
+zopeskel/templates/plone2_theme/__init__.py_tmpl
+zopeskel/templates/plone2_theme/config.py_tmpl
+zopeskel/templates/plone2_theme/version.txt_tmpl
+zopeskel/templates/plone2_theme/Extensions/Install.py_tmpl
+zopeskel/templates/plone2_theme/Extensions/__init__.py
+zopeskel/templates/plone2_theme/Extensions/utils.py
+zopeskel/templates/plone2_theme/skins/+package+_styles/+package+.css.dtml_tmpl
+zopeskel/templates/plone2_theme/skins/+package+_styles/base.css.dtml
+zopeskel/templates/plone2_theme/skins/+package+_styles/base_properties.props_tmpl
+zopeskel/templates/plone2_theme/skins/+package+_styles/generated.css.dtml
+zopeskel/templates/plone2_theme/skins/+package+_styles/portlets.css.dtml
+zopeskel/templates/plone2_theme/skins/+package+_styles/public.css.dtml
+zopeskel/templates/plone2_theme/tests/__init__.py
+zopeskel/templates/plone2_theme/tests/framework.py
+zopeskel/templates/plone2_theme/tests/runalltests.py
+zopeskel/templates/plone2_theme/tests/testSkeleton.py_tmpl
+zopeskel/templates/plone2_theme/tests/testStyleInstallation.py_tmpl
+zopeskel/templates/plone3_buildout/README.txt
+zopeskel/templates/plone3_buildout/bootstrap.py
+zopeskel/templates/plone3_buildout/buildout.cfg_tmpl
+zopeskel/templates/plone3_buildout/products/README.txt
+zopeskel/templates/plone3_buildout/src/README.txt
+zopeskel/templates/plone3_buildout/var/README.txt
+zopeskel/templates/plone3_portlet/setup.py_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.pt_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.py_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/metadata.xml_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/portlets.xml_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/base.py_tmpl
+zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/test_portlet.py_tmpl
+zopeskel/templates/plone3_portlet/docs/INSTALL.txt_tmpl
+zopeskel/templates/plone3_portlet/docs/LICENSE.GPL
+zopeskel/templates/plone3_portlet/docs/LICENSE.txt_tmpl
+zopeskel/templates/plone3_theme/+project+-configure.zcml_tmpl
+zopeskel/templates/plone3_theme/MANIFEST.in_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles.zcml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/setuphandlers.py_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins.zcml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/version.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/__init__.py
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/configure.zcml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/interfaces.py_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlet.pt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlets.py_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/README.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/README.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/main.css_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/README.txt
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/+namespace_package+.+package+_various.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/viewlets.xml_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/CONTENT.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/CONTENT.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/CONTENT.txt_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base.css.dtml
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base_properties.props_tmpl
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/portlets.css.dtml
+zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/public.css.dtml
+zopeskel/templates/plone4_buildout/README.txt
+zopeskel/templates/plone4_buildout/bootstrap.py
+zopeskel/templates/plone4_buildout/buildout.cfg_tmpl
+zopeskel/templates/plone4_buildout/src/README.txt
+zopeskel/templates/plone4_buildout/var/README.txt
+zopeskel/templates/plone_app/setup.py_tmpl
+zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
+zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
+zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
+zopeskel/templates/plone_app/docs/INSTALL.txt_tmpl
+zopeskel/templates/plone_app/docs/LICENSE.GPL
+zopeskel/templates/plone_app/docs/LICENSE.txt_tmpl
+zopeskel/templates/plone_hosting/README.txt
+zopeskel/templates/plone_hosting/base.cfg_tmpl
+zopeskel/templates/plone_hosting/bootstrap.py
+zopeskel/templates/plone_hosting/buildout.cfg_tmpl
+zopeskel/templates/plone_hosting/etc/supervisord.conf_tmpl
+zopeskel/templates/plone_hosting/products/README.txt
+zopeskel/templates/plone_hosting/src/README.txt
+zopeskel/templates/plone_hosting/templates/logrotate.conf
+zopeskel/templates/plone_hosting/var/README.txt
+zopeskel/templates/plone_pas/setup.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/install.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/interface.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugin.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/__init__.py
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/add_plugin.zpt_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/configure.zcml_tmpl
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/icon.gif
+zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/__init__.py_tmpl
+zopeskel/templates/plone_pas/docs/CHANGES.txt_tmpl
+zopeskel/templates/plone_pas/docs/CONTRIBUTORS.txt_tmpl
+zopeskel/templates/plone_pas/docs/INSTALL.txt_tmpl
+zopeskel/templates/plone_pas/docs/LICENSE.GPL
+zopeskel/templates/plone_pas/docs/LICENSE.txt_tmpl
+zopeskel/templates/plone_pas/docs/README.txt_tmpl
+zopeskel/templates/recipe/CHANGES.txt_tmpl
+zopeskel/templates/recipe/CONTRIBUTORS.txt_tmpl
+zopeskel/templates/recipe/README.txt_tmpl
+zopeskel/templates/recipe/bootstrap.py
+zopeskel/templates/recipe/buildout.cfg_tmpl
+zopeskel/templates/recipe/setup.py_tmpl
+zopeskel/templates/recipe/+namespace_package+/__init__.py_tmpl
+zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/__init__.py_tmpl
+zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
+zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
+zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py_tmpl
+zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/test_docs.py_tmpl
+zopeskel/templates/silva_buildout/README.txt
+zopeskel/templates/silva_buildout/bootstrap.py
+zopeskel/templates/silva_buildout/buildout.cfg_tmpl
+zopeskel/templates/silva_buildout/products/README.txt
+zopeskel/templates/silva_buildout/src/README.txt
+zopeskel/templates/silva_buildout/var/README.txt
+zopeskel/templates/zope2_buildout/README.txt
+zopeskel/templates/zope2_buildout/bootstrap.py
+zopeskel/templates/zope2_buildout/buildout.cfg_tmpl
+zopeskel/templates/zope2_buildout/products/README.txt
+zopeskel/templates/zope2_buildout/src/README.txt
+zopeskel/templates/zope2_buildout/var/README.txt
+zopeskel/tests/__init__.py
+zopeskel/tests/test_all.py
+zopeskel/tests/test_base.py
+zopeskel/tests/test_vars.py
+zopeskel/tests/test_zopeskel_script.py
+zopeskel/tests/test_zopeskeldocs.py
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/entry_points.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/entry_points.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/entry_points.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,56 @@
+
+      [paste.paster_create_template]
+      basic_namespace = zopeskel:BasicNamespace
+      nested_namespace = zopeskel:NestedNamespace
+      basic_zope = zopeskel:BasicZope
+      plone = zopeskel:Plone
+      plone_app = zopeskel:PloneApp
+      plone2_theme = zopeskel:Plone2Theme
+      plone2.5_theme = zopeskel:Plone25Theme
+      plone3_theme = zopeskel:Plone3Theme
+      plone2.5_buildout = zopeskel:Plone25Buildout
+      plone3_buildout = zopeskel:Plone3Buildout
+      plone4_buildout = zopeskel:Plone4Buildout
+      archetype = zopeskel:Archetype
+      plone3_portlet = zopeskel:Plone3Portlet
+      plone_hosting = zopeskel.hosting:StandardHosting
+      recipe = zopeskel:Recipe
+      silva_buildout = zopeskel:SilvaBuildout
+      plone_pas = zopeskel:PlonePas
+      kss_plugin = zopeskel:KssPlugin
+
+      [paste.paster_command]
+      addcontent = zopeskel.localcommands:ZopeSkelLocalCommand
+
+      [zopeskel.zopeskel_sub_template]
+      portlet = zopeskel.localcommands.plone:Portlet
+      view = zopeskel.localcommands.plone:View
+      zcmlmeta = zopeskel.localcommands.plone:ZCMLMetaDirective
+      i18nlocale = zopeskel.localcommands.plone:I18nLocale
+
+      contenttype = zopeskel.localcommands.archetype:ContentType
+      atschema = zopeskel.localcommands.archetype:ATSchemaField
+      form = zopeskel.localcommands.plone:Form
+      formfield = zopeskel.localcommands.plone:FormField
+      browserlayer = zopeskel.localcommands.plone:BrowserLayer
+
+      extraction_plugin = zopeskel.localcommands.plone_pas:ExtractionPlugin
+      authentication_plugin = zopeskel.localcommands.plone_pas:AuthenticationPlugin
+      challenge_plugin = zopeskel.localcommands.plone_pas:ChallengePlugin
+      credentials_reset_plugin = zopeskel.localcommands.plone_pas:CredentialsResetPlugin
+      user_adder_plugin = zopeskel.localcommands.plone_pas:UserAdderPlugin
+      role_assigner_plugin = zopeskel.localcommands.plone_pas:RoleAssignerPlugin
+      user_factory_plugin = zopeskel.localcommands.plone_pas:UserFactoryPlugin
+      anonymous_user_factory_plugin = zopeskel.localcommands.plone_pas:AnonymousUserFactoryPlugin
+      properties_plugin = zopeskel.localcommands.plone_pas:PropertiesPlugin
+      groups_plugin = zopeskel.localcommands.plone_pas:GroupsPlugin
+      roles_plugin = zopeskel.localcommands.plone_pas:RolesPlugin
+      update_plugin = zopeskel.localcommands.plone_pas:UpdatePlugin
+      validation_plugin = zopeskel.localcommands.plone_pas:ValidationPlugin
+      user_enumeration_plugin = zopeskel.localcommands.plone_pas:UserEnumerationPlugin
+      group_enumeration_plugin = zopeskel.localcommands.plone_pas:GroupEnumerationPlugin
+      role_enumeration_plugin = zopeskel.localcommands.plone_pas:RoleEnumerationPlugin
+
+      [console_scripts]
+      zopeskel = zopeskel.zopeskel_script:run
+      
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/requires.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/requires.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/requires.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+PasteScript>=1.7.2
+Cheetah>1.0,<=2.2.1
+
+[test]
+zope.testing
+zc.buildout
+Cheetah
+PasteScript
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+zopeskel

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,19 @@
+# package
+from zopeskel.basic_namespace import BasicNamespace
+from zopeskel.plone2_theme import Plone2Theme
+from zopeskel.plone25_theme import Plone25Theme
+from zopeskel.plone_app import PloneApp
+from zopeskel.basic_zope import BasicZope
+from zopeskel.nested_namespace import NestedNamespace
+from zopeskel.plone3_buildout import Plone3Buildout
+from zopeskel.plone4_buildout import Plone4Buildout
+from zopeskel.recipe import Recipe
+from zopeskel.archetype import Archetype
+from zopeskel.plone import Plone
+from zopeskel.plone3_portlet import Plone3Portlet
+from zopeskel.plone25_buildout import Plone25Buildout
+from zopeskel.plone3_theme import Plone3Theme
+from zopeskel.silva_buildout import SilvaBuildout
+from zopeskel.plone_pas import PlonePas
+from zopeskel.kss_plugin import KssPlugin
+from zopeskel.zope2_buildout import Zope2Buildout

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,144 @@
+import copy
+
+from zopeskel.base import BaseTemplate
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import StringVar, BooleanVar, IntVar, OnOffVar, BoundedIntVar
+
+VAR_PLONEVER = StringVar(
+    'plone_version',
+    title='Plone Version',
+    description='Plone version # to install',
+    default='3.3.5',
+    modes=(EASY,EXPERT),
+    page='Main',
+    help="""
+This is the version of Plone that will be used for this buildout.
+You should enter the version number you wish to use.
+"""
+    )
+
+VAR_Z2_INSTALL = StringVar(
+    'zope2_install',
+    title='Zope2 Install Path',
+    description='Path to Zope2 installation; leave blank to fetch one!',
+    default='',
+    modes=(EASY,EXPERT),
+    page='Main',
+    help="""
+This is the file path to the Zope 2 installation. You can enter this
+path to use a pre-existing installation, or you can leave it blank, and
+the current Zope 2 will be downloaded and installed in your new
+buildout.
+"""
+    )
+
+VAR_PLONE_PRODUCTS = StringVar(
+    'plone_products_install',
+    title='Plone Products Directory',
+    description='Path to Plone products; leave blank to fetch [Plone 3.0/3.1 only]',
+    modes=(EASY, EXPERT),
+    page='Main',
+    default='',
+    help="""
+Prior to Plone 3.2, Plone shipped as individual Zope products. If you
+are installing a version prior to 3.2, and you have these Plone products
+already downloaded, you can specify the path to them here. If you leave
+this blank, they will be downloaded.
+
+For Plone 3.2 and later, this option is ignored.
+"""
+    )
+
+VAR_ZOPE_USER = StringVar(
+    'zope_user',
+    title='Initial Zope Username',
+    description='Username for Zope root admin user',
+    modes=(EASY, EXPERT),
+    page='Main',
+    default='admin',
+    help="""
+Your buildout will have a single user, with manager privileges, defined
+at the root. This option lets you select the name for this user.
+"""
+    )
+
+VAR_ZOPE_PASSWD = StringVar(
+    'zope_password',
+    title='Initial User Password',
+    description='Password for Zope root admin user',
+    modes=(EASY, EXPERT),
+    page='Main',
+    default='',
+    help="""
+Your buildout will have a single user, "%(zope_user)s", with manager 
+privileges, defined at the root. This option lets you select the initial
+password for this user. If left blank, the password will be randomly
+generated.
+"""
+    )
+
+VAR_HTTP = BoundedIntVar(
+    'http_port',
+    title='HTTP Port',
+    description='Port that Zope will use for serving HTTP',
+    default='8080',
+    modes=(EXPERT,EASY),
+    page='Main',
+    help="""
+This options lets you select the port # that Zope will use for serving
+HTTP.
+""",
+    min=1024,
+    max=65535,
+    )
+
+VAR_DEBUG_MODE = OnOffVar(
+    'debug_mode',
+    title='Debug Mode',
+    description='Should debug mode be "on" or "off"?',
+    default='off',
+    modes=(EXPERT,EASY),
+    page='Main',
+    help="""
+Debug mode (sometimes called "Debug/Development Mode") is the correct
+setting for running a site under development--it ensures that on-disk
+changes to templates and skin scripts are immediately visible, and
+allows use of certain add-on debugging/profiling products. Running your
+Zope in the foreground (with "bin/plonectl fg" or similar commands)
+always puts you in debug mode; this setting controls whether you are
+in debug mode even when running in the background.
+
+You should set this to "on" during development; once you are ready to
+deploy your site, you change this to "off" in your buildout.cfg.
+"""
+    )
+
+VAR_VERBOSE_SEC = OnOffVar(
+        'verbose_security',
+        title='Verbose Security?',
+        description='Should verbose security be "on" or "off"?',
+        default='off',
+        modes=(EASY, EXPERT),
+        page='Main',
+        help="""
+Security error messages (such as "Unauthorized" errors) in Plone are
+intentionally vague--the system doesn't want to reveal too much about
+the security configuration in error messages, given that those error
+messages may be inappropriately printed out/shared/email and intercepted
+by others.
+
+"Verbose security" is a buildout setting that enables significantly more
+helpful, detailed unauthorized error messages.
+
+There may be a small security risk in leaving this enabled on a site in
+deployment; if you turn it on, you should consider turning it off.
+"""
+        )
+
+class AbstractBuildout(BaseTemplate):
+    """Abstract class for all templates that produce buildouts."""
+
+    category = "Buildout"
+
+    vars = copy.deepcopy(BaseTemplate.vars)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_zope.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_zope.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/abstract_zope.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,37 @@
+import copy
+from zopeskel.basic_namespace import BasicNamespace
+from zopeskel.nested_namespace import NestedNamespace
+from zopeskel.vars import BooleanVar
+
+VAR_ZOPE2 = BooleanVar(
+        'zope2product',
+        title='Zope2 Product?',
+        description='Are you creating a product for Zope2/Plone or an Archetypes Product?',
+        default=True,
+        modes=(),
+        help="""
+Zope2 products will have a registration hook in their __init__.py,
+used by the Zope2 machinery to handle any required processes during
+server startup. Archetypes projects will require this, and all
+projects for Zope2/Plone will benefit from it (even if not strictly
+required, this allows the project to appear in places like the
+Zope2 Control Panel list of products).
+
+An appropriate time to choose False here would be if you are creating
+a completely Zope3-only or non-Zope project.
+"""
+        )
+
+class AbstractZope(BasicNamespace):
+    """Abstract class for Zope-based packages in a namespace."""
+    vars = copy.deepcopy(BasicNamespace.vars)
+    vars.append(VAR_ZOPE2)
+    category = "Zope Development"
+
+class AbstractNestedZope(NestedNamespace):
+    """Abstract class for Zope-based packages in a nested namespace."""
+    vars = copy.deepcopy(NestedNamespace.vars)
+    vars.append(VAR_ZOPE2)
+    category = "Zope Development"
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/archetype.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/archetype.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/archetype.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,55 @@
+import os
+import copy
+
+from zopeskel.plone import Plone
+from zopeskel.base import get_var
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import StringVar
+
+class Archetype(Plone):
+    _template_dir = 'templates/archetype'
+    summary = 'A Plone project that uses Archetypes content types'
+    help = """
+This creates a Plone project that uses Archetypes content types.
+It has local commands that will allow you to add content types
+and to add fields to your new content types.
+"""
+    post_run_msg = """
+There is a local command to add individual Archetype content types
+and to add fields to those content types. See the instructions above
+on how to use this command.
+"""
+
+    required_templates = ['plone']
+    use_cheetah = True
+    use_local_commands = True
+
+    vars = copy.deepcopy(Plone.vars)
+    vars.insert(1, StringVar(
+        'title',
+        title='Project Title',
+        description='Title of the project',
+        modes=(EASY, EXPERT),
+        default='Example Name',
+        help="""
+This becomes the title of the project. It is used in the 
+GenericSetup registration for the project and, as such, appears
+in Plone's Add/Remove products form.
+"""
+       )
+       )
+    #zope2product should always defaults to True
+    get_var(vars, 'zope2product').default = True
+    #add_profile should always default to True for archetype packages
+    get_var(vars, 'add_profile').default = True
+    #add_profile need not appear as a question for archetype packages
+    get_var(vars, 'add_profile').modes = (EXPERT,)
+
+    def post(self, command, output_dir, vars):
+        # Remove tests.py -- we already have a tests/ package
+        path = os.path.join(output_dir,
+                            vars['namespace_package'],
+                            vars['package'])
+        os.remove(os.path.join(path, 'tests.py'))
+
+        super(Archetype, self).post(command, output_dir, vars)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/base.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/base.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/base.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,367 @@
+import os
+from textwrap import TextWrapper
+import ConfigParser
+from ConfigParser import SafeConfigParser
+from paste.script import command
+from paste.script import pluginlib
+from paste.script import templates
+from paste.script.templates import var as base_var
+from paste.script.command import BadCommand
+from paste.script.templates import BasicPackage
+from zopeskel.vars import var, BooleanVar, StringChoiceVar
+from zopeskel.vars import EASY, EXPERT, ALL
+from zopeskel.vars import ValidationException
+
+
+LICENSE_CATEGORIES = {
+    'DFSG' : 'License :: DFSG approved',
+    'EFS' : 'License :: Eiffel Forum License (EFL)',
+    'NPL' : 'License :: Netscape Public License (NPL)',
+    'ASL' : 'License :: OSI Approved :: Apache Software License',
+    'BSD' : 'License :: OSI Approved :: BSD License',
+    'FDL' : 'License :: OSI Approved :: GNU Free Documentation License (FDL)',
+    'GPL' : 'License :: OSI Approved :: GNU General Public License (GPL)',
+    'LGPL' : 'License :: OSI Approved :: GNU Library or Lesser General Public License (LGPL)',
+    'MIT' : 'License :: OSI Approved :: MIT License',
+    'MPL' : 'License :: OSI Approved :: Mozilla Public License 1.0 (MPL)',
+    'MPL11' : 'License :: OSI Approved :: Mozilla Public License 1.1 (MPL 1.1)',
+    'QPL' : 'License :: OSI Approved :: Qt Public License (QPL)',
+    'ZPL' : 'License :: OSI Approved :: Zope Public License',
+    }
+
+
+def wrap_help_paras(wrapper, text):
+    """Given a string containing embedded paras, output wrapped"""
+
+    for idx, para in enumerate(text.split("\n\n")):
+        if idx:
+            print
+        print wrapper.fill(para)
+
+def get_zopeskel_prefs():
+    # http://snipplr.com/view/7354/get-home-directory-path--in-python-win-lin-other/
+    try:
+        from win32com.shell import shellcon, shell
+        homedir = shell.SHGetFolderPath(0, shellcon.CSIDL_APPDATA, 0, 0)
+    except ImportError: # quick semi-nasty fallback for non-windows/win32com case
+        homedir = os.path.expanduser("~")
+
+    # Get defaults from .zopeskel
+    config = SafeConfigParser()
+    config.read('%s/.zopeskel' % homedir)
+    return config
+
+def get_var(vars, name):
+    for var in vars:
+        if var.name == name:
+            return var
+    else:
+        raise ValueError("No such var: %r" % name)
+
+
+def update_setup_cfg(path, section, option, value):
+
+    parser = ConfigParser.ConfigParser()
+    if os.path.exists(path):
+        parser.read(path)
+
+    if not parser.has_section(section):
+        parser.add_section(section)
+
+    parser.set(section, option, value)
+    parser.write(open(path, 'w'))
+
+
+class BaseTemplate(templates.Template):
+    """Base template for all ZopeSkel templates"""
+
+    #a zopeskel template has to set this to True if it wants to use
+    #localcommand
+    use_local_commands = False
+    null_value_marker = []
+    pre_run_msg = None
+    post_run_msg = None
+
+    vars = [
+        StringChoiceVar(
+            'expert_mode',
+            title='Expert Mode?',
+            description='What question mode would you like? (easy/expert/all)?',
+            page='Begin',
+            default='easy',
+            choices=('easy','expert','all'),
+            help="""
+In easy mode, you will be asked fewer, more common questions.
+
+In expert mode, you will be asked to answer more advanced,
+technical questions.
+
+In all mode, no questions will be skipped--even things like
+author_email, which would normally be a default set in a
+$HOME/.zopeskel file.
+"""),
+    ]
+
+    #this is just to be able to add ZopeSkel to the list of paster_plugins if
+    #the use_local_commands is set to true and to write a zopeskel section in
+    #setup.cfg file containing the name of the parent template.
+    #it will be used by addcontent command to list the apropriate subtemplates
+    #for the generated project. the post method is not a candidate because
+    #many templates override it
+    def run(self, command, output_dir, vars):
+
+        if self.use_local_commands and 'ZopeSkel' not in self.egg_plugins:
+            self.egg_plugins.append('ZopeSkel')
+
+        templates.Template.run(self, command, output_dir, vars)
+
+        setup_cfg = os.path.join(output_dir, 'setup.cfg')
+        if self.use_local_commands:
+            update_setup_cfg(setup_cfg, 'zopeskel', 'template', self.name)
+
+    def print_subtemplate_notice(self, output_dir=None):
+            """Print a notice about local commands being availabe (if this is
+            indeed the case).
+
+            Unfortunately for us, at this stage in the process, the
+            egg_info directory has not yet been created (and won't be
+            within the scope of this template running [see
+            paste.script.create_distro.py]), so we cannot show which
+            subtemplates are available.
+            """
+            plugins = pluginlib.resolve_plugins(['ZopeSkel'])
+            commands = pluginlib.load_commands_from_plugins(plugins)
+            if not commands:
+                return
+            commands = commands.items()
+            commands.sort()
+            longest = max([len(n) for n, c in commands])
+            print_commands = []
+            for name, command in commands:
+                name = name + ' ' * (longest - len(name))
+                print_commands.append('  %s  %s' % (name,
+                                                    command.load().summary))
+            print_commands = '\n'.join(print_commands)
+            print '-' * 78
+            print """\
+The project you just created has local commands. These can be used from within
+the product.
+
+usage: paster COMMAND
+
+Commands:
+%s
+
+For more information: paster help COMMAND""" % print_commands
+            print '-' * 78
+
+    def print_zopeskel_message(self, msg_name):
+        """ print a message stored as an attribute of the template
+        """
+        msg = getattr(self, msg_name, None)
+        if msg:
+            textwrapper = TextWrapper(
+                    initial_indent="**  ",
+                    subsequent_indent="**  ",
+                    )
+            print "\n" + '*'*74
+            wrap_help_paras(textwrapper, msg)
+            print '*'*74 + "\n"
+
+    def pre(self, *args, **kwargs):
+        templates.Template.pre(self, *args, **kwargs)
+
+    def get_template_stack(self, command):
+        """ return a list of the template objects being run through in the given command
+        """
+        asked_tmpls = command.options.templates or ['basic_package']
+        templates = []
+        for tmpl_name in asked_tmpls:
+            command.extend_templates(templates, tmpl_name)
+        return [tmpl_obj for tmpl_name, tmpl_obj in templates]
+
+    def get_position_in_stack(self, stack):
+        """ return the index of the currently running template in the overall stack
+        """
+        class_stack = [t.__class__ for t in stack]
+
+        return class_stack.index(self.__class__)
+
+    def should_print_subcommands(self, command):
+        """ return true or false
+
+            if this template has subcommands _and_ is the last template
+            to be run through that does, go ahead and return true, otherwise
+            return false
+        """
+        if not getattr(self, 'use_local_commands', False):
+            return False
+        # we have local commands for this template, is it the last one for
+        # which this is true?
+        stack = self.get_template_stack(command)
+        index = self.get_position_in_stack(stack)
+        remaining_stack = stack[index+1:]
+        have_subcommands_left = [getattr(t, 'use_local_commands', False)
+                                 for t in remaining_stack]
+        if True in have_subcommands_left:
+            return False
+
+        return True
+
+    def post(self, command, output_dir, vars):
+        if self.should_print_subcommands(command):
+            self.print_subtemplate_notice()
+        templates.Template.post(self, command, output_dir, vars)
+        # at the very end of it all, print the post_run_msg so we can
+        # inform users of important information.
+        self.print_zopeskel_message('post_run_msg')
+
+    def _filter_for_modes(self, mode, expected_vars):
+        """Filter questions down according to our mode.
+
+        ALL = show all questions
+        EASY, EXPERT = show just those
+        """
+
+        if mode == ALL: return {}
+
+        hidden = {}
+
+        for var in expected_vars:
+            # if in expert mode, hide vars not for expert mode
+            if  mode not in var.modes:
+                hidden[var.name] = var.default
+
+        return hidden
+
+    def override_package_names_defaults(self, vars, expect_vars):
+        """Override package names defaults using project title.
+
+        Override the default for namespace_package, namespace_package2,
+        and package from splitting the project title--if ndots is
+        specified by this template.
+
+        This is helpful for new users, who find it confusing to provide
+        a package name like "mycompany.theme.blue" and then have to
+        (slightly-redundantly) specify namespace_package=mycompany,
+        namespace_package2=theme, package=blue.
+        """
+
+        ndots = getattr(self, 'ndots', None)
+        if ndots:
+            parts = vars['project'].split(".")
+            if ndots >= 1 and len(parts) >= 1:
+                get_var(expect_vars, 'namespace_package').default = parts[0]
+            if ndots >= 2 and len(parts) >= 2:
+                get_var(expect_vars, 'namespace_package2').default = parts[1]
+            package_name = parts[-1]
+            get_var(expect_vars, 'package').default = package_name
+
+    def check_vars(self, vars, cmd):
+        # if we need to notify users of anything before they start this
+        # whole process, we can do it here.
+        self.print_zopeskel_message('pre_run_msg')
+
+        # Copied and modified from PasteScript's check_vars--
+        # the method there wasn't hookable for the things
+        # we need -- question posing, validation, etc.
+        #
+        # Admittedly, this could be merged into PasteScript,
+        # but it was decided it was easier to limit scope of
+        # these changes to ZopeSkel, as other projects may
+        # use PasteScript in very different ways.
+
+
+        cmd._deleted_once = 1      # don't re-del package
+
+        textwrapper = TextWrapper(
+                initial_indent="|  ",
+                subsequent_indent="|  ",
+                )
+
+        # now, mostly copied direct from paster
+        expect_vars = self.read_vars(cmd)
+        if not expect_vars:
+            # Assume that variables aren't defined
+            return vars
+        converted_vars = {}
+        errors = []
+
+        config = get_zopeskel_prefs()
+        # pastescript allows one to request more than one template (multiple
+        # -t options at the command line) so we will get a list of templates
+        # from the cmd's options property
+        requested_templates = cmd.options.templates
+        for var in expect_vars:
+            for template in requested_templates:
+                if config.has_option(template, var.name):
+                    var.default = config.get(template, var.name)
+                    break
+            else:
+                # Not found in template section, now look explicitly
+                # in DEFAULT section
+                if config.has_option('DEFAULT', var.name):
+                    var.default = config.get('DEFAULT', var.name)
+
+        self.override_package_names_defaults(vars, expect_vars)
+
+        unused_vars = vars.copy()
+
+        for var in expect_vars:
+            if var.name not in unused_vars:
+                if cmd.interactive:
+                    prompt = var.pretty_description()
+                    response = self.null_value_marker
+                    while response is self.null_value_marker:
+                        response = cmd.challenge(prompt, var.default, var.should_echo)
+                        if response == '?':
+                            help = var.further_help().strip() % converted_vars
+                            print
+                            wrap_help_paras(textwrapper, help)
+                            print
+                            response = self.null_value_marker;
+                        if response is not self.null_value_marker:
+                            try:
+                                response = var.validate(response)
+                            except ValidationException, e:
+                                print e
+                                response = self.null_value_marker;
+                    converted_vars[var.name] = response
+                elif var.default is command.NoDefault:
+                    errors.append('Required variable missing: %s'
+                                  % var.full_description())
+                else:
+                    converted_vars[var.name] = var.default
+            else:
+                converted_vars[var.name] = unused_vars.pop(var.name)
+
+            # filter the vars for mode.
+            if var.name == 'expert_mode':
+                expert_mode = converted_vars['expert_mode']
+                hidden = self._filter_for_modes(expert_mode, expect_vars)
+                unused_vars.update(hidden)
+
+        if errors:
+            raise command.BadCommand(
+                'Errors in variables:\n%s' % '\n'.join(errors))
+        converted_vars.update(unused_vars)
+        vars.update(converted_vars)
+
+        result = converted_vars
+
+        return result
+
+    @property
+    def pages(self):
+        pages = []
+        page_map = {}
+        for question in self.vars:
+            name = question.page
+            if name in page_map:
+                page = page_map[name]
+                page['vars'].append(question)
+            else:
+                page = {'name': name, 'vars': [question]}
+                pages.append(page)
+                page_map[name] = page
+        return pages

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_namespace.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_namespace.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_namespace.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,191 @@
+import copy
+from zopeskel.vars import var, DottedVar, StringVar, BooleanVar, TextVar
+from zopeskel.base import BaseTemplate
+from zopeskel.base import EASY, EXPERT
+
+class BasicNamespace(BaseTemplate):
+    _template_dir = 'templates/basic_namespace'
+    summary = "A basic Python project with a namespace package"
+    ndots = 1
+    help = """
+This creates a Python project without any Zope or Plone features.
+"""
+    category = "Core Python"
+
+    required_templates = []
+    use_cheetah = True
+    vars = copy.deepcopy(BaseTemplate.vars)
+    vars += [
+        DottedVar(
+            'namespace_package', 
+            title='Namespace Package Name',
+            description='Name of outer namespace package',
+            default='plone', 
+            modes=(EXPERT,), 
+            page='Namespaces',
+            help="""
+This is the name of the outer package (Python folder) for this project.
+For example, in 'Products.PloneFormGen', this would be 'Products'.
+This will often be (for Plone products) 'Products'; it may also be
+the name of your company/project, or a common-style name like
+(for Plone products) 'collective'.
+
+Note that, for some templates, there may be two namespaces, rather
+than one (to create eggs with names like 'plone.app.blog')--in this
+case, this would be 'plone', the first of the enclosing namespaces.
+            """
+            ), 
+
+        DottedVar(
+            'package', 
+            title='Package Name',
+            description='Name of the inner namespace package',
+            default='example', 
+            modes=(EXPERT,), 
+            page='Namespaces',
+            help="""
+This is the name of the innermost package (Python folder) for this project.
+For example, in 'Products.PloneFormGen', this would be 'PloneFormGen'.
+
+Note that, for some templates, there may be only a package name without
+a namespace package around it--in this case, this would be just the name
+of the package.
+"""
+            ),
+
+        StringVar(
+            'version', 
+            title='Version',
+            description='Version number for project',
+            default='1.0', 
+            modes=(EASY, EXPERT), 
+            page='Metadata',
+            help="""
+This becomes the version number of the created package. It will be set
+in the egg's setup.py, and may be referred to in other places in the
+generated project.    
+"""
+            ),
+
+        StringVar(
+            'description',
+            title='Description',
+            description='One-line description of the project', 
+            default='',
+            modes=(EASY, EXPERT), 
+            page='Metadata',
+            help="""
+This should be a single-line description of your project. It will be
+used in the egg's setup.py, and, for Zope/Plone projects, may be used
+in the GenericSetup profile description.
+"""
+            ),
+
+        TextVar(
+            'long_description', 
+            title='Long Description',
+            description='Multi-line description (in ReST)', 
+            default='',
+            modes=(), 
+            page='Metadata',
+            help="""
+This should be a full description for your project. It will be
+used in the egg's setup.py.
+
+It should be entered in 'restructured text' format; for information,
+see http://docutils.sourceforge.net/rst.html).
+"""
+            ),
+
+        StringVar(
+            'author',
+            title='Author',
+            description='Name of author for project',
+            modes=(), 
+            page='Metadata',
+            help="""
+This should be the name of the author of this project. It will be used
+in the egg's setup.py, and, for some templates, in the generated
+documentation/README files.
+"""
+            ),
+
+        StringVar(
+            'author_email',
+            title='Author Email', 
+            description='Email of author for project',
+            modes=(), 
+            page='Metadata',
+            help="""
+This should be the name of the author of this project. It will be used
+in the egg's setup.py, and, for some templates, in the generated
+documentation/README files.
+"""
+            ),
+
+        StringVar('keywords',
+            title='Keywords',
+            description='List of keywords, space-separated', 
+            modes=(), 
+            page='Metadata',
+            help="""
+This should be the list of keywords for this project. This will be
+used in the egg's setup.py (and, if this egg is later published on
+PyPI, will be used to categorize the project).
+"""
+            ),
+            
+        StringVar(
+            'url', 
+            title='Project URL',
+            description='URL of the homepage for this project',
+            modes=(), 
+            page='Metadata',
+            default='http://svn.plone.org/svn/collective/',
+            help="""
+This should be a URL for the homepage for this project (if applicable).
+It will be used in the egg's setup.py.
+"""
+            ),
+
+        StringVar(
+            'license_name', 
+            title='Project License',
+            description='Name of license for the project',
+            default='GPL', 
+            modes=(), 
+            page='Metadata',
+            help="""
+The license that this project is issued under. It will be used in the
+egg's setup.py.
+
+Common choices here are 'GPL' (for the GNU General Public License),
+'ZPL' (for the Zope Public License', and 'BSD' (for the BSD license).
+"""
+            ),
+
+        BooleanVar(
+            'zip_safe',
+            title='Zip-Safe?',
+            description='Can this project be used as a zipped egg? (true/false)',
+            default=False,
+            modes=(), 
+            page='Metadata',
+            help="""
+Some eggs can be used directly by Python in zipped format; others must
+be unzipped so that their contents can be properly used. Zipped eggs
+are smaller and may be easier to redistribute.
+
+Most Zope/Plone projects cannot be used in zipped format; if unsure,
+the safest answer is False.
+            """
+            ),
+        ]
+
+    def check_vars(self, vars, command):
+        if not command.options.no_interactive and \
+           not hasattr(command, '_deleted_once'):
+            del vars['package']
+            command._deleted_once = True
+        return super(BasicNamespace, self).check_vars(vars, command)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_zope.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_zope.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/basic_zope.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+import copy 
+from zopeskel.base import get_var
+from zopeskel.vars import var, BooleanVar
+from zopeskel import abstract_zope
+
+
+class BasicZope(abstract_zope.AbstractZope):
+    _template_dir = 'templates/basic_zope'
+    summary = "A Zope project"
+    help = """
+This creates a Zope project without any specific Plone features.
+"""
+    required_templates = ['basic_namespace']
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_zope.AbstractZope.vars)
+    get_var(vars, 'namespace_package').default = 'myzopelib'
+    get_var(vars, 'package').default = 'example'
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/archetypes.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/archetypes.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/archetypes.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,40 @@
+==================
+archetype template
+==================
+
+Use paster::
+
+    >>> paster('create -t archetype plone.example --no-interactive')
+    paster create -t archetype plone.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.example',
+    ...                            'plone', 'example')
+    >>> ls(package_dir)
+    README.txt
+    __init__.py
+    browser
+    config.py
+    configure.zcml
+    content
+    interfaces
+    portlets
+    profiles
+    tests
+
+Let's check the 'content' folder content::
+
+    >>> content_dir = os.path.join(package_dir, 'content')
+    >>> ls(content_dir)
+    __init__.py
+    configure.zcml
+
+Let's check the 'tests' folder content::
+
+    >>> tests_dir = os.path.join(package_dir, 'tests')
+    >>> ls(tests_dir)
+    __init__.py
+    base.py
+    test_doctest.py

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/atschema.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/atschema.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/atschema.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,68 @@
+================
+atschema builder
+================
+
+Build an archetype from scratch, and use paster to add a contenttype::
+
+    >>> paster('create -t archetype plone.example --no-interactive')
+    paster create -t archetype plone.example --no-interactive
+    ...
+    >>> cd('plone.example')
+    >>> paster('addcontent contenttype --no-interactive') # doctest: +ELLIPSIS
+    paster addcontent contenttype --no-interactive
+    ...
+          Inserting from types.xml_insert into...
+    ...
+    >>> content_dir = os.path.join('plone', 'example', 'content')
+    >>> interfaces_dir = os.path.join('plone', 'example', 'interfaces')
+    
+Check for the file::
+
+    >>> ls(content_dir)
+    __init__.py
+    configure.zcml
+    exampletype.py
+
+Check to see that atschema is available::
+
+    >>> paster('addcontent --list')
+    paster addcontent --list
+    ...
+      atschema:     A handy AT schema builder
+    ...
+    <BLANKLINE>
+    
+Now add a schema field via paster::
+
+    >>> paster('addcontent atschema --no-interactive')
+    paster addcontent atschema --no-interactive
+    ...
+	
+Check that the schema and was inserted and that related imports were inserted::
+
+    >>> cat(os.path.join(content_dir, 'exampletype.py'))
+    """Definition of the Example Type content type
+    """
+    ...
+    from plone.example import exampleMessageFactory as _
+    ... 
+        atapi.StringField(...
+    ...
+    atapi.registerType(ExampleType, PROJECTNAME)
+    <BLANKLINE>
+    
+Check that appropriate imports and a schema field were added to the interface file::
+
+    >>> cat(os.path.join(interfaces_dir, 'exampletype.py'))
+    from zope.interface import Interface
+    ...
+    from zope import schema
+    <BLANKLINE>
+    from plone.example import exampleMessageFactory as _
+    ...
+        newfield = schema.TextLine(
+    ...
+    <BLANKLINE>
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_namespace.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_namespace.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_namespace.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+========================
+basic_namespace template
+========================
+
+Use paster::
+
+    >>> paster('create -t basic_namespace plone.example --no-interactive')
+    paster create -t basic_namespace plone.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.example', 
+    ...                            'plone', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_zope.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_zope.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/basic_zope.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,23 @@
+========================
+basic_namespace template
+========================
+
+Use paster::
+
+    >>> paster('create -t basic_zope basiczope.example --no-interactive')
+    paster create -t basic_zope basiczope.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('basiczope.example', 
+    ...                            'basiczope', 'example')
+    >>> ls(package_dir)
+    README.txt
+    __init__.py
+    configure.zcml
+    tests.py
+    zope2.py
+
+    
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/kss_plugin.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/kss_plugin.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/kss_plugin.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,43 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t kss_plugin kss.plugin.example --no-interactive')
+    paster create -t kss_plugin kss.plugin.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> ls('kss.plugin.example')
+    README.txt
+    docs
+    kss
+    kss.plugin.example.egg-info
+    setup.py
+
+    >>> ls('kss.plugin.example', 'kss')
+    __init__.py
+    plugin
+
+    >>> ls('kss.plugin.example', 'kss', 'plugin')
+    __init__.py
+    example
+
+    >>> ls('kss.plugin.example', 'kss', 'plugin', 'example')
+    3rd_party
+    __init__.py
+    configure.zcml
+    demo
+    javascript
+    kss.plugin.example-configure.zcml
+    tests
+
+    >>> ls('kss.plugin.example', 'kss', 'plugin', 'example', 'demo')
+    __init__.py
+    configure.zcml
+    example.kss
+    example.pt
+    zopeconfig.py
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/localcommands.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/localcommands.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/localcommands.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,235 @@
+Local commands:
+==============
+
+PasteScript supports the notion of local commands. These are commands
+that can be executed from within a project. See the ``localcommands``
+directory in ZopeSkel for more information.
+
+
+Plone
+-----
+
+Check that the `addcontent` command is not globaly available::
+
+    >>> help_text = read_sh('paster help')
+    >>> help_text.find('addcontent') == -1
+    True
+
+`addcontent` is active for all ZopeSkel templates that have ``use_local_commands``
+attribute set to true.
+
+Let's for example take the plone template::
+
+    >>> paster('create -t plone plone.example --no-interactive')
+    paster create -t plone plone.example --no-interactive
+    ...
+    >>> cd('plone.example')
+    >>> paster('help')
+    paster help
+    ...
+    <BLANKLINE>
+    ZopeSkel local commands:
+      addcontent   Adds plone content types to your project
+    <BLANKLINE>
+    <BLANKLINE>
+    
+What sub-templates are available for a plone based project ?::
+
+    >>> paster('addcontent --list')
+    paster addcontent --list
+    Available templates:
+        browserlayer:  A Plone browserlayer
+        form:          A form skeleton
+        formfield:     Schema field for a form
+        i18nlocale:    An i18n locale directory structure
+        portlet:       A Plone 3 portlet
+        view:          A browser view skeleton
+        zcmlmeta:      A ZCML meta directive skeleton
+    
+
+Now we can add a portlet to our project::
+
+    >>> paster('addcontent --no-interactive portlet')
+    paster addcontent --no-interactive portlet
+    Inserting from __init__.py_insert into ...
+    Inserting from configure.zcml_insert into ...
+    Recursing into portlets
+    ...
+
+Test if we have the new files::
+
+    >>> ls('plone', 'example', 'portlets')
+    __init__.py
+    configure.zcml
+    exampleportlet.pt
+    exampleportlet.py
+    >>> ls('plone', 'example', 'tests')
+    __init__.py
+    base_exampleportlet.py
+    test_exampleportlet.py
+
+Check that the existing files like profile/portlets are updated::
+
+    >>> cat('plone', 'example', 'profiles', 'default', 'portlets.xml')
+    <?xml version="1.0"?>
+    ...
+       <portlet
+         addview="plone.example.portlets.ExamplePortlet"
+         title="Example portlet"
+         description=""
+         i18n:attributes="title; description"
+       />
+    ...
+    
+Adding a portlet via localcommand should update __init__.py to include 
+MessageFactory as well as defining a message factory for this project:
+
+    >>> cat('plone', 'example', '__init__.py')
+      # -*- extra stuff goes here -*- 
+    from zope.i18nmessageid import MessageFactory
+    <BLANKLINE>
+    exampleMessageFactory = MessageFactory('plone.example')
+    ...
+    
+The portlet localcommand should also update the root-level configure.zcml to insert an include package directive.  Make sure it has:
+
+    >>> cat('plone', 'example', 'configure.zcml')
+    <configure
+    ...
+    <BLANKLINE>
+      <include package=".portlets" />
+    <BLANKLINE>
+    ...
+
+
+Now add a new i18n locales directory structure to the project::
+
+    >>> paster('addcontent --no-interactive i18nlocale')
+    paster addcontent --no-interactive i18nlocale
+    Inserting from configure.zcml_insert into ...
+    Recursing into locales
+    ...
+
+Test if we have the new files::
+
+    >>> ls('plone', 'example', 'locales')
+    nl
+    
+The i18nlocale localcommand should also update the root-level configure.zcml to register the locales directory translations.  Make sure it has:
+
+    >>> cat('plone', 'example', 'configure.zcml')
+    <configure
+    ...
+    <BLANKLINE>
+      <i18n:registerTranslations directory="locales" />
+    <BLANKLINE>
+    ...
+
+Let's try to add a form to our project::
+
+    >>> paster('addcontent --no-interactive form')
+    paster addcontent --no-interactive form
+    Inserting from __init__.py_insert into ...
+    ...
+    Recursing into browser
+    ...
+
+Test if we have the new files::
+
+    >>> ls('plone', 'example', 'browser')
+    __init__.py
+    configure.zcml
+    exampleform.py
+    
+The form localcommand should also update the root-level configure.zcml to insert an include package directive.  Make sure it has:
+
+    >>> cat('plone', 'example', 'configure.zcml')
+    <configure
+    ...
+    <BLANKLINE>
+      <include package=".browser" />
+    <BLANKLINE>
+    ...
+
+
+Let's try to add a browserlayer to our project::
+    >>> paster('addcontent --no-interactive browserlayer')
+    paster addcontent --no-interactive browserlayer
+    A BrowserLayer is generally used in packages to be installed in a Plone Site.
+    If you didn't choose Register Profile option when creating this package
+    you should probably add a <genericsetup:registerProfile /> directive in
+    the main configure.zcml.
+    <BLANKLINE>
+      Recursing into browser 
+      ...
+        Inserting from configure.zcml_insert into ...
+      Recursing into interfaces
+      ...
+      Recursing into profiles
+        Recursing into default
+      ...
+
+Test if we have the new files::
+    >> ls('plone', 'example', 'browser')
+    __init__.py
+    configure.zcml
+
+    >> ls('plone', 'example', 'interfaces')
+    __init__.py
+    ploneexample.py
+
+Check that the existing files like profile/browserlayer are updated::
+    >>> cat('plone', 'example', 'profiles', 'default', 'browserlayer.xml')
+    <?xml version="1.0"?>
+    ...
+        <layer name="PloneExample"
+            interface="plone.example.interfaces.ploneexamplelayer.IPloneExampleLayer" />
+    ...
+
+    >>> cat('plone', 'example', 'browser', 'configure.zcml')
+    <configure
+    ...
+      <include package="plone.browserlayer" />
+    ...
+
+    >> cat('plone', 'example', 'interfaces', 'packagenamelayer.py')
+    ...
+    class IPloneExampleLayer(Interface):
+    ...
+
+Go back to the top level directory to have a more or less clean slate
+for the following tests.
+    >>> cd('..')
+
+Archetype
+---------
+
+An archetype based project has other localcommands available::
+
+    >>> paster('create -t archetype archetype.example --no-interactive')
+    paster create -t archetype archetype.example --no-interactive
+    ...
+    >>> cd('archetype.example')
+    >>> paster('help')
+    paster help
+    ...
+    <BLANKLINE>
+    ZopeSkel local commands:
+      addcontent   Adds plone content types to your project
+    <BLANKLINE>
+    <BLANKLINE>
+
+What sub-templates are available for an archetype based project ?::
+
+    >>> paster('addcontent --list')
+    paster addcontent --list
+    Available templates:
+        atschema:      A handy AT schema builder
+        browserlayer:  A Plone browserlayer
+        contenttype:   A content type skeleton
+        form:          A form skeleton
+        formfield:     Schema field for a form
+        i18nlocale:    An i18n locale directory structure
+        portlet:       A Plone 3 portlet
+        view:          A browser view skeleton
+        zcmlmeta:      A ZCML meta directive skeleton

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/nested_namespace.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/nested_namespace.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/nested_namespace.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+=========================
+nested_namespace template
+=========================
+
+Use paster::
+
+    >>> paster('create -t nested_namespace plone.app.example --no-interactive')
+    paster create -t nested_namespace plone.app.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.app.example', 
+    ...                            'plone', 'app', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,63 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone plone.example --no-interactive')
+    paster create -t plone plone.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.example', 
+    ...                            'plone', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    configure.zcml
+    tests.py 
+
+If we state that we want a GS profile, the template should create that for us::
+
+    >>> paster('create -t plone plone.example --no-interactive add_profile=True')
+    paster create -t plone plone.example --no-interactive add_profile=True
+    ...
+
+Check to ensure that the package structure is correct::
+
+    >>> package_dir = os.path.join('plone.example',
+    ...                             'plone', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    configure.zcml
+    profiles
+    tests.py
+    
+The profiles directory should contain only a 'default' folder with a metadata.xml file inside::
+
+    >>> ls(package_dir, 'profiles')
+    default
+    >>> ls(package_dir, 'profiles', 'default')
+    metadata.xml
+
+We need to verify that the metadata.xml file looks correct and that the configure.zcml file now contains a profile registration::
+
+    >>> cat(package_dir, 'profiles', 'default', 'metadata.xml')
+    <?xml version="1.0"?>
+    <metadata>
+      <version>1000</version>
+    </metadata>
+    <BLANKLINE>
+    >>> cat(package_dir, 'configure.zcml')
+    <configure
+    ...
+      <genericsetup:registerProfile
+          name="default"
+          title="plone.example"
+          directory="profiles/default"
+          description="Installs the plone.example package"
+          provides="Products.GenericSetup.interfaces.EXTENSION"
+          />
+    ...
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_buildout.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_buildout.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_buildout.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone2.5_buildout buildout --no-interactive')
+    paster create -t plone2.5_buildout buildout --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'buildout'
+    >>> ls(package_dir)
+    README.txt
+    bootstrap.py
+    buildout.cfg
+    products
+    src
+    var
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_theme.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_theme.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone25_theme.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,37 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone2.5_theme Products.ploneexample --no-interactive')
+    paster create -t plone2.5_theme Products.ploneexample --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'Products.ploneexample'
+    >>> ls(package_dir)
+    MANIFEST.in
+    Products
+    Products.ploneexample.egg-info
+    README.txt
+    docs
+    setup.cfg
+    setup.py
+
+And inside the package::
+
+    >>> package_dir = os.path.join('Products.ploneexample',
+    ...                            'Products', 'ploneexample')
+    >>> ls(package_dir)
+    Extensions
+    __init__.py
+    config.py
+    configure.zcml
+    profiles
+    profiles.zcml
+    setuphandlers.py
+    skins
+    tests.py
+    version.txt

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone2_theme.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone2_theme.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone2_theme.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone2_theme ExampleTheme --no-interactive')
+    paster create -t plone2_theme ExampleTheme --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'ExampleTheme'
+    >>> ls(package_dir)
+    Extensions
+    HISTORY.txt
+    README.txt
+    __init__.py
+    config.py
+    skins
+    tests
+    version.txt

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_buildout.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_buildout.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_buildout.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone3_buildout buildout --no-interactive')
+    paster create -t plone3_buildout buildout --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'buildout'
+    >>> ls(package_dir)
+    README.txt
+    bootstrap.py
+    buildout.cfg
+    products
+    src
+    var

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_portlet.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_portlet.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_portlet.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,19 @@
+========================
+plone template
+=======================
+
+Use paster::
+
+    >>> paster('create -t plone3_portlet collective.portlet.example --no-interactive')
+    paster create -t plone3_portlet collective.portlet.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'collective.portlet.example'
+    >>> ls(package_dir)
+    README.txt
+    collective
+    collective.portlet.example.egg-info
+    docs
+    setup.py

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_theme.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_theme.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone3_theme.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,39 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone3_theme plonetheme.example --no-interactive')
+    paster create -t plone3_theme plonetheme.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'plonetheme.example'
+    >>> ls(package_dir)
+    MANIFEST.in
+    README.txt
+    docs
+    plonetheme
+    plonetheme.example-configure.zcml
+    plonetheme.example.egg-info
+    setup.cfg
+    setup.py
+
+And the actual content of the theme::
+
+    >>> package_dir = os.path.join('plonetheme.example',
+    ...                            'plonetheme', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    browser
+    configure.zcml
+    locales
+    profiles
+    profiles.zcml
+    setuphandlers.py
+    skins
+    skins.zcml
+    tests.py
+    version.txt

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone4_buildout.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone4_buildout.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone4_buildout.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t plone4_buildout buildout --no-interactive')
+    paster create -t plone4_buildout buildout --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'buildout'
+    >>> ls(package_dir)
+    README.txt
+    bootstrap.py
+    buildout.cfg
+    src
+    var
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_app.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_app.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_app.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+========================
+plone_app template
+=======================
+
+Use paster::
+
+    >>> paster('create -t plone_app plone.app.example --no-interactive')
+    paster create -t plone_app plone.app.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.app.example', 
+    ...                            'plone', 'app', 'example')
+    >>> ls(package_dir)
+    __init__.py
+    configure.zcml
+    tests.py
+    version.txt
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_pas.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_pas.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/plone_pas.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,25 @@
+==================
+plone_pas template
+==================
+
+Use paster::
+
+    >>> paster('create -t plone_pas plone.pas.example --no-interactive')
+    paster create -t plone_pas plone.pas.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.pas.example',
+    ...                            'plone', 'pas', 'example')
+    >>> ls(package_dir)
+    README.txt
+    __init__.py
+    browser
+    configure.zcml
+    install.py
+    interface.py
+    plugin.py
+    plugins
+    tests.py
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/recipe.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/recipe.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/recipe.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,67 @@
+===============
+recipe template
+===============
+
+Use paster::
+
+    >>> paster('create -t recipe plone.recipe.example --no-interactive')
+    paster create -t recipe plone.recipe.example --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = os.path.join('plone.recipe.example', 
+    ...                            'plone', 'recipe', 'example')
+    >>> ls(package_dir)
+    README.txt
+    __init__.py
+    tests
+
+Let's check how the recipe looks like::
+
+    >>> recipe = open(os.path.join(package_dir, '__init__.py')).read()
+    >>> print recipe
+    # -*- coding: utf-8 -*-
+    """Recipe example"""
+    <BLANKLINE>
+    class Recipe(object):
+        """zc.buildout recipe"""
+    <BLANKLINE>
+        def __init__(self, buildout, name, options):
+            self.buildout, self.name, self.options = buildout, name, options
+    <BLANKLINE>
+        def install(self):
+            """Installer"""
+            # XXX Implement recipe functionality here
+    <BLANKLINE>
+            # Return files that were created by the recipe. The buildout
+            # will remove all returned files upon reinstall.
+        return tuple()
+    <BLANKLINE>
+        def update(self):
+            """Updater"""
+            pass
+
+Now let's try to run the recipe own tests::
+
+    >>> recipe_dir = 'plone.recipe.example'
+    >>> cd(recipe_dir)
+    >>> import sys
+    >>> python_ = sys.executable
+    >>> res = read_sh('%s setup.py test' % python_).strip().lower()
+    >>> 'doctest: readme.txt' in res
+    True
+    >>> 'ran 1 test' in res
+    True
+    >>> 'ok' in res[:-10]
+    True
+
+And the dedicated buildout `test` script (to be fixed)::
+
+    >> null = os.chdir(recipe_dir)
+    >> null = read_sh('%s bootstrap.py' % python_)
+    >> null = read_sh(os.path.join('bin', 'buildout'))
+    >> res = read_sh(os.path.join('bin', 'test'))
+    >> print res
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/silva_buildout.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/silva_buildout.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/docs/silva_buildout.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+==============
+plone template
+==============
+
+Use paster::
+
+    >>> paster('create -t silva_buildout buildout --no-interactive')
+    paster create -t silva_buildout buildout --no-interactive
+    ...
+
+Let's check the content::
+
+    >>> package_dir = 'buildout'
+    >>> ls(package_dir)
+    README.txt
+    bootstrap.py
+    buildout.cfg
+    products
+    src
+    var

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/hosting.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/hosting.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/hosting.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,203 @@
+import errno
+import os
+import socket
+import subprocess
+import sys
+import copy
+
+from paste.script import templates
+from zopeskel.base import BadCommand
+from zopeskel.base import BaseTemplate, EASY, EXPERT
+from zopeskel.vars import var, IntVar, BooleanVar, StringVar
+from zopeskel import abstract_buildout
+
+plone25s = {
+        "2.5.5": "https://launchpad.net/plone/2.5/2.5.5/+download/Plone-2.5.5.tar.gz",
+        "2.5.4": "https://launchpad.net/plone/2.5/2.5.4/+download/Plone-2.5.4-2.tar.gz",
+        "2.5.3": "https://launchpad.net/plone/2.5/2.5.3/+download/Plone-2.5.3-final.tar.gz",
+        "2.5.2": "http://plone.googlecode.com/files/Plone-2.5.2-1.tar.gz",
+        "2.5.1": "http://heanet.dl.sourceforge.net/sourceforge/plone/Plone-2.5.1-final.tar.gz",
+        "2.5"  : "http://heanet.dl.sourceforge.net/sourceforge/plone/Plone-2.5.tar.gz",
+        }
+
+class StandardHosting(abstract_buildout.AbstractBuildout):
+    _template_dir = "templates/plone_hosting"
+    use_cheetah = True
+    summary = "Plone hosting: buildout with ZEO and Plone versions below 3.2"
+    required_templates = []
+    help = """
+This template helps you to create an entire zope hosting setup, including
+ZEO and a single Zope client instance.  If you desire, it can also install
+and set up the Varnish Caching/Proxy Server.    
+
+Please Note:
+Due to changes in the packaging of Plone, this template is not suitable
+for versions of Plone beyond 3.1.7.  If you are trying to use a later 
+version of plone, you will need to edit the buildout resulting from this
+template in order to have it work correctly.  Information related to these
+issues may be found here:
+
+http://plone.org/documentation/kb/repair-a-plone-3.1-buildout
+
+and here:
+
+http://plone.org/products/zopeskel/issues/25
+"""
+
+    vars = copy.deepcopy(abstract_buildout.AbstractBuildout.vars);
+    vars = [
+
+        abstract_buildout.VAR_ZOPE_USER,
+        abstract_buildout.VAR_ZOPE_PASSWD, 
+
+        IntVar(
+            "base_port", 
+            title="Base Port #",
+            description="# to use as base for Zope/ZEO/proxy ports",
+            modes=(EASY, EXPERT),
+            page="Main",
+            default=8000,
+            help="""
+For standardization, rather than selecting ports for Zope, ZEO, and
+a proxy individually, these are tied together numerically.
+
+ZEO port = Base + 0 | Proxy port = Base + 1 | HTTP port = Base + 10
+
+If the ports specified by any of these numbers are already in use or
+otherwise unavailable, this template will inform you of the problem and
+exit with an error.  If this happens, please try another number for
+'Base Port #'
+""",
+            ),
+            
+        BooleanVar(
+            "proxy",
+            title="Install proxy server?",
+            description="Should a proxy server be installed?",
+            default=False,
+            help=""" 
+If you ask for a proxy server to be installed, this template will include
+the Varnish Caching/Proxy server.  If you wish to use a different proxy
+server, please answer False and install your own.  
+""",
+            ),
+
+        StringVar(
+            "plone",
+            title="Plone Version",
+            description="Version to install (2.5, 2.5.1, 3.0, 3.0.1, etc)",
+            default="3.1.7",
+            help="""
+You can use this template to install any version of Plone from 2.5 on. 
+Versions of Plone more recent than 3.1.7 will require some editing of the
+generated configuration files.  Please see the long description of this
+template (run 'zopskel --list') for more details.  In general it is 
+advisable to use the most recent version of Plone.  You can find a list of 
+stable Plone releases at 
+
+http://plone.org/products/plone/releases/
+
+""",
+            ),
+
+        BooleanVar(
+            "buildout",
+            title="Run Buildout?",
+            description="Should bin/buildout command be executed?",
+            default=True,
+            help="""
+Would you like this template to automatically run the buildut command as soon
+as it finishes creating the required files?  Please note that if you've chosen
+to build a version of Plone more recent than 3.1.7 running buildout will fail
+unless you make changes to the generated configuration files.  Please see the
+long description of this package (run 'zopeskel --list') for more details.
+
+If you intend on adding any specific third-party products or modifying the
+buildout in any way, you should answer 'False'.  Then make your modifications
+and run `python bootstrap.py` followed by `bin/buildout`.
+""",
+            ),
+
+            ]
+
+    def _buildout(self, output_dir):
+        olddir=os.getcwd()
+        try:
+            os.chdir(output_dir)
+            print "Bootstrapping the buildout"
+            subprocess.call([sys.executable, "bootstrap.py"])
+            print "Configuring the buildout"
+            subprocess.call(["bin/buildout", "-n"])
+        finally:
+            os.chdir(olddir)
+
+    def _checkPortAvailable(self, port):
+        s=socket.socket()
+        try:
+            s.connect(("127.0.0.1", port))
+        except socket.error, e:
+            s.close()
+
+            if e.args[0]==errno.ECONNREFUSED:
+                return 
+
+            raise BadCommand("Error checking port availability: %s" % e.args[1])
+
+        s.close()
+        raise BadCommand("Port %s is already in use" % port)
+
+
+    def check_vars(self, vars, cmd):
+        result=super(StandardHosting, self).check_vars(vars, cmd)
+
+        base_port=result["base_port"]
+        result["zeo_port"]=base_port
+        result["proxy_port"]=base_port+1
+        result["http_port"]=base_port+10
+
+        self._checkPortAvailable(result["zeo_port"])
+        self._checkPortAvailable(result["http_port"])
+        if result["proxy"]:
+            self._checkPortAvailable(result["proxy_port"])
+
+        if vars["plone"] not in plone25s and not vars["plone"].startswith("3."):
+            raise BadCommand("Unknown plone version: %s" % vars["plone"])
+
+        return result
+
+    def pre(self, command, output_dir, vars):
+        vars["output_dir"]=os.path.abspath(output_dir)
+        plone=vars["plone"]
+        if plone.startswith("3."):
+            vars["plone_recipe"]="plone.recipe.plone"
+            vars["plone_recipe_version"]=plone
+        else:
+            vars["plone_recipe"]="plone.recipe.plone25install"
+            vars["plone_url"]=plone25s[plone]
+        super(StandardHosting, self).pre(command, output_dir, vars)
+
+    def show_summary(self, vars):
+        print
+        print "Finished creation of standard hosting buildout."
+        print
+        print "Configuration summary:"
+        print "  Plone     : %s" % vars["plone"]
+        print
+        print "  HTTP port : %s" % vars["http_port"]
+        print "  ZEO port  : %s" % vars["zeo_port"]
+        if vars["proxy"]:
+            print "  Proxy port: %s" % vars["proxy_port"]
+        else:
+            print "  Proxy port: disabled"
+        print
+        print "  Zope admin user    :  %s" % vars["zope_user"]
+        print "  Zope admin password:  %s" % vars["zope_password"]
+
+
+    def post(self, command, output_dir, vars):
+        output_dir=vars["output_dir"]
+        if vars["buildout"]:
+            self._buildout(output_dir)
+        if not vars.get("hide_summary", False):
+            self.show_summary(vars)
+        super(StandardHosting, self).post(command, output_dir, vars)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/interfaces.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/interfaces.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/interfaces.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,55 @@
+class IVar:
+    """Variables in a ZopeSkel template.
+    """
+
+    # actual variable name, eg "description"
+    name = ""    
+
+    # human-facing variable name, eg "Product Description"
+    title = ""     
+    
+    # Short, 1-sentence description
+    # e.g., "Short description of this product."
+    description = ""
+
+    # Longer, potentially multi-paragraph help for users
+    # to explain this option
+    #
+    # e.g., "Products in Plone have a description that is used for ..."
+    help = ""
+
+    # Default value
+    default = None
+
+    # Should Echo   # wtf? is this used?
+    should_echo = True
+
+    # Modes that question should appear in
+    # 'easy', 'intermediate', 'advanced'
+    modes = ()
+
+    # Widget hint?
+    # XXX Todo
+    # strawman: ('text','multitext','tf','int')
+
+    def full_description():
+        """Returns variable name and description."""
+
+    def print_vars():
+        """ wtf? """
+
+    def validate(value):
+        """Check validity of entered value; exception on error.
+
+        Check validity of entered data and raise exception if
+        value is invalid.
+
+        If this value is valid, this method will return a
+        normalized version of it (eg, "yes" -> True, for boolean
+        questions).
+        """
+
+
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/kss_plugin.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/kss_plugin.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/kss_plugin.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,25 @@
+# -*- coding: utf-8 -*-
+import copy
+
+from zopeskel.base import get_var
+from zopeskel.base import var
+from zopeskel import abstract_zope
+
+
+class KssPlugin(abstract_zope.AbstractNestedZope):
+    _template_dir = 'templates/kss_plugin'
+    summary = "A project for a KSS plugin"
+    ndots = 2
+    help = """
+This creates a project for a KSS plugins ('Kinetic Style Sheets', a 
+Plone 3 framwork for JavaScript/AJAX).
+"""
+    category = "Plone Development"
+
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_zope.AbstractNestedZope.vars)
+    get_var(vars, 'namespace_package').default = 'kss'
+    get_var(vars, 'namespace_package2').default = 'plugin'
+    get_var(vars, 'keywords').default = 'kss plugin'

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,354 @@
+.. contents::
+
+ZopeSkel with local commands
+============================
+
+ZopeSkel is a great tool for generating plone projects structure from paste
+templates. You can install it with::
+
+  $ easy_install \
+  http://svn.plone.org/svn/collective/ZopeSkel/trunk#egg=ZopeSkel-dev
+
+You can list the available templates::
+
+  $ paster create --list-templates
+  Available templates:
+    archetype:          A Plone project that uses Archetypes
+    asic_namespace:    A project with a namespace package
+    basic_package:      A basic setuptools-enabled package
+    basic_zope:         A Zope project
+    nested_namespace:   A project with two nested namespaces.
+    paste_deploy:       A web application deployed through paste.deploy
+    plone:              A Plone project
+    plone2.5_buildout:  A buildout for Plone 2.5 projects
+    plone2.5_theme:     A Theme for Plone 2.5
+    plone2_theme:       A Theme Product for Plone 2.1 &amp; Plone 2.5
+    plone3_buildout:    A buildout for Plone 3 projects
+    plone3_portlet:     A Plone 3 portlet
+    plone3_theme:       A Theme for Plone 3.0
+    plone_app:          A Plone App project
+
+You can start a new project::
+
+  $ paster create -t archetype myproject
+
+You have to answer many questions and in the end you will get an archetype
+based skeleton to start your project.
+
+Now what will you do to add a new plone content type, Zope 3 utility, ...etc ?
+You have to create the new files by hand and copy/paste code from other
+projects. This is not the best approach to the problem. Martin Aspeli comes
+with the idea of implementing a paster local commands/templates so one can
+just add plone content types by running paster local commands inside
+the project directory.
+
+zopeskel.localcommands is one implementation of such idea.
+
+
+How to use zopeskel.localcommands
+=================================
+
+List the available paster commands::
+
+  $ paster --help
+  ...
+  Commands:
+    create       Create the file layout for a Python distribution
+    help         Display help
+    make-config  Install a package and create a fresh config file/directory
+    points       Show information about entry points
+    serve        Serve the described application
+    setup-app    Setup an application, given a config file
+
+Now create an archetype project as described above, cd to the project folder
+and check the available commands::
+
+  $ cd myproject
+  myproject$ paster --help
+  ...
+  Commands:
+    create       Create the file layout for a Python distribution
+    grep         Search project for symbol
+    help         Display help
+    make-config  Install a package and create a fresh config file/directory
+    points       Show information about entry points
+    serve        Serve the described application
+    setup-app    Setup an application, given a config file
+
+  ZopeSkel local commands:
+    addcontent   Add plone content types to your project
+
+You get a new section called ``ZopeSkel local commands`` with one command
+called ``addcontent``. This new section is only available if paster detects
+that your project is ``addcontent`` aware (more about this later) .
+
+To see the list of available templates for a zopeskel template, create
+a project based on that template and run ``paster addcontent -l``::
+
+  $ paster create -t archetype myproject
+  $ cd myproject
+  myproject$ paster addcontent -l
+  Available templates:
+      atschema:     A handy AT schema builder
+      contenttype:  A content type skeleton
+      form:         A form skeleton
+      formfields:   Schema fields for a form
+      i18nlocale:   An i18n locale directory structure
+      portlet:      A Plone 3 portlet
+      view:         A browser view skeleton
+      zcmlmeta:     A ZCML meta directive skeleton
+
+You get only the templates related to the type of your project. If you want
+to see all templates even those that are not related to the type of your
+project::
+
+  myproject$ paster addcontent -a
+  Available templates:
+    N anonymous_user_factory_plugin:  A Plone PAS AnonymousUserFactory Plugin
+      atschema:                       A handy AT schema builder
+    N authentication_plugin:          A Plone PAS Authentication Plugin
+    N challenge_plugin:               A Plone PAS Challenge Plugin
+      contenttype:                    A content type skeleton
+    N credentials_reset_plugin:       A Plone PAS CredentialsReset Plugin
+    N extraction_plugin:              A Plone PAS Extraction Plugin
+      form:                           A form skeleton
+      formfields:                     Schema fields for a form
+    N group_enumeration_plugin:       A Plone PAS GroupEnumeration Plugin
+    N groups_plugin:                  A Plone PAS Groups Plugin
+      i18nlocale:                     An i18n locale directory structure
+      portlet:                        A Plone 3 portlet
+    N properties_plugin:              A Plone PAS Properties Plugin
+    N role_assigner_plugin:           A Plone PAS RoleAssigner Plugin
+    N role_enumeration_plugin:        A Plone PAS RoleEnumeration Plugin
+    N roles_plugin:                   A Plone PAS Roles Plugin
+    N update_plugin:                  A Plone PAS Update Plugin
+    N user_adder_plugin:              A Plone PAS UserAdder Plugin
+    N user_enumeration_plugin:        A Plone PAS UserEnumeration Plugin
+    N user_factory_plugin:            A Plone PAS UserFactory Plugin
+    N validation_plugin:              A Plone PAS Validation Plugin
+      view:                           A browser view skeleton
+      zcmlmeta:                       A ZCML meta directive skeleton
+
+``N`` means: not related to the type of your project.
+
+To add a portlet to your project, run the following command from anywhere
+inside your project (you don't need to be in the project's root folder)::
+
+  myproject$ paster addcontent portlet
+  Enter portlet_name (Portlet name (human readable)) ['Example portlet']: My Portlet
+  Enter portlet_type_name (Portlet type name (should not contain spaces)) ['ExamplePortlet']: MyPortlet
+  Enter description (Portlet description) )['']: My Portlet
+    Recursing into portlets
+      Copying +portlet_filename+.pt_tmpl to /home/mustapha/Projects/pylonsenv/test/plone/example/portlets/myportlet.pt
+      Copying +portlet_filename+.py_tmpl to /home/mustapha/Projects/pylonsenv/test/plone/example/portlets/myportlet.py
+    Recursing into profiles
+      Recursing into default
+    Recursing into tests
+      Copying +portlet_filename+_base.py_tmpl to /home/mustapha/Projects/pylonsenv/test/plone/example/tests/myportlet_base.py
+      Copying test_+portlet_filename+.py_tmpl to /home/mustapha/Projects/pylonsenv/test/plone/example/tests/test_myportlet.py
+
+You get new files and if you check the ``configure.zcml`` in the portlets
+folder and the ``portlet.xml`` in the profiles/default folder, you will see
+that they are updated too.
+
+
+How to add new templates ?
+==========================
+
+The python part is very similar to what you know from ZopeSkel. The only
+difference is that your template class must inherit from
+``ZopeSkelLocalTemplate``.
+
+The template structure on the file system is the same as what you know from
+ZopeSkel with one difference: if your project has a file with the same name
+as a template file or the template filename ends with ``_insert``,
+the ``addcontent`` command will operate in insert-mode.
+
+To make things easy, let's take Martin's plone 3 portlet template and
+transform it to ``zopeskel.localcommands`` template so you can add as many
+portlets as you want to your project. Here is the files and the structure
+we use::
+
+  portlets/
+           +portlet_filename+.pt_tmpl
+           +portlet_filename+.py_tmpl
+           configure.zcml_insert
+  profiles/
+          default/
+                  portlets.xml_insert
+  tests/
+        base_+portlet_filename+.py_tmpl
+        test_+portlet_filename+portlet.py_tmpl
+
+The files that end with ``_tmpl`` will be handled as normal ZopeSkel templates.
+But the new thing here is the files that end with ``_insert``.
+The content of these files will be inserted in the correspondent files of
+the destination project. As example here is the content of the file
+``portlet.xml_insert``::
+
+    #<?xml version="1.0"?>
+    #  <!-- This file is used to register new types of portlets. It can also
+    #       be used to register completely new column types. See CMFPlone's
+    #       version of this file for more information.
+    #  -->
+    #  <portlets>
+    #    <!-- -*- extra stuff goes here -*- -->
+
+    <portlet
+      addview="${dotted_name}.${portlet_type_name}"
+      title="${portlet_name}"
+      description="${description}"
+    />
+
+    #</portlets>
+
+Here, some notes are needed:
+
+1. If your project contains a file named ``profile/default/portlets.xml``,
+    only the lines not starting with ``#`` will be inserted
+
+2. If your project doesn't contain the file ``profile/default/portlets.xml``,
+   the ``#``'s in the beginning of lines will be removed and a
+   ``profile/default/portlets.xml`` file will be created with the hole
+   content.
+   So it is a good idea when creating a new local template to think
+   about how the file will look like if it has to be created from scratch.
+   Look at the zcmlmeta template as example.
+
+Now, if you are asking how ``zopeskel.localcommands`` knows where (in the
+destination file) to insert the content of the source file, keep reading.
+
+
+NOTE:
+-----
+
+The '_insert' in the end of the name of the template file is required for .py
+files and optional for other kind of files. For zopeskel.localcommands there is
+no difference between `configure.zcml_insert` and `configure.zcml`. Both will be
+treated in insert-mode. In the case of .py files if you don't add '_insert' in
+the end of their name, setuptools will fail with 'SyntaxError' when installing
+ZopeSkel. That's normal because of the template variables in the file.
+For readability I recommand using the '_insert' syntax in all cases.
+
+Now, take a look to the python part. Here is the Portlet class::
+
+  from zopeskel import var
+  from zopeskel.localcommands import ZopeSkelLocalTemplate
+
+  class Portlet(ZopeSkelLocalTemplate):
+      """
+      A plone 3 portlet skeleton
+      """
+      _template_dir = 'templates/portlet'
+      summary = "A Plone 3 portlet"
+      use_cheetah = True
+      parent_templates = ['archetype']
+
+      vars = []
+      vars.append(var('portlet_name',
+                      'Portlet name (human readable)',
+                      default="Example portlet"))
+
+      vars.append(var('portlet_type_name',
+                      'Portlet type name (should not contain spaces)',
+                      default="ExamplePortlet"))
+
+      vars.append(var('description',
+                      'Portlet description',
+                      default=""))
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['portlet_filename'] = vars['portlet_type_name'].lower()
+
+        vars['dotted_name'] = "%s.portlets" % vars['package_dotted_name']
+
+Notes:
+
+1. Your template class has to inherit from ``ZopeSkelLocalTemplate``
+
+2. You template class may define a ``parent_templates`` attribute with
+   the list of zopeskel templates that can use this sub-template. This
+   attribute will be used for selection when you run ``addcontent -l``
+   or ``addcontent -a``
+
+3. You get the package_namespace, package_namespace2, package and
+   package_dotted_name of the parent package for free in the vars argument
+   of the "pre" method.
+
+4. The ZopeSkelLocalTemplate class defines an attribute named ``marker_name``
+   like this::
+
+     marker_name = "extra stuff goes here"
+
+   Your can override it in your template class if you want. The purpose of this
+   marker_name is to tell ``addcontent`` command where to insert the content if
+   it has to insert something in a file. The correspondent file must include
+   a line containing ``-*- marker_name -*-`` in our case::
+
+     -*- extra stuff goes here -*-
+
+   if you look in portlet.xml of your project you will find a line containing::
+
+     <!-- -*- extra stuff goes here -*- -->
+
+   If you want to know more about marker_name look at insert_into_file method
+   of paste.script.command.Command.
+
+OK, now we have the file system structure and the template class. We need just
+one more thing: add an egg entry point for our template class to make it
+available for the ``addcontent`` command. As I said before it is very similar
+to how you add a normal ZopeSkel template. The difference is that for normal
+ZopeSkel templates the entry point is added under
+``[paste.paste_create_template]`` section, but ``zopeskel.localcommands``
+adds a new kind of entry points named ``[zopeskel.zopeskel_sub_template]``
+and our templates have to be added under that section. If you look in the
+setup.py file of ZopeSkel to the entry_points argument, you will find::
+
+    [zopeskel.zopeskel_sub_template]
+    portlet = zopeskel.localcommands.plone:Portlet
+
+
+Enable ``addcontent`` in other ZopeSkel templates
+-------------------------------------------------
+
+To enable ``addcontent`` command in your current project add a line with
+``ZopeSkel`` to your ``paster_plugins.txt`` file of your egg-info directory
+and edit your setup.cfg file and add a new section called ``zopeskel`` with
+a ``template`` option containing the name of the template you used to generate
+your current projet::
+
+    [zopeskel]
+    template = archetype
+
+For the moment the ``addcontent`` command is only enabled for the
+archetype, plone and plone_pas templates. You can enable
+``addcontent`` command for other ZopeSkel templates by addinng a
+``use_local_commands`` attribute to the template class and set it to
+'True'::
+
+    use_local_commands = True
+
+Forthermore, you need to make sure the ZopeSkel template's name is in
+the ``parent_templates`` list of the command(s) you went to enable. To
+enable the portlet template for the plone template::
+
+  from zopeskel import var
+  from zopeskel.localcommands import ZopeSkelLocalTemplate
+
+  class Portlet(ZopeSkelLocalTemplate):
+      """
+      A plone 3 portlet skeleton
+      """
+      ...
+      parent_templates = ['archetype', 'plone']
+      ...
+
+
+/Mustapha
+url: http://www.mustap.com
+email: mustap_at_gamail_com

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,399 @@
+"""
+ ZopeSkel local command/template. Most of the code is a copy/paste from
+ paste.script module
+"""
+
+import os
+import subprocess
+import ConfigParser
+import pkg_resources
+from paste.script import command, pluginlib
+from paste.script import templates
+from paste.script import copydir
+
+
+class ZopeSkelLocalCommand(command.Command):
+    """paster command to add content skeleton to plone project"""
+
+    max_args = 2
+    usage = "[template name]"
+    summary = "Adds plone content types to your project"
+    group_name = "ZopeSkel local commands"
+
+    parser = command.Command.standard_parser(verbose=True)
+    parser.add_option('-l', '--list',
+                      action='store_true',
+                      dest='listcontents',
+                      help="List available templates for the current project")
+
+    parser.add_option('-a', '--list-all',
+                      action='store_true',
+                      dest='listallcontents',
+                      help="List all templates regardless of the current project")
+
+    parser.add_option('-q', '--no-interactive',
+                      action="count",
+                      dest="no_interactive",
+                      default=0)    
+
+    template_vars = {}
+    
+    def command(self):
+        """
+        command method
+        """
+        self.interactive = 1
+        options, args = self.options, self.args
+        
+        if options.listcontents:
+            self._list_sub_templates()
+            return
+
+        if options.listallcontents:
+            self._list_sub_templates(show_all=True)
+            return
+
+        if options.no_interactive:
+            self.interactive = False
+
+        if len(args) < 1:
+            print "\n\tError: Need a template name\n"
+            return
+
+        (self.template_vars['namespace_package'],
+         self.template_vars['namespace_package2'],
+         self.template_vars['package']) = self.get_parent_namespace_packages()
+        
+        dest_dir = self.dest_dir()
+        
+        templates = []
+        self._extend_templates(templates, args[0])
+
+        templates = [tmpl for name, tmpl in templates]
+        for tmpl in templates[::-1]:
+            self.template_vars = tmpl.check_vars(self.template_vars, self)
+
+        for tmpl in templates[::-1]:
+            if self.verbose:
+                print 'Creating template %s' % tmpl.name
+            tmpl.run(self, dest_dir, self.template_vars)
+        
+    
+    def dest_dir(self):
+        dest_dir = os.path.join(
+                   os.path.dirname(
+                       pluginlib.find_egg_info_dir(os.getcwd())),
+                                   self.template_vars['namespace_package'],
+                                   self.template_vars['namespace_package2'],
+                                   self.template_vars['package'])
+        return dest_dir
+    
+    def get_parent_namespace_packages(self):
+        """
+        return the project namespaces and package name.
+        This method can be a function
+        """
+        egg_info = pluginlib.find_egg_info_dir(os.getcwd())
+
+        hfile = open(os.path.join(egg_info, 'namespace_packages.txt'))
+        packages = [l.strip() for l in hfile.readlines()
+                    if l.strip() and not l.strip().startswith('#')]
+        hfile.close()
+
+        packages.sort(lambda x, y: -cmp(len(x), len(y)))
+        packages = packages[0].split('.')
+
+        namespace_package = packages[0]
+        namespace_package2 = ''
+        if len(packages) == 2:
+            namespace_package2 = packages[1]
+        ( dirpath, dirnames, filenames) = os.walk(os.path.join(
+                                            os.path.dirname(egg_info),
+                                                    namespace_package,
+                                                    namespace_package2)).next()
+        # Get the package dir because we usually want to issue the 
+        # localcommand in the package dir. 
+        package = os.path.basename(os.path.abspath(os.path.curdir))
+
+        # If the package dir is not in the list of inner_packages,
+        # then:
+        #    if there is only one package in the list, we take it
+        #    else ask the user to pick a package from the list
+        inner_packages = [d for d in dirnames if d != '.svn']
+        if package not in inner_packages:
+            package = inner_packages[0]
+            if len(inner_packages) > 1:
+                package = self.challenge('Please choose one package to inject content into %s' % inner_packages)
+
+        return namespace_package, namespace_package2, package
+
+    def _list_sub_templates(self, show_all=False):
+        """
+        lists available templates
+        """
+        templates = []
+        parent_template = None
+
+        egg_info_dir = pluginlib.find_egg_info_dir(os.getcwd())
+        setup_cfg = os.path.join(os.path.dirname(egg_info_dir), 'setup.cfg')
+
+        parent_template = None
+        if os.path.exists(setup_cfg):
+            parser = ConfigParser.ConfigParser()
+            parser.read(setup_cfg)
+            try:
+                parent_template = parser.get('zopeskel', 'template') or None
+            except:
+                pass
+
+        for entry in self._all_entry_points():
+            try:
+                entry_point = entry.load()
+                t = entry_point(entry.name)
+                if show_all or \
+                   parent_template is None or \
+                   parent_template in t.parent_templates:
+                    templates.append(t)
+            except Exception, e:
+                # We will not be stopped!
+                print 'Warning: could not load entry point %s (%s: %s)' % (
+                    entry.name, e.__class__.__name__, e)
+
+        print 'Available templates:'
+        if not templates:
+            print '  No template'
+            return
+
+        max_name = max([len(t.name) for t in templates])
+        templates.sort(lambda a, b: cmp(a.name, b.name))
+ 
+        for template in templates:
+            _marker = " "
+            if not template.parent_templates:
+                _marker = '?'
+            elif parent_template not in template.parent_templates:
+                _marker = 'N'
+
+            # @@: Wrap description
+            print '  %s %s:%s  %s' % (
+                _marker,
+                template.name,
+                ' '*(max_name-len(template.name)),
+                template.summary)
+
+    def _all_entry_points(self):
+        """
+        Return all entry points under zopeskel_sub_templates
+        """
+        if not hasattr(self, '_entry_points'):
+            self._entry_points = list(pkg_resources.iter_entry_points(
+            'zopeskel.zopeskel_sub_template'))
+        return self._entry_points
+
+    def _extend_templates(self, templates, tmpl_name):
+        """
+        Return ...
+        """
+        if '#' in tmpl_name:
+            dist_name, tmpl_name = tmpl_name.split('#', 1)
+        else:
+            dist_name, tmpl_name = None, tmpl_name
+        if dist_name is None:
+            for entry in self._all_entry_points():
+                if entry.name == tmpl_name:
+                    tmpl = entry.load()(entry.name)
+                    dist_name = entry.dist.project_name
+                    break
+            else:
+                raise LookupError(
+                    'Template by name %r not found' % tmpl_name)
+        else:
+            dist = pkg_resources.get_distribution(dist_name)
+            entry = dist.get_entry_info(
+                'paste.paster_create_template', tmpl_name)
+            tmpl = entry.load()(entry.name)
+        full_name = '%s#%s' % (dist_name, tmpl_name)
+        for item_full_name, in templates:
+            if item_full_name == full_name:
+                # Already loaded
+                return
+        for req_name in tmpl.required_templates:
+            self._extend_templates(templates, req_name)
+        templates.append((full_name, tmpl))
+
+
+class ZopeSkelLocalTemplate(templates.Template):
+    """
+    Base template class
+    """
+
+    marker_name = "extra stuff goes here"
+    #list of templates this subtemplate is related to
+    parent_templates = []
+
+    def run(self, command, output_dir, vars):
+        """
+        the run method
+        """
+        (vars['namespace_package'],
+         vars['namespace_package2'],
+         vars['package']) = command.get_parent_namespace_packages()
+
+        if vars['namespace_package2']:
+            vars['package_dotted_name'] = "%s.%s.%s" % \
+                (vars['namespace_package'],
+                vars['namespace_package2'],
+                vars['package'])
+        else:
+            vars['package_dotted_name'] = "%s.%s" % \
+                (vars['namespace_package'],
+                 vars['package'])
+
+        self.pre(command, output_dir, vars)
+        self.write_files(command, output_dir, vars)
+        self.post(command, output_dir, vars)
+
+    def write_files(self, command, output_dir, vars):
+        """
+        method
+        """
+        self._command = command
+        template_dir = self.template_dir()
+        if not os.path.exists(output_dir):
+            print "Creating directory %s" % output_dir
+            if not command.simulate:
+                # Don't let copydir create this top-level directory,
+                # since copydir will svn add it sometimes:
+                os.makedirs(output_dir)
+        self.copy_dir(template_dir, output_dir,
+                         vars,
+                         verbosity=1,
+                         simulate=0,
+                         interactive=1,
+                         overwrite=0,
+                         indent=1,
+                         use_cheetah=self.use_cheetah,
+                         template_renderer=self.template_renderer)
+
+    def copy_dir(self, source, dest, vars, verbosity, simulate, indent=0,
+                 use_cheetah=False, sub_vars=True, interactive=False,
+                 svn_add=True, overwrite=True, template_renderer=None):
+        """
+        This method is a modified copie of paste.script.copy_dir
+        """
+        # This allows you to use a leading +dot+ in filenames which would
+        # otherwise be skipped because leading dots make the file hidden:
+        vars.setdefault('dot', '.')
+        vars.setdefault('plus', '+')
+        names = os.listdir(source)
+        names.sort()
+        pad = ' '*(indent*2)
+        if not os.path.exists(dest):
+            if verbosity >= 1:
+                print '%sCreating %s/' % (pad, dest)
+            if not simulate:
+                copydir.svn_makedirs(dest, svn_add=svn_add, verbosity=verbosity,
+                             pad=pad)
+        elif verbosity >= 2:
+            print '%sDirectory %s exists' % (pad, dest)
+        for name in names:
+            full = os.path.join(source, name)
+            reason = copydir.should_skip_file(name)
+            if reason:
+                if verbosity >= 2:
+                    reason = pad + reason % {'filename': full}
+                    print reason
+                continue
+
+            if sub_vars:
+                dest_full = os.path.join(
+                                  dest, copydir.substitute_filename(name, vars))
+            sub_file = False
+            if dest_full.endswith('_tmpl'):
+                dest_full = dest_full[:-5]
+                sub_file = sub_vars
+            if os.path.isdir(full):
+                if verbosity:
+                    print '%sRecursing into %s' % (pad, os.path.basename(full))
+                self.copy_dir(full, dest_full, vars, verbosity, simulate,
+                         indent=indent+1, use_cheetah=use_cheetah,
+                         sub_vars=sub_vars, interactive=interactive,
+                         svn_add=svn_add, template_renderer=template_renderer)
+                continue
+            f = open(full, 'rb')
+            content = f.read()
+            f.close()
+            try:
+                content = copydir.substitute_content(
+                                            content,
+                                            vars, filename=full,
+                                            use_cheetah=use_cheetah,
+                                            template_renderer=template_renderer)
+            except copydir.SkipTemplate:
+                continue
+
+            if dest_full.endswith('_insert'):
+                dest_full = dest_full[:-7]
+
+            already_exists = os.path.exists(dest_full)
+            if already_exists:
+                if sub_file and verbosity:
+                    print "File '%s' already exists: skipped" % \
+                           os.path.basename(dest_full)
+                    continue
+                f = open(dest_full, 'rb')
+                old_content = f.read()
+                f.close()
+                if old_content == content:
+                    if verbosity:
+                        print '%s%s already exists (same content)' % \
+                               (pad, dest_full)
+                    continue
+
+                if verbosity:
+                    print "%sInserting from %s into %s" % \
+                                (pad, os.path.basename(full), dest_full)
+
+                if not content.endswith('\n'):
+                    content += '\n'
+                # remove lines starting with '#'
+                content = '\n'.join([l for l in content.split('\n') \
+                                     if not l.startswith('#')])
+                self._command.insert_into_file(dest_full,
+                                               self.marker_name,
+                                               content)
+                continue
+
+            if verbosity:
+                print '%sCopying %s to %s' % (pad,
+                                              os.path.basename(full),
+                                              dest_full)
+            # remove '#' from the start of lines
+            if not sub_file:
+                content = content.replace('\n#','\n')
+                if content[0] == '#': content = content[1:]
+
+            if not simulate:
+                f = open(dest_full, 'wb')
+                f.write(content)
+                f.close()
+            if svn_add and not already_exists:
+                if not os.path.exists(
+                           os.path.join(
+                               os.path.dirname(
+                                   os.path.abspath(dest_full)), '.svn')):
+                    if verbosity > 1:
+                        print '%s.svn/ does not exist; cannot add file' % pad
+                else:
+                    cmd = ['svn', 'add', dest_full]
+                    if verbosity > 1:
+                        print '%sRunning: %s' % (pad, ' '.join(cmd))
+                    if not simulate:
+                        # @@: Should
+                        proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
+                        stdout, stderr = proc.communicate()
+                        if verbosity > 1 and stdout:
+                            print 'Script output:'
+                            print stdout
+            elif svn_add and already_exists and verbosity > 1:
+                print '%sFile already exists (not doing svn add)' % pad

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/archetype.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/archetype.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/archetype.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,238 @@
+"""
+Local templates for the archetype zopeskel project
+"""
+import os
+from zopeskel.base import var
+from zopeskel.localcommands import ZopeSkelLocalTemplate
+
+from Cheetah.Template import Template as cheetah_template
+
+
+class ArchetypeSubTemplate(ZopeSkelLocalTemplate):
+    use_cheetah = True
+    parent_templates = ['archetype']
+
+
+class ContentType(ArchetypeSubTemplate):
+    """
+    A Content Type skeleton
+    """
+
+    _template_dir = 'templates/archetype/contenttype'
+    summary = "A content type skeleton"
+
+    vars = [
+        var('contenttype_name', 'Content type name ', default='Example Type'),
+        var('contenttype_description', 'Content type description ',
+            default='Description of the Example Type'),
+        var('folderish', 'True/False: Content type is Folderish ',
+            default=False),
+        var('global_allow', 'True/False: Globally addable ',
+            default=True),
+        var('allow_discussion', 'True/False: Allow discussion ',
+            default=False),
+        ]
+
+    def pre(self, command, output_dir, vars):
+
+        vars['contenttype_classname'] = vars['contenttype_name'].replace(" ", "")
+        vars['schema_name'] = vars['contenttype_classname'] + "Schema"
+        vars['content_class_filename'] = vars['contenttype_classname'].lower()
+        vars['types_xml_filename'] = vars['contenttype_name'].replace(" ", "_")
+        vars['interface_name'] = "I" + vars['contenttype_name'].replace(" ", "")
+        vars['add_permission_name'] = vars['package_dotted_name'] + ': Add ' + vars['contenttype_name']
+
+
+class ATSchemaField(ArchetypeSubTemplate):
+    """
+    A handy AT schema builder
+    """
+
+    _template_dir = 'templates/archetype/atschema'
+    summary = "A handy AT schema builder"
+    marker_name = "Your Archetypes field definitions here ..."
+
+    # mapping of ATSchema types to zope.schema types
+    typemap = {'boolean': 'Bool',
+               'computed': 'TextLine',
+               'cmfobject': 'TextLine',
+               'datetime': 'Date',
+               'file': 'Bytes',
+               'fixedpoint': 'Float',
+               'float': 'Float',
+               'image': 'Bytes',
+               'integer': 'Int',
+               'lines': 'List',
+               'reference': 'Object',
+               'string': 'TextLine',
+               'text': 'Text',
+               'unknown': 'TextLine'}
+
+    # fieldtypes-map to (widget, validator)
+    fieldtypes = {
+        'boolean': ('boolean', None),
+        'computed': ('computed', None),
+        'cmfobject': ('file', None),
+        'datetime': ('calendar', 'isValidDate'),
+        'file': ('file', 'isNonEmptyFile'),
+        'fixedpoint': ('decimal', 'isDecimal'),
+        'float': ('decimal', 'isDecimal'),
+        'image': ('image', 'isNonEmptyFile'),
+        'integer': ('integer', 'isInt'),
+        'lines': ('lines', None),
+        'reference': ('reference', None),
+        'string': ('string', None),
+        'text': ('textarea', None),
+    }
+
+    vars = [
+        var('content_class_filename',      
+            'What is the module (file)name of your content class?',           
+            default='exampletype'),
+        var('field_name',
+            'What would you like to name this field?',
+            default='newfield'),
+        var('field_type',       
+            'What kind of field should I make for you?\nSome examples: ['+','.join(fieldtypes.keys())+']\n', 
+            default='string'),            
+        var('widget_type',      
+            'What kind of widget do you want to use (example: Password)?',   
+            default='default'),
+        var('field_label',
+            'What should be the label of this field (title)?',
+            default='New Field'),
+        var('field_desc',
+            'What should be the description of this field (help text)?',
+            default='Field description'),
+        var('required',
+            'Is this field required?',
+            default='False'),
+        var('default',
+            "If you'd like a default type it here, otherwise leave it blank",
+            default=''),
+        var('validator',
+            "Enter a validator (isEmail), or None, or get a default validator for your specified field type.",
+            default='use default validator'),
+        ]
+
+    def check_vars(self, *args, **kwargs):
+        """
+        Overloading check_vars to print welcome message
+        """
+
+        print "Welcome to the ATSchema Builder. Field names/widgets can be specified in lowercase or upper case."
+        print "NOTE: No need to add 'widget' or 'field' to the names. atschema does the work for you!"
+        print "See "
+        print "    http://plone.org/documentation/manual/archetypes-developer-manual/fields/fields-reference/"
+        print "and "
+        print "    http://plone.org/documentation/manual/archetypes-developer-manual/fields/widgets-reference"
+        print "for field and widget details"
+
+        return super(ATSchemaField, self).check_vars(*args, **kwargs)
+
+    def run(self, command, output_dir, vars):
+        """
+        By-passing the base run so I can do multiple inserts
+        with different marker names
+        """
+
+        (vars['namespace_package'],
+         vars['namespace_package2'],
+         vars['package']) = command.get_parent_namespace_packages()
+
+        if vars['namespace_package2']:
+            vars['package_dotted_name'] = "%s.%s.%s" % \
+                (vars['namespace_package'],
+                vars['namespace_package2'],
+                vars['package'])
+        else:
+            vars['package_dotted_name'] = "%s.%s" % \
+                (vars['namespace_package'],
+                 vars['package'])
+        
+        vars['a_validator'] = ''
+        if vars['validator'] == 'use default validator':
+            ## take default Validator...
+            val = ATSchemaField.fieldtypes[vars['field_type'].lower()][1]
+            if val is not None:
+                vars['a_validator'] = """'%s'""" % val
+        elif vars['validator'] != 'None':    ## user providing 'aValidator'
+            vars['a_validator'] = """'%s'""" % vars['validator']
+
+        self.pre(command, output_dir, vars)
+
+        interface_insert_template = open(os.path.join(self.template_dir(), 'interfaces/+interface_name+.py_insert')).read()
+        atschema_insert_template = open(os.path.join(self.template_dir(),'content/+content_class_filename+.py_insert')).read()
+        bridges_insert_template = open(os.path.join(self.template_dir(),'content/schema_field_bridge.txt_insert')).read()
+        content_messagefactory_insert_template = open(os.path.join(self.template_dir(), 'content/messagefactory_insert.txt_insert')).read()
+        interface_additional_imports_template = open(os.path.join(self.template_dir(), 'interfaces/additional_imports.txt_insert')).read()
+
+        # insert_into_file really wants the inserted text to end with a newline
+        interface_insert = str(cheetah_template(interface_insert_template, vars))+"\n"
+        atschema_insert = str(cheetah_template(atschema_insert_template, vars))+"\n"
+        bridges_insert = str(cheetah_template(bridges_insert_template, vars))+"\n"
+        content_messagefactory_insert = str(cheetah_template(content_messagefactory_insert_template, vars))+"\n"
+        interface_additional_imports = str(cheetah_template(interface_additional_imports_template, vars))+"\n"
+
+        # self.write_files(command, output_dir, vars)
+        command.insert_into_file(os.path.join(command.dest_dir(), 'content', '%s.py' % (vars['content_class_filename'])), self.marker_name, atschema_insert)
+        command.insert_into_file(os.path.join(command.dest_dir(), 'interfaces', '%s.py' % (vars['content_class_filename'])), 'schema definition goes here', interface_insert)
+        command.insert_into_file(os.path.join(command.dest_dir(), 'content', '%s.py' % (vars['content_class_filename'])), 'Your ATSchema to Python Property Bridges Here ...', bridges_insert)
+        command.insert_into_file(os.path.join(command.dest_dir(), 'content', '%s.py' % (vars['content_class_filename'])), 'Message Factory Imported Here', content_messagefactory_insert)
+        command.insert_into_file(os.path.join(command.dest_dir(), 'interfaces', '%s.py' % (vars['content_class_filename'])), 'Additional Imports Here', interface_additional_imports)
+
+        self.post(command, output_dir, vars)
+
+
+    def pre(self, command, output_dir, vars):
+
+        file = vars['content_class_filename']
+        if file.endswith('.py'):
+            file = os.path.splitext(file)[0]
+
+        vars['field_type'] = vars['field_type'].capitalize()
+
+        if vars['widget_type'].lower() == 'default':
+            vars['widget_type'] = self.fieldtypes[vars['field_type'].lower()][0]
+        
+        vars['widget_type'] = vars['widget_type'].capitalize()
+
+        # camelcase multiword names
+        if vars['field_type'].lower() == 'fixedpoint':
+            vars['field_type'] = 'FixedPoint'
+
+        if vars['field_type'].lower() == 'datetime':
+            vars['field_type'] = 'DateTime'
+
+        if vars['field_type'].lower() == 'date':
+            vars['field_type'] = 'DateTime'
+
+        if vars['widget_type'].lower() == 'inandout':
+            vars['widget_type'] = 'InAndOut'
+
+        if vars['widget_type'].lower() == 'multiselection':
+            vars['widget_type'] = 'MultiSelection'
+
+        if vars['widget_type'].lower() == 'picklist':
+            vars['widget_type'] = 'PickList'
+
+        if vars['widget_type'].lower() == 'referencebrowser':
+            vars['widget_type'] = 'ReferenceBrowser'
+
+        if vars['widget_type'].lower() == 'textarea':
+            vars['widget_type'] = 'TextArea'
+
+        # try to get the zope.schema type, but default to TextLine if no dice
+        try:
+            vars['zopeschema_type'] = self.typemap[vars['field_type'].lower()]
+        except:
+            vars['zopeschema_type'] = self.typemap['unknown']
+
+        # if the widget is the RichWidget, set the type to 'SourceText'
+        if vars['widget_type'].lower() == 'rich':
+            vars['zopeschema_type'] = 'SourceText'
+
+        # if not vars['i18n_domain']:
+        #     vars['i18n_domain'] = vars['package_dotted_name']
+
+        vars['content_class_filename'] = file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,244 @@
+"""
+Local templates that are generically useful for every plone related project.
+"""
+from zopeskel.base import var
+from zopeskel.localcommands import ZopeSkelLocalTemplate
+
+class PloneSubTemplate(ZopeSkelLocalTemplate):
+    use_cheetah = True
+    parent_templates = ['plone', 'archetype']
+
+
+class Portlet(PloneSubTemplate):
+    """
+    A plone 3 portlet skeleton
+    """
+    _template_dir = 'templates/plone/portlet'
+    summary = "A Plone 3 portlet"
+
+    vars = [
+      var('portlet_name', 'Portlet name (human readable)',  default="Example portlet"),
+      var('portlet_type_name', 'Portlet type name (should not contain spaces)', default="ExamplePortlet"),
+      var('description', 'Portlet description', default=""),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['portlet_filename'] = vars['portlet_type_name'].lower()
+
+        vars['dotted_name'] = "%s.portlets" % vars['package_dotted_name']
+
+
+class View(PloneSubTemplate):
+    """
+    A browser view skeleton
+    """
+    _template_dir = 'templates/plone/view'
+    summary = "A browser view skeleton"
+
+    vars = [
+      var('view_name', 'Browser view name',  default="Example"),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['view_filename'] = vars['view_name'].lower().replace(' ', '')
+        vars['view_classname'] = vars['view_name'].replace(' ', '')
+
+
+class ZCMLMetaDirective(PloneSubTemplate):
+    """
+    A zcml meta directive skeleton
+    """
+    _template_dir = 'templates/plone/zcmlmeta'
+    summary = "A ZCML meta directive skeleton"
+
+    vars = [
+      var('directive_name', 'The directive name',  default="mydirective"),
+      var('directive_namespace', 'The directive namespace',  default="mynamespace"),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['directive_class_name'] = vars['directive_name'].title()
+
+
+class I18nLocale(PloneSubTemplate):
+    """
+    A skeleton for an i18n language
+    """
+    _template_dir = 'templates/plone/i18nlocales'
+    summary = "An i18n locale directory structure"
+
+    vars = [
+      var('language_code', 'The iso-code of the language'),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        # There is no default for language_code, because that makes no sense
+        # To accomodate testing, we introduce a default here.
+
+        language_iso_code = vars['language_code'].lower().strip()
+        vars['language_iso_code'] = language_iso_code and language_iso_code or 'nl'
+
+class Form(PloneSubTemplate):
+    """
+    A form skeleton
+    """
+    _template_dir = 'templates/plone/form'
+    summary = "A form skeleton"
+
+    vars = [
+        var('form_name', 'Form class name',  default="ExampleForm"),
+        var('form_label', "Form Title", default='Example Form'),
+        var('form_description', "Form Description", default=''),
+        var('form_actions', 'Comma separated list of form actions', default="Submit"),
+        var('form_invariants', 'Comma separated list of invariants', default=""), 
+        ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        splitCSV = lambda in_str: [x.strip() for x in in_str.split(",")]
+        vars['form_filename'] = vars['form_name'].lower()
+        vars['form_actions'] = splitCSV(vars['form_actions'])
+        vars['form_invariants'] = splitCSV(vars['form_invariants'].strip())
+        
+        
+class Z3cForm(PloneSubTemplate):
+    """
+    A zc3 form skeleton
+    """
+    _template_dir = 'templates/archetype/form'
+    summary = "A form skeleton"
+
+    vars = [
+      var('form_name', 'Form name',  default="Example"),
+           ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['form_filename'] = vars['form_name'].lower()
+
+class FormField(PloneSubTemplate):
+    """
+    A template to add a form field to a form. Essentially this 
+    adds a field to Zope 3 schema. 
+    """
+    _template_dir = 'templates/plone/formfield'
+    summary = "Schema field for a form"
+
+    _supported_fields = [
+        ("Bool", "Field containin a truth value."), 
+        ("Text", "Field containing unicode text."), 
+        ("TextLine", "Field containing a single line of unicode text."), 
+        ("Datetime", "Field containing a DateTime."),
+        ("Date", "Field containing a date."),
+        ("Choice", "Obect from a source or vocabulary."),
+        ("Password", "Field containing a unicode string without newlines that is a password.")
+        ]
+    _field_description = "\n".join(
+        [" "* 25 + x[0].lower() + " : " + x[1] for x in _supported_fields]
+         )
+        
+    vars = [
+        var('form_filename', "Name of the file containing the form in browser.", default="exampleform"),
+        var('field_name', "Name of the field (this should be a unique identifier).", default='examplefield'),
+        var('field_type', "Type of field. Use one of the following \n\n"+_field_description + "\n", default='textline'),
+        var('field_title', '', default='A short summary or label'),
+        var('field_description', 'A description of the field (to be displayed as a hint)', default=''),
+        var('field_required', 'Tells whether a field requires its value to exist (True/False)', default=False),
+        var('field_readonly', "If true, the field's value cannot be changed (True/False)", default=False),
+        var('field_default', 'The field default value may be None or a legal field value', default='None'),
+        var('field_missing_value', 'If a field has no assigned value, set it to this value', default=''),
+        var('field_constraint', 'Specify the name of a function to use for validation', default=''),
+        ]
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        # XXX this should be handled by _map_boolean in base.py 
+        # but this template does not inherit from BaseTemplate 
+        for var in FormField.vars:
+            if var.name in vars and (type(vars[var.name])==str) and var.default in [True, False, None]:
+                lowered = vars[var.name].lower().strip() 
+                if lowered in ['t', 'y', 'true']:
+                    vars[var.name] = True
+                elif lowered in ['f', 'n', 'false']:
+                    vars[var.name] = False
+                elif lowered == 'none': 
+                    vars[var.name] = None 
+
+        # make the field type case insensitive, if the field type is not in the list of enumerated types
+	# simple use the provided one 
+        vars['field_type'] = dict([(x[0].lower(), x) for x in self._supported_fields]).get(vars['field_type'].lower(), (vars['field_type'],))[0]
+
+
+class BrowserLayer(PloneSubTemplate):
+    """
+    A browserlayer skeleton
+    """
+    _template_dir = 'templates/plone/browserlayer'
+    summary = "A Plone browserlayer"
+
+    vars = [
+        var('interface_name', 'Interface name for the browserlayer',  default="IMyPackageBrowserLayer"),
+        var('layer_name', "Browser layer name", default='MyPackage'), 
+        ]
+
+    def check_vars(self, vars, cmd):
+        """
+        Overloading check_vars to print welcome message and provide sensitive default values
+        """
+
+        print "A BrowserLayer is generally used in packages to be installed in a Plone Site."
+        print "If you didn't choose Register Profile option when creating this package"
+        print "you should probably add a <genericsetup:registerProfile /> directive in"
+        print "the main configure.zcml.\n"
+        package_dotted_name = [vars['namespace_package']]
+        if 'namespace_package2' in vars:
+            package_dotted_name.append(vars['namespace_package2'])
+        package_dotted_name.append(vars['package'])
+        
+        layer_name = ''.join([x.capitalize() for x in package_dotted_name])
+        self.vars[1].default = layer_name
+        self.vars[0].default = 'I%sLayer' % (layer_name)
+
+        return super(BrowserLayer, self).check_vars(vars, cmd)
+
+
+    def pre(self, command, output_dir, vars):
+        """
+        you can use package_namespace, package_namespace2, package
+        and package_dotted_name of the parent package here. you get them
+        for free in the vars argument
+        """
+        vars['interface_filename'] = vars['layer_name'].lower() + 'layer'
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone_pas.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone_pas.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/plone_pas.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,140 @@
+"""
+Local templates for the plone PAS zopeskel project
+"""
+from zopeskel.localcommands import ZopeSkelLocalTemplate
+
+class PlonePasSubTemplate(ZopeSkelLocalTemplate):
+    use_cheetah = True
+    marker_name = 'implemented plugins'
+    parent_templates = ['plone_pas']
+
+
+class ExtractionPlugin(PlonePasSubTemplate):
+    """
+    A plone pas extraction plugin
+    """
+    _template_dir = 'templates/plone_pas/extraction'
+    summary = "A Plone PAS Extraction Plugin"
+
+
+class AuthenticationPlugin(PlonePasSubTemplate):
+    """
+    A plone pas authentication plugin
+    """
+    _template_dir = 'templates/plone_pas/authentication'
+    summary = "A Plone PAS Authentication Plugin"
+
+
+class ChallengePlugin(PlonePasSubTemplate):
+    """
+    A plone pas challenge plugin
+    """
+    _template_dir = 'templates/plone_pas/challenge'
+    summary = "A Plone PAS Challenge Plugin"
+
+
+class CredentialsResetPlugin(PlonePasSubTemplate):
+    """
+    A plone pas CredentialsReset plugin
+    """
+    _template_dir = 'templates/plone_pas/credentials_reset'
+    summary = "A Plone PAS CredentialsReset Plugin"
+
+
+class UserAdderPlugin(PlonePasSubTemplate):
+    """
+    A plone pas UserAdder plugin
+    """
+    _template_dir = 'templates/plone_pas/user_adder'
+    summary = "A Plone PAS UserAdder Plugin"
+
+
+class RoleAssignerPlugin(PlonePasSubTemplate):
+    """
+    A plone pas RoleAssigner plugin
+    """
+    _template_dir = 'templates/plone_pas/role_assigner'
+    summary = "A Plone PAS RoleAssigner Plugin"
+
+
+class UserFactoryPlugin(PlonePasSubTemplate):
+    """
+    A plone pas UserFactory plugin
+    """
+    _template_dir = 'templates/plone_pas/user_factory'
+    summary = "A Plone PAS UserFactory Plugin"
+
+
+class AnonymousUserFactoryPlugin(PlonePasSubTemplate):
+    """
+    A plone pas AnonymousUserFactory plugin
+    """
+    _template_dir = 'templates/plone_pas/anonymous_user_factory'
+    summary = "A Plone PAS AnonymousUserFactory Plugin"
+
+
+class PropertiesPlugin(PlonePasSubTemplate):
+    """
+    A plone pas Properties plugin
+    """
+    _template_dir = 'templates/plone_pas/properties'
+    summary = "A Plone PAS Properties Plugin"
+
+
+
+class GroupsPlugin(PlonePasSubTemplate):
+    """
+    A plone pas Groups plugin
+    """
+    _template_dir = 'templates/plone_pas/groups'
+    summary = "A Plone PAS Groups Plugin"
+
+
+class RolesPlugin(PlonePasSubTemplate):
+    """
+    A plone pas Roles plugin
+    """
+    _template_dir = 'templates/plone_pas/roles'
+    summary = "A Plone PAS Roles Plugin"
+
+
+class UpdatePlugin(PlonePasSubTemplate):
+    """
+    A plone pas Update plugin
+    """
+    _template_dir = 'templates/plone_pas/update'
+    summary = "A Plone PAS Update Plugin"
+
+
+class ValidationPlugin(PlonePasSubTemplate):
+    """
+    A plone pas Validation plugin
+    """
+    _template_dir = 'templates/plone_pas/validation'
+    summary = "A Plone PAS Validation Plugin"
+
+
+class UserEnumerationPlugin(PlonePasSubTemplate):
+    """
+    A plone pas UserEnumeration plugin
+    """
+    _template_dir = 'templates/plone_pas/user_enumeration'
+    summary = "A Plone PAS UserEnumeration Plugin"
+
+
+class GroupEnumerationPlugin(PlonePasSubTemplate):
+    """
+    A plone pas GroupEnumeration plugin
+    """
+    _template_dir = 'templates/plone_pas/group_enumeration'
+    summary = "A Plone PAS GroupEnumeration Plugin"
+
+
+class RoleEnumerationPlugin(PlonePasSubTemplate):
+    """
+    A plone pas RoleEnumeration plugin
+    """
+    _template_dir = 'templates/plone_pas/role_enumeration'
+    summary = "A Plone PAS RoleEnumeration Plugin"
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/+content_class_filename+.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/+content_class_filename+.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/+content_class_filename+.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,26 @@
+
+    atapi.${field_type}Field(
+        '${field_name}',
+        storage=atapi.AnnotationStorage(),
+        widget=atapi.${widget_type}Widget(
+            label=_(u"${field_label}"),
+            description=_(u"${field_desc}"),
+        ),
+#if str($required) == 'True'
+        required=${required},
+#end if
+#if str($default) != '' and str($field_type) != 'Computed'
+        default=_(u"${default}"),
+#end if
+#if str($field_type) == 'Reference'
+        relationship='${content_class_filename}_${field_name}',
+        allowed_types=(), # specify portal type names here ('Example Type',)
+        multiValued=False,
+#end if
+#if str($field_type) == 'Computed'
+        expression = '',
+#end if
+#if $a_validator
+        validators=($a_validator),
+#end if  
+    ),

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/messagefactory_insert.txt_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/messagefactory_insert.txt_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/messagefactory_insert.txt_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+#*
+This template is added to the main content type template, through a non-standard
+ZopeSkel method! 
+*#
+from ${package_dotted_name} import ${package}MessageFactory as _
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/schema_field_bridge.txt_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/schema_field_bridge.txt_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/content/schema_field_bridge.txt_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+    #*
+    This template is added to the main content type template, through a non-standard
+    ZopeSkel method! 
+    *#
+    #if $field_type == 'Reference'
+    ${field_name} = atapi.ATReferenceFieldProperty('${field_name}')
+    #else
+    ${field_name} = atapi.ATFieldProperty('${field_name}')
+    #end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/+interface_name+.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/+interface_name+.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/+interface_name+.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+    ${field_name} = schema.${zopeschema_type}(
+        title=_(u"${field_label}"),
+        required=${required},
+        description=_(u"${field_desc}"),
+        #if str($zopeschema_type) == 'Object'
+        schema=Interface, # specify the interface(s) of the addable types here
+        #end if
+    )
+#
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+from ${contenttype_classname} import ${interface_name}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/additional_imports.txt_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/additional_imports.txt_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/atschema/interfaces/additional_imports.txt_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+#*
+This template is added to the main content type interface template, through a 
+non-standard ZopeSkel method! 
+*#
+from zope import schema
+
+from ${package_dotted_name} import ${package}MessageFactory as _

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/README.txt_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/README.txt_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/README.txt_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,123 @@
+The $contenttype_name content type
+===============================
+
+In this section we are tesing the $contenttype_name content type by performing
+basic operations like adding, updadating and deleting $contenttype_name content
+items.
+
+Adding a new $contenttype_name content item
+--------------------------------
+
+We use the 'Add new' menu to add a new content item.
+
+    >>> browser.getLink('Add new').click()
+
+Then we select the type of item we want to add. In this case we select
+'$contenttype_name' and click the 'Add' button to get to the add form.
+
+    >>> browser.getControl('$contenttype_name').click()
+    >>> browser.getControl(name='form.button.Add').click()
+    >>> '$contenttype_name' in browser.contents
+    True
+
+Now we fill the form and submit it.
+
+    >>> browser.getControl(name='title').value = '$contenttype_name Sample'
+    >>> browser.getControl('Save').click()
+    >>> 'Changes saved' in browser.contents
+    True
+
+And we are done! We added a new '$contenttype_name' content item to the portal.
+
+Updating an existing $contenttype_name content item
+---------------------------------------
+
+Let's click on the 'edit' tab and update the object attribute values.
+
+    >>> browser.getLink('Edit').click()
+    >>> browser.getControl(name='title').value = 'New $contenttype_name Sample'
+    >>> browser.getControl('Save').click()
+
+We check that the changes were applied.
+
+    >>> 'Changes saved' in browser.contents
+    True
+    >>> 'New $contenttype_name Sample' in browser.contents
+    True
+
+Removing a/an $contenttype_name content item
+--------------------------------
+
+If we go to the home page, we can see a tab with the 'New $contenttype_name
+Sample' title in the global navigation tabs.
+
+    >>> browser.open(portal_url)
+    >>> 'New $contenttype_name Sample' in browser.contents
+    True
+
+Now we are going to delete the 'New $contenttype_name Sample' object. First we
+go to the contents tab and select the 'New $contenttype_name Sample' for
+deletion.
+
+    >>> browser.getLink('Contents').click()
+    >>> browser.getControl('New $contenttype_name Sample').click()
+
+We click on the 'Delete' button.
+
+    >>> browser.getControl('Delete').click()
+    >>> 'Item(s) deleted' in browser.contents
+    True
+
+So, if we go back to the home page, there is no longer a 'New $contenttype_name
+Sample' tab.
+
+    >>> browser.open(portal_url)
+    >>> 'New $contenttype_name Sample' in browser.contents
+    False
+
+Adding a new $contenttype_name content item as contributor
+------------------------------------------------
+
+Not only site managers are allowed to add $contenttype_name content items, but
+also site contributors.
+
+Let's logout and then login as 'contributor', a portal member that has the
+contributor role assigned.
+
+    >>> browser.getLink('Log out').click()
+    >>> browser.open(portal_url + '/login_form')
+    >>> browser.getControl(name='__ac_name').value = 'contributor'
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+    >>> browser.open(portal_url)
+
+We use the 'Add new' menu to add a new content item.
+
+    >>> browser.getLink('Add new').click()
+
+We select '$contenttype_name' and click the 'Add' button to get to the add form.
+
+    >>> browser.getControl('$contenttype_name').click()
+    >>> browser.getControl(name='form.button.Add').click()
+    >>> '$contenttype_name' in browser.contents
+    True
+
+Now we fill the form and submit it.
+
+    >>> browser.getControl(name='title').value = '$contenttype_name Sample'
+    >>> browser.getControl('Save').click()
+    >>> 'Changes saved' in browser.contents
+    True
+
+Done! We added a new $contenttype_name content item logged in as contributor.
+
+Finally, let's login back as manager.
+
+    >>> browser.getLink('Log out').click()
+    >>> browser.open(portal_url + '/login_form')
+    >>> browser.getControl(name='__ac_name').value = portal_owner
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+    >>> browser.open(portal_url)
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/config.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/config.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/config.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+    '$(contenttype_classname)': '$(add_permission_name)',

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/+content_class_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/+content_class_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/+content_class_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,67 @@
+"""Definition of the $contenttype_name content type
+"""
+
+from zope.interface import implements
+
+from Products.Archetypes import atapi
+#if str($folderish) == 'True'
+from Products.ATContentTypes.content import folder
+#else
+from Products.ATContentTypes.content import base
+#end if
+from Products.ATContentTypes.content import schemata
+
+# -*- Message Factory Imported Here -*-
+
+from ${package_dotted_name}.interfaces import ${interface_name}
+from ${package_dotted_name}.config import PROJECTNAME
+
+#if str($folderish) == 'True'
+${schema_name} = folder.ATFolderSchema.copy() + atapi.Schema((
+#else
+${schema_name} = schemata.ATContentTypeSchema.copy() + atapi.Schema((
+#end if
+
+    # -*- Your Archetypes field definitions here ... -*-
+
+))
+
+#if str($folderish) == 'True'
+# Set storage on fields copied from ATFolderSchema, making sure
+# they work well with the python bridge properties.
+#else
+# Set storage on fields copied from ATContentTypeSchema, making sure
+# they work well with the python bridge properties.
+#end if
+
+${schema_name}['title'].storage = atapi.AnnotationStorage()
+${schema_name}['description'].storage = atapi.AnnotationStorage()
+
+#if str($folderish) == 'True'
+schemata.finalizeATCTSchema(
+    ${schema_name},
+    folderish=True,
+    moveDiscussion=False
+)
+#else
+schemata.finalizeATCTSchema(${schema_name}, moveDiscussion=False)
+#end if
+
+
+#if str($folderish) == 'True'
+class ${contenttype_classname}(folder.ATFolder):
+#else
+class ${contenttype_classname}(base.ATCTContent):
+#end if
+    """${contenttype_description}"""
+    implements(${interface_name})
+
+    meta_type = "${contenttype_classname}"
+    schema = ${schema_name}
+
+    title = atapi.ATFieldProperty('title')
+    description = atapi.ATFieldProperty('description')
+
+    # -*- Your ATSchema to Python Property Bridges Here ... -*-
+
+atapi.registerType(${contenttype_classname}, PROJECTNAME)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/content/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+  <class class=".${content_class_filename}.${contenttype_classname}">
+    <require
+        permission="zope2.View"
+        interface="..interfaces.${interface_name}"
+        />
+  </class>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/+content_class_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/+content_class_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/+content_class_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+from zope.interface import Interface
+# -*- Additional Imports Here -*-
+
+
+class $(interface_name)(Interface):
+    """$(contenttype_description)"""
+
+    # -*- schema definition goes here -*-

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/interfaces/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+from ${content_class_filename} import $(interface_name)
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/factorytool.xml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/factorytool.xml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/factorytool.xml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+    <type portal_type="${contenttype_name}" />

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/rolemap.xml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/rolemap.xml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/rolemap.xml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<?xml version="1.0"?>
+#<rolemap>
+#  <permissions>
+#    <!-- -*- extra stuff goes here -*- -->
+    <permission name="$add_permission_name" acquire="False">
+      <role name="Manager" />
+      <role name="Contributor" />
+    </permission>
+#  </permissions>
+#</rolemap>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/+types_xml_filename+.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/+types_xml_filename+.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types/+types_xml_filename+.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<object name="${contenttype_name}"
+   meta_type="Factory-based Type Information with dynamic views"
+   i18n:domain="${package_dotted_name}" xmlns:i18n="http://xml.zope.org/namespaces/i18n">
+  <property name="title" i18n:translate="">${contenttype_name}</property>
+  <property name="description"
+    i18n:translate="">${contenttype_description}</property>
+  <property name="content_meta_type">${contenttype_classname}</property>
+#if str($folderish) == 'True'
+  <property name="content_icon">folder_icon.gif</property>
+#else
+  <property name="content_icon">document_icon.gif</property>
+#end if
+  <property name="product">${package_dotted_name}</property>
+  <property name="factory">add${contenttype_classname}</property>
+  <property name="immediate_view">atct_edit</property>
+  <property name="global_allow">${global_allow}</property>
+  <property name="filter_content_types">False</property>
+  <property name="allow_discussion">${allow_discussion}</property>
+  <property name="default_view">base_view</property>
+  <property name="view_methods">
+    <element value="base_view" />
+  </property>
+  <alias from="(Default)" to="(dynamic view)" />
+  <alias from="edit" to="atct_edit" />
+  <alias from="sharing" to="@@sharing" />
+  <alias from="view" to="(selected layout)" />
+  <action title="View" action_id="view" category="object" condition_expr=""
+#if str($folderish) == 'True'
+    url_expr="string:\${folder_url}/" visible="True">
+#else
+    url_expr="string:\${object_url}/" visible="True">
+#end if
+    <permission value="View" />
+  </action>
+  <action title="Edit" action_id="edit" category="object" condition_expr=""
+    url_expr="string:\${object_url}/edit" visible="True">
+    <permission value="Modify portal content" />
+  </action>
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types.xml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types.xml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/archetype/contenttype/profiles/default/types.xml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+  <object name="${contenttype_name}"
+    meta_type="Factory-based Type Information with dynamic views" />

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/browser/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+#<configure xmlns="http://namespaces.zope.org/zope"
+#           xmlns:browser="http://namespaces.zope.org/browser"
+#           i18n_domain="${namespace_package}.${package}">
+#
+#    <!-- -*- extra stuff goes here -*- -->
+
+    <!-- If you are using plone version 3.0, you will need to include the 
+         plone.browserlayer package in your buildout and uncomment the following
+         line in order to use ${interface_name} as a layer attribute -->
+    <!-- 
+    <include package="plone.browserlayer" />
+    -->
+    <!-- Example of browser component with ${interface_name} layer attribute -->
+    <!-- 
+    <browser:page
+        name="my-view"
+        for="*"
+        permission="zope.Public"
+        template="my-view.pt"
+        layer="..interfaces.${interface_name}"
+        />
+    -->
+
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/+interface_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/+interface_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/+interface_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+from zope.interface import Interface
+# -*- Additional Imports Here -*-
+
+
+class $(interface_name)(Interface):
+    """ A layer specific to this product. 
+        Is registered using browserlayer.xml
+    """
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/interfaces/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+#
+from ${interface_filename} import $(interface_name)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/default/browserlayer.xml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/default/browserlayer.xml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/browserlayer/profiles/default/browserlayer.xml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+#<?xml version="1.0"?>
+#<layers>
+#    <!-- -*- extra stuff goes here -*- -->
+
+    <layer name="${layer_name}"
+        interface="${namespace_package}.${package}.interfaces.${interface_filename}.${interface_name}"
+    />
+#</layers>
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+#  # -*- extra stuff goes here -*- 
+from zope.i18nmessageid import MessageFactory
+
+${package}MessageFactory = MessageFactory('${namespace_package}.${package}')
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/+form_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/+form_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/+form_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,35 @@
+from zope import interface, schema
+from zope.formlib import form
+from Products.Five.formlib import formbase
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
+
+from ${package_dotted_name} import ${package}MessageFactory as _
+
+class I${form_name}Schema(interface.Interface):
+    # -*- extra stuff goes here -*-
+
+#for $invariant in $form_invariants
+#if $invariant
+    @interface.invariant
+    def invariant_${invariant}(input):
+        pass
+	# Check input values example:
+	# if input.name != 'value':
+        #    raise interface.Invalid(_(u"Some error occurred !"))
+#end if
+#end for
+
+class ${form_name}(formbase.PageForm):
+    form_fields = form.FormFields(I${form_name}Schema)
+    label = _(u'${form_label}')
+    description = _(u'${form_description}')
+
+#for $action in $form_actions
+    @form.action('${action}')
+    def action${action}(self, action, data):
+        pass
+        # Put the action handler code here 
+
+#end for
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/browser/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,13 @@
+#<configure xmlns="http://namespaces.zope.org/zope"
+#           xmlns:browser="http://namespaces.zope.org/browser"
+#           i18n_domain="${package_dotted_name}">
+#
+#    <!-- -*- extra stuff goes here -*- -->
+    
+    <browser:page
+        for="*"
+        name="${form_filename}"
+        class=".${form_filename}.${form_name}"
+        permission="zope.Public" />
+
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:five="http://namespaces.zope.org/five"
+#    xmlns:i18n="http://namespaces.zope.org/i18n"
+#    i18n_domain="${namespace_package}.${package}">
+
+#  <!-- -*- extra stuff goes here -*- -->
+  <include package=".browser" />
+  
+#</configure>
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/form.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/form.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/form/form.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,184 @@
+from Products.Five.formlib import formbase
+
+from zope import interface, schema
+from zope.formlib import form
+from zope.schema.vocabulary import SimpleTerm, SimpleVocabulary
+
+
+def failing_constraint(value):
+    return 1 == 2
+
+
+def successfull_constraint(value):
+    return 1 == 1
+
+
+class IObjectSchema(interface.Interface):
+    test_field = schema.Text(
+        title=u'Test field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+        default=u'default',
+        missing_value=u'missing value')
+
+class IExampleSchema(interface.Interface):
+    """
+    Field types:
+        Datetime - Field containing a DateTime
+        Date - Field containing a date
+        Timedelta - Field containing a timedelta
+        Password - Field containing a unicode string without newlines that is a
+            password
+        Object - Field containing an Object value
+        URI - A field containing an absolute URI
+        ASCII - Field containing a 7-bit ASCII string. No characters > DEL
+            (chr(127)) are allowed
+        ASCIILine - Field containing a 7-bit ASCII string without newlines
+        Bytes - Field containing a byte string (like the python str)
+        BytesLine - Field containing a byte string without newlines
+        Tuple - Field containing a value that implements the API of a
+            conventional Python tuple
+        List - Field containing a value that implements the API of a
+            conventional Python list
+        Set - Field containing a value that implements the API of a
+            conventional Python standard library sets
+        FrozenSet - Field containing a value that implements the API of a
+            conventional Python 2.4+ frozenset
+        Dict - Field containing a conventional dict
+        SourceText - Field for source text of object
+        Id - A field containing a unique identifier
+            A unique identifier is either an absolute URI or a dotted name.
+            If it's a dotted name, it should have a module/package name as a
+            prefix
+        DottedName - Dotted name field
+        InterfaceField - Fields with a value that is an interface (implementing
+            zope.interface.Interface)
+
+    Field types arguments:
+        title - A short summary or label
+        description - A description of the field (to be displayed as a hint)
+        required - Tells whether a field requires its value to exist
+        readonly - If true, the field's value cannot be changed
+        default - The field default value may be None or a legal field value
+        missing_value - If a field has no assigned value, set it to this value
+        constraint - function checking a constraint on the field
+    """
+
+    # Text - Field containing a unicode string
+    text_field = schema.Text(
+        title=u'Text field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+        default=u'default value',
+        missing_value=u'missing value'
+        )
+
+    # TextLine - Field containing a unicode string without newlines
+    textline_field = schema.TextLine(
+        title=u'Textline field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+        default=u'default value',
+        missing_value=u'missing value',
+        constraint=successfull_constraint
+        )
+
+    # Int - Field containing an Integer Value
+    int_field = schema.Int(
+        title=u'Integer field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+        default=0,
+        missing_value=1,
+        min=0,
+        max=10
+        )
+
+    # Bool - Boolean Field
+    bool_field = schema.Bool(
+        title=u'Boolean field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+#        default=True,
+#        missing_value=True
+        )
+
+    # Float - Field containing a Float
+    float_field = schema.Float(
+        title=u'Float field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+#        default=0.0,
+#        missing_value=0.0
+        )
+
+    # Choice - Field whose value is contained in a predefined set
+    # Only one, values or vocabulary, may be specified for a given choice
+    choice_field = schema.Choice(
+        title=u'Choice field',
+        description=u'field description',
+        required=True,
+        readonly=False,
+#        default='Title 2',
+#        missing_value='Option 2',
+#        Only one of the arguments: vocabulary, source or values may be used
+        vocabulary=SimpleVocabulary((
+            SimpleTerm(value=1, token='Option 1', title='Title 1'),
+            SimpleTerm(value=2, token='Option 2', title='Title 2')
+            ))
+#        source=VocabularyExample
+#        values=['Option 1', 'Option 2'],
+        )
+
+#    object_field = schema.Object(
+#        title=u'Object field',
+#        description=u'field description',
+#        required=True,
+#        readonly=False,
+#        default=None,
+#        missing_value=None,
+#        schema=IObjectSchema
+#        )
+
+
+class ExampleForm(formbase.PageForm):
+    form_fields = form.FormFields(IExampleSchema)
+    # Put here the label to be displayed as form title
+    label = u'Form label'
+    # Put here the form description to be displayed under the form title
+    description = u'Form short description'
+
+    # Instead of 'Submit button' put here the label of the form submit button
+    @form.action('Submit button', failure='handle_failure')
+    def handle_success(self, action, data):
+        """
+        Called when the action was submitted and there are NO validation
+        errors.
+
+        This form is generated with ZopeSkel. Please make sure you fill in
+        the implementation of the form processing.
+
+        """
+        # Put here the feedback to show in case the form submission succeeded
+        self.status = 'The handle_success method of the %s form is not \
+            implemented.' % (self.__class__.__name__)
+
+        # Put here the code for processing the form
+
+
+    def handle_failure(self, action, data, errors):
+        """
+        Called when the action was submitted and there are validation errors.
+
+        """
+        # Put here the feedback message to show in case the validation failed
+        self.status = 'Errors occured while submitting the form'
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/browser/+form_filename+.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/browser/+form_filename+.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/formfield/browser/+form_filename+.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+
+    ${field_name} = schema.${field_type}(
+        title=u'${field_title}',
+        description=u'${field_description}',
+        required=${field_required},
+        readonly=${field_readonly},
+        default=${field_default},
+#if str($field_missing_value).strip()
+        missing_value=${field_missing_value},
+#end if 
+#if str($field_constraint)
+        constraint=${field_constraint},
+#end if
+#if $field_type == 'Choice'
+        vocabulary=SimpleVocabulary((
+            SimpleTerm(value=1, token='Option 1', title='Title 1'),
+            SimpleTerm(value=2, token='Option 2', title='Title 2')
+            ))	
+#end if 
+        )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:five="http://namespaces.zope.org/five"
+#    xmlns:i18n="http://namespaces.zope.org/i18n"
+#    i18n_domain="${namespace_package}.${package}">
+
+#  <!-- -*- extra stuff goes here -*- -->
+  <i18n:registerTranslations directory="locales" />
+  
+#</configure>
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/i18nlocales/locales/+language_iso_code+/LC_MESSAGES/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+The <packagename>.po file containing language-specific translations for your product will go here when it is generated.
+
+For more information on internationalization and the difference between the i18n directory and this locales directory, read here:
+
+http://maurits.vanrees.org/weblog/archive/2007/09/i18n-locales-and-plone-3.0

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+#  # -*- extra stuff goes here -*- 
+from zope.i18nmessageid import MessageFactory
+
+${package}MessageFactory = MessageFactory('${namespace_package}.${package}')
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:five="http://namespaces.zope.org/five"
+#    xmlns:i18n="http://namespaces.zope.org/i18n"
+#    i18n_domain="${namespace_package}.${package}">
+
+#  <!-- -*- extra stuff goes here -*- -->
+  <include package=".portlets" />
+  
+#</configure>
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.pt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.pt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.pt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+<dl class="portlet portlet${portlet_type_name}"
+    i18n:domain="${package_dotted_name}">
+
+    <dt class="portletHeader">
+        <span class="portletTopLeft"></span>
+        <span>
+           Header
+        </span>
+        <span class="portletTopRight"></span>
+    </dt>
+
+    <dd class="portletItem odd">
+        Body text
+    </dd>
+
+    <dd class="portletFooter">
+        <span class="portletBottomLeft"></span>
+        <span>
+           Footer
+        </span>
+        <span class="portletBottomRight"></span>
+    </dd>
+
+</dl>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/+portlet_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,99 @@
+from zope.interface import Interface
+from zope.interface import implements
+
+from plone.app.portlets.portlets import base
+from plone.portlets.interfaces import IPortletDataProvider
+
+from zope import schema
+from zope.formlib import form
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+
+from ${package_dotted_name} import ${package}MessageFactory as _
+
+from zope.i18nmessageid import MessageFactory
+__ = MessageFactory("plone")
+
+class I${portlet_type_name}(IPortletDataProvider):
+    """A portlet
+
+    It inherits from IPortletDataProvider because for this portlet, the
+    data that is being rendered and the portlet assignment itself are the
+    same.
+    """
+
+    # TODO: Add any zope.schema fields here to capture portlet configuration
+    # information. Alternatively, if there are no settings, leave this as an
+    # empty interface - see also notes around the add form and edit form
+    # below.
+
+    # some_field = schema.TextLine(title=_(u"Some field"),
+    #                              description=_(u"A field to use"),
+    #                              required=True)
+
+
+class Assignment(base.Assignment):
+    """Portlet assignment.
+
+    This is what is actually managed through the portlets UI and associated
+    with columns.
+    """
+
+    implements(I${portlet_type_name})
+
+    # TODO: Set default values for the configurable parameters here
+
+    # some_field = u""
+
+    # TODO: Add keyword parameters for configurable parameters here
+    # def __init__(self, some_field=u''):
+    #    self.some_field = some_field
+
+    def __init__(self):
+        pass
+
+    @property
+    def title(self):
+        """This property is used to give the title of the portlet in the
+        "manage portlets" screen.
+        """
+        return __(u"${portlet_name}")
+
+
+class Renderer(base.Renderer):
+    """Portlet renderer.
+
+    This is registered in configure.zcml. The referenced page template is
+    rendered, and the implicit variable 'view' will refer to an instance
+    of this class. Other methods can be added and referenced in the template.
+    """
+
+    render = ViewPageTemplateFile('${portlet_filename}.pt')
+
+
+# NOTE: If this portlet does not have any configurable parameters, you can
+# inherit from NullAddForm and remove the form_fields variable.
+
+class AddForm(base.AddForm):
+    """Portlet add form.
+
+    This is registered in configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display. The create() method actually
+    constructs the assignment that is being added.
+    """
+    form_fields = form.Fields(I${portlet_type_name})
+
+    def create(self, data):
+        return Assignment(**data)
+
+
+# NOTE: IF this portlet does not have any configurable parameters, you can
+# remove this class definition and delete the editview attribute from the
+# <plone:portlet /> registration in configure.zcml
+
+class EditForm(base.EditForm):
+    """Portlet edit form.
+
+    This is registered with configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display.
+    """
+    form_fields = form.Fields(I${portlet_type_name})

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/portlets/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+#<configure 
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:plone="http://namespaces.plone.org/plone"
+#    i18n_domain="${package_dotted_name}">
+#
+#  <!-- Ensure Plone's portlets ZCML has already been processed; without
+#       this, we may get a permission lookup error
+#  -->
+#  <include package="plone.app.portlets" />
+#
+#  <!-- -*- extra stuff goes here -*- -->
+
+  <plone:portlet
+      name="${dotted_name}.${portlet_type_name}"
+      interface=".${portlet_filename}.I${portlet_type_name}"
+      assignment=".${portlet_filename}.Assignment"
+      view_permission="zope2.View"
+      edit_permission="cmf.ManagePortal"
+      renderer=".${portlet_filename}.Renderer"
+      addview=".${portlet_filename}.AddForm"
+      editview=".${portlet_filename}.EditForm"
+      />
+
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/metadata.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/metadata.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/metadata.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>1000</version>
+</metadata>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/portlets.xml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/portlets.xml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/profiles/default/portlets.xml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,23 @@
+#<?xml version="1.0"?>
+#<!-- This file is used to register new types of portlets. It can also
+#     be used to register completely new column types. See CMFPlone's version
+#     of this file for more information.
+#  -->
+#<portlets
+#    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+#    i18n:domain="plone">
+#	<!-- -*- extra stuff goes here -*- -->
+
+   <!-- to have your portlet's title and description translated in 
+        @@manage-portlets, provide the messageids for the i18n:domain plone
+        (see http://dev.plone.org/plone/ticket/9631 or
+             http://dev.plone.org/plone/ticket/9090) for more information on 
+        internationalization with portlets or in plone in general -->
+   <portlet
+     addview="${dotted_name}.${portlet_type_name}"
+     title="${portlet_name}"
+     description="${description}"
+     i18n:attributes="title; description"
+   />
+
+#</portlets>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/base_+portlet_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/base_+portlet_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/base_+portlet_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+
+from Testing import ZopeTestCase as ztc
+
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import onsetup
+
+ at onsetup
+def setup_product():
+    """Set up additional products and ZCML required to test this product.
+
+    The @onsetup decorator causes the execution of this body to be deferred
+    until the setup of the Plone site testing layer.
+    """
+
+    # Load the ZCML configuration for this package and its dependencies
+
+    fiveconfigure.debug_mode = True
+    import ${dotted_name}
+    zcml.load_config('configure.zcml', ${dotted_name})
+    fiveconfigure.debug_mode = False
+
+    # We need to tell the testing framework that these products
+    # should be available. This can't happen until after we have loaded
+    # the ZCML.
+
+    ztc.installPackage('${dotted_name}')
+
+# The order here is important: We first call the deferred function and then
+# let PloneTestCase install it during Plone site setup
+
+setup_product()
+ptc.setupPloneSite(products=['${dotted_name}'])
+
+
+class TestCase(ptc.PloneTestCase):
+    """Base class used for test cases
+    """
+
+
+class FunctionalTestCase(ptc.FunctionalTestCase):
+    """Test case class used for functional (doc-)tests
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/test_+portlet_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/test_+portlet_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/portlet/tests/test_+portlet_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,94 @@
+from zope.component import getUtility, getMultiAdapter
+
+from plone.portlets.interfaces import IPortletType
+from plone.portlets.interfaces import IPortletManager
+from plone.portlets.interfaces import IPortletAssignment
+from plone.portlets.interfaces import IPortletDataProvider
+from plone.portlets.interfaces import IPortletRenderer
+
+from plone.app.portlets.storage import PortletAssignmentMapping
+
+from ${dotted_name} import ${portlet_filename}
+from ${dotted_name}.tests.base_${portlet_filename} import TestCase
+
+
+class TestPortlet(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager',))
+
+    def test_portlet_type_registered(self):
+        portlet = getUtility(IPortletType, name='${dotted_name}.${portlet_type_name}')
+        self.assertEquals(portlet.addview, '${dotted_name}.${portlet_type_name}')
+
+    def test_interfaces(self):
+        # TODO: Pass any keywoard arguments to the Assignment constructor
+        portlet = ${portlet_filename}.Assignment()
+        self.failUnless(IPortletAssignment.providedBy(portlet))
+        self.failUnless(IPortletDataProvider.providedBy(portlet.data))
+
+    def test_invoke_add_view(self):
+        portlet = getUtility(IPortletType, name='${dotted_name}.${portlet_type_name}')
+        mapping = self.portal.restrictedTraverse('++contextportlets++plone.leftcolumn')
+        for m in mapping.keys():
+            del mapping[m]
+        addview = mapping.restrictedTraverse('+/' + portlet.addview)
+
+        # TODO: Pass a dictionary containing dummy form inputs from the add form
+        addview.createAndAdd(data={})
+
+        self.assertEquals(len(mapping), 1)
+        self.failUnless(isinstance(mapping.values()[0], ${portlet_filename}.Assignment))
+
+    # NOTE: This test can be removed if the portlet has no edit form
+    def test_invoke_edit_view(self):
+        mapping = PortletAssignmentMapping()
+        request = self.folder.REQUEST
+
+        mapping['foo'] = ${portlet_filename}.Assignment()
+        editview = getMultiAdapter((mapping['foo'], request), name='edit')
+        self.failUnless(isinstance(editview, ${portlet_filename}.EditForm))
+
+    def test_obtain_renderer(self):
+        context = self.folder
+        request = self.folder.REQUEST
+        view = self.folder.restrictedTraverse('@@plone')
+        manager = getUtility(IPortletManager, name='plone.rightcolumn', context=self.portal)
+
+        # TODO: Pass any keywoard arguments to the Assignment constructor
+        assignment = ${portlet_filename}.Assignment()
+
+        renderer = getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
+        self.failUnless(isinstance(renderer, ${portlet_filename}.Renderer))
+
+
+class TestRenderer(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager',))
+
+    def renderer(self, context=None, request=None, view=None, manager=None, assignment=None):
+        context = context or self.folder
+        request = request or self.folder.REQUEST
+        view = view or self.folder.restrictedTraverse('@@plone')
+        manager = manager or getUtility(IPortletManager, name='plone.rightcolumn', context=self.portal)
+
+        # TODO: Pass any default keywoard arguments to the Assignment constructor
+        assignment = assignment or ${portlet_filename}.Assignment()
+        return getMultiAdapter((context, request, view, manager, assignment), IPortletRenderer)
+
+    def test_render(self):
+        # TODO: Pass any keywoard arguments to the Assignment constructor
+        r = self.renderer(context=self.portal, assignment=${portlet_filename}.Assignment())
+        r = r.__of__(self.folder)
+        r.update()
+        output = r.render()
+        # TODO: Test output
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPortlet))
+    suite.addTest(makeSuite(TestRenderer))
+    return suite

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+#  # -*- extra stuff goes here -*- 
+from zope.i18nmessageid import MessageFactory
+
+${package}MessageFactory = MessageFactory('${namespace_package}.${package}')
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.pt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.pt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.pt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,15 @@
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en"
+      lang="en"
+      metal:use-macro="here/main_template/macros/master"
+      i18n:domain="${package_dotted_name}">
+<body>
+    <div metal:fill-slot="main">
+        <tal:main-macro metal:define-macro="main"
+                        tal:define="testview view/test">
+
+            <span tal:content="testview/dummy">test</span>
+
+        </tal:main-macro>
+    </div>
+</body>
+</html>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/+view_filename+view.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,42 @@
+from zope.interface import implements, Interface
+
+from Products.Five import BrowserView
+from Products.CMFCore.utils import getToolByName
+
+from ${package_dotted_name} import ${package}MessageFactory as _
+
+
+class I${view_classname}View(Interface):
+    """
+    ${view_name} view interface
+    """
+
+    def test():
+        """ test method"""
+
+
+class ${view_classname}View(BrowserView):
+    """
+    ${view_name} browser view
+    """
+    implements(I${view_classname}View)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    @property
+    def portal_catalog(self):
+        return getToolByName(self.context, 'portal_catalog')
+
+    @property
+    def portal(self):
+        return getToolByName(self.context, 'portal_url').getPortalObject()
+
+    def test(self):
+        """
+        test method
+        """
+        dummy = _(u'a dummy string')
+
+        return {'dummy': dummy}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/browser/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+#<configure 
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:browser="http://namespaces.zope.org/browser"
+#    i18n_domain="${package_dotted_name}">
+#
+#    <!-- -*- extra stuff goes here -*- -->
+
+  <browser:page
+      for="*"
+      name="${view_filename}_view"
+      class=".${view_filename}view.${view_classname}View"
+      template="${view_filename}view.pt"
+      allowed_interface=".${view_filename}view.I${view_classname}View"
+      permission="zope.Public"
+      />
+
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/view/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:five="http://namespaces.zope.org/five"
+#    xmlns:i18n="http://namespaces.zope.org/i18n"
+#    i18n_domain="${namespace_package}.${package}">
+
+#  <!-- -*- extra stuff goes here -*- -->
+  <include package=".browser" />
+  
+#</configure>
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/configure.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/configure.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/configure.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:five="http://namespaces.zope.org/five"
+#    xmlns:i18n="http://namespaces.zope.org/i18n"
+#    i18n_domain="${namespace_package}.${package}">
+
+#  <!-- -*- extra stuff goes here -*- -->
+  <include package=".meta" />
+  
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/meta.zcml_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/meta.zcml_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/meta.zcml_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+#<configure
+#    xmlns="http://namespaces.zope.org/zope"
+#    xmlns:meta="http://namespaces.zope.org/meta">
+#
+#  <!-- -*- extra stuff goes here -*- -->
+
+  <meta:directive
+      name="$directive_name"
+      namespace="http://namespaces.zope.org/${directive_namespace}"
+      schema=".metadirectives.I${directive_class_name}Directive"
+      handler=".metaconfigure.${directive_class_name}Directive"
+      />
+
+#</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metaconfigure.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metaconfigure.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metaconfigure.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+\#from zope.app.component.metaconfigure import handler
+\#from zope.app.component.interface import provideInterface
+\#from zope.configuration.exceptions import ConfigurationError
+
+\#\# -*- extra stuff goes here -*-
+
+def ${directive_class_name}Directive(_context, name=None, for_=None, factory=None):
+    """
+    register the ${directive_name} directive
+    """
+    if name is None or for_ is None or factory is None:
+        raise ConfigurationError(
+         "You must specify the 'name', the 'for' and the 'factory' attributes.")
+
+    # # the following is just an example
+    # _context.action(
+    #                  discriminator = ('${directive_class_name}', name),
+    #                  callable = handler,
+    #                  args = ('provideAdapter', (for_,),
+    #                          IExampleInterface, name, factory, _context.info)
+    #                )
+    #
+    # for_ = tuple(for_)
+    #
+    # for iface in for_:
+    #     if iface is not None:
+    #         _context.action( discriminator = None,
+    #                          callable = provideInterface,
+    #                          args = ('', iface)
+    #                        )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metadirectives.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metadirectives.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone/zcmlmeta/meta/metadirectives.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+\#from zope.interface import Interface
+\#from zope.schema import TextLine
+\#from zope.configuration.fields import GlobalInterface, GlobalObject
+
+\#\# -*- extra stuff goes here -*-
+
+class I${directive_class_name}Directive(Interface):
+    """
+    Defines a schema for ${directive_name} directive
+    (The attributes are given as example)
+    """
+
+    name = TextLine(
+        title=u"Name",
+        description=u"The name of the ${directive_name} directive.",
+        required=True
+        )
+
+    for_ = GlobalInterface(
+        title=u"interface",
+        description=u"""Specifies the interface for which the directive is
+        registered.""",
+        required=True
+        )
+
+    factory = GlobalObject(
+        title=u"hander",
+        description=u"The factory",
+        required=True
+        )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IAnonymousUserFactoryPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.anonymous_user_factory.AnonymousUserFactoryPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import anonymous_user_factory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/anonymous_user_factory.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/anonymous_user_factory.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/anonymous_user_factory/plugins/anonymous_user_factory.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class AnonymousUserFactoryPlugin(BasePlugin):
+    """ Create a new anonymous IPropertiedUser.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('createAnonymousUser')
+    def createAnonymousUser(self):
+        """Return an anonymous user, if possible.
+
+        o Return None to allow another plugin, or the default, to fire.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IAuthenticationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.authentication.AuthenticationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import authentication

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/authentication.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/authentication.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/authentication/plugins/authentication.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,28 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class AuthenticationPlugin(BasePlugin):
+    """ Map credentials to a user ID.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('authenticateCredentials')
+    def authenticateCredentials(self, credentials):
+
+        """ credentials -> (userid, login)
+
+        o 'credentials' will be a mapping, as returned by IExtractionPlugin.
+
+        o Return a  tuple consisting of user ID (which may be different
+          from the login name) and login
+
+        o If the credentials cannot be authenticated, return None.
+        """
+        user_id = ''
+        user_login = ''
+
+        \#add your code here
+
+        return (user_id, user_login)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IChallengePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.challenge.ChallengePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import challenge

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/challenge.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/challenge.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/challenge/plugins/challenge.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,41 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class ChallengePlugin(BasePlugin):
+    """Initiate a challenge to the user to provide credentials.
+    
+    Challenge plugins have an attribute 'protocol' representing
+    the protocol the plugin operates under, defaulting to None.
+
+    Plugins operating under the same protocol will all be given an
+    attempt to fire. The first plugin of a protocol group that
+    successfully fires establishes the protocol of the overall
+    challenge.
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('challenge')
+    def challenge(self, request, response):
+
+        """ Assert via the response that credentials will be gathered.
+
+        Takes a REQUEST object and a RESPONSE object.
+
+        Returns True if it fired, False otherwise.
+
+        Two common ways to initiate a challenge:
+
+          - Add a 'WWW-Authenticate' header to the response object.
+
+            NOTE: add, since the HTTP spec specifically allows for
+            more than one challenge in a given response.
+
+          - Cause the response object to redirect to another URL (a
+            login form page, for instance)
+        """
+
+        \# add your code here
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.ICredentialsResetPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.credentials_reset.CredentialsResetPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import credentials_reset

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/credentials_reset.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/credentials_reset.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_reset/plugins/credentials_reset.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class CredentialsResetPlugin(BasePlugin):
+    """ Callback:  user has logged out.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('resetCredentials')
+    def resetCredentials(self, request, response):
+        """ Scribble as appropriate.
+        """
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.ICredentialsUpdatePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.credentials_update.CredentialsUpdatePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import credentials_update

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/credentials_update.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/credentials_update.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/credentials_update/plugins/credentials_update.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class CredentialsUpdatePlugin(BasePlugin):
+    """ Callback:  user has changed her password.
+
+    This interface is not responsible for the actual password change,
+    it is used after a successful password change event.
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('updateCredentials')
+    def updateCredentials(self, request, response, login, new_password):
+        """ Scribble as appropriate.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IExtractionPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.extraction.ExtractionPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import extraction

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/extraction.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/extraction.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/extraction/plugins/extraction.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class ExtractionPlugin(BasePlugin):
+    """Extracts login name and credentials from a request.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('extractCredentials')
+    def extractCredentials(self, request):
+        """request -> {...}
+
+        o Return a mapping of any derived credentials.
+
+        o Return an empty mapping to indicate that the plugin found no
+          appropriate credentials.
+        """
+        creds = {}
+
+        \#add your code here
+
+        return creds

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IGroupEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.group_enumeration.GroupEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import group_enumeration

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/group_enumeration.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/group_enumeration.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/group_enumeration/plugins/group_enumeration.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,63 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class GroupEnumerationPlugin( BasePlugin ):
+    """Allow querying groups by ID, and searching for groups.
+
+    o XXX:  can these be done by a single plugin?
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('enumerateGroups')
+    def enumerateGroups(self,
+                        id=None,
+                        exact_match=False,
+                        sort_by=None,
+                        max_results=None,
+                        **kw):
+        """ -> ( group_info_1, ... group_info_N )
+
+        o Return mappings for groups matching the given criteria.
+
+        o 'id' in combination with 'exact_match' true, will
+          return at most one mapping per supplied ID ('id' and 'login'
+          may be sequences).
+
+        o If 'exact_match' is False, then 'id' may be treated by
+          the plugin as "contains" searches (more complicated searches
+          may be supported by some plugins using other keyword arguments).
+
+        o If 'sort_by' is passed, the results will be sorted accordingly.
+          known valid values are 'id' (some plugins may support others).
+
+        o If 'max_results' is specified, it must be a positive integer,
+          limiting the number of returned mappings.  If unspecified, the
+          plugin should return mappings for all groups satisfying the
+          criteria.
+
+        o Minimal keys in the returned mappings:
+
+          'id' -- (required) the group ID
+
+          'pluginid' -- (required) the plugin ID (as returned by getId())
+
+          'properties_url' -- (optional) the URL to a page for updating the
+                              group's properties.
+
+          'members_url' -- (optional) the URL to a page for updating the
+                           principals who belong to the group.
+
+        o Plugin *must* ignore unknown criteria.
+
+        o Plugin may raise ValueError for invalid critera.
+
+        o Insufficiently-specified criteria may have catastrophic
+          scaling issues for some implementations.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IGroupsPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.groups.GroupsPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import groups

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/groups.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/groups.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/groups/plugins/groups.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,23 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class GroupsPlugin(BasePlugin):
+    """ Determine the groups to which a user belongs.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('getGroupsForPrincipal')
+    def getGroupsForPrincipal(self, principal, request=None):
+        """ principal -> (group_1, ... group_N)
+
+        o Return a sequence of group names to which the principal
+          (either a user or another group) belongs.
+
+        o May assign groups based on values in the REQUEST object, if present
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IPropertiesPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.properties.PropertiesPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import properties

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/properties.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/properties.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/properties/plugins/properties.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,29 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class PropertiesPlugin(BasePlugin):
+    """ Return a property set for a user.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('getPropertiesForUser')
+    def getPropertiesForUser(self, user, request=None):
+        """ user -> {}
+
+        o User will implement IPropertiedUser.
+
+        o Plugin should return a dictionary or an object providing
+          IPropertiesPlugin.
+
+        o Plugin may scribble on the user, if needed (but must still
+          return a mapping, even if empty).
+
+        o May assign properties based on values in the REQUEST object, if
+          present
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IRoleAssignerPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.role_assigner.RoleAssignerPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import role_assigner

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/role_assigner.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/role_assigner.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_assigner/plugins/role_assigner.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,31 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class RoleAssignerPlugin(BasePlugin):
+    """ Assign a role to an identified principal
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('doAssignRoleToPrincipal')
+    def doAssignRoleToPrincipal(self, principal_id, role):
+        """ Create a principal/role association in a Role Manager
+
+        o Return a Boolean indicating whether the role was assigned or not
+        """
+
+        \#add your code here
+
+        pass
+
+    security.declarePrivate('doRemoveRoleFromPrincipal')
+    def doRemoveRoleFromPrincipal(self, principal_id, role):
+        """ Remove a principal/role association from a Role Manager
+
+        o Return a Boolean indicating whether the role was removed or not
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IRoleEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.role_enumeration.RoleEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import role_enumeration

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/role_enumeration.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/role_enumeration.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/role_enumeration/plugins/role_enumeration.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,61 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class RoleEnumerationPlugin( BasePlugin ):
+    """ Allow querying roles by ID, and searching for roles.
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('enumerateRoles')
+    def enumerateRoles(self,
+                      id=None,
+                      exact_match=False,
+                      sort_by=None,
+                      max_results=None,
+                      **kw):
+        """ -> ( role_info_1, ... role_info_N )
+
+        o Return mappings for roles matching the given criteria.
+
+        o 'id' in combination with 'exact_match' true, will
+          return at most one mapping per supplied ID ('id' and 'login'
+          may be sequences).
+
+        o If 'exact_match' is False, then 'id' may be treated by
+          the plugin as "contains" searches (more complicated searches
+          may be supported by some plugins using other keyword arguments).
+
+        o If 'sort_by' is passed, the results will be sorted accordingly.
+          known valid values are 'id' (some plugins may support others).
+
+        o If 'max_results' is specified, it must be a positive integer,
+          limiting the number of returned mappings.  If unspecified, the
+          plugin should return mappings for all roles satisfying the
+          criteria.
+
+        o Minimal keys in the returned mappings:
+
+          'id' -- (required) the role ID
+
+          'pluginid' -- (required) the plugin ID (as returned by getId())
+
+          'properties_url' -- (optional) the URL to a page for updating the
+                              role's properties.
+
+          'members_url' -- (optional) the URL to a page for updating the
+                           principals to whom the role is assigned.
+
+        o Plugin *must* ignore unknown criteria.
+
+        o Plugin may raise ValueError for invalid critera.
+
+        o Insufficiently-specified criteria may have catastrophic
+          scaling issues for some implementations.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IRolesPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.roles.RolesPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import roles

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/roles.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/roles.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/roles/plugins/roles.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class RolesPlugin(BasePlugin):
+    """Determine the (global) roles which a user has.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('getRoles ForPrincipal')
+    def getRolesForPrincipal(self, principal, request=None):
+        """principal -> (role_1, ... role_N)
+
+        o Return a sequence of role names which the principal has.
+
+        o May assign roles based on values in the REQUEST object, if present.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IUpdatePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.update.UpdatePlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import update

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/update.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/update.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/update/plugins/update.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class UpdatePlugin(BasePlugin):
+    """ Allow the user or the application to update the user's properties.
+    """
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('updateUserInfo')
+    def updateUserInfo(self, user, set_id, set_info):
+        """ Update backing store for 'set_id' using 'set_info'.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IUserAdderPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.user_adder.UserAdderPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import user_adder

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/user_adder.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/user_adder.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_adder/plugins/user_adder.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class UserAdderPlugin(BasePlugin):
+    """ Create a new user record in a User Manager
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('doAddUser')
+    def doAddUser(self, login, password):
+        """ Add a user record to a User Manager, with the given login
+            and password
+
+        o Return a Boolean indicating whether a user was added or not
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IUserEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.user_enumeration.UserEnumerationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import user_enumeration

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/user_enumeration.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/user_enumeration.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_enumeration/plugins/user_enumeration.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,65 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class UserEnumerationPlugin(BasePlugin):
+    """Allow querying users by ID, and searching for users.
+
+    o XXX:  can these be done by a single plugin?
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('enumerateUsers')
+    def enumerateUsers(self,
+                       id=None,
+                       login=None,
+                       exact_match=False,
+                       sort_by=None,
+                       max_results=None,
+                       **kw):
+        """-> ( user_info_1, ... user_info_N )
+
+        o Return mappings for users matching the given criteria.
+
+        o 'id' or 'login', in combination with 'exact_match' true, will
+          return at most one mapping per supplied ID ('id' and 'login'
+          may be sequences).
+
+        o If 'exact_match' is False, then 'id' and / or login may be
+          treated by the plugin as "contains" searches (more complicated
+          searches may be supported by some plugins using other keyword
+          arguments).
+
+        o If 'sort_by' is passed, the results will be sorted accordingly.
+          known valid values are 'id' and 'login' (some plugins may support
+          others).
+
+        o If 'max_results' is specified, it must be a positive integer,
+          limiting the number of returned mappings.  If unspecified, the
+          plugin should return mappings for all users satisfying the criteria.
+
+        o Minimal keys in the returned mappings:
+
+          'id' -- (required) the user ID, which may be different than
+                  the login name
+
+          'login' -- (required) the login name
+
+          'pluginid' -- (required) the plugin ID (as returned by getId())
+
+          'editurl' -- (optional) the URL to a page for updating the
+                       mapping's user
+
+        o Plugin *must* ignore unknown criteria.
+
+        o Plugin may raise ValueError for invalid criteria.
+
+        o Insufficiently-specified criteria may have catastrophic
+          scaling issues for some implementations.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IUserFactoryPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.user_factory.UserFactoryPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import user_factory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/user_factory.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/user_factory.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/user_factory/plugins/user_factory.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class UserFactoryPlugin(BasePlugin):
+    """Create a new IPropertiedUser.
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('createUser')
+    def createUser(self, user_id, name):
+        """ Return a user, if possible.
+
+        o Return None to allow another plugin, or the default, to fire.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/interface.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/interface.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/interface.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    interfaces.plugins.IValidationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugin.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugin.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugin.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+                    plugins.validation.ValidationPlugin,

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/__init__.py_insert
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/__init__.py_insert	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/__init__.py_insert	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+import validation

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/validation.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/validation.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/localcommands/templates/plone_pas/validation/plugins/validation.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+
+
+class ValidationPlugin(BasePlugin):
+    """ Specify allowable values for user properties.
+
+    o E.g., constrain minimum password length, allowed characters, etc.
+
+    o Operate on entire property sets, not individual properties.
+    """
+
+    security = ClassSecurityInfo()
+
+    security.declarePrivate('validateUserInfo')
+    def validateUserInfo(self, user, set_id, set_info):
+        """-> ( error_info_1, ... error_info_N )
+
+        o Returned values are dictionaries, containing at least keys:
+
+          'id' -- the ID of the property, or None if the error is not
+                  specific to one property.
+
+          'error' -- the message string, suitable for display to the user.
+        """
+
+        \#add your code here
+
+        pass
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/nested_namespace.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/nested_namespace.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/nested_namespace.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,38 @@
+import copy
+
+from zopeskel.base import get_var
+from zopeskel.base import var, EXPERT, EASY
+from zopeskel.basic_namespace import BasicNamespace
+from zopeskel.vars import DottedVar
+
+VAR_NS2 = DottedVar(
+            'namespace_package2', 
+            title='Namespace 2 Package Name',
+            description='Name of inner namespace package',
+            default='plone', 
+            modes=(EXPERT,), 
+            page='Namespaces',
+            help="""
+This is the name of the inner namespace package (Python folder) for this
+project. For example, in 'plone.app.example', this would be
+'app' ('plone' will be the first namespace, and 'example' would be
+the package name). 
+"""
+)
+
+class NestedNamespace(BasicNamespace):
+    _template_dir = 'templates/nested_namespace'
+    summary = "A basic Python project with a nested namespace (2 dots in name)"
+    ndots = 2
+    help = """
+This creates a Python project without any Zope or Plone features.
+"""
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(BasicNamespace.vars)
+    get_var(vars, 'namespace_package').default = 'plone'
+    vars.insert(2, VAR_NS2)
+    get_var(vars, 'package').default = 'example'
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,63 @@
+import copy
+import shutil
+import os
+
+from zopeskel.basic_zope import BasicZope
+from zopeskel.base import get_var
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import BooleanVar
+
+class Plone(BasicZope):
+    _template_dir = 'templates/plone'
+    summary = "A project for Plone products"
+    help = """
+This creates a Plone project (to create a Plone *site*, you probably
+want to use the one of the templates for a buildout).
+
+To create a Plone project with a name like 'plone.app.myproject' 
+(2 dots, a 'nested namespace'), use the 'plone_app' template.
+"""
+    category = "Plone Development"
+    required_templates = ['basic_namespace']
+    use_local_commands = True
+    use_cheetah = True
+    vars = copy.deepcopy(BasicZope.vars)
+    vars.insert(5, BooleanVar(
+        'add_profile',
+        title='Register Profile',
+        description='Should this package register a GS Profile',
+        modes=(EASY, EXPERT),
+        default=False,
+        help="""
+If your package has need of a Generic Setup profile, set this value to 'True'.  
+
+Having a Generic Setup profile registered makes your package 'installable'
+using the ZMI portal_quickinstaller or Plone's 'Add/Remove Products' control
+panel.  This allows any portions of your package that require Generic
+Setup--such as portlets, content types, actions and so on--to be
+properly installed.
+"""
+    ))
+    get_var(vars, 'namespace_package').default = 'plone'
+    get_var(vars, 'package').default = 'example'
+    
+    def post(self, command, output_dir, vars):
+        if vars['add_profile'] == False:
+            # if we do not want a profile, remove it.            
+            path = os.path.join(output_dir,
+                                vars['namespace_package'],
+                                vars['package'])
+            try:
+                shutil.rmtree(os.path.join(path, 'profiles'))
+            except OSError, e:
+                msg = """WARNING: Error in template rendering:
+
+%s
+
+Your package may have structural problems, please check before 
+using it.
+"""
+                self.post_run_msg = msg % str(e)
+            
+        super(Plone, self).post(command, output_dir, vars)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+import copy
+from zopeskel.plone3_buildout import Plone3Buildout
+from zopeskel.base import get_var
+
+class Plone25Buildout(Plone3Buildout):
+    _template_dir = 'templates/plone2.5_buildout'
+    summary = "A buildout for Plone 2.5 projects"
+    help = """
+This template creates a buildout for Plone 2.5, appropriate for
+development. If you also need ZEO or caching, you may wish to look
+at the plone_hosting template.
+"""
+    required_templates = ['plone3_buildout']
+
+    vars = copy.deepcopy(Plone3Buildout.vars)
+    get_var(vars, 'plone_version').default = "2.5.5"
+
+    # The Plone3Buildout has an appropriate "use-the-installer"
+    # message, but this wouldn't be right here, so let's
+    # override it.
+    pre_run_msg = "" 

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_theme.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_theme.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone25_theme.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,41 @@
+import copy
+import os
+
+from zopeskel.plone import Plone
+from zopeskel.plone2_theme import theme_vars
+from zopeskel.base import get_var, EXPERT
+from zopeskel.plone2_theme import cleanupStylsheets
+
+class Plone25Theme(Plone):
+    _template_dir = 'templates/plone2.5_theme'
+    summary = "A theme for Plone 2.5"
+    help = """
+This creates a project for a theme for Plone 2.5
+"""
+    category = "Plone Theme Development"
+    required_templates = ['plone']
+    use_cheetah = True
+
+    vars = copy.deepcopy(Plone.vars)
+    get_var(vars, 'namespace_package').default = 'Products'
+    get_var(vars, 'description').default = 'An installable theme for Plone 2.5'
+    get_var(vars, 'keywords').default = 'web zope plone theme'
+    #add_profile should always default to True for theme packages
+    get_var(vars, 'add_profile').default = True
+    #add_profile need not appear as a question for theme packages
+    get_var(vars, 'add_profile').modes = ()
+    vars = vars[:3] + theme_vars + vars[3:]
+
+    def pre(self, command, output_dir, vars):
+        if vars['skinname'] == '':
+            # A title is needed in profiles.zcml otherwise adding a
+            # Plone Site will throw an error when displaying the
+            # extension profiles.
+            vars['skinname'] = 'Custom Theme'
+        super(Plone25Theme, self).pre(command, output_dir, vars)
+
+    def post(self, command, output_dir, vars):
+        if str(vars['empty_styles']) == 'False':
+            np, p = vars['namespace_package'], vars['package']
+            cleanupStylsheets(os.path.join(output_dir, np, p, 'skins'))
+        super(Plone25Theme, self).post(command, output_dir, vars)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone2_theme.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone2_theme.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone2_theme.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,136 @@
+import os
+import copy
+
+from zopeskel.base import BaseTemplate
+from zopeskel.base import get_var
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.base import BasicPackage
+from zopeskel.vars import StringVar, BooleanVar
+
+TARGET_STYLESHEETS = (
+    'base.css.dtml',
+    'generated.css.dtml',
+    'portlets.css.dtml',
+    'public.css.dtml'
+    )
+
+def cleanupStylsheets(skinsdir, targets=TARGET_STYLESHEETS):
+    for dirpath, dirnames, filenames in os.walk(skinsdir):
+        for target in [t for t in targets if t in filenames]:
+            print "Removing %s from %s%s" %(target, dirpath, os.sep)
+            os.remove(os.path.join(dirpath, target))
+
+
+theme_vars = [
+    StringVar(
+        'skinname',
+        title='Skin Name',
+        description='Name of the theme (human facing, added to portal_skins)',
+        modes=(EASY, EXPERT),
+        page='Main',
+        help="""
+This becomes the theme name (eg "My Theme").
+
+It appears as the skin name choice in portal_skins, and is generated into
+the GenericSetup profile.
+"""
+        ),
+
+    StringVar(
+        'skinbase',
+        title='Skin Base',
+        description='Name of the theme from which this is copied',
+        modes=(EXPERT,),
+        page='Main',
+        default='Plone Default',
+        help="""
+Themes can descend from other themes--by choosing a base theme here,
+your new theme will use the same skinpath ordering as this theme, except
+your theme-specific folders will appear at the top (right below 'custom').
+
+Typically, this will be 'Plone Default', the standard Plone theme.
+Unless you are certain what you are doing, keep this choice.
+"""
+        ),
+
+    BooleanVar('empty_styles',
+        title='Empty Styles?',
+        description='Override default public stylesheets with empty ones?',
+        modes=(EASY, EXPERT),
+        page='Main',
+        default=False,
+        help="""
+If this is not selected, your new theme will have the same CSS as the
+theme you are descending from (your skin base, answered above).
+
+If this is selected, your theme will have empty CSS files for several
+common 'public' areas--thereby starting you off with a theme that has
+less of the skin base's look and feel.
+
+Typically, if you are descending from Plone Default, this effectively
+hides some of the 'plone look and feel' from your theme; you'd then
+have to write CSS to provide more of your own look and feel.
+
+You can always refine the choice made here--to hide more of the base
+theme, create additional empty CSS files in your new theme to override
+other standard CSS files. To gain back some of the lost base look,
+you can just delete these overriding CSS files from your theme
+and the originals will now shine through.
+"""
+            ),
+
+    BooleanVar('include_doc',
+        title='Include Documentation?',
+        description="Include in-line documentation in generated code?",
+        modes=(EASY, EXPERT),
+        page="Main",
+        default=True,
+        help="""
+If selected, this adds verbose, helpful comments to the generated files.
+It does not change the appearance or functionality of the theme.
+These comments can always later be deleted.
+
+It is recommend you leave this on.
+"""
+        ),
+              ]
+
+class Plone2Theme(BaseTemplate):
+
+    # This does not descend from AbstractZope, since it's not
+    # a egg package, but just a raw Zope Product (unlike other
+    # templates)
+
+    _template_dir = 'templates/plone2_theme'
+    summary = "A theme for Plone 2.1"
+    ndots = 0
+    help = """
+This creates a project for a theme for Plone 2.1.
+
+This is not an egg, but a classic Product, and therefore is usable in
+Plone 2.1. This product should also work, without changes, in Plone
+2.5, though you may prefer to use the 'plone25_theme' template for
+this, as this will build an eggified Plone 2 theme.
+
+This template expects a name that is just the name of a classic
+product--a legal Python identifer without any dots in the name.
+"""
+    category = "Plone Development"
+
+    use_cheetah = True
+
+    vars = copy.deepcopy(BasicPackage.vars)
+    get_var(vars, 'description').default = 'An installable theme for Plone'
+    get_var(vars, 'keywords').default = 'web zope plone theme'
+    vars = theme_vars + vars[:3] + vars[4:6]
+
+    def pre(self, command, output_dir, vars):
+        if vars['skinname'] == '':
+            # It is always good to have a name for the skin.
+            vars['skinname'] = 'Custom Skin'
+        super(Plone2Theme, self).pre(command, output_dir, vars)
+
+    def post(self, command, output_dir, vars):
+        if str(vars['empty_styles']) == 'False':
+            cleanupStylsheets(os.path.join(output_dir, 'skins'))
+        super(Plone2Theme, self).post(command, output_dir, vars)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,68 @@
+import copy
+
+from zopeskel import abstract_buildout
+
+class Plone3Buildout(abstract_buildout.AbstractBuildout):
+    _template_dir = 'templates/plone3_buildout'
+    summary = "A buildout for Plone 3 installation"
+    help = """
+This template creates a Plone 3 buildout (for most users, a preferred
+way to get an installation of Plone 3 is to use the appropriate installer,
+as these are all buildout-based since Plone 3.1)
+"""
+    pre_run_msg = """
+*** NOTE: You probably don't want to use this template!
+
+Since Plone 3.1, the preferred way to get a buildout-based setup for
+Plone is to use the standard installer for your operating system (the
+Windows installer, the Mac installer, or the Unified Installer for
+Linux/Unix/BSD). These give you a best-practice, widely-used
+setup with an isolated Python and a well-documented buildout.
+This template is here for older versions of Plone and for experts
+who explicitly want a raw, non-installer-based installation.
+
+(This message is particularly aimed at people following out-of-date
+books/documentation that suggest this is the right way to get
+a Plone-based buildout. This is no longer the case.)
+"""
+
+    post_run_msg = """
+Generation finished.
+
+You probably want to run python bootstrap.py and then edit
+buildout.cfg before running bin/buildout -v".
+
+See README.txt for details.
+"""
+
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_buildout.AbstractBuildout.vars)
+    vars.extend(
+           [ abstract_buildout.VAR_PLONEVER,
+             abstract_buildout.VAR_Z2_INSTALL,
+             abstract_buildout.VAR_PLONE_PRODUCTS,
+             abstract_buildout.VAR_ZOPE_USER,
+             abstract_buildout.VAR_ZOPE_PASSWD,
+             abstract_buildout.VAR_HTTP,
+             abstract_buildout.VAR_DEBUG_MODE,
+             abstract_buildout.VAR_VERBOSE_SEC,
+        ]
+    )
+
+    def pre(self, command, output_dir, vars):
+        vars['tarballs'] = vars['plone_version'].startswith("3.0") or \
+                           vars['plone_version'].startswith("3.1")
+        vars['z29tarballs'] = vars['plone_version'].startswith("2.")
+        if vars['z29tarballs']:
+            vars['zope2_version'] = "2.9.12"
+        vars['eggifiedplone'] = not vars['z29tarballs'] and not vars['tarballs']
+        vars['eggifiedzope'] = vars['plone_version'].startswith("4.")
+        if vars['eggifiedzope']:
+            vars['zope2_install'] = True
+            vars['zope2_version'] = "2.12.3"
+        super(Plone3Buildout, self).pre(command, output_dir, vars)
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_portlet.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_portlet.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_portlet.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,59 @@
+import copy
+
+from zopeskel.plone_app import PloneApp
+from zopeskel.base import get_var
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import StringVar, DottedVar
+
+class Plone3Portlet(PloneApp):
+    _template_dir = 'templates/plone3_portlet'
+    summary = "A Plone 3 portlet"
+    help = """
+This creates a Plone project for a portlet.
+"""
+    required_templates = ['nested_namespace']
+    use_cheetah = True
+
+    vars = copy.deepcopy(PloneApp.vars)
+    get_var(vars, 'namespace_package').default = 'collective'
+    get_var(vars, 'namespace_package2').default = 'portlet'
+    vars.append(
+        StringVar(
+            'portlet_name',
+            title='Portlet Name',
+            description='Name of portlet (human readable)',
+            modes=(EASY,EXPERT),
+            default='Example Portlet',
+            help="""
+This becomes the human-readable title of the portlet.
+It gets generated in the GenericSetup profile file for the portlet.
+It appears in the Plone UI when managing portlets.
+"""
+        )
+        )
+    vars.append(
+        DottedVar(
+            'portlet_type_name',
+            title='Portlet Type Name',
+            description='Name of portlet type (actual name)',
+            modes=(EASY, EXPERT),
+            default='ExamplePortlet',
+            help="""
+This becomes the actual name of the portlet. It is not displayed
+in the Plone UI, but is the name it is registered under, and is
+used as the class name for the portlet, and is used in the
+generated GenericSetup profile.
+"""
+        )
+        )
+
+    def pre(self, command, output_dir, vars):
+        vars['zip_safe'] = False
+        vars['portlet_filename'] = vars['portlet_type_name'].lower()
+        vars['dotted_name'] = "%s.%s.%s" % (vars['namespace_package'],
+                                            vars['namespace_package2'],
+                                            vars['package'])
+
+        super(Plone3Portlet, self).pre(command, output_dir, vars)
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_theme.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_theme.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone3_theme.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+import copy
+import datetime
+
+from zopeskel.plone25_theme import Plone25Theme
+from zopeskel.base import get_var, EXPERT
+
+class Plone3Theme(Plone25Theme):
+    _template_dir = 'templates/plone3_theme'
+    summary = "A theme for Plone 3"
+    help = """
+This creates a project for a theme for Plone 3.
+"""
+    required_templates = ['plone']
+    use_cheetah = True
+
+    vars = copy.deepcopy(Plone25Theme.vars)
+    get_var(vars, 'namespace_package').default = 'plonetheme'
+    get_var(vars, 'description').default = 'An installable theme for Plone 3'
+    #add_profile should always default to True for theme packages
+    get_var(vars, 'add_profile').default = True
+    #add_profile need not appear as a question for theme packages
+    get_var(vars, 'add_profile').modes = ()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone4_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone4_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone4_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,58 @@
+import copy
+
+from zopeskel import abstract_buildout
+
+class Plone4Buildout(abstract_buildout.AbstractBuildout):
+    _template_dir = 'templates/plone4_buildout'
+    summary = "A buildout for Plone 4 developer installation"
+    help = """
+
+This template creates a Plone 4 buildout (for most users, a preferred
+way to get an installation of Plone is to use the appropriate installer,
+as these are all buildout-based since Plone 3.1)
+"""
+    pre_run_msg = """
+*** NOTE: You probably don't want to use this template!
+
+Since Plone 3.1, the preferred way to get a buildout-based setup for
+Plone is to use the standard installer for your operating system (the
+Windows installer, the Mac installer, or the Unified Installer for
+Linux/Unix/BSD). These give you a best-practice, widely-used
+setup with an isolated Python and a well-documented buildout.
+This template is here for older versions of Plone and for experts
+who explicitly want a raw, non-installer-based installation.
+
+(This message is particularly aimed at people following out-of-date
+books/documentation that suggest this is the right way to get
+a Plone-based buildout. This is no longer the case.)
+"""
+
+    post_run_msg = """
+Generation finished.
+
+You probably want to run python bootstrap.py and then edit
+buildout.cfg before running bin/buildout -v".
+
+See README.txt for details.
+"""
+
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_buildout.AbstractBuildout.vars)
+    vars.extend(
+           [ abstract_buildout.VAR_PLONEVER,           
+        ]
+    )
+    
+    # Set default Plone 4 version
+    vars[1].default = "4.0.1"
+    
+    def pre(self, command, output_dir, vars):
+        vars['eggifiedzope'] = True
+        vars['zope2_install'] = True
+        vars['zope2_version'] = "2.12.3"
+        super(Plone4Buildout, self).pre(command, output_dir, vars)
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_app.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_app.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_app.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+import copy
+
+from zopeskel.base import get_var
+from zopeskel.base import var
+from zopeskel import abstract_zope
+
+class PloneApp(abstract_zope.AbstractNestedZope):
+    _template_dir = 'templates/plone_app'
+    summary = "A project for Plone products with a nested namespace (2 dots in name)"
+    help = """
+This creates a Plone project (to create a Plone *site*, you probably
+want to use the one of the templates for a buildout).
+
+To create a Plone project with a name like 'mycompany.myproject' (1 dot,
+a 'basic namespace'), use the 'plone' template instead.
+"""
+    required_templates = ['nested_namespace']
+    use_cheetah = True
+    category = "Plone Development"
+
+    vars = copy.deepcopy(abstract_zope.AbstractNestedZope.vars)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_pas.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_pas.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/plone_pas.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+import copy
+
+from zopeskel import abstract_zope
+from zopeskel.base import get_var
+
+class PlonePas(abstract_zope.AbstractNestedZope):
+    _template_dir = 'templates/plone_pas'
+    summary = "A project for a Plone PAS plugin"
+    help = """
+This create a project for developing a PAS ('pluggable authentication
+system') plugin.
+"""
+    category = "Plone Development"
+    required_templates = ['nested_namespace']
+    use_cheetah = True
+    use_local_commands = True
+
+    vars = copy.deepcopy(abstract_zope.AbstractNestedZope.vars)
+    get_var(vars, 'namespace_package2').default = 'pas'
+
+    def pre(self, command, output_dir, vars):
+      vars['multiplugin_name'] = vars['package'].title()
+      super(PlonePas, self).pre(command, output_dir, vars)
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/recipe.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/recipe.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/recipe.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,19 @@
+import copy
+
+from zopeskel.nested_namespace import NestedNamespace
+from zopeskel.base import get_var
+
+class Recipe(NestedNamespace):
+    """A template for buildout recipes"""
+    _template_dir = 'templates/recipe'
+    summary = "A recipe project for zc.buildout"
+    help = """
+This creates a skeleton for a buildout recipe.
+"""
+    category = "Buildout"
+    required_templates = []
+    use_cheetah = True
+    vars = copy.deepcopy(NestedNamespace.vars)
+    get_var(vars, 'namespace_package2').default = 'recipe'
+    get_var(vars, 'license_name').default = 'ZPL'
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/silva_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/silva_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/silva_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+import copy
+
+from zopeskel import abstract_buildout
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import StringVar, StringChoiceVar
+
+
+class SilvaBuildout(abstract_buildout.AbstractBuildout):
+    _template_dir = 'templates/silva_buildout'
+    summary = "A buildout for Silva projects"
+    help = """
+This template creates an installation of Silva 
+(http://www.infrae.com/products/silva).
+"""
+    post_run_msg = """
+Generation finished.
+
+You probably want to run python bootstrap.py and then edit
+buildout.cfg before running bin/buildout -v".
+
+See README.txt for details.
+"""
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_buildout.AbstractBuildout.vars)
+    vars.extend([
+        abstract_buildout.VAR_Z2_INSTALL,
+        StringChoiceVar(
+            'silva_distribution',
+            title='Silva Distribution',
+            description='Version of Silva to install, "stable" or "development"',
+            default="stable",
+            modes=(EASY, EXPERT),
+            page='Main',
+            choices=('stable','development'),
+            ),
+        abstract_buildout.VAR_ZOPE_USER,
+        abstract_buildout.VAR_ZOPE_PASSWD,
+        abstract_buildout.VAR_HTTP,
+        abstract_buildout.VAR_DEBUG_MODE,
+        abstract_buildout.VAR_VERBOSE_SEC,
+        ]
+    )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,51 @@
+Introduction
+============
+
+This is a full-blown functional test. The emphasis here is on testing what
+the user may input and see, and the system is largely tested as a black box.
+We use PloneTestCase to set up this test as well, so we have a full Plone site
+to play with. We *can* inspect the state of the portal, e.g. using 
+self.portal and self.folder, but it is often frowned upon since you are not
+treating the system as a black box. Also, if you, for example, log in or set
+roles using calls like self.setRoles(), these are not reflected in the test
+browser, which runs as a separate session.
+
+Being a doctest, we can tell a story here.
+
+First, we must perform some setup. We use the testbrowser that is shipped
+with Five, as this provides proper Zope 2 integration. Most of the 
+documentation, though, is in the underlying zope.testbrower package.
+
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+    >>> portal_url = self.portal.absolute_url()
+
+The following is useful when writing and debugging testbrowser tests. It lets
+us see all error messages in the error_log.
+
+    >>> self.portal.error_log._ignored_exceptions = ()
+
+With that in place, we can go to the portal front page and log in. We will
+do this using the default user from PloneTestCase:
+
+    >>> from Products.PloneTestCase.setup import portal_owner, default_password
+
+Because add-on themes or products may remove or hide the login portlet, this test will use the login form that comes with plone.  
+
+    >>> browser.open(portal_url + '/login_form')
+    >>> browser.getControl(name='__ac_name').value = portal_owner
+    >>> browser.getControl(name='__ac_password').value = default_password
+    >>> browser.getControl(name='submit').click()
+
+Here, we set the value of the fields on the login form and then simulate a
+submit click.  We then ensure that we get the friendly logged-in message:
+
+    >>> "You are now logged in" in browser.contents
+    True
+
+Finally, let's return to the front page of our site before continuing
+
+    >>> browser.open(portal_url)
+
+-*- extra stuff goes here -*-
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,54 @@
+"""Main product initializer
+"""
+
+from zope.i18nmessageid import MessageFactory
+#if str($zope2product) == 'True'
+from ${namespace_package}.${package} import config
+
+from Products.Archetypes import atapi
+from Products.CMFCore import utils
+#end if
+
+\# Define a message factory for when this product is internationalised.
+\# This will be imported with the special name "_" in most modules. Strings
+\# like _(u"message") will then be extracted by i18n tools for translation.
+
+${package}MessageFactory = MessageFactory('${namespace_package}.${package}')
+#if str($zope2product) == 'True'
+
+
+def initialize(context):
+    """Initializer called when used as a Zope 2 product.
+
+    This is referenced from configure.zcml. Regstrations as a "Zope 2 product"
+    is necessary for GenericSetup profiles to work, for example.
+
+    Here, we call the Archetypes machinery to register our content types
+    with Zope and the CMF.
+    """
+
+    # Retrieve the content types that have been registered with Archetypes
+    # This happens when the content type is imported and the registerType()
+    # call in the content type's module is invoked. Actually, this happens
+    # during ZCML processing, but we do it here again to be explicit. Of
+    # course, even if we import the module several times, it is only run
+    # once.
+
+    content_types, constructors, ftis = atapi.process_types(
+        atapi.listTypes(config.PROJECTNAME),
+        config.PROJECTNAME)
+
+    # Now initialize all these content types. The initialization process takes
+    # care of registering low-level Zope 2 factories, including the relevant
+    # add-permission. These are listed in config.py. We use different
+    # permissions for each content type to allow maximum flexibility of who
+    # can add which content types, where. The roles are set up in rolemap.xml
+    # in the GenericSetup profile.
+
+    for atype, constructor in zip(content_types, constructors):
+        utils.ContentInit('%s: %s' % (config.PROJECTNAME, atype.portal_type),
+            content_types=(atype, ),
+            permission=config.ADD_PERMISSIONS[atype.portal_type],
+            extra_constructors=(constructor,),
+            ).initialize(context)
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/browser/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="${namespace_package}.${package}">
+
+  <include package="plone.app.contentmenu" />
+
+  <!-- -*- extra stuff goes here -*- -->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/config.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/config.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/config.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+"""Common configuration constants
+"""
+
+PROJECTNAME = '${namespace_package}.${package}'
+
+ADD_PERMISSIONS = {
+    # -*- extra stuff goes here -*-
+}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+#if str($add_profile) == 'True'
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+#end if
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    i18n_domain="${namespace_package}.${package}">
+    
+#if str($zope2product) == 'True'
+  <five:registerPackage package="." initialize=".initialize" />
+#end if
+
+  <!-- Include the sub-packages that use their own configure.zcml files. -->
+  <include package=".browser" />
+  <include package=".content" />
+  <include package=".portlets" />
+  
+#if str($add_profile) == 'True'
+  <!-- Register the installation GenericSetup extension profile -->
+  <genericsetup:registerProfile
+      name="default"
+      title="${title}"
+      directory="profiles/default"
+      description="${description}"
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+#end if
+  
+  <!-- -*- extra stuff goes here -*- -->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/content/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    i18n_domain="${namespace_package}.${package}">
+
+  <!-- configure your content components here -->
+  
+  <!-- -*- extra stuff goes here -*- -->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/interfaces/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+# -*- extra stuff goes here -*-

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/portlets/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,12 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:plone="http://namespaces.plone.org/plone"
+    i18n_domain="${namespace_package}.${package}">
+
+  <!-- Ensure Plone's portlets ZCML has already been processed;
+       without this, we may get a permission lookup error -->
+  <include package="plone.app.portlets" />
+
+	<!-- -*- extra stuff goes here -*- -->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/factorytool.xml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/factorytool.xml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/factorytool.xml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+<!-- This import step informs the portal_factory tool that we want it to
+     manage our content types. This tool deals with the fact that in
+     Archetypes and most CMF types, the object is actually created before
+     the first edit form is filled in. That is, there are no true "add forms".
+     The factory tool creates a temporary object in lieu of an "add form",
+     and then moves the object to the proper location after it has been
+     successfully saved.
+  -->
+<object name="portal_factory" meta_type="Plone Factory Tool">
+  <factorytypes>
+    <!-- -*- extra stuff goes here -*- -->
+  </factorytypes>
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>1000</version>
+</metadata>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/portlets.xml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/portlets.xml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/portlets.xml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+<?xml version="1.0"?>
+<!-- This file is used to register new types of portlets. It can also
+     be used to register completely new column types. See CMFPlone's version
+     of this file for more information.
+  -->
+<portlets
+    xmlns:i18n="http://xml.zope.org/namespaces/i18n"
+    i18n:domain="plone">
+  <!-- -*- extra stuff goes here -*- -->
+</portlets>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/types.xml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/types.xml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/profiles/default/types.xml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<!-- This file registers new types with portal_types. The types are
+     then configured with the corresponding files in types/*.xml. Note
+     that spaces are allowed in type names, but the corresponding XML file
+     uses an underscore instead. The "Factory-based Type Information with
+     dynamic views" refers to an FTI from Products.CMFDynamicViewFTI,
+     which supports Plone's "display" menu.
+  -->
+<object name="portal_types" meta_type="Plone Types Tool">
+  <!-- -*- extra stuff goes here -*- -->
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/base.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/base.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/base.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,87 @@
+"""Test setup for integration and functional tests.
+
+When we import PloneTestCase and then call setupPloneSite(), all of
+Plone's products are loaded, and a Plone site will be created. This
+happens at module level, which makes it faster to run each test, but
+slows down test runner startup.
+"""
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+
+from Testing import ZopeTestCase as ztc
+
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import onsetup
+
+# When ZopeTestCase configures Zope, it will *not* auto-load products
+# in Products/. Instead, we have to use a statement such as:
+#
+#   ztc.installProduct('SimpleAttachment')
+#
+# This does *not* apply to products in eggs and Python packages (i.e.
+# not in the Products.*) namespace. For that, see below.
+#
+# All of Plone's products are already set up by PloneTestCase.
+
+
+ at onsetup
+def setup_product():
+    """Set up the package and its dependencies.
+
+    The @onsetup decorator causes the execution of this body to be
+    deferred until the setup of the Plone site testing layer. We could
+    have created our own layer, but this is the easiest way for Plone
+    integration tests.
+    """
+
+    # Load the ZCML configuration for the example.tests package.
+    # This can of course use <include /> to include other packages.
+
+    fiveconfigure.debug_mode = True
+    import ${namespace_package}.${package}
+    zcml.load_config('configure.zcml', ${namespace_package}.${package})
+    fiveconfigure.debug_mode = False
+
+    # We need to tell the testing framework that these products
+    # should be available. This can't happen until after we have loaded
+    # the ZCML. Thus, we do it here. Note the use of installPackage()
+    # instead of installProduct().
+    # 
+    # This is *only* necessary for packages outside the Products.*
+    # namespace which are also declared as Zope 2 products, using
+    # <five:registerPackage /> in ZCML.
+
+    # We may also need to load dependencies, e.g.:
+    # 
+    #   ztc.installPackage('borg.localrole')
+    # 
+
+    ztc.installPackage('${namespace_package}.${package}')
+
+# The order here is important: We first call the (deferred) function
+# which installs the products we need for this product. Then, we let
+# PloneTestCase set up this product on installation.
+
+setup_product()
+ptc.setupPloneSite(products=['${namespace_package}.${package}'])
+
+
+class TestCase(ptc.PloneTestCase):
+    """We use this base class for all the tests in this package. If
+    necessary, we can put common utility or setup code in here. This
+    applies to unit test cases.
+    """
+
+
+class FunctionalTestCase(ptc.FunctionalTestCase):
+    """We use this class for functional integration tests that use
+    doctest syntax. Again, we can put basic common utility or setup
+    code in here.
+    """
+
+    def afterSetUp(self):
+        roles = ('Member', 'Contributor')
+        self.portal.portal_membership.addMember('contributor',
+                                                'secret',
+                                                roles, [])

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/test_doctest.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/test_doctest.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/+namespace_package+/+package+/tests/test_doctest.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,25 @@
+import unittest
+import doctest
+
+\#from zope.testing import doctestunit
+\#from zope.component import testing, eventtesting
+
+from Testing import ZopeTestCase as ztc
+
+from ${namespace_package}.${package}.tests import base
+
+
+def test_suite():
+    return unittest.TestSuite([
+
+        # Demonstrate the main content types
+        ztc.ZopeDocFileSuite(
+            'README.txt', package='${namespace_package}.${package}',
+            test_class=base.FunctionalTestCase,
+            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE |
+                doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CHANGES.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CHANGES.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CHANGES.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+Changelog
+=========
+
+#set $header_text = "%s (xxxx-xx-xx)" % $version or "0.0.0"
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+- Created recipe with ZopeSkel
+  [${$author or $empty}]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CONTRIBUTORS.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CONTRIBUTORS.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/CONTRIBUTORS.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+${$author or $empty}, Author
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/MANIFEST.in_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/MANIFEST.in_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/MANIFEST.in_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+recursive-include ${namespace_package} *
+global-exclude *pyc
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+.. contents::
+
+.. Note!
+   -----
+   Update the following URLs to point to your:
+
+   - code repository
+   - bug tracker
+   - questions/comments feedback mail
+   (do not set a real mail, to avoid spams)
+
+   Or remove it if not used.
+
+- Code repository: http://svn.somewhere.com/...
+- Questions and comments to somemailing_list
+- Report bugs at http://bug.somewhere.com/..
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/archetype/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+"""
+This module contains the tool of $project
+"""
+import os
+from setuptools import setup, find_packages
+
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = ${repr($version) or "0.0.0"}
+
+long_description = (
+    read('README.txt')
+    + '\n' +
+    'Change history\n'
+    '**************\n'
+    + '\n' +
+    read('CHANGES.txt')
+    + '\n' +
+    'Detailed Documentation\n'
+    '**********************\n'
+    + '\n' +
+    read(${repr($namespace_package)}, ${repr($package)}, 'README.txt')
+    + '\n' +
+    'Contributors\n'
+    '************\n'
+    + '\n' +
+    read('CONTRIBUTORS.txt')
+    + '\n' +
+    'Download\n'
+    '********\n')
+
+tests_require = ['zope.testing']
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=long_description,
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        'Framework :: Plone',
+        'Intended Audience :: Developers',
+        #from zopeskel.base import LICENSE_CATEGORIES
+        #if $license_name.strip() in $LICENSE_CATEGORIES
+        $repr($LICENSE_CATEGORIES[$license_name.strip()]),
+        #end if
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', ],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=['setuptools',
+                        # -*- Extra requirements: -*-
+                        ],
+      tests_require=tests_require,
+      extras_require=dict(tests=tests_require),
+      test_suite='$namespace_package.${package}.tests.test_docs.test_suite',
+      entry_points="""
+      # -*- entry_points -*-#
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      setup_requires=["PasteScript"],
+      paster_plugins=["ZopeSkel"],
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/+namespace_package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+Introduction
+============
+
+${long_description or None}
+
+This product may contain traces of nuts.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/docs/HISTORY.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/docs/HISTORY.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/docs/HISTORY.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+Changelog
+=========
+
+#set $header_text = "%sdev (unreleased)" % $version
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+- Initial release

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_namespace/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=[${repr($namespace_package)}],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+${project} Package Readme
+=========================
+
+Overview
+--------
+
+$description
+
+
+Your tests here
+---------------
+
+    >>> 1 + 1
+    3

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five">
+
+#if str($zope2product) == 'True'
+  <five:registerPackage package="." initialize=".zope2.initialize" />
+#end if
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/tests.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/tests.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/tests.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+import unittest
+
+from zope.testing import doctestunit
+from zope.component import testing
+from Testing import ZopeTestCase as ztc
+
+def test_suite():
+    return unittest.TestSuite([
+
+        # Unit tests for your API
+        doctestunit.DocFileSuite(
+            'README.txt', package='${namespace_package}.${package}',
+            setUp=testing.setUp, tearDown=testing.tearDown),
+
+        #doctestunit.DocTestSuite(
+        #    module='${namespace_package}.${package}.mymodule',
+        #    setUp=testing.setUp, tearDown=testing.tearDown),
+
+        # Integration tests that use ZopeTestCase
+        #ztc.ZopeDocFileSuite(
+        #    'README.txt', package='${namespace_package}.${package}',
+        #    setUp=testing.setUp, tearDown=testing.tearDown),
+
+        #ztc.FunctionalDocFileSuite(
+        #    'browser.txt', package='${namespace_package}.${package}'),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/zope2.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/zope2.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/+package+/zope2.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+#
+
+#if str($zope2product) == 'True'
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+namespace_package+/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+project+-configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+project+-configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/basic_zope/+project+-configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+<include package="${package}" />
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/+namespace_package+.+namespace_package2+.+package+-configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/+namespace_package+.+namespace_package2+.+package+-configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/+namespace_package+.+namespace_package2+.+package+-configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+<include package="${namespace_package}.${namespace_package2}.${package}" />

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    xmlns:kss="http://namespaces.zope.org/kss"
+    xmlns:zcml="http://namespaces.zope.org/zcml">
+
+  <!-- Including this configuration will activate this plugin inside zope. -->
+  
+  <!-- Include demo setup conditionally -->
+  <include zcml:condition="installed kss.demo" package=".demo" />
+  
+  <!-- Third party library dependencies -->
+  
+  <!--
+  <browser:resource
+      file="3rd_party/myfile.js"
+      name="myfile.js"
+      />
+  -->
+  
+  <!-- Event types -->
+  
+  <!--
+  <kss:eventtype
+      name="${package}-myevent"
+      jsfile="javascript/myfile.js"
+      />
+  -->
+  
+  <!-- Client actions & commands -->
+  
+  <!--
+  <kss:action
+      name="${package}-myaction"
+      jsfile="javascript/myfile.js"
+      command_factory="selector"
+      params_mandatory=""
+      params_optional=""
+      />
+  -->
+  
+  <!-- Command sets -->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.kss
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.kss	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.kss	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+# fill in your kss rules in here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.pt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.pt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/+package+.pt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+<html tal:define="viewname string:${package}">
+  <head>
+    <!-- add your third party resources here -->
+
+    <!-- link rel="stylesheet" type="text/css"
+          tal:attributes="href string:\${context/@@absolute_url}/++resource++${package}.css"/-->
+
+    <metal:header use-macro="context/@@header_macros/header_resources" />
+
+  </head>
+  <body>
+    <p metal:use-macro="context/@@body_macros/header">header</p>
+    <!-- START of demo content -->
+
+    <h2>Demo of ${package}:</h2>
+    <div id="description">${description}</div>
+  </body>
+</html>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+<configure xmlns="http://namespaces.zope.org/zope"
+           xmlns:browser="http://namespaces.zope.org/browser"
+           xmlns:kss="http://namespaces.zope.org/kss"
+           i18n_domain="kss"
+           >
+
+  <!-- Set up the demo utility, needed for registration -->
+  <!-- utility
+    name="${package}"
+    factory=".zopeconfig.KSSDemos"
+    provides="kss.demo.interfaces.IKSSDemoResource"
+    permission="zope.Public"
+    /-->
+
+  <!-- Set up resources needed for the demo -->
+  <!-- browser:page
+      for="kss.demo.interfaces.ISimpleContent"
+      template="${package}.pt"
+      name="${package}.html"
+      permission="zope2.View"
+      /-->
+
+  <browser:resource
+    file="${package}.kss"
+    name="${package}.kss"
+    />
+
+  <!-- browser:resource
+    file="${package}.css"
+    name="${package}.css"
+    /-->
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/zopeconfig.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/zopeconfig.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/demo/zopeconfig.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,33 @@
+from kss.demo.interfaces import (
+    IKSSDemoResource,
+    IKSSSeleniumTestResource,
+    )
+from kss.demo.resource import (
+    KSSDemo,
+    KSSSeleniumTestDirectory,
+    )
+from zope.interface import implements
+
+# Create a mesh of provided interfaces
+# This is needed, because an utility must have a single interface.
+class IResource(IKSSDemoResource, IKSSSeleniumTestResource):
+    pass
+
+# XXX you do not need to change anything above here
+# -------------------------------------------------
+
+class KSSDemos(object):
+    implements(IResource)
+
+    demos = (
+        # List your demos here.
+        # (Second parameter can be a subcategory within the demo if needed.)
+        #KSSDemo('${package}', '', '${package}.html', 'Demo Title (to edit!)'),
+        )
+
+    # directories are relative from the location of this .py file
+    selenium_tests = (
+        # if you only have one test directory, you
+        # need not change anything here.
+        #KSSSeleniumTestDirectory('selenium_tests'),
+        )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/+package+.js_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/+package+.js_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/+package+/javascript/+package+.js_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2007
+ * Authors: KSS Project Contributors (see docs/CREDITS.txt)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+kukit.${package} = {};
+
+
+/*    kukit.eventsGlobalRegistry.registerForAllEvents(
+            '${package}', ['dragstart', 'dragsuccess', 'dragfailure'],
+            EventBinder, '__bind_drag__', null, 'Node');
+      kukit.eventsGlobalRegistry.registerForAllEvents(
+            '${package}', ['drop'],
+            EventBinder, '__bind_drop__', null, 'Node');
+*/

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/+namespace_package2+/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/+namespace_package+/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/kss_plugin/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,39 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Framework :: Plone",
+        "Framework :: Zope2",
+        "Framework :: Zope3",
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=[
+          'setuptools',
+          'kss.core'
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/+namespace_package2+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/+namespace_package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+Introduction
+============
+
+${long_description or None}
+
+This product may contain traces of nuts.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/docs/HISTORY.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/docs/HISTORY.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/docs/HISTORY.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+Changelog
+=========
+
+#set $header_text = "%sdev (unreleased)" % $version
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+- Initial release

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/nested_namespace/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,32 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+  # -*- extra stuff goes here -*- 
+
+#if str($zope2product) == 'True'
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+#end if
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,25 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+#if str($add_profile) == 'True'
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+#end if
+    i18n_domain="${namespace_package}.${package}">
+
+#if str($zope2product) == 'True' and $namespace_package != 'Products'
+  <five:registerPackage package="." initialize=".initialize" />
+#end if
+
+#if str($add_profile) == 'True'
+  <genericsetup:registerProfile
+      name="default"
+      title="${namespace_package}.${package}"
+      directory="profiles/default"
+      description="Installs the ${namespace_package}.${package} package"
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+#end if
+  <!-- -*- extra stuff goes here -*- -->
+  
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>1000</version>
+</metadata>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/+namespace_package+/+package+/tests.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,63 @@
+import unittest
+
+\#from zope.testing import doctestunit
+\#from zope.component import testing
+from Testing import ZopeTestCase as ztc
+
+#if str($zope2product) != 'True'
+from Products.Five import zcml
+#end if
+from Products.Five import fiveconfigure
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import PloneSite
+ptc.setupPloneSite()
+
+import ${namespace_package}.${package}
+
+
+class TestCase(ptc.PloneTestCase):
+
+    class layer(PloneSite):
+
+        @classmethod
+        def setUp(cls):
+            fiveconfigure.debug_mode = True
+            #if str($zope2product) == 'True'
+            ztc.installPackage(${namespace_package}.${package})
+            #else
+            zcml.load_config('configure.zcml',
+                             ${namespace_package}.${package})
+            #end if
+            fiveconfigure.debug_mode = False
+
+        @classmethod
+        def tearDown(cls):
+            pass
+
+
+def test_suite():
+    return unittest.TestSuite([
+
+        \# Unit tests
+        \#doctestunit.DocFileSuite(
+        \#    'README.txt', package='${namespace_package}.${package}',
+        \#    setUp=testing.setUp, tearDown=testing.tearDown),
+
+        \#doctestunit.DocTestSuite(
+        \#    module='${namespace_package}.${package}.mymodule',
+        \#    setUp=testing.setUp, tearDown=testing.tearDown),
+
+
+        \# Integration tests that use PloneTestCase
+        \#ztc.ZopeDocFileSuite(
+        \#    'README.txt', package='${namespace_package}.${package}',
+        \#    test_class=TestCase),
+
+        \#ztc.FunctionalDocFileSuite(
+        \#    'browser.txt', package='${namespace_package}.${package}',
+        \#    test_class=TestCase),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/INSTALL.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/INSTALL.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/INSTALL.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,72 @@
+#set $full_package_name = "%s.%s" % ($namespace_package, $package)
+#set $header_text = "%s Installation" % $project
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+To install ${project} into the global Python environment (or a workingenv),
+using a traditional Zope 2 instance, you can do this:
+
+* When you're reading this you have probably already run 
+  ``easy_install ${project}``. Find out how to install setuptools
+  (and EasyInstall) here:
+  http://peak.telecommunity.com/DevCenter/EasyInstall
+
+#if str($zope2product) == 'True'
+* If you are using Zope 2.9 (not 2.10), get `pythonproducts`_ and install it 
+  via::
+
+    python setup.py install --home /path/to/instance
+
+into your Zope instance.
+
+#end if
+* Create a file called ``${project}-configure.zcml`` in the
+  ``/path/to/instance/etc/package-includes`` directory.  The file
+  should only contain this::
+
+    <include package="${full_package_name}" />
+
+#if str($zope2product) == 'True'
+.. _pythonproducts: http://plone.org/products/pythonproducts
+
+#end if
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+* Add ``${project}`` to the list of eggs to install, e.g.:
+
+    [buildout]
+    ...
+    eggs =
+        ...
+        ${project}
+       
+* Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        ${full_package_name}
+      
+* Re-run buildout, e.g. with:
+
+    $ ./bin/buildout
+        
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.
+#if str($zope2product) == 'True' and $namespace_package == 'Products'
+
+
+Because its top level Python namespace package is called ``Products``, this
+package can also be installed in Zope 2 as an old style **Zope 2 Product**.
+
+For that, move (or symlink) the ``$package`` folder of this project
+(``$project/$namespace_package/$package``) into the ``Products`` directory of
+the Zope instance it has to be installed for, and restart the server.
+
+You can also skip the ZCML slug if you install this package the **Zope 2
+Product** way.
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.GPL
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.GPL	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.GPL	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/docs/LICENSE.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+  ${project} is copyright $author
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston, 
+  MA 02111-1307 USA.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,38 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Framework :: Plone",
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=[${repr($namespace_package)}],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      setup_requires=["PasteScript"],
+      paster_plugins=["ZopeSkel"],
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_buildout/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_buildout/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_buildout/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,327 @@
+=======================
+Using a custom buildout
+=======================
+
+Note: If you are using Windows, if you do not have PIL installed, or you are
+not using Python 2.4 as your main system Python, please see the relevant
+sections below.
+
+You probably got here by running something like:
+
+ $ paster create -t plone3_buildout
+
+Now, you need to run:
+
+ $ python bootstrap.py
+
+This will install zc.buildout for you.
+
+To create an instance immediately, run:
+
+ $ bin/buildout
+
+This will download Plone's products for you, as well as other dependencies,
+create a new Zope 2 installation (unless you specified an existing one when
+you ran "paster create"), and create a new Zope instance configured with these
+products.
+
+You can start your Zope instance by running:
+
+ $ bin/instance start
+
+or, to run in foreground mode:
+
+ $ bin/instance fg
+
+To run unit tests, you can use:
+
+ $ bin/instance test -s my.package
+
+Installing PIL
+--------------
+
+To use Plone, you need PIL, the Python Imaging Library. If you don't already
+have this, download and install it from http://www.pythonware.com/products/pil.
+
+Using a different Python installation
+--------------------------------------
+
+Buildout will use your system Python installation by default. However, Zope
+2.10 (and by extension, Plone) will only work with Python 2.4. You can verify
+which version of Python you have, by running:
+
+ $ python -V
+
+If that is not a 2.4 version, you need to install Python 2.4 from
+http://python.org. If you wish to keep another version as your main system
+Python, edit buildout.cfg and add an 'executable' option to the "[buildout]"
+section, pointing to a python interpreter binary:
+
+ [buildout]
+ ...
+ executable = /path/to/python
+
+Working with buildout.cfg
+-------------------------
+
+You can change any option in buildout.cfg and re-run bin/buildout to reflect
+the changes. This may delete things inside the 'parts' directory, but should
+keep your Data.fs and source files intact.
+
+To save time, you can run buildout in "offline" (-o) and non-updating (-N)
+mode, which will prevent it from downloading things and checking for new
+versions online:
+
+ $ bin/buildout -Nov
+
+Creating new eggs
+-----------------
+
+New packages you are working on (but which are not yet released as eggs and
+uploaded to the Python Package Index, aka PYPI) should be placed in src. You can do:
+
+ $ cd src/
+ $ paster create -t plone my.package
+
+Use "paster create --list-templates" to see all available templates. Answer
+the questions and you will get a new egg. Then tell buildout about your egg
+by editing buildout.cfg and adding your source directory to 'develop':
+
+ [buildout]
+ ...
+ develop =
+    src/my.package
+
+You can list multiple packages here, separated by whitespace or indented
+newlines.
+
+You probably also want the Zope instance to know about the package. Add its
+package name to the list of eggs in the "[instance]" section, or under the
+main "[buildout]" section:
+
+ [instance]
+ ...
+ eggs =
+    ${buildout:eggs}
+    ${plone:eggs}
+    my.package
+
+Leave the ${buildout:eggs} part in place - it tells the instance to use the
+eggs that buildout will have downloaded from the Python Package Index
+previously.
+
+If you also require a ZCML slug for your package, buildout can create one
+automatically. Just add the package to the 'zcml' option:
+
+ [instance]
+ ...
+ zcml =
+    my.package
+
+When you are finished, re-run buildout. Offline, non-updating mode should
+suffice:
+
+ $ bin/buildout -Nov
+
+Developing old-style products
+-----------------------------
+
+If you are developing old-style Zope 2 products (not eggs) then you can do so
+by placing the product code in the top-level 'products' directory. This is
+analogous to the 'Products/' directory inside a normal Zope 2 instance and is
+scanned on start-up for new products.
+
+Depending on a new egg
+----------------------
+
+If you want to use a new egg that is in the Python Package Index, all you need
+to do is to add it to the "eggs" option under the main "[buildout]" section:
+
+ [buildout]
+ ...
+ eggs =
+    my.package
+
+If it's listed somewhere else than the Python Package Index, you can add a link
+telling buildout where to find it in the 'find-links' option:
+
+ [buildout]
+ ...
+ find-links =
+    http://dist.plone.org
+    http://download.zope.org/distribution/
+    http://effbot.org/downloads
+    http://some.host.com/packages
+
+Using existing old-style products
+---------------------------------
+
+If you are using an old-style (non-egg) product, you can either add it as an
+automatically downloaded archive or put it in the top-level "products" folder.
+The former is probably better, because it means you can redistribute your
+buildout.cfg more easily:
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+
+If someproduct-1.3.tar.gz extracts into several products inside a top-level
+directory, e.g. SomeProduct-1.3/PartOne and SomeProduct-1.3/PartTwo, then
+add it as a "nested package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ nested-packages =
+    someproduct-1.3.tar.gz
+
+Alternatively, if it extracts to a directory which contains the version
+number, add it as a "version suffix package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ version-suffix-packages =
+    someproduct-1.3.tar.gz
+
+You can also track products by adding a new bundle checkout part. It
+doesn't strictly have to be an svn bundle at all, any svn location will do,
+and cvs is also supported:
+
+ [buildout]
+ ...
+ parts =
+    plone
+    zope2
+    productdistros
+    myproduct
+    instance
+    zopepy
+
+Note that "myproduct" comes before the "instance" part. You then
+need to add a new section to buildout.cfg:
+
+ [myproduct]
+ recipe = plone.recipe.bundlecheckout
+ url = http://svn.plone.org/svn/collective/myproduct/trunk
+
+Finally, you need to tell Zope to find this new checkout and add it to its
+list of directories that are scanned for products:
+
+ [instance]
+ ...
+ products =
+    ${buildout:directory}/products
+    ${productdistros:location}
+    ${plonebundle:location}
+    ${myproduct:location}
+
+Without this last step, the "myproduct" part is simply managing an svn
+checkout and could potentially be used for something else instead.
+
+=============
+Using Windows
+=============
+
+To use buildout on Windows, you will need to install a few dependencies which
+other platforms manage on their own.
+
+Here are the steps you need to follow (thanks to Hanno Schlichting for these):
+
+Python (http://python.org)
+--------------------------
+
+  - Download and install Python 2.4.4 using the Windows installer from
+    http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi
+    Select 'Install for all users' and it will put Python into the
+    "C:\Python24" folder by default.
+
+  - You also want the pywin32 extensions available from
+    http://downloads.sourceforge.net/pywin32/pywin32-210.win32-py2.4.exe?modtime=1159009237&big_mirror=0
+
+  - And as a last step you want to download the Python imaging library available
+    from http://effbot.org/downloads/PIL-1.1.6.win32-py2.4.exe
+
+  - If you develop Zope based applications you will usually only need Python 2.4
+    at the moment, so it's easiest to put the Python binary on the systems PATH,
+    so you don't need to specify its location manually each time you call it.
+
+    Thus, put "C:\Python24" and "C:\Python24\Scripts" onto the PATH. You can
+    find the PATH definition in the control panel under system preferences on
+    the advanced tab at the bottom. The button is called environment variables.
+    You want to add it at the end of the already existing PATH in the system
+    section. Paths are separated by a semicolons.
+
+  - You can test if this was successful by opening a new shell (cmd) and type
+    in 'python -V'. It should report version 2.4.4 (or whichever version you
+    installed).
+
+    Opening a new shell can be done quickly by using the key combination
+    'Windows-r' or if you are using Parallels on a Mac 'Apple-r'. Type in 'cmd'
+    into the popup box that opens up and hit enter.
+
+
+Subversion (http://subversion.tigris.org)
+-----------------------------------------
+
+  - Download the nice installer from
+    http://subversion.tigris.org/files/documents/15/35379/svn-1.4.2-setup.exe
+
+  - Run the installer. It defaults to installing into
+    "C:\Program Files\Subversion".
+
+  - Now put the install locations bin subfolder (for example
+    "C:\Program Files\Subversion\bin") on your system PATH in the same way you
+    put Python on it.
+
+  - Open a new shell again and type in: 'svn --version' it should report
+    version 1.4.2 or newer.
+
+
+MinGW (http://www.mingw.org/)
+-----------------------------
+
+  This is a native port of the gcc compiler and its dependencies for Windows.
+  There are other approaches enabling you to compile Python C extensions on
+  Windows including Cygwin and using the official Microsoft C compiler, but this
+  is a lightweight approach that uses only freely available tools. As
+  it's used by a lot of people chances are high it will work for you and there's
+  plenty of documentation out there to help you in troubleshooting problems.
+
+  - Download the MinGW installer from
+    http://downloads.sourceforge.net/mingw/MinGW-5.1.3.exe?modtime=1168794334&big_mirror=1
+
+  - The installer will ask you which options you would like to install. Choose
+    base and make here. It will install into "C:\MinGW" by default. The install
+    might take some time as it's getting files from sourceforge.net and you
+    might need to hit 'retry' a couple of times.
+
+  - Now put the install location's bin subfolder (for example "C:\MinGW\bin") on
+    your system PATH in the same way you put Python on it.
+
+  - Test this again by typing in: 'gcc --version' on a newly opened shell and
+    it should report version 3.4.2 or newer.
+
+
+Configure Distutils to use MinGW
+--------------------------------
+
+  Some general information are available from
+  http://www.mingw.org/MinGWiki/index.php/Python%20extensions for example but
+  you don't need to read them all.
+
+  - Create a file called 'distutils.cfg' in "C:\Python24\Lib\distutils". Open it
+    with a text editor ('notepad distutils.cfg') and fill in the following lines:
+
+    [build]
+    compiler=mingw32
+
+    This will tell distutils to use MinGW as the default compiler, so you don't
+    need to specify it manually using "--compiler=mingw32" while calling a
+    package's setup.py with a command that involves building C extensions. This
+    is extremely useful if the build command is written down in a buildout
+    recipe where you cannot change the options without hacking the recipe
+    itself. The z2c.recipe.zope2install used in ploneout is one such example.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/Install.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/Install.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/Install.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+from Products.CMFCore.utils import getToolByName
+
+def install(portal):
+    setup_tool = getToolByName(portal, 'portal_setup')
+    originalContext = setup_tool.getImportContextID()
+    setup_tool.setImportContext('profile-${namespace_package}.${package}:default')
+    setup_tool.runAllImportSteps()
+    setup_tool.setImportContext(originalContext)
+    return "Ran all import steps."
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/Extensions/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+# this file is here to make importable the modules stored in the product
+# 'Extensions' folder.
+# keep these lines to make it non-zero size and have winzip cooperate.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+\# Register our skins directory - this makes it available via portal_skins.
+from Products.CMFCore.DirectoryView import registerDirectory
+from config import GLOBALS
+#if $namespace_package == "Products"
+
+registerDirectory('skins', GLOBALS)
+#else
+
+from Products.CMFCore import utils
+from Globals import package_home
+from os.path import dirname
+
+\# temporarily add the path to the namespace package to the products path,
+\# so that the directory views are set up correctly
+ppath = utils.ProductsPath
+utils.ProductsPath.append(dirname(package_home(GLOBALS)))
+registerDirectory('skins', GLOBALS)
+utils.ProductsPath = ppath
+#end if
+#if str($zope2product) == 'True'
+
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/config.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/config.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/config.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+GLOBALS = globals()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,15 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    i18n_domain="${namespace_package}.${package}">
+
+  <include package="Products.GenericSetup" file="meta.zcml" />
+
+#if str($zope2product) == 'True'
+  <!-- Note: this needs at least Five 1.4. -->
+  <five:registerPackage package="." initialize=".initialize" />
+
+#end if
+  <include file="profiles.zcml" />
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_css tool. -->
+
+#end if
+<object name="portal_css" meta_type="Stylesheets Registry">
+
+#if str($include_doc) == 'True'
+ <!-- Stylesheets that will be registered with the portal_css tool are defined
+      here. You can also specify values for existing resources if you need to
+      modify some of their properties.
+      Stylesheet elements accept these parameters:
+      - 'id' (required): it must respect the name of the css or DTML file
+        (case sensitive). '.dtml' suffixes must be ignored.
+      - 'expression' (optional - default: ''): a tal condition.
+      - 'media' (optional - default: ''): possible values: 'screen', 'print',
+        'projection', 'handheld'...
+      - 'rel' (optional - default: 'stylesheet')
+      - 'title' (optional - default: '')
+      - 'rendering' (optional - default: 'import'): 'import', 'link' or
+        'inline'.
+      - 'enabled' (optional - default: True): boolean
+      - 'cookable' (optional - default: True): boolean (aka 'merging allowed')
+      - 'insert_before', 'insert_after' (optional - default: '') resource id
+      See registerStylesheet() arguments in
+      ResourceRegistries/tools/CSSRegistry.py for the latest list of all
+      available keys and default values.
+   -->
+#end if
+ <stylesheet title="" cacheable="True" compression="safe" cookable="True"
+    enabled="1" expression="" id="${package}.css" media="screen"
+    rel="stylesheet" rendering="import"/>
+
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/import_steps.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/import_steps.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/import_steps.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,11 @@
+<?xml version="1.0"?>
+<import-steps>
+  <import-step id="${package}_various"
+               version="20070220-01"
+               handler="${namespace_package}.${package}.setuphandlers.setupVarious"
+               title="${skinname}: miscellaneous import steps">
+    <dependency step="skins" />
+    Various import steps that are not handled by GS import/export
+    handlers.
+  </import-step>
+</import-steps>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_javascripts tool.
+  -->
+
+#end if
+<object name="portal_javascripts">
+
+#if str($include_doc) == 'True'
+ <!-- Javascript files that will be registered with the
+      portal_javascripts tool are defined here. You can also specify values
+      for existing resources if you need to modify some of their properties.
+      Javascript elements accept these parameters:
+      - 'id' (required): same rules as for stylesheets (see
+        'cssregistry.xml').
+      - 'expression' (optional - default: ''): a tal condition.
+      - 'inline' (optional - default: False)
+      - 'enabled' (optional - default: True): boolean
+      - 'cookable' (optional - default: True): boolean (aka 'merging allowed')
+      See registerScript() arguments in ResourceRegistries/tools/JSRegistry.py
+      for the latest list of all available keys and default values.
+   -->
+#end if
+<!-- EXAMPLE (UNCOMMENT TO MAKE AVAILABLE):
+ <javascript cacheable="True" compression="safe" cookable="True"
+    enabled="True" expression="" id="example.js" inline="False"/>
+  -->
+
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_skins tool -->
+
+<!-- Change the value of these parameters to modify portal_skins behavior:
+     - allow_any: change it to True if you want users to be able to select the
+       skin to use from their personal preferences management page. In the
+       ZMI, this value is known as 'Skin flexibility'.
+     - cookie_persistence: change it to True if you want to make the skin cookie
+       persist indefinitely. In the ZMI, this value is known as 'Skin Cookie
+       persistence'.
+  -->
+#end if
+<object name="portal_skins" allow_any="False" cookie_persistence="False"
+   default_skin="${skinname}">
+
+#if str($include_doc) == 'True'
+ <!-- This list registers the folders that are stored in the skins directory
+      of your product (on the filesystem) as Filesystem Directory Views within
+      the portal_skins tool, so that they become usable as skin layers.
+   -->
+#end if
+ <object name="${package}_images"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_images"/>
+ <object name="${package}_custom_images"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_custom_images"/>
+ <object name="${package}_styles"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_styles"/>
+ <object name="${package}_custom_styles"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_custom_styles"/>
+ <object name="${package}_templates"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_templates"/>
+ <object name="${package}_custom_templates"
+    meta_type="Filesystem Directory View"
+    directory="${package}/skins/${package}_custom_templates"/>
+
+#if str($include_doc) == 'True'
+ <!-- A skin-path in this file corresponds to a Skin Selection in the
+     'Properties' tab of the portal_skins tool, in the ZMI.
+     You can define for each new skin path the layers that it holds. A new
+     skin can be based on another existing one by using the 'based-on'
+     attribute.
+     The definition of a layer accepts these parameters:
+       - name: quite self explanatory, the name of the layer.
+       - insert-before: name of the layer before which it must be added.
+       - insert-after: name of the layer after which it must be added.
+       Note: insert-before (and -after) accepts the value "*" which means
+       "all".
+   -->
+#end if
+ <skin-path name="${skinname}">
+  <layer name="custom"/>
+  <layer name="${package}_styles"/>
+  <layer name="kupu_tests"/>
+  <layer name="CMFPlacefulWorkflow"/>
+  <layer name="PasswordReset"/>
+  <layer name="kupu_plone"/>
+  <layer name="kupu"/>
+  <layer name="ATContentTypes"/>
+  <layer name="ATReferenceBrowserWidget"/>
+  <layer name="archetypes"/>
+  <layer name="mimetypes_icons"/>
+  <layer name="ResourceRegistries"/>
+  <layer name="gruf"/>
+  <layer name="plone_ecmascript"/>
+  <layer name="plone_wysiwyg"/>
+  <layer name="plone_prefs"/>
+  <layer name="plone_portlets"/>
+#if $skinbase == "Plone Tableless"
+  <layer name="plone_tableless"/>
+#end if
+  <layer name="plone_templates"/>
+  <layer name="plone_styles"/>
+  <layer name="plone_form_scripts"/>
+  <layer name="plone_scripts"/>
+  <layer name="plone_forms"/>
+  <layer name="plone_images"/>
+  <layer name="plone_content"/>
+  <layer name="plone_login"/>
+  <layer name="plone_deprecated"/>
+  <layer name="plone_3rdParty"/>
+  <layer name="cmf_legacy"/>
+ </skin-path>
+
+ <skin-path name="*">
+  <layer name="${package}_images"
+     insert-after="custom"/>
+  <layer name="${package}_templates"
+     insert-after="${package}_images"/>
+ </skin-path>
+
+ <skin-path name="${skinname}">
+  <layer name="${package}_custom_images"
+      insert-before="${package}_images"/>
+  <layer name="${package}_custom_templates"
+      insert-after="${package}_custom_images"/>
+  <layer name="${package}_custom_styles"
+      insert-after="${package}_custom_templates"/>
+ </skin-path>
+
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/profiles.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    i18n_domain="${namespace_package}.${package}">
+
+#if str($add_profile) == 'True'
+  <genericsetup:registerProfile
+      name="default"
+      title="$skinname"
+      directory="profiles/default"
+      description="Extension profile for ${skinname} Product."
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+#end if
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/setuphandlers.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/setuphandlers.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/setuphandlers.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+def setupVarious(context):
+    pass    # Replace this line with your own import stuff
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_images/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+This folder holds Filesystem Image files that are registered for the
+'${skinname}' Skin Selection only.
+They act as replacement for the default Plone (or 3rd party product) ones.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+This folder holds CSS and Filesystem Properties Object (commonly
+'base_properties.props') files that are registered for the
+'${skinname}' Skin Selection only.
+They act as replacement for the default Plone (or 3rd party product) ones.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base_properties.props_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base_properties.props_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/base_properties.props_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,52 @@
+# Please note that this approach will gradually be phased out, probably in
+# Plone 2.2 or 2.3. Using DTML in CSS is something we want to stop doing.
+
+DEPRECATED:string=This approach is deprecated and will be phased out in Plone 2.2 or 2.3
+
+title:string=${skinname}'s color, font, logo and border defaults
+
+plone_skin:string=${skinname}
+
+logoName:string=logo.jpg
+
+fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+fontBaseSize:string=69%
+fontColor:string=Black
+fontSmallSize:string=85%
+
+backgroundColor:string=White
+
+linkColor:string=#436976
+linkActiveColor:string=Red
+linkVisitedColor:string=Purple
+
+borderWidth:string=1px
+borderStyle:string=solid
+borderStyleAnnotations:string=dashed
+
+globalBorderColor:string=#8cacbb
+globalBackgroundColor:string=#dee7ec
+globalFontColor:string=#436976
+
+headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+
+contentViewBorderColor:string=#74ae0b
+contentViewBackgroundColor:string=#cde2a7
+contentViewFontColor:string=#578308
+
+inputFontColor:string=Black
+
+textTransform:string=lowercase
+
+evenRowBackgroundColor:string=#eef3f5 
+oddRowBackgroundColor:string=transparent
+
+notifyBorderColor:string=#ffa500
+notifyBackgroundColor:string=#ffce7b
+
+discreetColor:string=#76797c
+helpBackgroundColor:string=#ffffe1
+
+portalMinWidth:string=70em
+columnOneWidth:string=16em
+columnTwoWidth:string=16em

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/generated.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/generated.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/generated.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/portlets.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/portlets.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/portlets.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/public.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/public.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_styles/public.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_custom_templates/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+This folder holds Filesystem Page Template files that are registered for the
+'${skinname}' Skin Selection only.
+They act as replacement for the default Plone (or 3rd party product) ones.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/CONTENT.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/CONTENT.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_images/CONTENT.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+This folder holds Filesystem Image files that are registered for all Skin
+Selections (all selectable skins in the 'portal_skins' tool).
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/+package+.css.dtml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/+package+.css.dtml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/+package+.css.dtml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_styles/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+Although this folder is not meant for storing customization skins, it holds
+stylesheet files that are registered for the '${skinname}' Skin Selection only.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/CONTENT.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/CONTENT.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/skins/+package+_templates/CONTENT.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+This folder holds Filesystem Page Template files that are registered for all
+Skin Selections (all selectable skins in the 'portal_skins' tool).
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/version.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/version.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/+namespace_package+/+package+/version.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+${version}
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/MANIFEST.in_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/MANIFEST.in_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2.5_theme/MANIFEST.in_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+recursive-include ${namespace_package} *
+global-exclude *pyc
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/Install.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/Install.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/Install.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,23 @@
+from cStringIO import StringIO
+
+from Products.${project}.Extensions.utils import *
+from Products.${project}.config import *
+
+def install(self):
+    out = StringIO()
+
+    setupSkins(self, out, GLOBALS, SKINSELECTIONS, SELECTSKIN, DEFAULTSKIN,
+                          ALLOWSELECTION, PERSISTENTCOOKIE)
+    registerResources(self, out, 'portal_css', STYLESHEETS)
+    registerResources(self, out, 'portal_javascripts', JAVASCRIPTS)
+
+    print >> out, "Installation completed."
+    return out.getvalue()
+
+
+def uninstall(self):
+    out = StringIO()
+
+    removeSkins(self, out, SKINSELECTIONS, DEFAULTSKIN, RESETSKINTOOL)
+    resetResources(self, out, 'portal_css', STYLESHEETS)
+    resetResources(self, out, 'portal_javascripts', JAVASCRIPTS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+# this file is here to make Install.py and utils.py importable.
+# keep these lines to make it non-zero size and have winzip cooperate.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/utils.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/utils.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/Extensions/utils.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,147 @@
+import os, string
+from Globals import package_home
+from Products.CMFCore.DirectoryView import addDirectoryViews
+from Products.CMFCore.utils import getToolByName
+
+
+def getSkinsFolderNames(globals, skins_dir='skins'):
+    # Get the content of the skins folder
+    skins_path = os.path.join(package_home(globals), skins_dir)
+    return [ filename for filename in os.listdir(skins_path)
+        if (not filename.startswith('.') or filename in ('CVS', '{arch}'))
+        and os.path.isdir(os.path.join(skins_path, filename)) ]
+
+def setupSkin(self, out, globals, skin_selection, make_default,
+                         allow_any, cookie_persistence, skins_dir='skins'):
+    skins_tool = getToolByName(self, 'portal_skins')
+    skin_name, base_skin = skin_selection['name'], skin_selection['base']
+
+    # Only add the skin selection if it doesn't already exist
+    if skin_name not in skins_tool.getSkinSelections():
+
+        # Get the skin layers of the base skin and convert to an array
+        layers = skins_tool.getSkinPath(base_skin)
+        layers = map(string.strip, string.split(layers, ','))
+
+        # Add the skin folders to the layers, under 'custom'
+        filenames = skin_selection.get('layers',
+                                     getSkinsFolderNames(globals, skins_dir))
+        for filename in filenames:
+            if filename not in layers:
+                try:
+                    layers.insert(layers.index('custom')+1, filename)
+                except ValueError:
+                    layers.insert(0, filename)
+
+        # Add our skin selection
+        layers = ', '.join(layers)
+        skins_tool.addSkinSelection(skin_name, layers)
+        print >> out, "Added skin selection to portal_skins."
+
+        # Activate the skin selection
+        if make_default:
+            skins_tool.default_skin = skin_name
+
+        # Setup other tool properties
+        skins_tool.allow_any = allow_any
+        skins_tool.cookie_persistence = cookie_persistence
+
+    else:
+        print >> out, "Skin selection already exists, leaving it alone."
+
+def setupSkins(self, out, globals, skin_selections, select_skin, default_skin,
+                          allow_any, cookie_persistence, skins_dir='skins'):
+    skins_tool = getToolByName(self, 'portal_skins')
+
+    # Add directory views
+    addDirectoryViews(skins_tool, skins_dir, globals)
+    print >> out, "Added directory views to portal_skins."
+
+    # Install skin selections
+    for skin in skin_selections:
+        make_default = False
+        if select_skin and skin['name'] == default_skin:
+            make_default = True
+        setupSkin(self, out, globals, skin, make_default,
+                                   allow_any, cookie_persistence, skins_dir)
+
+def registerResources(self, out, toolname, resources):
+    tool = getToolByName(self, toolname)
+    existing = tool.getResourceIds()
+    cook = False
+    for resource in resources:
+        if not resource['id'] in existing:
+            # register additional resource in the specified registry...
+            if toolname == "portal_css":
+                tool.registerStylesheet(**resource)
+            if toolname == "portal_javascripts":
+                tool.registerScript(**resource)
+            print >> out, "Added %s to %s." % (resource['id'], tool)
+        else:
+            # ...or update existing one
+            parameters = tool.getResource(resource['id'])._data
+            for key in [k for k in resource.keys() if k != 'id']:
+                originalkey = 'original_'+key
+                original = parameters.get(originalkey)
+                if not original:
+                    parameters[originalkey] = parameters[key]
+                parameters[key] = resource[key]
+                print >> out, "Updated %s in %s." % (resource['id'], tool)
+                cook = True
+    if cook:
+        tool.cookResources()
+    print >> out, "Successfuly Installed/Updated resources in %s." % tool
+
+def removeSkins(self, out, skin_selections=(),
+                           default=None, resetskintool=True):
+    skins_tool = getToolByName(self, 'portal_skins')
+
+    # Remove skin selections from portal_skins
+    for skin in skin_selections:
+        skin_name = skin['name']
+        if skin_name in skins_tool.getSkinSelections():
+            skins_tool.manage_skinLayers(del_skin=1, chosen=(skin_name,))
+            print >> out, \
+                "Removed skin selection '%s' from portal skins." %skin_name
+
+    # Set Skins Tool parameters back to defaults
+    if resetskintool:
+        # Restore Plone defaults
+        skins_tool.allow_any = 0
+        skins_tool.cookie_persistence = 0
+        selection = 'Plone Default'
+        print >> out, "Restored Plone defaults in portal_skins"
+    else:
+        # Select the base of the default skin selection in the skins tool
+        if skin_selections:
+            if default:
+                selection = [ s for s in skin_selections
+                              if s['name'] == default ]
+                if selection:
+                    selection = selection[0]['base']
+            else:
+                selection = skin_selections[0]['base']
+    skins_tool.default_skin = selection
+    print >> out, "Setup '%s' as default skin in portal_skins" % selection
+
+def resetResources(self, out, toolname, resources):
+    # Revert resource customizations
+    tool = getToolByName(self, toolname)
+    for resource in [tool.getResource(r['id']) for r in resources]:
+        if resource is None:
+            continue
+        for key in resource._data.keys():
+            originalkey = 'original_'+key
+            if resource._data.has_key(originalkey):
+                try: # <- BBB
+                    resource._data[key] = resource._data[originalkey]['value']
+                except TypeError:
+                    resource._data[key] = resource._data[originalkey]
+                del resource._data[originalkey]
+
+__all__ = (
+    "setupSkins",
+    "registerResources",
+    "removeSkins",
+    "resetResources",
+        )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/HISTORY.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/HISTORY.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/HISTORY.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+Changelog for ${project}
+
+    (name of developer listed in brackets)
+
+${project} - ${version} Unreleased
+
+    - Initial theme product structure.
+      [zopeskel]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+${project} Readme
+${project and '='*(len($project)+7) or '========'}
+
+Overview
+--------
+
+$description
+${long_description and '\n'+long_description or None}
+
+Installation
+------------
+
+Place ${project} in the Products directory of your Zope instance
+and restart the server.
+
+Go to the 'Site Setup' page in the Plone interface and click on the
+'Add/Remove Products' link.
+
+Choose ${project} (check its checkbox) and click the 'Install' button.
+
+You may have to empty your browser cache to see the effects of the product
+installation/uninstallation.
+
+Uninstall
+    This can be done from the same management screen.
+
+
+Selecting a skin
+----------------
+
+Depending on the value given to SELECTSKIN (in config.py), the skin will be
+selected (or not) as default one while installing the product. If you need to
+switch from a default skin to another, go to the 'Site Setup' page, and choose
+'Skins' (as portal manager). You can also decide from that page if members can
+choose their preferred skin and, in that case, if the skin cookie should be
+persistent.
+
+Note -- Don't forget to perform a full refresh of the page or reload all
+images (not from browser cache) after selecting a skin. In Firefox, you can do
+so by pressing the 'shift' key while reloading the page. In IE, use the key
+combination <Ctrl-F5>.
+
+
+Credits
+-------
+
+Written by ${author or None}${author_email and ' (%s)'%$author_email or None}

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+# Register our skins directory - this makes it available via portal_skins.
+from Products.CMFCore.DirectoryView import registerDirectory
+
+from config import GLOBALS
+registerDirectory('skins', GLOBALS)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/config.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/config.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/config.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,92 @@
+GLOBALS = globals()
+
+#if str($include_doc) == 'True'
+# CHANGE this tuple of python dictionaries to list the different skin
+#  selections and their associated specific layers.
+#   'name' (required): the name of the new skin.
+#     This will be what the user sees when choosing skins, and will be the
+#     name of a property in portal_skins.
+#   'base' (required): the name of the skin selection on which the new one
+#     is based.
+#   'layers' (optional): the name of the specific layers for the skin
+#     selection. By default (if the value is empty or if the key is absent
+#     from the dictionnary), all the folders in 'skins/' will be listed
+#     underneath 'custom' in the new skin selection layers.
+#end if
+SKINSELECTIONS = (
+    {'name': '$skinname',
+     'base': '$skinbase',
+     },
+    )
+
+#if str($include_doc) == 'True'
+# CHANGE it to False if you don't want the new skin selection to be selected
+#  at installation.
+#end if
+SELECTSKIN = True
+
+#if str($include_doc) == 'True'
+# CHANGE it to the name of the skin selection that must be set as default in
+#  case SELECTSKIN is set to True.
+#end if
+DEFAULTSKIN = '$skinname'
+
+#if str($include_doc) == 'True'
+# CHANGE this tuple of python dictionnaries to list the stylesheets that
+#  will be registered with the portal_css tool.
+#  'id' (required):
+#    it must respect the name of the css or DTML file (case sensitive).
+#    '.dtml' suffixes must be ignored.
+#  'expression' (optional - default: ''): a tal condition.
+#  'media' (optional - default: ''): possible values: 'screen', 'print',
+#    'projection', 'handheld'...
+#  'rel' (optional - default: 'stylesheet')
+#  'title' (optional - default: '')
+#  'rendering' (optional - default: 'import'): 'import', 'link' or 'inline'.
+#  'enabled' (optional - default: True): boolean
+#  'cookable' (optional - default: True): boolean (aka 'merging allowed')
+#  See registerStylesheet() arguments in
+#  ResourceRegistries/tools/CSSRegistry.py
+#  for the latest list of all available keys and default values.
+#end if
+STYLESHEETS = (
+    {'id': '${package}.css', 'media': 'screen', 'rendering': 'import'},
+        )
+
+#if str($include_doc) == 'True'
+# CHANGE this tuple of python dictionnaries to list the javascripts that
+#  will be registered with the portal_javascripts tool.
+#  'id' (required): same rules as for stylesheets.
+#  'expression' (optional - default: ''): a tal condition.
+#  'inline' (optional - default: False): boolean
+#  'enabled' (optional - default: True): boolean
+#  'cookable' (optional - default: True): boolean (aka 'merging allowed')
+#  See registerScript() arguments in ResourceRegistries/tools/JSRegistry.py
+#  for the latest list of all available keys and default values.
+JAVASCRIPTS = (
+#    {'id': '${package}.js.dtml',},
+        )
+#else
+JAVASCRIPTS = ()
+#end if
+
+#if str($include_doc) == 'True'
+# CHANGE it to True if you want users to be able to select the skin to use
+#  from their personal preferences management page.
+#  In the ZMI, this value is known as 'Skin flexibility'.
+#end if
+ALLOWSELECTION = False
+
+#if str($include_doc) == 'True'
+# CHANGE it to True if you want to make the skin cookie persist indefinitely.
+#  In the ZMI, this value is known as 'Skin Cookie persistence'.
+#end if
+PERSISTENTCOOKIE = False
+
+#if str($include_doc) == 'True'
+# CHANGE it to True if you want portal_skins properties to be reset to Plone
+#  default values when the product is uninstalled:
+#  Default Skin: 'Plone Default', Skin flexibility: False,
+#  Skin Cookie persistence: False.
+#end if
+RESETSKINTOOL = False

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/+package+.css.dtml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/+package+.css.dtml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/+package+.css.dtml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base_properties.props_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base_properties.props_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/base_properties.props_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+title:string=$skinname's color, font, logo and border defaults
+
+plone_skin:string=$skinname
+
+logoName:string=logo.jpg
+
+fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+fontBaseSize:string=69%
+fontColor:string=Black
+fontSmallSize:string=85%
+
+backgroundColor:string=White
+
+linkColor:string=#436976
+linkActiveColor:string=Red
+linkVisitedColor:string=Purple
+
+borderWidth:string=1px
+borderStyle:string=solid
+borderStyleAnnotations:string=dashed
+
+globalBorderColor:string=#8cacbb
+globalBackgroundColor:string=#dee7ec
+globalFontColor:string=#436976
+
+headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+
+contentViewBorderColor:string=#74ae0b
+contentViewBackgroundColor:string=#cde2a7
+contentViewFontColor:string=#578308
+
+inputFontColor:string=Black
+
+textTransform:string=lowercase
+
+evenRowBackgroundColor:string=#eef3f5 
+oddRowBackgroundColor:string=transparent
+
+notifyBorderColor:string=#ffa500
+notifyBackgroundColor:string=#ffce7b
+
+discreetColor:string=#76797c
+helpBackgroundColor:string=#ffffe1
+
+portalMinWidth:string=70em
+columnOneWidth:string=16em
+columnTwoWidth:string=16em

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/generated.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/generated.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/generated.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/portlets.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/portlets.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/portlets.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/public.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/public.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/skins/+package+_styles/public.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+"""\
+To run all tests type 'python runalltests.py'
+"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/framework.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/framework.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/framework.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,110 @@
+##############################################################################
+#
+# ZopeTestCase 
+#
+# COPY THIS FILE TO YOUR 'tests' DIRECTORY.
+#
+# This version of framework.py will use the SOFTWARE_HOME
+# environment variable to locate Zope and the Testing package.
+#
+# If the tests are run in an INSTANCE_HOME installation of Zope,
+# Products.__path__ and sys.path with be adjusted to include the
+# instance's Products and lib/python directories respectively.
+#
+# If you explicitly set INSTANCE_HOME prior to running the tests,
+# auto-detection is disabled and the specified path will be used 
+# instead.
+#
+# If the 'tests' directory contains a custom_zodb.py file, INSTANCE_HOME
+# will be adjusted to use it.
+#
+# If you set the ZEO_INSTANCE_HOME environment variable a ZEO setup 
+# is assumed, and you can attach to a running ZEO server (via the 
+# instance's custom_zodb.py).
+#
+##############################################################################
+#
+# The following code should be at the top of every test module:
+#
+# import os, sys
+# if __name__ == '__main__':
+#     execfile(os.path.join(sys.path[0], 'framework.py'))
+#
+# ...and the following at the bottom:
+#
+# if __name__ == '__main__':
+#     framework()
+#
+##############################################################################
+
+__version__ = '0.2.3'
+
+# Save start state
+#
+
+import os
+import sys
+
+__SOFTWARE_HOME = os.environ.get('SOFTWARE_HOME', '')
+__INSTANCE_HOME = os.environ.get('INSTANCE_HOME', '')
+
+if __SOFTWARE_HOME.endswith(os.sep):
+    __SOFTWARE_HOME = os.path.dirname(__SOFTWARE_HOME)
+
+if __INSTANCE_HOME.endswith(os.sep):
+    __INSTANCE_HOME = os.path.dirname(__INSTANCE_HOME)
+
+# Find and import the Testing package
+#
+if not sys.modules.has_key('Testing'):
+    p0 = sys.path[0]
+    if p0 and __name__ == '__main__':
+        os.chdir(p0)
+        p0 = ''
+    s = __SOFTWARE_HOME
+    p = d = s and s or os.getcwd()
+    while d:
+        if os.path.isdir(os.path.join(p, 'Testing')):
+            zope_home = os.path.dirname(os.path.dirname(p))
+            sys.path[:1] = [p0, p, zope_home]
+            break
+        p, d = s and ('','') or os.path.split(p)
+    else:
+        print 'Unable to locate Testing package.',
+        print 'You might need to set SOFTWARE_HOME.'
+        sys.exit(1)
+
+import Testing, unittest
+execfile(os.path.join(os.path.dirname(Testing.__file__), 'common.py'))
+
+# Include ZopeTestCase support
+#
+if 1:   # Create a new scope
+
+    p = os.path.join(os.path.dirname(Testing.__file__), 'ZopeTestCase')
+
+    if not os.path.isdir(p):
+        print 'Unable to locate ZopeTestCase package.',
+        print 'You might need to install ZopeTestCase.'
+        sys.exit(1)
+
+    ztc_common = 'ztc_common.py'
+    ztc_common_global = os.path.join(p, ztc_common)
+
+    f = 0
+    if os.path.exists(ztc_common_global):
+        execfile(ztc_common_global)
+        f = 1
+    if os.path.exists(ztc_common):
+        execfile(ztc_common)
+        f = 1
+
+    if not f:
+        print 'Unable to locate %s.' % ztc_common
+        sys.exit(1)
+
+# Debug
+#
+print 'SOFTWARE_HOME: %s' % os.environ.get('SOFTWARE_HOME', 'Not set')
+print 'INSTANCE_HOME: %s' % os.environ.get('INSTANCE_HOME', 'Not set')
+sys.stdout.flush()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/runalltests.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/runalltests.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/runalltests.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,28 @@
+#
+# Runs all tests in the current directory
+#
+# Execute like:
+#   python runalltests.py
+#
+# Alternatively use the testrunner:
+#   python /path/to/Zope/utilities/testrunner.py -qa
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+import unittest
+TestRunner = unittest.TextTestRunner
+suite = unittest.TestSuite()
+
+tests = os.listdir(os.curdir)
+tests = [n[:-3] for n in tests if n.startswith('test') and n.endswith('.py')]
+
+for test in tests:
+    m = __import__(test)
+    if hasattr(m, 'test_suite'):
+        suite.addTest(m.test_suite())
+
+if __name__ == '__main__':
+    TestRunner().run(suite)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testSkeleton.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testSkeleton.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testSkeleton.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,37 @@
+#
+# This file is a skeleton test suite.
+# It is here for letting you add new tests to the product without having to
+# modify the existing testStyleInstallation.py module.
+# You may modify its name to something that describes what it tests
+# (keeping its 'test' prefix).
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Products.PloneTestCase import PloneTestCase
+
+PloneTestCase.installProduct('${project}')
+PloneTestCase.setupPloneSite(products=['${project}'])
+
+
+class TestSomething(PloneTestCase.PloneTestCase):
+
+    def afterSetUp(self):
+        pass
+
+    def testSomething(self):
+        # Test something
+        self.assertEqual(1+1, 2)
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestSomething))
+    return suite
+
+if __name__ == '__main__':
+    framework()
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testStyleInstallation.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testStyleInstallation.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/tests/testStyleInstallation.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,201 @@
+#
+# Unit Tests for the style install and uninstall methods
+#
+
+import os, sys
+if __name__ == '__main__':
+    execfile(os.path.join(sys.path[0], 'framework.py'))
+
+from Products.PloneTestCase import PloneTestCase
+
+from Products.${project}.config import *
+from Products.${project}.Extensions.utils import getSkinsFolderNames
+PROJECTNAME = '${project}'
+
+PloneTestCase.installProduct(PROJECTNAME)
+PloneTestCase.setupPloneSite(products=[PROJECTNAME])
+
+class testSkinsTool(PloneTestCase.PloneTestCase):
+
+    def afterSetUp(self):
+        self.tool = getattr(self.portal, 'portal_skins')
+
+    def testSkinSelectionCreated(self):
+        """Test if a new skin exists in portal_skins."""
+        for skin_selection in SKINSELECTIONS:
+            self.failUnless(
+                skin_selection['name'] in self.tool.getSkinSelections())
+
+    def testSkinPaths(self):
+        """Test if the skin layers in the new skin were correctly added."""
+        skinsfoldernames = getSkinsFolderNames(GLOBALS)
+        skins_dict = {}
+        for skin in SKINSELECTIONS:
+            skins_dict[skin['name']] = skin.get('layers', skinsfoldernames)
+        for selection, layers in self.tool.getSkinPaths():
+            if skins_dict.has_key(selection):
+                for specific_layer in skins_dict[selection]:
+                    self.failUnless(specific_layer in layers)
+            else:
+                for foldername in skinsfoldernames:
+                    self.failIf(foldername in layers)
+
+    def testSkinSelection(self):
+        """Test if the new skin was selected as default one."""
+        if SELECTSKIN:
+            self.assertEqual(self.tool.getDefaultSkin(), DEFAULTSKIN)
+
+    def testSkinFlexibility(self):
+        """Test if the users can choose their skin."""
+        self.assertEqual(self.tool.getAllowAny(), ALLOWSELECTION)
+
+    def testCookiePersistance(self):
+        """Test if the skin choice is peristant between sessions."""
+        self.assertEqual(bool(self.tool.getCookiePersistence()),
+                                                        PERSISTENTCOOKIE)
+
+class testResourceRegistrations(PloneTestCase.PloneTestCase):
+
+    def afterSetUp(self):
+        self.qitool      = getattr(self.portal, 'portal_quickinstaller')
+        self.csstool     = getattr(self.portal, 'portal_css')
+        self.jstool      = getattr(self.portal, 'portal_javascripts')
+        product_settings = getattr(self.qitool, PROJECTNAME)
+        self.stylesheets = product_settings.resources_css
+        self.javascripts = product_settings.resources_js
+
+    def testStylesheetsInstalled(self):
+        """Test if new stylesheets were added to portal_css."""
+        stylesheetids = self.csstool.getResourceIds()
+        for css in STYLESHEETS:
+            self.failUnless(css['id'] in stylesheetids)
+
+    def testStylesheetProperties(self):
+        """Test if new stylesheets have correct parameters."""
+        for config in STYLESHEETS:
+            res = self.csstool.getResource(config['id'])
+            for key in [key for key in config.keys() if key != 'id']:
+                self.assertEqual(res._data[key], config[key])
+
+    def testStylesheetsUpdated(self):
+        """Test if existing stylesheets were correctly updated."""
+        for config in [c for c in STYLESHEETS
+                       if c['id'] not in self.stylesheets]:
+            resource = self.csstool.getResource(config['id'])
+            for key in [k for k in config.keys() if k != 'id']:
+                self.failUnless(resource._data.has_key('original_'+key))
+
+    def testJavascriptsInstalled(self):
+        """Test if new javascripts were added to portal_javascripts."""
+        javascriptids = self.jstool.getResourceIds()
+        for js in JAVASCRIPTS:
+            self.failUnless(js['id'] in javascriptids)
+
+    def testMemberStylesheetProperties(self):
+        """Test if new javascripts have correct parameters."""
+        for config in JAVASCRIPTS:
+            res = self.jstool.getResource(config['id'])
+            for key in [key for key in config.keys() if key != 'id']:
+                self.assertEqual(res._data[key], config[key])
+
+    def testJavascriptsUpdated(self):
+        """Test if existing javascripts were correctly updated."""
+        for config in [c for c in JAVASCRIPTS
+                       if c['id'] not in self.javascripts]:
+            resource = self.jstool.getResource(config['id'])
+            for key in [k for k in config.keys() if k != 'id']:
+                self.failUnless(resource._data.has_key('original_'+key))
+
+
+class testUninstall(PloneTestCase.PloneTestCase):
+
+    def afterSetUp(self):
+        """Test if ."""
+        self.qitool      = getattr(self.portal, 'portal_quickinstaller')
+        self.skinstool   = getattr(self.portal, 'portal_skins')
+        self.csstool     = getattr(self.portal, 'portal_css')
+        self.jstool      = getattr(self.portal, 'portal_javascripts')
+        product_settings = getattr(self.qitool, PROJECTNAME)
+        self.stylesheets = product_settings.resources_css
+        self.javascripts = product_settings.resources_js
+        self.qitool.uninstallProducts(products=[PROJECTNAME])
+        self.ttool = getattr(self.portal, 'portal_types')
+
+    def testProductUninstalled(self):
+        """Test if the product was uninstalled."""
+        self.failIf(self.qitool.isProductInstalled(PROJECTNAME))
+
+    def testSkinSelectionDeleted(self):
+        """Test if the skin selection was removed from portal_skins."""
+        skin_selections = self.skinstool.getSkinSelections()
+        for skin in SKINSELECTIONS:
+            self.failIf(skin['name'] in skin_selections)
+
+    def testDefaultSkinChanged(self):
+        """Test if default skin is back to old value or default Plone."""
+        default_skin = self.skinstool.getDefaultSkin()
+        if RESETSKINTOOL:
+            self.assertEqual(default_skin, 'Plone Default')
+        else:
+            if DEFAULTSKIN:
+                for skin in SKINSELECTIONS:
+                    if skin['name'] == DEFAULTSKIN:
+                        self.assertEqual(default_skin, skin['base'])
+            else:
+                self.assertEqual(default_skin, SKINSELECTIONS[0]['base'])
+
+    def testResetSkinFlexibility(self):
+        """Test if the users still can choose their skin."""
+        allow_any = self.skinstool.getAllowAny()
+        if RESETSKINTOOL:
+            self.failIf(allow_any)
+        else:
+            self.assertEqual(allow_any, ALLOWSELECTION)
+
+    def testResetCookiePersistance(self):
+        """Test if the skin choice is still peristant between sessions."""
+        cookie_peristence = self.skinstool.getCookiePersistence()
+        if RESETSKINTOOL:
+            self.failIf(cookie_peristence)
+        else:
+            self.assertEqual(cookie_peristence, PERSISTENTCOOKIE)
+
+    def testStylesheetsUninstalled(self):
+        """Test if added stylesheets were removed from portal_css."""
+        resourceids = self.csstool.getResourceIds()
+        for css in self.stylesheets:
+            self.failIf(css in resourceids)
+
+    def testResetDefaultStylesheets(self):
+        """Test if values were reverted in existing stylesheets."""
+        for config in [c for c in STYLESHEETS
+                       if c['id'] not in self.stylesheets]:
+            resource = self.csstool.getResource(config['id'])
+            for key in [k for k in config.keys() if k != 'id']:
+                self.failIf(resource._data.has_key('original_'+key))
+
+    def testJavascriptsUninstalled(self):
+        """Test if added javascripts were removed from portal_js."""
+        resourceids = self.jstool.getResourceIds()
+        for js in self.javascripts:
+            self.failIf(js in resourceids)
+
+    def testResetDefaultJavascripts(self):
+        """Test if values were reverted in existing javascripts."""
+        for config in [c for c in JAVASCRIPTS
+                       if c['id'] not in self.javascripts]:
+            resource = self.jstool.getResource(config['id'])
+            for key in [k for k in config.keys() if k != 'id']:
+                self.failIf(resource._data.has_key('original_'+key))
+
+
+if __name__ == '__main__':
+    framework()
+else:
+    import unittest
+    def test_suite():
+        suite = unittest.TestSuite()
+        suite.addTest(unittest.makeSuite(testSkinsTool))
+        suite.addTest(unittest.makeSuite(testResourceRegistrations))
+        suite.addTest(unittest.makeSuite(testUninstall))
+        return suite

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/version.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/version.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone2_theme/version.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+$version
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,327 @@
+=======================
+Using a custom buildout
+=======================
+
+Note: If you are using Windows, if you do not have PIL installed, or you are
+not using Python 2.4 as your main system Python, please see the relevant
+sections below.
+
+You probably got here by running something like:
+
+ $ paster create -t plone3_buildout
+
+Now, you need to run:
+
+ $ python bootstrap.py
+
+This will install zc.buildout for you.
+
+To create an instance immediately, run:
+
+ $ bin/buildout
+
+This will download Plone's eggs and products for you, as well as other
+dependencies, create a new Zope 2 installation (unless you specified
+an existing one when you ran "paster create"), and create a new Zope instance
+configured with these products.
+
+You can start your Zope instance by running:
+
+ $ bin/instance start
+
+or, to run in foreground mode:
+
+ $ bin/instance fg
+
+To run unit tests, you can use:
+
+ $ bin/instance test -s my.package
+
+Installing PIL
+--------------
+
+To use Plone, you need PIL, the Python Imaging Library. If you don't already
+have this, download and install it from http://www.pythonware.com/products/pil.
+
+Using a different Python installation
+--------------------------------------
+
+Buildout will use your system Python installation by default. However, Zope
+2.10 (and by extension, Plone) will only work with Python 2.4. You can verify
+which version of Python you have, by running:
+
+ $ python -V
+
+If that is not a 2.4 version, you need to install Python 2.4 from
+http://python.org. If you wish to keep another version as your main system
+Python, edit buildout.cfg and add an 'executable' option to the "[buildout]"
+section, pointing to a python interpreter binary:
+
+ [buildout]
+ ...
+ executable = /path/to/python
+
+Working with buildout.cfg
+-------------------------
+
+You can change any option in buildout.cfg and re-run bin/buildout to reflect
+the changes. This may delete things inside the 'parts' directory, but should
+keep your Data.fs and source files intact.
+
+To save time, you can run buildout in "offline" (-o) and non-updating (-N)
+mode, which will prevent it from downloading things and checking for new
+versions online:
+
+ $ bin/buildout -Nov
+
+Creating new eggs
+-----------------
+
+New packages you are working on (but which are not yet released as eggs and
+uploaded to the Python Package Index, aka PYPI) should be placed in src. You can do:
+
+ $ cd src/
+ $ paster create -t plone my.package
+
+Use "paster create --list-templates" to see all available templates. Answer
+the questions and you will get a new egg. Then tell buildout about your egg
+by editing buildout.cfg and adding your source directory to 'develop':
+
+ [buildout]
+ ...
+ develop =
+    src/my.package
+
+You can list multiple packages here, separated by whitespace or indented
+newlines.
+
+You probably also want the Zope instance to know about the package. Add its
+package name to the list of eggs in the "[instance]" section, or under the
+main "[buildout]" section:
+
+ [instance]
+ ...
+ eggs =
+    ${buildout:eggs}
+    ${plone:eggs}
+    my.package
+
+Leave the ${buildout:eggs} part in place - it tells the instance to use the
+eggs that buildout will have downloaded from the Python Package Index
+previously.
+
+If you also require a ZCML slug for your package, buildout can create one
+automatically. Just add the package to the 'zcml' option:
+
+ [instance]
+ ...
+ zcml =
+    my.package
+
+When you are finished, re-run buildout. Offline, non-updating mode should
+suffice:
+
+ $ bin/buildout -Nov
+
+Developing old-style products
+-----------------------------
+
+If you are developing old-style Zope 2 products (not eggs) then you can do so
+by placing the product code in the top-level 'products' directory. This is
+analogous to the 'Products/' directory inside a normal Zope 2 instance and is
+scanned on start-up for new products.
+
+Depending on a new egg
+----------------------
+
+If you want to use a new egg that is in the Python Package Index, all you need
+to do is to add it to the "eggs" option under the main "[buildout]" section:
+
+ [buildout]
+ ...
+ eggs =
+    my.package
+
+If it's listed somewhere else than the Python Package Index, you can add a link
+telling buildout where to find it in the 'find-links' option:
+
+ [buildout]
+ ...
+ find-links =
+    http://dist.plone.org
+    http://download.zope.org/distribution/
+    http://effbot.org/downloads
+    http://some.host.com/packages
+
+Using existing old-style products
+---------------------------------
+
+If you are using an old-style (non-egg) product, you can either add it as an
+automatically downloaded archive or put it in the top-level "products" folder.
+The former is probably better, because it means you can redistribute your
+buildout.cfg more easily:
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+
+If someproduct-1.3.tar.gz extracts into several products inside a top-level
+directory, e.g. SomeProduct-1.3/PartOne and SomeProduct-1.3/PartTwo, then
+add it as a "nested package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ nested-packages =
+    someproduct-1.3.tar.gz
+
+Alternatively, if it extracts to a directory which contains the version
+number, add it as a "version suffix package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ version-suffix-packages =
+    someproduct-1.3.tar.gz
+
+You can also track products by adding a new bundle checkout part. It
+doesn't strictly have to be an svn bundle at all, any svn location will do,
+and cvs is also supported:
+
+ [buildout]
+ ...
+ parts =
+    plone
+    zope2
+    productdistros
+    myproduct
+    instance
+    zopepy
+
+Note that "myproduct" comes before the "instance" part. You then
+need to add a new section to buildout.cfg:
+
+ [myproduct]
+ recipe = plone.recipe.bundlecheckout
+ url = http://svn.plone.org/svn/collective/myproduct/trunk
+
+Finally, you need to tell Zope to find this new checkout and add it to its
+list of directories that are scanned for products:
+
+ [instance]
+ ...
+ products =
+    ${buildout:directory}/products
+    ${productdistros:location}
+    ${plonebundle:location}
+    ${myproduct:location}
+
+Without this last step, the "myproduct" part is simply managing an svn
+checkout and could potentially be used for something else instead.
+
+=============
+Using Windows
+=============
+
+To use buildout on Windows, you will need to install a few dependencies which
+other platforms manage on their own.
+
+Here are the steps you need to follow (thanks to Hanno Schlichting for these):
+
+Python (http://python.org)
+--------------------------
+
+  - Download and install Python 2.4.4 using the Windows installer from
+    http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi
+    Select 'Install for all users' and it will put Python into the
+    "C:\Python24" folder by default.
+
+  - You also want the pywin32 extensions available from
+    http://downloads.sourceforge.net/pywin32/pywin32-210.win32-py2.4.exe?modtime=1159009237&big_mirror=0
+
+  - And as a last step you want to download the Python imaging library available
+    from http://effbot.org/downloads/PIL-1.1.6.win32-py2.4.exe
+
+  - If you develop Zope based applications you will usually only need Python 2.4
+    at the moment, so it's easiest to put the Python binary on the systems PATH,
+    so you don't need to specify its location manually each time you call it.
+
+    Thus, put "C:\Python24" and "C:\Python24\Scripts" onto the PATH. You can
+    find the PATH definition in the control panel under system preferences on
+    the advanced tab at the bottom. The button is called environment variables.
+    You want to add it at the end of the already existing PATH in the system
+    section. Paths are separated by a semicolons.
+
+  - You can test if this was successful by opening a new shell (cmd) and type
+    in 'python -V'. It should report version 2.4.4 (or whichever version you
+    installed).
+
+    Opening a new shell can be done quickly by using the key combination
+    'Windows-r' or if you are using Parallels on a Mac 'Apple-r'. Type in 'cmd'
+    into the popup box that opens up and hit enter.
+
+
+Subversion (http://subversion.tigris.org)
+-----------------------------------------
+
+  - Download the nice installer from
+    http://subversion.tigris.org/files/documents/15/35379/svn-1.4.2-setup.exe
+
+  - Run the installer. It defaults to installing into
+    "C:\Program Files\Subversion".
+
+  - Now put the install locations bin subfolder (for example
+    "C:\Program Files\Subversion\bin") on your system PATH in the same way you
+    put Python on it.
+
+  - Open a new shell again and type in: 'svn --version' it should report
+    version 1.4.2 or newer.
+
+
+MinGW (http://www.mingw.org/)
+-----------------------------
+
+  This is a native port of the gcc compiler and its dependencies for Windows.
+  There are other approaches enabling you to compile Python C extensions on
+  Windows including Cygwin and using the official Microsoft C compiler, but this
+  is a lightweight approach that uses only freely available tools. As
+  it's used by a lot of people chances are high it will work for you and there's
+  plenty of documentation out there to help you in troubleshooting problems.
+
+  - Download the MinGW installer from
+    http://downloads.sourceforge.net/mingw/MinGW-5.1.3.exe?modtime=1168794334&big_mirror=1
+
+  - The installer will ask you which options you would like to install. Choose
+    base and make here. It will install into "C:\MinGW" by default. The install
+    might take some time as it's getting files from sourceforge.net and you
+    might need to hit 'retry' a couple of times.
+
+  - Now put the install location's bin subfolder (for example "C:\MinGW\bin") on
+    your system PATH in the same way you put Python on it.
+
+  - Test this again by typing in: 'gcc --version' on a newly opened shell and
+    it should report version 3.4.2 or newer.
+
+
+Configure Distutils to use MinGW
+--------------------------------
+
+  Some general information are available from
+  http://www.mingw.org/MinGWiki/index.php/Python%20extensions for example but
+  you don't need to read them all.
+
+  - Create a file called 'distutils.cfg' in "C:\Python24\Lib\distutils". Open it
+    with a text editor ('notepad distutils.cfg') and fill in the following lines:
+
+    [build]
+    compiler=mingw32
+
+    This will tell distutils to use MinGW as the default compiler, so you don't
+    need to specify it manually using "--compiler=mingw32" while calling a
+    package's setup.py with a command that involves building C extensions. This
+    is extremely useful if the build command is written down in a buildout
+    recipe where you cannot change the options without hacking the recipe
+    itself. The z2c.recipe.zope2install used in ploneout is one such example.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,120 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os
+import shutil
+import sys
+import tempfile
+import urllib2
+from optparse import OptionParser
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+# parsing arguments
+parser = OptionParser()
+parser.add_option("-v", "--version", dest="version",
+                          help="use a specific zc.buildout version")
+parser.add_option("-d", "--distribute",
+                   action="store_true", dest="distribute", default=False,
+                   help="Use Disribute rather than Setuptools.")
+
+parser.add_option("-c", None, action="store", dest="config_file",
+                   help=("Specify the path to the buildout configuration "
+                         "file to be used."))
+
+options, args = parser.parse_args()
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args += ['-c', options.config_file]
+
+if options.version is not None:
+    VERSION = '==%s' % options.version
+else:
+    VERSION = ''
+
+# We decided to always use distribute, make sure this is the default for us
+# USE_DISTRIBUTE = options.distribute
+USE_DISTRIBUTE = True
+args = args + ['bootstrap']
+
+to_reload = False
+try:
+    import pkg_resources
+    if not hasattr(pkg_resources, '_distribute'):
+        to_reload = True
+        raise ImportError
+except ImportError:
+    ez = {}
+    if USE_DISTRIBUTE:
+        setup_url = 'http://python-distribute.org/distribute_setup.py'
+        exec urllib2.urlopen(setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
+    else:
+        ez_setup_url = 'http://peak.telecommunity.com/dist/ez_setup.py'
+        exec urllib2.urlopen(ez_setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    if to_reload:
+        reload(pkg_resources)
+    else:
+        import pkg_resources
+
+
+def quote(c):
+    if sys.platform == 'win32':
+        if ' ' in c:
+            return '"%s"' % c  # work around spawn lamosity on windows
+    return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws = pkg_resources.working_set
+
+if USE_DISTRIBUTE:
+    requirement = 'distribute'
+else:
+    requirement = 'setuptools'
+
+pythonpath = ws.find(pkg_resources.Requirement.parse(requirement)).location
+
+if is_jython:
+    import subprocess
+
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+           quote(tmpeggs), 'zc.buildout' + VERSION],
+           env=dict(os.environ,
+               PYTHONPATH=pythonpath),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote(sys.executable),
+        '-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION,
+        dict(os.environ,
+            PYTHONPATH=pythonpath),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout' + VERSION)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,192 @@
+[buildout]
+parts =
+#if not $eggifiedplone
+    plone
+#end if
+#if not $zope2_install
+    zope2
+#end if
+    productdistros
+    instance
+    zopepy
+
+#if $eggifiedplone
+\# Change the number here to change the version of Plone being used
+extends = 
+#if $eggifiedzope
+    http://download.zope.org/Zope2/index/${zope2_version}/versions.cfg
+#end if
+    http://dist.plone.org/release/${plone_version}/versions.cfg
+#end if
+versions = versions
+
+
+\# Add additional egg download sources here. dist.plone.org contains archives
+\# of Plone packages.
+find-links =
+#if $eggifiedplone
+    http://dist.plone.org/release/${plone_version}
+#else
+    http://dist.plone.org
+#end if
+    http://dist.plone.org/thirdparty
+
+\# Add additional eggs here
+#if not $eggifiedplone
+\# elementtree is required by Plone
+#end if
+eggs =
+#if not $eggifiedplone
+    elementtree
+#end if
+
+\# Reference any eggs you are developing here, one per line
+\# e.g.: develop = src/my.package
+develop =
+
+#if not $eggifiedplone
+[versions]
+\# Version pins for new style products go here
+plone.recipe.zope2instance = 3.6
+#end if
+
+#if $tarballs
+[plone]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.plone
+recipe = plone.recipe.plone==${plone_version}
+#if $plone_products_install
+\# By overriding the download URLs and making them an empty list, we
+\# Make sure our own products directory takes precedence
+urls =
+#end if
+#end if
+
+#if $z29tarballs
+[plone]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.distros
+recipe = plone.recipe.distros
+urls = http://launchpad.net/plone/2.5/${plone_version}/+download/Plone-${plone_version}.tar.gz
+nested-packages = Plone-${plone_version}.tar.gz
+version-suffix-packages = Plone-${plone_version}.tar.gz
+#end if
+
+#if not $zope2_install
+[zope2]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.zope2install
+recipe = plone.recipe.zope2install
+fake-zope-eggs = true
+#if $tarballs
+url = \${plone:zope2-url}
+#end if
+#if $z29tarballs
+url = http://www.zope.org/Products/Zope/${zope2_version}/Zope-${zope2_version}-final.tgz
+#end if
+#if $eggifiedplone
+url = \${versions:zope2-url}
+#end if
+#end if
+
+\# Use this section to download additional old-style products.
+\# List any number of URLs for product tarballs under URLs (separate
+\# with whitespace, or break over several lines, with subsequent lines
+\# indented). If any archives contain several products inside a top-level
+\# directory, list the archive file name (i.e. the last part of the URL,
+\# normally with a .tar.gz suffix or similar) under 'nested-packages'.
+\# If any archives extract to a product directory with a version suffix, list
+\# the archive name under 'version-suffix-packages'.
+[productdistros]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.distros
+recipe = plone.recipe.distros
+urls =
+nested-packages =
+version-suffix-packages =
+
+[instance]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.zope2instance
+recipe = plone.recipe.zope2instance
+#if $zope2_install
+#if not $eggifiedzope
+zope2-location = ${zope2_install}
+#end if
+#else
+zope2-location = \${zope2:location}
+#end if
+user = ${zope_user}:${zope_password}
+http-address = ${http_port}
+#if $debug_mode == 'on'
+debug-mode = on
+#else
+\#debug-mode = on
+#end if
+#if $verbose_security == 'on'
+verbose-security = on
+#else
+\#verbose-security = on
+#end if
+#if $eggifiedzope
+blob-storage = var/blobstorage
+#end if
+\# If you want Zope to know about any additional eggs, list them here.
+\# This should include any development eggs you listed in develop-eggs above,
+\# e.g. eggs = Plone my.package
+eggs =
+#if $eggifiedzope
+    Zope2
+#end if
+#if $eggifiedplone
+    Plone
+    \${buildout:eggs}
+#end if
+#if $tarballs
+    \${buildout:eggs}
+    \${plone:eggs}
+#end if
+#if $z29tarballs
+    \${buildout:eggs}
+#end if
+#if $eggifiedzope
+environment-vars =
+    zope_i18n_compile_mo_files true
+#end if
+
+\# If you want to register ZCML slugs for any packages, list them here.
+\# e.g. zcml = my.package my.other.package
+zcml =
+
+products =
+    \${buildout:directory}/products
+    \${productdistros:location}
+#if $tarballs
+#if not $plone_products_install
+    \${plone:products}
+#else
+    ${plone_products_install}
+#end if
+#end if
+#if $z29tarballs
+#if not $plone_products_install
+    \${plone:location}
+#else
+    ${plone_products_install}
+#end if
+#end if
+
+[zopepy]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/zc.recipe.egg
+recipe = zc.recipe.egg
+eggs = \${instance:eggs}
+interpreter = zopepy
+#if not $eggifiedzope
+#if $zope2_install
+extra-paths = ${zope2_install}/lib/python
+#else
+extra-paths = \${zope2:location}/lib/python
+#end if
+#end if
+scripts = zopepy

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/products/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/products/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/products/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Old-style Zope products you are developing can be added here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_buildout/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.pt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.pt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.pt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+<dl class="portlet portlet${portlet_type_name}"
+    i18n:domain="${dotted_name}">
+
+    <dt class="portletHeader">
+        <span class="portletTopLeft"></span>
+        Header
+        <span class="portletTopRight"></span>
+    </dt>
+
+    <dd class="portletItem odd">
+        Body text
+    </dd>
+
+    <dd class="portletFooter">
+        <span class="portletBottomLeft"></span>
+        Footer
+        <span class="portletBottomRight"></span>
+    </dd>
+
+</dl>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/+portlet_filename+.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,110 @@
+from zope.interface import implements
+
+from plone.portlets.interfaces import IPortletDataProvider
+from plone.app.portlets.portlets import base
+
+\# TODO: If you define any fields for the portlet configuration schema below
+\# do not forget to uncomment the following import
+\#from zope import schema
+from zope.formlib import form
+
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+
+\# TODO: If you require i18n translation for any of your schema fields below,
+\# uncomment the following to import your package MessageFactory
+\#from ${dotted_name} import ${portlet_type_name}MessageFactory as _
+
+
+class I${portlet_type_name}(IPortletDataProvider):
+    """A portlet
+
+    It inherits from IPortletDataProvider because for this portlet, the
+    data that is being rendered and the portlet assignment itself are the
+    same.
+    """
+
+    # TODO: Add any zope.schema fields here to capture portlet configuration
+    # information. Alternatively, if there are no settings, leave this as an
+    # empty interface - see also notes around the add form and edit form
+    # below.
+
+    # some_field = schema.TextLine(title=_(u"Some field"),
+    #                              description=_(u"A field to use"),
+    #                              required=True)
+
+
+class Assignment(base.Assignment):
+    """Portlet assignment.
+
+    This is what is actually managed through the portlets UI and associated
+    with columns.
+    """
+
+    implements(I${portlet_type_name})
+
+    # TODO: Set default values for the configurable parameters here
+
+    # some_field = u""
+
+    # TODO: Add keyword parameters for configurable parameters here
+    # def __init__(self, some_field=u""):
+    #    self.some_field = some_field
+
+    def __init__(self):
+        pass
+
+    @property
+    def title(self):
+        """This property is used to give the title of the portlet in the
+        "manage portlets" screen.
+        """
+        return "${portlet_name}"
+
+
+class Renderer(base.Renderer):
+    """Portlet renderer.
+
+    This is registered in configure.zcml. The referenced page template is
+    rendered, and the implicit variable 'view' will refer to an instance
+    of this class. Other methods can be added and referenced in the template.
+    """
+
+    render = ViewPageTemplateFile('${portlet_filename}.pt')
+
+
+class AddForm(base.AddForm):
+    """Portlet add form.
+
+    This is registered in configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display. The create() method actually
+    constructs the assignment that is being added.
+    """
+    form_fields = form.Fields(I${portlet_type_name})
+
+    def create(self, data):
+        return Assignment(**data)
+
+
+# NOTE: If this portlet does not have any configurable parameters, you
+# can use the next AddForm implementation instead of the previous.
+
+# class AddForm(base.NullAddForm):
+#     """Portlet add form.
+#     """
+#
+#     def create(self):
+#         return Assignment()
+
+
+# NOTE: If this portlet does not have any configurable parameters, you
+# can remove the EditForm class definition and delete the editview
+# attribute from the <plone:portlet /> registration in configure.zcml
+
+
+class EditForm(base.EditForm):
+    """Portlet edit form.
+
+    This is registered with configure.zcml. The form_fields variable tells
+    zope.formlib which fields to display.
+    """
+    form_fields = form.Fields(I${portlet_type_name})

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+from zope.i18nmessageid import MessageFactory
+${portlet_type_name}MessageFactory = MessageFactory('${project}')
+
+#if str($zope2product) == 'True'
+
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,38 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    xmlns:plone="http://namespaces.plone.org/plone"
+    i18n_domain="${dotted_name}">
+
+#if str($zope2product) == 'True'
+    <five:registerPackage package="." initialize=".initialize" />
+
+#end if
+    <genericsetup:registerProfile
+       name="default"
+       title="${portlet_name}"
+       directory="profiles/default"
+       description="${description}"
+       provides="Products.GenericSetup.interfaces.EXTENSION"
+       />
+
+     <!-- Register the portlet -->
+
+     <!-- If the portlet has no configurable parameters, you can remove
+          the EditForm declaration in ${portlet_filename}.py and delete
+          the 'editview' attribute from this statement.
+       -->
+
+     <plone:portlet
+         name="${dotted_name}.${portlet_type_name}"
+         interface=".${portlet_filename}.I${portlet_type_name}"
+         assignment=".${portlet_filename}.Assignment"
+         view_permission="zope2.View"
+         edit_permission="cmf.ManagePortal"
+         renderer=".${portlet_filename}.Renderer"
+         addview=".${portlet_filename}.AddForm"
+         editview=".${portlet_filename}.EditForm"
+         />
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/metadata.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/metadata.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/metadata.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>1000</version>
+</metadata>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/portlets.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/portlets.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/profiles/default/portlets.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,12 @@
+<?xml version="1.0"?>
+<portlets>
+
+ <!-- Portlet type registrations -->
+
+ <portlet
+   addview="${namespace_package}.${namespace_package2}.${package}.${portlet_type_name}"
+   title="${portlet_name}"
+   description="${description}"
+   />
+
+</portlets>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/base.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/base.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/base.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,45 @@
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+
+from Testing import ZopeTestCase as ztc
+
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import onsetup
+
+
+ at onsetup
+def setup_product():
+    """Set up additional products and ZCML required to test this product.
+
+    The @onsetup decorator causes the execution of this body to be deferred
+    until the setup of the Plone site testing layer.
+    """
+
+    # Load the ZCML configuration for this package and its dependencies
+
+    fiveconfigure.debug_mode = True
+    import ${dotted_name}
+    zcml.load_config('configure.zcml', ${dotted_name})
+    fiveconfigure.debug_mode = False
+
+    # We need to tell the testing framework that these products
+    # should be available. This can't happen until after we have loaded
+    # the ZCML.
+
+    ztc.installPackage('${dotted_name}')
+
+# The order here is important: We first call the deferred function and then
+# let PloneTestCase install it during Plone site setup
+
+setup_product()
+ptc.setupPloneSite(products=['${dotted_name}'])
+
+
+class TestCase(ptc.PloneTestCase):
+    """Base class used for test cases
+    """
+
+
+class FunctionalTestCase(ptc.FunctionalTestCase):
+    """Test case class used for functional (doc-)tests
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/test_portlet.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/test_portlet.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/tests/test_portlet.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,112 @@
+from zope.component import getUtility, getMultiAdapter
+
+from plone.portlets.interfaces import IPortletType
+from plone.portlets.interfaces import IPortletManager
+from plone.portlets.interfaces import IPortletAssignment
+from plone.portlets.interfaces import IPortletDataProvider
+from plone.portlets.interfaces import IPortletRenderer
+
+from plone.app.portlets.storage import PortletAssignmentMapping
+
+from ${dotted_name} import ${portlet_filename}
+
+from ${dotted_name}.tests.base import TestCase
+
+
+class TestPortlet(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager', ))
+
+    def test_portlet_type_registered(self):
+        portlet = getUtility(
+            IPortletType,
+            name='${dotted_name}.${portlet_type_name}')
+        self.assertEquals(portlet.addview,
+                          '${dotted_name}.${portlet_type_name}')
+
+    def test_interfaces(self):
+        # TODO: Pass any keyword arguments to the Assignment constructor
+        portlet = ${portlet_filename}.Assignment()
+        self.failUnless(IPortletAssignment.providedBy(portlet))
+        self.failUnless(IPortletDataProvider.providedBy(portlet.data))
+
+    def test_invoke_add_view(self):
+        portlet = getUtility(
+            IPortletType,
+            name='${dotted_name}.${portlet_type_name}')
+        mapping = self.portal.restrictedTraverse(
+            '++contextportlets++plone.leftcolumn')
+        for m in mapping.keys():
+            del mapping[m]
+        addview = mapping.restrictedTraverse('+/' + portlet.addview)
+
+        # TODO: Pass a dictionary containing dummy form inputs from the add
+        # form.
+        # Note: if the portlet has a NullAddForm, simply call
+        # addview() instead of the next line.
+        addview.createAndAdd(data={})
+
+        self.assertEquals(len(mapping), 1)
+        self.failUnless(isinstance(mapping.values()[0],
+                                   ${portlet_filename}.Assignment))
+
+    def test_invoke_edit_view(self):
+        # NOTE: This test can be removed if the portlet has no edit form
+        mapping = PortletAssignmentMapping()
+        request = self.folder.REQUEST
+
+        mapping['foo'] = ${portlet_filename}.Assignment()
+        editview = getMultiAdapter((mapping['foo'], request), name='edit')
+        self.failUnless(isinstance(editview, ${portlet_filename}.EditForm))
+
+    def test_obtain_renderer(self):
+        context = self.folder
+        request = self.folder.REQUEST
+        view = self.folder.restrictedTraverse('@@plone')
+        manager = getUtility(IPortletManager, name='plone.rightcolumn',
+                             context=self.portal)
+
+        # TODO: Pass any keyword arguments to the Assignment constructor
+        assignment = ${portlet_filename}.Assignment()
+
+        renderer = getMultiAdapter(
+            (context, request, view, manager, assignment), IPortletRenderer)
+        self.failUnless(isinstance(renderer, ${portlet_filename}.Renderer))
+
+
+class TestRenderer(TestCase):
+
+    def afterSetUp(self):
+        self.setRoles(('Manager', ))
+
+    def renderer(self, context=None, request=None, view=None, manager=None,
+                 assignment=None):
+        context = context or self.folder
+        request = request or self.folder.REQUEST
+        view = view or self.folder.restrictedTraverse('@@plone')
+        manager = manager or getUtility(
+            IPortletManager, name='plone.rightcolumn', context=self.portal)
+
+        # TODO: Pass any default keyword arguments to the Assignment
+        # constructor.
+        assignment = assignment or ${portlet_filename}.Assignment()
+        return getMultiAdapter((context, request, view, manager, assignment),
+                               IPortletRenderer)
+
+    def test_render(self):
+        # TODO: Pass any keyword arguments to the Assignment constructor.
+        r = self.renderer(context=self.portal,
+                          assignment=${portlet_filename}.Assignment())
+        r = r.__of__(self.folder)
+        r.update()
+        #output = r.render()
+        # TODO: Test output
+
+
+def test_suite():
+    from unittest import TestSuite, makeSuite
+    suite = TestSuite()
+    suite.addTest(makeSuite(TestPortlet))
+    suite.addTest(makeSuite(TestRenderer))
+    return suite

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+${version}
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/INSTALL.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/INSTALL.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/INSTALL.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,40 @@
+#set $full_package_name = "%s.%s.%s" % ($namespace_package, $namespace_package2, $package)
+${project} Installation
+=======================
+
+ * When you're reading this you have probably already run
+   ``easy_install ${project}``. Find out how to install setuptools
+   (and EasyInstall) here:
+   http://peak.telecommunity.com/DevCenter/EasyInstall
+
+ * Create a file called ``${project}-configure.zcml`` in the
+   ``/path/to/instance/etc/package-includes`` directory.  The file
+   should only contain this::
+
+       <include package="${full_package_name}" />
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+ * Add ``${project}`` to the list of eggs to install, e.g.:
+
+    [buildout]
+    ...
+    eggs =
+        ...
+        ${project}
+
+  * Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        ${full_package_name}
+
+  * Re-run buildout, e.g. with:
+
+    $ ./bin/buildout
+
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.GPL
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.GPL	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.GPL	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/docs/LICENSE.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+  ${project} is copyright $author
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+  MA 02111-1307 USA.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_portlet/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,36 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Framework :: Plone",
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,67 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="${namespace_package}.${package}">
+
+#if str($include_doc) == 'True'
+  <!-- '$skinname' Zope 3 browser layer
+    Register views, viewlets and resources for this layer to make sure
+    they only apply to the '${skinname}' theme.
+    You can also use this layer to override default Plone browser views
+    and viewlets only within the '${skinname}' theme.
+  -->
+#else
+  <!-- '$skinname' Zope 3 browser layer -->
+#end if
+  <interface
+      interface=".interfaces.IThemeSpecific"
+      type="zope.publisher.interfaces.browser.IBrowserSkinType"
+      name="$skinname"
+      />
+  
+  <!-- Viewlets registration -->
+#if str($include_doc) == 'True'
+  <!-- EXAMPLE (UNCOMMENT TO MAKE AVAILABLE):
+  <browser:viewlet
+      name="${namespace_package}.someviewlet"
+      manager="plone.app.layout.viewlets.interfaces.IPortalFooter"
+      class=".viewlets.MyViewlet"
+      layer=".interfaces.IThemeSpecific"
+      permission="zope2.View"
+      />
+  -->
+
+#end if
+  <!-- Zope 3 browser resources -->
+
+#if str($include_doc) == 'True'
+  <!-- Resource directory for images
+    See ${namespace_package}/${package}/browser/images/README.txt
+    for more information about registering images as Zope 3 browser
+    resources.
+  -->
+#else
+  <!-- Resource directory for images -->
+#end if
+  <browser:resourceDirectory
+      name="${namespace_package}.${package}.images"
+      directory="images"
+      layer=".interfaces.IThemeSpecific"
+      />
+
+#if str($include_doc) == 'True'
+  <!-- Resource directory for stylesheets
+    See ${namespace_package}/${package}/browser/stylesheets/README.txt
+    for more information about registering stylesheets as Zope 3 browser
+    resources.
+  -->
+#else
+  <!-- Resource directory for stylesheets -->
+#end if
+  <browser:resourceDirectory
+      name="${namespace_package}.${package}.stylesheets"
+      directory="stylesheets"
+      layer=".interfaces.IThemeSpecific"
+      />
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/images/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,56 @@
+README for the 'browser/images/' directory
+==========================================
+
+This folder is a Zope 3 Resource Directory acting as a repository for images.
+
+Its declaration is located in 'browser/configure.zcml':
+
+    <!-- Resource directory for images -->
+    <browser:resourceDirectory
+        name="${namespace_package}.${package}.images"
+        directory="images"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+An image placed in this directory (e.g. 'logo.png') can be accessed from
+this relative URL:
+
+    "++resource++${namespace_package}.${package}.images/logo.png"
+
+Note that it might be better to register each of these resources separately if
+you want them to be overridable from zcml directives.
+
+The only way to override a resource in a resource directory is to override the
+entire directory (all elements have to be copied over).
+
+A Zope 3 browser resource declared like this in 'browser/configure.zcml':
+
+    <browser:resource
+        name="logo.png"
+        file="images/logo.png"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+can be accessed from this relative URL:
+
+    "++resource++logo.png"
+
+Notes
+-----
+
+* Whatever the way they are declared (in bulk inside a resource directory or
+  as separate resources), images registered as Zope 3 browser resources don't
+  have all the attributes that Zope 2 image objects have (i.e. the 'title'
+  property and the 'tag()' and 'get_size()' methods).
+  This means that if you want the html tag of your image to be auto-generated
+  (this is the case by default for the portal logo), you should store it in a
+  directory that is located in the 'skins/' folder of your package, registered
+  as a File System Directory View in the 'portal_skins' tool, and added to the
+  layers of your skin.
+
+* Customizing/overriding images that are originally accessed from the
+  'portal_skins' tool (e.g. Plone default logo and icons) can be done inside
+  that tool only. There is no known way to do it with Zope 3 browser
+  resources.
+  Vice versa, there is no known (easy) way to override a Zope 3 browser
+  resource from a skin layer in 'portal_skins'.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/interfaces.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/interfaces.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/interfaces.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,11 @@
+from plone.theme.interfaces import IDefaultPloneLayer
+
+
+class IThemeSpecific(IDefaultPloneLayer):
+    """Marker interface that defines a Zope 3 browser layer.
+#if str($include_doc) == 'True'
+       If you need to register a viewlet only for the
+       "$skinname" theme, this interface must be its layer
+       (in $package/viewlets/configure.zcml).
+#end if
+    """

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,61 @@
+README for the 'browser/stylesheets/' directory
+===============================================
+
+This folder is a Zope 3 Resource Directory acting as a repository for
+stylesheets.
+
+Its declaration is located in 'browser/configure.zcml':
+
+    <!-- Resource directory for stylesheets -->
+    <browser:resourceDirectory
+        name="${namespace_package}.${package}.stylesheets"
+        directory="stylesheets"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+A stylesheet placed in this directory (e.g. 'main.css') can be accessed from
+this relative URL:
+
+    "++resource++${namespace_package}.${package}.stylesheets/main.css"
+
+Note that it might be better to register each of these resources separately if
+you want them to be overridable from zcml directives.
+
+The only way to override a resource in a resource directory is to override the
+entire directory (all elements have to be copied over).
+
+A Zope 3 browser resource declared like this in 'browser/configure.zcml':
+
+    <browser:resource
+        name="main.css"
+        file="stylesheets/main.css"
+        layer=".interfaces.IThemeSpecific"
+        />
+
+can be accessed from this relative URL:
+
+    "++resource++main.css"
+
+Notes
+-----
+
+* Stylesheets registered as Zope 3 resources might be flagged as not found in
+  the 'portal_css' tool if the layer they are registered for doesn't match the
+  default skin set in 'portal_skins'.
+  This can be confusing but it must be considered as a minor bug in the CSS
+  registry instead of a lack in the way Zope 3 resources are handled in
+  Zope 2.
+
+* There might be a way to interpret DTML from a Zope 3 resource view.
+  Although, if you need to use DTML for setting values in a stylesheet (the
+  same way as in default Plone stylesheets where values are read from
+  'base_properties'), it is much easier to store it in a directory that is
+  located in the 'skins/' folder of your package, registered as a File System
+  Directory View in the 'portal_skins' tool, and added to the layers of your
+  skin.
+
+* Customizing/overriding stylesheets that are originally accessed from the
+  'portal_skins' tool (e.g. Plone default stylesheets) can be done inside that
+  tool only. There is no known way to do it with Zope 3 browser resources.
+  Vice versa, there is no known way to override a Zope 3 browser resource from
+  a skin layer in 'portal_skins'.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/main.css_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/main.css_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/stylesheets/main.css_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+/* Stylesheet for the '$skinname' Plone theme */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlet.pt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlet.pt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlet.pt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,14 @@
+#if str($include_doc) == 'True'
+<!--
+  'view' refers to the MyViewlet class in viewlets.py
+  If you do not need anything fancy where python code might help,
+  like just a viewlet that displays '<h1>Hello World</h1>',
+  then you can remove anything else from this page template, remove
+  viewlets.py and change the viewlet registration in configure.zcml:
+  replace
+     class=".viewlets.MyViewlet"
+  with 
+     template="viewlet.pt"
+  -->
+#end if
+<div tal:content="view/computed_value|nothing"/>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlets.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlets.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/browser/viewlets.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,27 @@
+#if str($include_doc) == 'True'
+from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+from plone.app.layout.viewlets.common import ViewletBase
+
+\# Sample code for a basic viewlet (In order to use it, you'll have to):
+\# - Un-comment the following useable piece of code (viewlet python class).
+\# - Rename the viewlet template file ('browser/viewlet.pt') and edit the
+\#   following python code accordingly.
+\# - Edit the class and template to make them suit your needs.
+\# - Make sure your viewlet is correctly registered in 'browser/configure.zcml'.
+\# - If you need it to appear in a specific order inside its viewlet manager,
+\#   edit 'profiles/default/viewlets.xml' accordingly.
+\# - Restart Zope.
+\# - If you edited any file in 'profiles/default/', reinstall your package.
+\# - Once you're happy with your viewlet implementation, remove any related
+\#   (unwanted) inline documentation  ;-p
+
+\#class MyViewlet(ViewletBase):
+\#    render = ViewPageTemplateFile('viewlet.pt')
+\##
+
+\#    def update(self):
+\#        self.computed_value = 'any output'
+#else
+\#from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
+\#from plone.app.layout.viewlets.common import ViewletBase
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    xmlns:i18n="http://namespaces.zope.org/i18n"
+    i18n_domain="${namespace_package}.${package}">
+
+#if str($zope2product) == 'True'
+  <five:registerPackage package="." initialize=".initialize" />
+#end if
+  <include package=".browser" />
+  <include file="skins.zcml" />
+  <include file="profiles.zcml" />
+  <i18n:registerTranslations directory="locales" />
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/locales/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,11 @@
+This directory will be the home for internationalizations for your theme 
+package.  For more information on internationalization please consult the 
+following sources:
+
+http://plone.org/documentation/kb/product-skin-localization
+http://plone.org/documentation/kb/i18n-for-developers
+http://www.mattdorn.com/content/plone-i18n-a-brief-tutorial/
+http://grok.zope.org/documentation/how-to/how-to-internationalize-your-application
+http://maurits.vanrees.org/weblog/archive/2007/09/i18n-locales-and-plone-3.0
+http://n2.nabble.com/Recipe-for-overriding-translations-td3045492ef221724.html
+http://dev.plone.org/plone/wiki/TranslationGuidelines

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/+namespace_package+.+package+_various.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/+namespace_package+.+package+_various.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/+namespace_package+.+package+_various.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This file is used as a marker in setuphandlers.py.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/cssregistry.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_css tool. -->
+
+#end if
+<object name="portal_css">
+
+#if str($include_doc) == 'True'
+ <!-- Stylesheets that will be registered with the portal_css tool are defined
+      here. You can also specify values for existing resources if you need to
+      modify some of their properties.
+      Stylesheet elements accept these parameters:
+      - 'id' (required): it must respect the name of the css or DTML file
+        (case sensitive). '.dtml' suffixes must be ignored.
+      - 'expression' (optional - default: ''): a tal condition.
+      - 'media' (optional - default: ''): possible values: 'screen', 'print',
+        'projection', 'handheld'...
+      - 'rel' (optional - default: 'stylesheet')
+      - 'title' (optional - default: '')
+      - 'rendering' (optional - default: 'import'): 'import', 'link' or
+        'inline'.
+      - 'enabled' (optional - default: True): boolean
+      - 'cookable' (optional - default: True): boolean (aka 'merging allowed')
+      - 'insert_before', 'insert_after' (optional - default: '') resource id
+      See registerStylesheet() arguments in
+      ResourceRegistries/tools/CSSRegistry.py for the latest list of all
+      available keys and default values.
+      -->
+#end if
+ <stylesheet title=""
+    id="++resource++${namespace_package}.${package}.stylesheets/main.css"
+    media="screen" rel="stylesheet" rendering="import"
+    cacheable="True" compression="safe" cookable="True"
+    enabled="1" expression=""/>
+
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/jsregistry.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_javascripts tool.
+     -->
+
+#end if
+<object name="portal_javascripts">
+
+#if str($include_doc) == 'True'
+ <!-- Javascript files that will be registered with the
+      portal_javascripts tool are defined here. You can also specify values
+      for existing resources if you need to modify some of their properties.
+      Javascript elements accept these parameters:
+      - 'id' (required): same rules as for stylesheets (see
+        'cssregistry.xml').
+      - 'expression' (optional - default: ''): a tal condition.
+      - 'inline' (optional - default: False)
+      - 'enabled' (optional - default: True): boolean
+      - 'cookable' (optional - default: True): boolean (aka 'merging allowed')
+      See registerScript() arguments in ResourceRegistries/tools/JSRegistry.py
+      for the latest list of all available keys and default values.
+      -->
+<!-- EXAMPLE (UNCOMMENT TO MAKE AVAILABLE):
+ <javascript
+    id="++resource++${namespace_package}.${package}.javascripts/something.js"
+    cacheable="False" compression="safe" cookable="False"
+    enabled="True" expression=""  inline="False"/>
+-->
+
+#end if
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/metadata.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,4 @@
+<?xml version="1.0"?>
+<metadata>
+  <version>1000</version>
+</metadata>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/skins.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,56 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration for the portal_skins tool -->
+
+<!-- Change the value of these parameters to modify portal_skins behavior:
+     - allow_any: change it to True if you want users to be able to select the
+       skin to use from their personal preferences management page. In the
+       ZMI, this value is known as 'Skin flexibility'.
+     - cookie_persistence: change it to True if you want to make the skin cookie
+       persist indefinitely. In the ZMI, this value is known as 'Skin Cookie
+       persistence'.
+       -->
+#end if
+<object name="portal_skins" allow_any="False" cookie_persistence="False"
+   default_skin="$skinname">
+
+#if str($include_doc) == 'True'
+ <!-- This list registers the folders that are stored in the skins directory
+      of your product (on the filesystem) as Filesystem Directory Views within
+      the portal_skins tool, so that they become usable as skin layers.
+      -->
+#end if
+ <object name="${namespace_package}_${package}_custom_images"
+    meta_type="Filesystem Directory View"
+    directory="${namespace_package}.${package}:skins/${namespace_package}_${package}_custom_images"/>
+ <object name="${namespace_package}_${package}_custom_templates"
+    meta_type="Filesystem Directory View"
+    directory="${namespace_package}.${package}:skins/${namespace_package}_${package}_custom_templates"/>
+ <object name="${namespace_package}_${package}_styles"
+    meta_type="Filesystem Directory View"
+    directory="${namespace_package}.${package}:skins/${namespace_package}_${package}_styles"/>
+
+#if str($include_doc) == 'True'
+ <!-- A skin-path in this file corresponds to a Skin Selection in the
+     'Properties' tab of the portal_skins tool, in the ZMI.
+     You can define for each new skin path the layers that it holds. A new
+     skin can be based on another existing one by using the 'based-on'
+     attribute.
+     The definition of a layer accepts these parameters:
+       - name: quite self explanatory, the name of the layer.
+       - insert-before: name of the layer before which it must be added.
+       - insert-after: name of the layer after which it must be added.
+       Note: insert-before (and -after) accepts the value "*" which means
+       "all".
+       -->
+#end if
+ <skin-path name="$skinname" based-on="$skinbase">
+  <layer name="${namespace_package}_${package}_custom_images"
+     insert-after="custom"/>
+  <layer name="${namespace_package}_${package}_custom_templates"
+     insert-after="${namespace_package}_${package}_custom_images"/>
+  <layer name="${namespace_package}_${package}_styles"
+     insert-after="${namespace_package}_${package}_custom_templates"/>
+ </skin-path>
+
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/viewlets.xml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/viewlets.xml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles/default/viewlets.xml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+<?xml version="1.0"?>
+#if str($include_doc) == 'True'
+<!-- This file holds the setup configuration of the viewlet managers
+     for the "$skinname" skin.
+     -->
+
+#end if
+<object>
+
+#if str($include_doc) == 'True'
+  <!-- Viewlets keep the same ordering than the default skin ('Plone Default'
+       out of the box).
+       You can specify skinname="*" if you want changes apply for all skins.
+       Using "True"" for the 'make-default' parameter will make the 'skinname'
+       value set as default skinname. Means the name of the skin that would be
+       used in case the viewlets ordering was not specified for the currently
+       used skin.
+       The 'based-on' attribute lets you inherit the viewlets ordering from an
+       existing skin.
+       -->
+  <order manager="plone.portalfooter" skinname="$skinname"
+         based-on="Plone Default">
+    <!-- The definition of a viewlet accepts these parameters:
+         - name: quite self explanatory, the name of the viewlet.
+         - insert-before: name of the viewlet before which it must be added or
+           moved.
+         - insert-after: name of the viewlet after which it must be added
+           or moved.
+         - remove: supported but rarely needed, removes the viewlet from the
+           ordering list (doesn't mean that it hides the viewlet).
+         Note: insert-before and -after accept the value "*" which means
+         "all".
+         -->
+<!-- EXAMPLE (UNCOMMENT TO MAKE AVAILABLE):
+    <viewlet name="${namespace_package}.someviewlet"
+             insert-before="*" />
+-->
+  </order>
+
+  <hidden manager="plone.portalheader" skinname="$skinname">
+<!-- EXAMPLE (UNCOMMENT TO MAKE AVAILABLE):
+    <viewlet name="plone.global_sections" />
+-->
+  </hidden>
+
+#end if
+</object>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/profiles.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,24 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
+    i18n_domain="${namespace_package}.${package}">
+
+#if str($add_profile) == 'True'
+  <genericsetup:registerProfile
+      name="default"
+      title="$skinname"
+      directory="profiles/default"
+      description='Extension profile for the "${skinname}" Plone theme.'
+      provides="Products.GenericSetup.interfaces.EXTENSION"
+      />
+
+  <genericsetup:importStep
+      name="${namespace_package}.${package}.various"
+      title="${skinname}: miscellaneous import steps"
+      description="Various import steps that are not handled by GS import/export handlers."
+      handler="${namespace_package}.${package}.setuphandlers.setupVarious">
+    <depends name="skins"/>
+  </genericsetup:importStep>
+#end if
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/setuphandlers.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/setuphandlers.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/setuphandlers.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,11 @@
+def setupVarious(context):
+
+    # Ordinarily, GenericSetup handlers check for the existence of XML files.
+    # Here, we are not parsing an XML file, but we use this text file as a
+    # flag to check that we actually meant for this import step to be run.
+    # The file is found in profiles/default.
+
+    if context.readDataFile('${namespace_package}.${package}_various.txt') is None:
+        return
+
+    # Add additional setup code here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_images/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+This folder holds Filesystem Image files that are registered for the
+'${skinname}' Skin Selection only.
+They act as replacement for the default Plone (or 3rd party products) ones.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_custom_templates/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+This folder holds Filesystem Page Template files that are registered for the
+'${skinname}' Skin Selection only.
+They act as replacement for the default Plone (or 3rd party products) ones.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/CONTENT.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/CONTENT.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/CONTENT.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+This folder holds stylesheet files that are registered for the
+'${skinname}' Skin Selection only.
+
+It is a repository for customizations of the default Plone stylesheets,
+as well as for package specific stylesheets.
+
+
+Note
+    Stylesheet files that don't use DTML can also stored in the 'browser'
+    folder and accessed as Zope 3 file resources.
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml file shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base_properties.props_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base_properties.props_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/base_properties.props_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+title:string=$skinname's color, font, logo and border defaults
+
+plone_skin:string=$skinname
+
+logoName:string=logo.jpg
+
+fontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+fontBaseSize:string=69%
+fontColor:string=Black
+fontSmallSize:string=85%
+
+backgroundColor:string=White
+
+linkColor:string=#436976
+linkActiveColor:string=Red
+linkVisitedColor:string=Purple
+
+borderWidth:string=1px
+borderStyle:string=solid
+borderStyleAnnotations:string=dashed
+
+globalBorderColor:string=#8cacbb
+globalBackgroundColor:string=#dee7ec
+globalFontColor:string=#436976
+
+headingFontFamily:string="Lucida Grande", Verdana, Lucida, Helvetica, Arial, sans-serif
+
+contentViewBorderColor:string=#74ae0b
+contentViewBackgroundColor:string=#cde2a7
+contentViewFontColor:string=#578308
+
+inputFontColor:string=Black
+
+textTransform:string=lowercase
+
+evenRowBackgroundColor:string=#eef3f5 
+oddRowBackgroundColor:string=transparent
+
+notifyBorderColor:string=#ffa500
+notifyBackgroundColor:string=#ffce7b
+
+discreetColor:string=#76797c
+helpBackgroundColor:string=#ffffe1
+
+portalMinWidth:string=70em
+columnOneWidth:string=16em
+columnTwoWidth:string=16em

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/portlets.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/portlets.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/portlets.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml file shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/public.css.dtml
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/public.css.dtml	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins/+namespace_package+_+package+_styles/public.css.dtml	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+/*
+  This file is based on the ploneCustom.css.dtml file shipped with Plone.
+
+  <dtml-with base_properties> (do not remove this)
+  <dtml-call "REQUEST.set('portal_url', portal_url())"> (not this either)
+*/
+
+/* YOUR CSS RULES START HERE */
+
+
+
+/* YOUR CSS RULES STOP HERE */
+
+/* </dtml-with> */
+
+/* Latest version of the documentation on pre-defined properties from Plone 
+   can be found in CMFPlone/skins/plone_styles/ploneCustom.css.dtml */
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/skins.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,18 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:cmf="http://namespaces.zope.org/cmf"
+    i18n_domain="${namespace_package}.${package}">
+
+  <!-- File System Directory Views registration -->
+  <cmf:registerDirectory name="${namespace_package}_${package}_custom_images"/>
+  <cmf:registerDirectory name="${namespace_package}_${package}_custom_templates"/>
+  <cmf:registerDirectory name="${namespace_package}_${package}_styles"/>
+
+#if str($include_doc) == 'True'
+  <!-- Note: This could also be done for all folders at once
+       by replacing the previous lines with this one:
+  <cmf:registerDirectory name="skins" directory="skins" recursive="True" />
+  -->
+
+#end if
+</configure>
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/version.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/version.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+namespace_package+/+package+/version.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+${version}
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+project+-configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+project+-configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/+project+-configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+<include package="${namespace_package}.${package}" />
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/MANIFEST.in_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/MANIFEST.in_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone3_theme/MANIFEST.in_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+recursive-include ${namespace_package} *
+global-exclude *pyc
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,173 @@
+================================
+Plone 4 buildout for developers
+================================
+
+.. contents ::
+
+Introduction
+------------
+
+`Buildout <http://www.buildout.org>`_ is a tool which automatically downloads, installs and configures Python software.
+Plone developers prefer uses buildout based installation method - it makes it easy to work with source code and developing your own Plone add-ons.
+
+For production site installations please use `standard Plone installer <http://plone.org/download>`_.
+
+Prerequisitements
+-----------------
+
+What you need in order to use developer buildout with Plone 4
+
+* Experience using command line tools
+
+* Experience using a text editor to work with configuration files (``buildout.cfg``)
+
+* GCC compiler suite to build native Python extensions (Zope contains C code for optimized parts)
+
+* Python 2.6 (other versions are *not* ok for Plone 4)
+
+* Python Imaging Library installed for your Python interpreter (more below)
+
+* Python `Distribute <http://pypi.python.org/pypi/distribute>`_ installation tool, provided by your operating system
+  or installed by hand
+
+Read below from operating system specific instructions how to install these dependencies.
+
+Features
+--------
+
+This buildout provides
+
+* Zope start up scripts (one instance)
+
+* ``paster`` command for creating Plone add-ons (different from system-wide installation)
+
+* `test <http://plone.org/documentation/manual/plone-community-developer-documentation/testing-and-debugging/unit-testing>`_ command for running automatic test suites 
+
+* `i18ndude <http://pypi.python.org/pypi/i18ndude>`_  for managing text string translations in Python source code 
+
+* `omelette <http://pypi.python.org/pypi/collective.recipe.omelette>`_ buildout recipe which makes Python egg source code more browseable by using symlinks
+
+* `mr.developer <http://pypi.python.org/pypi/mr.developer>`_ command for managing source code checkouts and updates with buildout repeatable manner
+
+* `collective.developermanual <http://plone.org/documentation/manual/plone-community-developer-documentation>`_ - community managed developer manual for Plone
+  in source code form, ready for contributions
+
+Creating Plone 4 buildout installation
+------------------------------------------
+
+Install ZopeSkel template package for your system-wide Python using Distribute::
+
+ easy_install ZopeSkel
+ 
+... or upgrade existing installation::
+
+ easy_install -U ZopeSkel
+
+You probably got here by running something like (replace *myplonefoldername* with the target folder where you want to Plone to be installed)::
+
+ zopeskel plone4_buildout myplonefoldername
+
+Now, you need to run (please see remarks regarding your operating system below)::
+
+ python bootstrap.py
+
+This will create ``bin`` folder and ``bin/buildout`` script. If you any time want to change Python interpreter
+associated with buildout, or you need to update ``buildout`` script itself to newer version please rerun ``bootsrap.py``.
+
+Now you can run buildout script which will download all Python packages
+(.egg files) and create ``parts/`` and ``var/`` folder structure ::
+
+  bin/buildout
+
+If this succesfully completes you can start buildout in foreground mode (Press *CTRL+C* to terminate)::
+
+  bin/instance fg 
+
+Now you can login to your site
+
+  http://localhost:8080
+
+The default user is ``admin`` with password ``admin``. 
+After initial start-up admin password is stored in Data.fs databse file and value in ``buildout.cfg`` is ignored.
+Please follow `these instructions to change admin password <http://manage.plone.org/documentation/kb/changing-the-admin-password>`_.
+
+Next steps
+----------
+
+Creating your first add-on
+==========================
+
+Plone 4 buildout comes with ``bin/paster`` command for creating Plone add-ons.
+
+.. note ::
+
+	When working with Plone add-ons, use paster command from buildout bin folder, not the system wide paster command.
+
+Create theme (applies for Plone 4 also)::
+	
+	bin/zopeskel plone3_theme plonetheme.mythemeid
+	
+Create Archetypes based content types package::
+
+	bin/zopeskel archetype mycompanyid.content
+
+Create other Plone customizations::
+
+	bin/zopeskel plone mycompanyid.mypackageid
+
+More info
+
+* `Instructions how to use Paster command to create your own add-ons <http://collective-docs.plone.org/tutorials/paste.html>`_ 
+
+Managing source code checkouts with buildout
+=============================================
+
+`mr.developer buildout extension <http://pypi.python.org/pypi/mr.developer>`_ command which can be used with buildout to manage your source code repositories
+*mr.developer* makes source code checkout from multiple repositores a repeatable task.
+
+Operating system specific instructions 
+-------------------------------------------
+
+Ubuntu/Debian
+==============
+
+Tested for Ubuntu 10.10.
+
+Install prerequisitements::
+
+	sudo apt-get install python2.6 python-imaging wget build-essential python2.6-dev python-setuptools
+	easy_install ZopeSkel
+
+OSX
+====
+
+Install `OSX development tools (XCode) <http://developer.apple.com/>`_ from Apple.
+
+Install `Macports <http://www.macports.org/>`_.
+
+Then the following installs dependencies::
+
+	sudo port install python26 py26-pil py26-distribute wget 
+	easy_install ZopeSkel
+
+When you run ``bootstrap.py``use the following command to make sure you are using Python interpreter from Macports::
+
+	python2.6 bootstrap.py
+
+Windows
+========
+
+Microsoft Windows systems is problematic because
+it does not provide to Microsoft Visual C compiler (commercial) which is
+required to build native Python extensions.
+
+Please read
+
+* http://plone.org/documentation/kb/using-buildout-on-windows
+
+Other
+-----
+
+The orignal copy of these instructions is available at
+
+* https://svn.plone.org/svn/collective/ZopeSkel/trunk/zopeskel/templates/plone4_buildout/README.txt

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,120 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+"""
+
+import os
+import shutil
+import sys
+import tempfile
+import urllib2
+from optparse import OptionParser
+
+tmpeggs = tempfile.mkdtemp()
+
+is_jython = sys.platform.startswith('java')
+
+# parsing arguments
+parser = OptionParser()
+parser.add_option("-v", "--version", dest="version",
+                          help="use a specific zc.buildout version")
+parser.add_option("-d", "--distribute",
+                   action="store_true", dest="distribute", default=False,
+                   help="Use Disribute rather than Setuptools.")
+
+parser.add_option("-c", None, action="store", dest="config_file",
+                   help=("Specify the path to the buildout configuration "
+                         "file to be used."))
+
+options, args = parser.parse_args()
+
+# if -c was provided, we push it back into args for buildout' main function
+if options.config_file is not None:
+    args += ['-c', options.config_file]
+
+if options.version is not None:
+    VERSION = '==%s' % options.version
+else:
+    VERSION = ''
+
+# We decided to always use distribute, make sure this is the default for us
+# USE_DISTRIBUTE = options.distribute
+USE_DISTRIBUTE = True
+args = args + ['bootstrap']
+
+to_reload = False
+try:
+    import pkg_resources
+    if not hasattr(pkg_resources, '_distribute'):
+        to_reload = True
+        raise ImportError
+except ImportError:
+    ez = {}
+    if USE_DISTRIBUTE:
+        setup_url = 'http://python-distribute.org/distribute_setup.py'
+        exec urllib2.urlopen(setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0, no_fake=True)
+    else:
+        ez_setup_url = 'http://peak.telecommunity.com/dist/ez_setup.py'
+        exec urllib2.urlopen(ez_setup_url).read() in ez
+        ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    if to_reload:
+        reload(pkg_resources)
+    else:
+        import pkg_resources
+
+
+def quote(c):
+    if sys.platform == 'win32':
+        if ' ' in c:
+            return '"%s"' % c  # work around spawn lamosity on windows
+    return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws = pkg_resources.working_set
+
+if USE_DISTRIBUTE:
+    requirement = 'distribute'
+else:
+    requirement = 'setuptools'
+
+pythonpath = ws.find(pkg_resources.Requirement.parse(requirement)).location
+
+if is_jython:
+    import subprocess
+
+    assert subprocess.Popen([sys.executable] + ['-c', quote(cmd), '-mqNxd',
+           quote(tmpeggs), 'zc.buildout' + VERSION],
+           env=dict(os.environ,
+               PYTHONPATH=pythonpath),
+           ).wait() == 0
+
+else:
+    assert os.spawnle(
+        os.P_WAIT, sys.executable, quote(sys.executable),
+        '-c', quote(cmd), '-mqNxd', quote(tmpeggs), 'zc.buildout' + VERSION,
+        dict(os.environ,
+            PYTHONPATH=pythonpath),
+        ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout' + VERSION)
+import zc.buildout.buildout
+zc.buildout.buildout.main(args)
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,102 @@
+# buildout.cfg file for Plone 4 development work
+# - for production installations please use http://plone.org/download
+#
+# Each part has more information about its recipe on PyPi
+# http://pypi.python.org/pypi 
+# ... just reach by the recipe name
+[buildout]
+parts =  
+    instance
+    zopepy
+    i18ndude
+    zopeskel
+    test
+\#    omelette
+
+extends = 
+    http://dist.plone.org/release/${plone_version}/versions.cfg
+	
+\# Add additional egg download sources here. dist.plone.org contains archives
+\# of Plone packages.
+find-links =
+    http://dist.plone.org/release/${plone_version}
+    http://dist.plone.org/thirdparty
+
+extensions = 
+    mr.developer
+    buildout.dumppickedversions
+    buildout.threatlevel
+
+sources = sources
+	
+versions = versions
+
+\# Reference any folders where you have Python egg source code under development here 
+\# e.g.: develop = src/my.package
+\# If you are using the mr.developer extension and have the source code in a 
+\# repository mr.developer will handle this automatically for you
+develop =
+
+
+\# Create bin/instance command to manage Zope start up and shutdown
+[instance]
+recipe = plone.recipe.zope2instance
+user = admin:admin
+http-address = 8080
+debug-mode = off
+verbose-security = on
+blob-storage = var/blobstorage
+
+eggs =
+	Plone
+
+\# Some pre-Plone 3.3 packages may need you to register the package name here in 
+\# order their configure.zcml to be run (http://plone.org/products/plone/roadmap/247)
+\# - this is never required for packages in the Products namespace (Products.*)
+zcml =
+
+
+\# zopepy commands allows you to execute Python scripts using a PYTHONPATH 
+\# including all the configured eggs
+[zopepy]
+recipe = zc.recipe.egg
+eggs = \${instance:eggs}
+interpreter = zopepy
+scripts = zopepy
+
+\# create bin/i18ndude command
+[i18ndude]
+unzip = true
+recipe = zc.recipe.egg
+eggs = i18ndude
+
+\# create bin/test command
+[test]
+recipe = zc.recipe.testrunner
+defaults = ['--auto-color', '--auto-progress']
+eggs =
+    \${instance:eggs}
+
+\# create ZopeSkel command
+[zopeskel]
+unzip = true
+recipe = zc.recipe.egg
+eggs =
+    ZopeSkel
+    \${instance:eggs}
+
+\# symlinks all Python source code to parts/omelette folder when buildout is run
+\# windows users will need to install additional software for this part to build 
+\# correctly.  See http://pypi.python.org/pypi/collective.recipe.omelette for
+\# relevant details.
+\# [omelette]
+\# recipe = collective.recipe.omelette
+\# eggs = \${instance:eggs}
+
+\# Put your mr.developer managed source code repositories here, see
+\# http://pypi.python.org/pypi/mr.developer for details on format for this part
+[sources]
+collective.developermanual = svn http://svn.plone.org/svn/collective/collective.developermanual
+
+\# Version pindowns for new style products go here - this section extends one provided in http://dist.plone.org/release/
+[versions]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone4_buildout/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+#
+
+#if str($zope2product) == 'True'
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+#end if

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    i18n_domain="${namespace_package}.${namespace_package2}.${package}">
+
+#if str($zope2product) == 'True'
+  <five:registerPackage package="." initialize=".initialize" />
+#end if
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,54 @@
+import unittest
+
+from zope.testing import doctestunit
+from zope.component import testing
+from Testing import ZopeTestCase as ztc
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import PloneSite
+ptc.setupPloneSite()
+
+import ${namespace_package}.${namespace_package2}.${package}
+
+class TestCase(ptc.PloneTestCase):
+    class layer(PloneSite):
+        @classmethod
+        def setUp(cls):
+            fiveconfigure.debug_mode = True
+            zcml.load_config('configure.zcml',
+                             ${namespace_package}.${namespace_package2}.${package})
+            fiveconfigure.debug_mode = False
+
+        @classmethod
+        def tearDown(cls):
+            pass
+
+
+def test_suite():
+    return unittest.TestSuite([
+
+        \# Unit tests
+        \#doctestunit.DocFileSuite(
+        \#    'README.txt', package='${namespace_package}.${namespace_package2}.${package}',
+        \#    setUp=testing.setUp, tearDown=testing.tearDown),
+
+        \#doctestunit.DocTestSuite(
+        \#    module='${namespace_package}.${namespace_package2}.${package}.mymodule',
+        \#    setUp=testing.setUp, tearDown=testing.tearDown),
+
+
+        \# Integration tests that use PloneTestCase
+        \#ztc.ZopeDocFileSuite(
+        \#    'README.txt', package='${namespace_package}.${namespace_package2}.${package}',
+        \#    test_class=TestCase),
+
+        \#ztc.FunctionalDocFileSuite(
+        \#    'browser.txt', package='${namespace_package}.${namespace_package2}.${package}',
+        \#    test_class=TestCase),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/+namespace_package+/+namespace_package2+/+package+/version.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+${version}
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/INSTALL.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/INSTALL.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/INSTALL.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,52 @@
+#set $full_package_name = "%s.%s.%s" % ($namespace_package, $namespace_package2, $package)
+${project} Installation
+=======================
+
+ * When you're reading this you have probably already run
+   ``easy_install ${project}``. Find out how to install setuptools
+   (and EasyInstall) here:
+   http://peak.telecommunity.com/DevCenter/EasyInstall
+
+#if str($zope2product) == 'True'
+ * Get `pythonproducts`_ and install it via::
+
+       python setup.py install --home /path/to/instance
+
+   into your Zope instance.
+
+#end if
+ * Create a file called ``${project}-configure.zcml`` in the
+   ``/path/to/instance/etc/package-includes`` directory.  The file
+   should only contain this::
+
+       <include package="${full_package_name}" />
+
+#if str($zope2product) == 'True'
+.. _pythonproducts: http://plone.org/products/pythonproducts
+#end if
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+ * Add ``${project}`` to the list of eggs to install, e.g.:
+
+    [buildout]
+    ...
+    eggs =
+        ...
+        ${project}
+
+  * Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        ${full_package_name}
+
+  * Re-run buildout, e.g. with:
+
+    $ ./bin/buildout
+
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.GPL
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.GPL	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.GPL	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/docs/LICENSE.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+  ${project} is copyright $author
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+  MA 02111-1307 USA.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_app/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,36 @@
+from setuptools import setup, find_packages
+import os
+
+version = ${repr($version) or "0.0"}
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=open("README.txt").read() + "\n" +
+                       open(os.path.join("docs", "HISTORY.txt")).read(),
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        "Framework :: Plone",
+        "Programming Language :: Python",
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=[
+          'setuptools',
+          # -*- Extra requirements: -*-
+      ],
+      entry_points="""
+      # -*- Entry points: -*-
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,52 @@
+Plone hosting buildout
+======================
+
+Process control
+---------------
+
+All services are controlled using the supervisord_ process manager. Supervisord
+takes care of starting all daemons, restarting them when needed and can
+optionally provide a web interface allowing for easy remote management.
+
+To start supervisord starts its daemon ``bin/supervisord``. This will
+automatically start the ZEO server, Zope and, if enabled, Varnish. You
+start, stop and restart those via the ``bin/supervisorctl`` utility.
+
+To start all processes automatically on system boot it is necessary to
+start supervisord as part of the system boot process. This can easily
+be done by adding a crontab entry to the account used for your site::
+
+  # Automatically start the plone.org website
+  @reboot /srv/plone.org/bin/supervisord -c /srv/plone.org/etc/supervisord.conf
+
+.. _supervisord: http://www.supervisord.org/
+
+
+Log rotation
+------------
+
+This buildout includes a configuration for ``logrotate``, which is included
+in all common Linux distributions. To setup log rotation you will need to
+add an entry to the crontab entry for the account user for your site::
+
+  # Rotate plone.org logfiles at 06:00
+  0 6 * * * /usr/sbin/logrotate --state /srv/plone.org/var/logrotate.status /srv/plone.org/etc/logrotate.conf
+
+
+Selecting product and package versions
+--------------------------------------
+
+For production environment it is generally a good idea to enforce
+use of specific, tested, versions of all packages and products. This
+can prevent unexpected surprises when updating a buildout environment
+or deploying it on another machine.
+
+For Zope2 products it is recommended to use a release tar or zip-archive.
+This can be installed using the *productdistros* section in ``buildout.cfg``.
+See `plone.recipe.distros`_ for more information.
+
+Packages can be pinned down in the *versions* section, also located in
+``buildout.cfg``.
+
+.. _plone.recipe.distros: http://pypi.python.org/pypi/plone.recipe.distros
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/base.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/base.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/base.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,93 @@
+[buildout]
+parts =
+    plone
+    zope2
+    productdistros
+    zeo
+    instance1
+    zopepy
+#if $proxy
+    varnish-build
+    varnish
+#end if
+    logrotate
+    supervisor
+find-links =
+    http://dist.plone.org
+    http://effbot.org/downloads
+eggs =
+develop =
+versions = versions
+
+[versions]
+plone.recipe.zope2instance = 3.6
+
+[plone]
+recipe = ${plone_recipe}
+#if $plone_recipe == "plone.recipe.plone25install"
+url = ${plone_url}
+#end if
+
+[zope2]
+recipe = plone.recipe.zope2install
+url = \${plone:zope2-url}
+
+[productdistros]
+recipe = plone.recipe.distros
+urls =
+nested-packages =
+version-suffix-packages =
+
+[zeo]
+recipe = plone.recipe.zope2zeoserver
+zope2-location = \${zope2:location}
+zeo-address = 127.0.0.1:${zeo_port}
+
+[instance1]
+recipe = plone.recipe.zope2instance
+zope2-location = \${zope2:location}
+debug-mode = off
+verbose-security = off
+zeo-client = True
+zeo-address = \${zeo:zeo-address}
+user = ${zope_user}:${zope_password}
+http-address = 127.0.0.1:${http_port}
+eggs =
+    \${buildout:eggs}
+    \${plone:eggs}
+    elementtree
+zcml =
+products =
+    \${buildout:directory}/products
+    \${productdistros:location}
+    \${plone:products}
+
+[zopepy]
+recipe = zc.recipe.egg
+eggs = \${instance1:eggs}
+interpreter = zopepy
+extra-paths = \${zope2:location}/lib/python
+scripts = zopepy
+
+#if $proxy
+[varnish-build]
+recipe = plone.recipe.varnish:build
+url = http://puzzle.dl.sourceforge.net/sourceforge/varnish/varnish-1.1.2.tar.gz
+
+[varnish]
+recipe = plone.recipe.varnish:instance
+backends = \${instance1:http-address}
+bind = 127.0.0.1:${proxy_port}
+cache-size = 512M
+#end if
+
+[logrotate]
+recipe = collective.recipe.template
+input = templates/logrotate.conf
+output = \${buildout:directory}/etc/logrotate.conf
+
+[supervisor]
+recipe = zc.recipe.egg
+eggs = supervisor
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 85041 2008-03-31 15:57:30Z andreasjung $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, quote (sys.executable),
+    '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,25 @@
+# This is the zc.buildout configuration
+# For more information on managing your Plone instance using buildout please
+# see http://plone.org/documentation/tutorial/buildout
+
+[buildout]
+extends = base.cfg
+versions = versions
+eggs =
+develop =
+
+[versions]
+#if $plone_recipe == "plone.recipe.plone"
+${plone_recipe} = ${plone_recipe_version}
+#end if
+
+[productdistros]
+urls =
+nested-packages =
+version-suffix-packages =
+
+[instance1]
+eggs =
+    \${buildout:eggs}
+    \${plone:eggs}
+zcml =

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/etc/supervisord.conf_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/etc/supervisord.conf_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/etc/supervisord.conf_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,49 @@
+[unix_http_server]
+file=%(here)s/../var/supervisor.sock
+chmod=0600
+
+[supervisorctl]
+serverurl=unix://%(here)s/../var/supervisor.sock
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory=supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisord]
+logfile=%(here)s/../var/log/supervisord.log
+logfile_maxbytes=5MB
+logfile_backups=10
+loglevel=info
+pidfile=%(here)s/../var/supervisord.pid ;
+childlogdir=%(here)s/../var/log
+nodaemon=false              ; (start in foreground if true;default false)
+minfds=1024                 ; (min. avail startup file descriptors;default 1024)
+minprocs=200                ; (min. avail process descriptors;default 200)
+directory=%(here)s
+
+[program:zeo]
+command = %(here)s/../bin/zeo fg
+autostart= true
+autorestart = true
+startsecs = 10
+priority = 100
+
+[program:instance1]
+command = %(here)s/../bin/instance1 console
+startsecs = 60
+priority = 2
+redirect_stderr = true
+autostart= true
+autorestart = true
+priority = 500
+
+[groups]
+programs = instance1
+
+#if $proxy
+[program:varnish]
+command = %(here)s/../bin/varnish -F
+autostart= true
+autorestart = true
+priority = 1000
+#end if
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/products/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/products/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/products/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Old-style Zope products you are developing can be added here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/templates/logrotate.conf
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/templates/logrotate.conf	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/templates/logrotate.conf	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+# This file is generated from templates/logrotate.conf.
+# Please do not edit the copy in etc/
+
+rotate 4
+weekly
+create
+compress
+delaycompress
+
+${buildout:directory}/var/log/zeo.log {
+    postrotate
+        ${buildout:bin-directory}/zeo logreopen
+    endscript
+}
+
+${buildout:directory}/var/log/instance1.log ${buildout:directory}/var/log/instance1-Z2.log {
+    sharedscripts
+    postrotate
+        /bin/kill -USR2 $(cat ${buildout:directory}/var/instance1.pid)
+    endscript
+}
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_hosting/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,44 @@
+Tests for ${namespace_package}.${namespace_package2}.${package}
+
+test setup
+----------
+
+    >>> from Testing.ZopeTestCase import user_password
+    >>> from Products.Five.testbrowser import Browser
+    >>> browser = Browser()
+
+Plugin setup
+------------
+
+    >>> acl_users_url = "%s/acl_users" % self.portal.absolute_url()
+    >>> browser.addHeader('Authorization', 'Basic %s:%s' % ('portal_owner', user_password))
+    >>> browser.open("%s/manage_main" % acl_users_url)
+    >>> browser.url
+    'http://nohost/plone/acl_users/manage_main'
+    >>> form = browser.getForm(index=0)
+    >>> select = form.getControl(name=':action')
+
+${namespace_package}.${namespace_package2}.${package} should be in the list of installable plugins:
+
+    >>> '${multiplugin_name} Helper' in select.displayOptions
+    True
+
+and we can select it:
+
+    >>> select.getControl('${multiplugin_name} Helper').click()
+    >>> select.displayValue
+    ['${multiplugin_name} Helper']
+    >>> select.value
+    ['manage_addProduct/${namespace_package}.${namespace_package2}.${package}/manage_add_${package}_helper_form']
+
+we add '${multiplugin_name} Helper' to acl_users:
+
+    >>> from ${namespace_package}.${namespace_package2}.${package}.plugin import ${multiplugin_name}Helper
+    >>> myhelper = ${multiplugin_name}Helper('myplugin', '${multiplugin_name} Helper')
+    >>> self.portal.acl_users['myplugin'] = myhelper
+
+and so on. Continue your tests here
+
+    >>> 'ALL OK'
+    'ALL OK'
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+import install
+
+install.register_${package}_plugin()
+
+def initialize(context):
+    """Initializer called when used as a Zope 2 product."""
+    install.register_${package}_plugin_class(context)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/add_plugin.zpt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/add_plugin.zpt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/add_plugin.zpt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,46 @@
+<h1 tal:replace="structure here/manage_page_header">Header</h1>
+
+<h2 tal:define="form_title string:Add ${package} Helper"
+    tal:replace="structure here/manage_form_title">Form Title</h2>
+
+<p class="form-help">
+SSL Basic Authentication for Pluggable Auth Service functionality.
+</p>
+
+<form action="manage_add_${package}_helper" method="post"
+ enctype="multipart/form-data">
+<table cellspacing="0" cellpadding="2" border="0">
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-label">
+    Id
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="id" size="40" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    <div class="form-optional">
+    Title
+    </div>
+    </td>
+    <td align="left" valign="top">
+    <input type="text" name="title" size="40" />
+    </td>
+  </tr>
+  <tr>
+    <td align="left" valign="top">
+    </td>
+    <td align="left" valign="top">
+    <div class="form-element">
+    <input class="form-element" type="submit" name="submit"
+     value=" Add " />
+    </div>
+    </td>
+  </tr>
+</table>
+</form>
+
+<h1 tal:replace="structure here/manage_page_footer">Footer</h1>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="${namespace_package}.${namespace_package2}.${package}">
+
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/icon.gif
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/browser/icon.gif
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/configure.zcml_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,10 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:five="http://namespaces.zope.org/five"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="${namespace_package}.${namespace_package2}.${package}">
+
+  <five:registerPackage package="." initialize=".initialize" />
+  <include package=".browser" />
+
+</configure>

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/install.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/install.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/install.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,39 @@
+from AccessControl.Permissions import manage_users
+from Products.PageTemplates.PageTemplateFile import PageTemplateFile
+from Products.PluggableAuthService import registerMultiPlugin
+
+import plugin
+
+manage_add_${package}_form = PageTemplateFile('browser/add_plugin',
+                            globals(), __name__='manage_add_${package}_form' )
+
+
+def manage_add_${package}_helper( dispatcher, id, title=None, REQUEST=None ):
+    """Add an ${package} Helper to the PluggableAuthentication Service."""
+
+    sp = plugin.${multiplugin_name}Helper( id, title )
+    dispatcher._setObject( sp.getId(), sp )
+
+    if REQUEST is not None:
+        REQUEST['RESPONSE'].redirect( '%s/manage_workspace'
+                                      '?manage_tabs_message='
+                                      '${package}Helper+added.'
+                                      % dispatcher.absolute_url() )
+
+
+def register_${package}_plugin():
+    try:
+        registerMultiPlugin(plugin.${multiplugin_name}Helper.meta_type)
+    except RuntimeError:
+        # make refresh users happy
+        pass
+
+
+def register_${package}_plugin_class(context):
+    context.registerClass(plugin.${multiplugin_name}Helper,
+                          permission = manage_users,
+                          constructors = (manage_add_${package}_form,
+                                          manage_add_${package}_helper),
+                          visibility = None,
+                          icon='browser/icon.gif'
+                         )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/interface.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/interface.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/interface.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,5 @@
+from Products.PluggableAuthService import interfaces
+  
+class I${multiplugin_name}Helper(# -*- implemented plugins -*-
+                                ):
+    """interface for ${multiplugin_name}Helper."""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugin.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugin.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugin.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+"""Class: ${multiplugin_name}Helper
+"""
+
+from AccessControl.SecurityInfo import ClassSecurityInfo
+from App.class_init import default__class_init__ as InitializeClass
+
+from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin
+from Products.PluggableAuthService.utils import classImplements
+
+import interface
+import plugins
+
+class ${multiplugin_name}Helper( # -*- implemented plugins -*-
+                               ):
+    """Multi-plugin
+
+    """
+
+    meta_type = '${package} Helper'
+    security = ClassSecurityInfo()
+
+    def __init__( self, id, title=None ):
+        self._setId( id )
+        self.title = title
+
+
+
+classImplements(${multiplugin_name}Helper, interface.I${multiplugin_name}Helper)
+
+InitializeClass( ${multiplugin_name}Helper )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/plugins/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+# -*- implemented plugins -*-

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/+namespace_package+/+namespace_package2+/+package+/tests.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,40 @@
+import unittest
+
+from zope.testing import doctestunit
+from zope.component import testing
+from Testing import ZopeTestCase as ztc
+
+from Products.Five import zcml
+from Products.Five import fiveconfigure
+from Products.PloneTestCase import PloneTestCase as ptc
+from Products.PloneTestCase.layer import PloneSite
+ptc.setupPloneSite()
+
+import ${namespace_package}.${namespace_package2}.${package}
+
+class TestCase(ptc.PloneTestCase):
+    class layer(PloneSite):
+        @classmethod
+        def setUp(cls):
+            fiveconfigure.debug_mode = True
+            zcml.load_config('configure.zcml',
+                             ${namespace_package}.${namespace_package2}.${package})
+            fiveconfigure.debug_mode = False
+
+        @classmethod
+        def tearDown(cls):
+            pass
+
+
+def test_suite():
+    return unittest.TestSuite([
+
+        ztc.FunctionalDocFileSuite(
+            'README.txt', package='${namespace_package}.${namespace_package2}.${package}',
+            test_class=TestCase),
+
+        ])
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CHANGES.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CHANGES.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CHANGES.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+#set $header_text = "%s (xxxx-xx-xx)" % $version or "0.0.0"
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+- Created recipe with ZopeSkel
+  [${$author or $empty}].

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CONTRIBUTORS.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CONTRIBUTORS.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/CONTRIBUTORS.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+${$author or $empty}, Author
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/INSTALL.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/INSTALL.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/INSTALL.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,42 @@
+#set $full_package_name = "%s.%s.%s" % ($namespace_package, $namespace_package2, $package)
+#set $header_text = "%s Installation" % $project
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+* When you're reading this you have probably already run
+  ``easy_install ${project}``. Find out how to install setuptools
+  (and EasyInstall) here:
+  http://peak.telecommunity.com/DevCenter/EasyInstall
+
+* Create a file called ``${project}-configure.zcml`` in the
+  ``/path/to/instance/etc/package-includes`` directory.  The file
+  should only contain this:
+
+    <include package="${full_package_name}" />
+
+Alternatively, if you are using zc.buildout and the plone.recipe.zope2instance
+recipe to manage your project, you can do this:
+
+* Add ``${full_package_name}`` to the list of eggs to install, e.g.:
+
+    [buildout]
+    ...
+    eggs =
+        ...
+        ${full_package_name}
+
+* Tell the plone.recipe.zope2instance recipe to install a ZCML slug:
+
+    [instance]
+    recipe = plone.recipe.zope2instance
+    ...
+    zcml =
+        ${full_package_name}
+
+* Re-run buildout, e.g. with:
+
+    $ ./bin/buildout
+
+You can skip the ZCML slug if you are going to explicitly include the package
+from another package's configure.zcml file.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.GPL
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.GPL	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.GPL	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,339 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/LICENSE.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+  ${project} is copyright $author
+
+  This program is free software; you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation; either version 2 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program; if not, write to the Free Software
+  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+  MA 02111-1307 USA.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/docs/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+.. contents::
+
+.. Note!
+   -----
+   Update the following URLs to point to your:
+
+   - code repository
+   - bug tracker
+   - questions/comments feedback mail
+   (do not set a real mail, to avoid spams)
+
+   Or remove it if not used.
+
+- Code repository: http://svn.somewhere.com/...
+- Questions and comments to somemailing_list
+- Report bugs at http://bug.somewhere.com/..
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/plone_pas/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+"""
+This module contains the tool of $project
+"""
+import os
+from setuptools import setup, find_packages
+
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = ${repr($version) or "0.0.0"}
+
+long_description = (
+    read('docs', 'README.txt')
+    + '\n' +
+    'Change history\n'
+    '**************\n'
+    + '\n' +
+    read('docs', 'CHANGES.txt')
+    + '\n' +
+    'Detailed Documentation\n'
+    '**********************\n'
+    + '\n' +
+    read(${repr($namespace_package)},
+         ${repr($namespace_package2)},
+         ${repr($package)}, 'README.txt')
+    + '\n' +
+    'Contributors\n'
+    '************\n'
+    + '\n' +
+    read('docs', 'CONTRIBUTORS.txt')
+    + '\n' +
+    'Download\n'
+    '********\n')
+
+tests_require = ['zope.testing']
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=long_description,
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        'Framework :: Plone',
+        'Intended Audience :: Developers',
+        #from zopeskel.base import LICENSE_CATEGORIES
+        #if $license_name.strip() in $LICENSE_CATEGORIES
+        $repr($LICENSE_CATEGORIES[$license_name.strip()]),
+        #end if
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=['setuptools',
+                        # -*- Extra requirements: -*-
+                        ],
+      tests_require=tests_require,
+      extras_require=dict(tests=tests_require),
+      test_suite='$namespace_package.$namespace_package2.${package}.tests.test_docs.test_suite',
+      entry_points="""
+      # -*- entry_points -*-
+
+      [z3c.autoinclude.plugin]
+      target = plone
+      """,
+      setup_requires=["PasteScript"],
+      paster_plugins=["ZopeSkel"],
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,61 @@
+Supported options
+=================
+
+The recipe supports the following options:
+
+.. Note to recipe author!
+   ----------------------
+   For each option the recipe uses you should include a description
+   about the purpose of the option, the format and semantics of the
+   values it accepts, whether it is mandatory or optional and what the
+   default value is if it is omitted.
+
+option1
+    Description for ``option1``...
+
+option2
+    Description for ``option2``...
+
+
+Example usage
+=============
+
+.. Note to recipe author!
+   ----------------------
+   zc.buildout provides a nice testing environment which makes it
+   relatively easy to write doctests that both demonstrate the use of
+   the recipe and test it.
+   You can find examples of recipe doctests from the PyPI, e.g.
+   
+     http://pypi.python.org/pypi/zc.recipe.egg
+
+   The PyPI page for zc.buildout contains documentation about the test
+   environment.
+
+     http://pypi.python.org/pypi/zc.buildout#testing-support
+
+   Below is a skeleton doctest that you can start with when building
+   your own tests.
+
+We'll start by creating a buildout that uses the recipe::
+
+    >>> write('buildout.cfg',
+    ... """
+    ... [buildout]
+    ... parts = test1
+    ...
+    ... [test1]
+    ... recipe = $project
+    ... option1 = %(foo)s
+    ... option2 = %(bar)s
+    ... """ % { 'foo' : 'value1', 'bar' : 'value2'})
+
+Running the buildout gives us::
+
+    >>> print 'start', system(buildout) 
+    start...
+    Installing test1.
+    Unused options for test1: 'option2' 'option1'.
+    <BLANKLINE>
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,20 @@
+# -*- coding: utf-8 -*-
+"""Recipe $package"""
+
+class Recipe(object):
+    """zc.buildout recipe"""
+
+    def __init__(self, buildout, name, options):
+        self.buildout, self.name, self.options = buildout, name, options
+
+    def install(self):
+        """Installer"""
+        # XXX Implement recipe functionality here
+        
+        # Return files that were created by the recipe. The buildout
+        # will remove all returned files upon reinstall.
+        return tuple()
+
+    def update(self):
+        """Updater"""
+        pass

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+# package

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/test_docs.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/test_docs.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/+package+/tests/test_docs.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,47 @@
+# -*- coding: utf-8 -*-
+"""
+Doctest runner for ${repr($project)}.
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+import zc.buildout.tests
+import zc.buildout.testing
+
+from zope.testing import doctest, renormalizing
+
+optionflags =  (doctest.ELLIPSIS |
+                doctest.NORMALIZE_WHITESPACE |
+                doctest.REPORT_ONLY_FIRST_FAILURE)
+
+def setUp(test):
+    zc.buildout.testing.buildoutSetUp(test)
+
+    # Install the recipe in develop mode
+    zc.buildout.testing.install_develop('$project', test)
+
+    # Install any other recipes that should be available in the tests
+    #zc.buildout.testing.install('collective.recipe.foobar', test)
+
+def test_suite():
+    suite = unittest.TestSuite((
+            doctest.DocFileSuite(
+                '../README.txt',
+                setUp=setUp,
+                tearDown=zc.buildout.testing.buildoutTearDown,
+                optionflags=optionflags,
+                checker=renormalizing.RENormalizing([
+                        # If want to clean up the doctest output you
+                        # can register additional regexp normalizers
+                        # here. The format is a two-tuple with the RE
+                        # as the first item and the replacement as the
+                        # second item, e.g.
+                        # (re.compile('my-[rR]eg[eE]ps'), 'my-regexps')
+                        zc.buildout.testing.normalize_path,
+                        ]),
+                ),
+            ))
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/+namespace_package2+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/__init__.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/__init__.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/+namespace_package+/__init__.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,6 @@
+# See http://peak.telecommunity.com/DevCenter/setuptools#namespace-packages
+try:
+    __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+    from pkgutil import extend_path
+    __path__ = extend_path(__path__, __name__)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CHANGES.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CHANGES.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CHANGES.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+#set $header_text = "%s (xxxx-xx-xx)" % ($version or "0.0.0",)
+#set $header_line = "-" * len($header_text)
+$header_text
+$header_line
+
+- Created recipe with ZopeSkel
+  [${$author or $empty}]

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CONTRIBUTORS.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CONTRIBUTORS.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/CONTRIBUTORS.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+${$author or $empty}, Author
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/README.txt_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/README.txt_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/README.txt_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,17 @@
+.. contents::
+
+.. Note to recipe author!
+   ---------------------
+   Update the following URLs to point to your:
+   
+   - code repository
+   - bug tracker 
+   - questions/comments feedback mail 
+   (do not set a real mail, to avoid spams)
+
+   Or remove it if not used.
+
+- Code repository: http://svn.somewhere.com/...
+- Questions and comments to somemailing_list
+- Report bugs at http://bug.somewhere.com/..
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 85041 2008-03-31 15:57:30Z andreasjung $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, quote (sys.executable),
+    '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,8 @@
+[buildout]
+develop = .
+parts = test
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = ${project} [tests]
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/setup.py_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/setup.py_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/recipe/setup.py_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,72 @@
+# -*- coding: utf-8 -*-
+"""
+This module contains the tool of $project
+"""
+import os
+from setuptools import setup, find_packages
+
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+version = ${repr($version) or "0.0.0"}
+
+long_description = (
+    read('README.txt')
+    + '\n' +
+    'Detailed Documentation\n'
+    '**********************\n'
+    + '\n' +
+    read(${repr($namespace_package)}, ${repr($namespace_package2)}, ${repr($package)}, 'README.txt')
+    + '\n' +
+    'Contributors\n'
+    '************\n'
+    + '\n' +
+    read('CONTRIBUTORS.txt')
+    + '\n' +
+    'Change history\n'
+    '**************\n'
+    + '\n' +
+    read('CHANGES.txt')
+    + '\n' +
+   'Download\n'
+    '********\n')
+
+entry_point = '$namespace_package.$namespace_package2.${package}:Recipe'
+entry_points = {"zc.buildout": ["default = %s" % entry_point]}
+
+tests_require = ['zope.testing', 'zc.buildout']
+
+setup(name=${repr($project)},
+      version=version,
+      description="${description or None}",
+      long_description=long_description,
+      # Get more strings from
+      # http://pypi.python.org/pypi?:action=list_classifiers
+      classifiers=[
+        'Framework :: Buildout',
+        'Intended Audience :: Developers',
+        'Topic :: Software Development :: Build Tools',
+        #from zopeskel.base import LICENSE_CATEGORIES
+        #if $license_name.strip() in $LICENSE_CATEGORIES
+        $repr($LICENSE_CATEGORIES[$license_name.strip()]),
+        #end if
+        ],
+      keywords=${repr($keywords) or $empty},
+      author=${repr($author) or $empty},
+      author_email=${repr($author_email) or $empty},
+      url=${repr($url) or $empty},
+      license=${repr($license_name) or $empty},
+      packages=find_packages(exclude=['ez_setup']),
+      namespace_packages=['$namespace_package', '$namespace_package.$namespace_package2'],
+      include_package_data=True,
+      zip_safe=${repr(bool($zip_safe)) or False},
+      install_requires=['setuptools',
+                        'zc.buildout'
+                        # -*- Extra requirements: -*-
+                        ],
+      tests_require=tests_require,
+      extras_require=dict(tests=tests_require),
+      test_suite='$namespace_package.$namespace_package2.${package}.tests.test_docs.test_suite',
+      entry_points=entry_points,
+      )

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,262 @@
+=======================
+Using a custom buildout
+=======================
+
+Note: If you are using Windows, please see below.
+
+You probably got here by running something like:
+
+ $ paster create -t silva_buildout
+
+Now, you need to run, using python 2.4:
+
+ $ python bootstrap.py
+
+This will install zc.buildout for you.
+
+To create an instance immediately, run:
+
+ $ bin/buildout
+
+This will install Silva for you, as well as other dependencies, create
+a new Zope 2 installation (unless you specified an existing one when
+you ran "paster create"), and create a new Zope instance configured
+with these products.
+
+You can start your Zope instance by running:
+
+ $ bin/instance start
+
+or, to run in foreground mode:
+
+ $ bin/instance fg
+
+To run unit tests, you can use:
+
+ $ bin/instance test -s my.package
+
+
+Using a different Python installation
+--------------------------------------
+
+Buildout will use your system Python installation by default. However, Zope
+2.10 (and by extension, Silva) will only work with Python 2.4. You can verify
+which version of Python you have, by running:
+
+ $ python -V
+
+If that is not a 2.4 version, you need to install Python 2.4 from
+http://python.org. If you wish to keep another version as your main system
+Python, edit buildout.cfg and add an 'executable' option to the "[buildout]"
+section, pointing to a python interpreter binary:
+
+ [buildout]
+ ...
+ executable = /path/to/python
+
+
+Working with buildout.cfg
+-------------------------
+
+You can change any option in buildout.cfg and re-run bin/buildout to reflect
+the changes. This may delete things inside the 'parts' directory, but should
+keep your Data.fs and source files intact.
+
+To save time, you can run buildout in "offline" (-o) and non-updating (-N)
+mode, which will prevent it from downloading things and checking for new
+versions online:
+
+ $ bin/buildout -Nov
+
+
+Developing old-style products
+-----------------------------
+
+If you are developing old-style Zope 2 products (not eggs) then you can do so
+by placing the product code in the top-level 'products' directory. This is
+analogous to the 'Products/' directory inside a normal Zope 2 instance and is
+scanned on start-up for new products.
+
+Depending on a new egg
+----------------------
+
+If you want to use a new egg that is in the Python Package Index, all you need
+to do is to add it to the "eggs" option under the main "[buildout]" section:
+
+ [buildout]
+ ...
+ eggs +=
+    my.package
+
+If it's listed somewhere else than the Python Package Index, you can add a link
+telling buildout where to find it in the 'find-links' option:
+
+ [buildout]
+ ...
+ find-links +=
+    http://some.host.com/packages
+
+Using existing old-style products
+---------------------------------
+
+If you are using an old-style (non-egg) product, you can either add it as an
+automatically downloaded archive or put it in the top-level "products" folder.
+The former is probably better, because it means you can redistribute your
+buildout.cfg more easily:
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://infrae.com/download/someproduct/releases/1.3/someproduct-1.3.tar.gz
+
+If someproduct-1.3.tar.gz extracts into several products inside a top-level
+directory, e.g. SomeProduct-1.3/PartOne and SomeProduct-1.3/PartTwo, then
+add it as a "nested package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://infrae.com/download/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ nested-packages =
+    someproduct-1.3.tar.gz
+
+Alternatively, if it extracts to a directory which contains the version
+number, add it as a "version suffix package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://infrae.com/download/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ version-suffix-packages =
+    someproduct-1.3.tar.gz
+
+You can also track products by adding a new bundle checkout part. It
+doesn't strictly have to be an svn bundle at all, any svn location will do,
+and cvs is also supported:
+
+ [buildout]
+ ...
+ parts +=
+    myproduct
+    productdistros
+
+Note that "myproduct" comes before the "instance" part. You then
+need to add a new section to buildout.cfg:
+
+ [myproduct]
+ recipe = plone.recipe.bundlecheckout
+ url = http://svn.plone.org/svn/collective/myproduct/trunk
+
+Finally, you need to tell Zope to find this new checkout and add it to its
+list of directories that are scanned for products:
+
+ [instance]
+ ...
+ products +=
+    ${myproduct:location}
+    ${productdistros:location}
+
+Without this last step, the "myproduct" part is simply managing an svn
+checkout and could potentially be used for something else instead.
+
+=============
+Using Windows
+=============
+
+To use buildout on Windows, you will need to install a few dependencies which
+other platforms manage on their own.
+
+Here are the steps you need to follow (thanks to Hanno Schlichting for these):
+
+Python (http://python.org)
+--------------------------
+
+  - Download and install Python 2.4.4 using the Windows installer from
+    http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi
+    Select 'Install for all users' and it will put Python into the
+    "C:\Python24" folder by default.
+
+  - You also want the pywin32 extensions available from
+    http://downloads.sourceforge.net/pywin32/pywin32-210.win32-py2.4.exe?modtime=1159009237&big_mirror=0
+
+  - If you develop Zope based applications you will usually only need Python 2.4
+    at the moment, so it's easiest to put the Python binary on the systems PATH,
+    so you don't need to specify its location manually each time you call it.
+
+    Thus, put "C:\Python24" and "C:\Python24\Scripts" onto the PATH. You can
+    find the PATH definition in the control panel under system preferences on
+    the advanced tab at the bottom. The button is called environment variables.
+    You want to add it at the end of the already existing PATH in the system
+    section. Paths are separated by a semicolons.
+
+  - You can test if this was successful by opening a new shell (cmd) and type
+    in 'python -V'. It should report version 2.4.4 (or whichever version you
+    installed).
+
+    Opening a new shell can be done quickly by using the key combination
+    'Windows-r' or if you are using Parallels on a Mac 'Apple-r'. Type in 'cmd'
+    into the popup box that opens up and hit enter.
+
+
+Subversion (http://subversion.tigris.org)
+-----------------------------------------
+
+  - Download the nice installer from
+    http://subversion.tigris.org/files/documents/15/35379/svn-1.4.2-setup.exe
+
+  - Run the installer. It defaults to installing into
+    "C:\Program Files\Subversion".
+
+  - Now put the install locations bin subfolder (for example
+    "C:\Program Files\Subversion\bin") on your system PATH in the same way you
+    put Python on it.
+
+  - Open a new shell again and type in: 'svn --version' it should report
+    version 1.4.2 or newer.
+
+
+MinGW (http://www.mingw.org/)
+-----------------------------
+
+  This is a native port of the gcc compiler and its dependencies for Windows.
+  There are other approaches enabling you to compile Python C extensions on
+  Windows including Cygwin and using the official Microsoft C compiler, but this
+  is a lightweight approach that uses only freely available tools. As
+  it's used by a lot of people chances are high it will work for you and there's
+  plenty of documentation out there to help you in troubleshooting problems.
+
+  - Download the MinGW installer from
+    http://downloads.sourceforge.net/mingw/MinGW-5.1.3.exe?modtime=1168794334&big_mirror=1
+
+  - The installer will ask you which options you would like to install. Choose
+    base and make here. It will install into "C:\MinGW" by default. The install
+    might take some time as it's getting files from sourceforge.net and you
+    might need to hit 'retry' a couple of times.
+
+  - Now put the install location's bin subfolder (for example "C:\MinGW\bin") on
+    your system PATH in the same way you put Python on it.
+
+  - Test this again by typing in: 'gcc --version' on a newly opened shell and
+    it should report version 3.4.2 or newer.
+
+
+Configure Distutils to use MinGW
+--------------------------------
+
+  Some general information are available from
+  http://www.mingw.org/MinGWiki/index.php/Python%20extensions for example but
+  you don't need to read them all.
+
+  - Create a file called 'distutils.cfg' in "C:\Python24\Lib\distutils". Open it
+    with a text editor ('notepad distutils.cfg') and fill in the following lines:
+
+    [build]
+    compiler=mingw32
+
+    This will tell distutils to use MinGW as the default compiler, so you don't
+    need to specify it manually using "--compiler=mingw32" while calling a
+    package's setup.py with a command that involves building C extensions. This
+    is extremely useful if the build command is written down in a buildout
+    recipe where you cannot change the options without hacking the recipe
+    itself. The z2c.recipe.zope2install used in ploneout is one such example.
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 74790 2008-10-31 20:59:38Z jjmojojjmojo $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, quote (sys.executable),
+    '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,35 @@
+[buildout]
+#if not $zope2_install
+parts -=
+    zope2
+#end if
+
+extends =
+    https://svn.infrae.com/buildout/silva/${silva_distribution}.cfg
+
+\# Reference any eggs you are developing here, one per line
+\# e.g.: develop = src/my.package
+develop =
+
+[instance]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.zope2instance
+recipe = plone.recipe.zope2instance
+#if $zope2_install
+zope2-location = ${zope2_install}
+#else
+zope2-location = \${zope2:location}
+#end if
+user = ${zope_user}:${zope_password}
+http-address = ${http_port}
+#if $debug_mode == 'on'
+debug-mode = on
+#else
+\#debug-mode = on
+#end if
+#if $verbose_security == 'on'
+verbose-security = on
+#else
+\#verbose-security = on
+#end if
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/products/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/products/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/products/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Old-style Zope products you are developing can be added here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/silva_buildout/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,285 @@
+=======================
+Using a custom buildout
+=======================
+
+Using a different Python installation
+--------------------------------------
+
+Buildout will use your system Python installation by default. However, Zope
+2.10 (and by extension, Plone) will only work with Python 2.4. You can verify
+which version of Python you have, by running:
+
+ $ python -V
+
+If that is not a 2.4 version, you need to install Python 2.4 from
+http://python.org. If you wish to keep another version as your main system
+Python, edit buildout.cfg and add an 'executable' option to the "[buildout]"
+section, pointing to a python interpreter binary:
+
+ [buildout]
+ ...
+ executable = /path/to/python
+
+Working with buildout.cfg
+-------------------------
+
+You can change any option in buildout.cfg and re-run bin/buildout to reflect
+the changes. This may delete things inside the 'parts' directory, but should
+keep your Data.fs and source files intact.
+
+To save time, you can run buildout in "offline" (-o) and non-updating (-N)
+mode, which will prevent it from downloading things and checking for new
+versions online:
+
+ $ bin/buildout -Nov
+
+Creating new eggs
+-----------------
+
+New packages you are working on (but which are not yet released as eggs and
+uploaded to the Python Package Index, aka PYPI) should be placed in src. You can do:
+
+ $ cd src/
+ $ paster create -t plone my.package
+
+Use "paster create --list-templates" to see all available templates. Answer
+the questions and you will get a new egg. Then tell buildout about your egg
+by editing buildout.cfg and adding your source directory to 'develop':
+
+ [buildout]
+ ...
+ develop =
+    src/my.package
+
+You can list multiple packages here, separated by whitespace or indented
+newlines.
+
+You probably also want the Zope instance to know about the package. Add its
+package name to the list of eggs in the "[instance]" section, or under the
+main "[buildout]" section:
+
+ [instance]
+ ...
+ eggs =
+    ${buildout:eggs}
+    ${plone:eggs}
+    my.package
+
+Leave the ${buildout:eggs} part in place - it tells the instance to use the
+eggs that buildout will have downloaded from the Python Package Index
+previously.
+
+If you also require a ZCML slug for your package, buildout can create one
+automatically. Just add the package to the 'zcml' option:
+
+ [instance]
+ ...
+ zcml =
+    my.package
+
+When you are finished, re-run buildout. Offline, non-updating mode should
+suffice:
+
+ $ bin/buildout -Nov
+
+Developing old-style products
+-----------------------------
+
+If you are developing old-style Zope 2 products (not eggs) then you can do so
+by placing the product code in the top-level 'products' directory. This is
+analogous to the 'Products/' directory inside a normal Zope 2 instance and is
+scanned on start-up for new products.
+
+Depending on a new egg
+----------------------
+
+If you want to use a new egg that is in the Python Package Index, all you need
+to do is to add it to the "eggs" option under the main "[buildout]" section:
+
+ [buildout]
+ ...
+ eggs =
+    my.package
+
+If it's listed somewhere else than the Python Package Index, you can add a link
+telling buildout where to find it in the 'find-links' option:
+
+ [buildout]
+ ...
+ find-links =
+    http://dist.plone.org
+    http://download.zope.org/distribution/
+    http://effbot.org/downloads
+    http://some.host.com/packages
+
+Using existing old-style products
+---------------------------------
+
+If you are using an old-style (non-egg) product, you can either add it as an
+automatically downloaded archive or put it in the top-level "products" folder.
+The former is probably better, because it means you can redistribute your
+buildout.cfg more easily:
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+
+If someproduct-1.3.tar.gz extracts into several products inside a top-level
+directory, e.g. SomeProduct-1.3/PartOne and SomeProduct-1.3/PartTwo, then
+add it as a "nested package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ nested-packages =
+    someproduct-1.3.tar.gz
+
+Alternatively, if it extracts to a directory which contains the version
+number, add it as a "version suffix package":
+
+ [productdistros]
+ recipe = plone.recipe.distros
+ urls =
+    http://plone.org/products/someproduct/releases/1.3/someproduct-1.3.tar.gz
+ version-suffix-packages =
+    someproduct-1.3.tar.gz
+
+You can also track products by adding a new bundle checkout part. It
+doesn't strictly have to be an svn bundle at all, any svn location will do,
+and cvs is also supported:
+
+ [buildout]
+ ...
+ parts =
+    zope2
+    productdistros
+    myproduct
+    instance
+    zopepy
+
+Note that "myproduct" comes before the "instance" part. You then
+need to add a new section to buildout.cfg:
+
+ [myproduct]
+ recipe = plone.recipe.bundlecheckout
+ url = http://svn.plone.org/svn/collective/myproduct/trunk
+
+Finally, you need to tell Zope to find this new checkout and add it to its
+list of directories that are scanned for products:
+
+ [instance]
+ ...
+ products =
+    ${buildout:directory}/products
+    ${productdistros:location}
+    ${plonebundle:location}
+    ${myproduct:location}
+
+Without this last step, the "myproduct" part is simply managing an svn
+checkout and could potentially be used for something else instead.
+
+=============
+Using Windows
+=============
+
+To use buildout on Windows, you will need to install a few dependencies which
+other platforms manage on their own.
+
+Here are the steps you need to follow (thanks to Hanno Schlichting for these):
+
+Python (http://python.org)
+--------------------------
+
+  - Download and install Python 2.4.4 using the Windows installer from
+    http://www.python.org/ftp/python/2.4.4/python-2.4.4.msi
+    Select 'Install for all users' and it will put Python into the
+    "C:\Python24" folder by default.
+
+  - You also want the pywin32 extensions available from
+    http://downloads.sourceforge.net/pywin32/pywin32-210.win32-py2.4.exe?modtime=1159009237&big_mirror=0
+
+  - And as a last step you want to download the Python imaging library available
+    from http://effbot.org/downloads/PIL-1.1.6.win32-py2.4.exe
+
+  - If you develop Zope based applications you will usually only need Python 2.4
+    at the moment, so it's easiest to put the Python binary on the systems PATH,
+    so you don't need to specify its location manually each time you call it.
+
+    Thus, put "C:\Python24" and "C:\Python24\Scripts" onto the PATH. You can
+    find the PATH definition in the control panel under system preferences on
+    the advanced tab at the bottom. The button is called environment variables.
+    You want to add it at the end of the already existing PATH in the system
+    section. Paths are separated by a semicolons.
+
+  - You can test if this was successful by opening a new shell (cmd) and type
+    in 'python -V'. It should report version 2.4.4 (or whichever version you
+    installed).
+
+    Opening a new shell can be done quickly by using the key combination
+    'Windows-r' or if you are using Parallels on a Mac 'Apple-r'. Type in 'cmd'
+    into the popup box that opens up and hit enter.
+
+
+Subversion (http://subversion.tigris.org)
+-----------------------------------------
+
+  - Download the nice installer from
+    http://subversion.tigris.org/files/documents/15/35379/svn-1.4.2-setup.exe
+
+  - Run the installer. It defaults to installing into
+    "C:\Program Files\Subversion".
+
+  - Now put the install locations bin subfolder (for example
+    "C:\Program Files\Subversion\bin") on your system PATH in the same way you
+    put Python on it.
+
+  - Open a new shell again and type in: 'svn --version' it should report
+    version 1.4.2 or newer.
+
+
+MinGW (http://www.mingw.org/)
+-----------------------------
+
+  This is a native port of the gcc compiler and its dependencies for Windows.
+  There are other approaches enabling you to compile Python C extensions on
+  Windows including Cygwin and using the official Microsoft C compiler, but this
+  is a lightweight approach that uses only freely available tools. As
+  it's used by a lot of people chances are high it will work for you and there's
+  plenty of documentation out there to help you in troubleshooting problems.
+
+  - Download the MinGW installer from
+    http://downloads.sourceforge.net/mingw/MinGW-5.1.3.exe?modtime=1168794334&big_mirror=1
+
+  - The installer will ask you which options you would like to install. Choose
+    base and make here. It will install into "C:\MinGW" by default. The install
+    might take some time as it's getting files from sourceforge.net and you
+    might need to hit 'retry' a couple of times.
+
+  - Now put the install location's bin subfolder (for example "C:\MinGW\bin") on
+    your system PATH in the same way you put Python on it.
+
+  - Test this again by typing in: 'gcc --version' on a newly opened shell and
+    it should report version 3.4.2 or newer.
+
+
+Configure Distutils to use MinGW
+--------------------------------
+
+  Some general information are available from
+  http://www.mingw.org/MinGWiki/index.php/Python%20extensions for example but
+  you don't need to read them all.
+
+  - Create a file called 'distutils.cfg' in "C:\Python24\Lib\distutils". Open it
+    with a text editor ('notepad distutils.cfg') and fill in the following lines:
+
+    [build]
+    compiler=mingw32
+
+    This will tell distutils to use MinGW as the default compiler, so you don't
+    need to specify it manually using "--compiler=mingw32" while calling a
+    package's setup.py with a command that involves building C extensions. This
+    is extremely useful if the build command is written down in a buildout
+    recipe where you cannot change the options without hacking the recipe
+    itself. The z2c.recipe.zope2install used in ploneout is one such example.

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/bootstrap.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/bootstrap.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/bootstrap.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,62 @@
+##############################################################################
+#
+# Copyright (c) 2006 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.
+#
+##############################################################################
+"""Bootstrap a buildout-based project
+
+Simply run this script in a directory containing a buildout.cfg.
+The script accepts buildout command-line options, so you can
+use the -c option to specify an alternate configuration file.
+
+$Id: bootstrap.py 85041 2008-03-31 15:57:30Z andreasjung $
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+try:
+    import pkg_resources
+except ImportError:
+    ez = {}
+    exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
+                         ).read() in ez
+    ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
+
+    import pkg_resources
+
+if sys.platform == 'win32':
+    def quote(c):
+        if ' ' in c:
+            return '"%s"' % c # work around spawn lamosity on windows
+        else:
+            return c
+else:
+    def quote (c):
+        return c
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+ws  = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, quote (sys.executable),
+    '-c', quote (cmd), '-mqNxd', quote (tmpeggs), 'zc.buildout',
+    dict(os.environ,
+         PYTHONPATH=
+         ws.find(pkg_resources.Requirement.parse('setuptools')).location
+         ),
+    ) == 0
+
+ws.add_entry(tmpeggs)
+ws.require('zc.buildout')
+import zc.buildout.buildout
+zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
+shutil.rmtree(tmpeggs)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/buildout.cfg_tmpl
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/buildout.cfg_tmpl	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/buildout.cfg_tmpl	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,94 @@
+[buildout]
+parts =
+#if not $zope2_install
+    zope2
+#end if
+    productdistros
+    instance
+    zopepy
+
+\# Add additional egg download sources here. 
+find-links =
+    http://download.zope.org/ppix/
+    http://download.zope.org/distribution/
+    http://effbot.org/downloads
+
+\# Add additional eggs here
+eggs =
+
+\# Reference any eggs you are developing here, one per line
+\# e.g.: develop = src/my.package
+develop =
+
+#if not $zope2_install
+[zope2]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.zope2install
+recipe = plone.recipe.zope2install
+url = http://www.zope.org/Products/Zope/${zope2_version}/Zope-${zope2_version}-final.tgz
+#end if
+
+\# Use this section to download additional old-style products.
+\# List any number of URLs for product tarballs under URLs (separate
+\# with whitespace, or break over several lines, with subsequent lines
+\# indented). If any archives contain several products inside a top-level
+\# directory, list the archive file name (i.e. the last part of the URL,
+\# normally with a .tar.gz suffix or similar) under 'nested-packages'.
+\# If any archives extract to a product directory with a version suffix, list
+\# the archive name under 'version-suffix-packages'.
+[productdistros]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.distros
+recipe = plone.recipe.distros
+urls =
+nested-packages =
+version-suffix-packages =
+
+[instance]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/plone.recipe.zope2instance
+recipe = plone.recipe.zope2instance
+#if $zope2_install
+zope2-location = ${zope2_install}
+#else
+zope2-location = \${zope2:location}
+#end if
+user = ${zope_user}:${zope_password}
+http-address = ${http_port}
+#if $debug_mode == 'on'
+debug-mode = on
+#else
+\#debug-mode = on
+#end if
+#if $verbose_security == 'on'
+verbose-security = on
+#else
+\#verbose-security = on
+#end if
+
+\# If you want Zope to know about any additional eggs, list them here.
+\# This should include any development eggs you listed in develop-eggs above,
+\# e.g. eggs = \${buildout:eggs} \${plone:eggs} my.package
+eggs =
+    \${buildout:eggs}
+
+\# If you want to register ZCML slugs for any packages, list them here.
+\# e.g. zcml = my.package my.other.package
+zcml =
+
+products =
+    \${buildout:directory}/products
+    \${productdistros:location}
+
+[zopepy]
+\# For more information on this step and configuration options see:
+\# http://pypi.python.org/pypi/zc.recipe.egg
+recipe = zc.recipe.egg
+eggs = \${instance:eggs}
+interpreter = zopepy
+#if $zope2_install
+extra-paths = ${zope2_install}/lib/python
+#else
+extra-paths = \${zope2:location}/lib/python
+#end if
+scripts = zopepy

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/products/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/products/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/products/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Old-style Zope products you are developing can be added here

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/templates/zope2_buildout/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,2 @@
+# package
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_all.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_all.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_all.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,21 @@
+import unittest
+
+from zopeskel.tests.test_zopeskeldocs import test_suite as doc_test_suite
+from zopeskel.tests.test_base import test_suite as base_test_suite
+from zopeskel.tests.test_vars import test_suite as vars_test_suite
+from zopeskel.tests.test_zopeskel_script import test_suite as script_test_suite
+
+def test_suite():
+    """ it appears that the order here makes a difference, ensure that doc_test_suite
+        is always added last
+    """
+    suite = unittest.TestSuite([
+        base_test_suite(),
+        vars_test_suite(),
+        script_test_suite(),
+        doc_test_suite(),
+    ])
+    return suite
+    
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_base.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_base.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_base.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,157 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+
+from paste.script.command import get_commands
+
+from zopeskel.base import BaseTemplate, get_var
+from zopeskel.vars import var, BooleanVar, StringVar, TextVar, DottedVar
+from zopeskel.vars import EXPERT, EASY
+from zopeskel.archetype import Archetype
+from zopeskel.plone import Plone
+from zopeskel.basic_namespace import BasicNamespace
+
+class test_base_template(unittest.TestCase):
+    """ test for methods on the base template class
+    """
+    def setUp(self):
+        """ set up some basics for the coming tests
+        """
+        self.vars = [
+            var('basic_var', 'This is a basic variable',
+                title="Basic Title", default="foo",
+                modes=(EXPERT, EASY)),
+            BooleanVar('bool_var', 'This is a boolean variable',
+                       title="Boolean Title", default=False, page='Main',
+                       modes=(EASY)),
+            StringVar('str_var', 'This is a string variable',
+                      title="String Title", default="string", page='Carl',
+                      modes=(EXPERT)),
+            TextVar('txt_var', 'This is a text variable', page='Martin',
+                    title="Text Title", default="text",
+                    modes=()),
+            DottedVar('dot_var', 'This is a dotted variable',
+                      title="Dotted Title", default="dotted.variable")
+        ]
+        self.template = BaseTemplate('my_name')
+        create = get_commands()['create'].load()
+        command = create('create')
+        command.parse_args(['-t','archetype'])
+        self.command = command
+
+    def test_filter_for_modes(self):
+        """ _filter_for_modes should return a dictionary of var names to
+            be hidden from view dependent on the running mode of zopeskel
+            and the modes property of each variable
+        """
+        easy_vars = [var.name for var in self.vars
+                     if EASY not in var.modes]
+        expert_vars = [var.name for var in self.vars
+                       if EXPERT not in var.modes]
+
+        expert_mode = EASY
+        hidden = self.template._filter_for_modes(expert_mode, self.vars)
+
+        self.assertEqual(len(hidden), 2)
+        for varname in hidden.keys():
+            self.failUnless(varname in easy_vars,
+                            "missing easy var: %s" % varname)
+
+        expert_mode = EXPERT
+        hidden = self.template._filter_for_modes(expert_mode, self.vars)
+
+        self.assertEqual(len(hidden), 2)
+        for varname in hidden.keys():
+            self.failUnless(varname in expert_vars,
+                            "missing expert var: %s" % varname)
+
+    def test_get_vars(self):
+        """ get_vars is not a method of BaseTemplate, but we've got a nice set
+            of variables all set up in here, so let's use it
+        """
+        var = get_var(self.vars, 'basic_var')
+        self.assertEqual(var.name, 'basic_var')
+        self.assertEqual(var.title, 'Basic Title')
+        self.assertEqual(var.description, 'This is a basic variable')
+        self.assertEqual(var.modes, (EXPERT, EASY))
+        self.assertEqual(var.default, 'foo')
+
+    def test_pages(self):
+        """ pagaes divide questions for a template into discreet sets for web GUI
+        """
+        class MyTemplate(BaseTemplate):
+            vars = BaseTemplate.vars + self.vars
+
+        template = MyTemplate('some_name')
+        pages = template.pages
+        self.assertEqual(len(pages), 4)
+
+        page = pages.pop(0)
+        self.assertEqual(page['name'], 'Begin')
+        questions = page['vars']
+        self.assertEqual(len(questions), 1)
+        self.assertEqual(questions[0].name, 'expert_mode')
+        page = pages.pop(0)
+        self.assertEqual(page['name'], 'Main')
+        questions = page['vars']
+        self.assertEqual(len(questions), 3)
+        self.assertEqual(questions[0].name, 'basic_var')
+        self.assertEqual(questions[1].name, 'bool_var')
+        self.assertEqual(questions[2].name, 'dot_var')
+
+        page = pages.pop(0)
+        self.assertEqual(page['name'], 'Carl')
+        questions = page['vars']
+        self.assertEqual(len(questions), 1)
+        self.assertEqual(questions[0].name, 'str_var')
+
+        page = pages.pop(0)
+        self.assertEqual(page['name'], 'Martin')
+        questions = page['vars']
+        self.assertEqual(len(questions), 1)
+        self.assertEqual(questions[0].name, 'txt_var')
+
+    def test_get_position_in_stack(self):
+        """ verify that the position of a template can be reliably found
+        """
+        stack = self.template.get_template_stack(self.command)
+        self.assertRaises(ValueError, self.template.get_position_in_stack, stack)
+
+        new_template = Archetype('joe')
+        self.assertEqual(new_template.get_position_in_stack(stack), len(stack)-1)
+
+    def test_get_template_stack(self):
+        """ verify that running this command against a create command
+            with the argument '-t archetype' returns the expected vals
+        """
+        stack = self.template.get_template_stack(self.command)
+        self.assertEqual(len(stack), 3)
+        self.failIf(self.template.__class__ in
+                    [t.__class__ for t in stack], "%s" % stack)
+        new_template = Archetype('joe')
+        self.failUnless(new_template.__class__ in
+                        [t.__class__ for t in stack], "%s" % stack)
+
+        for c in [t.__class__ for t in stack]:
+            self.failUnless(isinstance(new_template, c),
+                            "%s does not appear to be a subclass of %s" % (new_template, c))
+
+    def test_should_print_subcommands(self):
+        """ If a template has subcommands, they should be printed after the template runs
+        """
+        n_template = BasicNamespace('tom')
+        p_template = Plone('bob')
+        a_template = Archetype('joe')
+
+        self.failIf(n_template.should_print_subcommands(self.command))
+        self.failIf(p_template.should_print_subcommands(self.command))
+        self.failUnless(a_template.should_print_subcommands(self.command))
+
+def test_suite():
+    suite = unittest.TestSuite([
+        unittest.makeSuite(test_base_template),
+    ])
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_vars.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_vars.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_vars.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,195 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+import sys
+from zopeskel.vars import var, BooleanVar, StringVar, TextVar, DottedVar,\
+    OnOffVar, IntVar, BoundedIntVar
+from zopeskel.vars import ValidationException
+
+class test_var(unittest.TestCase):
+    """ test that there is no default implementation of the validation method
+    """
+    def setUp(self):
+        self.var = var('name', 'description')
+    
+    def testValidation(self):
+        """ the validation method should raise a ValidationException
+        """
+        try:
+            self.var.validate('foo')
+        except NotImplementedError:
+            pass
+        else:
+            self.fail("The validation method should not be implemented on the basic var class")
+    
+    def testPrettyDescription(self):
+        """ pretty_description should return a nice combination of title or name
+            and description
+        """
+        self.assertEqual(self.var.pretty_description(), 'name (description)')
+        
+        self.var.title = 'title'
+        self.assertEqual(self.var.pretty_description(), 'title (description)')
+        
+    def testFurtherHelp(self):
+        """ further_help will return the extensive help string set for a var
+            or a default 'nothing to see here' string
+        """
+        default = "Sorry, no further help is available for name\n"
+        self.assertEqual(self.var.further_help(), default)
+        
+        self.var.help = "I'm a little help text, short and stout"
+        self.assertEqual(self.var.further_help(), 
+                         "I'm a little help text, short and stout")
+
+
+class test_BooleanVar(unittest.TestCase):
+    """ verify functionality of the BooleanVar variable class
+    """
+    def setUp(self):
+        self.bvar = BooleanVar('name', 'description')
+    
+    def testValidation(self):
+        """ check to see that various inputs result in a Boolean Value
+        """
+        for val in ('f','F','n','N','false',0):
+            self.failIf(self.bvar.validate(val))
+        
+        for val in ('t','T','y','Y','true',1):
+            self.failUnless(self.bvar.validate(val))
+        
+        self.assertRaises(ValidationException, self.bvar.validate, 'humpty-dumpty')    
+
+
+class test_OnOffVar(unittest.TestCase):
+    """ verify functionality of the OnOffVar variable class
+    """
+    def setUp(self):
+        self.ovar = OnOffVar('name', 'description')
+
+    def testValidation(self):
+        """ check to see that various inputs result in a Boolean Value
+        """
+        for val in ('f','F','n','N','false',0,'off'):
+            self.assertEqual(self.ovar.validate(val), 'off')
+        
+        for val in ('t','T','y','Y','true',1,'on'):
+            self.assertEqual(self.ovar.validate(val), 'on')
+        
+        self.assertRaises(ValidationException, self.ovar.validate, 'lunchbox')
+
+
+class test_IntVar(unittest.TestCase):
+    """ verify functionality of the IntVar variable class
+    """
+    def setUp(self):
+        self.ivar = IntVar('name', 'description')
+    
+    def testValidation(self):
+        """ an IntVar should take values that can be cast to an integer,
+            any other value should raise a ValidationException
+        """
+        self.assertEqual(1, self.ivar.validate(1))
+        self.assertEqual(1, self.ivar.validate(1.9))
+        self.assertEqual(1, self.ivar.validate('1'))
+        
+        self.assertRaises(ValidationException, self.ivar.validate, 'one')
+
+
+class test_BoundedIntVar(unittest.TestCase):
+    """ verify functionality of the BoundedIntVar variable class
+    """
+    def setUp(self):
+        self.bivar = BoundedIntVar('name','description', min=3, max=10)
+        self.defaultminvar = BoundedIntVar('name', 'description', max=10)
+        self.defaultmaxvar = BoundedIntVar('name', 'description', min=3)
+        self.max = sys.maxint
+        self.min = -self.max-1
+    
+    def testValidation(self):
+        """ A BoundedIntVar should take values between min and max (inclusive)
+            If max is not provided, default to sys.maxint
+            if min is not provided, default to -sys.maxint-1
+        """
+        self.assertEqual(4, self.bivar.validate(4))
+        self.assertEqual(5, self.bivar.validate(5.9))
+        self.assertEqual(6, self.bivar.validate('6'))
+        
+        self.assertRaises(ValidationException, self.bivar.validate, 'four')
+        self.assertRaises(ValidationException, self.bivar.validate, 1)
+        self.assertRaises(ValidationException, self.bivar.validate, 11)
+        
+        self.assertEqual(self.max, self.defaultmaxvar.validate(self.max))
+        self.assertEqual(self.min, self.defaultminvar.validate(self.min))
+
+
+class test_StringVar(unittest.TestCase):
+    """ verify functionality of the StringVar variable class
+    """
+    def setUp(self):
+        self.svar = StringVar('name', 'description')
+    
+    def testValidation(self):
+        """ check to see that validation returns appropriate values:
+                string should have no spaces at front or back
+                unicode strings and regular strings should pass through unchanged
+                non-string values raise validation errors
+        """
+        val = 'george'
+        self.assertEqual(val, self.svar.validate(val))
+        
+        val = u'george'
+        self.assertEqual(val, self.svar.validate(val))
+        
+        val = ' hello '
+        validated = self.svar.validate(val)
+        self.assertNotEqual(validated[0], ' ')
+        self.assertNotEqual(validated[-1], ' ')
+        self.failUnless(validated in val)
+        
+        for val in (0, True):
+            self.assertRaises(ValidationException, self.svar.validate, val)
+
+
+class test_TextVar(unittest.TestCase):
+    """ verify functionality of the TextVar variable class
+    """
+    def setUp(self):
+        self.tvar = TextVar('name', 'description')
+    
+    def testValidation(self):
+        """ we will test this more thoroughly when it does something useful that
+            is different than the above.
+        """
+        pass
+
+
+class test_DottedVar(unittest.TestCase):
+    def setUp(self):
+        self.dvar = DottedVar('name', 'description')
+    
+    def testValidation(self):
+        """ all parts of a dotted name must be valid python identifiers
+        """
+        for val in ('this.package', '_foo_.bar', '__class__.__name__'):
+            self.assertEquals(val, self.dvar.validate(val))
+        
+        for val in ('ham-and-eggs.yummy', 'spam.yucky!'):
+            self.assertRaises(ValidationException, self.dvar.validate, val)
+
+
+def test_suite():
+    suite = unittest.TestSuite([
+        unittest.makeSuite(test_var),
+        unittest.makeSuite(test_BooleanVar),
+        unittest.makeSuite(test_OnOffVar),
+        unittest.makeSuite(test_IntVar),
+        unittest.makeSuite(test_BoundedIntVar),
+        unittest.makeSuite(test_StringVar),
+        unittest.makeSuite(test_TextVar),
+        unittest.makeSuite(test_DottedVar),
+    ])
+    return suite
+    
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskel_script.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskel_script.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskel_script.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,165 @@
+# -*- coding: utf-8 -*-
+
+import unittest
+import sys
+import StringIO
+
+from zopeskel.zopeskel_script import checkdots, process_args, run, DESCRIPTION
+from zopeskel.ui import list_sorted_templates
+
+
+def capture_stdout(function):
+    def _capture_stdout(*args, **kw):
+        newout = StringIO.StringIO()
+        oldout = sys.stdout
+        sys.stdout = newout
+        try:
+            function(*args, **kw)
+        finally:
+            sys.stdout = oldout
+            newout.seek(0)
+            return newout.read()
+    return _capture_stdout
+    
+run = capture_stdout(run)
+
+class test_zopeskel(unittest.TestCase):
+    """Tests for ZopeSkel script.
+    """
+
+    def test_checkdots_none(self):
+        """Verify that checkdots works with templates without ndots hint."""
+
+        class FauxTemplate: pass
+        t = FauxTemplate()
+
+        checkdots(t, "anything is legal; not a package")
+
+    def test_checkdots_two(self):
+        """Verify that checkdots validates templates with ndots hint."""
+
+        class FauxTemplate: pass
+        t = FauxTemplate()
+
+        t.ndots = 2
+
+        self.assertRaises(ValueError, checkdots, t, "nodots")
+        self.assertRaises(ValueError, checkdots, t, "one.dot")
+        self.assertRaises(ValueError, checkdots, t, "three.dots.in.this")
+        self.assertRaises(ValueError, checkdots, t, "two.dots.but not legal")
+
+        checkdots(t, "two.dots.legal")
+        
+    def test_process_args(self):
+        """Ensure that process_args correctly processes command-line arguments"""
+        oldargv = sys.argv
+        
+        sys.argv = ['zopskel']
+        self.assertRaises(SyntaxError, process_args)
+        
+        sys.argv.append('archetype')
+        processed = process_args()
+        self.failUnlessEqual(processed[0], 'archetype')
+        self.failIf(processed[1])
+        self.failIf(processed[2])
+        
+        sys.argv.append('my.project')
+        processed = process_args()
+        self.failUnlessEqual(processed[0], 'archetype')
+        self.failUnlessEqual(processed[1], 'my.project')
+        self.failIf(processed[2])
+        
+        sys.argv.append('--bob=kate')
+        processed = process_args()
+        self.failUnlessEqual(processed[0], 'archetype')
+        self.failUnlessEqual(processed[1], 'my.project')
+        self.failUnlessEqual(processed[2]['--bob'], 'kate')
+
+        # process_args will allow us to skip the project name argument
+        sys.argv.pop(2)
+        processed = process_args()
+        self.failUnlessEqual(processed[0], 'archetype')
+        self.failIf(processed[1])
+        self.failUnlessEqual(processed[2]['--bob'], 'kate')
+        
+        # providing arguments in '-name val' form is _not_ allowed
+        sys.argv = ['zopeskel', 'archetype', 'my.project', '-bob', 'kate']
+        self.assertRaises(SyntaxError, process_args)
+        
+        # the --svn-repository argument is _not_ allowed in any form
+        sys.argv = sys.argv[:3] + ['--svn-repository=svn://svn.junk.org/svn/blah']
+        self.assertRaises(SyntaxError, process_args)
+        
+        sys.argv[3] = 'svn-repository=svn://svn.junk.org/svn/blah'
+        self.assertRaises(SyntaxError, process_args)
+        
+        # providing args in a '-name val' format is not supported
+        sys.argv = sys.argv[:3] + ['bob', 'kate']
+        self.assertRaises(SyntaxError, process_args)
+        
+        sys.argv = oldargv
+
+    def test_script_errors(self):
+        """Verify that the run method catches errors correctly"""
+        oldargv = sys.argv
+        
+        # non-existent templates are not caught until in 'run'
+        sys.argv = ['zopeskel', 'no-template', 'my.package']
+        output = run()
+        self.failUnless('ERROR: No such template' in output)
+        
+        # calling the script with no arguments at all prints usage
+        sys.argv = sys.argv[:1]
+        output = run()
+        self.failUnless('Usage:' in output)
+        
+        sys.argv = oldargv
+
+    def test_script_features(self):
+        """Verify that the help features of the script function correctly"""
+        oldargv = sys.argv
+        
+        # --help produces the DESCRIPTION string 
+        sys.argv = ['zopeskel', '--help']
+        output = run()
+        self.failUnless(DESCRIPTION in output, '--help produces incorrect output: %s' % output)        
+        
+        # --list produces a verbose list of all templates by category
+        sys.argv = ['zopeskel', '--list']
+        output = run()
+        cats = list_sorted_templates()
+        catnames = cats.keys()
+        templates = sum(cats.values(), [])
+        tempnames = [t['name'] for t in templates]
+        tempsums = [t['summary'] for t in templates]
+        for cat in catnames:
+            self.failUnless(cat in output, '%s not in --list output' % cat)
+        for tname in tempnames:
+            self.failUnless(tname in output, '%s not in --list output' % tname)
+        for summary in tempsums:
+            self.failUnless(summary in output, '%s not in --list output' % summary)
+        
+        # --make-config-file produces a config file with headings for each template
+        sys.argv = ['zopeskel', '--make-config-file']
+        output = run()
+        for theading in ['[' + name + ']' for name in tempnames]:
+            self.failUnless(theading in output, '%s does not appear in .zopeskel' % theading)
+        
+        # --version should output a version number.  make sure it finds something
+        sys.argv = ['zopeskel', '--version']
+        output = run()
+        self.failIf('unable' in output)
+        
+        sys.argv = oldargv
+        
+        
+        
+        
+
+def test_suite():
+    suite = unittest.TestSuite([
+        unittest.makeSuite(test_zopeskel)])
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskeldocs.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskeldocs.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/tests/test_zopeskeldocs.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,173 @@
+# -*- coding: utf-8 -*-
+"""
+Grabs the tests in doctest
+"""
+__docformat__ = 'restructuredtext'
+
+import unittest
+import doctest
+import sys
+import os
+import shutil
+import popen2
+import tempfile
+
+from zope.testing import doctest
+
+current_dir = os.path.abspath(os.path.dirname(__file__))
+
+def rmdir(*args):
+    dirname = os.path.join(*args)
+    if os.path.isdir(dirname):
+        shutil.rmtree(dirname)
+
+
+def paster(cmd):
+    print "paster %s" % cmd
+    from paste.script import command
+    #the overwite option for the create command defaults to True
+    #but in the paste.script.command it defaults to False.
+    #so we fixe it here
+    if 'create' in cmd:
+        cmd += " --overwrite=1"
+    args = cmd.split()
+    options, args = command.parser.parse_args(args)
+    options.base_parser = command.parser
+    command.system_plugins.extend(options.plugins or [])
+    commands = command.get_commands()
+    command_name = args[0]
+    if command_name not in commands:
+        command = command.NotFoundCommand
+    else:
+        command = commands[command_name].load()
+    runner = command(command_name)
+    runner.run(args[1:])
+
+
+def read_sh(cmd):
+    _cmd = cmd
+    old = sys.stdout 
+    child_stdout_and_stderr, child_stdin = popen2.popen4(_cmd)
+    child_stdin.close()
+    return child_stdout_and_stderr.read()
+
+
+def ls(*args):
+    dirname = os.path.join(*args)
+    if os.path.isdir(dirname):
+        filenames = os.listdir(dirname)
+        for filename in sorted(filenames):
+            # Depending on how pristine your testing env is, the
+            # Paster/PasteScript eggs may end up here; this ins't
+            # very predictable. Hide them.
+            if filename.endswith('.egg'):
+                continue
+            print filename
+    else:
+        print 'No directory named %s' % dirname
+
+
+def cd(*args):
+    dirname = os.path.join(*args)
+    os.chdir(dirname)
+
+
+def config(filename):
+    return os.path.join(current_dir, filename)
+
+
+def cat(*args):
+    filename = os.path.join(*args)
+    if os.path.isfile(filename):
+        print open(filename).read()
+    else:
+        print 'No file named %s' % filename
+
+
+def touch(*args, **kwargs):
+    filename = os.path.join(*args)
+    open(filename, 'w').write(kwargs.get('data',''))
+
+
+class ZopeSkelLayer:
+
+    temp_dir = None
+
+    @classmethod
+    def testSetUp(self):
+        self.temp_dir = tempfile.mkdtemp()
+        cd(self.temp_dir)
+      
+    @classmethod
+    def testTearDown(self):
+        shutil.rmtree(self.temp_dir, ignore_errors=True)
+        self.temp_dir = None
+
+        from pkg_resources import working_set as ws
+        #cleanup entries in the working set
+        for k, v in ws.by_key.items():
+            if not os.path.exists(v.location):
+                del ws.by_key[k]
+
+        for i in reversed(range(len(ws.entries))):
+            if not os.path.exists(ws.entries[i]):
+                del ws.entries[i]
+
+        sys.path = ws.entries[:]
+
+def testSetUp(test):
+    test.temp_dir = tempfile.mkdtemp()
+    cd(test.temp_dir)
+
+def testTearDown(test):
+    shutil.rmtree(test.temp_dir, ignore_errors=True)
+    test.temp_dir = None
+
+    from pkg_resources import working_set as ws
+    #cleanup entries in the working set
+    for k, v in ws.by_key.items():
+        if not os.path.exists(v.location):
+            del ws.by_key[k]
+
+    for i in reversed(range(len(ws.entries))):
+        if not os.path.exists(ws.entries[i]):
+            del ws.entries[i]
+
+    sys.path = ws.entries[:]
+
+def doc_suite(test_dir, setUp=testSetUp, tearDown=testTearDown, globs=None):
+    """Returns a test suite, based on doctests found in /docs."""
+    suite = []
+    if globs is None:
+        globs = globals()
+
+    flags = (doctest.ELLIPSIS | doctest.NORMALIZE_WHITESPACE |
+             doctest.REPORT_ONLY_FIRST_FAILURE)
+
+    package_dir = os.path.split(test_dir)[0]
+    if package_dir not in sys.path:
+        sys.path.append(package_dir)
+
+    doctest_dir = os.path.join(package_dir, 'docs')
+
+    # filtering files on extension
+    docs = [os.path.join(doctest_dir, doc) for doc in
+            os.listdir(doctest_dir) if doc.endswith('.txt')]
+
+    for test in docs:
+        suite.append(doctest.DocFileSuite(test, optionflags=flags, 
+                                          globs=globs, setUp=setUp, 
+                                          tearDown=tearDown,
+                                          module_relative=False))
+
+    return unittest.TestSuite(suite)
+
+def test_suite():
+    """returns the test suite"""
+    suite = doc_suite(current_dir)
+    suite.layer = ZopeSkelLayer
+    return suite
+
+if __name__ == '__main__':
+    unittest.main(defaultTest='test_suite')
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/ui.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/ui.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/ui.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,60 @@
+"""
+Module containing some common UI components that are useful for all user
+interfaces, ie the console and the web interfaces.
+"""
+import pkg_resources
+
+from zopeskel.base import BaseTemplate
+
+# These are the "common" templates; they will be listed in a separate
+# list for new users. Please be conservative about adding new
+# templates to this list--we don't want it to be overwhelming.
+# Users also see the "non-common" templates, just in a different
+# listing; this is where things like PAS plugins, special hosting,
+# Silva, etc., should remain.
+
+def list_sorted_templates(filter_group=False):
+    """
+    Returns a dictionary of template lists by category.  Key is the category
+    name, value is a list of templates.
+
+    If "filter_group" is True, then this explictly filters to
+    things provided by the ZopeSkel package--thereby hiding any
+    templates the user may have on their system that sit on top
+    of zopeskel's base classes. This is required in places where
+    we want to generate canonical documents, and don't want to
+    accidentally include things from the machine it's being run
+    on.
+    """
+
+    cats = {}
+    # grab a list of all paster create template entry points
+    if filter_group:
+        t_e_ps = pkg_resources.get_entry_map(
+            'zopeskel')['paste.paster_create_template'].values()
+    else:
+        t_e_ps = pkg_resources.iter_entry_points('paste.paster_create_template')
+    templates = []
+    for entry in t_e_ps:
+        try:
+            # We only want our templates in this list
+            template = entry.load()
+            if issubclass(template, BaseTemplate):
+                templates.append(
+                        { 'name': entry.name,
+                          'summary': template.summary,
+                          'class': template,
+                          'category': getattr(template, 'category', 'Uncategorized'),
+                          'help': getattr(template, 'help', "").strip(),
+                          'entry':entry,
+                        } )
+        except Exception, e:
+            # We will not be stopped!
+            print 'Warning: could not load entry point %s (%s: %s)' % (
+                entry.name, e.__class__.__name__, e)
+    templates.sort(key=lambda x: x['name'])
+
+    for entry in templates:
+        cats.setdefault(entry['category'], []).append(entry)
+
+    return cats

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/vars.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/vars.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/vars.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,203 @@
+import sys
+from paste.script.templates import var as base_var
+
+
+##########################################################################
+# Mode constants
+
+# keep these lowercased, as choicesvars are lowercased
+
+EXPERT = 'expert'
+EASY = 'easy'
+ALL = 'all'
+
+##########################################################################
+# Variable classes
+
+class ValidationException(ValueError):
+    """Invalid value provided for variable."""
+
+
+class var(base_var):
+
+    _default_widget = 'string'
+
+    def __init__(self, name, description,
+                 default='', should_echo=True,
+                 title=None, help=None, widget=None,
+                 modes=(EASY, EXPERT), page='Main'):
+        self.name = name
+        self.description = description
+        self.default = default
+        self.should_echo = should_echo
+        self.title = title
+        self.help = help
+        if not widget:
+            self.widget = self._default_widget
+        else:
+            self.widget = widget
+        self.modes = modes
+        self.page = page
+
+    def pretty_description(self):
+        title = getattr(self, 'title', self.name) or self.name
+
+        if self.description:
+            return '%s (%s)' % (title, self.description)
+        else:
+            return title
+    
+    def further_help(self):
+        """ return the help string for this class or inform user that none is
+            available
+        """
+        no_help = "Sorry, no further help is available for %s\n" % self.name
+        return self.help and self.help or no_help
+
+    def validate(self, value):
+        raise NotImplementedError
+
+
+class BooleanVar(var):
+    _default_widget = 'boolean'
+
+    def validate(self, value):
+        #Get rid of bonus whitespace
+        if isinstance(value, basestring):
+            value = value.strip().lower()
+
+        #Map special cases to correct values.
+        if value in ['t', 'y', 'yes', 'true', 1]: 
+            value = True
+        elif value in ['f','n','no', 'false', 0]:
+            value = False
+
+        if type(value) != bool:
+            raise ValidationException("Not a valid boolean value: %s" % value)
+
+        return value
+
+
+class StringVar(var):
+    """Single string values."""
+
+    _default_widget = 'string'
+
+    def validate(self, value):
+        if not isinstance(value, basestring):
+            raise ValidationException("Not a string value: %s" % value)
+
+        value = value.strip()
+
+        return value
+
+class StringChoiceVar(var):
+    """Choice of strings."""
+
+    _default_widget = 'select'
+
+    def __init__(self, *args, **kwargs):
+        self.choices = kwargs['choices']
+        del kwargs['choices']
+        super(StringChoiceVar, self).__init__(*args, **kwargs)
+
+    def validate(self, value):
+        value = value.strip().lower()
+        if not value in self.choices:
+            raise ValidationException("Not a valid value: %s" % value)
+
+        return value
+
+class TextVar(StringVar):
+    """Multi-line values."""
+
+    _default_widget = 'text'
+
+
+class OnOffVar(StringVar):
+    """'On' or 'Off' text values."""
+
+    _default_widget = 'onoff'
+
+    def validate(self, value):
+        #Get rid of bonus whitespace
+        if isinstance(value, basestring):
+            value = value.strip().lower()
+
+        #Map special cases to correct values.
+        if value in ['t', 'y', 'yes', 'true', 1, 'on']: 
+            value = 'on'
+        elif value in ['f','n','no', 'false', 0, 'off']:
+            value = 'off'
+        else:
+            raise ValidationException("Not a valid on/off value: %s" % value)
+
+        return value
+
+
+class IntVar(var):
+    """Integer values"""
+    
+    _default_widget = 'string'
+    
+    def validate(self, value):
+        try:
+            value = int(value)
+        except ValueError:
+            raise ValidationException("Not a valid int: %s" % value)
+        
+        return value
+    
+
+MAXINT = sys.maxint
+MININT = -MAXINT-1
+class BoundedIntVar(IntVar):
+    """Integer values with allowed maximum and minimum values"""
+    
+    def __init__(self, *args, **kwargs):
+        if 'min' in kwargs:
+            self.min = kwargs.pop('min')
+        else:
+            self.min = MININT
+        
+        if 'max' in kwargs:
+            self.max = kwargs.pop('max')
+        else:
+            self.max = MAXINT
+            
+        super(BoundedIntVar, self).__init__(*args, **kwargs)
+    
+    def validate(self, value):
+        # first validate that value is an integer
+        try:
+            val = super(BoundedIntVar, self).validate(value)
+        except ValidationException, e:
+            raise e
+        
+        if not self.min <= val <= self.max:
+            msg = "%d does not fall within allowed bounds: %d:%d"
+            raise ValidationException(msg % (val, self.min, self.max))
+        
+        return val
+    
+
+class DottedVar(var):
+    """Variable for 'dotted Python name', eg, 'foo.bar.baz'"""
+
+    _default_widget = 'string'
+
+    def validate(self, value):
+        if not isinstance(value, basestring):
+            raise ValidationException("Not a string value: %s" % value)
+        value = value.strip()
+
+        names = value.split(".")
+        for name in names:
+            # Check if Python identifier, http://code.activestate.com/recipes/413487/
+            try:
+                class test(object): __slots__ = [name]
+            except TypeError:
+                raise ValidationException("Not a valid Python dotted name: %s ('%s' is not an identifier)" % (value, name))
+
+        return value
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zope2_buildout.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zope2_buildout.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zope2_buildout.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,51 @@
+import copy
+
+from zopeskel import abstract_buildout
+from zopeskel.base import var, EASY, EXPERT
+from zopeskel.vars import StringVar
+
+
+class Zope2Buildout(abstract_buildout.AbstractBuildout):
+    _template_dir = 'templates/zope2_buildout'
+    summary = "A buildout for a blank (non-Silva, non-Plone) Zope 2 instance"
+    help = """
+This template creates a buildout that does not contain Plone or Silva
+information. It is intended for people using Zope 2 directly. If you
+would like to use Plone or Silva, you should use the appropriate buildouts.
+"""
+    post_run_msg = """
+Generation finished.
+
+You probably want to run python bootstrap.py and then edit
+buildout.cfg before running bin/buildout -v".
+
+See README.txt for details.
+"""
+    required_templates = []
+    use_cheetah = True
+
+    vars = copy.deepcopy(abstract_buildout.AbstractBuildout.vars)
+    vars.extend([
+        abstract_buildout.VAR_Z2_INSTALL,
+        StringVar(
+            'zope2_version',
+            title='Zope 2 Version',
+            description='Version of Zope 2 to fetch, if needed',
+            modes=(EASY, EXPERT),
+            page='Main',
+            default='2.11.1',
+            help="""
+If a version of Zope needs to be pulled down, this option lets you
+specify the version.
+"""
+            ),
+        abstract_buildout.VAR_ZOPE_USER,
+        abstract_buildout.VAR_ZOPE_PASSWD,
+        abstract_buildout.VAR_HTTP,
+        abstract_buildout.VAR_DEBUG_MODE,
+        abstract_buildout.VAR_VERBOSE_SEC,
+        ]
+    )
+
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zopeskel_script.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zopeskel_script.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/ZopeSkel-2.19-py2.6.egg/zopeskel/zopeskel_script.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,399 @@
+import sys
+import pkg_resources
+from cStringIO import StringIO
+from textwrap import TextWrapper
+from zopeskel.base import wrap_help_paras
+from paste.script.command import get_commands
+
+from zopeskel.ui import list_sorted_templates
+
+USAGE = """
+Usage:
+
+    zopeskel <template> <output-name> [var1=value] ... [varN=value]
+
+    zopeskel --help                Full help
+    zopeskel --list                List template verbosely, with details
+    zopeskel --make-config-file    Output .zopeskel prefs file
+    zopeskel --version             Print installed version
+    
+%s
+Warning:  use of the --svn-repository argument is not allowed with this script
+
+For further help information, please invoke this script with the
+option "--help".
+"""
+
+DESCRIPTION = """
+This script allows you to create basic skeletons for plone and zope
+products and buildouts based on best-practice templates.
+
+It is a wrapper around PasteScript ("paster"), providing an easier
+syntax for invoking and better help.
+
+
+Invoking this script
+--------------------
+
+Basic usage::
+
+    zopeskel <template>
+
+(To get a list of the templates, run the script without any arguments;
+for a verbose list with full descriptions, run the ``zopeskel --list``)
+
+For example::
+
+    zopeskel archetypes
+
+To create an Archetypes-based product for Plone. This will prompt you
+for the name of your product, and for other information about it.
+
+If you to specify your output name (resulting product, egg, or buildout,
+depending on the template being used), you can also do so::
+
+    zopeskel <template> <output-name>
+
+For example::
+
+    zopeskel archetypes Products.Example
+
+In addition, you can pass variables to this that would be requested
+by that template, and these will then be used. This is an advanced
+feature mostly useful for scripted use of this::
+
+    zopeskel archetypes Products.Example author_email=joel at joelburton.com
+
+(You can specify as many of these as you want, in name=value pairs.
+To get the list of variables that a template expects, you can ask for
+this with ``paster create -t <template-name> --list-variables``).
+
+
+Interactive Help
+----------------
+
+While being prompted on each question, you can enter with a single
+question mark to receive interactive help for that question.
+
+For example::
+
+  Description (One-line description of the project) ['']: ?
+
+  |  This should be a single-line description of your project. It will
+  |  be used in the egg's setup.py, and, for Zope/Plone projects, may be
+  |  used in the GenericSetup profile description.
+
+
+Providing defaults
+------------------
+
+It is also possible to set up default values to be used for any template by
+creating a file called ``.zopeskel`` in your home directory. This file
+should be in INI format.
+
+For example, our ``$HOME/.zopeskel`` could contain::
+
+    [DEFAULT]
+    author_email = joel at joelburton.com
+    license_name = GPL
+    master_keywords = my common keywords here
+
+    [plone3_theme]
+    empty_styles = False
+    license_name = BSD
+    keywords = %(master_keywords)s additional keywords
+
+You can generate a starter .zopeskel file by running this script with
+the --make-config-file option. This output can be redirected into
+your ``.zopeskel`` file::
+
+    bin/zopeskel --make-config-file > /path/to/home/.zopeskel
+
+Notes:
+
+1) "empty_styles" applies only to themes; we can make this setting
+   in the template-specific section of this file. This setting will
+   not be used for other templates.
+
+2) For a common setting, like our email address, we can set this in
+   a section called DEFAULT; settings made in this section are used
+   for all templates.
+
+3) We can make a setting in DEFAULT and then override it for a
+   particular template. In this example, we might generally prefer the GPL,
+   but issue our themes under the BSD license.
+
+4) You can refer to variables from the same section or from the
+   DEFAULT section using Python string formatting. In this example,
+   we have a common set of keywords set in DEFAULT and extend it
+   for the theming template by referring to the master list.
+
+
+Differences from the 'paster create' command
+--------------------------------------------
+
+1) The --svn-repository argument that can be provided to 'paster create' is not
+   allowed when using the zopeskel script.  It will raise an error.  The reasons
+   for this are discussed at length in the zopeskel mailing list and in the 
+   zopeskel issue tracker:
+   http://plone.org/products/zopeskel/issues/34
+   http://plone.org/products/zopeskel/issues/35
+   
+   If this argument is desired, the user should revert to calling 'paster create'
+   directly.  However, be warned that buildout templates will not work with the
+   argument due to assumptions in the base paster code.
+
+
+Questions
+---------
+
+If you have further questions about the usage of bin/zopeskel, please feel
+free to post your questions to the zopeskel mailing list or jump onto the
+plone IRC channel (#plone) at irc.freenode.net.
+
+
+To see the templates supported, run this script without any options.
+For a verbose listing with help, use ``zopeskel --list``.
+"""
+
+DOT_HELP = {
+  0: """
+This template expects a project name with no dots in it (a simple
+Python package name, like 'foo').
+""",
+  1: """
+This template expects a project name with 1 dot in it (a 'basic
+namespace', like 'foo.bar').
+""",
+  2: """
+This template expects a project name with 2 dots in it (a 'nested
+namespace', like 'foo.bar.baz').
+"""
+}
+
+def checkdots(template, name):
+    """Check if project name appears legal, given template requirements.
+
+    Templates can provide number of namespaces they expect (provided
+    in 'ndots' attributes for number-of-dots in name). This checks that
+    provided project name is has correct number of namespaces and that
+    each part is a legal Python identifier.
+    """
+
+    ndots = getattr(template, 'ndots', None)
+    if ndots is None: return   # No validation possible
+
+    cdots = name.count(".")
+    if ndots != cdots:
+        raise ValueError(
+            "Project name expected %i dots, supplied '%s' has %i dots" % (
+                ndots, name, cdots))
+    for part in name.split("."):
+        # Check if Python identifier, http://code.activestate.com/recipes/413487/
+        try:
+            class test(object): __slots__ = [part]
+        except TypeError:
+            raise ValueError(
+                "Not a valid Python dotted name: %s ('%s' is not an identifier)" % (name, part))
+
+
+
+def usage():
+    templates = list_printable_templates()
+    print USAGE % templates
+
+def show_help():
+    print DESCRIPTION
+
+def show_version():
+    try:
+        dist = pkg_resources.get_distribution('zopeskel')
+        print dist.version
+    except pkg_resources.DistributionNotFound:
+        print 'unable to identify zopeskel version'
+
+def list_verbose():
+    """List templates verbosely, with full help."""
+
+    textwrapper = TextWrapper(
+            initial_indent="   ", subsequent_indent="   ")
+    cats = list_sorted_templates()
+
+    for title, items in cats.items():
+        print "\n"+ title
+        print "-" * len(title)
+        for temp in items:
+            print "\n%s: %s\n" % (temp['name'], temp['summary'])
+            if temp['help']:
+                wrap_help_paras(textwrapper, temp['help'])
+    print
+
+
+def list_printable_templates():
+    """
+    Printable list of all templates, sorted into two categories.
+    """
+
+    s = StringIO()
+
+    cats = list_sorted_templates()
+    templates = sum(cats.values(), [])   # flatten into single list
+    max_name = max([len(x['name']) for x  in templates])
+
+    for title, items in cats.items():
+        print >>s, "\n%s\n" % title
+        for entry in items:
+            print >>s, "|  %s:%s %s\n" % (
+                 entry['name'],
+                ' '*(max_name-len(entry['name'])),
+                entry['summary']),
+
+    s.seek(0)
+    return s.read()
+
+
+def generate_dotzopeskel():
+    """Make an example .zopeskel file for user."""
+
+    cats = list_sorted_templates()
+    print """
+
+# This file can contain preferences for zopeskel.
+# To do so, uncomment the lines that look like:
+#    variable_name = Default Value
+
+[DEFAULT]
+"""
+    for temp in sum(cats.values(), []):
+        print "\n[%(name)s]\n" % temp
+        tempc = temp['entry'].load()
+        for var in tempc.vars:
+            if hasattr(var, 'pretty_description'):
+                print "# %s" % var.pretty_description()
+            print "# %s = %s\n" % ( var.name, var.default )
+
+def process_args():
+    """ return a tuple of template_name, output_name and everything else
+
+        everything else will be returned as a dictionary of key/value pairs
+    """
+    args = sys.argv[1:]
+    try:
+        template_name = args.pop(0)
+    except IndexError:
+        raise SyntaxError('No template name provided')
+    output_name = None
+    others = {}
+    for arg in args:
+        eq_index = arg.find('=')
+        if eq_index == -1 and not output_name:
+            output_name = arg
+        elif eq_index > 0:
+            key, val = arg.split('=')
+            # the --svn-repository argument to paster does some things that cause
+            # it to be pretty much incompatible with zopeskel. See the following
+            # zopeskel issues:
+            #     http://plone.org/products/zopeskel/issues/35
+            #     http://plone.org/products/zopeskel/issues/34
+            # For this reason, we are going to disallow using the --svn-repository 
+            # argument when using the zopeskel wrapper.  Those who wish to use it
+            # can still do so by going back to paster, with the caveat that there
+            # are some templates (particularly the buildout ones) for which the
+            # argument will always throw errors (at least until the problems are
+            # fixed upstream in paster itself).
+            if 'svn-repository' in key:
+                msg = 'for a number of reasons, the --svn-repository argument '
+                msg += 'is not allowed with the zopeskel script. '
+                msg += "Try --help for more information"
+                raise SyntaxError(msg)
+            others[key] = val
+        else:
+            raise SyntaxError(arg)
+    
+    
+
+    return template_name, output_name, others
+
+def run():
+    """ """
+
+    if "--help" in sys.argv:
+        show_help()
+        return
+
+    if "--make-config-file" in sys.argv:
+        generate_dotzopeskel()
+        return
+
+    if "--list" in sys.argv:
+        list_verbose()
+        return
+
+    if "--version" in sys.argv:
+        show_version()
+        return
+
+    if len(sys.argv) == 1:
+        usage()
+        return
+
+    try:
+        template_name, output_name, opts = process_args()
+    except SyntaxError, e:
+        usage()
+        print "ERROR: There was a problem with your arguments: %s\n" % e
+        return
+
+    rez = pkg_resources.iter_entry_points(
+            'paste.paster_create_template',
+            template_name)
+    rez = list(rez)
+    if not rez:
+        usage()
+        print "ERROR: No such template: %s\n" % template_name
+        return
+
+    template = rez[0].load()
+
+    print "\n%s: %s" % (template_name, template.summary)
+    help = getattr(template, 'help', None)
+    if help:
+        print template.help
+
+    create = get_commands()['create'].load()
+
+    command = create('create')
+
+    if output_name:
+        try:
+            checkdots(template, output_name)
+        except ValueError, e:
+            print "ERROR: %s\n" % e
+            return
+
+    else:
+        ndots = getattr(template, 'ndots', None)
+        help = DOT_HELP.get(ndots)
+
+        while True:
+            if help: print help
+            try:
+                output_name = command.challenge("Enter project name")
+                checkdots(template, output_name)
+            except ValueError, e:
+                print "\nERROR: %s" % e
+            else:
+                break
+
+
+    print """
+If at any point, you need additional help for a question, you can enter
+'?' and press RETURN.
+"""
+
+    optslist = [ '%s=%s' % (k,v) for k, v in opts.items() ]
+    if output_name is not None:
+        optslist.insert(0, output_name)
+    command.run( [ '-q', '-t', template_name ] + optslist )
+
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/easy-install.pth
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/easy-install.pth	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/easy-install.pth	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,9 @@
+import sys; sys.__plen = len(sys.path)
+./setuptools-0.6c11-py2.6.egg
+./pip-0.7.2-py2.6.egg
+./ZopeSkel-2.19-py2.6.egg
+./Cheetah-2.2.1-py2.6-linux-x86_64.egg
+./PasteScript-1.7.3-py2.6.egg
+./PasteDeploy-1.3.4-py2.6.egg
+./Paste-1.7.5.1-py2.6.egg
+import sys; new=sys.path[sys.__plen:]; del sys.path[sys.__plen:]; p=getattr(sys,'__egginsert',0); sys.path[p:p]=new; sys.__egginsert = p+len(new)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/PKG-INFO
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/PKG-INFO	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/PKG-INFO	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,310 @@
+Metadata-Version: 1.0
+Name: pip
+Version: 0.7.2
+Summary: pip installs packages.  Python packages.  An easy_install replacement
+Home-page: http://pip.openplans.org
+Author: The Open Planning Project
+Author-email: python-virtualenv at groups.google.com
+License: MIT
+Description: The main website for pip is `pip.openplans.org
+        <http://pip.openplans.org>`_.  You can also install
+        the `in-development version <http://bitbucket.org/ianb/pip/get/tip.gz#egg=pip-dev>`_
+        of pip with ``easy_install pip==dev``.
+        
+        
+        Introduction
+        ------------
+        
+        pip is a replacement for `easy_install
+        <http://peak.telecommunity.com/DevCenter/EasyInstall>`_.  It uses mostly the
+        same techniques for finding packages, so packages that were made
+        easy_installable should be pip-installable as well.
+        
+        pip is meant to improve on easy_install.  Some of the improvements:
+        
+        * All packages are downloaded before installation.  Partially-completed
+          installation doesn't occur as a result.
+        
+        * Care is taken to present useful output on the console.
+        
+        * The reasons for actions are kept track of.  For instance, if a package is
+          being installed, pip keeps track of why that package was required.
+        
+        * Error messages should be useful.
+        
+        * The code is relatively concise and cohesive, making it easier to use
+          programmatically.
+        
+        * Packages don't have to be installed as egg archives, they can be installed
+          flat (while keeping the egg metadata).
+        
+        * Native support for other version control systems (Git, Mercurial and Bazaar)
+        
+        * Uninstallation of packages.
+        
+        * Simple to define fixed sets of requirements and reliably reproduce a
+          set of packages.
+        
+        pip is complementary with `virtualenv
+        <http://pypi.python.org/pypi/virtualenv>`_, and it is encouraged that you use
+        virtualenv to isolate your installation.
+        
+        Community
+        ---------
+        
+        The homepage for pip is temporarily located `on PyPI
+        <http://pypi.python.org/pypi/pip>`_ -- a more proper homepage will
+        follow.  Bugs can go on the `pip issue tracker
+        <http://bitbucket.org/ianb/pip/issues/>`_.  Discussion should happen on the
+        `virtualenv email group
+        <http://groups.google.com/group/python-virtualenv?hl=en>`_.
+        
+        Differences From easy_install
+        -----------------------------
+        
+        pip cannot install some packages.  Specifically:
+        
+        * It cannot install from eggs.  It only installs from source.  (In the future it would be good if it could install binaries from Windows ``.exe`` or ``.msi`` -- binary install on other platforms is not a priority.)
+        
+        * It doesn't understand Setuptools extras (like ``package[test]``).  This should
+          be added eventually.
+        
+        * It is incompatible with some packages that customize distutils or setuptools
+          in their ``setup.py`` files.
+        
+        * Maybe it doesn't work on Windows.  At least, the author doesn't test on
+          Windows often.
+        
+        * It also has some extra features.  Extra features the author thinks are great.
+        
+        Uninstall
+        ---------
+        
+        pip is able to uninstall most installed packages with ``pip uninstall
+        package-name``.
+        
+        Known exceptions include pure-distutils packages installed with
+        ``python setup.py install`` (such packages leave behind no metadata allowing
+        determination of what files were installed), and script wrappers installed
+        by develop-installs (``python setup.py develop``).
+        
+        pip also performs an automatic uninstall of an old version of a package
+        before upgrading to a newer version, so outdated files (and egg-info data)
+        from conflicting versions aren't left hanging around to cause trouble. The
+        old version of the package is automatically restored if the new version
+        fails to download or install.
+        
+        .. _`requirements file`:
+        
+        Requirements Files
+        ------------------
+        
+        When installing software, and Python packages in particular, it's common that
+        you get a lot of libraries installed.  You just did ``easy_install MyPackage``
+        and you get a dozen packages.  Each of these packages has its own version.
+        
+        Maybe you ran that installation and it works.  Great!  Will it keep working?
+        Did you have to provide special options to get it to find everything?  Did you
+        have to install a bunch of other optional pieces?  Most of all, will you be able
+        to do it again?  Requirements files give you a way to create an *environment*:
+        a *set* of packages that work together.
+        
+        If you've ever tried to setup an application on a new system, or with slightly
+        updated pieces, and had it fail, pip requirements are for you.  If you
+        haven't had this problem then you will eventually, so pip requirements are
+        for you too -- requirements make explicit, repeatable installation of packages.
+        
+        So what are requirements files?  They are very simple: lists of packages to
+        install.  Instead of running something like ``pip MyApp`` and getting
+        whatever libraries come along, you can create a requirements file something like::
+        
+            MyApp
+            Framework==0.9.4
+            Library>=0.2
+        
+        Then, regardless of what MyApp lists in ``setup.py``, you'll get a
+        specific version of Framework (0.9.4) and at least the 0.2 version of
+        Library.  (You might think you could list these specific versions in
+        MyApp's ``setup.py`` -- but if you do that you'll have to edit MyApp
+        if you want to try a new version of Framework, or release a new
+        version of MyApp if you determine that Library 0.3 doesn't work with
+        your application.)  You can also add optional libraries and support
+        tools that MyApp doesn't strictly require, giving people a set of
+        recommended libraries.
+        
+        You can also include "editable" packages -- packages that are checked out from
+        Subversion, Git, Mercurial and Bazaar.  These are just like using the ``-e``
+        option to pip.  They look like::
+        
+            -e svn+http://myrepo/svn/MyApp#egg=MyApp
+        
+        You have to start the URL with ``svn+`` (``git+``, ``hg+`` or ``bzr+``), and
+        you have to include ``#egg=Package`` so pip knows what to expect at that URL.
+        You can also include ``@rev`` in the URL, e.g., ``@275`` to check out
+        revision 275.
+        
+        Requirement files are mostly *flat*.  Maybe ``MyApp`` requires
+        ``Framework``, and ``Framework`` requires ``Library``.  I encourage
+        you to still list all these in a single requirement file; it is the
+        nature of Python programs that there are implicit bindings *directly*
+        between MyApp and Library.  For instance, Framework might expose one
+        of Library's objects, and so if Library is updated it might directly
+        break MyApp.  If that happens you can update the requirements file to
+        force an earlier version of Library, and you can do that without
+        having to re-release MyApp at all.
+        
+        Read the `requirements file format <requirement-format.html>`_ to
+        learn about other features.
+        
+        Freezing Requirements
+        ---------------------
+        
+        So you have a working set of packages, and you want to be able to install them
+        elsewhere.  `Requirements files`_ let you install exact versions, but it won't
+        tell you what all the exact versions are.
+        
+        To create a new requirements file from a known working environment, use::
+        
+            $ pip freeze > stable-req.txt
+        
+        This will write a listing of *all* installed libraries to ``stable-req.txt``
+        with exact versions for every library.  You may want to edit the file down after
+        generating (e.g., to eliminate unnecessary libraries), but it'll give you a
+        stable starting point for constructing your requirements file.
+        
+        You can also give it an existing requirements file, and it will use that as a
+        sort of template for the new file.  So if you do::
+        
+            $ pip freeze -r devel-req.txt > stable-req.txt
+        
+        it will keep the packages listed in ``devel-req.txt`` in order and preserve
+        comments.
+        
+        Bundles
+        -------
+        
+        Another way to distribute a set of libraries is a bundle format (specific to
+        pip).  This format is not stable at this time (there simply hasn't been
+        any feedback, nor a great deal of thought).  A bundle file contains all the
+        source for your package, and you can have pip install them all together.
+        Once you have the bundle file further network access won't be necessary.  To
+        build a bundle file, do::
+        
+            $ pip bundle MyApp.pybundle MyApp
+        
+        (Using a `requirements file`_ would be wise.)  Then someone else can get the
+        file ``MyApp.pybundle`` and run::
+        
+            $ pip install MyApp.pybundle
+        
+        This is *not* a binary format.  This only packages source.  If you have binary
+        packages, then the person who installs the files will have to have a compiler,
+        any necessary headers installed, etc.  Binary packages are hard, this is
+        relatively easy.
+        
+        Using pip with virtualenv
+        -------------------------
+        
+        pip is most nutritious when used with `virtualenv
+        <http://pypi.python.org/pypi/virtualenv>`_.  One of the reasons pip
+        doesn't install "multi-version" eggs is that virtualenv removes much of the need
+        for it.
+        
+        pip does not have to be installed to use it, you can run ``python
+        path/to/pip.py`` and it will work.  This is intended to avoid the
+        bootstrapping problem of installation.  You can also run pip inside
+        any virtualenv environment, like::
+        
+            $ virtualenv new-env/
+            ... creates new-env/ ...
+            $ pip install -E new-env/ MyPackage
+        
+        This is exactly equivalent to::
+        
+            $ ./new-env/bin/python path/to/pip.py install MyPackage
+        
+        Except, if you have ``virtualenv`` installed and the path ``new-env/``
+        doesn't exist, then a new virtualenv will be created.
+        
+        pip also has two advanced features for working with virtualenvs -- both of
+        which activated by defining a variable in your environment.
+        
+        To tell pip to only run if there is a virtualenv currently activated,
+        and to bail if not, use::
+        
+            export PIP_REQUIRE_VIRTUALENV=true
+        
+        To tell pip to automatically use the currently active virtualenv::
+        
+            export PIP_RESPECT_VIRTUALENV=true
+        
+        Providing an environment with ``-E`` will be ignored.
+        
+        Using pip with virtualenvwrapper
+        ---------------------------------
+        
+        If you are using `virtualenvwrapper
+        <http://www.doughellmann.com/projects/virtualenvwrapper/>`_, you might
+        want pip to automatically create its virtualenvs in your
+        ``$WORKON_HOME``.
+        
+        You can tell pip to do so by defining ``PIP_VIRTUALENV_BASE`` in your
+        environment and setting it to the same value as that of
+        ``$WORKON_HOME``.
+        
+        Do so by adding the line::
+        
+            export PIP_VIRTUALENV_BASE=$WORKON_HOME
+        
+        in your .bashrc under the line starting with ``export WORKON_HOME``.
+        
+        Using pip with buildout
+        -----------------------
+        
+        If you are using `zc.buildout
+        <http://pypi.python.org/pypi/zc.buildout>`_ you should look at
+        `gp.recipe.pip <http://pypi.python.org/pypi/gp.recipe.pip>`_ as an
+        option to use pip and virtualenv in your buildouts.
+        
+        Command line completion
+        -----------------------
+        
+        pip comes with support for command line completion in bash and zsh and
+        allows you tab complete commands and options. To enable it you simply
+        need copy the required shell script to the your shell startup file
+        (e.g. ``.profile`` or ``.zprofile``) by running the special ``completion``
+        command, e.g. for bash::
+        
+            $ pip completion --bash >> ~/.profile
+        
+        And for zsh::
+        
+            $ pip completion --zsh >> ~/.zprofile
+        
+        Alternatively, you can use the result of the ``completion`` command
+        directly with the eval function of you shell, e.g. by adding::
+        
+            eval `pip completion --bash`
+        
+        to your startup file.
+        
+        Searching for packages
+        ----------------------
+        
+        pip can search the `Python Package Index <http://pypi.python.org/pypi>`_ (PyPI)
+        for packages using the ``pip search`` command. To search, run::
+        
+            $ pip search "query"
+        
+        The query will be used to search the names and summaries of all packages
+        indexed.
+        
+        pip searches http://pypi.python.org/pypi by default but alternative indexes
+        can be searched by using the ``--index`` flag.
+        
+Keywords: easy_install distutils setuptools egg virtualenv
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Topic :: Software Development :: Build Tools

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/SOURCES.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/SOURCES.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/SOURCES.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,42 @@
+MANIFEST.in
+setup.cfg
+setup.py
+docs/branches.txt
+docs/configuration.txt
+docs/index.txt
+docs/license.txt
+docs/news.txt
+docs/requirement-format.txt
+pip/__init__.py
+pip/backwardcompat.py
+pip/basecommand.py
+pip/baseparser.py
+pip/exceptions.py
+pip/index.py
+pip/locations.py
+pip/log.py
+pip/req.py
+pip/runner.py
+pip/util.py
+pip/venv.py
+pip.egg-info/PKG-INFO
+pip.egg-info/SOURCES.txt
+pip.egg-info/dependency_links.txt
+pip.egg-info/entry_points.txt
+pip.egg-info/not-zip-safe
+pip.egg-info/top_level.txt
+pip/commands/__init__.py
+pip/commands/bundle.py
+pip/commands/completion.py
+pip/commands/freeze.py
+pip/commands/help.py
+pip/commands/install.py
+pip/commands/search.py
+pip/commands/uninstall.py
+pip/commands/unzip.py
+pip/commands/zip.py
+pip/vcs/__init__.py
+pip/vcs/bazaar.py
+pip/vcs/git.py
+pip/vcs/mercurial.py
+pip/vcs/subversion.py
\ No newline at end of file

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/dependency_links.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/dependency_links.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/dependency_links.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/entry_points.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/entry_points.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/entry_points.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,3 @@
+[console_scripts]
+pip = pip:main
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/not-zip-safe
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/not-zip-safe	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/not-zip-safe	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/top_level.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/top_level.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/EGG-INFO/top_level.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+pip

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,239 @@
+#!/usr/bin/env python
+import sys
+import os
+import optparse
+import subprocess
+import re
+from pip.log import logger
+from pip.baseparser import parser
+from pip.exceptions import InstallationError
+from pip.basecommand import command_dict, load_command, load_all_commands
+from pip.vcs import vcs, get_src_requirement, import_vcs_support
+from pip.util import get_installed_distributions
+
+def autocomplete():
+    """Command and option completion for the main option parser (and options)
+    and its subcommands (and options).
+
+    Enable by sourcing one of the completion shell scripts (bash or zsh).
+    """
+    # Don't complete if user hasn't sourced bash_completion file.
+    if not os.environ.has_key('PIP_AUTO_COMPLETE'):
+        return
+    cwords = os.environ['COMP_WORDS'].split()[1:]
+    cword = int(os.environ['COMP_CWORD'])
+    try:
+        current = cwords[cword-1]
+    except IndexError:
+        current = ''
+    load_all_commands()
+    subcommands = [cmd for cmd, cls in command_dict.items() if not cls.hidden]
+    options = []
+    # subcommand
+    try:
+        subcommand_name = [w for w in cwords if w in subcommands][0]
+    except IndexError:
+        subcommand_name = None
+    # subcommand options
+    if subcommand_name:
+        # special case: 'help' subcommand has no options
+        if subcommand_name == 'help':
+            sys.exit(1)
+        # special case: list locally installed dists for uninstall command
+        if subcommand_name == 'uninstall' and not current.startswith('-'):
+            installed = []
+            lc = current.lower()
+            for dist in get_installed_distributions(local_only=True):
+                if dist.key.startswith(lc) and dist.key not in cwords[1:]:
+                    installed.append(dist.key)
+            # if there are no dists installed, fall back to option completion
+            if installed:
+                for dist in installed:
+                    print dist
+                sys.exit(1)
+        subcommand = command_dict.get(subcommand_name)
+        options += [(opt.get_opt_string(), opt.nargs)
+                    for opt in subcommand.parser.option_list
+                    if opt.help != optparse.SUPPRESS_HELP]
+        # filter out previously specified options from available options
+        prev_opts = [x.split('=')[0] for x in cwords[1:cword-1]]
+        options = filter(lambda (x, v): x not in prev_opts, options)
+        # filter options by current input
+        options = [(k, v) for k, v in options if k.startswith(current)]
+        for option in options:
+            opt_label = option[0]
+            # append '=' to options which require args
+            if option[1]:
+                opt_label += '='
+            print opt_label
+    else:
+        # show options of main parser only when necessary
+        if current.startswith('-') or current.startswith('--'):
+            subcommands += [opt.get_opt_string()
+                            for opt in parser.option_list
+                            if opt.help != optparse.SUPPRESS_HELP]
+        print ' '.join(filter(lambda x: x.startswith(current), subcommands))
+    sys.exit(1)
+
+def main(initial_args=None):
+    if initial_args is None:
+        initial_args = sys.argv[1:]
+    autocomplete()
+    options, args = parser.parse_args(initial_args)
+    if options.help and not args:
+        args = ['help']
+    if not args:
+        parser.error('You must give a command (use "pip help" see a list of commands)')
+    command = args[0].lower()
+    load_command(command)
+    ## FIXME: search for a command match?
+    if command not in command_dict:
+        parser.error('No command by the name %(script)s %(arg)s\n  (maybe you meant "%(script)s install %(arg)s")'
+                     % dict(script=os.path.basename(sys.argv[0]), arg=command))
+    command = command_dict[command]
+    return command.main(initial_args, args[1:], options)
+
+
+############################################################
+## Writing freeze files
+
+
+class FrozenRequirement(object):
+
+    def __init__(self, name, req, editable, comments=()):
+        self.name = name
+        self.req = req
+        self.editable = editable
+        self.comments = comments
+
+    _rev_re = re.compile(r'-r(\d+)$')
+    _date_re = re.compile(r'-(20\d\d\d\d\d\d)$')
+
+    @classmethod
+    def from_dist(cls, dist, dependency_links, find_tags=False):
+        location = os.path.normcase(os.path.abspath(dist.location))
+        comments = []
+        if vcs.get_backend_name(location):
+            editable = True
+            req = get_src_requirement(dist, location, find_tags)
+            if req is None:
+                logger.warn('Could not determine repository location of %s' % location)
+                comments.append('## !! Could not determine repository location')
+                req = dist.as_requirement()
+                editable = False
+        else:
+            editable = False
+            req = dist.as_requirement()
+            specs = req.specs
+            assert len(specs) == 1 and specs[0][0] == '=='
+            version = specs[0][1]
+            ver_match = cls._rev_re.search(version)
+            date_match = cls._date_re.search(version)
+            if ver_match or date_match:
+                svn_backend = vcs.get_backend('svn')
+                if svn_backend:
+                    svn_location = svn_backend(
+                        ).get_location(dist, dependency_links)
+                if not svn_location:
+                    logger.warn(
+                        'Warning: cannot find svn location for %s' % req)
+                    comments.append('## FIXME: could not find svn URL in dependency_links for this package:')
+                else:
+                    comments.append('# Installing as editable to satisfy requirement %s:' % req)
+                    if ver_match:
+                        rev = ver_match.group(1)
+                    else:
+                        rev = '{%s}' % date_match.group(1)
+                    editable = True
+                    req = 'svn+%s@%s#egg=%s' % (svn_location, rev, cls.egg_name(dist))
+        return cls(dist.project_name, req, editable, comments)
+
+    @staticmethod
+    def egg_name(dist):
+        name = dist.egg_name()
+        match = re.search(r'-py\d\.\d$', name)
+        if match:
+            name = name[:match.start()]
+        return name
+
+    def __str__(self):
+        req = self.req
+        if self.editable:
+            req = '-e %s' % req
+        return '\n'.join(list(self.comments)+[str(req)])+'\n'
+
+############################################################
+## Requirement files
+
+
+def call_subprocess(cmd, show_stdout=True,
+                    filter_stdout=None, cwd=None,
+                    raise_on_returncode=True,
+                    command_level=logger.DEBUG, command_desc=None,
+                    extra_environ=None):
+    if command_desc is None:
+        cmd_parts = []
+        for part in cmd:
+            if ' ' in part or '\n' in part or '"' in part or "'" in part:
+                part = '"%s"' % part.replace('"', '\\"')
+            cmd_parts.append(part)
+        command_desc = ' '.join(cmd_parts)
+    if show_stdout:
+        stdout = None
+    else:
+        stdout = subprocess.PIPE
+    logger.log(command_level, "Running command %s" % command_desc)
+    env = os.environ.copy()
+    if extra_environ:
+        env.update(extra_environ)
+    try:
+        proc = subprocess.Popen(
+            cmd, stderr=subprocess.STDOUT, stdin=None, stdout=stdout,
+            cwd=cwd, env=env)
+    except Exception, e:
+        logger.fatal(
+            "Error %s while executing command %s" % (e, command_desc))
+        raise
+    all_output = []
+    if stdout is not None:
+        stdout = proc.stdout
+        while 1:
+            line = stdout.readline()
+            if not line:
+                break
+            line = line.rstrip()
+            all_output.append(line + '\n')
+            if filter_stdout:
+                level = filter_stdout(line)
+                if isinstance(level, tuple):
+                    level, line = level
+                logger.log(level, line)
+                if not logger.stdout_level_matches(level):
+                    logger.show_progress()
+            else:
+                logger.info(line)
+    else:
+        returned_stdout, returned_stderr = proc.communicate()
+        all_output = [returned_stdout or '']
+    proc.wait()
+    if proc.returncode:
+        if raise_on_returncode:
+            if all_output:
+                logger.notify('Complete output from command %s:' % command_desc)
+                logger.notify('\n'.join(all_output) + '\n----------------------------------------')
+            raise InstallationError(
+                "Command %s failed with error code %s"
+                % (command_desc, proc.returncode))
+        else:
+            logger.warn(
+                "Command %s had error code %s"
+                % (command_desc, proc.returncode))
+    if stdout is not None:
+        return ''.join(all_output)
+
+import_vcs_support()
+
+if __name__ == '__main__':
+    exit = main()
+    if exit:
+        sys.exit(exit)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/backwardcompat.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/backwardcompat.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/backwardcompat.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,22 @@
+"""Stuff that isn't in some old versions of Python"""
+
+__all__ = ['any', 'WindowsError', 'md5']
+
+try:
+    WindowsError = WindowsError
+except NameError:
+    WindowsError = None
+try:
+    from hashlib import md5
+except ImportError:
+    import md5 as md5_module
+    md5 = md5_module.new
+
+try:
+    any = any
+except NameError:
+    def any(seq):
+        for item in seq:
+            if item:
+                return True
+        return False

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/basecommand.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/basecommand.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/basecommand.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,221 @@
+"""Base Command class, and related routines"""
+
+import sys
+import os
+import socket
+import urllib2
+import urllib
+from cStringIO import StringIO
+import traceback
+import time
+from pip.log import logger
+from pip.baseparser import parser, ConfigOptionParser, UpdatingDefaultsHelpFormatter
+from pip.exceptions import BadCommand, InstallationError, UninstallationError
+from pip.venv import restart_in_venv
+
+__all__ = ['command_dict', 'Command', 'load_all_commands',
+           'load_command', 'command_names']
+
+command_dict = {}
+
+class Command(object):
+    name = None
+    usage = None
+    hidden = False
+    def __init__(self):
+        assert self.name
+        self.parser = ConfigOptionParser(
+            usage=self.usage,
+            prog='%s %s' % (sys.argv[0], self.name),
+            version=parser.version,
+            formatter=UpdatingDefaultsHelpFormatter(),
+            name=self.name)
+        for option in parser.option_list:
+            if not option.dest or option.dest == 'help':
+                # -h, --version, etc
+                continue
+            self.parser.add_option(option)
+        command_dict[self.name] = self
+
+    def merge_options(self, initial_options, options):
+        # Make sure we have all global options carried over
+        for attr in ['log', 'venv', 'proxy', 'venv_base', 'require_venv',
+                     'respect_venv', 'log_explicit_levels', 'log_file',
+                     'timeout', 'default_vcs', 'skip_requirements_regex']:
+            setattr(options, attr, getattr(initial_options, attr) or getattr(options, attr))
+        options.quiet += initial_options.quiet
+        options.verbose += initial_options.verbose
+
+    def setup_logging(self):
+        pass
+        
+    def main(self, complete_args, args, initial_options):
+        options, args = self.parser.parse_args(args)
+        self.merge_options(initial_options, options)
+
+        level = 1 # Notify
+        level += options.verbose
+        level -= options.quiet
+        level = logger.level_for_integer(4-level)
+        complete_log = []
+        logger.consumers.extend(
+            [(level, sys.stdout),
+             (logger.DEBUG, complete_log.append)])
+        if options.log_explicit_levels:
+            logger.explicit_levels = True
+
+        self.setup_logging()
+            
+        if options.require_venv and not options.venv:
+            # If a venv is required check if it can really be found
+            if not os.environ.get('VIRTUAL_ENV'):
+                logger.fatal('Could not find an activated virtualenv (required).')
+                sys.exit(3)
+            # Automatically install in currently activated venv if required
+            options.respect_venv = True
+
+        if args and args[-1] == '___VENV_RESTART___':
+            ## FIXME: We don't do anything this this value yet:
+            venv_location = args[-2]
+            args = args[:-2]
+            options.venv = None
+        else:
+            # If given the option to respect the activated environment
+            # check if no venv is given as a command line parameter
+            if options.respect_venv and os.environ.get('VIRTUAL_ENV'):
+                if options.venv and os.path.exists(options.venv):
+                    # Make sure command line venv and environmental are the same
+                    if (os.path.realpath(os.path.expanduser(options.venv)) !=
+                            os.path.realpath(os.environ.get('VIRTUAL_ENV'))):
+                        logger.fatal("Given virtualenv (%s) doesn't match "
+                                     "currently activated virtualenv (%s)."
+                                     % (options.venv, os.environ.get('VIRTUAL_ENV')))
+                        sys.exit(3)
+                else:
+                    options.venv = os.environ.get('VIRTUAL_ENV')
+                    logger.info('Using already activated environment %s' % options.venv)
+        if options.venv:
+            logger.info('Running in environment %s' % options.venv)
+            site_packages=False
+            if options.site_packages:
+                site_packages=True
+            restart_in_venv(options.venv, options.venv_base, site_packages,
+                            complete_args)
+            # restart_in_venv should actually never return, but for clarity...
+            return
+
+        ## FIXME: not sure if this sure come before or after venv restart
+        if options.log:
+            log_fp = open_logfile(options.log, 'a')
+            logger.consumers.append((logger.DEBUG, log_fp))
+        else:
+            log_fp = None
+
+        socket.setdefaulttimeout(options.timeout or None)
+
+        setup_proxy_handler(options.proxy)
+
+        exit = 0
+        try:
+            self.run(options, args)
+        except (InstallationError, UninstallationError), e:
+            logger.fatal(str(e))
+            logger.info('Exception information:\n%s' % format_exc())
+            exit = 1
+        except BadCommand, e:
+            logger.fatal(str(e))
+            logger.info('Exception information:\n%s' % format_exc())
+            exit = 1
+        except:
+            logger.fatal('Exception:\n%s' % format_exc())
+            exit = 2
+
+        if log_fp is not None:
+            log_fp.close()
+        if exit:
+            log_fn = options.log_file
+            text = '\n'.join(complete_log)
+            logger.fatal('Storing complete log in %s' % log_fn)
+            log_fp = open_logfile(log_fn, 'w')
+            log_fp.write(text)
+            log_fp.close()
+        return exit
+
+## FIXME: should get moved somewhere else:
+def setup_proxy_handler(proxystr=''):
+    """Set the proxy handler given the option passed on the command
+    line.  If an empty string is passed it looks at the HTTP_PROXY
+    environment variable.  """
+    proxy = get_proxy(proxystr)
+    if proxy:
+        proxy_support = urllib2.ProxyHandler({"http": proxy, "ftp": proxy})
+        opener = urllib2.build_opener(proxy_support, urllib2.CacheFTPHandler)
+        urllib2.install_opener(opener)
+
+def get_proxy(proxystr=''):
+    """Get the proxy given the option passed on the command line.  If an
+    empty string is passed it looks at the HTTP_PROXY environment
+    variable."""
+    if not proxystr:
+        proxystr = os.environ.get('HTTP_PROXY', '')
+    if proxystr:
+        if '@' in proxystr:
+            user_password, server_port = proxystr.split('@', 1)
+            if ':' in user_password:
+                user, password = user_password.split(':', 1)
+            else:
+                user = user_password
+                import getpass
+                prompt = 'Password for %s@%s: ' % (user, server_port)
+                password = urllib.quote(getpass.getpass(prompt))
+            return '%s:%s@%s' % (user, password, server_port)
+        else:
+            return proxystr
+    else:
+        return None
+
+def format_exc(exc_info=None):
+    if exc_info is None:
+        exc_info = sys.exc_info()
+    out = StringIO()
+    traceback.print_exception(*exc_info, **dict(file=out))
+    return out.getvalue()
+
+def open_logfile(filename, mode='a'):
+    """Open the named log file in append mode.
+
+    If the file already exists, a separator will also be printed to
+    the file to separate past activity from current activity.
+    """
+    filename = os.path.expanduser(filename)
+    filename = os.path.abspath(filename)
+    dirname = os.path.dirname(filename)
+    if not os.path.exists(dirname):
+        os.makedirs(dirname)
+    exists = os.path.exists(filename)
+    log_fp = open(filename, mode)
+    if exists:
+        print >> log_fp, '-'*60
+        print >> log_fp, '%s run on %s' % (sys.argv[0], time.strftime('%c'))
+    return log_fp
+
+def load_command(name):
+    full_name = 'pip.commands.%s' % name
+    if full_name in sys.modules:
+        return
+    try:
+        __import__(full_name)
+    except ImportError:
+        pass
+
+def load_all_commands():
+    for name in command_names():
+        load_command(name)
+
+def command_names():
+    dir = os.path.join(os.path.dirname(__file__), 'commands')
+    names = []
+    for name in os.listdir(dir):
+        if name.endswith('.py') and os.path.isfile(os.path.join(dir, name)):
+            names.append(os.path.splitext(name)[0])
+    return names

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/baseparser.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/baseparser.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/baseparser.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,223 @@
+"""Base option parser setup"""
+
+import sys
+import optparse
+import pkg_resources
+import ConfigParser
+import os
+from distutils.util import strtobool
+from pip.locations import default_config_file, default_log_file
+
+class UpdatingDefaultsHelpFormatter(optparse.IndentedHelpFormatter):
+    """Custom help formatter for use in ConfigOptionParser that updates
+    the defaults before expanding them, allowing them to show up correctly
+    in the help listing"""
+
+    def expand_default(self, option):
+        if self.parser is not None:
+            self.parser.update_defaults(self.parser.defaults)
+        return optparse.IndentedHelpFormatter.expand_default(self, option)
+
+
+class ConfigOptionParser(optparse.OptionParser):
+    """Custom option parser which updates its defaults by by checking the
+    configuration files and environmental variables"""
+
+    def __init__(self, *args, **kwargs):
+        self.config = ConfigParser.RawConfigParser()
+        self.name = kwargs.pop('name')
+        self.files = self.get_config_files()
+        self.config.read(self.files)
+        assert self.name
+        optparse.OptionParser.__init__(self, *args, **kwargs)
+
+    def get_config_files(self):
+        config_file = os.environ.get('PIP_CONFIG_FILE', False)
+        if config_file and os.path.exists(config_file):
+            return [config_file]
+        return [default_config_file]
+
+    def update_defaults(self, defaults):
+        """Updates the given defaults with values from the config files and
+        the environ. Does a little special handling for certain types of
+        options (lists)."""
+        # Then go and look for the other sources of configuration:
+        config = {}
+        # 1. config files
+        for section in ('global', self.name):
+            config.update(dict(self.get_config_section(section)))
+        # 2. environmental variables
+        config.update(dict(self.get_environ_vars()))
+        # Then set the options with those values
+        for key, val in config.iteritems():
+            key = key.replace('_', '-')
+            if not key.startswith('--'):
+                key = '--%s' % key # only prefer long opts
+            option = self.get_option(key)
+            if option is not None:
+                # ignore empty values
+                if not val:
+                    continue
+                # handle multiline configs
+                if option.action == 'append':
+                    val = val.split()
+                else:
+                    option.nargs = 1
+                if option.action in ('store_true', 'store_false', 'count'):
+                    val = strtobool(val)
+                try:
+                    val = option.convert_value(key, val)
+                except optparse.OptionValueError, e:
+                    print ("An error occured during configuration: %s" % e)
+                    sys.exit(3)
+                defaults[option.dest] = val
+        return defaults
+
+    def get_config_section(self, name):
+        """Get a section of a configuration"""
+        if self.config.has_section(name):
+            return self.config.items(name)
+        return []
+
+    def get_environ_vars(self, prefix='PIP_'):
+        """Returns a generator with all environmental vars with prefix PIP_"""
+        for key, val in os.environ.iteritems():
+            if key.startswith(prefix):
+                yield (key.replace(prefix, '').lower(), val)
+
+    def get_default_values(self):
+        """Overridding to make updating the defaults after instantiation of
+        the option parser possible, update_defaults() does the dirty work."""
+        if not self.process_default_values:
+            # Old, pre-Optik 1.5 behaviour.
+            return optparse.Values(self.defaults)
+
+        defaults = self.update_defaults(self.defaults.copy()) # ours
+        for option in self._get_all_options():
+            default = defaults.get(option.dest)
+            if isinstance(default, basestring):
+                opt_str = option.get_opt_string()
+                defaults[option.dest] = option.check_value(opt_str, default)
+        return optparse.Values(defaults)
+
+try:
+    pip_dist = pkg_resources.get_distribution('pip')
+    version = '%s from %s (python %s)' % (
+        pip_dist, pip_dist.location, sys.version[:3])
+except pkg_resources.DistributionNotFound:
+    # when running pip.py without installing
+    version=None
+
+parser = ConfigOptionParser(
+    usage='%prog COMMAND [OPTIONS]',
+    version=version,
+    add_help_option=False,
+    formatter=UpdatingDefaultsHelpFormatter(),
+    name='global')
+
+parser.add_option(
+    '-h', '--help',
+    dest='help',
+    action='store_true',
+    help='Show help')
+parser.add_option(
+    '-E', '--environment',
+    dest='venv',
+    metavar='DIR',
+    help='virtualenv environment to run pip in (either give the '
+    'interpreter or the environment base directory)')
+parser.add_option(
+    '-s', '--enable-site-packages',
+    dest='site_packages',
+    action='store_true',
+    help='Include site-packages in virtualenv if one is to be '
+    'created. Ignored if --environment is not used or '
+    'the virtualenv already exists.')
+parser.add_option(
+    # Defines a default root directory for virtualenvs, relative
+    # virtualenvs names/paths are considered relative to it.
+    '--virtualenv-base',
+    dest='venv_base',
+    type='str',
+    default='',
+    help=optparse.SUPPRESS_HELP)
+parser.add_option(
+    # Run only if inside a virtualenv, bail if not.
+    '--require-virtualenv', '--require-venv',
+    dest='require_venv',
+    action='store_true',
+    default=False,
+    help=optparse.SUPPRESS_HELP)
+parser.add_option(
+    # Use automatically an activated virtualenv instead of installing
+    # globally. -E will be ignored if used.
+    '--respect-virtualenv', '--respect-venv',
+    dest='respect_venv',
+    action='store_true',
+    default=False,
+    help=optparse.SUPPRESS_HELP)
+
+parser.add_option(
+    '-v', '--verbose',
+    dest='verbose',
+    action='count',
+    default=0,
+    help='Give more output')
+parser.add_option(
+    '-q', '--quiet',
+    dest='quiet',
+    action='count',
+    default=0,
+    help='Give less output')
+parser.add_option(
+    '--log',
+    dest='log',
+    metavar='FILENAME',
+    help='Log file where a complete (maximum verbosity) record will be kept')
+parser.add_option(
+    # Writes the log levels explicitely to the log'
+    '--log-explicit-levels',
+    dest='log_explicit_levels',
+    action='store_true',
+    default=False,
+    help=optparse.SUPPRESS_HELP)
+parser.add_option(
+    # The default log file
+    '--local-log', '--log-file',
+    dest='log_file',
+    metavar='FILENAME',
+    default=default_log_file,
+    help=optparse.SUPPRESS_HELP)
+
+parser.add_option(
+    '--proxy',
+    dest='proxy',
+    type='str',
+    default='',
+    help="Specify a proxy in the form user:passwd at proxy.server:port. "
+    "Note that the user:password@ is optional and required only if you "
+    "are behind an authenticated proxy.  If you provide "
+    "user at proxy.server:port then you will be prompted for a password.")
+parser.add_option(
+    '--timeout', '--default-timeout',
+    metavar='SECONDS',
+    dest='timeout',
+    type='float',
+    default=15,
+    help='Set the socket timeout (default %default seconds)')
+parser.add_option(
+    # The default version control system for editables, e.g. 'svn'
+    '--default-vcs',
+    dest='default_vcs',
+    type='str',
+    default='',
+    help=optparse.SUPPRESS_HELP)
+parser.add_option(
+    # A regex to be used to skip requirements
+    '--skip-requirements-regex',
+    dest='skip_requirements_regex',
+    type='str',
+    default='',
+    help=optparse.SUPPRESS_HELP)
+
+parser.disable_interspersed_args()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+#

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/bundle.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/bundle.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/bundle.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,31 @@
+from pip.locations import build_prefix, src_prefix
+from pip.util import display_path, backup_dir
+from pip.log import logger
+from pip.exceptions import InstallationError
+from pip.commands.install import InstallCommand
+
+class BundleCommand(InstallCommand):
+    name = 'bundle'
+    usage = '%prog [OPTIONS] BUNDLE_NAME.pybundle PACKAGE_NAMES...'
+    summary = 'Create pybundles (archives containing multiple packages)'
+    bundle = True
+
+    def __init__(self):
+        super(BundleCommand, self).__init__()
+
+    def run(self, options, args):
+        if not args:
+            raise InstallationError('You must give a bundle filename')
+        if not options.build_dir:
+            options.build_dir = backup_dir(build_prefix, '-bundle')
+        if not options.src_dir:
+            options.src_dir = backup_dir(src_prefix, '-bundle')
+        # We have to get everything when creating a bundle:
+        options.ignore_installed = True
+        logger.notify('Putting temporary build files in %s and source/develop files in %s'
+                      % (display_path(options.build_dir), display_path(options.src_dir)))
+        self.bundle_filename = args.pop(0)
+        requirement_set = super(BundleCommand, self).run(options, args)
+        return requirement_set
+
+BundleCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/completion.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/completion.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/completion.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,60 @@
+import sys
+from pip.basecommand import Command
+
+BASE_COMPLETION = """
+# pip %(shell)s completion start%(script)s# pip %(shell)s completion end
+"""
+
+COMPLETION_SCRIPTS = {
+    'bash': """
+_pip_completion()
+{
+    COMPREPLY=( $( COMP_WORDS="${COMP_WORDS[*]}" \\
+                   COMP_CWORD=$COMP_CWORD \\
+                   PIP_AUTO_COMPLETE=1 $1 ) )
+}
+complete -o default -F _pip_completion pip
+""", 'zsh': """
+function _pip_completion {
+  local words cword
+  read -Ac words
+  read -cn cword
+  reply=( $( COMP_WORDS="$words[*]" \\ 
+             COMP_CWORD=$(( cword-1 )) \\
+             PIP_AUTO_COMPLETE=1 $words[1] ) )
+}
+compctl -K _pip_completion pip
+"""
+}
+
+class CompletionCommand(Command):
+    name = 'completion'
+    summary = 'A helper command to be used for command completion'
+    hidden = True
+
+    def __init__(self):
+        super(CompletionCommand, self).__init__()
+        self.parser.add_option(
+            '--bash', '-b',
+            action='store_const',
+            const='bash',
+            dest='shell',
+            help='Emit completion code for bash')
+        self.parser.add_option(
+            '--zsh', '-z',
+            action='store_const',
+            const='zsh',
+            dest='shell',
+            help='Emit completion code for zsh')
+
+    def run(self, options, args):
+        """Prints the completion code of the given shell"""
+        shells = COMPLETION_SCRIPTS.keys()
+        shell_options = ['--'+shell for shell in sorted(shells)]
+        if options.shell in shells:
+            script = COMPLETION_SCRIPTS.get(options.shell, '')
+            print BASE_COMPLETION % {'script': script, 'shell': options.shell}
+        else:
+            sys.stderr.write('ERROR: You must pass %s\n' % ' or '.join(shell_options))
+
+CompletionCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/freeze.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/freeze.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/freeze.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,107 @@
+import re
+import sys
+import pkg_resources
+import pip
+from pip.req import InstallRequirement
+from pip.log import logger
+from pip.basecommand import Command
+from pip.util import get_installed_distributions
+
+class FreezeCommand(Command):
+    name = 'freeze'
+    usage = '%prog [OPTIONS]'
+    summary = 'Output all currently installed packages (exact versions) to stdout'
+
+    def __init__(self):
+        super(FreezeCommand, self).__init__()
+        self.parser.add_option(
+            '-r', '--requirement',
+            dest='requirement',
+            action='store',
+            default=None,
+            metavar='FILENAME',
+            help='Use the given requirements file as a hint about how to generate the new frozen requirements')
+        self.parser.add_option(
+            '-f', '--find-links',
+            dest='find_links',
+            action='append',
+            default=[],
+            metavar='URL',
+            help='URL for finding packages, which will be added to the frozen requirements file')
+        self.parser.add_option(
+            '-l', '--local',
+            dest='local',
+            action='store_true',
+            default=False,
+            help='If in a virtualenv, do not report globally-installed packages')
+
+    def setup_logging(self):
+        logger.move_stdout_to_stderr()
+        
+    def run(self, options, args):
+        requirement = options.requirement
+        find_links = options.find_links or []
+        local_only = options.local
+        ## FIXME: Obviously this should be settable:
+        find_tags = False
+        skip_match = None
+
+        skip_regex = options.skip_requirements_regex
+        if skip_regex:
+            skip_match = re.compile(skip_regex)
+
+        dependency_links = []
+
+        f = sys.stdout
+
+        for dist in pkg_resources.working_set:
+            if dist.has_metadata('dependency_links.txt'):
+                dependency_links.extend(dist.get_metadata_lines('dependency_links.txt'))
+        for link in find_links:
+            if '#egg=' in link:
+                dependency_links.append(link)
+        for link in find_links:
+            f.write('-f %s\n' % link)
+        installations = {}
+        for dist in get_installed_distributions(local_only=local_only):
+            req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
+            installations[req.name] = req
+        if requirement:
+            req_f = open(requirement)
+            for line in req_f:
+                if not line.strip() or line.strip().startswith('#'):
+                    f.write(line)
+                    continue
+                if skip_match and skip_match.search(line):
+                    f.write(line)
+                    continue
+                elif line.startswith('-e') or line.startswith('--editable'):
+                    if line.startswith('-e'):
+                        line = line[2:].strip()
+                    else:
+                        line = line[len('--editable'):].strip().lstrip('=')
+                    line_req = InstallRequirement.from_editable(line, default_vcs=options.default_vcs)
+                elif (line.startswith('-r') or line.startswith('--requirement')
+                      or line.startswith('-Z') or line.startswith('--always-unzip')
+                      or line.startswith('-f') or line.startswith('-i')
+                      or line.startswith('--extra-index-url')):
+                    f.write(line)
+                    continue
+                else:
+                    line_req = InstallRequirement.from_line(line)
+                if not line_req.name:
+                    logger.notify("Skipping line because it's not clear what it would install: %s"
+                                  % line.strip())
+                    logger.notify("  (add #egg=PackageName to the URL to avoid this warning)")
+                    continue
+                if line_req.name not in installations:
+                    logger.warn("Requirement file contains %s, but that package is not installed"
+                                % line.strip())
+                    continue
+                f.write(str(installations[line_req.name]))
+                del installations[line_req.name]
+            f.write('## The following requirements were added by pip --freeze:\n')
+        for installation in sorted(installations.values(), key=lambda x: x.name):
+            f.write(str(installation))
+
+FreezeCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/help.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/help.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/help.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,30 @@
+from pip.basecommand import Command, command_dict, load_all_commands
+from pip.exceptions import InstallationError
+from pip.baseparser import parser
+
+class HelpCommand(Command):
+    name = 'help'
+    usage = '%prog'
+    summary = 'Show available commands'
+
+    def run(self, options, args):
+        load_all_commands()
+        if args:
+            ## FIXME: handle errors better here
+            command = args[0]
+            if command not in command_dict:
+                raise InstallationError('No command with the name: %s' % command)
+            command = command_dict[command]
+            command.parser.print_help()
+            return
+        parser.print_help()
+        print
+        print 'Commands available:'
+        commands = list(set(command_dict.values()))
+        commands.sort(key=lambda x: x.name)
+        for command in commands:
+            if command.hidden:
+                continue
+            print '  %s: %s' % (command.name, command.summary)
+
+HelpCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/install.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/install.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/install.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,183 @@
+import os
+from pip.req import InstallRequirement, RequirementSet
+from pip.req import parse_requirements
+from pip.log import logger
+from pip.locations import build_prefix, src_prefix
+from pip.basecommand import Command
+from pip.index import PackageFinder
+
+class InstallCommand(Command):
+    name = 'install'
+    usage = '%prog [OPTIONS] PACKAGE_NAMES...'
+    summary = 'Install packages'
+    bundle = False
+
+    def __init__(self):
+        super(InstallCommand, self).__init__()
+        self.parser.add_option(
+            '-e', '--editable',
+            dest='editables',
+            action='append',
+            default=[],
+            metavar='VCS+REPOS_URL[@REV]#egg=PACKAGE',
+            help='Install a package directly from a checkout. Source will be checked '
+            'out into src/PACKAGE (lower-case) and installed in-place (using '
+            'setup.py develop). You can run this on an existing directory/checkout (like '
+            'pip install -e src/mycheckout). This option may be provided multiple times. '
+            'Possible values for VCS are: svn, git, hg and bzr.')
+        self.parser.add_option(
+            '-r', '--requirement',
+            dest='requirements',
+            action='append',
+            default=[],
+            metavar='FILENAME',
+            help='Install all the packages listed in the given requirements file.  '
+            'This option can be used multiple times.')
+        self.parser.add_option(
+            '-f', '--find-links',
+            dest='find_links',
+            action='append',
+            default=[],
+            metavar='URL',
+            help='URL to look for packages at')
+        self.parser.add_option(
+            '-i', '--index-url', '--pypi-url',
+            dest='index_url',
+            metavar='URL',
+            default='http://pypi.python.org/simple',
+            help='Base URL of Python Package Index (default %default)')
+        self.parser.add_option(
+            '--extra-index-url',
+            dest='extra_index_urls',
+            metavar='URL',
+            action='append',
+            default=[],
+            help='Extra URLs of package indexes to use in addition to --index-url')
+        self.parser.add_option(
+            '--no-index',
+            dest='no_index',
+            action='store_true',
+            default=False,
+            help='Ignore package index (only looking at --find-links URLs instead)')
+
+        self.parser.add_option(
+            '-b', '--build', '--build-dir', '--build-directory',
+            dest='build_dir',
+            metavar='DIR',
+            default=None,
+            help='Unpack packages into DIR (default %s) and build from there' % build_prefix)
+        self.parser.add_option(
+            '-d', '--download', '--download-dir', '--download-directory',
+            dest='download_dir',
+            metavar='DIR',
+            default=None,
+            help='Download packages into DIR instead of installing them')
+        self.parser.add_option(
+            '--download-cache',
+            dest='download_cache',
+            metavar='DIR',
+            default=None,
+            help='Cache downloaded packages in DIR')
+        self.parser.add_option(
+            '--src', '--source', '--source-dir', '--source-directory',
+            dest='src_dir',
+            metavar='DIR',
+            default=None,
+            help='Check out --editable packages into DIR (default %s)' % src_prefix)
+
+        self.parser.add_option(
+            '-U', '--upgrade',
+            dest='upgrade',
+            action='store_true',
+            help='Upgrade all packages to the newest available version')
+        self.parser.add_option(
+            '-I', '--ignore-installed',
+            dest='ignore_installed',
+            action='store_true',
+            help='Ignore the installed packages (reinstalling instead)')
+        self.parser.add_option(
+            '--no-deps', '--no-dependencies',
+            dest='ignore_dependencies',
+            action='store_true',
+            default=False,
+            help='Ignore package dependencies')
+        self.parser.add_option(
+            '--no-install',
+            dest='no_install',
+            action='store_true',
+            help="Download and unpack all packages, but don't actually install them")
+        self.parser.add_option(
+            '--no-download',
+            dest='no_download',
+            action="store_true",
+            help="Don't download any packages, just install the ones already downloaded "
+            "(completes an install run with --no-install)")
+
+        self.parser.add_option(
+            '--install-option',
+            dest='install_options',
+            action='append',
+            help="Extra arguments to be supplied to the setup.py install "
+            "command (use like --install-option=\"--install-scripts=/usr/local/bin\").  "
+            "Use multiple --install-option options to pass multiple options to setup.py install.  "
+            "If you are using an option with a directory path, be sure to use absolute path.")
+
+    def run(self, options, args):
+        if not options.build_dir:
+            options.build_dir = build_prefix
+        if not options.src_dir:
+            options.src_dir = src_prefix
+        if options.download_dir:
+            options.no_install = True
+            options.ignore_installed = True
+        options.build_dir = os.path.abspath(options.build_dir)
+        options.src_dir = os.path.abspath(options.src_dir)
+        install_options = options.install_options or []
+        index_urls = [options.index_url] + options.extra_index_urls
+        if options.no_index:
+            logger.notify('Ignoring indexes: %s' % ','.join(index_urls))
+            index_urls = []
+        finder = PackageFinder(
+            find_links=options.find_links,
+            index_urls=index_urls)
+        requirement_set = RequirementSet(
+            build_dir=options.build_dir,
+            src_dir=options.src_dir,
+            download_dir=options.download_dir,
+            download_cache=options.download_cache,
+            upgrade=options.upgrade,
+            ignore_installed=options.ignore_installed,
+            ignore_dependencies=options.ignore_dependencies)
+        for name in args:
+            requirement_set.add_requirement(
+                InstallRequirement.from_line(name, None))
+        for name in options.editables:
+            requirement_set.add_requirement(
+                InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
+        for filename in options.requirements:
+            for req in parse_requirements(filename, finder=finder, options=options):
+                requirement_set.add_requirement(req)
+        if not options.no_download:
+            requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
+        else:
+            requirement_set.locate_files()
+        if not options.no_install and not self.bundle:
+            requirement_set.install(install_options)
+            installed = ' '.join([req.name for req in
+                                  requirement_set.successfully_installed])
+            if installed:
+                logger.notify('Successfully installed %s' % installed)
+        elif not self.bundle:
+            downloaded = ' '.join([req.name for req in
+                                   requirement_set.successfully_downloaded])
+            if downloaded:
+                logger.notify('Successfully downloaded %s' % downloaded)
+        elif self.bundle:
+            requirement_set.create_bundle(self.bundle_filename)
+            logger.notify('Created bundle in %s' % self.bundle_filename)
+        # Clean up
+        if not options.no_install:
+            requirement_set.cleanup_files(bundle=self.bundle)
+        return requirement_set
+
+InstallCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/search.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/search.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/search.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,109 @@
+import sys
+import xmlrpclib
+import textwrap
+import pkg_resources
+from pip.basecommand import Command
+from pip.util import get_terminal_size
+from pip.log import logger
+from distutils.version import StrictVersion, LooseVersion
+
+class SearchCommand(Command):
+    name = 'search'
+    usage = '%prog QUERY'
+    summary = 'Search PyPI'
+
+    def __init__(self):
+        super(SearchCommand, self).__init__()
+        self.parser.add_option(
+            '--index',
+            dest='index',
+            metavar='URL',
+            default='http://pypi.python.org/pypi',
+            help='Base URL of Python Package Index (default %default)')
+
+    def run(self, options, args):
+        if not args:
+            logger.warn('ERROR: Missing required argument (search query).')
+            return
+        query = ' '.join(args)
+        index_url = options.index
+
+        pypi_hits = self.search(query, index_url)
+        hits = transform_hits(pypi_hits)
+
+        terminal_width = None
+        if sys.stdout.isatty():
+            terminal_width = get_terminal_size()[0]
+
+        print_results(hits, terminal_width=terminal_width)
+
+    def search(self, query, index_url):
+        pypi = xmlrpclib.ServerProxy(index_url)
+        hits = pypi.search({'name': query, 'summary': query}, 'or')
+        return hits
+
+def transform_hits(hits):
+    """
+    The list from pypi is really a list of versions. We want a list of
+    packages with the list of versions stored inline. This converts the
+    list from pypi into one we can use.
+    """
+    packages = {}
+    for hit in hits:
+        name = hit['name']
+        summary = hit['summary']
+        version = hit['version']
+        score = hit['_pypi_ordering']
+
+        if name not in packages.keys():
+            packages[name] = {'name': name, 'summary': summary, 'versions': [version], 'score': score}
+        else:
+            packages[name]['versions'].append(version)
+
+            # if this is the highest version, replace summary and score
+            if version == highest_version(packages[name]['versions']):
+                packages[name]['summary'] = summary
+                packages[name]['score'] = score
+
+    # each record has a unique name now, so we will convert the dict into a list sorted by score
+    package_list = sorted(packages.values(), lambda x, y: cmp(y['score'], x['score']))
+    return package_list
+
+def print_results(hits, name_column_width=25, terminal_width=None):
+    installed_packages = [p.project_name for p in pkg_resources.working_set]
+    for hit in hits:
+        name = hit['name']
+        summary = hit['summary'] or ''
+        if terminal_width is not None:
+            # wrap and indent summary to fit terminal
+            summary = textwrap.wrap(summary, terminal_width - name_column_width - 5)
+            summary = ('\n' + ' ' * (name_column_width + 3)).join(summary)
+        line = '%s - %s' % (name.ljust(name_column_width), summary)
+        try:
+            logger.notify(line)
+            if name in installed_packages:
+                dist = pkg_resources.get_distribution(name)
+                logger.indent += 2
+                try:
+                    latest = highest_version(hit['versions'])
+                    if dist.version == latest:
+                        logger.notify('INSTALLED: %s (latest)' % dist.version)
+                    else:
+                        logger.notify('INSTALLED: %s' % dist.version)
+                        logger.notify('LATEST:    %s' % latest)
+                finally:
+                    logger.indent -= 2
+        except UnicodeEncodeError:
+            pass
+
+def compare_versions(version1, version2):
+    try:
+        return cmp(StrictVersion(version1), StrictVersion(version2))
+    # in case of abnormal version number, fall back to LooseVersion
+    except ValueError:
+        return cmp(LooseVersion(version1), LooseVersion(version2))
+
+def highest_version(versions):
+    return reduce((lambda v1, v2: compare_versions(v1, v2) == 1 and v1 or v2), versions)
+
+SearchCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/uninstall.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/uninstall.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/uninstall.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,39 @@
+from pip.req import InstallRequirement, RequirementSet
+from pip.req import parse_requirements
+from pip.basecommand import Command
+
+class UninstallCommand(Command):
+    name = 'uninstall'
+    usage = '%prog [OPTIONS] PACKAGE_NAMES ...'
+    summary = 'Uninstall packages'
+
+    def __init__(self):
+        super(UninstallCommand, self).__init__()
+        self.parser.add_option(
+            '-r', '--requirement',
+            dest='requirements',
+            action='append',
+            default=[],
+            metavar='FILENAME',
+            help='Uninstall all the packages listed in the given requirements file.  '
+            'This option can be used multiple times.')
+        self.parser.add_option(
+            '-y', '--yes',
+            dest='yes',
+            action='store_true',
+            help="Don't ask for confirmation of uninstall deletions.")
+
+    def run(self, options, args):
+        requirement_set = RequirementSet(
+            build_dir=None,
+            src_dir=None,
+            download_dir=None)
+        for name in args:
+            requirement_set.add_requirement(
+                InstallRequirement.from_line(name))
+        for filename in options.requirements:
+            for req in parse_requirements(filename, options=options):
+                requirement_set.add_requirement(req)
+        requirement_set.uninstall(auto_confirm=options.yes)
+
+UninstallCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/unzip.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/unzip.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/unzip.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,7 @@
+from pip.commands.zip import ZipCommand
+
+class UnzipCommand(ZipCommand):
+    name = 'unzip'
+    summary = 'Unzip individual packages'
+
+UnzipCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/zip.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/zip.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/commands/zip.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,344 @@
+import sys
+import re
+import fnmatch
+import os
+import shutil
+import zipfile
+from pip.util import display_path, backup_dir
+from pip.log import logger
+from pip.exceptions import InstallationError
+from pip.basecommand import Command
+
+class ZipCommand(Command):
+    name = 'zip'
+    usage = '%prog [OPTIONS] PACKAGE_NAMES...'
+    summary = 'Zip individual packages'
+
+    def __init__(self):
+        super(ZipCommand, self).__init__()
+        if self.name == 'zip':
+            self.parser.add_option(
+                '--unzip',
+                action='store_true',
+                dest='unzip',
+                help='Unzip (rather than zip) a package')
+        else:
+            self.parser.add_option(
+                '--zip',
+                action='store_false',
+                dest='unzip',
+                default=True,
+                help='Zip (rather than unzip) a package')
+        self.parser.add_option(
+            '--no-pyc',
+            action='store_true',
+            dest='no_pyc',
+            help='Do not include .pyc files in zip files (useful on Google App Engine)')
+        self.parser.add_option(
+            '-l', '--list',
+            action='store_true',
+            dest='list',
+            help='List the packages available, and their zip status')
+        self.parser.add_option(
+            '--sort-files',
+            action='store_true',
+            dest='sort_files',
+            help='With --list, sort packages according to how many files they contain')
+        self.parser.add_option(
+            '--path',
+            action='append',
+            dest='paths',
+            help='Restrict operations to the given paths (may include wildcards)')
+        self.parser.add_option(
+            '-n', '--simulate',
+            action='store_true',
+            help='Do not actually perform the zip/unzip operation')
+
+    def paths(self):
+        """All the entries of sys.path, possibly restricted by --path"""
+        if not self.select_paths:
+            return sys.path
+        result = []
+        match_any = set()
+        for path in sys.path:
+            path = os.path.normcase(os.path.abspath(path))
+            for match in self.select_paths:
+                match = os.path.normcase(os.path.abspath(match))
+                if '*' in match:
+                    if re.search(fnmatch.translate(match+'*'), path):
+                        result.append(path)
+                        match_any.add(match)
+                        break
+                else:
+                    if path.startswith(match):
+                        result.append(path)
+                        match_any.add(match)
+                        break
+            else:
+                logger.debug("Skipping path %s because it doesn't match %s"
+                             % (path, ', '.join(self.select_paths)))
+        for match in self.select_paths:
+            if match not in match_any and '*' not in match:
+                result.append(match)
+                logger.debug("Adding path %s because it doesn't match anything already on sys.path"
+                             % match)
+        return result
+
+    def run(self, options, args):
+        self.select_paths = options.paths
+        self.simulate = options.simulate
+        if options.list:
+            return self.list(options, args)
+        if not args:
+            raise InstallationError(
+                'You must give at least one package to zip or unzip')
+        packages = []
+        for arg in args:
+            module_name, filename = self.find_package(arg)
+            if options.unzip and os.path.isdir(filename):
+                raise InstallationError(
+                    'The module %s (in %s) is not a zip file; cannot be unzipped'
+                    % (module_name, filename))
+            elif not options.unzip and not os.path.isdir(filename):
+                raise InstallationError(
+                    'The module %s (in %s) is not a directory; cannot be zipped'
+                    % (module_name, filename))
+            packages.append((module_name, filename))
+        last_status = None
+        for module_name, filename in packages:
+            if options.unzip:
+                last_status = self.unzip_package(module_name, filename)
+            else:
+                last_status = self.zip_package(module_name, filename, options.no_pyc)
+        return last_status
+
+    def unzip_package(self, module_name, filename):
+        zip_filename = os.path.dirname(filename)
+        if not os.path.isfile(zip_filename) and zipfile.is_zipfile(zip_filename):
+            raise InstallationError(
+                'Module %s (in %s) isn\'t located in a zip file in %s'
+                % (module_name, filename, zip_filename))
+        package_path = os.path.dirname(zip_filename)
+        if not package_path in self.paths():
+            logger.warn(
+                'Unpacking %s into %s, but %s is not on sys.path'
+                % (display_path(zip_filename), display_path(package_path),
+                   display_path(package_path)))
+        logger.notify('Unzipping %s (in %s)' % (module_name, display_path(zip_filename)))
+        if self.simulate:
+            logger.notify('Skipping remaining operations because of --simulate')
+            return
+        logger.indent += 2
+        try:
+            ## FIXME: this should be undoable:
+            zip = zipfile.ZipFile(zip_filename)
+            to_save = []
+            for name in zip.namelist():
+                if name.startswith('%s/' % module_name):
+                    content = zip.read(name)
+                    dest = os.path.join(package_path, name)
+                    if not os.path.exists(os.path.dirname(dest)):
+                        os.makedirs(os.path.dirname(dest))
+                    if not content and dest.endswith('/'):
+                        if not os.path.exists(dest):
+                            os.makedirs(dest)
+                    else:
+                        f = open(dest, 'wb')
+                        f.write(content)
+                        f.close()
+                else:
+                    to_save.append((name, zip.read(name)))
+            zip.close()
+            if not to_save:
+                logger.info('Removing now-empty zip file %s' % display_path(zip_filename))
+                os.unlink(zip_filename)
+                self.remove_filename_from_pth(zip_filename)
+            else:
+                logger.info('Removing entries in %s/ from zip file %s' % (module_name, display_path(zip_filename)))
+                zip = zipfile.ZipFile(zip_filename, 'w')
+                for name, content in to_save:
+                    zip.writestr(name, content)
+                zip.close()
+        finally:
+            logger.indent -= 2
+
+    def zip_package(self, module_name, filename, no_pyc):
+        orig_filename = filename
+        logger.notify('Zip %s (in %s)' % (module_name, display_path(filename)))
+        logger.indent += 2
+        if filename.endswith('.egg'):
+            dest_filename = filename
+        else:
+            dest_filename = filename + '.zip'
+        try:
+            ## FIXME: I think this needs to be undoable:
+            if filename == dest_filename:
+                filename = backup_dir(orig_filename)
+                logger.notify('Moving %s aside to %s' % (orig_filename, filename))
+                if not self.simulate:
+                    shutil.move(orig_filename, filename)
+            try:
+                logger.info('Creating zip file in %s' % display_path(dest_filename))
+                if not self.simulate:
+                    zip = zipfile.ZipFile(dest_filename, 'w')
+                    zip.writestr(module_name + '/', '')
+                    for dirpath, dirnames, filenames in os.walk(filename):
+                        if no_pyc:
+                            filenames = [f for f in filenames
+                                         if not f.lower().endswith('.pyc')]
+                        for fns, is_dir in [(dirnames, True), (filenames, False)]:
+                            for fn in fns:
+                                full = os.path.join(dirpath, fn)
+                                dest = os.path.join(module_name, dirpath[len(filename):].lstrip(os.path.sep), fn)
+                                if is_dir:
+                                    zip.writestr(dest+'/', '')
+                                else:
+                                    zip.write(full, dest)
+                    zip.close()
+                logger.info('Removing old directory %s' % display_path(filename))
+                if not self.simulate:
+                    shutil.rmtree(filename)
+            except:
+                ## FIXME: need to do an undo here
+                raise
+            ## FIXME: should also be undone:
+            self.add_filename_to_pth(dest_filename)
+        finally:
+            logger.indent -= 2
+
+    def remove_filename_from_pth(self, filename):
+        for pth in self.pth_files():
+            f = open(pth, 'r')
+            lines = f.readlines()
+            f.close()
+            new_lines = [
+                l for l in lines if l.strip() != filename]
+            if lines != new_lines:
+                logger.info('Removing reference to %s from .pth file %s'
+                            % (display_path(filename), display_path(pth)))
+                if not filter(None, new_lines):
+                    logger.info('%s file would be empty: deleting' % display_path(pth))
+                    if not self.simulate:
+                        os.unlink(pth)
+                else:
+                    if not self.simulate:
+                        f = open(pth, 'w')
+                        f.writelines(new_lines)
+                        f.close()
+                return
+        logger.warn('Cannot find a reference to %s in any .pth file' % display_path(filename))
+
+    def add_filename_to_pth(self, filename):
+        path = os.path.dirname(filename)
+        dest = os.path.join(path, filename + '.pth')
+        if path not in self.paths():
+            logger.warn('Adding .pth file %s, but it is not on sys.path' % display_path(dest))
+        if not self.simulate:
+            if os.path.exists(dest):
+                f = open(dest)
+                lines = f.readlines()
+                f.close()
+                if lines and not lines[-1].endswith('\n'):
+                    lines[-1] += '\n'
+                lines.append(filename+'\n')
+            else:
+                lines = [filename + '\n']
+            f = open(dest, 'w')
+            f.writelines(lines)
+            f.close()
+
+    def pth_files(self):
+        for path in self.paths():
+            if not os.path.exists(path) or not os.path.isdir(path):
+                continue
+            for filename in os.listdir(path):
+                if filename.endswith('.pth'):
+                    yield os.path.join(path, filename)
+
+    def find_package(self, package):
+        for path in self.paths():
+            full = os.path.join(path, package)
+            if os.path.exists(full):
+                return package, full
+            if not os.path.isdir(path) and zipfile.is_zipfile(path):
+                zip = zipfile.ZipFile(path, 'r')
+                try:
+                    zip.read('%s/__init__.py' % package)
+                except KeyError:
+                    pass
+                else:
+                    zip.close()
+                    return package, full
+                zip.close()
+        ## FIXME: need special error for package.py case:
+        raise InstallationError(
+            'No package with the name %s found' % package)
+
+    def list(self, options, args):
+        if args:
+            raise InstallationError(
+                'You cannot give an argument with --list')
+        for path in sorted(self.paths()):
+            if not os.path.exists(path):
+                continue
+            basename = os.path.basename(path.rstrip(os.path.sep))
+            if os.path.isfile(path) and zipfile.is_zipfile(path):
+                if os.path.dirname(path) not in self.paths():
+                    logger.notify('Zipped egg: %s' % display_path(path))
+                continue
+            if (basename != 'site-packages' and basename != 'dist-packages'
+                and not path.replace('\\', '/').endswith('lib/python')):
+                continue
+            logger.notify('In %s:' % display_path(path))
+            logger.indent += 2
+            zipped = []
+            unzipped = []
+            try:
+                for filename in sorted(os.listdir(path)):
+                    ext = os.path.splitext(filename)[1].lower()
+                    if ext in ('.pth', '.egg-info', '.egg-link'):
+                        continue
+                    if ext == '.py':
+                        logger.info('Not displaying %s: not a package' % display_path(filename))
+                        continue
+                    full = os.path.join(path, filename)
+                    if os.path.isdir(full):
+                        unzipped.append((filename, self.count_package(full)))
+                    elif zipfile.is_zipfile(full):
+                        zipped.append(filename)
+                    else:
+                        logger.info('Unknown file: %s' % display_path(filename))
+                if zipped:
+                    logger.notify('Zipped packages:')
+                    logger.indent += 2
+                    try:
+                        for filename in zipped:
+                            logger.notify(filename)
+                    finally:
+                        logger.indent -= 2
+                else:
+                    logger.notify('No zipped packages.')
+                if unzipped:
+                    if options.sort_files:
+                        unzipped.sort(key=lambda x: -x[1])
+                    logger.notify('Unzipped packages:')
+                    logger.indent += 2
+                    try:
+                        for filename, count in unzipped:
+                            logger.notify('%s  (%i files)' % (filename, count))
+                    finally:
+                        logger.indent -= 2
+                else:
+                    logger.notify('No unzipped packages.')
+            finally:
+                logger.indent -= 2
+
+    def count_package(self, path):
+        total = 0
+        for dirpath, dirnames, filenames in os.walk(path):
+            filenames = [f for f in filenames
+                         if not f.lower().endswith('.pyc')]
+            total += len(filenames)
+        return total
+
+ZipCommand()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/exceptions.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/exceptions.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/exceptions.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,13 @@
+"""Exceptions used throughout package"""
+
+class InstallationError(Exception):
+    """General exception during installation"""
+
+class UninstallationError(Exception):
+    """General exception during uninstallation"""
+
+class DistributionNotFound(InstallationError):
+    """Raised when a distribution cannot be found to satisfy a requirement"""
+
+class BadCommand(Exception):
+    """Raised when virtualenv or a command is not found"""

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/index.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/index.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/index.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,567 @@
+"""Routines related to PyPI, indexes"""
+
+import sys
+import os
+import re
+import threading
+import posixpath
+import pkg_resources
+import urllib2
+import urlparse
+import httplib
+import socket
+from Queue import Queue
+from Queue import Empty as QueueEmpty
+from pip.log import logger
+from pip.util import Inf, path_to_url2, url_to_path
+from pip.util import normalize_name, splitext
+from pip.exceptions import DistributionNotFound
+
+__all__ = ['PackageFinder']
+
+class PackageFinder(object):
+    """This finds packages.
+
+    This is meant to match easy_install's technique for looking for
+    packages, by reading pages and looking for appropriate links
+    """
+
+    failure_limit = 3
+
+    def __init__(self, find_links, index_urls):
+        self.find_links = find_links
+        self.index_urls = index_urls
+        self.dependency_links = []
+        self.cache = PageCache()
+        # These are boring links that have already been logged somehow:
+        self.logged_links = set()
+
+    def add_dependency_links(self, links):
+        ## FIXME: this shouldn't be global list this, it should only
+        ## apply to requirements of the package that specifies the
+        ## dependency_links value
+        ## FIXME: also, we should track comes_from (i.e., use Link)
+        self.dependency_links.extend(links)
+
+    def find_requirement(self, req, upgrade):
+        url_name = req.url_name
+        # Only check main index if index URL is given:
+        main_index_url = None
+        if self.index_urls:
+            # Check that we have the url_name correctly spelled:
+            main_index_url = Link(posixpath.join(self.index_urls[0], url_name))
+            # This will also cache the page, so it's okay that we get it again later:
+            page = self._get_page(main_index_url, req)
+            if page is None:
+                url_name = self._find_url_name(Link(self.index_urls[0]), url_name, req) or req.url_name
+        def mkurl_pypi_url(url):
+            loc =  posixpath.join(url, url_name)
+            # For maximum compatibility with easy_install, ensure the path
+            # ends in a trailing slash.  Although this isn't in the spec
+            # (and PyPI can handle it without the slash) some other index
+            # implementations might break if they relied on easy_install's behavior.
+            if not loc.endswith('/'):
+                loc = loc + '/'
+            return loc
+        if url_name is not None:
+            locations = [
+                mkurl_pypi_url(url)
+                for url in self.index_urls] + self.find_links
+        else:
+            locations = list(self.find_links)
+        locations.extend(self.dependency_links)
+        for version in req.absolute_versions:
+            if url_name is not None and main_index_url is not None:
+                locations = [
+                    posixpath.join(main_index_url.url, version)] + locations
+        file_locations = []
+        url_locations = []
+        for url in locations:
+            if url.startswith('file:'):
+                path = url_to_path(url)
+                if os.path.isdir(path):
+                    path = os.path.realpath(path)
+                    for item in os.listdir(path):
+                        file_locations.append(
+                            path_to_url2(os.path.join(path, item)))
+                elif os.path.isfile(path):
+                    file_locations.append(path_to_url2(path))
+            else:
+                url_locations.append(url)
+
+        locations = [Link(url) for url in url_locations]
+        logger.debug('URLs to search for versions for %s:' % req)
+        for location in locations:
+            logger.debug('* %s' % location)
+        found_versions = []
+        found_versions.extend(
+            self._package_versions(
+                [Link(url, '-f') for url in self.find_links], req.name.lower()))
+        page_versions = []
+        for page in self._get_pages(locations, req):
+            logger.debug('Analyzing links from page %s' % page.url)
+            logger.indent += 2
+            try:
+                page_versions.extend(self._package_versions(page.links, req.name.lower()))
+            finally:
+                logger.indent -= 2
+        dependency_versions = list(self._package_versions(
+            [Link(url) for url in self.dependency_links], req.name.lower()))
+        if dependency_versions:
+            logger.info('dependency_links found: %s' % ', '.join([link.url for parsed, link, version in dependency_versions]))
+        file_versions = list(self._package_versions(
+                [Link(url) for url in file_locations], req.name.lower()))
+        if not found_versions and not page_versions and not dependency_versions and not file_versions:
+            logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
+            raise DistributionNotFound('No distributions at all found for %s' % req)
+        if req.satisfied_by is not None:
+            found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
+        if file_versions:
+            file_versions.sort(reverse=True)
+            logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
+            found_versions = file_versions + found_versions
+        all_versions = found_versions + page_versions + dependency_versions
+        applicable_versions = []
+        for (parsed_version, link, version) in all_versions:
+            if version not in req.req:
+                logger.info("Ignoring link %s, version %s doesn't match %s"
+                            % (link, version, ','.join([''.join(s) for s in req.req.specs])))
+                continue
+            applicable_versions.append((link, version))
+        applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
+        existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
+        if not upgrade and existing_applicable:
+            if applicable_versions[0][1] is Inf:
+                logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
+                            % req.satisfied_by.version)
+            else:
+                logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
+                            % (req.satisfied_by.version, applicable_versions[0][1]))
+            return None
+        if not applicable_versions:
+            logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
+                         % (req, ', '.join([version for parsed_version, link, version in found_versions])))
+            raise DistributionNotFound('No distributions matching the version for %s' % req)
+        if applicable_versions[0][0] is Inf:
+            # We have an existing version, and its the best version
+            logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
+                        % (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
+            return None
+        if len(applicable_versions) > 1:
+            logger.info('Using version %s (newest of versions: %s)' %
+                        (applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
+        return applicable_versions[0][0]
+
+    def _find_url_name(self, index_url, url_name, req):
+        """Finds the true URL name of a package, when the given name isn't quite correct.
+        This is usually used to implement case-insensitivity."""
+        if not index_url.url.endswith('/'):
+            # Vaguely part of the PyPI API... weird but true.
+            ## FIXME: bad to modify this?
+            index_url.url += '/'
+        page = self._get_page(index_url, req)
+        if page is None:
+            logger.fatal('Cannot fetch index base URL %s' % index_url)
+            return
+        norm_name = normalize_name(req.url_name)
+        for link in page.links:
+            base = posixpath.basename(link.path.rstrip('/'))
+            if norm_name == normalize_name(base):
+                logger.notify('Real name of requirement %s is %s' % (url_name, base))
+                return base
+        return None
+
+    def _get_pages(self, locations, req):
+        """Yields (page, page_url) from the given locations, skipping
+        locations that have errors, and adding download/homepage links"""
+        pending_queue = Queue()
+        for location in locations:
+            pending_queue.put(location)
+        done = []
+        seen = set()
+        threads = []
+        for i in range(min(10, len(locations))):
+            t = threading.Thread(target=self._get_queued_page, args=(req, pending_queue, done, seen))
+            t.setDaemon(True)
+            threads.append(t)
+            t.start()
+        for t in threads:
+            t.join()
+        return done
+
+    _log_lock = threading.Lock()
+
+    def _get_queued_page(self, req, pending_queue, done, seen):
+        while 1:
+            try:
+                location = pending_queue.get(False)
+            except QueueEmpty:
+                return
+            if location in seen:
+                continue
+            seen.add(location)
+            page = self._get_page(location, req)
+            if page is None:
+                continue
+            done.append(page)
+            for link in page.rel_links():
+                pending_queue.put(link)
+
+    _egg_fragment_re = re.compile(r'#egg=([^&]*)')
+    _egg_info_re = re.compile(r'([a-z0-9_.]+)-([a-z0-9_.-]+)', re.I)
+    _py_version_re = re.compile(r'-py([123]\.[0-9])$')
+
+    def _sort_links(self, links):
+        "Brings links in order, non-egg links first, egg links second"
+        eggs, no_eggs = [], []
+        for link in links:
+            if link.egg_fragment:
+                eggs.append(link)
+            else:
+                no_eggs.append(link)
+        return no_eggs + eggs
+
+    def _package_versions(self, links, search_name):
+        seen_links = {}
+        for link in self._sort_links(links):
+            if link.url in seen_links:
+                continue
+            seen_links[link.url] = None
+            if link.egg_fragment:
+                egg_info = link.egg_fragment
+            else:
+                path = link.path
+                egg_info, ext = link.splitext()
+                if not ext:
+                    if link not in self.logged_links:
+                        logger.debug('Skipping link %s; not a file' % link)
+                        self.logged_links.add(link)
+                    continue
+                if egg_info.endswith('.tar'):
+                    # Special double-extension case:
+                    egg_info = egg_info[:-4]
+                    ext = '.tar' + ext
+                if ext not in ('.tar.gz', '.tar.bz2', '.tar', '.tgz', '.zip'):
+                    if link not in self.logged_links:
+                        logger.debug('Skipping link %s; unknown archive format: %s' % (link, ext))
+                        self.logged_links.add(link)
+                    continue
+            version = self._egg_info_matches(egg_info, search_name, link)
+            if version is None:
+                logger.debug('Skipping link %s; wrong project name (not %s)' % (link, search_name))
+                continue
+            match = self._py_version_re.search(version)
+            if match:
+                version = version[:match.start()]
+                py_version = match.group(1)
+                if py_version != sys.version[:3]:
+                    logger.debug('Skipping %s because Python version is incorrect' % link)
+                    continue
+            logger.debug('Found link %s, version: %s' % (link, version))
+            yield (pkg_resources.parse_version(version),
+                   link,
+                   version)
+
+    def _egg_info_matches(self, egg_info, search_name, link):
+        match = self._egg_info_re.search(egg_info)
+        if not match:
+            logger.debug('Could not parse version from link: %s' % link)
+            return None
+        name = match.group(0).lower()
+        # To match the "safe" name that pkg_resources creates:
+        name = name.replace('_', '-')
+        if name.startswith(search_name.lower()):
+            return match.group(0)[len(search_name):].lstrip('-')
+        else:
+            return None
+
+    def _get_page(self, link, req):
+        return HTMLPage.get_page(link, req, cache=self.cache)
+
+
+class PageCache(object):
+    """Cache of HTML pages"""
+
+    failure_limit = 3
+
+    def __init__(self):
+        self._failures = {}
+        self._pages = {}
+        self._archives = {}
+
+    def too_many_failures(self, url):
+        return self._failures.get(url, 0) >= self.failure_limit
+
+    def get_page(self, url):
+        return self._pages.get(url)
+
+    def is_archive(self, url):
+        return self._archives.get(url, False)
+
+    def set_is_archive(self, url, value=True):
+        self._archives[url] = value
+
+    def add_page_failure(self, url, level):
+        self._failures[url] = self._failures.get(url, 0)+level
+
+    def add_page(self, urls, page):
+        for url in urls:
+            self._pages[url] = page
+
+class HTMLPage(object):
+    """Represents one page, along with its URL"""
+
+    ## FIXME: these regexes are horrible hacks:
+    _homepage_re = re.compile(r'<th>\s*home\s*page', re.I)
+    _download_re = re.compile(r'<th>\s*download\s+url', re.I)
+    ## These aren't so aweful:
+    _rel_re = re.compile("""<[^>]*\srel\s*=\s*['"]?([^'">]+)[^>]*>""", re.I)
+    _href_re = re.compile('href=(?:"([^"]*)"|\'([^\']*)\'|([^>\\s\\n]*))', re.I|re.S)
+    _base_re = re.compile(r"""<base\s+href\s*=\s*['"]?([^'">]+)""", re.I)
+
+    def __init__(self, content, url, headers=None):
+        self.content = content
+        self.url = url
+        self.headers = headers
+
+    def __str__(self):
+        return self.url
+
+    @classmethod
+    def get_page(cls, link, req, cache=None, skip_archives=True):
+        url = link.url
+        url = url.split('#', 1)[0]
+        if cache.too_many_failures(url):
+            return None
+        if url.lower().startswith('svn'):
+            logger.debug('Cannot look at svn URL %s' % link)
+            return None
+        if cache is not None:
+            inst = cache.get_page(url)
+            if inst is not None:
+                return inst
+        try:
+            if skip_archives:
+                if cache is not None:
+                    if cache.is_archive(url):
+                        return None
+                filename = link.filename
+                for bad_ext in ['.tar', '.tar.gz', '.tar.bz2', '.tgz', '.zip']:
+                    if filename.endswith(bad_ext):
+                        content_type = cls._get_content_type(url)
+                        if content_type.lower().startswith('text/html'):
+                            break
+                        else:
+                            logger.debug('Skipping page %s because of Content-Type: %s' % (link, content_type))
+                            if cache is not None:
+                                cache.set_is_archive(url)
+                            return None
+            logger.debug('Getting page %s' % url)
+            resp = urllib2.urlopen(url)
+            real_url = resp.geturl()
+            headers = resp.info()
+            inst = cls(resp.read(), real_url, headers)
+        except (urllib2.HTTPError, urllib2.URLError, socket.timeout, socket.error), e:
+            desc = str(e)
+            if isinstance(e, socket.timeout):
+                log_meth = logger.info
+                level =1
+                desc = 'timed out'
+            elif isinstance(e, urllib2.URLError):
+                log_meth = logger.info
+                if hasattr(e, 'reason') and isinstance(e.reason, socket.timeout):
+                    desc = 'timed out'
+                    level = 1
+                else:
+                    level = 2
+            elif isinstance(e, urllib2.HTTPError) and e.code == 404:
+                ## FIXME: notify?
+                log_meth = logger.info
+                level = 2
+            else:
+                log_meth = logger.info
+                level = 1
+            log_meth('Could not fetch URL %s: %s' % (link, desc))
+            log_meth('Will skip URL %s when looking for download links for %s' % (link.url, req))
+            if cache is not None:
+                cache.add_page_failure(url, level)
+            return None
+        if cache is not None:
+            cache.add_page([url, real_url], inst)
+        return inst
+
+    @staticmethod
+    def _get_content_type(url):
+        """Get the Content-Type of the given url, using a HEAD request"""
+        scheme, netloc, path, query, fragment = urlparse.urlsplit(url)
+        if scheme == 'http':
+            ConnClass = httplib.HTTPConnection
+        elif scheme == 'https':
+            ConnClass = httplib.HTTPSConnection
+        else:
+            ## FIXME: some warning or something?
+            ## assertion error?
+            return ''
+        if query:
+            path += '?' + query
+        conn = ConnClass(netloc)
+        try:
+            conn.request('HEAD', path, headers={'Host': netloc})
+            resp = conn.getresponse()
+            if resp.status != 200:
+                ## FIXME: doesn't handle redirects
+                return ''
+            return resp.getheader('Content-Type') or ''
+        finally:
+            conn.close()
+
+    @property
+    def base_url(self):
+        if not hasattr(self, "_base_url"):
+            match = self._base_re.search(self.content)
+            if match:
+                self._base_url = match.group(1)
+            else:
+                self._base_url = self.url
+        return self._base_url
+
+    @property
+    def links(self):
+        """Yields all links in the page"""
+        for match in self._href_re.finditer(self.content):
+            url = match.group(1) or match.group(2) or match.group(3)
+            url = self.clean_link(urlparse.urljoin(self.base_url, url))
+            yield Link(url, self)
+
+    def rel_links(self):
+        for url in self.explicit_rel_links():
+            yield url
+        for url in self.scraped_rel_links():
+            yield url
+
+    def explicit_rel_links(self, rels=('homepage', 'download')):
+        """Yields all links with the given relations"""
+        for match in self._rel_re.finditer(self.content):
+            found_rels = match.group(1).lower().split()
+            for rel in rels:
+                if rel in found_rels:
+                    break
+            else:
+                continue
+            match = self._href_re.search(match.group(0))
+            if not match:
+                continue
+            url = match.group(1) or match.group(2) or match.group(3)
+            url = self.clean_link(urlparse.urljoin(self.base_url, url))
+            yield Link(url, self)
+
+    def scraped_rel_links(self):
+        for regex in (self._homepage_re, self._download_re):
+            match = regex.search(self.content)
+            if not match:
+                continue
+            href_match = self._href_re.search(self.content, pos=match.end())
+            if not href_match:
+                continue
+            url = match.group(1) or match.group(2) or match.group(3)
+            if not url:
+                continue
+            url = self.clean_link(urlparse.urljoin(self.base_url, url))
+            yield Link(url, self)
+
+    _clean_re = re.compile(r'[^a-z0-9$&+,/:;=?@.#%_\\|-]', re.I)
+
+    def clean_link(self, url):
+        """Makes sure a link is fully encoded.  That is, if a ' ' shows up in
+        the link, it will be rewritten to %20 (while not over-quoting
+        % or other characters)."""
+        return self._clean_re.sub(
+            lambda match: '%%%2x' % ord(match.group(0)), url)
+
+class Link(object):
+
+    def __init__(self, url, comes_from=None):
+        self.url = url
+        self.comes_from = comes_from
+
+    def __str__(self):
+        if self.comes_from:
+            return '%s (from %s)' % (self.url, self.comes_from)
+        else:
+            return self.url
+
+    def __repr__(self):
+        return '<Link %s>' % self
+
+    def __eq__(self, other):
+        return self.url == other.url
+
+    def __hash__(self):
+        return hash(self.url)
+
+    @property
+    def filename(self):
+        url = self.url
+        url = url.split('#', 1)[0]
+        url = url.split('?', 1)[0]
+        url = url.rstrip('/')
+        name = posixpath.basename(url)
+        assert name, (
+            'URL %r produced no filename' % url)
+        return name
+
+    @property
+    def scheme(self):
+        return urlparse.urlsplit(self.url)[0]
+
+    @property
+    def path(self):
+        return urlparse.urlsplit(self.url)[2]
+
+    def splitext(self):
+        return splitext(posixpath.basename(self.path.rstrip('/')))
+
+    _egg_fragment_re = re.compile(r'#egg=([^&]*)')
+
+    @property
+    def egg_fragment(self):
+        match = self._egg_fragment_re.search(self.url)
+        if not match:
+            return None
+        return match.group(1)
+
+    _md5_re = re.compile(r'md5=([a-f0-9]+)')
+
+    @property
+    def md5_hash(self):
+        match = self._md5_re.search(self.url)
+        if match:
+            return match.group(1)
+        return None
+
+    @property
+    def show_url(self):
+        return posixpath.basename(self.url.split('#', 1)[0].split('?', 1)[0])
+
+def get_requirement_from_url(url):
+    """Get a requirement from the URL, if possible.  This looks for #egg
+    in the URL"""
+    link = Link(url)
+    egg_info = link.egg_fragment
+    if not egg_info:
+        egg_info = splitext(link.filename)[0]
+    return package_to_requirement(egg_info)
+
+def package_to_requirement(package_name):
+    """Translate a name like Foo-1.2 to Foo==1.3"""
+    match = re.search(r'^(.*?)(-dev|-\d.*)', package_name)
+    if match:
+        name = match.group(1)
+        version = match.group(2)
+    else:
+        name = package_name
+        version = ''
+    if version:
+        return '%s==%s' % (name, version)
+    else:
+        return name

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/locations.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/locations.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/locations.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,36 @@
+"""Locations where we look for configs, install stuff, etc"""
+
+import sys
+import os
+from distutils import sysconfig
+
+if getattr(sys, 'real_prefix', None):
+    ## FIXME: is build/ a good name?
+    build_prefix = os.path.join(sys.prefix, 'build')
+    src_prefix = os.path.join(sys.prefix, 'src')
+else:
+    ## FIXME: this isn't a very good default
+    build_prefix = os.path.join(os.getcwd(), 'build')
+    src_prefix = os.path.join(os.getcwd(), 'src')
+
+# FIXME doesn't account for venv linked to global site-packages
+
+site_packages = sysconfig.get_python_lib()
+user_dir = os.path.expanduser('~')
+if sys.platform == 'win32':
+    bin_py = os.path.join(sys.prefix, 'Scripts')
+    # buildout uses 'bin' on Windows too?
+    if not os.path.exists(bin_py):
+        bin_py = os.path.join(sys.prefix, 'bin')
+    user_dir = os.environ.get('APPDATA', user_dir) # Use %APPDATA% for roaming
+    default_storage_dir = os.path.join(user_dir, 'pip')
+    default_config_file = os.path.join(default_storage_dir, 'pip.ini')
+    default_log_file = os.path.join(default_storage_dir, 'pip.log')
+else:
+    bin_py = os.path.join(sys.prefix, 'bin')
+    default_storage_dir = os.path.join(user_dir, '.pip')
+    default_config_file = os.path.join(default_storage_dir, 'pip.conf')
+    default_log_file = os.path.join(default_storage_dir, 'pip.log')
+    # Forcing to use /usr/local/bin for standard Mac OS X framework installs
+    if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/':
+        bin_py = '/usr/local/bin'

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/log.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/log.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/log.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,174 @@
+"""Logging
+"""
+
+import sys
+import logging
+
+class Logger(object):
+
+    """
+    Logging object for use in command-line script.  Allows ranges of
+    levels, to avoid some redundancy of displayed information.
+    """
+
+    VERBOSE_DEBUG = logging.DEBUG-1
+    DEBUG = logging.DEBUG
+    INFO = logging.INFO
+    NOTIFY = (logging.INFO+logging.WARN)/2
+    WARN = WARNING = logging.WARN
+    ERROR = logging.ERROR
+    FATAL = logging.FATAL
+
+    LEVELS = [VERBOSE_DEBUG, DEBUG, INFO, NOTIFY, WARN, ERROR, FATAL]
+
+    def __init__(self):
+        self.consumers = []
+        self.indent = 0
+        self.explicit_levels = False
+        self.in_progress = None
+        self.in_progress_hanging = False
+
+    def debug(self, msg, *args, **kw):
+        self.log(self.DEBUG, msg, *args, **kw)
+    def info(self, msg, *args, **kw):
+        self.log(self.INFO, msg, *args, **kw)
+    def notify(self, msg, *args, **kw):
+        self.log(self.NOTIFY, msg, *args, **kw)
+    def warn(self, msg, *args, **kw):
+        self.log(self.WARN, msg, *args, **kw)
+    def error(self, msg, *args, **kw):
+        self.log(self.WARN, msg, *args, **kw)
+    def fatal(self, msg, *args, **kw):
+        self.log(self.FATAL, msg, *args, **kw)
+    def log(self, level, msg, *args, **kw):
+        if args:
+            if kw:
+                raise TypeError(
+                    "You may give positional or keyword arguments, not both")
+        args = args or kw
+        rendered = None
+        for consumer_level, consumer in self.consumers:
+            if self.level_matches(level, consumer_level):
+                if (self.in_progress_hanging
+                    and consumer in (sys.stdout, sys.stderr)):
+                    self.in_progress_hanging = False
+                    sys.stdout.write('\n')
+                    sys.stdout.flush()
+                if rendered is None:
+                    if args:
+                        rendered = msg % args
+                    else:
+                        rendered = msg
+                    rendered = ' '*self.indent + rendered
+                    if self.explicit_levels:
+                        ## FIXME: should this be a name, not a level number?
+                        rendered = '%02i %s' % (level, rendered)
+                if hasattr(consumer, 'write'):
+                    consumer.write(rendered+'\n')
+                else:
+                    consumer(rendered)
+
+    def start_progress(self, msg):
+        assert not self.in_progress, (
+            "Tried to start_progress(%r) while in_progress %r"
+            % (msg, self.in_progress))
+        if self.level_matches(self.NOTIFY, self._stdout_level()):
+            sys.stdout.write(' '*self.indent + msg)
+            sys.stdout.flush()
+            self.in_progress_hanging = True
+        else:
+            self.in_progress_hanging = False
+        self.in_progress = msg
+        self.last_message = None
+
+    def end_progress(self, msg='done.'):
+        assert self.in_progress, (
+            "Tried to end_progress without start_progress")
+        if self.stdout_level_matches(self.NOTIFY):
+            if not self.in_progress_hanging:
+                # Some message has been printed out since start_progress
+                sys.stdout.write('...' + self.in_progress + msg + '\n')
+                sys.stdout.flush()
+            else:
+                # These erase any messages shown with show_progress (besides .'s)
+                logger.show_progress('')
+                logger.show_progress('')
+                sys.stdout.write(msg + '\n')
+                sys.stdout.flush()
+        self.in_progress = None
+        self.in_progress_hanging = False
+
+    def show_progress(self, message=None):
+        """If we are in a progress scope, and no log messages have been
+        shown, write out another '.'"""
+        if self.in_progress_hanging:
+            if message is None:
+                sys.stdout.write('.')
+                sys.stdout.flush()
+            else:
+                if self.last_message:
+                    padding = ' ' * max(0, len(self.last_message)-len(message))
+                else:
+                    padding = ''
+                sys.stdout.write('\r%s%s%s%s' % (' '*self.indent, self.in_progress, message, padding))
+                sys.stdout.flush()
+                self.last_message = message
+
+    def stdout_level_matches(self, level):
+        """Returns true if a message at this level will go to stdout"""
+        return self.level_matches(level, self._stdout_level())
+
+    def _stdout_level(self):
+        """Returns the level that stdout runs at"""
+        for level, consumer in self.consumers:
+            if consumer is sys.stdout:
+                return level
+        return self.FATAL
+
+    def level_matches(self, level, consumer_level):
+        """
+        >>> l = Logger()
+        >>> l.level_matches(3, 4)
+        False
+        >>> l.level_matches(3, 2)
+        True
+        >>> l.level_matches(slice(None, 3), 3)
+        False
+        >>> l.level_matches(slice(None, 3), 2)
+        True
+        >>> l.level_matches(slice(1, 3), 1)
+        True
+        >>> l.level_matches(slice(2, 3), 1)
+        False
+        """
+        if isinstance(level, slice):
+            start, stop = level.start, level.stop
+            if start is not None and start > consumer_level:
+                return False
+            if stop is not None or stop <= consumer_level:
+                return False
+            return True
+        else:
+            return level >= consumer_level
+
+    @classmethod
+    def level_for_integer(cls, level):
+        levels = cls.LEVELS
+        if level < 0:
+            return levels[0]
+        if level >= len(levels):
+            return levels[-1]
+        return levels[level]
+
+    def move_stdout_to_stderr(self):
+        to_remove = []
+        to_add = []
+        for consumer_level, consumer in self.consumers:
+            if consumer == sys.stdout:
+                to_remove.append((consumer_level, consumer))
+                to_add.append((consumer_level, sys.stderr))
+        for item in to_remove:
+            self.consumers.remove(item)
+        self.consumers.extend(to_add)
+
+logger = Logger()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/req.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/req.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/req.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,1604 @@
+import sys
+import os
+import shutil
+import re
+import zipfile
+import tarfile
+import pkg_resources
+import tempfile
+import mimetypes
+import urlparse
+import urllib2
+import urllib
+import ConfigParser
+from distutils.sysconfig import get_python_version
+from email.FeedParser import FeedParser
+from pip.locations import bin_py
+from pip.exceptions import InstallationError, UninstallationError
+from pip.vcs import vcs
+from pip.log import logger
+from pip.util import display_path, rmtree, format_size
+from pip.util import splitext, ask, backup_dir
+from pip.util import url_to_path, path_to_url
+from pip.util import is_url, is_installable_dir, is_archive_file, is_local, dist_is_local
+from pip.util import renames, normalize_path, egg_link_path
+from pip.util import make_path_relative, is_svn_page, file_contents
+from pip.util import has_leading_dir, split_leading_dir
+from pip.util import get_file_content
+from pip.util import in_venv
+from pip import call_subprocess
+from pip.backwardcompat import any, md5
+from pip.index import Link
+
+class InstallRequirement(object):
+
+    def __init__(self, req, comes_from, source_dir=None, editable=False,
+                 url=None, update=True):
+        if isinstance(req, basestring):
+            req = pkg_resources.Requirement.parse(req)
+        self.req = req
+        self.comes_from = comes_from
+        self.source_dir = source_dir
+        self.editable = editable
+        self.url = url
+        self._egg_info_path = None
+        # This holds the pkg_resources.Distribution object if this requirement
+        # is already available:
+        self.satisfied_by = None
+        # This hold the pkg_resources.Distribution object if this requirement
+        # conflicts with another installed distribution:
+        self.conflicts_with = None
+        self._temp_build_dir = None
+        self._is_bundle = None
+        # True if the editable should be updated:
+        self.update = update
+        # Set to True after successful installation
+        self.install_succeeded = None
+        # UninstallPathSet of uninstalled distribution (for possible rollback)
+        self.uninstalled = None
+
+    @classmethod
+    def from_editable(cls, editable_req, comes_from=None, default_vcs=None):
+        name, url = parse_editable(editable_req, default_vcs)
+        if url.startswith('file:'):
+            source_dir = url_to_path(url)
+        else:
+            source_dir = None
+        return cls(name, comes_from, source_dir=source_dir, editable=True, url=url)
+
+    @classmethod
+    def from_line(cls, name, comes_from=None):
+        """Creates an InstallRequirement from a name, which might be a
+        requirement, directory containing 'setup.py', filename, or URL.
+        """
+        url = None
+        name = name.strip()
+        req = name
+        path = os.path.normpath(os.path.abspath(name))
+
+        if is_url(name):
+            url = name
+            ## FIXME: I think getting the requirement here is a bad idea:
+            #req = get_requirement_from_url(url)
+            req = None
+        elif os.path.isdir(path):
+            if not is_installable_dir(path):
+                raise InstallationError("Directory %r is not installable. File 'setup.py' not found."
+                                        % name)
+            url = path_to_url(name)
+            #req = get_requirement_from_url(url)
+            req = None
+        elif is_archive_file(path):
+            if not os.path.isfile(path):
+                logger.warn('Requirement %r looks like a filename, but the file does not exist'
+                            % name)
+            url = path_to_url(name)
+            #req = get_requirement_from_url(url)
+            req = None
+        return cls(req, comes_from, url=url)
+
+    def __str__(self):
+        if self.req:
+            s = str(self.req)
+            if self.url:
+                s += ' from %s' % self.url
+        else:
+            s = self.url
+        if self.satisfied_by is not None:
+            s += ' in %s' % display_path(self.satisfied_by.location)
+        if self.comes_from:
+            if isinstance(self.comes_from, basestring):
+                comes_from = self.comes_from
+            else:
+                comes_from = self.comes_from.from_path()
+            if comes_from:
+                s += ' (from %s)' % comes_from
+        return s
+
+    def from_path(self):
+        if self.req is None:
+            return None
+        s = str(self.req)
+        if self.comes_from:
+            if isinstance(self.comes_from, basestring):
+                comes_from = self.comes_from
+            else:
+                comes_from = self.comes_from.from_path()
+            if comes_from:
+                s += '->' + comes_from
+        return s
+
+    def build_location(self, build_dir, unpack=True):
+        if self._temp_build_dir is not None:
+            return self._temp_build_dir
+        if self.req is None:
+            self._temp_build_dir = tempfile.mkdtemp('-build', 'pip-')
+            self._ideal_build_dir = build_dir
+            return self._temp_build_dir
+        if self.editable:
+            name = self.name.lower()
+        else:
+            name = self.name
+        # FIXME: Is there a better place to create the build_dir? (hg and bzr need this)
+        if not os.path.exists(build_dir):
+            os.makedirs(build_dir)
+        return os.path.join(build_dir, name)
+
+    def correct_build_location(self):
+        """If the build location was a temporary directory, this will move it
+        to a new more permanent location"""
+        if self.source_dir is not None:
+            return
+        assert self.req is not None
+        assert self._temp_build_dir
+        old_location = self._temp_build_dir
+        new_build_dir = self._ideal_build_dir
+        del self._ideal_build_dir
+        if self.editable:
+            name = self.name.lower()
+        else:
+            name = self.name
+        new_location = os.path.join(new_build_dir, name)
+        if not os.path.exists(new_build_dir):
+            logger.debug('Creating directory %s' % new_build_dir)
+            os.makedirs(new_build_dir)
+        if os.path.exists(new_location):
+            raise InstallationError(
+                'A package already exists in %s; please remove it to continue'
+                % display_path(new_location))
+        logger.debug('Moving package %s from %s to new location %s'
+                     % (self, display_path(old_location), display_path(new_location)))
+        shutil.move(old_location, new_location)
+        self._temp_build_dir = new_location
+        self.source_dir = new_location
+        self._egg_info_path = None
+
+    @property
+    def name(self):
+        if self.req is None:
+            return None
+        return self.req.project_name
+
+    @property
+    def url_name(self):
+        if self.req is None:
+            return None
+        return urllib.quote(self.req.unsafe_name)
+
+    @property
+    def setup_py(self):
+        return os.path.join(self.source_dir, 'setup.py')
+
+    def run_egg_info(self, force_root_egg_info=False):
+        assert self.source_dir
+        if self.name:
+            logger.notify('Running setup.py egg_info for package %s' % self.name)
+        else:
+            logger.notify('Running setup.py egg_info for package from %s' % self.url)
+        logger.indent += 2
+        try:
+            script = self._run_setup_py
+            script = script.replace('__SETUP_PY__', repr(self.setup_py))
+            script = script.replace('__PKG_NAME__', repr(self.name))
+            # We can't put the .egg-info files at the root, because then the source code will be mistaken
+            # for an installed egg, causing problems
+            if self.editable or force_root_egg_info:
+                egg_base_option = []
+            else:
+                egg_info_dir = os.path.join(self.source_dir, 'pip-egg-info')
+                if not os.path.exists(egg_info_dir):
+                    os.makedirs(egg_info_dir)
+                egg_base_option = ['--egg-base', 'pip-egg-info']
+            call_subprocess(
+                [sys.executable, '-c', script, 'egg_info'] + egg_base_option,
+                cwd=self.source_dir, filter_stdout=self._filter_install, show_stdout=False,
+                command_level=logger.VERBOSE_DEBUG,
+                command_desc='python setup.py egg_info')
+        finally:
+            logger.indent -= 2
+        if not self.req:
+            self.req = pkg_resources.Requirement.parse(self.pkg_info()['Name'])
+            self.correct_build_location()
+
+    ## FIXME: This is a lame hack, entirely for PasteScript which has
+    ## a self-provided entry point that causes this awkwardness
+    _run_setup_py = """
+__file__ = __SETUP_PY__
+from setuptools.command import egg_info
+def replacement_run(self):
+    self.mkpath(self.egg_info)
+    installer = self.distribution.fetch_build_egg
+    for ep in egg_info.iter_entry_points('egg_info.writers'):
+        # require=False is the change we're making:
+        writer = ep.load(require=False)
+        if writer:
+            writer(self, ep.name, egg_info.os.path.join(self.egg_info,ep.name))
+    self.find_sources()
+egg_info.egg_info.run = replacement_run
+execfile(__file__)
+"""
+
+    def egg_info_data(self, filename):
+        if self.satisfied_by is not None:
+            if not self.satisfied_by.has_metadata(filename):
+                return None
+            return self.satisfied_by.get_metadata(filename)
+        assert self.source_dir
+        filename = self.egg_info_path(filename)
+        if not os.path.exists(filename):
+            return None
+        fp = open(filename, 'r')
+        data = fp.read()
+        fp.close()
+        return data
+
+    def egg_info_path(self, filename):
+        if self._egg_info_path is None:
+            if self.editable:
+                base = self.source_dir
+            else:
+                base = os.path.join(self.source_dir, 'pip-egg-info')
+            filenames = os.listdir(base)
+            if self.editable:
+                filenames = []
+                for root, dirs, files in os.walk(base):
+                    for dir in vcs.dirnames:
+                        if dir in dirs:
+                            dirs.remove(dir)
+                    for dir in dirs:
+                        # Don't search in anything that looks like a virtualenv environment
+                        if (os.path.exists(os.path.join(root, dir, 'bin', 'python'))
+                            or os.path.exists(os.path.join(root, dir, 'Scripts', 'Python.exe'))):
+                            dirs.remove(dir)
+                        # Also don't search through tests
+                        if dir == 'test' or dir == 'tests':
+                            dirs.remove(dir)
+                    filenames.extend([os.path.join(root, dir)
+                                     for dir in dirs])
+                filenames = [f for f in filenames if f.endswith('.egg-info')]
+            assert filenames, "No files/directories in %s (from %s)" % (base, filename)
+            assert len(filenames) == 1, "Unexpected files/directories in %s: %s" % (base, ' '.join(filenames))
+            self._egg_info_path = os.path.join(base, filenames[0])
+        return os.path.join(self._egg_info_path, filename)
+
+    def egg_info_lines(self, filename):
+        data = self.egg_info_data(filename)
+        if not data:
+            return []
+        result = []
+        for line in data.splitlines():
+            line = line.strip()
+            if not line or line.startswith('#'):
+                continue
+            result.append(line)
+        return result
+
+    def pkg_info(self):
+        p = FeedParser()
+        data = self.egg_info_data('PKG-INFO')
+        if not data:
+            logger.warn('No PKG-INFO file found in %s' % display_path(self.egg_info_path('PKG-INFO')))
+        p.feed(data or '')
+        return p.close()
+
+    @property
+    def dependency_links(self):
+        return self.egg_info_lines('dependency_links.txt')
+
+    _requirements_section_re = re.compile(r'\[(.*?)\]')
+
+    def requirements(self, extras=()):
+        in_extra = None
+        for line in self.egg_info_lines('requires.txt'):
+            match = self._requirements_section_re.match(line)
+            if match:
+                in_extra = match.group(1)
+                continue
+            if in_extra and in_extra not in extras:
+                # Skip requirement for an extra we aren't requiring
+                continue
+            yield line
+
+    @property
+    def absolute_versions(self):
+        for qualifier, version in self.req.specs:
+            if qualifier == '==':
+                yield version
+
+    @property
+    def installed_version(self):
+        return self.pkg_info()['version']
+
+    def assert_source_matches_version(self):
+        assert self.source_dir
+        if self.comes_from is None:
+            # We don't check the versions of things explicitly installed.
+            # This makes, e.g., "pip Package==dev" possible
+            return
+        version = self.installed_version
+        if version not in self.req:
+            logger.fatal(
+                'Source in %s has the version %s, which does not match the requirement %s'
+                % (display_path(self.source_dir), version, self))
+            raise InstallationError(
+                'Source in %s has version %s that conflicts with %s'
+                % (display_path(self.source_dir), version, self))
+        else:
+            logger.debug('Source in %s has version %s, which satisfies requirement %s'
+                         % (display_path(self.source_dir), version, self))
+
+    def update_editable(self, obtain=True):
+        if not self.url:
+            logger.info("Cannot update repository at %s; repository location is unknown" % self.source_dir)
+            return
+        assert self.editable
+        assert self.source_dir
+        if self.url.startswith('file:'):
+            # Static paths don't get updated
+            return
+        assert '+' in self.url, "bad url: %r" % self.url
+        if not self.update:
+            return
+        vc_type, url = self.url.split('+', 1)
+        backend = vcs.get_backend(vc_type)
+        if backend:
+            vcs_backend = backend(self.url)
+            if obtain:
+                vcs_backend.obtain(self.source_dir)
+            else:
+                vcs_backend.export(self.source_dir)
+        else:
+            assert 0, (
+                'Unexpected version control type (in %s): %s'
+                % (self.url, vc_type))
+
+    def uninstall(self, auto_confirm=False):
+        """
+        Uninstall the distribution currently satisfying this requirement.
+
+        Prompts before removing or modifying files unless
+        ``auto_confirm`` is True.
+
+        Refuses to delete or modify files outside of ``sys.prefix`` -
+        thus uninstallation within a virtual environment can only
+        modify that virtual environment, even if the virtualenv is
+        linked to global site-packages.
+
+        """
+        if not self.check_if_exists():
+            raise UninstallationError("Cannot uninstall requirement %s, not installed" % (self.name,))
+        dist = self.satisfied_by or self.conflicts_with
+
+        paths_to_remove = UninstallPathSet(dist)
+
+        pip_egg_info_path = os.path.join(dist.location,
+                                         dist.egg_name()) + '.egg-info'
+        easy_install_egg = dist.egg_name() + '.egg'
+        develop_egg_link = egg_link_path(dist)
+        if os.path.exists(pip_egg_info_path):
+            # package installed by pip
+            paths_to_remove.add(pip_egg_info_path)
+            if dist.has_metadata('installed-files.txt'):
+                for installed_file in dist.get_metadata('installed-files.txt').splitlines():
+                    path = os.path.normpath(os.path.join(pip_egg_info_path, installed_file))
+                    paths_to_remove.add(path)
+            if dist.has_metadata('top_level.txt'):
+                if dist.has_metadata('namespace_packages.txt'):
+                    namespaces = dist.get_metadata('namespace_packages.txt')
+                else:
+                    namespaces = []
+                for top_level_pkg in [p for p
+                                      in dist.get_metadata('top_level.txt').splitlines()
+                                      if p and p not in namespaces]:
+                    path = os.path.join(dist.location, top_level_pkg)
+                    paths_to_remove.add(path)
+                    paths_to_remove.add(path + '.py')
+                    paths_to_remove.add(path + '.pyc')
+
+        elif dist.location.endswith(easy_install_egg):
+            # package installed by easy_install
+            paths_to_remove.add(dist.location)
+            easy_install_pth = os.path.join(os.path.dirname(dist.location),
+                                            'easy-install.pth')
+            paths_to_remove.add_pth(easy_install_pth, './' + easy_install_egg)
+
+        elif os.path.isfile(develop_egg_link):
+            # develop egg
+            fh = open(develop_egg_link, 'r')
+            link_pointer = os.path.normcase(fh.readline().strip())
+            fh.close()
+            assert (link_pointer == dist.location), 'Egg-link %s does not match installed location of %s (at %s)' % (link_pointer, self.name, dist.location)
+            paths_to_remove.add(develop_egg_link)
+            easy_install_pth = os.path.join(os.path.dirname(develop_egg_link),
+                                            'easy-install.pth')
+            paths_to_remove.add_pth(easy_install_pth, dist.location)
+
+        # find distutils scripts= scripts
+        if dist.has_metadata('scripts') and dist.metadata_isdir('scripts'):
+            for script in dist.metadata_listdir('scripts'):
+                paths_to_remove.add(os.path.join(bin_py, script))
+                if sys.platform == 'win32':
+                    paths_to_remove.add(os.path.join(bin_py, script) + '.bat')
+
+        # find console_scripts
+        if dist.has_metadata('entry_points.txt'):
+            config = ConfigParser.SafeConfigParser()
+            config.readfp(FakeFile(dist.get_metadata_lines('entry_points.txt')))
+            if config.has_section('console_scripts'):
+                for name, value in config.items('console_scripts'):
+                    paths_to_remove.add(os.path.join(bin_py, name))
+                    if sys.platform == 'win32':
+                        paths_to_remove.add(os.path.join(bin_py, name) + '.exe')
+                        paths_to_remove.add(os.path.join(bin_py, name) + '-script.py')
+
+        paths_to_remove.remove(auto_confirm)
+        self.uninstalled = paths_to_remove
+
+    def rollback_uninstall(self):
+        if self.uninstalled:
+            self.uninstalled.rollback()
+        else:
+            logger.error("Can't rollback %s, nothing uninstalled."
+                         % (self.project_name,))
+
+    def commit_uninstall(self):
+        if self.uninstalled:
+            self.uninstalled.commit()
+        else:
+            logger.error("Can't commit %s, nothing uninstalled."
+                         % (self.project_name,))
+
+    def archive(self, build_dir):
+        assert self.source_dir
+        create_archive = True
+        archive_name = '%s-%s.zip' % (self.name, self.installed_version)
+        archive_path = os.path.join(build_dir, archive_name)
+        if os.path.exists(archive_path):
+            response = ask('The file %s exists. (i)gnore, (w)ipe, (b)ackup '
+                           % display_path(archive_path), ('i', 'w', 'b'))
+            if response == 'i':
+                create_archive = False
+            elif response == 'w':
+                logger.warn('Deleting %s' % display_path(archive_path))
+                os.remove(archive_path)
+            elif response == 'b':
+                dest_file = backup_dir(archive_path)
+                logger.warn('Backing up %s to %s'
+                            % (display_path(archive_path), display_path(dest_file)))
+                shutil.move(archive_path, dest_file)
+        if create_archive:
+            zip = zipfile.ZipFile(archive_path, 'w', zipfile.ZIP_DEFLATED)
+            dir = os.path.normcase(os.path.abspath(self.source_dir))
+            for dirpath, dirnames, filenames in os.walk(dir):
+                if 'pip-egg-info' in dirnames:
+                    dirnames.remove('pip-egg-info')
+                for dirname in dirnames:
+                    dirname = os.path.join(dirpath, dirname)
+                    name = self._clean_zip_name(dirname, dir)
+                    zipdir = zipfile.ZipInfo(self.name + '/' + name + '/')
+                    zipdir.external_attr = 0755 << 16L
+                    zip.writestr(zipdir, '')
+                for filename in filenames:
+                    if filename == 'pip-delete-this-directory.txt':
+                        continue
+                    filename = os.path.join(dirpath, filename)
+                    name = self._clean_zip_name(filename, dir)
+                    zip.write(filename, self.name + '/' + name)
+            zip.close()
+            logger.indent -= 2
+            logger.notify('Saved %s' % display_path(archive_path))
+
+    def _clean_zip_name(self, name, prefix):
+        assert name.startswith(prefix+'/'), (
+            "name %r doesn't start with prefix %r" % (name, prefix))
+        name = name[len(prefix)+1:]
+        name = name.replace(os.path.sep, '/')
+        return name
+
+    def install(self, install_options):
+        if self.editable:
+            self.install_editable()
+            return
+        temp_location = tempfile.mkdtemp('-record', 'pip-')
+        record_filename = os.path.join(temp_location, 'install-record.txt')
+        try:
+
+            install_args = [sys.executable, '-c',
+                            "import setuptools; __file__=%r; execfile(%r)" % (self.setup_py, self.setup_py),
+                            'install', '--single-version-externally-managed', '--record', record_filename]
+
+            if in_venv():
+                ## FIXME: I'm not sure if this is a reasonable location; probably not
+                ## but we can't put it in the default location, as that is a virtualenv symlink that isn't writable
+                install_args += ['--install-headers',
+                                 os.path.join(sys.prefix, 'include', 'site',
+                                              'python' + get_python_version())]
+            logger.notify('Running setup.py install for %s' % self.name)
+            logger.indent += 2
+            try:
+                call_subprocess(install_args + install_options,
+                    cwd=self.source_dir, filter_stdout=self._filter_install, show_stdout=False)
+            finally:
+                logger.indent -= 2
+            self.install_succeeded = True
+            f = open(record_filename)
+            for line in f:
+                line = line.strip()
+                if line.endswith('.egg-info'):
+                    egg_info_dir = line
+                    break
+            else:
+                logger.warn('Could not find .egg-info directory in install record for %s' % self)
+                ## FIXME: put the record somewhere
+                ## FIXME: should this be an error?
+                return
+            f.close()
+            new_lines = []
+            f = open(record_filename)
+            for line in f:
+                filename = line.strip()
+                if os.path.isdir(filename):
+                    filename += os.path.sep
+                new_lines.append(make_path_relative(filename, egg_info_dir))
+            f.close()
+            f = open(os.path.join(egg_info_dir, 'installed-files.txt'), 'w')
+            f.write('\n'.join(new_lines)+'\n')
+            f.close()
+        finally:
+            if os.path.exists(record_filename):
+                os.remove(record_filename)
+            os.rmdir(temp_location)
+
+    def remove_temporary_source(self):
+        """Remove the source files from this requirement, if they are marked
+        for deletion"""
+        if self.is_bundle or os.path.exists(self.delete_marker_filename):
+            logger.info('Removing source in %s' % self.source_dir)
+            if self.source_dir:
+                rmtree(self.source_dir)
+            self.source_dir = None
+            if self._temp_build_dir and os.path.exists(self._temp_build_dir):
+                rmtree(self._temp_build_dir)
+            self._temp_build_dir = None
+
+    def install_editable(self):
+        logger.notify('Running setup.py develop for %s' % self.name)
+        logger.indent += 2
+        try:
+            ## FIXME: should we do --install-headers here too?
+            call_subprocess(
+                [sys.executable, '-c',
+                 "import setuptools; __file__=%r; execfile(%r)" % (self.setup_py, self.setup_py),
+                 'develop', '--no-deps'], cwd=self.source_dir, filter_stdout=self._filter_install,
+                show_stdout=False)
+        finally:
+            logger.indent -= 2
+        self.install_succeeded = True
+
+    def _filter_install(self, line):
+        level = logger.NOTIFY
+        for regex in [r'^running .*', r'^writing .*', '^creating .*', '^[Cc]opying .*',
+                      r'^reading .*', r"^removing .*\.egg-info' \(and everything under it\)$",
+                      r'^byte-compiling ',
+                      # Not sure what this warning is, but it seems harmless:
+                      r"^warning: manifest_maker: standard file '-c' not found$"]:
+            if re.search(regex, line.strip()):
+                level = logger.INFO
+                break
+        return (level, line)
+
+    def check_if_exists(self):
+        """Find an installed distribution that satisfies or conflicts
+        with this requirement, and set self.satisfied_by or
+        self.conflicts_with appropriately."""
+        if self.req is None:
+            return False
+        try:
+            self.satisfied_by = pkg_resources.get_distribution(self.req)
+        except pkg_resources.DistributionNotFound:
+            return False
+        except pkg_resources.VersionConflict:
+            self.conflicts_with = pkg_resources.get_distribution(self.req.project_name)
+        return True
+
+    @property
+    def is_bundle(self):
+        if self._is_bundle is not None:
+            return self._is_bundle
+        base = self._temp_build_dir
+        if not base:
+            ## FIXME: this doesn't seem right:
+            return False
+        self._is_bundle = (os.path.exists(os.path.join(base, 'pip-manifest.txt'))
+                           or os.path.exists(os.path.join(base, 'pyinstall-manifest.txt')))
+        return self._is_bundle
+
+    def bundle_requirements(self):
+        for dest_dir in self._bundle_editable_dirs:
+            package = os.path.basename(dest_dir)
+            ## FIXME: svnism:
+            for vcs_backend in vcs.backends:
+                url = rev = None
+                vcs_bundle_file = os.path.join(
+                    dest_dir, vcs_backend.bundle_file)
+                if os.path.exists(vcs_bundle_file):
+                    vc_type = vcs_backend.name
+                    fp = open(vcs_bundle_file)
+                    content = fp.read()
+                    fp.close()
+                    url, rev = vcs_backend().parse_vcs_bundle_file(content)
+                    break
+            if url:
+                url = '%s+%s@%s' % (vc_type, url, rev)
+            else:
+                url = None
+            yield InstallRequirement(
+                package, self, editable=True, url=url,
+                update=False, source_dir=dest_dir)
+        for dest_dir in self._bundle_build_dirs:
+            package = os.path.basename(dest_dir)
+            yield InstallRequirement(
+                package, self,
+                source_dir=dest_dir)
+
+    def move_bundle_files(self, dest_build_dir, dest_src_dir):
+        base = self._temp_build_dir
+        assert base
+        src_dir = os.path.join(base, 'src')
+        build_dir = os.path.join(base, 'build')
+        bundle_build_dirs = []
+        bundle_editable_dirs = []
+        for source_dir, dest_dir, dir_collection in [
+            (src_dir, dest_src_dir, bundle_editable_dirs),
+            (build_dir, dest_build_dir, bundle_build_dirs)]:
+            if os.path.exists(source_dir):
+                for dirname in os.listdir(source_dir):
+                    dest = os.path.join(dest_dir, dirname)
+                    dir_collection.append(dest)
+                    if os.path.exists(dest):
+                        logger.warn('The directory %s (containing package %s) already exists; cannot move source from bundle %s'
+                                    % (dest, dirname, self))
+                        continue
+                    if not os.path.exists(dest_dir):
+                        logger.info('Creating directory %s' % dest_dir)
+                        os.makedirs(dest_dir)
+                    shutil.move(os.path.join(source_dir, dirname), dest)
+                if not os.listdir(source_dir):
+                    os.rmdir(source_dir)
+        self._temp_build_dir = None
+        self._bundle_build_dirs = bundle_build_dirs
+        self._bundle_editable_dirs = bundle_editable_dirs
+
+    @property
+    def delete_marker_filename(self):
+        assert self.source_dir
+        return os.path.join(self.source_dir, 'pip-delete-this-directory.txt')
+
+DELETE_MARKER_MESSAGE = '''\
+This file is placed here by pip to indicate the source was put
+here by pip.
+
+Once this package is successfully installed this source code will be
+deleted (unless you remove this file).
+'''
+
+class RequirementSet(object):
+
+    def __init__(self, build_dir, src_dir, download_dir, download_cache=None,
+                 upgrade=False, ignore_installed=False,
+                 ignore_dependencies=False):
+        self.build_dir = build_dir
+        self.src_dir = src_dir
+        self.download_dir = download_dir
+        self.download_cache = download_cache
+        self.upgrade = upgrade
+        self.ignore_installed = ignore_installed
+        self.requirements = {}
+        # Mapping of alias: real_name
+        self.requirement_aliases = {}
+        self.unnamed_requirements = []
+        self.ignore_dependencies = ignore_dependencies
+        self.successfully_downloaded = []
+        self.successfully_installed = []
+        self.reqs_to_cleanup = []
+
+    def __str__(self):
+        reqs = [req for req in self.requirements.values()
+                if not req.comes_from]
+        reqs.sort(key=lambda req: req.name.lower())
+        return ' '.join([str(req.req) for req in reqs])
+
+    def add_requirement(self, install_req):
+        name = install_req.name
+        if not name:
+            self.unnamed_requirements.append(install_req)
+        else:
+            if self.has_requirement(name):
+                raise InstallationError(
+                    'Double requirement given: %s (aready in %s, name=%r)'
+                    % (install_req, self.get_requirement(name), name))
+            self.requirements[name] = install_req
+            ## FIXME: what about other normalizations?  E.g., _ vs. -?
+            if name.lower() != name:
+                self.requirement_aliases[name.lower()] = name
+
+    def has_requirement(self, project_name):
+        for name in project_name, project_name.lower():
+            if name in self.requirements or name in self.requirement_aliases:
+                return True
+        return False
+
+    @property
+    def is_download(self):
+        if self.download_dir:
+            self.download_dir = os.path.expanduser(self.download_dir)
+            if os.path.exists(self.download_dir):
+                return True
+            else:
+                logger.fatal('Could not find download directory')
+                raise InstallationError(
+                    "Could not find or access download directory '%s'"
+                    % display_path(self.download_dir))
+        return False
+
+    def get_requirement(self, project_name):
+        for name in project_name, project_name.lower():
+            if name in self.requirements:
+                return self.requirements[name]
+            if name in self.requirement_aliases:
+                return self.requirements[self.requirement_aliases[name]]
+        raise KeyError("No project with the name %r" % project_name)
+
+    def uninstall(self, auto_confirm=False):
+        for req in self.requirements.values():
+            req.uninstall(auto_confirm=auto_confirm)
+            req.commit_uninstall()
+
+    def locate_files(self):
+        ## FIXME: duplicates code from install_files; relevant code should
+        ##        probably be factored out into a separate method
+        unnamed = list(self.unnamed_requirements)
+        reqs = self.requirements.values()
+        while reqs or unnamed:
+            if unnamed:
+                req_to_install = unnamed.pop(0)
+            else:
+                req_to_install = reqs.pop(0)
+            install_needed = True
+            if not self.ignore_installed and not req_to_install.editable:
+                req_to_install.check_if_exists()
+                if req_to_install.satisfied_by:
+                    if self.upgrade:
+                        req_to_install.conflicts_with = req_to_install.satisfied_by
+                        req_to_install.satisfied_by = None
+                    else:
+                        install_needed = False
+                if req_to_install.satisfied_by:
+                    logger.notify('Requirement already satisfied '
+                                  '(use --upgrade to upgrade): %s'
+                                  % req_to_install)
+
+            if req_to_install.editable:
+                if req_to_install.source_dir is None:
+                    req_to_install.source_dir = req_to_install.build_location(self.src_dir)
+            elif install_needed:
+                req_to_install.source_dir = req_to_install.build_location(self.build_dir, not self.is_download)
+
+            if req_to_install.source_dir is not None and not os.path.isdir(req_to_install.source_dir):
+                raise InstallationError('Could not install requirement %s '
+                                       'because source folder %s does not exist '
+                                       '(perhaps --no-download was used without first running '
+                                       'an equivalent install with --no-install?)'
+                                       % (req_to_install, req_to_install.source_dir))
+
+    def prepare_files(self, finder, force_root_egg_info=False, bundle=False):
+        """Prepare process. Create temp directories, download and/or unpack files."""
+        unnamed = list(self.unnamed_requirements)
+        reqs = self.requirements.values()
+        while reqs or unnamed:
+            if unnamed:
+                req_to_install = unnamed.pop(0)
+            else:
+                req_to_install = reqs.pop(0)
+            install = True
+            if not self.ignore_installed and not req_to_install.editable:
+                req_to_install.check_if_exists()
+                if req_to_install.satisfied_by:
+                    if self.upgrade:
+                        req_to_install.conflicts_with = req_to_install.satisfied_by
+                        req_to_install.satisfied_by = None
+                    else:
+                        install = False
+                if req_to_install.satisfied_by:
+                    logger.notify('Requirement already satisfied '
+                                  '(use --upgrade to upgrade): %s'
+                                  % req_to_install)
+            if req_to_install.editable:
+                logger.notify('Obtaining %s' % req_to_install)
+            elif install:
+                if req_to_install.url and req_to_install.url.lower().startswith('file:'):
+                    logger.notify('Unpacking %s' % display_path(url_to_path(req_to_install.url)))
+                else:
+                    logger.notify('Downloading/unpacking %s' % req_to_install)
+            logger.indent += 2
+            try:
+                is_bundle = False
+                if req_to_install.editable:
+                    if req_to_install.source_dir is None:
+                        location = req_to_install.build_location(self.src_dir)
+                        req_to_install.source_dir = location
+                    else:
+                        location = req_to_install.source_dir
+                    if not os.path.exists(self.build_dir):
+                        os.makedirs(self.build_dir)
+                    req_to_install.update_editable(not self.is_download)
+                    if self.is_download:
+                        req_to_install.run_egg_info()
+                        req_to_install.archive(self.download_dir)
+                    else:
+                        req_to_install.run_egg_info()
+                elif install:
+                    ##@@ if filesystem packages are not marked
+                    ##editable in a req, a non deterministic error
+                    ##occurs when the script attempts to unpack the
+                    ##build directory
+
+                    location = req_to_install.build_location(self.build_dir, not self.is_download)
+                    ## FIXME: is the existance of the checkout good enough to use it?  I don't think so.
+                    unpack = True
+                    if not os.path.exists(os.path.join(location, 'setup.py')):
+                        ## FIXME: this won't upgrade when there's an existing package unpacked in `location`
+                        if req_to_install.url is None:
+                            url = finder.find_requirement(req_to_install, upgrade=self.upgrade)
+                        else:
+                            ## FIXME: should req_to_install.url already be a link?
+                            url = Link(req_to_install.url)
+                            assert url
+                        if url:
+                            try:
+                                self.unpack_url(url, location, self.is_download)
+                            except urllib2.HTTPError, e:
+                                logger.fatal('Could not install requirement %s because of error %s'
+                                             % (req_to_install, e))
+                                raise InstallationError(
+                                    'Could not install requirement %s because of HTTP error %s for URL %s'
+                                    % (req_to_install, e, url))
+                        else:
+                            unpack = False
+                    if unpack:
+                        is_bundle = req_to_install.is_bundle
+                        url = None
+                        if is_bundle:
+                            req_to_install.move_bundle_files(self.build_dir, self.src_dir)
+                            for subreq in req_to_install.bundle_requirements():
+                                reqs.append(subreq)
+                                self.add_requirement(subreq)
+                        elif self.is_download:
+                            req_to_install.source_dir = location
+                            if url and url.scheme in vcs.all_schemes:
+                                req_to_install.run_egg_info()
+                                req_to_install.archive(self.download_dir)
+                        else:
+                            req_to_install.source_dir = location
+                            req_to_install.run_egg_info()
+                            if force_root_egg_info:
+                                # We need to run this to make sure that the .egg-info/
+                                # directory is created for packing in the bundle
+                                req_to_install.run_egg_info(force_root_egg_info=True)
+                            req_to_install.assert_source_matches_version()
+                            f = open(req_to_install.delete_marker_filename, 'w')
+                            f.write(DELETE_MARKER_MESSAGE)
+                            f.close()
+                            #@@ sketchy way of identifying packages not grabbed from an index
+                            if bundle and req_to_install.url:
+                                self.copy_to_builddir(req_to_install)
+                if not is_bundle and not self.is_download:
+                    ## FIXME: shouldn't be globally added:
+                    finder.add_dependency_links(req_to_install.dependency_links)
+                    ## FIXME: add extras in here:
+                    if not self.ignore_dependencies:
+                        for req in req_to_install.requirements():
+                            try:
+                                name = pkg_resources.Requirement.parse(req).project_name
+                            except ValueError, e:
+                                ## FIXME: proper warning
+                                logger.error('Invalid requirement: %r (%s) in requirement %s' % (req, e, req_to_install))
+                                continue
+                            if self.has_requirement(name):
+                                ## FIXME: check for conflict
+                                continue
+                            subreq = InstallRequirement(req, req_to_install)
+                            reqs.append(subreq)
+                            self.add_requirement(subreq)
+                    if req_to_install.name not in self.requirements:
+                        self.requirements[req_to_install.name] = req_to_install
+                else:
+                    self.reqs_to_cleanup.append(req_to_install)
+                if install:
+                    self.successfully_downloaded.append(req_to_install)
+                    if bundle and (req_to_install.url and req_to_install.url.startswith('file:///')):
+                        self.copy_to_builddir(req_to_install)
+            finally:
+                logger.indent -= 2
+
+    def cleanup_files(self, bundle=False):
+        """Clean up files, remove builds."""
+        logger.notify('Cleaning up...')
+        logger.indent += 2
+        for req in self.reqs_to_cleanup:
+            req.remove_temporary_source()
+
+        # The build dir can always be removed.
+        remove_dir = [self.build_dir]
+
+        # The source dir of a bundle can always be removed.
+        if bundle:
+            remove_dir.append(self.src_dir)
+
+        for dir in remove_dir:
+            if os.path.exists(dir):
+                logger.info('Removing temporary dir %s...' % dir)
+                ## FIXME: should this use pip.util.rmtree?
+                shutil.rmtree(dir)
+
+        logger.indent -= 2
+
+    def copy_to_builddir(self, req_to_install):
+        target_dir = req_to_install.editable and self.src_dir or self.build_dir
+        logger.info("Copying %s to %s" %(req_to_install.name, target_dir))
+        dest = os.path.join(target_dir, req_to_install.name)
+        shutil.copytree(req_to_install.source_dir, dest)
+        shutil.copymode(req_to_install.source_dir, dest)
+        call_subprocess(["python", "%s/setup.py"%dest, "clean"])
+
+    def unpack_url(self, link, location, only_download=False):
+        if only_download:
+            location = self.download_dir
+        for backend in vcs.backends:
+            if link.scheme in backend.schemes:
+                vcs_backend = backend(link.url)
+                if only_download:
+                    vcs_backend.export(location)
+                else:
+                    vcs_backend.unpack(location)
+                return
+        if link.url.lower().startswith('file:'):
+            source = url_to_path(link.url)
+            content_type = mimetypes.guess_type(source)[0]
+            if os.path.isdir(source):
+                # delete the location since shutil will create it again :(
+                if os.path.isdir(location):
+                    shutil.rmtree(location)
+                shutil.copytree(source, location)
+            else:
+                self.unpack_file(source, location, content_type, link)
+            return
+        temp_dir = tempfile.mkdtemp('-unpack', 'pip-')
+        md5_hash = link.md5_hash
+        target_url = link.url.split('#', 1)[0]
+        target_file = None
+        if self.download_cache:
+            self.download_cache = os.path.expanduser(self.download_cache)
+            if not os.path.isdir(self.download_cache):
+                logger.indent -= 2
+                logger.notify('Creating supposed download cache at %s' % self.download_cache)
+                logger.indent += 2
+                os.makedirs(self.download_cache)
+            target_file = os.path.join(self.download_cache,
+                                       urllib.quote(target_url, ''))
+        if (target_file and os.path.exists(target_file)
+            and os.path.exists(target_file+'.content-type')):
+            fp = open(target_file+'.content-type')
+            content_type = fp.read().strip()
+            fp.close()
+            if md5_hash:
+                download_hash = md5()
+                fp = open(target_file, 'rb')
+                while 1:
+                    chunk = fp.read(4096)
+                    if not chunk:
+                        break
+                    download_hash.update(chunk)
+                fp.close()
+            temp_location = target_file
+            logger.notify('Using download cache from %s' % target_file)
+        else:
+            try:
+                resp = urllib2.urlopen(target_url)
+            except urllib2.HTTPError, e:
+                logger.fatal("HTTP error %s while getting %s" % (e.code, link))
+                raise
+            except IOError, e:
+                # Typically an FTP error
+                logger.fatal("Error %s while getting %s" % (e, link))
+                raise
+            content_type = resp.info()['content-type']
+            filename = link.filename
+            ext = splitext(filename)[1]
+            if not ext:
+                ext = mimetypes.guess_extension(content_type)
+                if ext:
+                    filename += ext
+            if not ext and link.url != resp.geturl():
+                ext = os.path.splitext(resp.geturl())[1]
+                if ext:
+                    filename += ext
+            temp_location = os.path.join(temp_dir, filename)
+            fp = open(temp_location, 'wb')
+            if md5_hash:
+                download_hash = md5()
+            try:
+                total_length = int(resp.info()['content-length'])
+            except (ValueError, KeyError):
+                total_length = 0
+            downloaded = 0
+            show_progress = total_length > 40*1000 or not total_length
+            show_url = link.show_url
+            try:
+                if show_progress:
+                    ## FIXME: the URL can get really long in this message:
+                    if total_length:
+                        logger.start_progress('Downloading %s (%s): ' % (show_url, format_size(total_length)))
+                    else:
+                        logger.start_progress('Downloading %s (unknown size): ' % show_url)
+                else:
+                    logger.notify('Downloading %s' % show_url)
+                logger.debug('Downloading from URL %s' % link)
+                while 1:
+                    chunk = resp.read(4096)
+                    if not chunk:
+                        break
+                    downloaded += len(chunk)
+                    if show_progress:
+                        if not total_length:
+                            logger.show_progress('%s' % format_size(downloaded))
+                        else:
+                            logger.show_progress('%3i%%  %s' % (100*downloaded/total_length, format_size(downloaded)))
+                    if md5_hash:
+                        download_hash.update(chunk)
+                    fp.write(chunk)
+                fp.close()
+            finally:
+                if show_progress:
+                    logger.end_progress('%s downloaded' % format_size(downloaded))
+        if md5_hash:
+            download_hash = download_hash.hexdigest()
+            if download_hash != md5_hash:
+                logger.fatal("MD5 hash of the package %s (%s) doesn't match the expected hash %s!"
+                             % (link, download_hash, md5_hash))
+                raise InstallationError('Bad MD5 hash for package %s' % link)
+        if only_download:
+            self.copy_file(temp_location, location, content_type, link)
+        else:
+            self.unpack_file(temp_location, location, content_type, link)
+        if target_file and target_file != temp_location:
+            logger.notify('Storing download in cache at %s' % display_path(target_file))
+            shutil.copyfile(temp_location, target_file)
+            fp = open(target_file+'.content-type', 'w')
+            fp.write(content_type)
+            fp.close()
+            os.unlink(temp_location)
+        if target_file is None:
+            os.unlink(temp_location)
+        os.rmdir(temp_dir)
+
+    def copy_file(self, filename, location, content_type, link):
+        copy = True
+        download_location = os.path.join(location, link.filename)
+        if os.path.exists(download_location):
+            response = ask('The file %s exists. (i)gnore, (w)ipe, (b)ackup '
+                           % display_path(download_location), ('i', 'w', 'b'))
+            if response == 'i':
+                copy = False
+            elif response == 'w':
+                logger.warn('Deleting %s' % display_path(download_location))
+                os.remove(download_location)
+            elif response == 'b':
+                dest_file = backup_dir(download_location)
+                logger.warn('Backing up %s to %s'
+                            % (display_path(download_location), display_path(dest_file)))
+                shutil.move(download_location, dest_file)
+        if copy:
+            shutil.copy(filename, download_location)
+            logger.indent -= 2
+            logger.notify('Saved %s' % display_path(download_location))
+
+    def unpack_file(self, filename, location, content_type, link):
+        if (content_type == 'application/zip'
+            or filename.endswith('.zip')
+            or filename.endswith('.pybundle')
+            or zipfile.is_zipfile(filename)):
+            self.unzip_file(filename, location, flatten=not filename.endswith('.pybundle'))
+        elif (content_type == 'application/x-gzip'
+              or tarfile.is_tarfile(filename)
+              or splitext(filename)[1].lower() in ('.tar', '.tar.gz', '.tar.bz2', '.tgz', '.tbz')):
+            self.untar_file(filename, location)
+        elif (content_type and content_type.startswith('text/html')
+              and is_svn_page(file_contents(filename))):
+            # We don't really care about this
+            from pip.vcs.subversion import Subversion
+            Subversion('svn+' + link.url).unpack(location)
+        else:
+            ## FIXME: handle?
+            ## FIXME: magic signatures?
+            logger.fatal('Cannot unpack file %s (downloaded from %s, content-type: %s); cannot detect archive format'
+                         % (filename, location, content_type))
+            raise InstallationError('Cannot determine archive format of %s' % location)
+
+    def unzip_file(self, filename, location, flatten=True):
+        """Unzip the file (zip file located at filename) to the destination
+        location"""
+        if not os.path.exists(location):
+            os.makedirs(location)
+        zipfp = open(filename, 'rb')
+        try:
+            zip = zipfile.ZipFile(zipfp)
+            leading = has_leading_dir(zip.namelist()) and flatten
+            for name in zip.namelist():
+                data = zip.read(name)
+                fn = name
+                if leading:
+                    fn = split_leading_dir(name)[1]
+                fn = os.path.join(location, fn)
+                dir = os.path.dirname(fn)
+                if not os.path.exists(dir):
+                    os.makedirs(dir)
+                if fn.endswith('/') or fn.endswith('\\'):
+                    # A directory
+                    if not os.path.exists(fn):
+                        os.makedirs(fn)
+                else:
+                    fp = open(fn, 'wb')
+                    try:
+                        fp.write(data)
+                    finally:
+                        fp.close()
+        finally:
+            zipfp.close()
+
+    def untar_file(self, filename, location):
+        """Untar the file (tar file located at filename) to the destination location"""
+        if not os.path.exists(location):
+            os.makedirs(location)
+        if filename.lower().endswith('.gz') or filename.lower().endswith('.tgz'):
+            mode = 'r:gz'
+        elif filename.lower().endswith('.bz2') or filename.lower().endswith('.tbz'):
+            mode = 'r:bz2'
+        elif filename.lower().endswith('.tar'):
+            mode = 'r'
+        else:
+            logger.warn('Cannot determine compression type for file %s' % filename)
+            mode = 'r:*'
+        tar = tarfile.open(filename, mode)
+        try:
+            leading = has_leading_dir([member.name for member in tar.getmembers()])
+            for member in tar.getmembers():
+                fn = member.name
+                if leading:
+                    fn = split_leading_dir(fn)[1]
+                path = os.path.join(location, fn)
+                if member.isdir():
+                    if not os.path.exists(path):
+                        os.makedirs(path)
+                else:
+                    try:
+                        fp = tar.extractfile(member)
+                    except (KeyError, AttributeError), e:
+                        # Some corrupt tar files seem to produce this
+                        # (specifically bad symlinks)
+                        logger.warn(
+                            'In the tar file %s the member %s is invalid: %s'
+                            % (filename, member.name, e))
+                        continue
+                    if not os.path.exists(os.path.dirname(path)):
+                        os.makedirs(os.path.dirname(path))
+                    destfp = open(path, 'wb')
+                    try:
+                        shutil.copyfileobj(fp, destfp)
+                    finally:
+                        destfp.close()
+                    fp.close()
+        finally:
+            tar.close()
+
+    def install(self, install_options):
+        """Install everything in this set (after having downloaded and unpacked the packages)"""
+        to_install = sorted([r for r in self.requirements.values()
+                             if self.upgrade or not r.satisfied_by],
+                            key=lambda p: p.name.lower())
+        if to_install:
+            logger.notify('Installing collected packages: %s' % (', '.join([req.name for req in to_install])))
+        logger.indent += 2
+        try:
+            for requirement in to_install:
+                if requirement.conflicts_with:
+                    logger.notify('Found existing installation: %s'
+                                  % requirement.conflicts_with)
+                    logger.indent += 2
+                    try:
+                        requirement.uninstall(auto_confirm=True)
+                    finally:
+                        logger.indent -= 2
+                try:
+                    requirement.install(install_options)
+                except:
+                    # if install did not succeed, rollback previous uninstall
+                    if requirement.conflicts_with and not requirement.install_succeeded:
+                        requirement.rollback_uninstall()
+                    raise
+                else:
+                    if requirement.conflicts_with and requirement.install_succeeded:
+                        requirement.commit_uninstall()
+                requirement.remove_temporary_source()
+        finally:
+            logger.indent -= 2
+        self.successfully_installed = to_install
+
+    def create_bundle(self, bundle_filename):
+        ## FIXME: can't decide which is better; zip is easier to read
+        ## random files from, but tar.bz2 is smaller and not as lame a
+        ## format.
+
+        ## FIXME: this file should really include a manifest of the
+        ## packages, maybe some other metadata files.  It would make
+        ## it easier to detect as well.
+        zip = zipfile.ZipFile(bundle_filename, 'w', zipfile.ZIP_DEFLATED)
+        vcs_dirs = []
+        for dir, basename in (self.build_dir, 'build'), (self.src_dir, 'src'):
+            dir = os.path.normcase(os.path.abspath(dir))
+            for dirpath, dirnames, filenames in os.walk(dir):
+                for backend in vcs.backends:
+                    vcs_backend = backend()
+                    vcs_url = vcs_rev = None
+                    if vcs_backend.dirname in dirnames:
+                        for vcs_dir in vcs_dirs:
+                            if dirpath.startswith(vcs_dir):
+                                # vcs bundle file already in parent directory
+                                break
+                        else:
+                            vcs_url, vcs_rev = vcs_backend.get_info(
+                                os.path.join(dir, dirpath))
+                            vcs_dirs.append(dirpath)
+                        vcs_bundle_file = vcs_backend.bundle_file
+                        vcs_guide = vcs_backend.guide % {'url': vcs_url,
+                                                         'rev': vcs_rev}
+                        dirnames.remove(vcs_backend.dirname)
+                        break
+                if 'pip-egg-info' in dirnames:
+                    dirnames.remove('pip-egg-info')
+                for dirname in dirnames:
+                    dirname = os.path.join(dirpath, dirname)
+                    name = self._clean_zip_name(dirname, dir)
+                    zip.writestr(basename + '/' + name + '/', '')
+                for filename in filenames:
+                    if filename == 'pip-delete-this-directory.txt':
+                        continue
+                    filename = os.path.join(dirpath, filename)
+                    name = self._clean_zip_name(filename, dir)
+                    zip.write(filename, basename + '/' + name)
+                if vcs_url:
+                    name = os.path.join(dirpath, vcs_bundle_file)
+                    name = self._clean_zip_name(name, dir)
+                    zip.writestr(basename + '/' + name, vcs_guide)
+
+        zip.writestr('pip-manifest.txt', self.bundle_requirements())
+        zip.close()
+
+    BUNDLE_HEADER = '''\
+# This is a pip bundle file, that contains many source packages
+# that can be installed as a group.  You can install this like:
+#     pip this_file.zip
+# The rest of the file contains a list of all the packages included:
+'''
+
+    def bundle_requirements(self):
+        parts = [self.BUNDLE_HEADER]
+        for req in sorted(
+            [req for req in self.requirements.values()
+             if not req.comes_from],
+            key=lambda x: x.name):
+            parts.append('%s==%s\n' % (req.name, req.installed_version))
+        parts.append('# These packages were installed to satisfy the above requirements:\n')
+        for req in sorted(
+            [req for req in self.requirements.values()
+             if req.comes_from],
+            key=lambda x: x.name):
+            parts.append('%s==%s\n' % (req.name, req.installed_version))
+        ## FIXME: should we do something with self.unnamed_requirements?
+        return ''.join(parts)
+
+    def _clean_zip_name(self, name, prefix):
+        assert name.startswith(prefix+'/'), (
+            "name %r doesn't start with prefix %r" % (name, prefix))
+        name = name[len(prefix)+1:]
+        name = name.replace(os.path.sep, '/')
+        return name
+
+_scheme_re = re.compile(r'^(http|https|file):', re.I)
+
+def parse_requirements(filename, finder=None, comes_from=None, options=None):
+    skip_match = None
+    skip_regex = options.skip_requirements_regex
+    if skip_regex:
+        skip_match = re.compile(skip_regex)
+    filename, content = get_file_content(filename, comes_from=comes_from)
+    for line_number, line in enumerate(content.splitlines()):
+        line_number += 1
+        line = line.strip()
+        if not line or line.startswith('#'):
+            continue
+        if skip_match and skip_match.search(line):
+            continue
+        if line.startswith('-r') or line.startswith('--requirement'):
+            if line.startswith('-r'):
+                req_url = line[2:].strip()
+            else:
+                req_url = line[len('--requirement'):].strip().strip('=')
+            if _scheme_re.search(filename):
+                # Relative to a URL
+                req_url = urlparse.urljoin(req_url, filename)
+            elif not _scheme_re.search(req_url):
+                req_url = os.path.join(os.path.dirname(filename), req_url)
+            for item in parse_requirements(req_url, finder, comes_from=filename, options=options):
+                yield item
+        elif line.startswith('-Z') or line.startswith('--always-unzip'):
+            # No longer used, but previously these were used in
+            # requirement files, so we'll ignore.
+            pass
+        elif line.startswith('-f') or line.startswith('--find-links'):
+            if line.startswith('-f'):
+                line = line[2:].strip()
+            else:
+                line = line[len('--find-links'):].strip().lstrip('=')
+            ## FIXME: it would be nice to keep track of the source of
+            ## the find_links:
+            if finder: finder.find_links.append(line)
+        elif line.startswith('-i') or line.startswith('--index-url'):
+            if line.startswith('-i'):
+                line = line[2:].strip()
+            else:
+                line = line[len('--index-url'):].strip().lstrip('=')
+            if finder: finder.index_urls = [line]
+        elif line.startswith('--extra-index-url'):
+            line = line[len('--extra-index-url'):].strip().lstrip('=')
+            if finder: finder.index_urls.append(line)
+        else:
+            comes_from = '-r %s (line %s)' % (filename, line_number)
+            if line.startswith('-e') or line.startswith('--editable'):
+                if line.startswith('-e'):
+                    line = line[2:].strip()
+                else:
+                    line = line[len('--editable'):].strip()
+                req = InstallRequirement.from_editable(
+                    line, comes_from=comes_from, default_vcs=options.default_vcs)
+            else:
+                req = InstallRequirement.from_line(line, comes_from)
+            yield req
+
+def parse_editable(editable_req, default_vcs=None):
+    """Parses svn+http://blahblah@rev#egg=Foobar into a requirement
+    (Foobar) and a URL"""
+    url = editable_req
+    if os.path.isdir(url) and os.path.exists(os.path.join(url, 'setup.py')):
+        # Treating it as code that has already been checked out
+        url = path_to_url(url)
+    if url.lower().startswith('file:'):
+        return None, url
+    for version_control in vcs:
+        if url.lower().startswith('%s:' % version_control):
+            url = '%s+%s' % (version_control, url)
+    if '+' not in url:
+        if default_vcs:
+            url = default_vcs + '+' + url
+        else:
+            raise InstallationError(
+                '--editable=%s should be formatted with svn+URL, git+URL, hg+URL or bzr+URL' % editable_req)
+    vc_type = url.split('+', 1)[0].lower()
+    if not vcs.get_backend(vc_type):
+        raise InstallationError(
+            'For --editable=%s only svn (svn+URL), Git (git+URL), Mercurial (hg+URL) and Bazaar (bzr+URL) is currently supported' % editable_req)
+    match = re.search(r'(?:#|#.*?&)egg=([^&]*)', editable_req)
+    if (not match or not match.group(1)) and vcs.get_backend(vc_type):
+        parts = [p for p in editable_req.split('#', 1)[0].split('/') if p]
+        if parts[-2] in ('tags', 'branches', 'tag', 'branch'):
+            req = parts[-3]
+        elif parts[-1] == 'trunk':
+            req = parts[-2]
+        else:
+            raise InstallationError(
+                '--editable=%s is not the right format; it must have #egg=Package'
+                % editable_req)
+    else:
+        req = match.group(1)
+    ## FIXME: use package_to_requirement?
+    match = re.search(r'^(.*?)(?:-dev|-\d.*)', req)
+    if match:
+        # Strip off -dev, -0.2, etc.
+        req = match.group(1)
+    return req, url
+
+class UninstallPathSet(object):
+    """A set of file paths to be removed in the uninstallation of a
+    requirement."""
+    def __init__(self, dist):
+        self.paths = set()
+        self._refuse = set()
+        self.pth = {}
+        self.dist = dist
+        self.save_dir = None
+        self._moved_paths = []
+
+    def _permitted(self, path):
+        """
+        Return True if the given path is one we are permitted to
+        remove/modify, False otherwise.
+
+        """
+        return is_local(path)
+
+    def _can_uninstall(self):
+        if not dist_is_local(self.dist):
+            logger.notify("Not uninstalling %s at %s, outside environment %s"
+                          % (self.dist.project_name, normalize_path(self.dist.location), sys.prefix))
+            return False
+        return True
+
+    def add(self, path):
+        path = normalize_path(path)
+        if not os.path.exists(path):
+            return
+        if self._permitted(path):
+            self.paths.add(path)
+        else:
+            self._refuse.add(path)
+
+    def add_pth(self, pth_file, entry):
+        pth_file = normalize_path(pth_file)
+        if self._permitted(pth_file):
+            entry = os.path.normcase(entry)
+            if pth_file not in self.pth:
+                self.pth[pth_file] = UninstallPthEntries(pth_file)
+            self.pth[pth_file].add(entry)
+        else:
+            self._refuse.add(pth_file)
+
+    def compact(self, paths):
+        """Compact a path set to contain the minimal number of paths
+        necessary to contain all paths in the set. If /a/path/ and
+        /a/path/to/a/file.txt are both in the set, leave only the
+        shorter path."""
+        short_paths = set()
+        for path in sorted(paths, key=len):
+            if not any([(path.startswith(shortpath) and
+                         path[len(shortpath.rstrip(os.path.sep))] == os.path.sep)
+                        for shortpath in short_paths]):
+                short_paths.add(path)
+        return short_paths
+
+    def remove(self, auto_confirm=False):
+        """Remove paths in ``self.paths`` with confirmation (unless
+        ``auto_confirm`` is True)."""
+        if not self._can_uninstall():
+            return
+        logger.notify('Uninstalling %s:' % self.dist.project_name)
+        logger.indent += 2
+        paths = sorted(self.compact(self.paths))
+        try:
+            if auto_confirm:
+                response = 'y'
+            else:
+                for path in paths:
+                    logger.notify(path)
+                response = ask('Proceed (y/n)? ', ('y', 'n'))
+            if self._refuse:
+                logger.notify('Not removing or modifying (outside of prefix):')
+                for path in self.compact(self._refuse):
+                    logger.notify(path)
+            if response == 'y':
+                self.save_dir = tempfile.mkdtemp(suffix='-uninstall',
+                                                 prefix='pip-')
+                for path in paths:
+                    new_path = os.path.splitdrive(path)[1].lstrip(os.path.sep)
+                    new_path = os.path.join(self.save_dir, new_path)
+                    logger.info('Removing file or directory %s' % path)
+                    self._moved_paths.append(path)
+                    renames(path, new_path)
+                for pth in self.pth.values():
+                    pth.remove()
+                logger.notify('Successfully uninstalled %s' % self.dist.project_name)
+
+        finally:
+            logger.indent -= 2
+
+    def rollback(self):
+        """Rollback the changes previously made by remove()."""
+        if self.save_dir is None:
+            logger.error("Can't roll back %s; was not uninstalled" % self.dist.project_name)
+            return False
+        logger.notify('Rolling back uninstall of %s' % self.dist.project_name)
+        for path in self._moved_paths:
+            tmp_path = os.path.join(self.save_dir, path.lstrip(os.path.sep))
+            logger.info('Replacing %s' % path)
+            renames(tmp_path, path)
+        for pth in self.pth:
+            pth.rollback()
+
+    def commit(self):
+        """Remove temporary save dir: rollback will no longer be possible."""
+        if self.save_dir is not None:
+            shutil.rmtree(self.save_dir)
+            self.save_dir = None
+            self._moved_paths = []
+
+
+class UninstallPthEntries(object):
+    def __init__(self, pth_file):
+        if not os.path.isfile(pth_file):
+            raise UninstallationError("Cannot remove entries from nonexistent file %s" % pth_file)
+        self.file = pth_file
+        self.entries = set()
+        self._saved_lines = None
+
+    def add(self, entry):
+        self.entries.add(entry)
+
+    def remove(self):
+        logger.info('Removing pth entries from %s:' % self.file)
+        fh = open(self.file, 'r')
+        lines = fh.readlines()
+        self._saved_lines = lines
+        fh.close()
+        try:
+            for entry in self.entries:
+                logger.info('Removing entry: %s' % entry)
+            try:
+                lines.remove(entry + '\n')
+            except ValueError:
+                pass
+        finally:
+            pass
+        fh = open(self.file, 'w')
+        fh.writelines(lines)
+        fh.close()
+
+    def rollback(self):
+        if self._saved_lines is None:
+            logger.error('Cannot roll back changes to %s, none were made' % self.file)
+            return False
+        logger.info('Rolling %s back to previous state' % self.file)
+        fh = open(self.file, 'w')
+        fh.writelines(self._saved_lines)
+        fh.close()
+        return True
+
+class FakeFile(object):
+    """Wrap a list of lines in an object with readline() to make
+    ConfigParser happy."""
+    def __init__(self, lines):
+        self._gen = (l for l in lines)
+
+    def readline(self):
+        try:
+            return self._gen.next()
+        except StopIteration:
+            return ''

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/runner.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/runner.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/runner.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,16 @@
+import sys
+import os
+
+def run():
+    base = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+    ## FIXME: this is kind of crude; if we could create a fake pip
+    ## module, then exec into it and update pip.__path__ properly, we
+    ## wouldn't have to update sys.path:
+    sys.path.insert(0, base)
+    import pip
+    return pip.main()
+
+if __name__ == '__main__':
+    exit = run()
+    if exit:
+        sys.exit(exit)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/util.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/util.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/util.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,419 @@
+import sys
+import shutil
+import os
+import posixpath
+import stat
+import urllib
+import urllib2
+import re
+
+import pkg_resources
+
+from pip.backwardcompat import WindowsError
+from pip.exceptions import InstallationError
+from pip.locations import site_packages
+
+__all__ = ['rmtree', 'display_path', 'backup_dir',
+           'find_command', 'splitext', 'ask', 'Inf',
+           'url_to_path', 'path_to_url',
+           'path_to_url2', 'normalize_name',
+           'format_size', 'is_url', 'is_installable_dir', 'is_archive_file',
+           'strip_prefix', 'is_svn_page', 'file_contents',
+           'split_leading_dir', 'has_leading_dir',
+           'make_path_relative', 'normalize_path',
+           'get_file_content', 'renames', 'get_terminal_size']
+
+def rmtree(dir):
+    shutil.rmtree(dir, ignore_errors=True,
+                  onerror=rmtree_errorhandler)
+
+def rmtree_errorhandler(func, path, exc_info):
+    """On Windows, the files in .svn are read-only, so when rmtree() tries to
+    remove them, an exception is thrown.  We catch that here, remove the
+    read-only attribute, and hopefully continue without problems."""
+    exctype, value = exc_info[:2]
+    # lookin for a windows error
+    if exctype is not WindowsError or 'Access is denied' not in str(value):
+        raise
+    # file type should currently be read only
+    if ((os.stat(path).st_mode & stat.S_IREAD) != stat.S_IREAD):
+        raise
+    # convert to read/write
+    os.chmod(path, stat.S_IWRITE)
+    # use the original function to repeat the operation
+    func(path)
+
+def display_path(path):
+    """Gives the display value for a given path, making it relative to cwd
+    if possible."""
+    path = os.path.normcase(os.path.abspath(path))
+    if path.startswith(os.getcwd() + os.path.sep):
+        path = '.' + path[len(os.getcwd()):]
+    return path
+
+def backup_dir(dir, ext='.bak'):
+    """Figure out the name of a directory to back up the given dir to
+    (adding .bak, .bak2, etc)"""
+    n = 1
+    extension = ext
+    while os.path.exists(dir + extension):
+        n += 1
+        extension = ext + str(n)
+    return dir + extension
+    
+def splitext(path):
+    """Like os.path.splitext, but take off .tar too"""
+    base, ext = posixpath.splitext(path)
+    if base.lower().endswith('.tar'):
+        ext = base[-4:] + ext
+        base = base[:-4]
+    return base, ext
+
+def find_command(cmd, paths=None, pathext=None):
+    """Searches the PATH for the given command and returns its path"""
+    if paths is None:
+        paths = os.environ.get('PATH', []).split(os.pathsep)
+    if isinstance(paths, basestring):
+        paths = [paths]
+    # check if there are funny path extensions for executables, e.g. Windows
+    if pathext is None:
+        pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
+    pathext = [ext for ext in pathext.lower().split(os.pathsep)]
+    # don't use extensions if the command ends with one of them
+    if os.path.splitext(cmd)[1].lower() in pathext:
+        pathext = ['']
+    # check if we find the command on PATH
+    for path in paths:
+        # try without extension first
+        cmd_path = os.path.join(path, cmd)
+        for ext in pathext:
+            # then including the extension
+            cmd_path_ext = cmd_path + ext
+            if os.path.exists(cmd_path_ext):
+                return cmd_path_ext
+        if os.path.exists(cmd_path):
+            return cmd_path
+    return None
+
+def ask(message, options):
+    """Ask the message interactively, with the given possible responses"""
+    while 1:
+        if os.environ.get('PIP_NO_INPUT'):
+            raise Exception('No input was expected ($PIP_NO_INPUT set); question: %s' % message)
+        response = raw_input(message)
+        response = response.strip().lower()
+        if response not in options:
+            print 'Your response (%r) was not one of the expected responses: %s' % (
+                response, ', '.join(options))
+        else:
+            return response
+
+class _Inf(object):
+    """I am bigger than everything!"""
+    def __cmp__(self, a):
+        if self is a:
+            return 0
+        return 1
+    def __repr__(self):
+        return 'Inf'
+Inf = _Inf()
+del _Inf
+
+
+def url_to_path(url):
+    """
+    Convert a file: URL to a path.
+    """
+    assert url.startswith('file:'), (
+        "You can only turn file: urls into filenames (not %r)" % url)
+    path = url[len('file:'):].lstrip('/')
+    path = urllib.unquote(path)
+    if _url_drive_re.match(path):
+        path = path[0] + ':' + path[2:]
+    else:
+        path = '/' + path
+    return path
+
+_drive_re = re.compile('^([a-z]):', re.I)
+_url_drive_re = re.compile('^([a-z])[:|]', re.I)
+
+def path_to_url(path):
+    """
+    Convert a path to a file: URL.  The path will be made absolute.
+    """
+    path = os.path.normcase(os.path.abspath(path))
+    if _drive_re.match(path):
+        path = path[0] + '|' + path[2:]
+    url = urllib.quote(path)
+    url = url.replace(os.path.sep, '/')
+    url = url.lstrip('/')
+    return 'file:///' + url
+
+def path_to_url2(path):
+    """
+    Convert a path to a file: URL.  The path will be made absolute and have
+    quoted path parts.
+    """
+    path = os.path.normcase(os.path.abspath(path))
+    drive, path = os.path.splitdrive(path)
+    filepath = path.split(os.path.sep)
+    url = '/'.join([urllib.quote(part) for part in filepath])
+    if not drive:
+        url = url.lstrip('/')
+    return 'file:///' + drive + url
+
+_normalize_re = re.compile(r'[^a-z]', re.I)
+
+def normalize_name(name):
+    return _normalize_re.sub('-', name.lower())
+
+def format_size(bytes):
+    if bytes > 1000*1000:
+        return '%.1fMb' % (bytes/1000.0/1000)
+    elif bytes > 10*1000:
+        return '%iKb' % (bytes/1000)
+    elif bytes > 1000:
+        return '%.1fKb' % (bytes/1000.0)
+    else:
+        return '%ibytes' % bytes
+
+def is_url(name):
+    """Returns true if the name looks like a URL"""
+    from pip.vcs import vcs
+    if ':' not in name:
+        return False
+    scheme = name.split(':', 1)[0].lower()
+    return scheme in ['http', 'https', 'file', 'ftp'] + vcs.all_schemes
+
+def is_installable_dir(path):
+    """Return True if `path` is a directory containing a setup.py file."""
+    if not os.path.isdir(path):
+        return False
+    setup_py = os.path.join(path, 'setup.py')
+    if os.path.isfile(setup_py):
+        return True
+    return False
+
+def is_archive_file(name):
+    """Return True if `name` is a considered as an archive file."""
+    archives = ('.zip', '.tar.gz', '.tar.bz2', '.tgz', '.tar', '.pybundle')
+    ext = splitext(name)[1].lower()
+    if ext in archives:
+        return True
+    return False
+
+def is_svn_page(html):
+    """Returns true if the page appears to be the index page of an svn repository"""
+    return (re.search(r'<title>[^<]*Revision \d+:', html)
+            and re.search(r'Powered by (?:<a[^>]*?>)?Subversion', html, re.I))
+
+def file_contents(filename):
+    fp = open(filename, 'rb')
+    try:
+        return fp.read()
+    finally:
+        fp.close()
+
+def split_leading_dir(path):
+    path = str(path)
+    path = path.lstrip('/').lstrip('\\')
+    if '/' in path and (('\\' in path and path.find('/') < path.find('\\'))
+                        or '\\' not in path):
+        return path.split('/', 1)
+    elif '\\' in path:
+        return path.split('\\', 1)
+    else:
+        return path, ''
+
+def has_leading_dir(paths):
+    """Returns true if all the paths have the same leading path name
+    (i.e., everything is in one subdirectory in an archive)"""
+    common_prefix = None
+    for path in paths:
+        prefix, rest = split_leading_dir(path)
+        if not prefix:
+            return False
+        elif common_prefix is None:
+            common_prefix = prefix
+        elif prefix != common_prefix:
+            return False
+    return True
+
+def make_path_relative(path, rel_to):
+    """
+    Make a filename relative, where the filename path, and it is
+    relative to rel_to
+
+        >>> make_relative_path('/usr/share/something/a-file.pth',
+        ...                    '/usr/share/another-place/src/Directory')
+        '../../../something/a-file.pth'
+        >>> make_relative_path('/usr/share/something/a-file.pth',
+        ...                    '/home/user/src/Directory')
+        '../../../usr/share/something/a-file.pth'
+        >>> make_relative_path('/usr/share/a-file.pth', '/usr/share/')
+        'a-file.pth'
+    """
+    path_filename = os.path.basename(path)
+    path = os.path.dirname(path)
+    path = os.path.normpath(os.path.abspath(path))
+    rel_to = os.path.normpath(os.path.abspath(rel_to))
+    path_parts = path.strip(os.path.sep).split(os.path.sep)
+    rel_to_parts = rel_to.strip(os.path.sep).split(os.path.sep)
+    while path_parts and rel_to_parts and path_parts[0] == rel_to_parts[0]:
+        path_parts.pop(0)
+        rel_to_parts.pop(0)
+    full_parts = ['..']*len(rel_to_parts) + path_parts + [path_filename]
+    if full_parts == ['']:
+        return '.' + os.path.sep
+    return os.path.sep.join(full_parts)
+
+def normalize_path(path):
+    """
+    Convert a path to its canonical, case-normalized, absolute version.
+    
+    """
+    return os.path.normcase(os.path.realpath(path))
+
+_scheme_re = re.compile(r'^(http|https|file):', re.I)
+_url_slash_drive_re = re.compile(r'/*([a-z])\|', re.I)
+
+def get_file_content(url, comes_from=None):
+    """Gets the content of a file; it may be a filename, file: URL, or
+    http: URL.  Returns (location, content)"""
+    match = _scheme_re.search(url)
+    if match:
+        scheme = match.group(1).lower()
+        if (scheme == 'file' and comes_from
+            and comes_from.startswith('http')):
+            raise InstallationError(
+                'Requirements file %s references URL %s, which is local'
+                % (comes_from, url))
+        if scheme == 'file':
+            path = url.split(':', 1)[1]
+            path = path.replace('\\', '/')
+            match = _url_slash_drive_re.match(path)
+            if match:
+                path = match.group(1) + ':' + path.split('|', 1)[1]
+            path = urllib.unquote(path)
+            if path.startswith('/'):
+                path = '/' + path.lstrip('/')
+            url = path
+        else:
+            ## FIXME: catch some errors
+            resp = urllib2.urlopen(url)
+            return resp.geturl(), resp.read()
+    f = open(url)
+    content = f.read()
+    f.close()
+    return url, content
+
+def renames(old, new):
+    """Like os.renames(), but handles renaming across devices."""
+    # Implementation borrowed from os.renames().
+    head, tail = os.path.split(new)
+    if head and tail and not os.path.exists(head):
+        os.makedirs(head)
+
+    shutil.move(old, new)
+
+    head, tail = os.path.split(old)
+    if head and tail:
+        try:
+            os.removedirs(head)
+        except OSError:
+            pass
+
+def in_venv():
+    """
+    Return True if we're running inside a virtualenv, False otherwise.
+
+    """
+    return hasattr(sys, 'real_prefix')
+        
+def is_local(path):
+    """
+    Return True if path is within sys.prefix, if we're running in a virtualenv.
+
+    If we're not in a virtualenv, all paths are considered "local."
+
+    """
+    if not in_venv():
+        return True
+    return normalize_path(path).startswith(normalize_path(sys.prefix))
+
+def dist_is_local(dist):
+    """
+    Return True if given Distribution object is installed locally
+    (i.e. within current virtualenv).
+
+    Always True if we're not in a virtualenv.
+    
+    """
+    return is_local(dist_location(dist))
+
+def get_installed_distributions(local_only=True, skip=('setuptools', 'pip', 'python')):
+    """
+    Return a list of installed Distribution objects.
+
+    If ``local_only`` is True (default), only return installations
+    local to the current virtualenv, if in a virtualenv.
+
+    ``skip`` argument is an iterable of lower-case project names to
+    ignore; defaults to ('setuptools', 'pip', 'python'). [FIXME also
+    skip virtualenv?]
+
+    """
+    if local_only:
+        local_test = dist_is_local
+    else:
+        local_test = lambda d: True
+    return [d for d in pkg_resources.working_set if local_test(d) and d.key not in skip]
+
+def egg_link_path(dist):
+    """
+    Return the path where we'd expect to find a .egg-link file for
+    this distribution. (There doesn't seem to be any metadata in the
+    Distribution object for a develop egg that points back to its
+    .egg-link and easy-install.pth files).
+
+    This won't find a globally-installed develop egg if we're in a
+    virtualenv. 
+
+    """
+    return os.path.join(site_packages, dist.project_name) + '.egg-link'
+
+def dist_location(dist):
+    """
+    Get the site-packages location of this distribution. Generally
+    this is dist.location, except in the case of develop-installed
+    packages, where dist.location is the source code location, and we
+    want to know where the egg-link file is.
+
+    """
+    egg_link = egg_link_path(dist)
+    if os.path.exists(egg_link):
+        return egg_link
+    return dist.location
+
+def get_terminal_size():
+    """Returns a tuple (x, y) representing the width(x) and the height(x)
+    in characters of the terminal window."""
+    def ioctl_GWINSZ(fd):
+        try:
+            import fcntl, termios, struct
+            cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
+        '1234'))
+        except:
+            return None
+        return cr
+    cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
+    if not cr:
+        try:
+            fd = os.open(os.ctermid(), os.O_RDONLY)
+            cr = ioctl_GWINSZ(fd)
+            os.close(fd)
+        except:
+            pass
+    if not cr:
+        cr = (os.environ.get('LINES', 25), os.environ.get('COLUMNS', 80))
+    return int(cr[1]), int(cr[0])

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/__init__.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/__init__.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/__init__.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,234 @@
+"""Handles all VCS (version control) support"""
+
+import os
+import shutil
+import urlparse
+import urllib
+from pip.util import display_path, backup_dir, find_command, ask
+from pip.exceptions import BadCommand
+from pip.log import logger
+
+__all__ = ['vcs', 'get_source_requirement', 'import_vcs_support']
+
+class VcsSupport(object):
+    _registry = {}
+    schemes = ['ssh', 'git', 'hg', 'bzr', 'sftp']
+
+    def __init__(self):
+        # Register more schemes with urlparse for various version control systems
+        urlparse.uses_netloc.extend(self.schemes)
+        urlparse.uses_fragment.extend(self.schemes)
+        super(VcsSupport, self).__init__()
+
+    def __iter__(self):
+        return self._registry.__iter__()
+
+    @property
+    def backends(self):
+        return self._registry.values()
+
+    @property
+    def dirnames(self):
+        return [backend.dirname for backend in self.backends]
+
+    @property
+    def all_schemes(self):
+        schemes = []
+        for backend in self.backends:
+            schemes.extend(backend.schemes)
+        return schemes
+
+    def register(self, cls):
+        if not hasattr(cls, 'name'):
+            logger.warn('Cannot register VCS %s' % cls.__name__)
+            return
+        if cls.name not in self._registry:
+            self._registry[cls.name] = cls
+
+    def unregister(self, cls=None, name=None):
+        if name in self._registry:
+            del self._registry[name]
+        elif cls in self._registry.values():
+            del self._registry[cls.name]
+        else:
+            logger.warn('Cannot unregister because no class or name given')
+
+    def get_backend_name(self, location):
+        """
+        Return the name of the version control backend if found at given
+        location, e.g. vcs.get_backend_name('/path/to/vcs/checkout')
+        """
+        for vc_type in self._registry.values():
+            path = os.path.join(location, vc_type.dirname)
+            if os.path.exists(path):
+                return vc_type.name
+        return None
+
+    def get_backend(self, name):
+        name = name.lower()
+        if name in self._registry:
+            return self._registry[name]
+
+    def get_backend_from_location(self, location):
+        vc_type = self.get_backend_name(location)
+        if vc_type:
+            return self.get_backend(vc_type)
+        return None
+
+vcs = VcsSupport()
+
+
+
+class VersionControl(object):
+    name = ''
+    dirname = ''
+
+    def __init__(self, url=None, *args, **kwargs):
+        self.url = url
+        self._cmd = None
+        super(VersionControl, self).__init__(*args, **kwargs)
+
+    def _filter(self, line):
+        return (logger.INFO, line)
+
+    @property
+    def cmd(self):
+        if self._cmd is not None:
+            return self._cmd
+        command = find_command(self.name)
+        if command is None:
+            raise BadCommand('Cannot find command %r' % self.name)
+        logger.info('Found command %r at %r' % (self.name, command))
+        self._cmd = command
+        return command
+
+    def get_url_rev(self):
+        """
+        Returns the correct repository URL and revision by parsing the given
+        repository URL
+        """
+        url = self.url.split('+', 1)[1]
+        scheme, netloc, path, query, frag = urlparse.urlsplit(url)
+        rev = None
+        if '@' in path:
+            path, rev = path.rsplit('@', 1)
+        url = urlparse.urlunsplit((scheme, netloc, path, query, ''))
+        return url, rev
+
+    def get_info(self, location):
+        """
+        Returns (url, revision), where both are strings
+        """
+        assert not location.rstrip('/').endswith(self.dirname), 'Bad directory: %s' % location
+        return self.get_url(location), self.get_revision(location)
+
+    def normalize_url(self, url):
+        """
+        Normalize a URL for comparison by unquoting it and removing any trailing slash.
+        """
+        return urllib.unquote(url).rstrip('/')
+
+    def compare_urls(self, url1, url2):
+        """
+        Compare two repo URLs for identity, ignoring incidental differences.
+        """
+        return (self.normalize_url(url1) == self.normalize_url(url2))
+
+    def parse_vcs_bundle_file(self, content):
+        """
+        Takes the contents of the bundled text file that explains how to revert
+        the stripped off version control data of the given package and returns
+        the URL and revision of it.
+        """
+        raise NotImplementedError
+
+    def obtain(self, dest):
+        """
+        Called when installing or updating an editable package, takes the
+        source path of the checkout.
+        """
+        raise NotImplementedError
+
+    def switch(self, dest, url, rev_options):
+        """
+        Switch the repo at ``dest`` to point to ``URL``.
+        """
+        raise NotImplemented
+
+    def update(self, dest, rev_options):
+        """
+        Update an already-existing repo to the given ``rev_options``.
+        """
+        raise NotImplementedError
+
+    def check_destination(self, dest, url, rev_options, rev_display):
+        """
+        Prepare a location to receive a checkout/clone.
+
+        Return True if the location is ready for (and requires) a
+        checkout/clone, False otherwise.
+        """
+        checkout = True
+        prompt = False
+        if os.path.exists(dest):
+            checkout = False
+            if os.path.exists(os.path.join(dest, self.dirname)):
+                existing_url = self.get_url(dest)
+                if self.compare_urls(existing_url, url):
+                    logger.info('%s in %s exists, and has correct URL (%s)'
+                                % (self.repo_name.title(), display_path(dest), url))
+                    logger.notify('Updating %s %s%s'
+                                  % (display_path(dest), self.repo_name, rev_display))
+                    self.update(dest, rev_options)
+                else:
+                    logger.warn('%s %s in %s exists with URL %s'
+                                % (self.name, self.repo_name, display_path(dest), existing_url))
+                    prompt = ('(s)witch, (i)gnore, (w)ipe, (b)ackup ', ('s', 'i', 'w', 'b'))
+            else:
+                logger.warn('Directory %s already exists, and is not a %s %s.'
+                            % (dest, self.name, self.repo_name))
+                prompt = ('(i)gnore, (w)ipe, (b)ackup ', ('i', 'w', 'b'))
+        if prompt:
+            logger.warn('The plan is to install the %s repository %s'
+                        % (self.name, url))
+            response = ask('What to do?  %s' % prompt[0], prompt[1])
+
+            if response == 's':
+                logger.notify('Switching %s %s to %s%s'
+                              % (self.repo_name, display_path(dest), url, rev_display))
+                self.switch(dest, url, rev_options)
+            elif response == 'i':
+                # do nothing
+                pass
+            elif response == 'w':
+                logger.warn('Deleting %s' % display_path(dest))
+                shutil.rmtree(dest)
+                checkout = True
+            elif response == 'b':
+                dest_dir = backup_dir(dest)
+                logger.warn('Backing up %s to %s'
+                            % (display_path(dest), dest_dir))
+                shutil.move(dest, dest_dir)
+                checkout = True
+        return checkout
+
+    def unpack(self, location):
+        raise NotImplementedError
+
+    def get_src_requirement(self, dist, location, find_tags=False):
+        raise NotImplementedError
+
+def get_src_requirement(dist, location, find_tags):
+    version_control = vcs.get_backend_from_location(location)
+    if version_control:
+        return version_control().get_src_requirement(dist, location, find_tags)
+    logger.warn('cannot determine version of editable source in %s (is not SVN checkout, Git clone, Mercurial clone or Bazaar branch)' % location)
+    return dist.as_requirement()
+
+def import_vcs_support():
+    # Import all the version control support modules:
+    here = os.path.dirname(__file__)
+    for name in os.listdir(here):
+        if name != '__init__.py' and name.endswith('.py'):
+            name = os.path.splitext(name)[0]
+            __import__('pip.vcs.%s' % name)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/bazaar.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/bazaar.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/bazaar.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,133 @@
+import os
+import shutil
+import tempfile
+import re
+from pip import call_subprocess
+from pip.log import logger
+from pip.util import rmtree, display_path
+from pip.vcs import vcs, VersionControl
+
+class Bazaar(VersionControl):
+    name = 'bzr'
+    dirname = '.bzr'
+    repo_name = 'branch'
+    bundle_file = 'bzr-branch.txt'
+    schemes = ('bzr', 'bzr+http', 'bzr+https', 'bzr+ssh', 'bzr+sftp', 'bzr+ftp')
+    guide = ('# This was a Bazaar branch; to make it a branch again run:\n'
+             'bzr branch -r %(rev)s %(url)s .\n')
+
+    def parse_vcs_bundle_file(self, content):
+        url = rev = None
+        for line in content.splitlines():
+            if not line.strip() or line.strip().startswith('#'):
+                continue
+            match = re.search(r'^bzr\s*branch\s*-r\s*(\d*)', line)
+            if match:
+                rev = match.group(1).strip()
+            url = line[match.end():].strip().split(None, 1)[0]
+            if url and rev:
+                return url, rev
+        return None, None
+
+    def unpack(self, location):
+        """Get the bzr branch at the url to the destination location"""
+        url, rev = self.get_url_rev()
+        logger.notify('Checking out bzr repository %s to %s' % (url, location))
+        logger.indent += 2
+        try:
+            if os.path.exists(location):
+                os.rmdir(location)
+            call_subprocess(
+                [self.cmd, 'branch', url, location],
+                filter_stdout=self._filter, show_stdout=False)
+        finally:
+            logger.indent -= 2
+
+    def export(self, location):
+        """Export the Bazaar repository at the url to the destination location"""
+        temp_dir = tempfile.mkdtemp('-export', 'pip-')
+        self.unpack(temp_dir)
+        if os.path.exists(location):
+            # Remove the location to make sure Bazaar can export it correctly
+            rmtree(location)
+        try:
+            call_subprocess([self.cmd, 'export', location], cwd=temp_dir,
+                            filter_stdout=self._filter, show_stdout=False)
+        finally:
+            shutil.rmtree(temp_dir)
+
+    def switch(self, dest, url, rev_options):
+        call_subprocess([self.cmd, 'switch', url], cwd=dest)
+
+    def update(self, dest, rev_options):
+        call_subprocess(
+            [self.cmd, 'pull', '-q'] + rev_options, cwd=dest)
+
+    def obtain(self, dest):
+        url, rev = self.get_url_rev()
+        if rev:
+            rev_options = ['-r', rev]
+            rev_display = ' (to revision %s)' % rev
+        else:
+            rev_options = []
+            rev_display = ''
+        if self.check_destination(dest, url, rev_options, rev_display):
+            logger.notify('Checking out %s%s to %s'
+                          % (url, rev_display, display_path(dest)))
+            call_subprocess(
+                [self.cmd, 'branch', '-q'] + rev_options + [url, dest])
+
+    def get_url_rev(self):
+        # hotfix the URL scheme after removing bzr+ from bzr+ssh:// readd it
+        url, rev = super(Bazaar, self).get_url_rev()
+        if url.startswith('ssh://'):
+            url = 'bzr+' + url
+        return url, rev
+
+    def get_url(self, location):
+        urls = call_subprocess(
+            [self.cmd, 'info'], show_stdout=False, cwd=location)
+        for line in urls.splitlines():
+            line = line.strip()
+            for x in ('checkout of branch: ',
+                      'parent branch: '):
+                if line.startswith(x):
+                    return line.split(x)[1]
+        return None
+
+    def get_revision(self, location):
+        revision = call_subprocess(
+            [self.cmd, 'revno'], show_stdout=False, cwd=location)
+        return revision.splitlines()[-1]
+
+    def get_tag_revs(self, location):
+        tags = call_subprocess(
+            [self.cmd, 'tags'], show_stdout=False, cwd=location)
+        tag_revs = []
+        for line in tags.splitlines():
+            tags_match = re.search(r'([.\w-]+)\s*(.*)$', line)
+            if tags_match:
+                tag = tags_match.group(1)
+                rev = tags_match.group(2)
+                tag_revs.append((rev.strip(), tag.strip()))
+        return dict(tag_revs)
+
+    def get_src_requirement(self, dist, location, find_tags):
+        repo = self.get_url(location)
+        if not repo.lower().startswith('bzr:'):
+            repo = 'bzr+' + repo
+        egg_project_name = dist.egg_name().split('-', 1)[0]
+        if not repo:
+            return None
+        current_rev = self.get_revision(location)
+        tag_revs = self.get_tag_revs(location)
+
+        if current_rev in tag_revs:
+            # It's a tag
+            tag = tag_revs.get(current_rev, current_rev)
+            full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
+        else:
+            full_egg_name = '%s-dev_r%s' % (dist.egg_name(), current_rev)
+        return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
+
+vcs.register(Bazaar)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/git.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/git.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/git.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,185 @@
+import os
+import shutil
+import tempfile
+import re
+from pip import call_subprocess
+from pip.util import display_path
+from pip.vcs import vcs, VersionControl
+from pip.log import logger
+
+class Git(VersionControl):
+    name = 'git'
+    dirname = '.git'
+    repo_name = 'clone'
+    schemes = ('git', 'git+http', 'git+ssh', 'git+git')
+    bundle_file = 'git-clone.txt'
+    guide = ('# This was a Git repo; to make it a repo again run:\n'
+        'git init\ngit remote add origin %(url)s -f\ngit checkout %(rev)s\n')
+
+    def parse_vcs_bundle_file(self, content):
+        url = rev = None
+        for line in content.splitlines():
+            if not line.strip() or line.strip().startswith('#'):
+                continue
+            url_match = re.search(r'git\s*remote\s*add\s*origin(.*)\s*-f', line)
+            if url_match:
+                url = url_match.group(1).strip()
+            rev_match = re.search(r'^git\s*checkout\s*-q\s*(.*)\s*', line)
+            if rev_match:
+                rev = rev_match.group(1).strip()
+            if url and rev:
+                return url, rev
+        return None, None
+
+    def unpack(self, location):
+        """Clone the Git repository at the url to the destination location"""
+        url, rev = self.get_url_rev()
+        logger.notify('Cloning Git repository %s to %s' % (url, location))
+        logger.indent += 2
+        try:
+            if os.path.exists(location):
+                os.rmdir(location)
+            call_subprocess(
+                [self.cmd, 'clone', url, location],
+                filter_stdout=self._filter, show_stdout=False)
+        finally:
+            logger.indent -= 2
+
+    def export(self, location):
+        """Export the Git repository at the url to the destination location"""
+        temp_dir = tempfile.mkdtemp('-export', 'pip-')
+        self.unpack(temp_dir)
+        try:
+            if not location.endswith('/'):
+                location = location + '/'
+            call_subprocess(
+                [self.cmd, 'checkout-index', '-a', '-f', '--prefix', location],
+                filter_stdout=self._filter, show_stdout=False, cwd=temp_dir)
+        finally:
+            shutil.rmtree(temp_dir)
+
+    def check_rev_options(self, rev, dest, rev_options):
+        """Check the revision options before checkout to compensate that tags
+        and branches may need origin/ as a prefix"""
+        if rev is None:
+            # bail and use preset
+            return rev_options
+        revisions = self.get_tag_revs(dest)
+        revisions.update(self.get_branch_revs(dest))
+        if rev in revisions:
+            # if rev is a sha
+            return [rev]
+        inverse_revisions = dict((v,k) for k, v in revisions.iteritems())
+        if rev not in inverse_revisions: # is rev a name or tag?
+            origin_rev = 'origin/%s' % rev
+            if origin_rev in inverse_revisions:
+                rev = inverse_revisions[origin_rev]
+            else:
+                logger.warn("Could not find a tag or branch '%s', assuming commit." % rev)
+        return [rev]
+
+    def switch(self, dest, url, rev_options):
+        call_subprocess(
+            [self.cmd, 'config', 'remote.origin.url', url], cwd=dest)
+        call_subprocess(
+            [self.cmd, 'checkout', '-q'] + rev_options, cwd=dest)
+
+    def update(self, dest, rev_options):
+        call_subprocess([self.cmd, 'fetch', '-q'], cwd=dest)
+        call_subprocess(
+            [self.cmd, 'checkout', '-q', '-f'] + rev_options, cwd=dest)
+
+    def obtain(self, dest):
+        url, rev = self.get_url_rev()
+        if rev:
+            rev_options = [rev]
+            rev_display = ' (to %s)' % rev
+        else:
+            rev_options = ['master']
+            rev_display = ''
+        if self.check_destination(dest, url, rev_options, rev_display):
+            logger.notify('Cloning %s%s to %s' % (url, rev_display, display_path(dest)))
+            call_subprocess([self.cmd, 'clone', '-q', url, dest])
+            checked_rev = self.check_rev_options(rev, dest, rev_options)
+            # only explicitely checkout the "revision" in case the check
+            # found a valid tag, commit or branch
+            if rev_options != checked_rev:
+                call_subprocess(
+                    [self.cmd, 'checkout', '-q'] + checked_rev, cwd=dest)
+
+    def get_url(self, location):
+        url = call_subprocess(
+            [self.cmd, 'config', 'remote.origin.url'],
+            show_stdout=False, cwd=location)
+        return url.strip()
+
+    def get_revision(self, location):
+        current_rev = call_subprocess(
+            [self.cmd, 'rev-parse', 'HEAD'], show_stdout=False, cwd=location)
+        return current_rev.strip()
+
+    def get_tag_revs(self, location):
+        tags = call_subprocess(
+            [self.cmd, 'tag', '-l'],
+            show_stdout=False, raise_on_returncode=False, cwd=location)
+        tag_revs = []
+        for line in tags.splitlines():
+            tag = line.strip()
+            rev = call_subprocess(
+                [self.cmd, 'rev-parse', tag], show_stdout=False, cwd=location)
+            tag_revs.append((rev.strip(), tag))
+        tag_revs = dict(tag_revs)
+        return tag_revs
+
+    def get_branch_revs(self, location):
+        branches = call_subprocess(
+            [self.cmd, 'branch', '-r'], show_stdout=False, cwd=location)
+        branch_revs = []
+        for line in branches.splitlines():
+            line = line.split('->')[0].strip()
+            branch = "".join([b for b in line.split() if b != '*'])
+            rev = call_subprocess(
+                [self.cmd, 'rev-parse', branch], show_stdout=False, cwd=location)
+            branch_revs.append((rev.strip(), branch))
+        branch_revs = dict(branch_revs)
+        return branch_revs
+
+    def get_src_requirement(self, dist, location, find_tags):
+        repo = self.get_url(location)
+        if not repo.lower().startswith('git:'):
+            repo = 'git+' + repo
+        egg_project_name = dist.egg_name().split('-', 1)[0]
+        if not repo:
+            return None
+        current_rev = self.get_revision(location)
+        tag_revs = self.get_tag_revs(location)
+        branch_revs = self.get_branch_revs(location)
+
+        if current_rev in tag_revs:
+            # It's a tag
+            full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
+        elif (current_rev in branch_revs and
+              branch_revs[current_rev] != 'origin/master'):
+            # It's the head of a branch
+            full_egg_name = '%s-%s' % (dist.egg_name(),
+                                       branch_revs[current_rev].replace('origin/', ''))
+        else:
+            full_egg_name = '%s-dev' % dist.egg_name()
+
+        return '%s@%s#egg=%s' % (repo, current_rev, full_egg_name)
+
+    def get_url_rev(self):
+        """
+        Prefixes stub URLs like 'user at hostname:user/repo.git' with 'ssh://'.
+        That's required because although they use SSH they sometimes doesn't
+        work with a ssh:// scheme (e.g. Github). But we need a scheme for
+        parsing. Hence we remove it again afterwards and return it as a stub.
+        """
+        if not '://' in self.url:
+            self.url = self.url.replace('git+', 'git+ssh://')
+            url, rev = super(Git, self).get_url_rev()
+            url = url.replace('ssh://', '')
+            return url, rev
+        return super(Git, self).get_url_rev()
+
+vcs.register(Git)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/mercurial.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/mercurial.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/mercurial.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,161 @@
+import os
+import shutil
+import tempfile
+import re
+import ConfigParser
+from pip import call_subprocess
+from pip.util import display_path, path_to_url
+from pip.log import logger
+from pip.vcs import vcs, VersionControl
+
+
+class Mercurial(VersionControl):
+    name = 'hg'
+    dirname = '.hg'
+    repo_name = 'clone'
+    schemes = ('hg', 'hg+http', 'hg+https', 'hg+ssh', 'hg+static-http')
+    bundle_file = 'hg-clone.txt'
+    guide = ('# This was a Mercurial repo; to make it a repo again run:\n'
+            'hg init\nhg pull %(url)s\nhg update -r %(rev)s\n')
+
+    def parse_vcs_bundle_file(self, content):
+        url = rev = None
+        for line in content.splitlines():
+            if not line.strip() or line.strip().startswith('#'):
+                continue
+            url_match = re.search(r'hg\s*pull\s*(.*)\s*', line)
+            if url_match:
+                url = url_match.group(1).strip()
+            rev_match = re.search(r'^hg\s*update\s*-r\s*(.*)\s*', line)
+            if rev_match:
+                rev = rev_match.group(1).strip()
+            if url and rev:
+                return url, rev
+        return None, None
+
+    def unpack(self, location):
+        """Clone the Hg repository at the url to the destination location"""
+        url, rev = self.get_url_rev()
+        logger.notify('Cloning Mercurial repository %s to %s' % (url, location))
+        logger.indent += 2
+        try:
+            if os.path.exists(location):
+                os.rmdir(location)
+            call_subprocess(
+                [self.cmd, 'clone', url, location],
+                filter_stdout=self._filter, show_stdout=False)
+        finally:
+            logger.indent -= 2
+
+    def export(self, location):
+        """Export the Hg repository at the url to the destination location"""
+        temp_dir = tempfile.mkdtemp('-export', 'pip-')
+        self.unpack(temp_dir)
+        try:
+            call_subprocess(
+                [self.cmd, 'archive', location],
+                filter_stdout=self._filter, show_stdout=False, cwd=temp_dir)
+        finally:
+            shutil.rmtree(temp_dir)
+
+    def switch(self, dest, url, rev_options):
+        repo_config = os.path.join(dest, self.dirname, 'hgrc')
+        config = ConfigParser.SafeConfigParser()
+        try:
+            config.read(repo_config)
+            config.set('paths', 'default', url)
+            config_file = open(repo_config, 'w')
+            config.write(config_file)
+            config_file.close()
+        except (OSError, ConfigParser.NoSectionError), e:
+            logger.warn(
+                'Could not switch Mercurial repository to %s: %s'
+                % (url, e))
+        else:
+            call_subprocess([self.cmd, 'update', '-q'] + rev_options, cwd=dest)
+
+    def update(self, dest, rev_options):
+        call_subprocess([self.cmd, 'pull', '-q'], cwd=dest)
+        call_subprocess(
+            [self.cmd, 'update', '-q'] + rev_options, cwd=dest)
+
+    def obtain(self, dest):
+        url, rev = self.get_url_rev()
+        if rev:
+            rev_options = [rev]
+            rev_display = ' (to revision %s)' % rev
+        else:
+            rev_options = []
+            rev_display = ''
+        if self.check_destination(dest, url, rev_options, rev_display):
+            logger.notify('Cloning hg %s%s to %s'
+                          % (url, rev_display, display_path(dest)))
+            call_subprocess([self.cmd, 'clone', '--noupdate', '-q', url, dest])
+            call_subprocess([self.cmd, 'update', '-q'] + rev_options, cwd=dest)
+
+    def get_url(self, location):
+        url = call_subprocess(
+            [self.cmd, 'showconfig', 'paths.default'],
+            show_stdout=False, cwd=location).strip()
+        if url.startswith('/') or url.startswith('\\'):
+            url = path_to_url(url)
+        return url.strip()
+
+    def get_tag_revs(self, location):
+        tags = call_subprocess(
+            [self.cmd, 'tags'], show_stdout=False, cwd=location)
+        tag_revs = []
+        for line in tags.splitlines():
+            tags_match = re.search(r'([\w\d\.-]+)\s*([\d]+):.*$', line)
+            if tags_match:
+                tag = tags_match.group(1)
+                rev = tags_match.group(2)
+                tag_revs.append((rev.strip(), tag.strip()))
+        return dict(tag_revs)
+
+    def get_branch_revs(self, location):
+        branches = call_subprocess(
+            [self.cmd, 'branches'], show_stdout=False, cwd=location)
+        branch_revs = []
+        for line in branches.splitlines():
+            branches_match = re.search(r'([\w\d\.-]+)\s*([\d]+):.*$', line)
+            if branches_match:
+                branch = branches_match.group(1)
+                rev = branches_match.group(2)
+                branch_revs.append((rev.strip(), branch.strip()))
+        return dict(branch_revs)
+
+    def get_revision(self, location):
+        current_revision = call_subprocess(
+            [self.cmd, 'parents', '--template={rev}'],
+            show_stdout=False, cwd=location).strip()
+        return current_revision
+
+    def get_revision_hash(self, location):
+        current_rev_hash = call_subprocess(
+            [self.cmd, 'parents', '--template={node}'],
+            show_stdout=False, cwd=location).strip()
+        return current_rev_hash
+
+    def get_src_requirement(self, dist, location, find_tags):
+        repo = self.get_url(location)
+        if not repo.lower().startswith('hg:'):
+            repo = 'hg+' + repo
+        egg_project_name = dist.egg_name().split('-', 1)[0]
+        if not repo:
+            return None
+        current_rev = self.get_revision(location)
+        current_rev_hash = self.get_revision_hash(location)
+        tag_revs = self.get_tag_revs(location)
+        branch_revs = self.get_branch_revs(location)
+        if current_rev in tag_revs:
+            # It's a tag
+            full_egg_name = '%s-%s' % (egg_project_name, tag_revs[current_rev])
+        elif current_rev in branch_revs:
+            # It's the tip of a branch
+            full_egg_name = '%s-%s' % (dist.egg_name(), branch_revs[current_rev])
+        else:
+            full_egg_name = '%s-dev' % dist.egg_name()
+        return '%s@%s#egg=%s' % (repo, current_rev_hash, full_egg_name)
+
+vcs.register(Mercurial)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/subversion.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/subversion.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/vcs/subversion.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,260 @@
+import os
+import re
+from pip import call_subprocess
+from pip.index import Link
+from pip.util import rmtree, display_path
+from pip.log import logger
+from pip.vcs import vcs, VersionControl
+
+_svn_xml_url_re = re.compile('url="([^"]+)"')
+_svn_rev_re = re.compile('committed-rev="(\d+)"')
+_svn_url_re = re.compile(r'URL: (.+)')
+_svn_revision_re = re.compile(r'Revision: (.+)')
+
+class Subversion(VersionControl):
+    name = 'svn'
+    dirname = '.svn'
+    repo_name = 'checkout'
+    schemes = ('svn', 'svn+ssh', 'svn+http', 'svn+https')
+    bundle_file = 'svn-checkout.txt'
+    guide = ('# This was an svn checkout; to make it a checkout again run:\n'
+            'svn checkout --force -r %(rev)s %(url)s .\n')
+
+    def get_info(self, location):
+        """Returns (url, revision), where both are strings"""
+        assert not location.rstrip('/').endswith(self.dirname), 'Bad directory: %s' % location
+        output = call_subprocess(
+            [self.cmd, 'info', location], show_stdout=False, extra_environ={'LANG': 'C'})
+        match = _svn_url_re.search(output)
+        if not match:
+            logger.warn('Cannot determine URL of svn checkout %s' % display_path(location))
+            logger.info('Output that cannot be parsed: \n%s' % output)
+            return None, None
+        url = match.group(1).strip()
+        match = _svn_revision_re.search(output)
+        if not match:
+            logger.warn('Cannot determine revision of svn checkout %s' % display_path(location))
+            logger.info('Output that cannot be parsed: \n%s' % output)
+            return url, None
+        return url, match.group(1)
+
+    def parse_vcs_bundle_file(self, content):
+        for line in content.splitlines():
+            if not line.strip() or line.strip().startswith('#'):
+                continue
+            match = re.search(r'^-r\s*([^ ])?', line)
+            if not match:
+                return None, None
+            rev = match.group(1)
+            rest = line[match.end():].strip().split(None, 1)[0]
+            return rest, rev
+        return None, None
+
+    def unpack(self, location):
+        """Check out the svn repository at the url to the destination location"""
+        url, rev = self.get_url_rev()
+        logger.notify('Checking out svn repository %s to %s' % (url, location))
+        logger.indent += 2
+        try:
+            if os.path.exists(location):
+                # Subversion doesn't like to check out over an existing directory
+                # --force fixes this, but was only added in svn 1.5
+                rmtree(location)
+            call_subprocess(
+                [self.cmd, 'checkout', url, location],
+                filter_stdout=self._filter, show_stdout=False)
+        finally:
+            logger.indent -= 2
+
+    def export(self, location):
+        """Export the svn repository at the url to the destination location"""
+        url, rev = self.get_url_rev()
+        logger.notify('Exporting svn repository %s to %s' % (url, location))
+        logger.indent += 2
+        try:
+            if os.path.exists(location):
+                # Subversion doesn't like to check out over an existing directory
+                # --force fixes this, but was only added in svn 1.5
+                rmtree(location)
+            call_subprocess(
+                [self.cmd, 'export', url, location],
+                filter_stdout=self._filter, show_stdout=False)
+        finally:
+            logger.indent -= 2
+
+    def switch(self, dest, url, rev_options):
+        call_subprocess(
+            [self.cmd, 'switch'] + rev_options + [url, dest])
+
+    def update(self, dest, rev_options):
+        call_subprocess(
+            [self.cmd, 'update'] + rev_options + [dest])
+
+    def obtain(self, dest):
+        url, rev = self.get_url_rev()
+        if rev:
+            rev_options = ['-r', rev]
+            rev_display = ' (to revision %s)' % rev
+        else:
+            rev_options = []
+            rev_display = ''
+        if self.check_destination(dest, url, rev_options, rev_display):
+            logger.notify('Checking out %s%s to %s'
+                          % (url, rev_display, display_path(dest)))
+            call_subprocess(
+                [self.cmd, 'checkout', '-q'] + rev_options + [url, dest])
+
+    def get_location(self, dist, dependency_links):
+        egg_fragment_re = re.compile(r'#egg=(.*)$')
+        for url in dependency_links:
+            egg_fragment = Link(url).egg_fragment
+            if not egg_fragment:
+                continue
+            if '-' in egg_fragment:
+                ## FIXME: will this work when a package has - in the name?
+                key = '-'.join(egg_fragment.split('-')[:-1]).lower()
+            else:
+                key = egg_fragment
+            if key == dist.key:
+                return url.split('#', 1)[0]
+        return None
+
+    def get_revision(self, location):
+        """
+        Return the maximum revision for all files under a given location
+        """
+        # Note: taken from setuptools.command.egg_info
+        revision = 0
+
+        for base, dirs, files in os.walk(location):
+            if self.dirname not in dirs:
+                dirs[:] = []
+                continue    # no sense walking uncontrolled subdirs
+            dirs.remove(self.dirname)
+            entries_fn = os.path.join(base, self.dirname, 'entries')
+            if not os.path.exists(entries_fn):
+                ## FIXME: should we warn?
+                continue
+            f = open(entries_fn)
+            data = f.read()
+            f.close()
+
+            if data.startswith('8') or data.startswith('9') or data.startswith('10'):
+                data = map(str.splitlines,data.split('\n\x0c\n'))
+                del data[0][0]  # get rid of the '8'
+                dirurl = data[0][3]
+                revs = [int(d[9]) for d in data if len(d)>9 and d[9]]+[0]
+                if revs:
+                    localrev = max(revs)
+                else:
+                    localrev = 0
+            elif data.startswith('<?xml'):
+                dirurl = _svn_xml_url_re.search(data).group(1)    # get repository URL
+                revs = [int(m.group(1)) for m in _svn_rev_re.finditer(data)]+[0]
+                if revs:
+                    localrev = max(revs)
+                else:
+                    localrev = 0
+            else:
+                logger.warn("Unrecognized .svn/entries format; skipping %s", base)
+                dirs[:] = []
+                continue
+            if base == location:
+                base_url = dirurl+'/'   # save the root url
+            elif not dirurl.startswith(base_url):
+                dirs[:] = []
+                continue    # not part of the same svn tree, skip it
+            revision = max(revision, localrev)
+        return revision
+
+    def get_url_rev(self):
+        # hotfix the URL scheme after removing svn+ from svn+ssh:// readd it
+        url, rev = super(Subversion, self).get_url_rev()
+        if url.startswith('ssh://'):
+            url = 'svn+' + url
+        return url, rev
+
+    def get_url(self, location):
+        # In cases where the source is in a subdirectory, not alongside setup.py
+        # we have to look up in the location until we find a real setup.py
+        orig_location = location
+        while not os.path.exists(os.path.join(location, 'setup.py')):
+            last_location = location
+            location = os.path.dirname(location)
+            if location == last_location:
+                # We've traversed up to the root of the filesystem without finding setup.py
+                logger.warn("Could not find setup.py for directory %s (tried all parent directories)"
+                            % orig_location)
+                return None
+        f = open(os.path.join(location, self.dirname, 'entries'))
+        data = f.read()
+        f.close()
+        if data.startswith('8') or data.startswith('9') or data.startswith('10'):
+            data = map(str.splitlines,data.split('\n\x0c\n'))
+            del data[0][0]  # get rid of the '8'
+            return data[0][3]
+        elif data.startswith('<?xml'):
+            match = _svn_xml_url_re.search(data)
+            if not match:
+                raise ValueError('Badly formatted data: %r' % data)
+            return match.group(1)    # get repository URL
+        else:
+            logger.warn("Unrecognized .svn/entries format in %s" % location)
+            # Or raise exception?
+            return None
+
+    def get_tag_revs(self, svn_tag_url):
+        stdout = call_subprocess(
+            [self.cmd, 'ls', '-v', svn_tag_url], show_stdout=False)
+        results = []
+        for line in stdout.splitlines():
+            parts = line.split()
+            rev = int(parts[0])
+            tag = parts[-1].strip('/')
+            results.append((tag, rev))
+        return results
+
+    def find_tag_match(self, rev, tag_revs):
+        best_match_rev = None
+        best_tag = None
+        for tag, tag_rev in tag_revs:
+            if (tag_rev > rev and
+                (best_match_rev is None or best_match_rev > tag_rev)):
+                # FIXME: Is best_match > tag_rev really possible?
+                # or is it a sign something is wacky?
+                best_match_rev = tag_rev
+                best_tag = tag
+        return best_tag
+
+    def get_src_requirement(self, dist, location, find_tags=False):
+        repo = self.get_url(location)
+        if repo is None:
+            return None
+        parts = repo.split('/')
+        ## FIXME: why not project name?
+        egg_project_name = dist.egg_name().split('-', 1)[0]
+        rev = self.get_revision(location)
+        if parts[-2] in ('tags', 'tag'):
+            # It's a tag, perfect!
+            full_egg_name = '%s-%s' % (egg_project_name, parts[-1])
+        elif parts[-2] in ('branches', 'branch'):
+            # It's a branch :(
+            full_egg_name = '%s-%s-r%s' % (dist.egg_name(), parts[-1], rev)
+        elif parts[-1] == 'trunk':
+            # Trunk :-/
+            full_egg_name = '%s-dev_r%s' % (dist.egg_name(), rev)
+            if find_tags:
+                tag_url = '/'.join(parts[:-1]) + '/tags'
+                tag_revs = self.get_tag_revs(tag_url)
+                match = self.find_tag_match(rev, tag_revs)
+                if match:
+                    logger.notify('trunk checkout %s seems to be equivalent to tag %s' % match)
+                    repo = '%s/%s' % (tag_url, match)
+                    full_egg_name = '%s-%s' % (egg_project_name, match)
+        else:
+            # Don't know what it is
+            logger.warn('svn URL does not fit normal structure (tags/branches/trunk): %s' % repo)
+            full_egg_name = '%s-dev_r%s' % (egg_project_name, rev)
+        return 'svn+%s@%s#egg=%s' % (repo, rev, full_egg_name)
+
+vcs.register(Subversion)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/venv.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/venv.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/pip-0.7.2-py2.6.egg/pip/venv.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,52 @@
+"""Tools for working with virtualenv environments"""
+
+import os
+import sys
+import subprocess
+from pip.exceptions import BadCommand
+from pip.log import logger
+
+def restart_in_venv(venv, base, site_packages, args):
+    """
+    Restart this script using the interpreter in the given virtual environment
+    """
+    if base and not os.path.isabs(venv) and not venv.startswith('~'):
+        base = os.path.expanduser(base)
+        # ensure we have an abs basepath at this point:
+        #    a relative one makes no sense (or does it?)
+        if os.path.isabs(base):
+            venv = os.path.join(base, venv)
+
+    if venv.startswith('~'):
+        venv = os.path.expanduser(venv)
+
+    if not os.path.exists(venv):
+        try:
+            import virtualenv
+        except ImportError:
+            print 'The virtual environment does not exist: %s' % venv
+            print 'and virtualenv is not installed, so a new environment cannot be created'
+            sys.exit(3)
+        print 'Creating new virtualenv environment in %s' % venv
+        virtualenv.logger = logger
+        logger.indent += 2
+        virtualenv.create_environment(venv, site_packages=site_packages)
+    if sys.platform == 'win32':
+        python = os.path.join(venv, 'Scripts', 'python.exe')
+        # check for bin directory which is used in buildouts
+        if not os.path.exists(python):
+            python = os.path.join(venv, 'bin', 'python.exe')
+    else:
+        python = os.path.join(venv, 'bin', 'python')
+    if not os.path.exists(python):
+        python = venv
+    if not os.path.exists(python):
+        raise BadCommand('Cannot find virtual environment interpreter at %s' % python)
+    base = os.path.dirname(os.path.dirname(python))
+    file = os.path.join(os.path.dirname(__file__), 'runner.py')
+    if file.endswith('.pyc'):
+        file = file[:-1]
+    proc = subprocess.Popen(
+        [python, file] + args + [base, '___VENV_RESTART___'])
+    proc.wait()
+    sys.exit(proc.returncode)

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg
===================================================================
(Binary files differ)


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools-0.6c11-py2.6.egg
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools.pth
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools.pth	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site-packages/setuptools.pth	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+./setuptools-0.6c11-py2.6.egg

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/site.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1,701 @@
+"""Append module search paths for third-party packages to sys.path.
+
+****************************************************************
+* This module is automatically imported during initialization. *
+****************************************************************
+
+In earlier versions of Python (up to 1.5a3), scripts or modules that
+needed to use site-specific modules would place ``import site''
+somewhere near the top of their code.  Because of the automatic
+import, this is no longer necessary (but code that does it still
+works).
+
+This will append site-specific paths to the module search path.  On
+Unix, it starts with sys.prefix and sys.exec_prefix (if different) and
+appends lib/python<version>/site-packages as well as lib/site-python.
+It also supports the Debian convention of
+lib/python<version>/dist-packages.  On other platforms (mainly Mac and
+Windows), it uses just sys.prefix (and sys.exec_prefix, if different,
+but this is unlikely).  The resulting directories, if they exist, are
+appended to sys.path, and also inspected for path configuration files.
+
+FOR DEBIAN, this sys.path is augmented with directories in /usr/local.
+Local addons go into /usr/local/lib/python<version>/site-packages
+(resp. /usr/local/lib/site-python), Debian addons install into
+/usr/{lib,share}/python<version>/dist-packages.
+
+A path configuration file is a file whose name has the form
+<package>.pth; its contents are additional directories (one per line)
+to be added to sys.path.  Non-existing directories (or
+non-directories) are never added to sys.path; no directory is added to
+sys.path more than once.  Blank lines and lines beginning with
+'#' are skipped. Lines starting with 'import' are executed.
+
+For example, suppose sys.prefix and sys.exec_prefix are set to
+/usr/local and there is a directory /usr/local/lib/python2.X/site-packages
+with three subdirectories, foo, bar and spam, and two path
+configuration files, foo.pth and bar.pth.  Assume foo.pth contains the
+following:
+
+  # foo package configuration
+  foo
+  bar
+  bletch
+
+and bar.pth contains:
+
+  # bar package configuration
+  bar
+
+Then the following directories are added to sys.path, in this order:
+
+  /usr/local/lib/python2.X/site-packages/bar
+  /usr/local/lib/python2.X/site-packages/foo
+
+Note that bletch is omitted because it doesn't exist; bar precedes foo
+because bar.pth comes alphabetically before foo.pth; and spam is
+omitted because it is not mentioned in either path configuration file.
+
+After these path manipulations, an attempt is made to import a module
+named sitecustomize, which can perform arbitrary additional
+site-specific customizations.  If this import fails with an
+ImportError exception, it is silently ignored.
+
+"""
+
+import sys
+import os
+import __builtin__
+try:
+    set
+except NameError:
+    from sets import Set as set
+
+# Prefixes for site-packages; add additional prefixes like /usr/local here
+PREFIXES = [sys.prefix, sys.exec_prefix]
+# Enable per user site-packages directory
+# set it to False to disable the feature or True to force the feature
+ENABLE_USER_SITE = None
+# for distutils.commands.install
+USER_SITE = None
+USER_BASE = None
+
+_is_jython = sys.platform[:4] == 'java'
+if _is_jython:
+    ModuleType = type(os)
+
+def makepath(*paths):
+    dir = os.path.join(*paths)
+    if _is_jython and (dir == '__classpath__' or
+                       dir.startswith('__pyclasspath__')):
+        return dir, dir
+    dir = os.path.abspath(dir)
+    return dir, os.path.normcase(dir)
+
+def abs__file__():
+    """Set all module' __file__ attribute to an absolute path"""
+    for m in sys.modules.values():
+        if ((_is_jython and not isinstance(m, ModuleType)) or
+            hasattr(m, '__loader__')):
+            # only modules need the abspath in Jython. and don't mess
+            # with a PEP 302-supplied __file__
+            continue
+        f = getattr(m, '__file__', None)
+        if f is None:
+            continue
+        m.__file__ = os.path.abspath(f)
+
+def removeduppaths():
+    """ Remove duplicate entries from sys.path along with making them
+    absolute"""
+    # This ensures that the initial path provided by the interpreter contains
+    # only absolute pathnames, even if we're running from the build directory.
+    L = []
+    known_paths = set()
+    for dir in sys.path:
+        # Filter out duplicate paths (on case-insensitive file systems also
+        # if they only differ in case); turn relative paths into absolute
+        # paths.
+        dir, dircase = makepath(dir)
+        if not dircase in known_paths:
+            L.append(dir)
+            known_paths.add(dircase)
+    sys.path[:] = L
+    return known_paths
+
+# XXX This should not be part of site.py, since it is needed even when
+# using the -S option for Python.  See http://www.python.org/sf/586680
+def addbuilddir():
+    """Append ./build/lib.<platform> in case we're running in the build dir
+    (especially for Guido :-)"""
+    from distutils.util import get_platform
+    s = "build/lib.%s-%.3s" % (get_platform(), sys.version)
+    if hasattr(sys, 'gettotalrefcount'):
+        s += '-pydebug'
+    s = os.path.join(os.path.dirname(sys.path[-1]), s)
+    sys.path.append(s)
+
+def _init_pathinfo():
+    """Return a set containing all existing directory entries from sys.path"""
+    d = set()
+    for dir in sys.path:
+        try:
+            if os.path.isdir(dir):
+                dir, dircase = makepath(dir)
+                d.add(dircase)
+        except TypeError:
+            continue
+    return d
+
+def addpackage(sitedir, name, known_paths):
+    """Add a new path to known_paths by combining sitedir and 'name' or execute
+    sitedir if it starts with 'import'"""
+    if known_paths is None:
+        _init_pathinfo()
+        reset = 1
+    else:
+        reset = 0
+    fullname = os.path.join(sitedir, name)
+    try:
+        f = open(fullname, "rU")
+    except IOError:
+        return
+    try:
+        for line in f:
+            if line.startswith("#"):
+                continue
+            if line.startswith("import"):
+                exec line
+                continue
+            line = line.rstrip()
+            dir, dircase = makepath(sitedir, line)
+            if not dircase in known_paths and os.path.exists(dir):
+                sys.path.append(dir)
+                known_paths.add(dircase)
+    finally:
+        f.close()
+    if reset:
+        known_paths = None
+    return known_paths
+
+def addsitedir(sitedir, known_paths=None):
+    """Add 'sitedir' argument to sys.path if missing and handle .pth files in
+    'sitedir'"""
+    if known_paths is None:
+        known_paths = _init_pathinfo()
+        reset = 1
+    else:
+        reset = 0
+    sitedir, sitedircase = makepath(sitedir)
+    if not sitedircase in known_paths:
+        sys.path.append(sitedir)        # Add path component
+    try:
+        names = os.listdir(sitedir)
+    except os.error:
+        return
+    names.sort()
+    for name in names:
+        if name.endswith(os.extsep + "pth"):
+            addpackage(sitedir, name, known_paths)
+    if reset:
+        known_paths = None
+    return known_paths
+
+def addsitepackages(known_paths, sys_prefix=sys.prefix, exec_prefix=sys.exec_prefix):
+    """Add site-packages (and possibly site-python) to sys.path"""
+    prefixes = [os.path.join(sys_prefix, "local"), sys_prefix]
+    if exec_prefix != sys_prefix:
+        prefixes.append(os.path.join(exec_prefix, "local"))
+
+    for prefix in prefixes:
+        if prefix:
+            if sys.platform in ('os2emx', 'riscos') or _is_jython:
+                sitedirs = [os.path.join(prefix, "Lib", "site-packages")]
+            elif sys.platform == 'darwin' and prefix == sys_prefix:
+
+                if prefix.startswith("/System/Library/Frameworks/"): # Apple's Python
+
+                    sitedirs = [os.path.join("/Library/Python", sys.version[:3], "site-packages"),
+                                os.path.join(prefix, "Extras", "lib", "python")]
+
+                else: # any other Python distros on OSX work this way
+                    sitedirs = [os.path.join(prefix, "lib",
+                                             "python" + sys.version[:3], "site-packages")]
+
+            elif os.sep == '/':
+                sitedirs = [os.path.join(prefix,
+                                         "lib",
+                                         "python" + sys.version[:3],
+                                         "site-packages"),
+                            os.path.join(prefix, "lib", "site-python"),
+                            os.path.join(prefix, "python" + sys.version[:3], "lib-dynload")]
+                lib64_dir = os.path.join(prefix, "lib64", "python" + sys.version[:3], "site-packages")
+                if (os.path.exists(lib64_dir) and 
+                    os.path.realpath(lib64_dir) not in [os.path.realpath(p) for p in sitedirs]):
+                    sitedirs.append(lib64_dir)
+                try:
+                    # sys.getobjects only available in --with-pydebug build
+                    sys.getobjects
+                    sitedirs.insert(0, os.path.join(sitedirs[0], 'debug'))
+                except AttributeError:
+                    pass
+                # Debian-specific dist-packages directories:
+                sitedirs.append(os.path.join(prefix, "lib",
+                                             "python" + sys.version[:3],
+                                             "dist-packages"))
+                sitedirs.append(os.path.join(prefix, "local/lib",
+                                             "python" + sys.version[:3],
+                                             "dist-packages"))
+                sitedirs.append(os.path.join(prefix, "lib", "dist-python"))
+            else:
+                sitedirs = [prefix, os.path.join(prefix, "lib", "site-packages")]
+            if sys.platform == 'darwin':
+                # for framework builds *only* we add the standard Apple
+                # locations. Currently only per-user, but /Library and
+                # /Network/Library could be added too
+                if 'Python.framework' in prefix:
+                    home = os.environ.get('HOME')
+                    if home:
+                        sitedirs.append(
+                            os.path.join(home,
+                                         'Library',
+                                         'Python',
+                                         sys.version[:3],
+                                         'site-packages'))
+            for sitedir in sitedirs:
+                if os.path.isdir(sitedir):
+                    addsitedir(sitedir, known_paths)
+    return None
+
+def check_enableusersite():
+    """Check if user site directory is safe for inclusion
+
+    The function tests for the command line flag (including environment var),
+    process uid/gid equal to effective uid/gid.
+
+    None: Disabled for security reasons
+    False: Disabled by user (command line option)
+    True: Safe and enabled
+    """
+    if hasattr(sys, 'flags') and getattr(sys.flags, 'no_user_site', False):
+        return False
+
+    if hasattr(os, "getuid") and hasattr(os, "geteuid"):
+        # check process uid == effective uid
+        if os.geteuid() != os.getuid():
+            return None
+    if hasattr(os, "getgid") and hasattr(os, "getegid"):
+        # check process gid == effective gid
+        if os.getegid() != os.getgid():
+            return None
+
+    return True
+
+def addusersitepackages(known_paths):
+    """Add a per user site-package to sys.path
+
+    Each user has its own python directory with site-packages in the
+    home directory.
+
+    USER_BASE is the root directory for all Python versions
+
+    USER_SITE is the user specific site-packages directory
+
+    USER_SITE/.. can be used for data.
+    """
+    global USER_BASE, USER_SITE, ENABLE_USER_SITE
+    env_base = os.environ.get("PYTHONUSERBASE", None)
+
+    def joinuser(*args):
+        return os.path.expanduser(os.path.join(*args))
+
+    #if sys.platform in ('os2emx', 'riscos'):
+    #    # Don't know what to put here
+    #    USER_BASE = ''
+    #    USER_SITE = ''
+    if os.name == "nt":
+        base = os.environ.get("APPDATA") or "~"
+        if env_base:
+            USER_BASE = env_base
+        else:
+            USER_BASE = joinuser(base, "Python")
+        USER_SITE = os.path.join(USER_BASE,
+                                 "Python" + sys.version[0] + sys.version[2],
+                                 "site-packages")
+    else:
+        if env_base:
+            USER_BASE = env_base
+        else:
+            USER_BASE = joinuser("~", ".local")
+        USER_SITE = os.path.join(USER_BASE, "lib",
+                                 "python" + sys.version[:3],
+                                 "site-packages")
+
+    if ENABLE_USER_SITE and os.path.isdir(USER_SITE):
+        addsitedir(USER_SITE, known_paths)
+    if ENABLE_USER_SITE:
+        for dist_libdir in ("lib", "local/lib"):
+            user_site = os.path.join(USER_BASE, dist_libdir,
+                                     "python" + sys.version[:3],
+                                     "dist-packages")
+            if os.path.isdir(user_site):
+                addsitedir(user_site, known_paths)
+    return known_paths
+
+
+
+def setBEGINLIBPATH():
+    """The OS/2 EMX port has optional extension modules that do double duty
+    as DLLs (and must use the .DLL file extension) for other extensions.
+    The library search path needs to be amended so these will be found
+    during module import.  Use BEGINLIBPATH so that these are at the start
+    of the library search path.
+
+    """
+    dllpath = os.path.join(sys.prefix, "Lib", "lib-dynload")
+    libpath = os.environ['BEGINLIBPATH'].split(';')
+    if libpath[-1]:
+        libpath.append(dllpath)
+    else:
+        libpath[-1] = dllpath
+    os.environ['BEGINLIBPATH'] = ';'.join(libpath)
+
+
+def setquit():
+    """Define new built-ins 'quit' and 'exit'.
+    These are simply strings that display a hint on how to exit.
+
+    """
+    if os.sep == ':':
+        eof = 'Cmd-Q'
+    elif os.sep == '\\':
+        eof = 'Ctrl-Z plus Return'
+    else:
+        eof = 'Ctrl-D (i.e. EOF)'
+
+    class Quitter(object):
+        def __init__(self, name):
+            self.name = name
+        def __repr__(self):
+            return 'Use %s() or %s to exit' % (self.name, eof)
+        def __call__(self, code=None):
+            # Shells like IDLE catch the SystemExit, but listen when their
+            # stdin wrapper is closed.
+            try:
+                sys.stdin.close()
+            except:
+                pass
+            raise SystemExit(code)
+    __builtin__.quit = Quitter('quit')
+    __builtin__.exit = Quitter('exit')
+
+
+class _Printer(object):
+    """interactive prompt objects for printing the license text, a list of
+    contributors and the copyright notice."""
+
+    MAXLINES = 23
+
+    def __init__(self, name, data, files=(), dirs=()):
+        self.__name = name
+        self.__data = data
+        self.__files = files
+        self.__dirs = dirs
+        self.__lines = None
+
+    def __setup(self):
+        if self.__lines:
+            return
+        data = None
+        for dir in self.__dirs:
+            for filename in self.__files:
+                filename = os.path.join(dir, filename)
+                try:
+                    fp = file(filename, "rU")
+                    data = fp.read()
+                    fp.close()
+                    break
+                except IOError:
+                    pass
+            if data:
+                break
+        if not data:
+            data = self.__data
+        self.__lines = data.split('\n')
+        self.__linecnt = len(self.__lines)
+
+    def __repr__(self):
+        self.__setup()
+        if len(self.__lines) <= self.MAXLINES:
+            return "\n".join(self.__lines)
+        else:
+            return "Type %s() to see the full %s text" % ((self.__name,)*2)
+
+    def __call__(self):
+        self.__setup()
+        prompt = 'Hit Return for more, or q (and Return) to quit: '
+        lineno = 0
+        while 1:
+            try:
+                for i in range(lineno, lineno + self.MAXLINES):
+                    print self.__lines[i]
+            except IndexError:
+                break
+            else:
+                lineno += self.MAXLINES
+                key = None
+                while key is None:
+                    key = raw_input(prompt)
+                    if key not in ('', 'q'):
+                        key = None
+                if key == 'q':
+                    break
+
+def setcopyright():
+    """Set 'copyright' and 'credits' in __builtin__"""
+    __builtin__.copyright = _Printer("copyright", sys.copyright)
+    if _is_jython:
+        __builtin__.credits = _Printer(
+            "credits",
+            "Jython is maintained by the Jython developers (www.jython.org).")
+    else:
+        __builtin__.credits = _Printer("credits", """\
+    Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
+    for supporting Python development.  See www.python.org for more information.""")
+    here = os.path.dirname(os.__file__)
+    __builtin__.license = _Printer(
+        "license", "See http://www.python.org/%.3s/license.html" % sys.version,
+        ["LICENSE.txt", "LICENSE"],
+        [os.path.join(here, os.pardir), here, os.curdir])
+
+
+class _Helper(object):
+    """Define the built-in 'help'.
+    This is a wrapper around pydoc.help (with a twist).
+
+    """
+
+    def __repr__(self):
+        return "Type help() for interactive help, " \
+               "or help(object) for help about object."
+    def __call__(self, *args, **kwds):
+        import pydoc
+        return pydoc.help(*args, **kwds)
+
+def sethelper():
+    __builtin__.help = _Helper()
+
+def aliasmbcs():
+    """On Windows, some default encodings are not provided by Python,
+    while they are always available as "mbcs" in each locale. Make
+    them usable by aliasing to "mbcs" in such a case."""
+    if sys.platform == 'win32':
+        import locale, codecs
+        enc = locale.getdefaultlocale()[1]
+        if enc.startswith('cp'):            # "cp***" ?
+            try:
+                codecs.lookup(enc)
+            except LookupError:
+                import encodings
+                encodings._cache[enc] = encodings._unknown
+                encodings.aliases.aliases[enc] = 'mbcs'
+
+def setencoding():
+    """Set the string encoding used by the Unicode implementation.  The
+    default is 'ascii', but if you're willing to experiment, you can
+    change this."""
+    encoding = "ascii" # Default value set by _PyUnicode_Init()
+    if 0:
+        # Enable to support locale aware default string encodings.
+        import locale
+        loc = locale.getdefaultlocale()
+        if loc[1]:
+            encoding = loc[1]
+    if 0:
+        # Enable to switch off string to Unicode coercion and implicit
+        # Unicode to string conversion.
+        encoding = "undefined"
+    if encoding != "ascii":
+        # On Non-Unicode builds this will raise an AttributeError...
+        sys.setdefaultencoding(encoding) # Needs Python Unicode build !
+
+
+def execsitecustomize():
+    """Run custom site specific code, if available."""
+    try:
+        import sitecustomize
+    except ImportError:
+        pass
+
+def virtual_install_main_packages():
+    f = open(os.path.join(os.path.dirname(__file__), 'orig-prefix.txt'))
+    sys.real_prefix = f.read().strip()
+    f.close()
+    pos = 2
+    if sys.path[0] == '':
+        pos += 1
+    if sys.platform == 'win32':
+        paths = [os.path.join(sys.real_prefix, 'Lib'), os.path.join(sys.real_prefix, 'DLLs')]
+    elif _is_jython:
+        paths = [os.path.join(sys.real_prefix, 'Lib')]
+    else:
+        paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3])]
+        lib64_path = os.path.join(sys.real_prefix, 'lib64', 'python'+sys.version[:3])
+        if os.path.exists(lib64_path):
+            paths.append(lib64_path)
+        # This is hardcoded in the Python executable, but relative to sys.prefix:
+        plat_path = os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3],
+                                 'plat-%s' % sys.platform)
+        if os.path.exists(plat_path):
+            paths.append(plat_path)
+    # This is hardcoded in the Python executable, but
+    # relative to sys.prefix, so we have to fix up:
+    for path in list(paths):
+        tk_dir = os.path.join(path, 'lib-tk')
+        if os.path.exists(tk_dir):
+            paths.append(tk_dir)
+
+    # These are hardcoded in the Apple's Python executable,
+    # but relative to sys.prefix, so we have to fix them up:
+    if sys.platform == 'darwin':
+        hardcoded_paths = [os.path.join(sys.real_prefix, 'lib', 'python'+sys.version[:3], module)
+                           for module in ('plat-darwin', 'plat-mac', 'plat-mac/lib-scriptpackages')]
+
+        for path in hardcoded_paths:
+            if os.path.exists(path):
+                paths.append(path)
+
+    sys.path.extend(paths)
+
+def force_global_eggs_after_local_site_packages():
+    """
+    Force easy_installed eggs in the global environment to get placed
+    in sys.path after all packages inside the virtualenv.  This
+    maintains the "least surprise" result that packages in the
+    virtualenv always mask global packages, never the other way
+    around.
+    
+    """
+    egginsert = getattr(sys, '__egginsert', 0)
+    for i, path in enumerate(sys.path):
+        if i > egginsert and path.startswith(sys.prefix):
+            egginsert = i
+    sys.__egginsert = egginsert + 1
+    
+def virtual_addsitepackages(known_paths):
+    force_global_eggs_after_local_site_packages()
+    return addsitepackages(known_paths, sys_prefix=sys.real_prefix)
+
+def fixclasspath():
+    """Adjust the special classpath sys.path entries for Jython. These
+    entries should follow the base virtualenv lib directories.
+    """
+    paths = []
+    classpaths = []
+    for path in sys.path:
+        if path == '__classpath__' or path.startswith('__pyclasspath__'):
+            classpaths.append(path)
+        else:
+            paths.append(path)
+    sys.path = paths
+    sys.path.extend(classpaths)
+
+def execusercustomize():
+    """Run custom user specific code, if available."""
+    try:
+        import usercustomize
+    except ImportError:
+        pass
+
+
+def main():
+    global ENABLE_USER_SITE
+    virtual_install_main_packages()
+    abs__file__()
+    paths_in_sys = removeduppaths()
+    if (os.name == "posix" and sys.path and
+        os.path.basename(sys.path[-1]) == "Modules"):
+        addbuilddir()
+    if _is_jython:
+        fixclasspath()
+    GLOBAL_SITE_PACKAGES = not os.path.exists(os.path.join(os.path.dirname(__file__), 'no-global-site-packages.txt'))
+    if not GLOBAL_SITE_PACKAGES:
+        ENABLE_USER_SITE = False
+    if ENABLE_USER_SITE is None:
+        ENABLE_USER_SITE = check_enableusersite()
+    paths_in_sys = addsitepackages(paths_in_sys)
+    paths_in_sys = addusersitepackages(paths_in_sys)
+    if GLOBAL_SITE_PACKAGES:
+        paths_in_sys = virtual_addsitepackages(paths_in_sys)
+    if sys.platform == 'os2emx':
+        setBEGINLIBPATH()
+    setquit()
+    setcopyright()
+    sethelper()
+    aliasmbcs()
+    setencoding()
+    execsitecustomize()
+    if ENABLE_USER_SITE:
+        execusercustomize()
+    # Remove sys.setdefaultencoding() so that users cannot change the
+    # encoding after initialization.  The test for presence is needed when
+    # this module is run as a script, because this code is executed twice.
+    if hasattr(sys, "setdefaultencoding"):
+        del sys.setdefaultencoding
+
+main()
+
+def _script():
+    help = """\
+    %s [--user-base] [--user-site]
+
+    Without arguments print some useful information
+    With arguments print the value of USER_BASE and/or USER_SITE separated
+    by '%s'.
+
+    Exit codes with --user-base or --user-site:
+      0 - user site directory is enabled
+      1 - user site directory is disabled by user
+      2 - uses site directory is disabled by super user
+          or for security reasons
+     >2 - unknown error
+    """
+    args = sys.argv[1:]
+    if not args:
+        print "sys.path = ["
+        for dir in sys.path:
+            print "    %r," % (dir,)
+        print "]"
+        def exists(path):
+            if os.path.isdir(path):
+                return "exists"
+            else:
+                return "doesn't exist"
+        print "USER_BASE: %r (%s)" % (USER_BASE, exists(USER_BASE))
+        print "USER_SITE: %r (%s)" % (USER_SITE, exists(USER_BASE))
+        print "ENABLE_USER_SITE: %r" %  ENABLE_USER_SITE
+        sys.exit(0)
+
+    buffer = []
+    if '--user-base' in args:
+        buffer.append(USER_BASE)
+    if '--user-site' in args:
+        buffer.append(USER_SITE)
+
+    if buffer:
+        print os.pathsep.join(buffer)
+        if ENABLE_USER_SITE:
+            sys.exit(0)
+        elif ENABLE_USER_SITE is False:
+            sys.exit(1)
+        elif ENABLE_USER_SITE is None:
+            sys.exit(2)
+        else:
+            sys.exit(3)
+    else:
+        import textwrap
+        print textwrap.dedent(help % (sys.argv[0], os.pathsep))
+        sys.exit(10)
+
+if __name__ == '__main__':
+    _script()

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/sre.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_compile.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_compile.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_compile.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/sre_compile.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_compile.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_constants.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_constants.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_constants.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/sre_constants.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_constants.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_parse.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_parse.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_parse.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/sre_parse.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/sre_parse.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/stat.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/stat.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/stat.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/stat.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/stat.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/types.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/types.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/types.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/types.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/types.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/warnings.py
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/lib/python2.6/warnings.py	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/lib/python2.6/warnings.py	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+link /opt/python-2.6.4/lib/python2.6/warnings.py
\ No newline at end of file


Property changes on: zopeorg.buildout/branches/beta.zope.org/lib/python2.6/warnings.py
___________________________________________________________________
Added: svn:special
   + *

Added: zopeorg.buildout/branches/beta.zope.org/src/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/src/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/src/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+Packages in eggs that you develop should go in this directory

Added: zopeorg.buildout/branches/beta.zope.org/var/README.txt
===================================================================
--- zopeorg.buildout/branches/beta.zope.org/var/README.txt	                        (rev 0)
+++ zopeorg.buildout/branches/beta.zope.org/var/README.txt	2011-05-09 12:32:56 UTC (rev 121636)
@@ -0,0 +1 @@
+This directory contains the Data.fs ZODB data storage, and other runtime files



More information about the checkins mailing list