[Checkins] SVN: z3c.rest/trunk/ Okay, I am back working on REST again. ; -) This time I am less

Stephan Richter srichter at cosmos.phy.tufts.edu
Fri Nov 30 06:40:13 EST 2007


Log message for revision 82045:
  Okay, I am back working on REST again. ;-) This time I am less 
  ambitious.
  
  I have a special publisher for REST and a special request. The code is 
  still experimental, but I discovered already several flaws during 
  testing, so it is getting better. I also have a little demo for 
  folders that provides a very simple RESTive API.
  
  I also developed a REST client that is somewhat similar to test 
  browser. It works very well and can be used in real applications as 
  well.
  
  Everything is 100% tested!
  
  Thanks to Bayview Financial for allowing me to develop this code under 
  the ZPL and publish it to svn.zope.org.
  
  

Changed:
  A   z3c.rest/trunk/
  A   z3c.rest/trunk/.installed.cfg
  A   z3c.rest/trunk/CHANGES.txt
  A   z3c.rest/trunk/README.txt
  A   z3c.rest/trunk/bin/
  A   z3c.rest/trunk/bin/buildout
  A   z3c.rest/trunk/bin/coverage
  A   z3c.rest/trunk/bin/coveragediff
  A   z3c.rest/trunk/bin/demo
  A   z3c.rest/trunk/bin/test
  A   z3c.rest/trunk/bootstrap.py
  A   z3c.rest/trunk/buildout.cfg
  A   z3c.rest/trunk/coverage/
  A   z3c.rest/trunk/coverage/report/
  A   z3c.rest/trunk/coverage/report/all.html
  A   z3c.rest/trunk/coverage/report/z3c.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.__init__.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.client.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.interfaces.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.null.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.rest.html
  A   z3c.rest/trunk/coverage/report/z3c.rest.traverser.html
  A   z3c.rest/trunk/coverage/z3c.rest.__init__.cover
  A   z3c.rest/trunk/coverage/z3c.rest.client.cover
  A   z3c.rest/trunk/coverage/z3c.rest.interfaces.cover
  A   z3c.rest/trunk/coverage/z3c.rest.null.cover
  A   z3c.rest/trunk/coverage/z3c.rest.rest.cover
  A   z3c.rest/trunk/coverage/z3c.rest.testing.cover
  A   z3c.rest/trunk/coverage/z3c.rest.tests.__init__.cover
  A   z3c.rest/trunk/coverage/z3c.rest.tests.folder.cover
  A   z3c.rest/trunk/coverage/z3c.rest.tests.test.cover
  A   z3c.rest/trunk/coverage/z3c.rest.traverser.cover
  A   z3c.rest/trunk/develop-eggs/
  A   z3c.rest/trunk/develop-eggs/z3c.rest.egg-link
  A   z3c.rest/trunk/parts/
  A   z3c.rest/trunk/parts/database/
  A   z3c.rest/trunk/parts/database/Data.fs
  A   z3c.rest/trunk/parts/database/Data.fs.index
  A   z3c.rest/trunk/parts/database/Data.fs.lock
  A   z3c.rest/trunk/parts/demo/
  A   z3c.rest/trunk/parts/demo/zdaemon.conf
  A   z3c.rest/trunk/parts/demo/zope.conf
  A   z3c.rest/trunk/parts/form-demo-app/
  A   z3c.rest/trunk/parts/form-demo-app/debugzope
  A   z3c.rest/trunk/parts/form-demo-app/runzope
  A   z3c.rest/trunk/parts/form-demo-app/site.zcml
  A   z3c.rest/trunk/parts/test/
  A   z3c.rest/trunk/rest.prof
  A   z3c.rest/trunk/setup.py
  A   z3c.rest/trunk/src/
  A   z3c.rest/trunk/src/z3c/
  A   z3c.rest/trunk/src/z3c/__init__.py
  A   z3c.rest/trunk/src/z3c/rest/
  A   z3c.rest/trunk/src/z3c/rest/README.txt
  A   z3c.rest/trunk/src/z3c/rest/__init__.py
  A   z3c.rest/trunk/src/z3c/rest/application.zcml
  A   z3c.rest/trunk/src/z3c/rest/client.py
  A   z3c.rest/trunk/src/z3c/rest/client.txt
  A   z3c.rest/trunk/src/z3c/rest/configure.zcml
  A   z3c.rest/trunk/src/z3c/rest/interfaces.py
  A   z3c.rest/trunk/src/z3c/rest/null.py
  A   z3c.rest/trunk/src/z3c/rest/null.txt
  A   z3c.rest/trunk/src/z3c/rest/rest.py
  A   z3c.rest/trunk/src/z3c/rest/rest.txt
  A   z3c.rest/trunk/src/z3c/rest/testing.py
  A   z3c.rest/trunk/src/z3c/rest/tests/
  A   z3c.rest/trunk/src/z3c/rest/tests/__init__.py
  A   z3c.rest/trunk/src/z3c/rest/tests/folder.pt
  A   z3c.rest/trunk/src/z3c/rest/tests/folder.py
  A   z3c.rest/trunk/src/z3c/rest/tests/folder.zcml
  A   z3c.rest/trunk/src/z3c/rest/tests/ftesting.zcml
  A   z3c.rest/trunk/src/z3c/rest/tests/test.py
  A   z3c.rest/trunk/src/z3c/rest/traverser.py
  A   z3c.rest/trunk/src/z3c/rest/traverser.txt
  A   z3c.rest/trunk/src/z3c/rest/twist.py
  A   z3c.rest/trunk/src/z3c/rest/zserver.py
  A   z3c.rest/trunk/src/z3c.rest.egg-info/
  A   z3c.rest/trunk/src/z3c.rest.egg-info/PKG-INFO
  A   z3c.rest/trunk/src/z3c.rest.egg-info/SOURCES.txt
  A   z3c.rest/trunk/src/z3c.rest.egg-info/dependency_links.txt
  A   z3c.rest/trunk/src/z3c.rest.egg-info/namespace_packages.txt
  A   z3c.rest/trunk/src/z3c.rest.egg-info/not-zip-safe
  A   z3c.rest/trunk/src/z3c.rest.egg-info/requires.txt
  A   z3c.rest/trunk/src/z3c.rest.egg-info/top_level.txt

-=-
Added: z3c.rest/trunk/.installed.cfg
===================================================================
--- z3c.rest/trunk/.installed.cfg	                        (rev 0)
+++ z3c.rest/trunk/.installed.cfg	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,178 @@
+[buildout]
+installed_develop_eggs = /opt/zope/packages/z3c.rest/develop-eggs/z3c.rest.egg-link
+parts = test coverage database form-demo-app demo
+
+[test]
+__buildout_installed__ = /opt/zope/packages/z3c.rest/parts/test
+	/opt/zope/packages/z3c.rest/bin/test
+__buildout_signature__ = zc.recipe.testrunner-1.0.0-py2.4.egg zc.recipe.egg-1.0.0-py2.4.egg setuptools-0.6c7-py2.4.egg zope.testing-3.5.1-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg
+_b = /opt/zope/packages/z3c.rest/bin
+_d = /opt/zope/packages/z3c.rest/develop-eggs
+_e = /opt/zope/packages/eggs
+bin-directory = /opt/zope/packages/z3c.rest/bin
+develop-eggs-directory = /opt/zope/packages/z3c.rest/develop-eggs
+eggs = z3c.rest [app, test]
+eggs-directory = /opt/zope/packages/eggs
+executable = /usr/bin/py24
+index = http://download.zope.org/zope3.4
+location = /opt/zope/packages/z3c.rest/parts/test
+recipe = zc.recipe.testrunner
+script = /opt/zope/packages/z3c.rest/bin/test
+
+[coverage]
+__buildout_installed__ = /opt/zope/packages/z3c.rest/bin/coverage
+	/opt/zope/packages/z3c.rest/bin/coveragediff
+__buildout_signature__ = zc.recipe.egg-1.0.0-py2.4.egg setuptools-0.6c7-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg
+_b = /opt/zope/packages/z3c.rest/bin
+_d = /opt/zope/packages/z3c.rest/develop-eggs
+_e = /opt/zope/packages/eggs
+bin-directory = /opt/zope/packages/z3c.rest/bin
+develop-eggs-directory = /opt/zope/packages/z3c.rest/develop-eggs
+eggs = z3c.coverage
+eggs-directory = /opt/zope/packages/eggs
+executable = /usr/bin/py24
+index = http://download.zope.org/zope3.4
+recipe = zc.recipe.egg
+
+[database]
+__buildout_installed__ = 
+__buildout_signature__ = zc.recipe.filestorage-1.0.0-py2.4.egg setuptools-0.6c7-py2.4.egg zope.testing-3.5.1-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg
+blob-dir = 
+path = /opt/zope/packages/z3c.rest/parts/database/Data.fs
+recipe = zc.recipe.filestorage
+zconfig = <zodb>
+	%(__buildout_space__)s%(__buildout_space__)s<filestorage>
+	%(__buildout_space__)s%(__buildout_space__)s%(__buildout_space__)s%(__buildout_space__)spath /opt/zope/packages/z3c.rest/parts/database/Data.fs
+	%(__buildout_space__)s%(__buildout_space__)s</filestorage>
+	</zodb>%(__buildout_space_n__)s
+
+[form-demo-app]
+__buildout_installed__ = /opt/zope/packages/z3c.rest/parts/form-demo-app
+__buildout_signature__ = zc.zope3recipes-0.6.0-py2.4.egg ZConfig-2.5-py2.4.egg zc.recipe.egg-1.0.0-py2.4.egg setuptools-0.6c7-py2.4.egg zope.testing-3.5.1-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg
+_b = /opt/zope/packages/z3c.rest/bin
+_d = /opt/zope/packages/z3c.rest/develop-eggs
+_e = /opt/zope/packages/eggs
+bin-directory = /opt/zope/packages/z3c.rest/bin
+develop-eggs-directory = /opt/zope/packages/z3c.rest/develop-eggs
+eggs = z3c.rest [app]
+eggs-directory = /opt/zope/packages/eggs
+executable = /usr/bin/py24
+index = http://download.zope.org/zope3.4
+location = /opt/zope/packages/z3c.rest/parts/form-demo-app
+recipe = zc.zope3recipes:app
+scripts = 
+servers = twisted
+site.zcml = <include package="z3c.rest" file="application.zcml" />
+zope3-location = /opt/zope/packages/z3c.rest/.
+
+[demo]
+__buildout_installed__ = /opt/zope/packages/z3c.rest/parts/demo
+	/opt/zope/packages/z3c.rest/bin/demo
+__buildout_signature__ = zc.zope3recipes-0.6.0-py2.4.egg ZConfig-2.5-py2.4.egg zc.recipe.egg-1.0.0-py2.4.egg setuptools-0.6c7-py2.4.egg zope.testing-3.5.1-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg zc.buildout-1.0.0b31-py2.4.egg
+_b = /opt/zope/packages/z3c.rest/bin
+_d = /opt/zope/packages/z3c.rest/develop-eggs
+_e = /opt/zope/packages/eggs
+application = form-demo-app
+application-location = /opt/zope/packages/z3c.rest/parts/form-demo-app
+bin-directory = /opt/zope/packages/z3c.rest/bin
+develop-eggs-directory = /opt/zope/packages/z3c.rest/develop-eggs
+eggs = zdaemon
+	setuptools
+eggs-directory = /opt/zope/packages/eggs
+executable = /usr/bin/py24
+index = http://download.zope.org/zope3.4
+recipe = zc.zope3recipes:instance
+run-directory = /opt/zope/packages/z3c.rest/parts/demo
+scripts = 
+servers = twisted
+zope.conf = <zodb>
+	%(__buildout_space__)s%(__buildout_space__)s<filestorage>
+	%(__buildout_space__)s%(__buildout_space__)s%(__buildout_space__)s%(__buildout_space__)spath /opt/zope/packages/z3c.rest/parts/database/Data.fs
+	%(__buildout_space__)s%(__buildout_space__)s</filestorage>
+	</zodb>
+	%(__buildout_space_n__)s<server>
+	type HTTP
+	address 8080
+	</server>
+	<server>
+	type REST-HTTP
+	address 8081
+	</server>
+
+[buildout]
+parts = coverage database form-demo-app demo test
+
+[buildout]
+parts = database form-demo-app demo test coverage
+
+[buildout]
+installed_develop_eggs = /opt/zope/packages/z3c.rest/develop-eggs/z3c.rest.egg-link
+
+[buildout]
+parts = form-demo-app demo test coverage database
+
+[buildout]
+parts = demo test coverage database form-demo-app
+
+[buildout]
+parts = test coverage database form-demo-app demo
+
+[buildout]
+parts = coverage database form-demo-app demo test
+
+[buildout]
+parts = database form-demo-app demo test coverage
+
+[buildout]
+installed_develop_eggs = /opt/zope/packages/z3c.rest/develop-eggs/z3c.rest.egg-link
+
+[buildout]
+parts = form-demo-app demo test coverage database
+
+[buildout]
+parts = demo test coverage database form-demo-app
+
+[buildout]
+parts = test coverage database form-demo-app demo
+
+[buildout]
+parts = coverage database form-demo-app demo test
+
+[buildout]
+parts = database form-demo-app demo test coverage
+
+[buildout]
+installed_develop_eggs = /opt/zope/packages/z3c.rest/develop-eggs/z3c.rest.egg-link
+
+[buildout]
+parts = form-demo-app demo test coverage database
+
+[buildout]
+parts = demo test coverage database form-demo-app
+
+[buildout]
+parts = test coverage database form-demo-app demo
+
+[buildout]
+parts = coverage database form-demo-app demo test
+
+[buildout]
+parts = database form-demo-app demo test coverage
+
+[buildout]
+installed_develop_eggs = /opt/zope/packages/z3c.rest/develop-eggs/z3c.rest.egg-link
+
+[buildout]
+parts = form-demo-app demo test coverage database
+
+[buildout]
+parts = demo test coverage database form-demo-app
+
+[buildout]
+parts = test coverage database form-demo-app demo
+
+[buildout]
+parts = coverage database form-demo-app demo test
+
+[buildout]
+parts = database form-demo-app demo test coverage

Added: z3c.rest/trunk/CHANGES.txt
===================================================================
--- z3c.rest/trunk/CHANGES.txt	                        (rev 0)
+++ z3c.rest/trunk/CHANGES.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,16 @@
+=======
+CHANGES
+=======
+
+Version 0.1.0 (2007-12-??)
+--------------------------
+
+- Initial Release
+
+  * Publisher hooks to build dedicated REST servers
+
+  * Simple REST traverser
+
+  * REST client
+
+  * Minimal sample application


Property changes on: z3c.rest/trunk/CHANGES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/README.txt
===================================================================
--- z3c.rest/trunk/README.txt	                        (rev 0)
+++ z3c.rest/trunk/README.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+This package provides a framework to build REST APIs on top of Zope 3.


Property changes on: z3c.rest/trunk/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/bin/buildout
===================================================================
--- z3c.rest/trunk/bin/buildout	                        (rev 0)
+++ z3c.rest/trunk/bin/buildout	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,12 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  '/opt/zope/packages/eggs/zc.buildout-1.0.0b31-py2.4.egg',
+  ]
+
+import zc.buildout.buildout
+
+if __name__ == '__main__':
+    zc.buildout.buildout.main()


Property changes on: z3c.rest/trunk/bin/buildout
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/bin/coverage
===================================================================
--- z3c.rest/trunk/bin/coverage	                        (rev 0)
+++ z3c.rest/trunk/bin/coverage	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,12 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/eggs/z3c.coverage-1.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  ]
+
+import z3c.coverage.coveragereport
+
+if __name__ == '__main__':
+    z3c.coverage.coveragereport.main()


Property changes on: z3c.rest/trunk/bin/coverage
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/bin/coveragediff
===================================================================
--- z3c.rest/trunk/bin/coveragediff	                        (rev 0)
+++ z3c.rest/trunk/bin/coveragediff	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,12 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/eggs/z3c.coverage-1.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  ]
+
+import z3c.coverage.coveragediff
+
+if __name__ == '__main__':
+    z3c.coverage.coveragediff.main()


Property changes on: z3c.rest/trunk/bin/coveragediff
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/bin/demo
===================================================================
--- z3c.rest/trunk/bin/demo	                        (rev 0)
+++ z3c.rest/trunk/bin/demo	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,19 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/eggs/zdaemon-2.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  '/opt/zope/packages/eggs/ZConfig-2.5-py2.4.egg',
+  '/opt/zope/packages/eggs/zc.zope3recipes-0.6.0-py2.4.egg',
+  ]
+
+import zc.zope3recipes.ctl
+
+if __name__ == '__main__':
+    zc.zope3recipes.ctl.main([
+        '/opt/zope/packages/z3c.rest/parts/form-demo-app/debugzope',
+        '/opt/zope/packages/z3c.rest/parts/demo/zope.conf',
+        '-C', '/opt/zope/packages/z3c.rest/parts/demo/zdaemon.conf',
+        ]+sys.argv[1:]
+        )


Property changes on: z3c.rest/trunk/bin/demo
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/bin/test
===================================================================
--- z3c.rest/trunk/bin/test	                        (rev 0)
+++ z3c.rest/trunk/bin/test	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,108 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/z3c.rest/src',
+  '/opt/zope/packages/eggs/zope.testing-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.testing-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/z3c.etestbrowser-1.0.4-py2.4.egg',
+  '/opt/zope/packages/eggs/z3c.coverage-1.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.contentprovider-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zcmlfiles-3.4.3-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.wsgi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.twisted-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.securitypolicy-3.4.6-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.form-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.container-3.5.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.authentication-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.appsetup-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/lxml-1.3.6-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.i18n-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deferredimport-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.folder-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.dependable-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.debug-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.annotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.testbrowser-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.location-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.event-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.formlib-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.rotterdam-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.basicskin-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.principalannotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zopeappgenerations-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.locales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.i18n-3.4.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.interface-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.generations-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.content-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.modulealias-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/ZConfig-2.5-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zapi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.server-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.applicationcontrol-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.exceptions-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.copypastemove-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zdaemon-2.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.i18nmessageid-3.4.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.configuration-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deprecation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.exception-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.http-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.datetime-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.contenttype-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.proxy-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.cachedescriptors-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.broken-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.size-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.filerepresentation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.lifecycleevent-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dottedname-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.thread-3.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.session-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/pytz-2007g-py2.4.egg',
+  '/opt/zope/packages/eggs/ClientForm-0.2.7-py2.4.egg',
+  '/opt/zope/packages/eggs/mechanize-0.1.7b-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zodbcode-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.renderer-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.server-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.hookable-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.session-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.minmax-1.1.0-py2.4.egg',
+  '/opt/zope/packages/eggs/RestrictedPython-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.structuredtext-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/docutils-0.4-py2.4.egg',
+  ]
+
+import os
+sys.argv[0] = os.path.abspath(sys.argv[0])
+os.chdir('/opt/zope/packages/z3c.rest/parts/test')
+
+
+import zope.testing.testrunner
+
+if __name__ == '__main__':
+    zope.testing.testrunner.run([
+  '--test-path', '/opt/zope/packages/z3c.rest/src',
+  ])


Property changes on: z3c.rest/trunk/bin/test
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/bootstrap.py
===================================================================
--- z3c.rest/trunk/bootstrap.py	                        (rev 0)
+++ z3c.rest/trunk/bootstrap.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,52 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""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$
+"""
+
+import os, shutil, sys, tempfile, urllib2
+
+tmpeggs = tempfile.mkdtemp()
+
+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
+
+cmd = 'from setuptools.command.easy_install import main; main()'
+if sys.platform == 'win32':
+    cmd = '"%s"' % cmd # work around spawn lamosity on windows
+
+ws = pkg_resources.working_set
+assert os.spawnle(
+    os.P_WAIT, sys.executable, sys.executable,
+    '-c', cmd, '-mqNxd', 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)


Property changes on: z3c.rest/trunk/bootstrap.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/buildout.cfg
===================================================================
--- z3c.rest/trunk/buildout.cfg	                        (rev 0)
+++ z3c.rest/trunk/buildout.cfg	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,37 @@
+[buildout]
+develop = .
+index = http://download.zope.org/zope3.4
+parts = demo test coverage
+
+[test]
+recipe = zc.recipe.testrunner
+eggs = z3c.rest [app, test]
+
+[coverage]
+recipe = zc.recipe.egg
+eggs = z3c.coverage
+
+[zope3]
+location = .
+
+[form-demo-app]
+recipe = zc.zope3recipes:app
+site.zcml = <include package="z3c.rest" file="application.zcml" />
+eggs = z3c.rest [app]
+
+[demo]
+recipe = zc.zope3recipes:instance
+application = form-demo-app
+zope.conf = ${database:zconfig}
+  <server>
+    type HTTP
+    address 8080
+  </server>
+
+  <server>
+    type REST-HTTP
+    address 8081
+  </server>
+
+[database]
+recipe = zc.recipe.filestorage

Added: z3c.rest/trunk/coverage/report/all.html
===================================================================
--- z3c.rest/trunk/coverage/report/all.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/all.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,29 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.traverser.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;traverser.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.interfaces.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interfaces.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 58 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 50 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.client.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 128 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.null.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.__init__.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__init__.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 0 uncovered)</td></tr>
+</table><hr/>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,23 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+</table><hr/>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.__init__.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.__init__.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.__init__.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,27 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.__init__</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.__init__</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.__init__.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__init__.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 0 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222"># Make a package
+</FONT></I></pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.client.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.client.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.client.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,227 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.client</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.client</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.client.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 128 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># Copyright (c) 2007 Zope Corporation and Contributors.
+</FONT></I>       <I><FONT COLOR="#B22222"># All Rights Reserved.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># This software is subject to the provisions of the Zope Public License,
+</FONT></I>       <I><FONT COLOR="#B22222"># Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+</FONT></I>       <I><FONT COLOR="#B22222"># THIS SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ANY AND ALL EXPRESS OR IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+</FONT></I>       <I><FONT COLOR="#B22222"># FOR A PARTICULAR PURPOSE.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;REST Client
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: &quot;&quot;&quot;</FONT></B>
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> lxml
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> httplib
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> socket
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> urllib
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> urlparse
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> base64
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.interface
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> z3c.rest <B><FONT COLOR="#A020F0">import</FONT></B> interfaces
+       
+    1: <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">isRelativeURL</FONT></B>(url):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Determines whether the given URL is a relative path segment.&quot;&quot;&quot;</FONT></B>
+   37:     pieces = urlparse.urlparse(url)
+   37:     <B><FONT COLOR="#A020F0">if</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> pieces[0] <B><FONT COLOR="#A020F0">and</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> pieces[1]:
+    5:         <B><FONT COLOR="#A020F0">return</FONT></B> True
+   32:     <B><FONT COLOR="#A020F0">return</FONT></B> False
+       
+    1: <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">absoluteURL</FONT></B>(base, url):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Convertes a URL to an absolute URL given a base.&quot;&quot;&quot;</FONT></B>
+   37:     <B><FONT COLOR="#A020F0">if</FONT></B> isRelativeURL(url):
+    5:         fullUrl = urlparse.urljoin(base, url)
+           <B><FONT COLOR="#A020F0">else</FONT></B>:
+   32:         fullUrl = url
+   37:     pieces = list(urlparse.urlparse(fullUrl))
+   37:     <B><FONT COLOR="#A020F0">if</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> pieces[2].endswith(<B><FONT COLOR="#BC8F8F">'/'</FONT></B>):
+   18:         pieces[2] += <B><FONT COLOR="#BC8F8F">'/'</FONT></B>
+   37:     <B><FONT COLOR="#A020F0">return</FONT></B> urlparse.urlunparse(pieces)
+       
+    1: <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">getFullPath</FONT></B>(pieces, params):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Build a full httplib request path, including a query string.&quot;&quot;&quot;</FONT></B>
+   32:     query = <B><FONT COLOR="#BC8F8F">''</FONT></B>
+   32:     <B><FONT COLOR="#A020F0">if</FONT></B> pieces[4]:
+    2:         query = pieces[4]
+   32:     <B><FONT COLOR="#A020F0">if</FONT></B> params:
+    2:         encParams = urllib.urlencode(params)
+    2:         <B><FONT COLOR="#A020F0">if</FONT></B> query:
+    1:             query += <B><FONT COLOR="#BC8F8F">'&amp;'</FONT></B> + encParams
+               <B><FONT COLOR="#A020F0">else</FONT></B>:
+    1:             query = encParams
+   32:     <B><FONT COLOR="#A020F0">return</FONT></B> urlparse.urlunparse(
+               (<B><FONT COLOR="#BC8F8F">''</FONT></B>, <B><FONT COLOR="#BC8F8F">''</FONT></B>, pieces[2], pieces[3], query, pieces[5]))
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> XLink(object):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;A link implementation for simple XLinks.&quot;&quot;&quot;</FONT></B>
+    1:     zope.interface.implements(interfaces.ILink)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, client, title, url):
+    5:         self._client = client
+    5:         self.title = title
+    5:         self.url = url
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">click</FONT></B>(self):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;See interfaces.ILink&quot;&quot;&quot;</FONT></B>
+    3:         self._client.get(self.url)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__repr__</FONT></B>(self):
+    2:         <B><FONT COLOR="#A020F0">return</FONT></B> <B><FONT COLOR="#BC8F8F">'&lt;%s title=%r url=%r&gt;'</FONT></B> %(
+                   self.__class__.__name__, self.title, self.url)
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> RESTClient(object):
+    1:     zope.interface.implements(interfaces.IRESTClient)
+       
+    1:     connectionFactory = httplib.HTTPConnection
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, url=None):
+    3:         self.requestHeaders = {}
+    3:         self._reset()
+    3:         self._history = []
+    3:         self._requestData = None
+    3:         self.url = <B><FONT COLOR="#BC8F8F">''</FONT></B>
+    3:         <B><FONT COLOR="#A020F0">if</FONT></B> url:
+    1:             self.open(url)
+       
+    1:     @property
+           <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">fullStatus</FONT></B>(self):
+   12:         <B><FONT COLOR="#A020F0">return</FONT></B> <B><FONT COLOR="#BC8F8F">'%i %s'</FONT></B> %(self.status, self.reason)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">_reset</FONT></B>(self):
+   35:         self.headers = []
+   35:         self.contents = {}
+   35:         self.status = None
+   35:         self.reason = None
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">open</FONT></B>(self, url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=None, params=None, headers=None, method=<B><FONT COLOR="#BC8F8F">'GET'</FONT></B>):
+               <I><FONT COLOR="#B22222"># Create a correct absolute URL and set it.
+</FONT></I>   32:         self.url = absoluteURL(self.url, url)
+       
+               <I><FONT COLOR="#B22222"># Create the full set of request headers
+</FONT></I>   32:         requestHeaders = self.requestHeaders.copy()
+   32:         <B><FONT COLOR="#A020F0">if</FONT></B> headers:
+    1:             requestHeaders.update(headers)
+       
+               <I><FONT COLOR="#B22222"># Let's now reset all response values
+</FONT></I>   32:         self._reset()
+       
+               <I><FONT COLOR="#B22222"># Store all the request data
+</FONT></I>   32:         self._requestData = (url, data, params, headers, method)
+       
+               <I><FONT COLOR="#B22222"># Make a connection and retrieve the result
+</FONT></I>   32:         pieces = urlparse.urlparse(self.url)
+   32:         connection = self.connectionFactory(pieces[1])
+   32:         <B><FONT COLOR="#A020F0">try</FONT></B>:
+   32:             connection.request(
+                       method, getFullPath(pieces, params), data, requestHeaders)
+   30:             response = connection.getresponse()
+   30:             connection.close()
+    2:         <B><FONT COLOR="#A020F0">except</FONT></B> socket.error, e:
+    1:             connection.close()
+    1:             self.status, self.reason = e.args
+    1:             self._addHistory()
+    1:             <B><FONT COLOR="#A020F0">raise</FONT></B> e
+               <B><FONT COLOR="#A020F0">else</FONT></B>:
+   30:             self.headers = response.getheaders()
+   30:             self.contents = response.read()
+   30:             self.status = response.status
+   30:             self.reason = response.reason
+   30:             self._addHistory()
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">get</FONT></B>(self, url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+   17:         self.open(url, None, params, headers)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">put</FONT></B>(self, url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+    6:         self.open(url, data, params, headers, <B><FONT COLOR="#BC8F8F">'PUT'</FONT></B>)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">post</FONT></B>(self, url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+    1:         self.open(url, data, params, headers, <B><FONT COLOR="#BC8F8F">'POST'</FONT></B>)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">delete</FONT></B>(self, url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+    4:         self.open(url, None, params, headers, <B><FONT COLOR="#BC8F8F">'DELETE'</FONT></B>)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">setCredentials</FONT></B>(self, username, password):
+    1:         creds = username + u<B><FONT COLOR="#BC8F8F">':'</FONT></B> + password
+    1:         creds = <B><FONT COLOR="#BC8F8F">&quot;Basic &quot;</FONT></B> + base64.encodestring(creds.encode(<B><FONT COLOR="#BC8F8F">'utf-8'</FONT></B>)).strip()
+    1:         self.requestHeaders[<B><FONT COLOR="#BC8F8F">'Authorization'</FONT></B>] = creds
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">_addHistory</FONT></B>(self):
+   31:         self._history.append((
+                   self.url, self.requestHeaders, self.headers, self.contents,
+                   self.status, self.reason, self._requestData
+                   ))
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">goBack</FONT></B>(self, count=1):
+               <I><FONT COLOR="#B22222"># The user really does not want to go back.
+</FONT></I>    4:         <B><FONT COLOR="#A020F0">if</FONT></B> count == 0:
+    1:             <B><FONT COLOR="#A020F0">return</FONT></B>
+               <I><FONT COLOR="#B22222"># The user wants to reach before a pre-historical state.
+</FONT></I>    3:         <B><FONT COLOR="#A020F0">if</FONT></B> len(self._history) &lt; count:
+    1:             <B><FONT COLOR="#A020F0">raise</FONT></B> ValueError(<B><FONT COLOR="#BC8F8F">'There is not enough history.'</FONT></B>)
+               <I><FONT COLOR="#B22222"># Let's now get the entry and set the history back to that state.
+</FONT></I>    2:         entry = self._history[-(count+1)]
+    2:         self._history = self._history[:-count]
+               <I><FONT COLOR="#B22222"># Reset the state.
+</FONT></I>    2:         (self.url, self.requestHeaders, self.headers, self.contents,
+                self.status, self.reason, self._requestData) = entry
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">reload</FONT></B>(self):
+    1:         self.open(*self._requestData)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">getLink</FONT></B>(self, title=None, url=None, index=0):
+    6:         nsmap = {<B><FONT COLOR="#BC8F8F">'xlink'</FONT></B>: <B><FONT COLOR="#BC8F8F">&quot;http://www.w3.org/1999/xlink&quot;</FONT></B>}
+    6:         tree = lxml.etree.fromstring(self.contents)
+    6:         res = []
+    6:         <B><FONT COLOR="#A020F0">if</FONT></B> title <B><FONT COLOR="#A020F0">is</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> None:
+    4:             res = tree.xpath(
+                       <B><FONT COLOR="#BC8F8F">'//*[@xlink:title=&quot;%s&quot;]'</FONT></B> %title, nsmap)
+    2:         <B><FONT COLOR="#A020F0">elif</FONT></B> url <B><FONT COLOR="#A020F0">is</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> None:
+    1:             res = tree.xpath(
+                       <B><FONT COLOR="#BC8F8F">'//*[@xlink:href=&quot;%s&quot;]'</FONT></B> %url, nsmap)
+               <B><FONT COLOR="#A020F0">else</FONT></B>:
+    1:             <B><FONT COLOR="#A020F0">raise</FONT></B> ValueError(<B><FONT COLOR="#BC8F8F">'You must specify a title or URL.'</FONT></B>)
+    5:         elem = res[index]
+    5:         url = elem.attrib.get(<B><FONT COLOR="#BC8F8F">'{%(xlink)s}href'</FONT></B> %nsmap, <B><FONT COLOR="#BC8F8F">''</FONT></B>)
+    5:         <B><FONT COLOR="#A020F0">return</FONT></B> XLink(self,
+    5:                      elem.attrib.get(<B><FONT COLOR="#BC8F8F">'{%(xlink)s}title'</FONT></B> %nsmap),
+    5:                      absoluteURL(self.url, url))
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">xpath</FONT></B>(self, expr, nsmap=None, single=False):
+    3:         res = lxml.etree.fromstring(self.contents).xpath(expr, nsmap)
+    3:         <B><FONT COLOR="#A020F0">if</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> single:
+    1:             <B><FONT COLOR="#A020F0">return</FONT></B> res
+    2:         <B><FONT COLOR="#A020F0">if</FONT></B> len(res) != 1:
+    1:             <B><FONT COLOR="#A020F0">raise</FONT></B> ValueError(<B><FONT COLOR="#BC8F8F">'XPath expression returned more than one result.'</FONT></B>)
+    1:         <B><FONT COLOR="#A020F0">return</FONT></B> res[0]
+</pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,29 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.__init__.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;__init__.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 0 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.client.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;client.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 128 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.interfaces.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interfaces.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 58 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.null.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 50 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.traverser.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;traverser.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+</table><hr/>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.interfaces.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.interfaces.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.interfaces.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,240 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.interfaces</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.interfaces</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.interfaces.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;interfaces.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 58 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># Copyright (c) 2007 Zope Corporation and Contributors.
+</FONT></I>       <I><FONT COLOR="#B22222"># All Rights Reserved.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># This software is subject to the provisions of the Zope Public License,
+</FONT></I>       <I><FONT COLOR="#B22222"># Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+</FONT></I>       <I><FONT COLOR="#B22222"># THIS SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ANY AND ALL EXPRESS OR IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+</FONT></I>       <I><FONT COLOR="#B22222"># FOR A PARTICULAR PURPOSE.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;REST publishing interfaces.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: &quot;&quot;&quot;</FONT></B>
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.interface
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.schema
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.location.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> ILocation
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.publisher.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> http
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> IRESTRequest(http.IHTTPRequest):
+    1:     <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;A special type of request for handling REST-based requests.&quot;&quot;&quot;</FONT></B>
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> IRESTView(ILocation):
+    1:     <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;A REST view&quot;&quot;&quot;</FONT></B>
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> ILink(zope.interface.Interface):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;An object representing a hyperlink.&quot;&quot;&quot;</FONT></B>
+       
+    1:     href = zope.schema.TextLine(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;URL&quot;</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">&quot;The normalized URL of the link&quot;</FONT></B>,
+    1:         required=False)
+       
+    1:     title = zope.schema.TextLine(
+               title=u<B><FONT COLOR="#BC8F8F">'Title'</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">'The title of the link'</FONT></B>,
+    1:         required=False)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">click</FONT></B>():
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;click the link, going to the URL referenced&quot;&quot;&quot;</FONT></B>
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> IRESTClient(zope.interface.Interface):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;A REST client.
+       
+           This client provides a high-level API to access RESTful Web APIs. The
+           interface is designed to resemble the test browser API as much as
+           practical.
+           &quot;&quot;&quot;</FONT></B>
+       
+    1:     connectionFactory = zope.schema.Field(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Connection Facotry&quot;</FONT></B>,
+    1:         description=(u<B><FONT COLOR="#BC8F8F">'A callable that creates an `httplib`-compliant '</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">'connection object.'</FONT></B>),
+    1:         required=True)
+       
+    1:     requestHeaders = zope.schema.Dict(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Request Headers&quot;</FONT></B>,
+    1:         description=(u<B><FONT COLOR="#BC8F8F">&quot;A set of headers that will be sent in every request.&quot;</FONT></B>),
+    1:         required=True)
+       
+    1:     url = zope.schema.URI(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;URL&quot;</FONT></B>,
+    1:         description=(u<B><FONT COLOR="#BC8F8F">&quot;The URL the browser is currently showing. It is &quot;</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">&quot;always a full, absolute URL.&quot;</FONT></B>),
+    1:         required=True)
+       
+    1:     headers = zope.schema.List(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Response Headers&quot;</FONT></B>,
+    1:         description=(u<B><FONT COLOR="#BC8F8F">'A list of all headers that have been returned '</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">'in the last request.'</FONT></B>),
+    1:         required=True)
+       
+    1:     contents = zope.schema.Text(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Contents&quot;</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">&quot;The complete response body of the HTTP request.&quot;</FONT></B>,
+    1:         required=True)
+       
+    1:     status = zope.schema.Int(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Status&quot;</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">&quot;The status code of the last response.&quot;</FONT></B>,
+    1:         min=0,
+    1:         required=True)
+       
+    1:     reason = zope.schema.TextLine(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Reason&quot;</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">&quot;A short explanation of the status of the last response.&quot;</FONT></B>,
+    1:         required=True)
+       
+    1:     fullStatus = zope.schema.TextLine(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Full Status&quot;</FONT></B>,
+    1:         description=u<B><FONT COLOR="#BC8F8F">&quot;The status code and reason of the last response.&quot;</FONT></B>,
+    1:         required=True)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">open</FONT></B>(url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=None, params=None, headers=None, method=<B><FONT COLOR="#BC8F8F">'GET'</FONT></B>):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Open a URL and retrieve the result.
+       
+               The `url` argument can either be a full URL or a URL relative to the
+               previous one. If no URL is specified, then the previous URL will be
+               used.
+       
+               The `data` is the contents of the request body. It is used to send
+               information to the server.
+       
+               The `params` describe additional query parameters that will be added
+               to the request. Query string parameters are frequently used by RESTive
+               APIs to provide additional return value options.
+       
+               The `headers` specify additional request headers that are specific for
+               this particular request.
+       
+               The `method` specifies the HTTP method or verb to use to access the
+               resource on the server. While there are only a few methods in RFC
+               2616, an string is allowed, since any particular API can extend the
+               set of allowed methods.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">get</FONT></B>(url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Make a GET request to the server.
+       
+               For argument details see ``open()``.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">put</FONT></B>(url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Make a PUT request to the server.
+       
+               For argument details see ``open()``.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">post</FONT></B>(url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, data=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Make a POST request to the server.
+       
+               For argument details see ``open()``.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">delete</FONT></B>(url=<B><FONT COLOR="#BC8F8F">''</FONT></B>, params=None, headers=None):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Make a DELETE request to the server.
+       
+               For argument details see ``open()``.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">setCredentials</FONT></B>(username, password):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Set the credentials.
+       
+               This method adds the necessary information to authenticate the user. A
+               common example is basic auth, which inserts the `Authentication`
+               request header.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">goBack</FONT></B>(count=1):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Go back in history by a certain amount of visisted pages.
+       
+               The ``count`` argument specifies how far to go back. It is set to 1 by
+               default.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">reload</FONT></B>():
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Reload the current resource.
+       
+               All arguments, including the HTTP method, parameters and additional
+               headers are honored.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">getLink</FONT></B>(title=None, url=None, index=0):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Return an ILink of the found link.
+       
+               This method assumes that the current content type of the response body
+               is XML.
+       
+               The link is found by the arguments of the method.  Only one can be
+               used at a time:
+       
+                 o ``title`` -- The title or a sub-string thereof of the link.
+       
+                 o ``url`` -- The URL the link is going to.
+       
+               If multiple matching links are found, the `index` specifies which one
+               to use.
+               &quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">xpath</FONT></B>(expr, nsmap=None, single=False):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Returns the result of an XPath search expression.
+       
+               This method assumes that the current content type of the response body
+               is XML.
+       
+               The `expr` argument is the actual XPath expression. If the expression
+               is incorrect, an unspecified error must be raised.
+       
+               The `nsmap` is a mapping from the short version to the full URL of
+               each XML namespace used in the expression.
+       
+               If `single` is set to ``True``, then only one result is returned,
+               instead of a list. If the XPath expression results in more than one
+               result, a ``ValueError`` must be raised.
+               &quot;&quot;&quot;</FONT></B>
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> IPublisherRESTClient(IRESTClient):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;An extension to the REST client to support test-specific features.&quot;&quot;&quot;</FONT></B>
+       
+    1:     handleErrors = zope.schema.Bool(
+               title=u<B><FONT COLOR="#BC8F8F">&quot;Handle Errors&quot;</FONT></B>,
+    1:         description=(u<B><FONT COLOR="#BC8F8F">&quot;Describes whether server-side errors will be handled &quot;</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">&quot;by the publisher. If set to ``False``, the error will &quot;</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">&quot;progress all the way to the test, which is good for &quot;</FONT></B>
+                            u<B><FONT COLOR="#BC8F8F">&quot;debugging.&quot;</FONT></B>),
+    1:         default=True,
+    1:         required=True)
+</pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.null.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.null.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.null.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,80 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.null</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.null</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.null.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;null.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># Copyright (c) 2007 Zope Corporation and Contributors.
+</FONT></I>       <I><FONT COLOR="#B22222"># All Rights Reserved.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># This software is subject to the provisions of the Zope Public License,
+</FONT></I>       <I><FONT COLOR="#B22222"># Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+</FONT></I>       <I><FONT COLOR="#B22222"># THIS SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ANY AND ALL EXPRESS OR IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+</FONT></I>       <I><FONT COLOR="#B22222"># FOR A PARTICULAR PURPOSE.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Null resource.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: &quot;&quot;&quot;</FONT></B>
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.component
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.interface
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.app.http.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> INullResource
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.location <B><FONT COLOR="#A020F0">import</FONT></B> location
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.traversing.browser <B><FONT COLOR="#A020F0">import</FONT></B> absoluteURL
+       
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> z3c.rest <B><FONT COLOR="#A020F0">import</FONT></B> rest
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> NullResource(location.Location):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Object representing objects to be created by a `PUT`.&quot;&quot;&quot;</FONT></B>
+    1:     zope.interface.implements(INullResource)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, container, name):
+    6:         self.__parent__ = self.container = container
+    6:         self.__name__ = self.name = name
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__repr__</FONT></B>(self):
+    1:         <B><FONT COLOR="#A020F0">return</FONT></B> <B><FONT COLOR="#BC8F8F">'&lt;%s %r&gt;'</FONT></B> %(self.__class__.__name__, self.name)
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> NullPUT(rest.RESTView):
+           <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Put handler for null resources&quot;&quot;&quot;</FONT></B>
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">PUT</FONT></B>(self):
+    6:         nullPut = zope.component.queryMultiAdapter(
+                   (self.context.container, self.request), name=<B><FONT COLOR="#BC8F8F">'NullPUT'</FONT></B>)
+    6:         <B><FONT COLOR="#A020F0">if</FONT></B> nullPut <B><FONT COLOR="#A020F0">is</FONT></B> None:
+                   <I><FONT COLOR="#B22222"># See RFC 2616, section 9.6
+</FONT></I>    1:             self.request.response.setStatus(501)
+    1:             <B><FONT COLOR="#A020F0">return</FONT></B>
+       
+    5:         newObj = nullPut.NullPUT(self.context)
+       
+               <I><FONT COLOR="#B22222"># See RFC 2616, section 9.6
+</FONT></I>    4:         self.request.response.setStatus(201)
+    4:         self.request.response.setHeader(
+                   <B><FONT COLOR="#BC8F8F">'Location'</FONT></B>, absoluteURL(newObj, self.request))
+</pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.rest.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.rest.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.rest.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,120 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.rest</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.rest</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rest.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 50 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># Copyright (c) 2007 Zope Corporation and Contributors.
+</FONT></I>       <I><FONT COLOR="#B22222"># All Rights Reserved.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># This software is subject to the provisions of the Zope Public License,
+</FONT></I>       <I><FONT COLOR="#B22222"># Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+</FONT></I>       <I><FONT COLOR="#B22222"># THIS SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ANY AND ALL EXPRESS OR IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+</FONT></I>       <I><FONT COLOR="#B22222"># FOR A PARTICULAR PURPOSE.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;REST publication and publisher factories
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: &quot;&quot;&quot;</FONT></B>
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> cgi
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.interface
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.app.publication.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> IPublicationRequestFactory
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.app.publication.http <B><FONT COLOR="#A020F0">import</FONT></B> HTTPPublication
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.publisher.http <B><FONT COLOR="#A020F0">import</FONT></B> HTTPRequest
+       
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> z3c.rest <B><FONT COLOR="#A020F0">import</FONT></B> interfaces
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> RESTRequest(HTTPRequest):
+    1:     zope.interface.implements(interfaces.IRESTRequest)
+       
+    1:     __slots__ = (
+               <B><FONT COLOR="#BC8F8F">'parameters'</FONT></B>, <I><FONT COLOR="#B22222"># Parameters sent via the query string.
+</FONT></I>               )
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, body_instream, environ, response=None):
+   39:         self.parameters = {}
+   39:         super(RESTRequest, self).__init__(body_instream, environ, response)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">processInputs</FONT></B>(self):
+               <B><FONT COLOR="#BC8F8F">'See IPublisherRequest'</FONT></B>
+   35:         <B><FONT COLOR="#A020F0">if</FONT></B> <B><FONT COLOR="#BC8F8F">'QUERY_STRING'</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> <B><FONT COLOR="#A020F0">in</FONT></B> self._environ:
+   31:             <B><FONT COLOR="#A020F0">return</FONT></B>
+               <I><FONT COLOR="#B22222"># Parse the query string into our parameters dictionary.
+</FONT></I>    4:         self.parameters = cgi.parse_qs(
+                   self._environ[<B><FONT COLOR="#BC8F8F">'QUERY_STRING'</FONT></B>], keep_blank_values=1)
+               <I><FONT COLOR="#B22222"># Since the parameter value is always a list (sigh), let's at least
+</FONT></I>               <I><FONT COLOR="#B22222"># detect single values and store them.
+</FONT></I>   11:         <B><FONT COLOR="#A020F0">for</FONT></B> name, value <B><FONT COLOR="#A020F0">in</FONT></B> self.parameters.items():
+    7:             <B><FONT COLOR="#A020F0">if</FONT></B> len(value) == 1:
+    6:                 self.parameters[name] = value[0]
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">keys</FONT></B>(self):
+               <B><FONT COLOR="#BC8F8F">'See Interface.Common.Mapping.IEnumerableMapping'</FONT></B>
+    7:         d = {}
+    7:         d.update(self._environ)
+    7:         d.update(self.parameters)
+    7:         <B><FONT COLOR="#A020F0">return</FONT></B> d.keys()
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">get</FONT></B>(self, key, default=None):
+               <B><FONT COLOR="#BC8F8F">'See Interface.Common.Mapping.IReadMapping'</FONT></B>
+  300:         marker = object()
+  300:         result = self.parameters.get(key, marker)
+  300:         <B><FONT COLOR="#A020F0">if</FONT></B> result <B><FONT COLOR="#A020F0">is</FONT></B> <B><FONT COLOR="#A020F0">not</FONT></B> marker:
+    8:             <B><FONT COLOR="#A020F0">return</FONT></B> result
+       
+  292:         <B><FONT COLOR="#A020F0">return</FONT></B> super(RESTRequest, self).get(key, default)
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> RESTView(object):
+    1:     zope.interface.implements(interfaces.IRESTView)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, context, request):
+   39:         self.context = context
+   39:         self.request = request
+       
+    1:     @apply
+           <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__parent__</FONT></B>():
+    1:         <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">get</FONT></B>(self):
+    2:             <B><FONT COLOR="#A020F0">return</FONT></B> getattr(self, <B><FONT COLOR="#BC8F8F">'_parent'</FONT></B>, self.context)
+    1:         <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">set</FONT></B>(self, parent):
+    1:             self._parent = parent
+    1:         <B><FONT COLOR="#A020F0">return</FONT></B> property(get, set)
+       
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> RESTPublicationRequestFactory(object):
+    1:     zope.interface.implements(IPublicationRequestFactory)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, db):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;See zope.app.publication.interfaces.IPublicationRequestFactory&quot;&quot;&quot;</FONT></B>
+    2:         self.publication = HTTPPublication(db)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__call__</FONT></B>(self, input_stream, env, output_stream=None):
+               <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;See zope.app.publication.interfaces.IPublicationRequestFactory&quot;&quot;&quot;</FONT></B>
+    5:         request = RESTRequest(input_stream, env)
+    5:         request.setPublication(self.publication)
+    5:         <B><FONT COLOR="#A020F0">return</FONT></B> request
+</pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/report/z3c.rest.traverser.html
===================================================================
--- z3c.rest/trunk/coverage/report/z3c.rest.traverser.html	                        (rev 0)
+++ z3c.rest/trunk/coverage/report/z3c.rest.traverser.html	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,76 @@
+
+    <html>
+      <head><title>Unit test coverage for z3c.rest.traverser</title>
+      <style type="text/css">
+        a {text-decoration: none; display: block; padding-right: 1em;}
+        a:hover {background: #EFA;}
+        hr {height: 1px; border: none; border-top: 1px solid gray;}
+        .notcovered {background: #FCC;}
+        .footer {margin: 2em; font-size: small; color: gray;}
+      </style>
+      </head>
+      <body><h1>Unit test coverage for z3c.rest.traverser</h1>
+      <table>
+    
+<tr><td><a href="z3c.html">z3c/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.html">&nbsp;&nbsp;&nbsp;&nbsp;rest/</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 282 uncovered)</td></tr>
+<tr><td><a href="z3c.rest.traverser.html">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;traverser.py</a></td> <td style="background: green">&nbsp;&nbsp;&nbsp;&nbsp;</td> <td>covered 100% (0 of 23 uncovered)</td></tr>
+</table><hr/>
+<pre>
+       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># Copyright (c) 2007 Zope Corporation and Contributors.
+</FONT></I>       <I><FONT COLOR="#B22222"># All Rights Reserved.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222"># This software is subject to the provisions of the Zope Public License,
+</FONT></I>       <I><FONT COLOR="#B22222"># Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+</FONT></I>       <I><FONT COLOR="#B22222"># THIS SOFTWARE IS PROVIDED &quot;AS IS&quot; AND ANY AND ALL EXPRESS OR IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+</FONT></I>       <I><FONT COLOR="#B22222"># WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+</FONT></I>       <I><FONT COLOR="#B22222"># FOR A PARTICULAR PURPOSE.
+</FONT></I>       <I><FONT COLOR="#B22222">#
+</FONT></I>       <I><FONT COLOR="#B22222">##############################################################################
+</FONT></I>       <B><FONT COLOR="#BC8F8F">&quot;&quot;&quot;Some basic traversers for REST
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: &quot;&quot;&quot;</FONT></B>
+    1: <B><FONT COLOR="#A020F0">import</FONT></B> zope.interface
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.publisher.interfaces.http <B><FONT COLOR="#A020F0">import</FONT></B> IHTTPPublisher
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.app.container.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> IItemContainer
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> zope.publisher.interfaces <B><FONT COLOR="#A020F0">import</FONT></B> NotFound
+    1: <B><FONT COLOR="#A020F0">from</FONT></B> z3c.rest <B><FONT COLOR="#A020F0">import</FONT></B> interfaces, null
+       
+    2: <B><FONT COLOR="#A020F0">class</FONT></B> ItemTraverser(object):
+    1:     zope.interface.implements(IHTTPPublisher)
+    1:     zope.component.adapts(IItemContainer, interfaces.IRESTRequest)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">__init__</FONT></B>(self, container, request):
+   20:         self.context = container
+   20:         self.request = request
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">publishTraverse</FONT></B>(self, request, name):
+   23:         <B><FONT COLOR="#A020F0">try</FONT></B>:
+   23:             <B><FONT COLOR="#A020F0">return</FONT></B> self.context[name]
+   12:         <B><FONT COLOR="#A020F0">except</FONT></B> KeyError:
+   12:             <B><FONT COLOR="#A020F0">return</FONT></B> self.nullResource(request, name)
+       
+    1:     <B><FONT COLOR="#A020F0">def</FONT></B> <B><FONT COLOR="#0000FF">nullResource</FONT></B>(self, request, name):
+               <I><FONT COLOR="#B22222"># we traversed to something that doesn't exist.
+</FONT></I>       
+               <I><FONT COLOR="#B22222"># The name must be the last name in the path, so the traversal
+</FONT></I>               <I><FONT COLOR="#B22222"># name stack better be empty:
+</FONT></I>   12:         <B><FONT COLOR="#A020F0">if</FONT></B> request.getTraversalStack():
+    2:             <B><FONT COLOR="#A020F0">raise</FONT></B> NotFound(self.context, name, request)
+       
+               <I><FONT COLOR="#B22222"># This should only happen for a PUT:
+</FONT></I>   10:         <B><FONT COLOR="#A020F0">if</FONT></B> request.method != <B><FONT COLOR="#BC8F8F">'PUT'</FONT></B>:
+    5:             <B><FONT COLOR="#A020F0">raise</FONT></B> NotFound(self.context, name, request)
+       
+    5:         <B><FONT COLOR="#A020F0">return</FONT></B> null.NullResource(self.context, name)
+</pre>
+
+      <div class="footer">
+      Generated for revision exported on 2007-11-30 11:34:55.110922Z
+      </div>
+    </body>
+    </html>

Added: z3c.rest/trunk/coverage/z3c.rest.__init__.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.__init__.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.__init__.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+       # Make a package

Added: z3c.rest/trunk/coverage/z3c.rest.client.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.client.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.client.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,201 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """REST Client
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import lxml
+    1: import httplib
+    1: import socket
+    1: import urllib
+    1: import urlparse
+    1: import base64
+    1: import zope.interface
+    1: from z3c.rest import interfaces
+       
+    1: def isRelativeURL(url):
+           """Determines whether the given URL is a relative path segment."""
+   37:     pieces = urlparse.urlparse(url)
+   37:     if not pieces[0] and not pieces[1]:
+    5:         return True
+   32:     return False
+       
+    1: def absoluteURL(base, url):
+           """Convertes a URL to an absolute URL given a base."""
+   37:     if isRelativeURL(url):
+    5:         fullUrl = urlparse.urljoin(base, url)
+           else:
+   32:         fullUrl = url
+   37:     pieces = list(urlparse.urlparse(fullUrl))
+   37:     if not pieces[2].endswith('/'):
+   18:         pieces[2] += '/'
+   37:     return urlparse.urlunparse(pieces)
+       
+    1: def getFullPath(pieces, params):
+           """Build a full httplib request path, including a query string."""
+   32:     query = ''
+   32:     if pieces[4]:
+    2:         query = pieces[4]
+   32:     if params:
+    2:         encParams = urllib.urlencode(params)
+    2:         if query:
+    1:             query += '&' + encParams
+               else:
+    1:             query = encParams
+   32:     return urlparse.urlunparse(
+               ('', '', pieces[2], pieces[3], query, pieces[5]))
+       
+       
+    2: class XLink(object):
+           """A link implementation for simple XLinks."""
+    1:     zope.interface.implements(interfaces.ILink)
+       
+    1:     def __init__(self, client, title, url):
+    5:         self._client = client
+    5:         self.title = title
+    5:         self.url = url
+       
+    1:     def click(self):
+               """See interfaces.ILink"""
+    3:         self._client.get(self.url)
+       
+    1:     def __repr__(self):
+    2:         return '<%s title=%r url=%r>' %(
+                   self.__class__.__name__, self.title, self.url)
+       
+       
+    2: class RESTClient(object):
+    1:     zope.interface.implements(interfaces.IRESTClient)
+       
+    1:     connectionFactory = httplib.HTTPConnection
+       
+    1:     def __init__(self, url=None):
+    3:         self.requestHeaders = {}
+    3:         self._reset()
+    3:         self._history = []
+    3:         self._requestData = None
+    3:         self.url = ''
+    3:         if url:
+    1:             self.open(url)
+       
+    1:     @property
+           def fullStatus(self):
+   12:         return '%i %s' %(self.status, self.reason)
+       
+    1:     def _reset(self):
+   35:         self.headers = []
+   35:         self.contents = {}
+   35:         self.status = None
+   35:         self.reason = None
+       
+    1:     def open(self, url='', data=None, params=None, headers=None, method='GET'):
+               # Create a correct absolute URL and set it.
+   32:         self.url = absoluteURL(self.url, url)
+       
+               # Create the full set of request headers
+   32:         requestHeaders = self.requestHeaders.copy()
+   32:         if headers:
+    1:             requestHeaders.update(headers)
+       
+               # Let's now reset all response values
+   32:         self._reset()
+       
+               # Store all the request data
+   32:         self._requestData = (url, data, params, headers, method)
+       
+               # Make a connection and retrieve the result
+   32:         pieces = urlparse.urlparse(self.url)
+   32:         connection = self.connectionFactory(pieces[1])
+   32:         try:
+   32:             connection.request(
+                       method, getFullPath(pieces, params), data, requestHeaders)
+   30:             response = connection.getresponse()
+   30:             connection.close()
+    2:         except socket.error, e:
+    1:             connection.close()
+    1:             self.status, self.reason = e.args
+    1:             self._addHistory()
+    1:             raise e
+               else:
+   30:             self.headers = response.getheaders()
+   30:             self.contents = response.read()
+   30:             self.status = response.status
+   30:             self.reason = response.reason
+   30:             self._addHistory()
+       
+    1:     def get(self, url='', params=None, headers=None):
+   17:         self.open(url, None, params, headers)
+       
+    1:     def put(self, url='', data='', params=None, headers=None):
+    6:         self.open(url, data, params, headers, 'PUT')
+       
+    1:     def post(self, url='', data='', params=None, headers=None):
+    1:         self.open(url, data, params, headers, 'POST')
+       
+    1:     def delete(self, url='', params=None, headers=None):
+    4:         self.open(url, None, params, headers, 'DELETE')
+       
+    1:     def setCredentials(self, username, password):
+    1:         creds = username + u':' + password
+    1:         creds = "Basic " + base64.encodestring(creds.encode('utf-8')).strip()
+    1:         self.requestHeaders['Authorization'] = creds
+       
+    1:     def _addHistory(self):
+   31:         self._history.append((
+                   self.url, self.requestHeaders, self.headers, self.contents,
+                   self.status, self.reason, self._requestData
+                   ))
+       
+    1:     def goBack(self, count=1):
+               # The user really does not want to go back.
+    4:         if count == 0:
+    1:             return
+               # The user wants to reach before a pre-historical state.
+    3:         if len(self._history) < count:
+    1:             raise ValueError('There is not enough history.')
+               # Let's now get the entry and set the history back to that state.
+    2:         entry = self._history[-(count+1)]
+    2:         self._history = self._history[:-count]
+               # Reset the state.
+    2:         (self.url, self.requestHeaders, self.headers, self.contents,
+                self.status, self.reason, self._requestData) = entry
+       
+    1:     def reload(self):
+    1:         self.open(*self._requestData)
+       
+    1:     def getLink(self, title=None, url=None, index=0):
+    6:         nsmap = {'xlink': "http://www.w3.org/1999/xlink"}
+    6:         tree = lxml.etree.fromstring(self.contents)
+    6:         res = []
+    6:         if title is not None:
+    4:             res = tree.xpath(
+                       '//*[@xlink:title="%s"]' %title, nsmap)
+    2:         elif url is not None:
+    1:             res = tree.xpath(
+                       '//*[@xlink:href="%s"]' %url, nsmap)
+               else:
+    1:             raise ValueError('You must specify a title or URL.')
+    5:         elem = res[index]
+    5:         url = elem.attrib.get('{%(xlink)s}href' %nsmap, '')
+    5:         return XLink(self,
+    5:                      elem.attrib.get('{%(xlink)s}title' %nsmap),
+    5:                      absoluteURL(self.url, url))
+       
+    1:     def xpath(self, expr, nsmap=None, single=False):
+    3:         res = lxml.etree.fromstring(self.contents).xpath(expr, nsmap)
+    3:         if not single:
+    1:             return res
+    2:         if len(res) != 1:
+    1:             raise ValueError('XPath expression returned more than one result.')
+    1:         return res[0]

Added: z3c.rest/trunk/coverage/z3c.rest.interfaces.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.interfaces.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.interfaces.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,214 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """REST publishing interfaces.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import zope.interface
+    1: import zope.schema
+    1: from zope.location.interfaces import ILocation
+    1: from zope.publisher.interfaces import http
+       
+    2: class IRESTRequest(http.IHTTPRequest):
+    1:     """A special type of request for handling REST-based requests."""
+       
+       
+    2: class IRESTView(ILocation):
+    1:     """A REST view"""
+       
+       
+    2: class ILink(zope.interface.Interface):
+           """An object representing a hyperlink."""
+       
+    1:     href = zope.schema.TextLine(
+               title=u"URL",
+    1:         description=u"The normalized URL of the link",
+    1:         required=False)
+       
+    1:     title = zope.schema.TextLine(
+               title=u'Title',
+    1:         description=u'The title of the link',
+    1:         required=False)
+       
+    1:     def click():
+               """click the link, going to the URL referenced"""
+       
+       
+    2: class IRESTClient(zope.interface.Interface):
+           """A REST client.
+       
+           This client provides a high-level API to access RESTful Web APIs. The
+           interface is designed to resemble the test browser API as much as
+           practical.
+           """
+       
+    1:     connectionFactory = zope.schema.Field(
+               title=u"Connection Facotry",
+    1:         description=(u'A callable that creates an `httplib`-compliant '
+                            u'connection object.'),
+    1:         required=True)
+       
+    1:     requestHeaders = zope.schema.Dict(
+               title=u"Request Headers",
+    1:         description=(u"A set of headers that will be sent in every request."),
+    1:         required=True)
+       
+    1:     url = zope.schema.URI(
+               title=u"URL",
+    1:         description=(u"The URL the browser is currently showing. It is "
+                            u"always a full, absolute URL."),
+    1:         required=True)
+       
+    1:     headers = zope.schema.List(
+               title=u"Response Headers",
+    1:         description=(u'A list of all headers that have been returned '
+                            u'in the last request.'),
+    1:         required=True)
+       
+    1:     contents = zope.schema.Text(
+               title=u"Contents",
+    1:         description=u"The complete response body of the HTTP request.",
+    1:         required=True)
+       
+    1:     status = zope.schema.Int(
+               title=u"Status",
+    1:         description=u"The status code of the last response.",
+    1:         min=0,
+    1:         required=True)
+       
+    1:     reason = zope.schema.TextLine(
+               title=u"Reason",
+    1:         description=u"A short explanation of the status of the last response.",
+    1:         required=True)
+       
+    1:     fullStatus = zope.schema.TextLine(
+               title=u"Full Status",
+    1:         description=u"The status code and reason of the last response.",
+    1:         required=True)
+       
+    1:     def open(url='', data=None, params=None, headers=None, method='GET'):
+               """Open a URL and retrieve the result.
+       
+               The `url` argument can either be a full URL or a URL relative to the
+               previous one. If no URL is specified, then the previous URL will be
+               used.
+       
+               The `data` is the contents of the request body. It is used to send
+               information to the server.
+       
+               The `params` describe additional query parameters that will be added
+               to the request. Query string parameters are frequently used by RESTive
+               APIs to provide additional return value options.
+       
+               The `headers` specify additional request headers that are specific for
+               this particular request.
+       
+               The `method` specifies the HTTP method or verb to use to access the
+               resource on the server. While there are only a few methods in RFC
+               2616, an string is allowed, since any particular API can extend the
+               set of allowed methods.
+               """
+       
+    1:     def get(url='', params=None, headers=None):
+               """Make a GET request to the server.
+       
+               For argument details see ``open()``.
+               """
+       
+    1:     def put(url='', data='', params=None, headers=None):
+               """Make a PUT request to the server.
+       
+               For argument details see ``open()``.
+               """
+       
+    1:     def post(url='', data='', params=None, headers=None):
+               """Make a POST request to the server.
+       
+               For argument details see ``open()``.
+               """
+       
+    1:     def delete(url='', params=None, headers=None):
+               """Make a DELETE request to the server.
+       
+               For argument details see ``open()``.
+               """
+       
+    1:     def setCredentials(username, password):
+               """Set the credentials.
+       
+               This method adds the necessary information to authenticate the user. A
+               common example is basic auth, which inserts the `Authentication`
+               request header.
+               """
+       
+    1:     def goBack(count=1):
+               """Go back in history by a certain amount of visisted pages.
+       
+               The ``count`` argument specifies how far to go back. It is set to 1 by
+               default.
+               """
+       
+    1:     def reload():
+               """Reload the current resource.
+       
+               All arguments, including the HTTP method, parameters and additional
+               headers are honored.
+               """
+       
+    1:     def getLink(title=None, url=None, index=0):
+               """Return an ILink of the found link.
+       
+               This method assumes that the current content type of the response body
+               is XML.
+       
+               The link is found by the arguments of the method.  Only one can be
+               used at a time:
+       
+                 o ``title`` -- The title or a sub-string thereof of the link.
+       
+                 o ``url`` -- The URL the link is going to.
+       
+               If multiple matching links are found, the `index` specifies which one
+               to use.
+               """
+       
+    1:     def xpath(expr, nsmap=None, single=False):
+               """Returns the result of an XPath search expression.
+       
+               This method assumes that the current content type of the response body
+               is XML.
+       
+               The `expr` argument is the actual XPath expression. If the expression
+               is incorrect, an unspecified error must be raised.
+       
+               The `nsmap` is a mapping from the short version to the full URL of
+               each XML namespace used in the expression.
+       
+               If `single` is set to ``True``, then only one result is returned,
+               instead of a list. If the XPath expression results in more than one
+               result, a ``ValueError`` must be raised.
+               """
+       
+       
+    2: class IPublisherRESTClient(IRESTClient):
+           """An extension to the REST client to support test-specific features."""
+       
+    1:     handleErrors = zope.schema.Bool(
+               title=u"Handle Errors",
+    1:         description=(u"Describes whether server-side errors will be handled "
+                            u"by the publisher. If set to ``False``, the error will "
+                            u"progress all the way to the test, which is good for "
+                            u"debugging."),
+    1:         default=True,
+    1:         required=True)

Added: z3c.rest/trunk/coverage/z3c.rest.null.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.null.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.null.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,54 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """Null resource.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import zope.component
+    1: import zope.interface
+    1: from zope.app.http.interfaces import INullResource
+    1: from zope.location import location
+    1: from zope.traversing.browser import absoluteURL
+       
+    1: from z3c.rest import rest
+       
+    2: class NullResource(location.Location):
+           """Object representing objects to be created by a `PUT`."""
+    1:     zope.interface.implements(INullResource)
+       
+    1:     def __init__(self, container, name):
+    6:         self.__parent__ = self.container = container
+    6:         self.__name__ = self.name = name
+       
+    1:     def __repr__(self):
+    1:         return '<%s %r>' %(self.__class__.__name__, self.name)
+       
+       
+    2: class NullPUT(rest.RESTView):
+           """Put handler for null resources"""
+       
+    1:     def PUT(self):
+    6:         nullPut = zope.component.queryMultiAdapter(
+                   (self.context.container, self.request), name='NullPUT')
+    6:         if nullPut is None:
+                   # See RFC 2616, section 9.6
+    1:             self.request.response.setStatus(501)
+    1:             return
+       
+    5:         newObj = nullPut.NullPUT(self.context)
+       
+               # See RFC 2616, section 9.6
+    4:         self.request.response.setStatus(201)
+    4:         self.request.response.setHeader(
+                   'Location', absoluteURL(newObj, self.request))

Added: z3c.rest/trunk/coverage/z3c.rest.rest.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.rest.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.rest.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,94 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """REST publication and publisher factories
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import cgi
+    1: import zope.interface
+    1: from zope.app.publication.interfaces import IPublicationRequestFactory
+    1: from zope.app.publication.http import HTTPPublication
+    1: from zope.publisher.http import HTTPRequest
+       
+    1: from z3c.rest import interfaces
+       
+    2: class RESTRequest(HTTPRequest):
+    1:     zope.interface.implements(interfaces.IRESTRequest)
+       
+    1:     __slots__ = (
+               'parameters', # Parameters sent via the query string.
+               )
+       
+    1:     def __init__(self, body_instream, environ, response=None):
+   39:         self.parameters = {}
+   39:         super(RESTRequest, self).__init__(body_instream, environ, response)
+       
+    1:     def processInputs(self):
+               'See IPublisherRequest'
+   35:         if 'QUERY_STRING' not in self._environ:
+   31:             return
+               # Parse the query string into our parameters dictionary.
+    4:         self.parameters = cgi.parse_qs(
+                   self._environ['QUERY_STRING'], keep_blank_values=1)
+               # Since the parameter value is always a list (sigh), let's at least
+               # detect single values and store them.
+   11:         for name, value in self.parameters.items():
+    7:             if len(value) == 1:
+    6:                 self.parameters[name] = value[0]
+       
+    1:     def keys(self):
+               'See Interface.Common.Mapping.IEnumerableMapping'
+    7:         d = {}
+    7:         d.update(self._environ)
+    7:         d.update(self.parameters)
+    7:         return d.keys()
+       
+    1:     def get(self, key, default=None):
+               'See Interface.Common.Mapping.IReadMapping'
+  300:         marker = object()
+  300:         result = self.parameters.get(key, marker)
+  300:         if result is not marker:
+    8:             return result
+       
+  292:         return super(RESTRequest, self).get(key, default)
+       
+       
+    2: class RESTView(object):
+    1:     zope.interface.implements(interfaces.IRESTView)
+       
+    1:     def __init__(self, context, request):
+   39:         self.context = context
+   39:         self.request = request
+       
+    1:     @apply
+           def __parent__():
+    1:         def get(self):
+    2:             return getattr(self, '_parent', self.context)
+    1:         def set(self, parent):
+    1:             self._parent = parent
+    1:         return property(get, set)
+       
+       
+    2: class RESTPublicationRequestFactory(object):
+    1:     zope.interface.implements(IPublicationRequestFactory)
+       
+    1:     def __init__(self, db):
+               """See zope.app.publication.interfaces.IPublicationRequestFactory"""
+    2:         self.publication = HTTPPublication(db)
+       
+    1:     def __call__(self, input_stream, env, output_stream=None):
+               """See zope.app.publication.interfaces.IPublicationRequestFactory"""
+    5:         request = RESTRequest(input_stream, env)
+    5:         request.setPublication(self.publication)
+    5:         return request

Added: z3c.rest/trunk/coverage/z3c.rest.testing.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.testing.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.testing.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,100 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """REST testing support.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import sys
+    1: import zope.interface
+    1: from z3c.rest import client, rest, interfaces
+    1: from zope.app.publication.http import HTTPPublication
+    1: from zope.app.testing.functional import HTTPCaller
+       
+       
+    2: class RESTCaller(HTTPCaller):
+           """An HTTP caller for REST functional page tests"""
+       
+    1:     def chooseRequestClass(self, method, path, environment):
+               """Always returns HTTPRequests regardless of methods and content"""
+   31:         return rest.RESTRequest, HTTPPublication
+       
+       
+    2: class PublisherConnection(object):
+       
+    1:     def __init__(self, server, port=None):
+   31:         self._response = None
+   31:         self.server = server
+   31:         self.port = port
+       
+    1:     def request(self, method, path, body, headers):
+               # Extract the handle_error option header
+   31:         if sys.version_info >= (2,5):
+>>>>>>             handleErrorsKey = 'X-Zope-Handle-Errors'
+               else:
+   31:             handleErrorsKey = 'X-zope-handle-errors'
+   31:         handleErrors = headers.get(handleErrorsKey, True)
+   31:         if handleErrorsKey in headers:
+   27:             del headers[handleErrorsKey]
+       
+               # Construct the request body and call the publisher
+   31:         body = body or ''
+   31:         request = ["%s %s HTTP/1.1" % (method, path)]
+   54:         for hdr, value in headers.items():
+   23:             request.append("%s: %s" % (hdr, value))
+   31:         request_string = "\n".join(request) + "\n\n" + body
+   31:         self._response = RESTCaller()(
+                   request_string, handle_errors=handleErrors)
+       
+    1:     def getresponse(self):
+   30:         return PublisherResponse(self._response)
+       
+    1:     def close(self):
+   30:         self._response = None
+       
+       
+    2: class PublisherResponse(object):
+           """Adapter of Zope 3 response objects into httplib.HTTPResponse."""
+       
+    1:     def __init__(self, response):
+   30:         self._response = response
+   30:         self.status = response.getStatus()
+   30:         self.reason = response._reason
+       
+    1:     def getheaders(self):
+   30:         return self._response.getHeaders()
+       
+    1:     def read(self):
+   30:         return self._response.consumeBody()
+       
+       
+    2: class RESTClient(client.RESTClient):
+    1:     zope.interface.implements(interfaces.IPublisherRESTClient)
+       
+    1:     connectionFactory = PublisherConnection
+       
+    1:     @apply
+           def handleErrors():
+               """See zope.testbrowser.interfaces.IBrowser"""
+    1:         headerKey = 'X-zope-handle-errors'
+       
+    1:         def get(self):
+    2:             return self.requestHeaders.get(headerKey, True)
+       
+    1:         def set(self, value):
+    2:             current_value = get(self)
+    2:             if current_value == value:
+>>>>>>                 return
+    2:             self.requestHeaders[headerKey] = value
+       
+    1:         return property(get, set)

Added: z3c.rest/trunk/coverage/z3c.rest.tests.__init__.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.tests.__init__.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.tests.__init__.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+       # Make a package

Added: z3c.rest/trunk/coverage/z3c.rest.tests.folder.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.tests.folder.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.tests.folder.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,57 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """Test REST view for folders.
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import lxml.etree
+    1: from z3c.rest import rest
+    1: from zope.app.folder import folder
+    1: from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+    1: from zope.app.publication.http import MethodNotAllowed
+    1: from zope.dublincore.interfaces import IZopeDublinCore
+       
+    2: class FolderAPI(rest.RESTView):
+           """A simple REST view for folders."""
+       
+    1:     template = ViewPageTemplateFile("folder.pt")
+       
+    1:     def __init__(self, context, request):
+   31:         super(FolderAPI, self).__init__(context, request)
+   93:         for param in ('noitems', 'notitle'):
+   62:             if 'HTTP_DEMO_' + param.upper() in self.request:
+    3:                 self.request.parameters[param] = 1
+       
+    1:     def GET(self):
+   17:         return self.template()
+       
+    1:     def POST(self):
+    2:         tree = lxml.etree.parse(self.request.bodyStream)
+    2:         title = tree.find('title').text
+    2:         dc = IZopeDublinCore(self.context)
+    2:         dc.title = unicode(title)
+       
+           # For existing resources, PUT pretty much behaves like POST
+    1:     PUT = POST
+       
+    1:     def NullPUT(self, nullResource):
+    4:         name = nullResource.name
+    4:         self.context[name] = folder.Folder()
+    3:         return self.context[name]
+       
+    1:     def DELETE(self):
+    3:         container = self.context.__parent__
+    3:         if container is None:
+    1:             raise MethodNotAllowed(self.context, self.request)
+    2:         del container[self.context.__name__]

Added: z3c.rest/trunk/coverage/z3c.rest.tests.test.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.tests.test.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.tests.test.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,79 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2004 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.
+       #
+       ##############################################################################
+       """REST Tests
+       
+       $Id$
+    1: """
+    1: __docformat__ = "reStructuredText"
+    1: import os
+    1: import unittest
+    1: import zope.component
+    1: from zope.testing import doctest, doctestunit
+    1: from zope.traversing.browser import absoluteurl
+    1: from zope.traversing.interfaces import IContainmentRoot
+    1: from zope.app.testing import functional, placelesssetup
+    1: from z3c.rest import interfaces
+       
+    1: RESTLayer = functional.ZCMLLayer(
+           os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+    1:     __name__, 'RESTLayer', allow_teardown=True)
+       
+    1: def setUp(test):
+    1:     placelesssetup.setUp(test)
+       
+           # XXX: This really needs a REST equivalent w/o breadcrumbs.
+       
+    1:     zope.component.provideAdapter(
+               absoluteurl.AbsoluteURL,
+    1:         (None, interfaces.IRESTRequest),
+    1:         absoluteurl.IAbsoluteURL)
+       
+    1:     zope.component.provideAdapter(
+               absoluteurl.SiteAbsoluteURL,
+    1:         (IContainmentRoot, interfaces.IRESTRequest),
+    1:         absoluteurl.IAbsoluteURL,
+    1:         'absolute_url')
+       
+    1:     zope.component.provideAdapter(
+               absoluteurl.SiteAbsoluteURL,
+    1:         (IContainmentRoot, interfaces.IRESTRequest),
+    1:         absoluteurl.IAbsoluteURL)
+       
+    1:     zope.component.provideAdapter(
+               absoluteurl.AbsoluteURL,
+    1:         (None, interfaces.IRESTRequest),
+    1:         absoluteurl.IAbsoluteURL,
+    1:         'absolute_url')
+       
+       
+    1: def test_suite():
+    1:     client = functional.FunctionalDocFileSuite('../client.txt')
+    1:     client.layer = RESTLayer
+    1:     return unittest.TestSuite((
+               client,
+               doctest.DocFileSuite(
+                   '../rest.txt',
+    1:             globs={'pprint': doctestunit.pprint},
+    1:             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                   ),
+               doctest.DocFileSuite(
+                   '../null.txt',
+    1:             setUp=setUp, tearDown=placelesssetup.tearDown,
+    1:             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                   ),
+               doctest.DocFileSuite(
+                   '../traverser.txt',
+    1:             optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+                   ),
+               ))

Added: z3c.rest/trunk/coverage/z3c.rest.traverser.cover
===================================================================
--- z3c.rest/trunk/coverage/z3c.rest.traverser.cover	                        (rev 0)
+++ z3c.rest/trunk/coverage/z3c.rest.traverser.cover	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,50 @@
+       ##############################################################################
+       #
+       # Copyright (c) 2007 Zope Corporation and Contributors.
+       # All Rights Reserved.
+       #
+       # This software is subject to the provisions of the Zope Public License,
+       # Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+       # THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+       # WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+       # WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+       # FOR A PARTICULAR PURPOSE.
+       #
+       ##############################################################################
+       """Some basic traversers for REST
+       
+       $Id: http.py 72310 2007-02-01 21:39:01Z mkerrin $
+    1: """
+    1: import zope.interface
+    1: from zope.publisher.interfaces.http import IHTTPPublisher
+    1: from zope.app.container.interfaces import IItemContainer
+    1: from zope.publisher.interfaces import NotFound
+    1: from z3c.rest import interfaces, null
+       
+    2: class ItemTraverser(object):
+    1:     zope.interface.implements(IHTTPPublisher)
+    1:     zope.component.adapts(IItemContainer, interfaces.IRESTRequest)
+       
+    1:     def __init__(self, container, request):
+   20:         self.context = container
+   20:         self.request = request
+       
+    1:     def publishTraverse(self, request, name):
+   23:         try:
+   23:             return self.context[name]
+   12:         except KeyError:
+   12:             return self.nullResource(request, name)
+       
+    1:     def nullResource(self, request, name):
+               # we traversed to something that doesn't exist.
+       
+               # The name must be the last name in the path, so the traversal
+               # name stack better be empty:
+   12:         if request.getTraversalStack():
+    2:             raise NotFound(self.context, name, request)
+       
+               # This should only happen for a PUT:
+   10:         if request.method != 'PUT':
+    5:             raise NotFound(self.context, name, request)
+       
+    5:         return null.NullResource(self.context, name)

Added: z3c.rest/trunk/develop-eggs/z3c.rest.egg-link
===================================================================
--- z3c.rest/trunk/develop-eggs/z3c.rest.egg-link	                        (rev 0)
+++ z3c.rest/trunk/develop-eggs/z3c.rest.egg-link	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,2 @@
+/opt/zope/packages/z3c.rest/src
+../
\ No newline at end of file

Added: z3c.rest/trunk/parts/database/Data.fs
===================================================================
(Binary files differ)


Property changes on: z3c.rest/trunk/parts/database/Data.fs
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: z3c.rest/trunk/parts/database/Data.fs.index
===================================================================
(Binary files differ)


Property changes on: z3c.rest/trunk/parts/database/Data.fs.index
___________________________________________________________________
Name: svn:mime-type
   + application/octet-stream

Added: z3c.rest/trunk/parts/database/Data.fs.lock
===================================================================
--- z3c.rest/trunk/parts/database/Data.fs.lock	                        (rev 0)
+++ z3c.rest/trunk/parts/database/Data.fs.lock	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+ 11734

Added: z3c.rest/trunk/parts/demo/zdaemon.conf
===================================================================
--- z3c.rest/trunk/parts/demo/zdaemon.conf	                        (rev 0)
+++ z3c.rest/trunk/parts/demo/zdaemon.conf	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,13 @@
+<runner>
+  daemon on
+  directory /opt/zope/packages/z3c.rest/parts/demo
+  program /opt/zope/packages/z3c.rest/parts/form-demo-app/runzope -C /opt/zope/packages/z3c.rest/parts/demo/zope.conf
+  socket-name /opt/zope/packages/z3c.rest/parts/demo/zdaemon.sock
+  transcript /opt/zope/packages/z3c.rest/parts/demo/z3.log
+</runner>
+
+<eventlog>
+  <logfile>
+    path /opt/zope/packages/z3c.rest/parts/demo/z3.log
+  </logfile>
+</eventlog>

Added: z3c.rest/trunk/parts/demo/zope.conf
===================================================================
--- z3c.rest/trunk/parts/demo/zope.conf	                        (rev 0)
+++ z3c.rest/trunk/parts/demo/zope.conf	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,30 @@
+site-definition /opt/zope/packages/z3c.rest/parts/form-demo-app/site.zcml
+
+<zodb>
+  <filestorage>
+    path /opt/zope/packages/z3c.rest/parts/database/Data.fs
+  </filestorage>
+</zodb>
+
+<server>
+  address 8080
+  type HTTP
+</server>
+
+<server>
+  address 8081
+  type REST-HTTP
+</server>
+
+<accesslog>
+  <logfile>
+    path /opt/zope/packages/z3c.rest/parts/demo/access.log
+  </logfile>
+</accesslog>
+
+<eventlog>
+  <logfile>
+    formatter zope.exceptions.log.Formatter
+    path STDOUT
+  </logfile>
+</eventlog>

Added: z3c.rest/trunk/parts/form-demo-app/debugzope
===================================================================
--- z3c.rest/trunk/parts/form-demo-app/debugzope	                        (rev 0)
+++ z3c.rest/trunk/parts/form-demo-app/debugzope	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,101 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/z3c.rest/src',
+  '/opt/zope/packages/eggs/zope.contentprovider-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zcmlfiles-3.4.3-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.wsgi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.twisted-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.securitypolicy-3.4.6-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.form-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.container-3.5.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.authentication-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.appsetup-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/lxml-1.3.6-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.location-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.event-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.i18n-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.formlib-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.rotterdam-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.basicskin-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.principalannotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zopeappgenerations-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.locales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.i18n-3.4.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.interface-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.generations-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.content-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.dependable-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.annotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.modulealias-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/ZConfig-2.5-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zapi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.server-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.applicationcontrol-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.exceptions-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.copypastemove-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zdaemon-2.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.i18nmessageid-3.4.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.configuration-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deprecation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deferredimport-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.exception-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.http-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.datetime-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.contenttype-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.proxy-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.cachedescriptors-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.broken-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.size-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.filerepresentation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.lifecycleevent-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dottedname-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.thread-3.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.session-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.folder-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.testing-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.testing-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/pytz-2007g-py2.4.egg',
+  '/opt/zope/packages/eggs/zodbcode-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.renderer-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.server-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.hookable-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.session-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.minmax-1.1.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.debug-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/RestrictedPython-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.structuredtext-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/docutils-0.4-py2.4.egg',
+  '/opt/zope/packages/z3c.rest/./src',
+  '/opt/zope/packages/eggs/zc.zope3recipes-0.6.0-py2.4.egg',
+  ]
+
+import zope.app.twisted.main
+
+
+import zc.zope3recipes.debugzope
+
+if __name__ == '__main__':
+    zc.zope3recipes.debugzope.debug(main_module=zope.app.twisted.main)


Property changes on: z3c.rest/trunk/parts/form-demo-app/debugzope
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/parts/form-demo-app/runzope
===================================================================
--- z3c.rest/trunk/parts/form-demo-app/runzope	                        (rev 0)
+++ z3c.rest/trunk/parts/form-demo-app/runzope	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,97 @@
+#!/usr/bin/py24
+
+import sys
+sys.path[0:0] = [
+  '/opt/zope/packages/z3c.rest/src',
+  '/opt/zope/packages/eggs/zope.contentprovider-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zcmlfiles-3.4.3-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.wsgi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.twisted-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.securitypolicy-3.4.6-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.form-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.container-3.5.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.authentication-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.appsetup-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/lxml-1.3.6-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.location-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.event-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.schema-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.i18n-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.formlib-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.rotterdam-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.basicskin-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.principalannotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zopeappgenerations-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.locales-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.i18n-3.4.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.interface-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.generations-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.content-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.dependable-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.annotation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.modulealias-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/ZConfig-2.5-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.zapi-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.server-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.applicationcontrol-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.exceptions-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.copypastemove-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zdaemon-2.0.1-py2.4.egg',
+  '/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.i18nmessageid-3.4.3-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.configuration-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deprecation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.deferredimport-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.exception-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.http-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.error-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.datetime-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.contenttype-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.proxy-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.cachedescriptors-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.broken-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.size-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.filerepresentation-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.lifecycleevent-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.dottedname-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.thread-3.4-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.session-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.folder-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.testing-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.testing-3.5.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/pytz-2007g-py2.4.egg',
+  '/opt/zope/packages/eggs/zodbcode-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.renderer-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.server-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.hookable-3.4.0-py2.4-linux-i686.egg',
+  '/opt/zope/packages/eggs/zope.session-3.4.1-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.minmax-1.1.0-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.app.debug-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/RestrictedPython-3.4.2-py2.4.egg',
+  '/opt/zope/packages/eggs/zope.structuredtext-3.4.0-py2.4.egg',
+  '/opt/zope/packages/eggs/docutils-0.4-py2.4.egg',
+  '/opt/zope/packages/z3c.rest/./src',
+  ]
+
+import zope.app.twisted.main
+
+if __name__ == '__main__':
+    zope.app.twisted.main.main()


Property changes on: z3c.rest/trunk/parts/form-demo-app/runzope
___________________________________________________________________
Name: svn:executable
   + 

Added: z3c.rest/trunk/parts/form-demo-app/site.zcml
===================================================================
--- z3c.rest/trunk/parts/form-demo-app/site.zcml	                        (rev 0)
+++ z3c.rest/trunk/parts/form-demo-app/site.zcml	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,5 @@
+<configure xmlns='http://namespaces.zope.org/zope'
+           xmlns:meta="http://namespaces.zope.org/meta"
+           >
+<include package="z3c.rest" file="application.zcml" />
+</configure>


Property changes on: z3c.rest/trunk/parts/form-demo-app/site.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/rest.prof
===================================================================
--- z3c.rest/trunk/rest.prof	                        (rev 0)
+++ z3c.rest/trunk/rest.prof	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,277 @@
+hotshot-version51405requested-frame-timingsyesrequested-line-eventsnorequested-line-timingsnoplatformlinux2
+executable
+/usr/bin/py24executable-version\2.4.4 (#7, Oct 26 2007, 03:03:08) 
+[GCC 4.2.2 20070909 (prerelease) (4.2.2-0.RC.1mdv2008.0)]observed-interval-getrusage10000observed-interval-gettimeofday2current-directory/opt/zope/packages/z3c.restsys-path-entry/opt/zope/packages/z3c.rest/srcsys-path-entry</opt/zope/packages/eggs/zope.contentprovider-3.4.0-py2.4.eggsys-path-entry2/opt/zope/packages/eggs/setuptools-0.6c7-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.zcmlfiles-3.4.3-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.app.wsgi-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.app.twisted-3.4.0-py2.4.eggsys-path-entry?/opt/zope/packages/eggs/zope.app.securitypolicy-3.4.6-py2.4.eggsys-path-entry9/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.eggsys-path-entry</opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.publisher-3.4.1-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.app.form-3.4.1-py2.4.eggsys-path-entry6/opt/zope/packages/eggs/zope.app.error-3.5.1-py2.4.eggsys-path-entryE/opt/zope/packages/eggs/zope.app.container-3.5.3-py2.4-linux-i686.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.eggsys-path-entry?/opt/zope/packages/eggs/zope.app.authentication-3.4.1-py2.4.eggsys-path-entry9/opt/zope/packages/eggs/zope.app.appsetup-3.4.1-py2.4.eggsys-path-entry6/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/lxml-1.3.6-py2.4-linux-i686.eggsys-path-entry2/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.eggsys-path-entry3/opt/zope/packages/eggs/zope.schema-3.4.0-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.location-3.4.0-py2.4.eggsys-path-entryA/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.eggsys-path-entry2/opt/zope/packages/eggs/zope.event-3.4.0-py2.4.eggsys-path-entry6/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.app.schema-3.4.0-py2.4.eggsys-path-entry=/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.eggsys-path-entry1/opt/zope/packages/eggs/zope.i18n-3.4.0-py2.4.eggsys-path-entry4/opt/zope/packages/eggs/zope.formlib-3.4.0-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.rotterdam-3.4.1-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.basicskin-3.4.0-py2.4.eggsys-path-entryD/opt/zope/packages/eggs/zope.app.principalannotation-3.4.0-py2.4.eggsys-path-entryC/opt/zope/packages/eggs/zope.app.zopeappgenerations-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.app.locales-3.4.0-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.app.i18n-3.4.4-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.interface-3.4.0-py2.4.eggsys-path-entry</opt/zope/packages/eggs/zope.app.generations-3.4.1-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.app.content-3.4.0-py2.4.eggsys-path-entry;/opt/zope/packages/eggs/zope.app.dependable-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.annotation-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.modulealias-3.4.0-py2.4.eggsys-path-entry@/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.eggsys-path-entry-/opt/zope/packages/eggs/ZConfig-2.5-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.app.zapi-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.app.server-3.4.0-py2.4.eggsys-path-entryC/opt/zope/packages/eggs/zope.app.applicationcontrol-3.4.1-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.exceptions-3.4.0-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.copypastemove-3.4.0-py2.4.eggsys-path-entry//opt/zope/packages/eggs/zdaemon-2.0.1-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.eggsys-path-entry;/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.eggsys-path-entryE/opt/zope/packages/eggs/zope.i18nmessageid-3.4.3-py2.4-linux-i686.eggsys-path-entry:/opt/zope/packages/eggs/zope.configuration-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.deprecation-3.4.0-py2.4.eggsys-path-entry;/opt/zope/packages/eggs/zope.deferredimport-3.4.0-py2.4.eggsys-path-entry:/opt/zope/packages/eggs/zope.app.exception-3.4.1-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.app.http-3.4.1-py2.4.eggsys-path-entry2/opt/zope/packages/eggs/zope.error-3.5.1-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.eggsys-path-entry9/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.eggsys-path-entry5/opt/zope/packages/eggs/zope.datetime-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.contenttype-3.4.0-py2.4.eggsys-path-entry=/opt/zope/packages/eggs/zope.proxy-3.4.0-py2.4-linux-i686.eggsys-path-entry=/opt/zope/packages/eggs/zope.cachedescriptors-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.app.broken-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.eggsys-path-entry1/opt/zope/packages/eggs/zope.size-3.4.0-py2.4.eggsys-path-entry?/opt/zope/packages/eggs/zope.filerepresentation-3.4.0-py2.4.eggsys-path-entry;/opt/zope/packages/eggs/zope.lifecycleevent-3.4.0-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.dottedname-3.4.2-py2.4.eggsys-path-entry1/opt/zope/packages/eggs/zope.thread-3.4-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.app.session-3.5.1-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zope.app.folder-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/zope.app.testing-3.4.1-py2.4.eggsys-path-entry4/opt/zope/packages/eggs/zope.testing-3.5.1-py2.4.eggsys-path-entry0/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.eggsys-path-entry,/opt/zope/packages/eggs/pytz-2007g-py2.4.eggsys-path-entry0/opt/zope/packages/eggs/zodbcode-3.4.0-py2.4.eggsys-path-entry9/opt/zope/packages/eggs/zope.app.renderer-3.4.0-py2.4.eggsys-path-entry3/opt/zope/packages/eggs/zope.server-3.4.1-py2.4.eggsys-path-entry@/opt/zope/packages/eggs/zope.hookable-3.4.0-py2.4-linux-i686.eggsys-path-entry4/opt/zope/packages/eggs/zope.session-3.4.1-py2.4.eggsys-path-entry3/opt/zope/packages/eggs/zope.minmax-1.1.0-py2.4.eggsys-path-entry6/opt/zope/packages/eggs/zope.app.debug-3.4.0-py2.4.eggsys-path-entry8/opt/zope/packages/eggs/RestrictedPython-3.4.2-py2.4.eggsys-path-entry;/opt/zope/packages/eggs/zope.structuredtext-3.4.0-py2.4.eggsys-path-entry./opt/zope/packages/eggs/docutils-0.4-py2.4.eggsys-path-entry7/opt/zope/packages/eggs/zc.zope3recipes-0.6.0-py2.4.eggsys-path-entry//opt/zope/packages/z3c.rest/parts/form-demo-appsys-path-entry/opt/zope/packages/z3c.restsys-path-entry/usr/lib/ooo-2.2/programsys-path-entry/opt/python2.4/lib/python24.zipsys-path-entry/opt/python2.4/lib/python2.4sys-path-entry(/opt/python2.4/lib/python2.4/plat-linux2sys-path-entry#/opt/python2.4/lib/python2.4/lib-tksys-path-entry(/opt/python2.4/lib/python2.4/lib-dynloadsys-path-entry*/opt/python2.4/lib/python2.4/site-packagessys-path-entry./opt/python2.4/lib/python2.4/site-packages/PILS3 # N/opt/zope/packages/eggs/zope.app.debug-3.4.0-py2.4.egg/zope/app/debug/debug.pyC bpublish bC 6_request 6#)/opt/python2.4//lib/python2.4/StringIO.pyC6__init__6
+1#'/opt/python2.4//lib/python2.4/urllib.pyC§unquote§
+!#d/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg/zope/app/publication/zopepublication.pyCN__init__N#0/opt/zope/packages/z3c.rest/src/z3c/rest/rest.pyC!__init__!#M/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg/zope/publisher/http.pyCª__init__ªCÀ__init__À)#M/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg/zope/publisher/base.pyC»__init__»Cü_createResponseüCî__init__îC/__init__/
+CóresetóCAresetA			-C@sane_environment@#0/opt/python2.4//lib/python2.4/encodings/utf_8.pyCdecode!Cœ__setupCookiesœ	C¥__setupPath¥Cð_setupPath_helperðC9get9CËgetËCÔgetÔ	C§setTraversalStack§
+	CÚ__setupURLBaseÚCó__deduceServerURLóACÂsetupLocaleÂ#U/opt/zope/packages/eggs/zope.app.twisted-3.4.0-py2.4.egg/twisted/python/components.pyCl_hook l%#	V/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg/zope/app/component/hooks.pyC	]adapter_hook$]C	__get__$C	&adapter_hook$&%	#
+P/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg/zope/publisher/browser.pyC
+ö__init__(ö
+#a/opt/zope/packages/eggs/zope.app.publisher-3.4.1-py2.4.egg/zope/app/publisher/browser/__init__.pyC[getPreferredLanguages,[Cd_getLanguagesData,dC
+ùgetPreferredLanguages(ù9ËÔ
+	C
+ìnormalize_lang(ì1
+#O/opt/zope/packages/eggs/zope.i18n-3.4.0-py2.4.egg/zope/i18n/locales/provider.pyCB	getLocale0B
+	CåsetPublicationå
+	Cš_getResponseš	#
+P/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg/zope/publisher/publish.pyC
+tpublish4t	C×_getPublication×
+C%
+processInputs%
+CRbeforeTraversalR#W/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg/zope/component/globalregistry.pyC–getGlobalSiteManager8–
+#Q/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg/zope/component/registry.pyC†
+getUtility<†	%#`/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg/zope/app/security/principalregistry.pyC%authenticate@% l
+$]#_/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg/zope/app/security/basicauthadapter.pyC__init__D
+Cæ_authUserPWæ	#\/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg/zope/app/security/loginpassword.pyC__init__H		
+C getLoginH 		C>unauthenticatedPrincipal@>
+#M/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg/zope/component/_api.pyCË
+getUtilityLËCÑqueryUtilityLÑC	IgetSiteManager$I
+CƒqueryUtility<ƒ		CòsetPrincipalòCÒsetPrincipalÒ	 l$]#_/opt/zope/packages/eggs/zope.app.security-3.4.0-py2.4.egg/zope/app/security/principallogging.pyC__init__P
+	
+C
+getLogMessagePš	
+#\/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg/zope/security/management.pyCWnewInteractionTW×CMqueryInteractionTM)C7getSecurityPolicyT7	#]/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg/zope/securitypolicy/zopepolicy.pyC6__init__X6	#`/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg/zope/security/simplepolicies.pyC__init__\C add\ 	#R/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/transaction/_manager.pyCtbegin`t#V/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/transaction/_transaction.pyC__init__d#1/opt/python2.4//lib/python2.4/logging/__init__.pyCÔ		getLoggerhÔ	CÇ	getLoggerhÇC«_acquireLockh«#*/opt/python2.4//lib/python2.4/threading.pyC]acquirel]C 
+currentThreadl C,_notel,
+		C·_releaseLockh·	Coreleaselol 	l,	
+		C¯debugh¯CðgetEffectiveLevelhðA	C/_new_transaction`/#H/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/ZODB/utils.pyCö__len__pö#)/opt/python2.4//lib/python2.4/UserDict.pyC__len__t	
+C‡mapp‡CŸas_weakref_listpŸC1<lambda>`1#M/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/ZODB/Connection.pyC€
+_storage_syncx€CÖ_flush_invalidationsxÖi		
+	
+CŒgetApplicationŒCŸgetTraversalStackŸ9ËÔ
+		#E/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/ZODB/DB.pyCºopen|ºl]l 
+l,
+	C”pop|”Cù__contains__pù	# (/opt/python2.4//lib/python2.4/weakref.pyC <__contains__€<	
+CÊopenxÊxÖ
+AC‘
+registerSynch`‘CýaddpýC M__setitem__€MC º__new__€ºC ¿__init__€¿
+
+!Có_connectionMap|ól]l 	l,
+	C£map|£lol 
+l,			lol 
+l,
+	C:__init__:
+C£hold£CˆopenedConnectionˆ	CØrootxØCâgetxâC4gett4C'has_keyt'C__getitem__t
+	#!Y/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg/zope/security/checker.pyC!;ProxyFactory„;E	CÂtraverseÂCítraverseí×
+C}callTraversalHooks}#"_/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg/zope/app/publication/interfaces.pyC"*__init__ˆ*##I/opt/zope/packages/eggs/zope.event-3.4.0-py2.4.egg/zope/event/__init__.pyC#notifyŒ#$N/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg/zope/component/event.pyC$dispatchC|subscribersL|$I
+C¡subscribers<¡#%[/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg/zope/interface/adapter.pyC%’subscribers”’C$objectEventNotifyL|$I
+<¡”’#&U/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg/zope/app/component/site.pyC&òthreadSiteSubscriber˜ò%C	/setSite$/C&bgetSiteManager˜b
+				
+				
+Cb_maybePlacefullyAuthenticatebCÕ<lambda>Õ
+˜b
+<ƒ5@% l	$]$$&D	æ
+H		H 		@>				
+CƒafterTraversalƒbÕ	˜b
+<ƒ@% l$]Dæ	H		H 		@>		#'Y/opt/zope/packages/eggs/zope.app.publication-3.4.2-py2.4.egg/zope/app/publication/http.pyC'A
+callObjectœACjqueryMultiAdapterLj$I
+CÍqueryMultiAdapter<ÍC%ÝqueryMultiAdapter”Ý#(^/opt/zope/packages/eggs/zope.app.component-3.4.1-py2.4.egg/zope/app/component/metaconfigure.pyC(ž__call__ ž"#)8/opt/zope/packages/z3c.rest/src/z3c/rest/tests/folder.pyC)__init__¤CF__init__FCÜ__contains__Ü	9ËÔ
+			Ü9ËÔ
+				#*M/opt/zope/packages/eggs/zope.component-3.4.0-py2.4.egg/zope/component/zcml.pyC*‡proxify¨‡				C–getPositionalArguments–	C
+<mapply4<C
+unwrapMethod4QC
+p
+debug_call4pC)$GET¤$#+k/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg/zope/app/pagetemplate/viewpagetemplatefile.pyC+:__get__¬:C+G__init__¬G
+C+N__call__¬NC++__call__¬+C+"
+pt_getContext¬"#,[/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.egg/zope/pagetemplate/pagetemplate.pyC,T
+pt_getContext°T
+#-]/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg/zope/app/pagetemplate/engine.pyC-Ýpt_getEngine´Ý
+#.F/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.egg/zope/tales/tales.pyC.ÇgetBaseNames¸Ç
+C+>__init__¬>	
+
+C,f	pt_render°f
+#/_/opt/zope/packages/eggs/zope.pagetemplate-3.4.0-py2.4.egg/zope/pagetemplate/pagetemplatefile.pyC/]_cook_check¼]#0*/opt/python2.4//lib/python2.4/posixpath.pyC0getmtimeÀ	•6C,`pt_getEngineContext°`´Ý	C-„
+getContext´„C.ñ__init__¸ñC.‚
+setContext¸‚
+¸‚	¸‚	¸‚
+%	#1K/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg/zope/tal/talinterpreter.pyC1‘__init__Ä‘C.Ô
+getDefault¸Ô	C1Ÿ	popStreamÄŸ
+#2O/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg/zope/tal/translationcontext.pyC2__init__È
+C1‹__call__Ä‹C1Ë	interpretÄËC1Þ
+do_versionÄÞ	C1âdo_modeÄâC1ìdo_setSourceFileÄìC.×
+setSourceFile¸×
+	C1Ëdo_rawtextColumnÄËCÑwriteÑC&_complain_ifclosed&	!	C1þdo_startTagÄþÑ&
+C1§do_rawtextBeginScope_talħÑ&	C.ÚsetPosition¸Ú
+C.†
+beginScope¸†%C.šsetLocal¸š
+	ÄþÑ&		C1îdo_insertText_talÄîC.¿evaluateText¸¿C.³evaluate¸³#3L/opt/zope/packages/eggs/zope.tales-3.4.0-py2.4.egg/zope/tales/expressions.pyC3Ö__call__ÌÖ
+C3¶_eval̶C3l_evalÌlC-5__call__´5#4S/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg/zope/traversing/adapters.pyC4ztraversePathElementÐz l=$]#5e/opt/zope/packages/eggs/zope.app.container-3.5.3-py2.4-linux-i686.egg/zope/app/container/traversal.pyC5Y__init__ÔY
+
+C5]traverseÔ]C‡checkPermissionX‡Õ
+Cµ
+_groupsForXµ!CFcached_decisionXFC=cacheX=Cqcached_prinperXq!X= l$]#6Y/opt/zope/packages/eggs/zope.security-3.4.0-py2.4-linux-i686.egg/zope/security/adapter.pyC6P__call__ØP
+#7^/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg/zope/securitypolicy/securitymap.pyC7‚__init__Ü‚
+ l
+$]#8T/opt/zope/packages/eggs/zope.annotation-3.4.0-py2.4.egg/zope/annotation/attribute.pyC8#__init__à#	
+C8)getà)5C6J_customizeUnprotectedØJ	
+#9f/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg/zope/securitypolicy/principalpermission.pyC93
+getSettingä3C7S	queryCellÜS	XqX=C9g
+getSettingägÜS
+	
+C®cached_rolesX®X=X®X=#:a/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg/zope/securitypolicy/rolepermission.pyC:XgetRolesForPermissionèXC7agetRowÜa	1 l
+$]ØPÜ‚ l$]à#		à)!ØJ		C7__nonzero__Ü
+Cåcached_principal_rolesXåX=XåX=#;`/opt/zope/packages/eggs/zope.securitypolicy-3.4.0-py2.4.egg/zope/securitypolicy/principalrole.pyC;YgetRolesForPrincipalìYC7hgetColÜh	 l$]ØPÜ‚ l
+$]à#	
+à)ØJ	
+Ü	-#<Q/opt/zope/packages/eggs/zope.app.folder-3.4.0-py2.4.egg/zope/app/folder/folder.pyC<@getð@
+-5	C-1<lambda>´1		
+)	
+¸Ô	
+	ħÑ&!¸Ú	C.‹endScope¸‹!¸†%¸š
+	C1Õdo_conditionÄÕC.¼evaluateBoolean¸¼¸³C3—__call__Ì—¸¼¸³ÌÖ̶Ìl´5	Ðz l$]C4&__init__Ð&
+
+
+C4)traverseÐ)CÌ__getitem__Ì9ËÔ	!-)
+Ìl
+´5	
+!!
+			ÄËÄþÑ&	
+Ä¸³ÌÖ̶Ìl´5C-ò	namespace´òCW
+getAdapterLWC]queryAdapterL]$]#=_/opt/zope/packages/eggs/zope.app.pagetemplate-3.4.0-py2.4.egg/zope/app/pagetemplate/talesapi.pyC=!__init__ô!
+
+			C=$	setEngineô$
+	´5Ðz l
+$]Ð&	
+Ð)C='titleô' l9$]ØP#>]/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.egg/zope/dublincore/annotatableadapter.pyC>'__init__ø' l	$]à#		à)!#?Y/opt/zope/packages/eggs/zope.dublincore-3.4.0-py2.4.egg/zope/dublincore/zopedublincore.pyC?g__init__üg	
+	C6k_customizeProtectedØkØJ!	„;)
+
+X‡Õ
+XµXFX=XqX= l$]XqX= l$]ØP	Ü‚ l$]à#		à)!ØJ	
+ä3ÜS
+	XqX=äg
+ÜS
+	
+X®X=X®X=X®X=
+èX
+Üa	1 l$]ØP	Ü‚ l	$]à#		à)ØJ	
+Ü	 l
+$]	XåX=XåX=
+
+ l$]	)C?!__get__ü!t4t'			´1		%		¸Ô
+C1ã
+_writeTextÄãÑ&			C1Ðdo_rawtextOffsetÄÐÑ&	
+
+	ħÑ&	¸Ú
+¸‹)¸†%¸š
+	ÄÕ¸¼¸³Ì—¸¼¸³ÌÖ̶Ìl´5	Ðz l$]Ð&
+
+	Ð)Ì9ËÔ		)%
+Ìl	´5
+
+%
+	
+
+	ÄËÄþÑ&	
+C1õdo_setPositionÄõ¸Ú		C1ºdo_beginScope_tal帆)¸š
+	C1µdo_loop_talĵC.©	setRepeat¸©¸³ÌÖ̶Ìl´5Ðz l=$]ÔY
+	Ô]X‡Õ	XµXFX=
+ð@	!X‡	Õ	XµXFX=
+!	´1		
+C<.valuesð.!		C.@__init__¸@u!C.tnext¸t¸š
+	ÄËÄËÑ&	
+C1údo_startEndTagÄúÄþC1×attrAction_talÄ׸¿¸³ÌÖ̶Ìl´5Ðz#@T/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg/zope/traversing/namespace.pyC at unsParse€uC@(namespaceLookup€(Lj$I
+<Í”ÝC@Ñ__init__€Ñ!
+		C@Õtraverse€ÕLj	$I
+<͔ݠžC
+³__init__(³¨‡						
+´1	
+#A^/opt/zope/packages/eggs/zope.traversing-3.4.0-py2.4.egg/zope/traversing/browser/absoluteurl.pyCA*__str__„*CÁgetVirtualHostRootÁ
+CdgetMultiAdapterLdLj$I
+<͔ݠž(³
+¨‡					CAl__str__„lÁ	C“getApplicationURL“%CAF_getContextName„FC¾quote¾=	
+	¸Ô#BD/opt/zope/packages/eggs/zope.tal-3.4.0-py2.4.egg/zope/tal/taldefs.pyCBÇquoteˆÇ	#C$/opt/python2.4//lib/python2.4/cgi.pyCC—escapeŒ—)Ä×
+¸¿¸³ÌÖ̶Ìl´5Ðz l=$]ÔY
+
+Ô]X‡Õ
+XµXFX=XqX= l$]ØP	Ü‚ l
+$]à#	
+à)!ØJ		ä3ÜS
+	XqX=
+
+X®X=X®X=	 l
+$]ØP	Ü‚ l
+$]à#		à)ØJ		Ü	Xå	X=XåX=
+ l	$]ØPÜ‚ l
+$]à#		à)ØJ		Ü
+
+1ð@
+1	´1		%		¸Ô	
+ˆÇŒ—1Ñ&	
+
+
+¸t¸š	ÄËÄËÑ&		ÄúÄþÄ׸¿¸³ÌÖ̶Ìl´5Ðz€u€(Lj$I
+<͔݀Ñ
+	€ÕLj$I	<͔ݠž(³
+¨‡						
+´1	
+
+„*Á
+LdLj$I
+<͔ݠž(³
+¨‡
+			„lÁ	“%„F¾	1
+	
+¸Ô	ˆÇŒ—!Ä×	¸¿¸³ÌÖ̶Ìl´5Ðz l=$]ÔY(
+
+Ô]X‡Õ
+XµXFX=!XqX= l$]ØP	Ü‚ l
+$]à#	
+à)!1ØJ	
+ä3ÜS	XqX=	X®X=X®X=
+
+ l
+$]ØP	Ü‚ l
+$]à#		à)ØJ		Ü
+XåX=XåX=
+ l$]ØPÜ‚ l
+$]à#		à)ØJ	
+Ü
+
+-ð@
+-
+´1		
+%	
+¸ÔˆÇŒ—-Ñ&	
+
+
+¸t		C1Ádo_endScopeÄÁ¸‹1ÄËÑ&	
+
+ÄÁ¸‹
+ÄËÑ&		
+Cƒgetvalueƒ	=	š
+
+C¨	getHeader¨C—	setHeader—	
+			š	Cñ	setResultñLj$I
+<Í”ÝQ		C”_implicitResult”CÉgetCharsetUsingRequestÉ l$]C—__init__—	
+	CšgetPreferredCharsetsšÜ¬9ËÔ			9ËÔ	19¨#DT/opt/zope/packages/eggs/zope.publisher-3.4.1-py2.4.egg/zope/publisher/contenttype.pyCDparse
+CD$parseOrdered$CD`_check_token`
+-`	MC‚<generator expression>‚
+
+‚	‚	Cþ	setStatusþ
+-	C©	afterCall©C‚get`‚CÂisDoomeddÂ
+C'6annotateTransactionœ6CµannotateTransactionµÕ	Õ	CôsetUserdô lA$]C4<__init__Ð<
+	C4?getPathÐ?	C÷setExtendedInfod÷	#E`/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg/zope/interface/declarations.pyCER__iter__”R#F]/opt/zope/packages/eggs/zope.interface-3.4.1-py2.4-linux-i686.egg/zope/interface/interface.pyCFÂ
+interfaces˜ÂCF¡<lambda>˜¡CFî
+interfaces˜î	
+CFäextends˜ä%CFEgetName˜E	d÷
+	CgetURLd÷		CµcommitdµCð_callBeforeCommitHooksdð
+p‡pŸCÁ<lambda>dÁCùbeforeCompletionxù	dÁxù		CŸ_commitResourcesdŸ!CŒfree`Œp‡pŸ
+CÎ<lambda>dÎx€xÖ	U		dÎx€xÖ9		
+C_callAfterCommitHooksd	h¯hð9			C±
+endRequest±CbendInteractionTbC"8__init__ˆ8ŒL|$I
+<¡”’C&úclearThreadSiteSubscriber˜ú$/8–						
+	š
+C‹close‹C=release=
+C’closex’C˜unregisterSynch`˜
+C‚removep‚C__delitem__t
+
+	CÓ
+_returnToPool|Ól]l l,			#GR/opt/zope/packages/eggs/ZODB3-3.8.0b4-py2.4-linux-i686.egg/ZODB/ActivityMonitor.pyCG$closedConnectionœ$	CŽgetTransferCountsxŽCG+trimœ+	Cprepush|ppù€<
+	C{_reduce_size|{lol 
+l,					
+)CA__del__A
+
+š	C²
+getHeaders²Cì_cookie_listì #H'/opt/python2.4//lib/python2.4/Cookie.pyCH·__init__ ·	CHÈoutput Èš	C“getStatusString“)š	CŠconsumeBodyŠ
+C	getStatus>
+	
\ No newline at end of file

Added: z3c.rest/trunk/setup.py
===================================================================
--- z3c.rest/trunk/setup.py	                        (rev 0)
+++ z3c.rest/trunk/setup.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,78 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Foundation 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.
+#
+##############################################################################
+"""Setup
+
+$Id$
+"""
+import os
+from setuptools import setup, find_packages
+
+def read(*rnames):
+    return open(os.path.join(os.path.dirname(__file__), *rnames)).read()
+
+setup (
+    name='z3c.rest',
+    version='1.5.1',
+    author = "Stephan Richter and the Zope Community",
+    author_email = "zope3-dev at zope.org",
+    description = "A REST Framework for Zope 3 Applications",
+    long_description=(
+        read('README.txt')
+        + '\n\n' +
+        read('CHANGES.txt')
+        ),
+    license = "ZPL 2.1",
+    keywords = "zope3 form widget",
+    classifiers = [
+        'Development Status :: 4 - Beta',
+        'Environment :: Web Environment',
+        'Intended Audience :: Developers',
+        'License :: OSI Approved :: Zope Public License',
+        'Programming Language :: Python',
+        'Natural Language :: English',
+        'Operating System :: OS Independent',
+        'Topic :: Internet :: WWW/HTTP',
+        'Framework :: Zope3'],
+    url = 'http://cheeseshop.python.org/pypi/z3c.rest',
+    packages = find_packages('src'),
+    include_package_data = True,
+    package_dir = {'':'src'},
+    namespace_packages = ['z3c'],
+    extras_require = dict(
+        app = ['zope.app.appsetup',
+               'zope.app.authentication',
+               'zope.app.component',
+               'zope.app.container',
+               'zope.app.error',
+               'zope.app.form',
+               'zope.app.publisher',
+               'zope.app.publication',
+               'zope.app.security',
+               'zope.app.securitypolicy',
+               'zope.app.twisted',
+               'zope.app.wsgi',
+               'zope.app.zcmlfiles',
+               'zope.contentprovider',
+               ],
+        test = ['z3c.coverage',
+                'z3c.etestbrowser',
+                'zope.app.testing'],
+        ),
+    install_requires = [
+        'lxml',
+        'setuptools',
+        'zope.publisher',
+        ],
+    zip_safe = False,
+    )


Property changes on: z3c.rest/trunk/setup.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/__init__.py
===================================================================
--- z3c.rest/trunk/src/z3c/__init__.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/__init__.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,8 @@
+try:
+    # Declare this a namespace package if pkg_resources is available.
+    import pkg_resources
+    pkg_resources.declare_namespace('z3c')
+except ImportError:
+    pass
+
+


Property changes on: z3c.rest/trunk/src/z3c/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/README.txt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/README.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/README.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,29 @@
+===================================================
+A Framework for Building RESTive Services in Zope 3
+===================================================
+
+This package implements several components that relate to building RESTive Web
+services using the Zope publisher. Each set of components is documented in a
+corresponding text file.
+
+* ``client.txt`` [must read]
+
+  This package also provides a REST Web client, which can be used for testing
+  or for accessing a RESTive API within an application.
+
+* ``null.txt`` [advanced user]
+
+  In order to create new resources, the publisher must be able to traverse to
+  resources/objects that do not yet exist. This file explains how those null
+  resources work.
+
+* ``traverser.txt`` [advanced user]
+
+  The ``traverser`` module contains several traversal helper components for
+  common traversal scenarios, suhc as containers and null resources.
+
+* ``rest.txt`` [informative]
+
+  This document introduces the hooks required to manage RESTive requests in
+  the publisher. It also discusses hwo those components are used by the
+  publisher.


Property changes on: z3c.rest/trunk/src/z3c/rest/README.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/__init__.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/__init__.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/__init__.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+# Make a package


Property changes on: z3c.rest/trunk/src/z3c/rest/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/application.zcml
===================================================================
--- z3c.rest/trunk/src/z3c/rest/application.zcml	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/application.zcml	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,72 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:browser="http://namespaces.zope.org/browser"
+    i18n_domain="rest">
+
+  <include package="zope.app.component" file="meta.zcml" />
+  <include package="zope.app.component.browser" file="meta.zcml" />
+  <include package="zope.app.container.browser" file="meta.zcml" />
+  <include package="zope.app.form.browser" file="meta.zcml" />
+  <include package="zope.app.pagetemplate" file="meta.zcml" />
+  <include package="zope.app.publication" file="meta.zcml" />
+  <include package="zope.app.publisher" file="meta.zcml" />
+  <include package="zope.app.security" file="meta.zcml" />
+  <include package="zope.app.securitypolicy" file="meta.zcml" />
+
+  <browser:menu id="zmi_views" title="Views" />
+  <browser:menu id="zmi_actions" title="Actions" />
+
+  <include package="zope.app.appsetup" />
+  <include package="zope.app.authentication" />
+  <include package="zope.app.component" />
+  <include package="zope.app.container" />
+  <include package="zope.app.error" />
+  <include package="zope.app.folder" />
+  <include package="zope.app.http" />
+  <include package="zope.app.i18n" />
+  <include package="zope.app.pagetemplate" />
+  <include package="zope.app.publication" />
+  <include package="zope.app.security" />
+  <include package="zope.app.securitypolicy" />
+  <include package="zope.app.session" />
+  <include package="zope.app.twisted" />
+  <include package="zope.app.wsgi" />
+  <include package="zope.annotation" />
+  <include package="zope.component" />
+  <include package="zope.contentprovider" />
+  <include package="zope.dublincore" />
+  <include package="zope.location" />
+  <include package="zope.publisher" />
+  <include package="zope.traversing" />
+  <include package="zope.traversing.browser" />
+
+
+  <include file="configure.zcml" />
+  <include package=".tests" file="folder.zcml" />
+
+  <securityPolicy
+      component="zope.securitypolicy.zopepolicy.ZopeSecurityPolicy" />
+
+  <role id="zope.Anonymous" title="Everybody" />
+  <grant permission="zope.View"
+         role="zope.Anonymous" />
+  <grant permission="zope.app.dublincore.view"
+         role="zope.Anonymous" />
+
+  <role id="zope.Manager" title="Site Manager" />
+  <grantAll role="zope.Manager" />
+
+  <principal
+      id="zope.mgr"
+      title="Manager"
+      login="mgr"
+      password="mgrpw" />
+
+  <principal
+      id="zope.globalmgr"
+      title="Manager"
+      login="globalmgr"
+      password="globalmgrpw" />
+
+  <grant role="zope.Manager" principal="zope.globalmgr" />
+</configure>


Property changes on: z3c.rest/trunk/src/z3c/rest/application.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/client.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/client.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/client.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,201 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST Client
+
+$Id$
+"""
+import lxml
+import httplib
+import socket
+import urllib
+import urlparse
+import base64
+import zope.interface
+from z3c.rest import interfaces
+
+def isRelativeURL(url):
+    """Determines whether the given URL is a relative path segment."""
+    pieces = urlparse.urlparse(url)
+    if not pieces[0] and not pieces[1]:
+        return True
+    return False
+
+def absoluteURL(base, url):
+    """Convertes a URL to an absolute URL given a base."""
+    if isRelativeURL(url):
+        fullUrl = urlparse.urljoin(base, url)
+    else:
+        fullUrl = url
+    pieces = list(urlparse.urlparse(fullUrl))
+    if not pieces[2].endswith('/'):
+        pieces[2] += '/'
+    return urlparse.urlunparse(pieces)
+
+def getFullPath(pieces, params):
+    """Build a full httplib request path, including a query string."""
+    query = ''
+    if pieces[4]:
+        query = pieces[4]
+    if params:
+        encParams = urllib.urlencode(params)
+        if query:
+            query += '&' + encParams
+        else:
+            query = encParams
+    return urlparse.urlunparse(
+        ('', '', pieces[2], pieces[3], query, pieces[5]))
+
+
+class XLink(object):
+    """A link implementation for simple XLinks."""
+    zope.interface.implements(interfaces.ILink)
+
+    def __init__(self, client, title, url):
+        self._client = client
+        self.title = title
+        self.url = url
+
+    def click(self):
+        """See interfaces.ILink"""
+        self._client.get(self.url)
+
+    def __repr__(self):
+        return '<%s title=%r url=%r>' %(
+            self.__class__.__name__, self.title, self.url)
+
+
+class RESTClient(object):
+    zope.interface.implements(interfaces.IRESTClient)
+
+    connectionFactory = httplib.HTTPConnection
+
+    def __init__(self, url=None):
+        self.requestHeaders = {}
+        self._reset()
+        self._history = []
+        self._requestData = None
+        self.url = ''
+        if url:
+            self.open(url)
+
+    @property
+    def fullStatus(self):
+        return '%i %s' %(self.status, self.reason)
+
+    def _reset(self):
+        self.headers = []
+        self.contents = {}
+        self.status = None
+        self.reason = None
+
+    def open(self, url='', data=None, params=None, headers=None, method='GET'):
+        # Create a correct absolute URL and set it.
+        self.url = absoluteURL(self.url, url)
+
+        # Create the full set of request headers
+        requestHeaders = self.requestHeaders.copy()
+        if headers:
+            requestHeaders.update(headers)
+
+        # Let's now reset all response values
+        self._reset()
+
+        # Store all the request data
+        self._requestData = (url, data, params, headers, method)
+
+        # Make a connection and retrieve the result
+        pieces = urlparse.urlparse(self.url)
+        connection = self.connectionFactory(pieces[1])
+        try:
+            connection.request(
+                method, getFullPath(pieces, params), data, requestHeaders)
+            response = connection.getresponse()
+            connection.close()
+        except socket.error, e:
+            connection.close()
+            self.status, self.reason = e.args
+            self._addHistory()
+            raise e
+        else:
+            self.headers = response.getheaders()
+            self.contents = response.read()
+            self.status = response.status
+            self.reason = response.reason
+            self._addHistory()
+
+    def get(self, url='', params=None, headers=None):
+        self.open(url, None, params, headers)
+
+    def put(self, url='', data='', params=None, headers=None):
+        self.open(url, data, params, headers, 'PUT')
+
+    def post(self, url='', data='', params=None, headers=None):
+        self.open(url, data, params, headers, 'POST')
+
+    def delete(self, url='', params=None, headers=None):
+        self.open(url, None, params, headers, 'DELETE')
+
+    def setCredentials(self, username, password):
+        creds = username + u':' + password
+        creds = "Basic " + base64.encodestring(creds.encode('utf-8')).strip()
+        self.requestHeaders['Authorization'] = creds
+
+    def _addHistory(self):
+        self._history.append((
+            self.url, self.requestHeaders, self.headers, self.contents,
+            self.status, self.reason, self._requestData
+            ))
+
+    def goBack(self, count=1):
+        # The user really does not want to go back.
+        if count == 0:
+            return
+        # The user wants to reach before a pre-historical state.
+        if len(self._history) < count:
+            raise ValueError('There is not enough history.')
+        # Let's now get the entry and set the history back to that state.
+        entry = self._history[-(count+1)]
+        self._history = self._history[:-count]
+        # Reset the state.
+        (self.url, self.requestHeaders, self.headers, self.contents,
+         self.status, self.reason, self._requestData) = entry
+
+    def reload(self):
+        self.open(*self._requestData)
+
+    def getLink(self, title=None, url=None, index=0):
+        nsmap = {'xlink': "http://www.w3.org/1999/xlink"}
+        tree = lxml.etree.fromstring(self.contents)
+        res = []
+        if title is not None:
+            res = tree.xpath(
+                '//*[@xlink:title="%s"]' %title, nsmap)
+        elif url is not None:
+            res = tree.xpath(
+                '//*[@xlink:href="%s"]' %url, nsmap)
+        else:
+            raise ValueError('You must specify a title or URL.')
+        elem = res[index]
+        url = elem.attrib.get('{%(xlink)s}href' %nsmap, '')
+        return XLink(self,
+                     elem.attrib.get('{%(xlink)s}title' %nsmap),
+                     absoluteURL(self.url, url))
+
+    def xpath(self, expr, nsmap=None, single=False):
+        res = lxml.etree.fromstring(self.contents).xpath(expr, nsmap)
+        if not single:
+            return res
+        if len(res) != 1:
+            raise ValueError('XPath expression returned more than one result.')
+        return res[0]


Property changes on: z3c.rest/trunk/src/z3c/rest/client.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/client.txt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/client.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/client.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,508 @@
+===========
+REST Client
+===========
+
+The REST client provides a simple Python API to interact easily with RESTive
+Web services. It was designed with to have a similar API to Zope's test
+browser.
+
+Let's start by instantiating the the client. Of course we have a version of
+the client that talks directly to the Zope publisher:
+
+  >>> from z3c.rest import testing
+  >>> client = testing.RESTClient()
+
+For testing purposes, we have defined a simple REST API for folders. The
+simplest call is to retrieve the contents of the root folder:
+
+  >>> client.open('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+    </items>
+  </folder>
+
+You can also instantiate the client providing a URL:
+
+  >>> client = testing.RESTClient('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+    </items>
+  </folder>
+
+
+Getting Resources
+-----------------
+
+The ``open()`` method implicitely uses the "GET" HTTP method. An alternative
+would be to use this:
+
+  >>> client.get('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+    </items>
+  </folder>
+
+There are several other pieces of information of the response that are
+available:
+
+  >>> client.url
+  'http://localhost/'
+  >>> client.status
+  200
+  >>> client.reason
+  'Ok'
+  >>> client.fullStatus
+  '200 Ok'
+  >>> client.headers
+  [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'),
+   ('Content-Length', '140'),
+   ('Content-Type', 'text/xml;charset=utf-8')]
+
+If we try to access a non-existent resource, no exception is raised, but the
+status is '404' (not found) of course:
+
+  >>> client.get('http://localhost/unknown')
+  >>> client.fullStatus
+  '404 Not Found'
+  >>> client.contents
+  ''
+  >>> client.headers
+  [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'),
+   ('Content-Length', '0')]
+
+As in the original test browser, I can turn off the Zope error handling and
+the Python exception will propagate through the publisher:
+
+  >>> client.handleErrors = False
+  >>> client.get('http://localhost/unknown')
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: <zope.app.folder.folder.Folder ...>, name: u'unknown'
+
+  >>> client.handleErrors = True
+
+As RESTive APIs often use query string key-value pairs to parameterize the
+request, this REST client has strong support for it. For example, you can
+simply specify the parameters in the URL:
+
+  >>> client.get('http://localhost/?noitems=1')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+  </folder>
+
+You can also specify the parameter via an argument:
+
+  >>> client.get('http://localhost/', params={'noitems': 1})
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+  </folder>
+
+You can even combine the two methods of specifying parameters:
+
+  >>> client.get('http://localhost/?noitems=1', params={'notitle': 1})
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+  </folder>
+
+But our little demo API can do morw. Parameters can also be specified as a
+header with a special prefix. Headers can be globally specified and are then
+used for every request:
+
+  >>> client.requestHeaders['demo-noitems'] = 'on'
+  >>> client.get('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+  </folder>
+
+There is also a headers argument to the "open" methods that specify the header
+once:
+
+  >>> client.get('http://localhost/', headers={'demo-notitle': 1})
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+  </folder>
+
+  >>> del client.requestHeaders['demo-noitems']
+
+Finally, when dealing with a real site, a socket error might occur. The error
+is propagated, but the error number and message are recorded:
+
+  >>> from z3c.rest.client import RESTClient
+  >>> realClient = RESTClient()
+  >>> realClient.open('http://localhost:65000')
+  Traceback (most recent call last):
+  ...
+  error: (111, 'Connection refused')
+
+  >>> realClient.fullStatus
+  '111 Connection refused'
+
+
+Creating new resources
+----------------------
+
+Let's now create a new resource in the server root. Our little sample
+application will simply create another collection:
+
+  >>> client.put(
+  ...     'http://localhost/folder1',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder />''')
+
+  >>> client.fullStatus
+  '401 Unauthorized'
+
+Accessing the folder resource is available to everyone. But if you want to
+modify any resource, you have to log in:
+
+  >>> client.setCredentials('globalmgr', 'globalmgrpw')
+
+So let's try this again:
+
+  >>> client.put(
+  ...     'http://localhost/folder1',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder />''')
+
+  >>> client.fullStatus
+  '201 Created'
+  >>> client.headers
+  [('X-Powered-By', 'Zope (www.zope.org), Python (www.python.org)'),
+   ('Content-Length', '0'),
+   ('Location', 'http://localhost/folder1')]
+
+We can now look at the root container and see the item there:
+
+  >>> client.get('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder1"
+            xlink:title="folder1"/>
+    </items>
+  </folder>
+
+By the way, you can now use a relative URL to access the `folder1` resource:
+
+  >>> client.get('folder1')
+
+  >>> client.url
+  'http://localhost/folder1/'
+
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name>folder1</name>
+    <title></title>
+    <items>
+    </items>
+  </folder>
+
+When we try to create a resource on top of a non-existent resource, we get a
+404 error:
+
+  >>> client.put(
+  ...     'http://localhost/folder2/folder21',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder />''')
+
+  >>> client.fullStatus
+  '404 Not Found'
+
+
+Modifying Resources
+-------------------
+
+Modifying a given resource can be done via POST or PUT, but they have different
+semantics. Let's have a look at POST first. We would now like to change the
+title of the folder; this can be done as follows:
+
+  >>> client.post(
+  ...     'http://localhost/folder1',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder>
+  ...          <title>My Folder 1</title>
+  ...        </folder>''')
+
+  >>> client.fullStatus
+  '200 Ok'
+
+  >>> client.get()
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name>folder1</name>
+    <title>My Folder 1</title>
+    <items>
+    </items>
+  </folder>
+
+As mentioned above, it must also work for PUT:
+
+  >>> client.put(
+  ...     'http://localhost/folder1',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder>
+  ...          <title>Folder 1</title>
+  ...        </folder>''')
+
+  >>> client.fullStatus
+  '200 Ok'
+
+  >>> client.get()
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name>folder1</name>
+    <title>Folder 1</title>
+    <items>
+    </items>
+  </folder>
+
+
+Deleting Resources
+------------------
+
+Deleting a resource is as simple as all of the other methods. Let's delete our
+`folder1`:
+
+  >>> client.delete('http://localhost/folder1')
+
+  >>> client.fullStatus
+  '200 Ok'
+
+So the resource is really gone:
+
+  >>> client.get()
+  >>> client.fullStatus
+  '404 Not Found'
+
+It should not be possible to delete a non-existing resource:
+
+  >>> client.delete('http://localhost/folder2')
+  >>> client.fullStatus
+  '404 Not Found'
+
+Also, we cannot delete the root folder:
+
+  >>> client.delete('http://localhost/')
+  >>> client.fullStatus
+  '405 Method Not Allowed'
+
+
+Searching the Response Data
+---------------------------
+
+While not required, most REST services are XML-based. Thus, the client
+supports inspecting the result XML using XPath. Let's create a couple of
+folders for this to be more interesting:
+
+  >>> client.put(
+  ...     'http://localhost/folder1',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder />''')
+
+  >>> client.put(
+  ...     'http://localhost/folder2',
+  ...     '''<?xml version="1.0" ?>
+  ...        <folder />''')
+
+Next we get the root folder resource:
+
+  >>> client.get('http://localhost/')
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder1"
+            xlink:title="folder1"/>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder2"
+            xlink:title="folder2"/>
+    </items>
+  </folder>
+
+But in general, inspecting the XML output on the string level is tedious. So
+let's write a cool XPath expression that extracts the xlink title of all
+items:
+
+  >>> nsmap = {'xlink': "http://www.w3.org/1999/xlink"}
+  >>> client.xpath('//folder/items/item/@xlink:title', nsmap)
+  ['folder1', 'folder2']
+
+Oftentimes, however, we specifically query for one result. In those cases we
+do not want to receive a list:
+
+  >>> client.xpath('//folder/items/item[@xlink:title="folder1"]', nsmap, True)
+  <Element item ...>
+
+Now, if multiple matches are detected, even though we only expect one, then a
+``ValueError`` is raised:
+
+  >>> client.xpath('//folder/items/item', nsmap, True)
+  Traceback (most recent call last):
+  ...
+  ValueError: XPath expression returned more than one result.
+
+
+Accessing Links
+---------------
+
+Since we want the REST client to behave like a browser -- at least a little
+bit -- we can also use the ``getLink()`` method to access links:
+
+  >>> client.getLink('folder1')
+  <XLink title='folder1' url='http://localhost/folder1/'>
+
+By default, the link is looked up by title. But you can also look it up by
+URL:
+
+  >>> client.getLink(url='http://localhost/folder1')
+  <XLink title='folder1' url='http://localhost/folder1/'>
+
+If you forget to specify a title or URL, you receive a ``ValueError``:
+
+  >>> client.getLink()
+  Traceback (most recent call last):
+  ...
+  ValueError: You must specify a title or URL.
+
+The cool part about the link is that you can click it:
+
+  >>> client.url
+  'http://localhost/'
+
+  >>> client.getLink('folder1').click()
+
+  >>> client.url
+  'http://localhost/folder1/'
+
+
+Moving through time
+-------------------
+
+Like in a real browser, you can go back to a previous state. For example,
+currently we are looking at `folder1`, ...
+
+  >>> client.url
+  'http://localhost/folder1/'
+
+but if I go back one step, I am back at the root folder:
+
+  >>> client.goBack()
+
+  >>> client.url
+  'http://localhost/'
+
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder1"
+            xlink:title="folder1"/>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder2"
+            xlink:title="folder2"/>
+    </items>
+  </folder>
+
+But going back in history is only cool, if you can also reload. So let's
+delete `folder2`:
+
+  >>> client.getLink('folder2').click()
+  >>> client.delete()
+
+Now we go back 2 steps:
+
+  >>> client.goBack(2)
+
+  >>> client.url
+  'http://localhost/'
+
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder1"
+            xlink:title="folder1"/>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder2"
+            xlink:title="folder2"/>
+    </items>
+  </folder>
+
+As expected, the contents has not changed yet. So let's reload:
+
+  >>> client.reload()
+
+  >>> client.url
+  'http://localhost/'
+
+  >>> print client.contents
+  <?xml version="1.0" ?>
+  <folder xmlns:xlink="http://www.w3.org/1999/xlink">
+    <name></name>
+    <title></title>
+    <items>
+      <item xlink:type="simple"
+            xlink:href="http://localhost/folder1"
+            xlink:title="folder1"/>
+    </items>
+  </folder>
+
+Note that going back zero steps does nothing:
+
+  >>> client.url
+  'http://localhost/'
+
+  >>> client.getLink('folder1').click()
+  >>> client.goBack(0)
+
+  >>> client.url
+  'http://localhost/folder1/'
+
+Also, if you try to go back beyond the beginning of time, a value error is
+raised:
+
+  >>> client.goBack(1000)
+  Traceback (most recent call last):
+  ...
+  ValueError: There is not enough history.


Property changes on: z3c.rest/trunk/src/z3c/rest/client.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/configure.zcml
===================================================================
--- z3c.rest/trunk/src/z3c/rest/configure.zcml	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/configure.zcml	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,70 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope"
+    xmlns:zcml="http://namespaces.zope.org/zcml">
+
+  <!-- NULL Resource support -->
+
+  <class class=".null.NullResource">
+    <allow interface="zope.app.http.interfaces.INullResource" />
+  </class>
+
+  <!-- Basic Container traversers -->
+
+  <view
+      for="zope.app.http.interfaces.INullResource"
+      name="PUT"
+      type=".interfaces.IRESTRequest"
+      factory=".null.NullPUT"
+      permission="zope.Public"
+      allowed_attributes="PUT"
+      />
+
+  <view
+      for="zope.app.container.interfaces.IItemContainer"
+      type=".interfaces.IRESTRequest"
+      provides="zope.publisher.interfaces.IPublishTraverse"
+      factory=".traverser.ItemTraverser"
+      permission="zope.Public"
+      allowed_interface="zope.publisher.interfaces.IPublishTraverse"
+      />
+
+  <view
+      for="zope.app.container.interfaces.ISimpleReadContainer"
+      type=".interfaces.IRESTRequest"
+      provides="zope.publisher.interfaces.IPublishTraverse"
+      factory=".traverser.ItemTraverser"
+      permission="zope.Public"
+      allowed_interface="zope.publisher.interfaces.IPublishTraverse"
+      />
+
+  <!-- Basic REST publishing setup -->
+
+  <class class=".rest.RESTRequest">
+    <require
+        permission="zope.View"
+        interface="zope.publisher.interfaces.http.IHTTPApplicationRequest"/>
+  </class>
+
+  <configure
+      zcml:condition="have twisted">
+
+    <utility
+        name="REST-HTTP"
+        component=".twist.rest"
+        provides="zope.app.twisted.interfaces.IServerType"
+        />
+
+  </configure>
+
+  <configure
+      zcml:condition="have zserver">
+
+    <utility
+        name="REST-HTTP"
+        component=".zserver.rest"
+        provides="zope.app.server.interfaces.IServerType"
+        />
+
+  </configure>
+
+</configure>


Property changes on: z3c.rest/trunk/src/z3c/rest/configure.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/interfaces.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/interfaces.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/interfaces.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,214 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST publishing interfaces.
+
+$Id$
+"""
+import zope.interface
+import zope.schema
+from zope.location.interfaces import ILocation
+from zope.publisher.interfaces import http
+
+class IRESTRequest(http.IHTTPRequest):
+    """A special type of request for handling REST-based requests."""
+
+
+class IRESTView(ILocation):
+    """A REST view"""
+
+
+class ILink(zope.interface.Interface):
+    """An object representing a hyperlink."""
+
+    href = zope.schema.TextLine(
+        title=u"URL",
+        description=u"The normalized URL of the link",
+        required=False)
+
+    title = zope.schema.TextLine(
+        title=u'Title',
+        description=u'The title of the link',
+        required=False)
+
+    def click():
+        """click the link, going to the URL referenced"""
+
+
+class IRESTClient(zope.interface.Interface):
+    """A REST client.
+
+    This client provides a high-level API to access RESTful Web APIs. The
+    interface is designed to resemble the test browser API as much as
+    practical.
+    """
+
+    connectionFactory = zope.schema.Field(
+        title=u"Connection Facotry",
+        description=(u'A callable that creates an `httplib`-compliant '
+                     u'connection object.'),
+        required=True)
+
+    requestHeaders = zope.schema.Dict(
+        title=u"Request Headers",
+        description=(u"A set of headers that will be sent in every request."),
+        required=True)
+
+    url = zope.schema.URI(
+        title=u"URL",
+        description=(u"The URL the browser is currently showing. It is "
+                     u"always a full, absolute URL."),
+        required=True)
+
+    headers = zope.schema.List(
+        title=u"Response Headers",
+        description=(u'A list of all headers that have been returned '
+                     u'in the last request.'),
+        required=True)
+
+    contents = zope.schema.Text(
+        title=u"Contents",
+        description=u"The complete response body of the HTTP request.",
+        required=True)
+
+    status = zope.schema.Int(
+        title=u"Status",
+        description=u"The status code of the last response.",
+        min=0,
+        required=True)
+
+    reason = zope.schema.TextLine(
+        title=u"Reason",
+        description=u"A short explanation of the status of the last response.",
+        required=True)
+
+    fullStatus = zope.schema.TextLine(
+        title=u"Full Status",
+        description=u"The status code and reason of the last response.",
+        required=True)
+
+    def open(url='', data=None, params=None, headers=None, method='GET'):
+        """Open a URL and retrieve the result.
+
+        The `url` argument can either be a full URL or a URL relative to the
+        previous one. If no URL is specified, then the previous URL will be
+        used.
+
+        The `data` is the contents of the request body. It is used to send
+        information to the server.
+
+        The `params` describe additional query parameters that will be added
+        to the request. Query string parameters are frequently used by RESTive
+        APIs to provide additional return value options.
+
+        The `headers` specify additional request headers that are specific for
+        this particular request.
+
+        The `method` specifies the HTTP method or verb to use to access the
+        resource on the server. While there are only a few methods in RFC
+        2616, an string is allowed, since any particular API can extend the
+        set of allowed methods.
+        """
+
+    def get(url='', params=None, headers=None):
+        """Make a GET request to the server.
+
+        For argument details see ``open()``.
+        """
+
+    def put(url='', data='', params=None, headers=None):
+        """Make a PUT request to the server.
+
+        For argument details see ``open()``.
+        """
+
+    def post(url='', data='', params=None, headers=None):
+        """Make a POST request to the server.
+
+        For argument details see ``open()``.
+        """
+
+    def delete(url='', params=None, headers=None):
+        """Make a DELETE request to the server.
+
+        For argument details see ``open()``.
+        """
+
+    def setCredentials(username, password):
+        """Set the credentials.
+
+        This method adds the necessary information to authenticate the user. A
+        common example is basic auth, which inserts the `Authentication`
+        request header.
+        """
+
+    def goBack(count=1):
+        """Go back in history by a certain amount of visisted pages.
+
+        The ``count`` argument specifies how far to go back. It is set to 1 by
+        default.
+        """
+
+    def reload():
+        """Reload the current resource.
+
+        All arguments, including the HTTP method, parameters and additional
+        headers are honored.
+        """
+
+    def getLink(title=None, url=None, index=0):
+        """Return an ILink of the found link.
+
+        This method assumes that the current content type of the response body
+        is XML.
+
+        The link is found by the arguments of the method.  Only one can be
+        used at a time:
+
+          o ``title`` -- The title or a sub-string thereof of the link.
+
+          o ``url`` -- The URL the link is going to.
+
+        If multiple matching links are found, the `index` specifies which one
+        to use.
+        """
+
+    def xpath(expr, nsmap=None, single=False):
+        """Returns the result of an XPath search expression.
+
+        This method assumes that the current content type of the response body
+        is XML.
+
+        The `expr` argument is the actual XPath expression. If the expression
+        is incorrect, an unspecified error must be raised.
+
+        The `nsmap` is a mapping from the short version to the full URL of
+        each XML namespace used in the expression.
+
+        If `single` is set to ``True``, then only one result is returned,
+        instead of a list. If the XPath expression results in more than one
+        result, a ``ValueError`` must be raised.
+        """
+
+
+class IPublisherRESTClient(IRESTClient):
+    """An extension to the REST client to support test-specific features."""
+
+    handleErrors = zope.schema.Bool(
+        title=u"Handle Errors",
+        description=(u"Describes whether server-side errors will be handled "
+                     u"by the publisher. If set to ``False``, the error will "
+                     u"progress all the way to the test, which is good for "
+                     u"debugging."),
+        default=True,
+        required=True)


Property changes on: z3c.rest/trunk/src/z3c/rest/interfaces.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/null.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/null.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/null.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,54 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Null resource.
+
+$Id$
+"""
+import zope.component
+import zope.interface
+from zope.app.http.interfaces import INullResource
+from zope.location import location
+from zope.traversing.browser import absoluteURL
+
+from z3c.rest import rest
+
+class NullResource(location.Location):
+    """Object representing objects to be created by a `PUT`."""
+    zope.interface.implements(INullResource)
+
+    def __init__(self, container, name):
+        self.__parent__ = self.container = container
+        self.__name__ = self.name = name
+
+    def __repr__(self):
+        return '<%s %r>' %(self.__class__.__name__, self.name)
+
+
+class NullPUT(rest.RESTView):
+    """Put handler for null resources"""
+
+    def PUT(self):
+        nullPut = zope.component.queryMultiAdapter(
+            (self.context.container, self.request), name='NullPUT')
+        if nullPut is None:
+            # See RFC 2616, section 9.6
+            self.request.response.setStatus(501)
+            return
+
+        newObj = nullPut.NullPUT(self.context)
+
+        # See RFC 2616, section 9.6
+        self.request.response.setStatus(201)
+        self.request.response.setHeader(
+            'Location', absoluteURL(newObj, self.request))


Property changes on: z3c.rest/trunk/src/z3c/rest/null.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/null.txt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/null.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/null.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,103 @@
+==============
+Null Resources
+==============
+
+It is sometimes necessary to traverse to resources that do not yet exist. In
+particular, this is needed when creating resources using "PUT" or "POST". It
+is the responsibility of the traverser to handle those cases correctly and
+produce the null resources. This document only describes their behavior.
+
+A null resource is easily instantiated using the container and the name of the
+resource:
+
+  >>> class Folder(object):
+  ...     __parent__ = __name__ = None
+  ...     child = None
+  ...
+  ...     def __init__(self, name=''):
+  ...         self.name = self.__name__ = name
+  ...
+  ...     def __repr__(self):
+  ...         return '<Folder %r>' %self.name
+  >>> folder = Folder()
+
+  >>> from z3c.rest import null
+  >>> resource = null.NullResource(folder, 'resource')
+
+  >>> from zope.app.http.interfaces import INullResource
+  >>> INullResource.providedBy(resource)
+  True
+
+Null resources are locations, so security is available:
+
+  >>> from zope.location.interfaces import ILocation
+  >>> ILocation.providedBy(resource)
+  True
+
+The container is also the parent:
+
+  >>> resource.container
+  <Folder ''>
+  >>> resource.__parent__
+  <Folder ''>
+
+The name of the resource is available at:
+
+  >>> resource.name
+  'resource'
+  >>> resource.__name__
+  'resource'
+
+There is a special implementation of "PUT" for null resources. It works by
+looking up a view called "NullPUT" for the container. This way, one null
+resource implementation can be used for all container implementations.
+
+  >>> import StringIO
+  >>> from z3c.rest import rest
+  >>> request = rest.RESTRequest(StringIO.StringIO(), {})
+
+  >>> nullPut = null.NullPUT(resource, request)
+  >>> nullPut.PUT()
+
+Since no view called "NullPUT" exists for our `Folder` class, we get a 501
+return status:
+
+  >>> request.response.getStatusString()
+  '501 Not Implemented'
+
+Let's now register a simple NullPUT view:
+
+  >>> class FolderAPI(rest.RESTView):
+  ...
+  ...     def NullPUT(self, resource):
+  ...         self.context.child = Folder(resource.name)
+  ...         self.context.child.__parent__ = self.context
+  ...         return self.context.child
+
+  >>> import zope.component
+  >>> from z3c.rest import interfaces
+  >>> zope.component.provideAdapter(
+  ...     FolderAPI, (Folder, interfaces.IRESTRequest), name='NullPUT')
+
+Let's make sure our location structure is correctly setup, so that absolute
+URL will work:
+
+  >>> from zope.traversing.interfaces import IContainmentRoot
+  >>> import zope.interface
+  >>> zope.interface.alsoProvides(folder, IContainmentRoot)
+
+Now we are ready to PUT the new resource:
+
+  >>> request = rest.RESTRequest(
+  ...     StringIO.StringIO(), {'SERVER_URL': 'http://localhost/'})
+
+  >>> nullPut = null.NullPUT(resource, request)
+  >>> nullPut.PUT()
+
+  >>> request.response.getStatusString()
+  '201 Created'
+  >>> request.response.getHeader('Location')
+  'http://localhost/resource'
+
+  >>> folder.child
+  <Folder 'resource'>


Property changes on: z3c.rest/trunk/src/z3c/rest/null.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/rest.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/rest.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/rest.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,94 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST publication and publisher factories
+
+$Id$
+"""
+import cgi
+import zope.interface
+from zope.app.publication.interfaces import IPublicationRequestFactory
+from zope.app.publication.http import HTTPPublication
+from zope.publisher.http import HTTPRequest
+
+from z3c.rest import interfaces
+
+class RESTRequest(HTTPRequest):
+    zope.interface.implements(interfaces.IRESTRequest)
+
+    __slots__ = (
+        'parameters', # Parameters sent via the query string.
+        )
+
+    def __init__(self, body_instream, environ, response=None):
+        self.parameters = {}
+        super(RESTRequest, self).__init__(body_instream, environ, response)
+
+    def processInputs(self):
+        'See IPublisherRequest'
+        if 'QUERY_STRING' not in self._environ:
+            return
+        # Parse the query string into our parameters dictionary.
+        self.parameters = cgi.parse_qs(
+            self._environ['QUERY_STRING'], keep_blank_values=1)
+        # Since the parameter value is always a list (sigh), let's at least
+        # detect single values and store them.
+        for name, value in self.parameters.items():
+            if len(value) == 1:
+                self.parameters[name] = value[0]
+
+    def keys(self):
+        'See Interface.Common.Mapping.IEnumerableMapping'
+        d = {}
+        d.update(self._environ)
+        d.update(self.parameters)
+        return d.keys()
+
+    def get(self, key, default=None):
+        'See Interface.Common.Mapping.IReadMapping'
+        marker = object()
+        result = self.parameters.get(key, marker)
+        if result is not marker:
+            return result
+
+        return super(RESTRequest, self).get(key, default)
+
+
+class RESTView(object):
+    zope.interface.implements(interfaces.IRESTView)
+
+    def __init__(self, context, request):
+        self.context = context
+        self.request = request
+
+    @apply
+    def __parent__():
+        def get(self):
+            return getattr(self, '_parent', self.context)
+        def set(self, parent):
+            self._parent = parent
+        return property(get, set)
+
+
+class RESTPublicationRequestFactory(object):
+    zope.interface.implements(IPublicationRequestFactory)
+
+    def __init__(self, db):
+        """See zope.app.publication.interfaces.IPublicationRequestFactory"""
+        self.publication = HTTPPublication(db)
+
+    def __call__(self, input_stream, env, output_stream=None):
+        """See zope.app.publication.interfaces.IPublicationRequestFactory"""
+        request = RESTRequest(input_stream, env)
+        request.setPublication(self.publication)
+        return request


Property changes on: z3c.rest/trunk/src/z3c/rest/rest.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/rest.txt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/rest.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/rest.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,204 @@
+=================================
+Publisher Hooks for REST Requests
+=================================
+
+Reading this document requires -- to some extend -- that the reader is
+familiar with the basic steps of the publication process.
+
+
+The Publication Request Factory
+-------------------------------
+
+The Zope publication process starts when a WSGI server sends the request
+environment and response initialization callable to the Zope WSGI Publisher
+application _[1]. The WSGI publisher application is then responsible for
+processing the request in the publisher and stream out the result.
+
+In order to process a request in the publisher, we have to create a valid
+publisher request object. The WSGI publisher application uses a request
+factory for this purpose. This package implements this factory to ensure that
+a special REST request (based on HTTP Request) is created at all times.
+
+The request factory is instantiated using a ZODB database object:
+
+  >>> from ZODB.DB import DB
+  >>> from ZODB.DemoStorage import DemoStorage
+  >>> db = DB(DemoStorage())
+
+Let's now create the factory:
+
+  >>> from z3c.rest import rest
+  >>> RequestFactory = rest.RESTPublicationRequestFactory(db)
+
+When a request comes in from the server, the request is created as follows:
+
+  >>> import StringIO
+  >>> inStream = StringIO.StringIO('Input stream')
+
+  >>> env = {'HTTP_ACCEPT_LANGUAGE': 'en-US,en',
+  ...        'SERVER_URL': 'http://localhost:8080/'}
+
+  >>> request = RequestFactory(inStream, env)
+
+We now got a valid request that we can send through the publisher:
+
+  >>> request
+  <z3c.rest.rest.RESTRequest instance URL=http://localhost:8080>
+
+The request, however, is only responsible for representing the network request
+in the publisher and has no direct knowledge of the application. But the
+request connects to an application-specific -- in this case Zope 3 --
+component known as the publication.
+
+  >>> request.publication
+  <zope.app.publication.http.HTTPPublication object at ...>
+
+Since we do not need a special REST publication, we are simply reusing the
+more generic HTTP version. The publication will be the same for all
+requests. It also contains the reference to the database:
+
+  >>> request.publication.db
+  <ZODB.DB.DB object at ...>
+
+Unfortunately, it takes a lot more setup to send the request through the
+publisher successfully. The publication requires many other aspects of
+publishing to be available, including traversal, security, and a properly
+constructed database. However, we can still see a failure:
+
+  >>> from zope.publisher import publish
+  >>> publish.publish(request)
+  <z3c.rest.rest.RESTRequest instance URL=http://localhost:8080>
+  >>> print request.response.consumeBody()
+  <html><head><title>ComponentLookupError</title></head>
+  <body><h2>ComponentLookupError</h2>
+  A server error occurred.
+  </body></html>
+
+Let' unwind a bit. Originally, we started with the desire to create a
+Publisher WSGI Application instance that internally uses a REST request. All
+that you need to do is:
+
+  >>> from zope.app import wsgi
+  >>> app = wsgi.WSGIPublisherApplication(
+  ...     db, rest.RESTPublicationRequestFactory)
+  >>> app
+  <zope.app.wsgi.WSGIPublisherApplication object at ...>
+
+When the WSGI server sends a request to the WSGI application, the following
+happens:
+
+  >>> status = None
+  >>> headers = None
+  >>> def start_response(s, h):
+  ...     global status
+  ...     global headers
+  ...     status, headers = s, h
+
+  >>> wsgiEnv = {'wsgi.input': inStream}
+  >>> wsgiEnv.update(env)
+
+  >>> print '\n'.join(app(wsgiEnv, start_response))
+  <html><head><title>ComponentLookupError</title></head>
+  <body><h2>ComponentLookupError</h2>
+  A server error occurred.
+  </body></html>
+
+
+.. [1]: ``zope.app.wsgi.WSGIPublisherApplication.__call__``
+
+
+The REST Request
+----------------
+
+For most parts, the REST request is identical to the HTTP request, so I won't
+go into too much detail about the HTTP request API.
+
+The REST request mainly extends the HTTP request in that it parses the query
+string of the URL into a set of parameters. This happens during
+``processInputs()``.
+
+If there is no query string, the paramaters mapping is empty:
+
+  >>> request = RequestFactory(
+  ...     StringIO.StringIO(), {})
+  >>> request.processInputs()
+  >>> request.parameters
+  {}
+
+So let's now pass a few parameters:
+
+  >>> request = RequestFactory(
+  ...     StringIO.StringIO(),
+  ...     {'QUERY_STRING': 'format=html&action=delete&item=1&item=3'})
+  >>> request.processInputs()
+  >>> pprint(request.parameters)
+  {'action': 'delete',
+   'format': 'html',
+   'item': ['1', '3']}
+
+We also override some of the request's mapping methods, so that the parameters
+and environment values are available as part of the request:
+
+  >>> sorted(request.keys())
+  ['QUERY_STRING', 'action', 'format', 'item']
+
+  >>> request.get('QUERY_STRING')
+  'format=html&action=delete&item=1&item=3'
+  >>> request.get('action')
+  'delete'
+  >>> request.get('unknwon', 'default')
+  'default'
+
+
+REST Views
+----------
+
+Unlike browser views, a REST view does *not* represent its own sub-resource
+(such as "index.html"). Instead it merely defines the behavior of the HTTP
+methods for a particular content component.
+
+Here is an example:
+
+  >>> class ObjectAPI(rest.RESTView):
+  ...
+  ...     def GET(self):
+  ...          return str(self.context)
+
+The ``RESTView`` base class provides a suitable constructor:
+
+  >>> class Object(object):
+  ...     def __repr__(self):
+  ...         return '<Object>'
+  >>> myobj = Object()
+
+  >>> request = RequestFactory(
+  ...     StringIO.StringIO(), {'SERVER_URL': 'http://localhost:8080/myobj'})
+
+  >>> view = ObjectAPI(myobj, request)
+
+When the publisher traverses to `myobj`, it will look up a view based on the
+HTTP mehtod, such as "GET". It then also expects to find a method of that same
+name and calls it _[2].
+
+  >>> view.GET()
+  '<Object>'
+
+The REST View, like all other views, exposes its context and the request:
+
+  >>> view.context
+  <Object>
+  >>> view.request
+  <z3c.rest.rest.RESTRequest instance URL=http://localhost:8080/myobj>
+
+Also, a view must be located, so it has a parent as well:
+
+  >>> view.__parent__
+  <Object>
+
+You can set it to something else of course:
+
+  >>> view.__parent__ = 1
+  >>> view.__parent__
+  1
+
+.. [2]: ``zope.app.publication.HTTPPublication.callObject``


Property changes on: z3c.rest/trunk/src/z3c/rest/rest.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/testing.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/testing.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/testing.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,100 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST testing support.
+
+$Id$
+"""
+import sys
+import zope.interface
+from z3c.rest import client, rest, interfaces
+from zope.app.publication.http import HTTPPublication
+from zope.app.testing.functional import HTTPCaller
+
+
+class RESTCaller(HTTPCaller):
+    """An HTTP caller for REST functional page tests"""
+
+    def chooseRequestClass(self, method, path, environment):
+        """Always returns HTTPRequests regardless of methods and content"""
+        return rest.RESTRequest, HTTPPublication
+
+
+class PublisherConnection(object):
+
+    def __init__(self, server, port=None):
+        self._response = None
+        self.server = server
+        self.port = port
+
+    def request(self, method, path, body, headers):
+        # Extract the handle_error option header
+        if sys.version_info >= (2,5):
+            handleErrorsKey = 'X-Zope-Handle-Errors'
+        else:
+            handleErrorsKey = 'X-zope-handle-errors'
+        handleErrors = headers.get(handleErrorsKey, True)
+        if handleErrorsKey in headers:
+            del headers[handleErrorsKey]
+
+        # Construct the request body and call the publisher
+        body = body or ''
+        request = ["%s %s HTTP/1.1" % (method, path)]
+        for hdr, value in headers.items():
+            request.append("%s: %s" % (hdr, value))
+        request_string = "\n".join(request) + "\n\n" + body
+        self._response = RESTCaller()(
+            request_string, handle_errors=handleErrors)
+
+    def getresponse(self):
+        return PublisherResponse(self._response)
+
+    def close(self):
+        self._response = None
+
+
+class PublisherResponse(object):
+    """Adapter of Zope 3 response objects into httplib.HTTPResponse."""
+
+    def __init__(self, response):
+        self._response = response
+        self.status = response.getStatus()
+        self.reason = response._reason
+
+    def getheaders(self):
+        return self._response.getHeaders()
+
+    def read(self):
+        return self._response.consumeBody()
+
+
+class RESTClient(client.RESTClient):
+    zope.interface.implements(interfaces.IPublisherRESTClient)
+
+    connectionFactory = PublisherConnection
+
+    @apply
+    def handleErrors():
+        """See zope.testbrowser.interfaces.IBrowser"""
+        headerKey = 'X-zope-handle-errors'
+
+        def get(self):
+            return self.requestHeaders.get(headerKey, True)
+
+        def set(self, value):
+            current_value = get(self)
+            if current_value == value:
+                return
+            self.requestHeaders[headerKey] = value
+
+        return property(get, set)


Property changes on: z3c.rest/trunk/src/z3c/rest/testing.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/tests/__init__.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/__init__.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/__init__.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+# Make a package


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/__init__.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/tests/folder.pt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/folder.pt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/folder.pt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,14 @@
+<?xml version="1.0" ?>
+<folder xmlns:xlink="http://www.w3.org/1999/xlink"
+        xmlns:tal="http://xml.zope.org/namespaces/tal">
+  <name tal:content="context/__name__">folder</name>
+  <title tal:content="context/zope:title"
+         tal:condition="not: request/notitle|nothing">Folder</title>
+  <items
+      tal:condition="not: request/noitems|nothing">
+    <item xlink:type="simple" xlink:href="" xlink:title=""
+          tal:repeat="item context/values"
+          tal:attributes="xlink:href item/@@absolute_url;
+                          xlink:title item/__name__" />
+  </items>
+</folder>


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/folder.pt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/tests/folder.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/folder.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/folder.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,57 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Test REST view for folders.
+
+$Id$
+"""
+import lxml.etree
+from z3c.rest import rest
+from zope.app.folder import folder
+from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
+from zope.app.publication.http import MethodNotAllowed
+from zope.dublincore.interfaces import IZopeDublinCore
+
+class FolderAPI(rest.RESTView):
+    """A simple REST view for folders."""
+
+    template = ViewPageTemplateFile("folder.pt")
+
+    def __init__(self, context, request):
+        super(FolderAPI, self).__init__(context, request)
+        for param in ('noitems', 'notitle'):
+            if 'HTTP_DEMO_' + param.upper() in self.request:
+                self.request.parameters[param] = 1
+
+    def GET(self):
+        return self.template()
+
+    def POST(self):
+        tree = lxml.etree.parse(self.request.bodyStream)
+        title = tree.find('title').text
+        dc = IZopeDublinCore(self.context)
+        dc.title = unicode(title)
+
+    # For existing resources, PUT pretty much behaves like POST
+    PUT = POST
+
+    def NullPUT(self, nullResource):
+        name = nullResource.name
+        self.context[name] = folder.Folder()
+        return self.context[name]
+
+    def DELETE(self):
+        container = self.context.__parent__
+        if container is None:
+            raise MethodNotAllowed(self.context, self.request)
+        del container[self.context.__name__]


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/folder.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/tests/folder.zcml
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/folder.zcml	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/folder.zcml	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,48 @@
+<configure xmlns="http://namespaces.zope.org/zope">
+
+<view
+    for="zope.app.folder.interfaces.IFolder"
+    name="GET"
+    type="..interfaces.IRESTRequest"
+    factory=".folder.FolderAPI"
+    permission="zope.View"
+    allowed_attributes="GET"
+    />
+
+<view
+    for="zope.app.folder.interfaces.IFolder"
+    name="POST"
+    type="..interfaces.IRESTRequest"
+    factory=".folder.FolderAPI"
+    permission="zope.ManageContent"
+    allowed_attributes="POST"
+    />
+
+<view
+    for="zope.app.folder.interfaces.IFolder"
+    name="PUT"
+    type="..interfaces.IRESTRequest"
+    factory=".folder.FolderAPI"
+    permission="zope.ManageContent"
+    allowed_attributes="PUT"
+    />
+
+<view
+    name="NullPUT"
+    for="zope.app.folder.interfaces.IFolder"
+    type="..interfaces.IRESTRequest"
+    factory=".folder.FolderAPI"
+    permission="zope.ManageContent"
+    allowed_attributes="NullPUT"
+    />
+
+<view
+    for="zope.app.folder.interfaces.IFolder"
+    name="DELETE"
+    type="..interfaces.IRESTRequest"
+    factory=".folder.FolderAPI"
+    permission="zope.ManageContent"
+    allowed_attributes="DELETE"
+    />
+
+</configure>


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/folder.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/tests/ftesting.zcml
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/ftesting.zcml	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/ftesting.zcml	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,6 @@
+<configure
+    xmlns="http://namespaces.zope.org/zope">
+
+  <include package="z3c.rest" file="application.zcml" />
+
+</configure>


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/ftesting.zcml
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/tests/test.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/tests/test.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/tests/test.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,79 @@
+##############################################################################
+#
+# Copyright (c) 2004 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.
+#
+##############################################################################
+"""REST Tests
+
+$Id$
+"""
+__docformat__ = "reStructuredText"
+import os
+import unittest
+import zope.component
+from zope.testing import doctest, doctestunit
+from zope.traversing.browser import absoluteurl
+from zope.traversing.interfaces import IContainmentRoot
+from zope.app.testing import functional, placelesssetup
+from z3c.rest import interfaces
+
+RESTLayer = functional.ZCMLLayer(
+    os.path.join(os.path.split(__file__)[0], 'ftesting.zcml'),
+    __name__, 'RESTLayer', allow_teardown=True)
+
+def setUp(test):
+    placelesssetup.setUp(test)
+
+    # XXX: This really needs a REST equivalent w/o breadcrumbs.
+
+    zope.component.provideAdapter(
+        absoluteurl.AbsoluteURL,
+        (None, interfaces.IRESTRequest),
+        absoluteurl.IAbsoluteURL)
+
+    zope.component.provideAdapter(
+        absoluteurl.SiteAbsoluteURL,
+        (IContainmentRoot, interfaces.IRESTRequest),
+        absoluteurl.IAbsoluteURL,
+        'absolute_url')
+
+    zope.component.provideAdapter(
+        absoluteurl.SiteAbsoluteURL,
+        (IContainmentRoot, interfaces.IRESTRequest),
+        absoluteurl.IAbsoluteURL)
+
+    zope.component.provideAdapter(
+        absoluteurl.AbsoluteURL,
+        (None, interfaces.IRESTRequest),
+        absoluteurl.IAbsoluteURL,
+        'absolute_url')
+
+
+def test_suite():
+    client = functional.FunctionalDocFileSuite('../client.txt')
+    client.layer = RESTLayer
+    return unittest.TestSuite((
+        client,
+        doctest.DocFileSuite(
+            '../rest.txt',
+            globs={'pprint': doctestunit.pprint},
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+        doctest.DocFileSuite(
+            '../null.txt',
+            setUp=setUp, tearDown=placelesssetup.tearDown,
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+        doctest.DocFileSuite(
+            '../traverser.txt',
+            optionflags=doctest.NORMALIZE_WHITESPACE|doctest.ELLIPSIS,
+            ),
+        ))


Property changes on: z3c.rest/trunk/src/z3c/rest/tests/test.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/traverser.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/traverser.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/traverser.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,50 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Some basic traversers for REST
+
+$Id$
+"""
+import zope.interface
+from zope.publisher.interfaces.http import IHTTPPublisher
+from zope.app.container.interfaces import IItemContainer
+from zope.publisher.interfaces import NotFound
+from z3c.rest import interfaces, null
+
+class ItemTraverser(object):
+    zope.interface.implements(IHTTPPublisher)
+    zope.component.adapts(IItemContainer, interfaces.IRESTRequest)
+
+    def __init__(self, container, request):
+        self.context = container
+        self.request = request
+
+    def publishTraverse(self, request, name):
+        try:
+            return self.context[name]
+        except KeyError:
+            return self.nullResource(request, name)
+
+    def nullResource(self, request, name):
+        # we traversed to something that doesn't exist.
+
+        # The name must be the last name in the path, so the traversal
+        # name stack better be empty:
+        if request.getTraversalStack():
+            raise NotFound(self.context, name, request)
+
+        # This should only happen for a PUT:
+        if request.method != 'PUT':
+            raise NotFound(self.context, name, request)
+
+        return null.NullResource(self.context, name)


Property changes on: z3c.rest/trunk/src/z3c/rest/traverser.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/traverser.txt
===================================================================
--- z3c.rest/trunk/src/z3c/rest/traverser.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/traverser.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,74 @@
+=========================
+REST Traverser Components
+=========================
+
+The traverser module contains several travreser implementations for common
+scenarios.
+
+
+Item Container Traverser
+------------------------
+
+The item mapping interface -- from which item container inherits -- is the
+most minimal mapping interface in Python. Thus, once traversing through this
+item container is implemented, it can be used by all other container
+interfaces and implementations.
+
+Let's start by creating a very simple item container implementation:
+
+  >>> import zope.interface
+  >>> from zope.app.container.interfaces import IItemContainer
+
+  >>> class SimpleContainer(dict):
+  ...     zope.interface.implements(IItemContainer)
+  ...     def __init__(self, name=''):
+  ...         self.name = name
+  ...     def __repr__(self):
+  ...         return '<Container name=%s>' %self.name
+
+  >>> container = SimpleContainer()
+
+  >>> container['sub1'] = SimpleContainer('sub1')
+  >>> container['sub2'] = SimpleContainer('sub2')
+
+After creating a traverser instance,
+
+  >>> from z3c.rest import traverser
+
+  >>> import StringIO
+  >>> from z3c.rest import rest
+  >>> request = rest.RESTRequest(StringIO.StringIO(), {})
+
+
+  >>> containerTraverser = traverser.ItemTraverser(
+  ...     container, request)
+
+we can traverse to a sub-object of that container:
+
+  >>> containerTraverser.publishTraverse(request, 'sub1')
+  <Container name=sub1>
+
+If no proper sub-item can be found, some interesting can happen. In a normal
+case, ``NotFound`` is raised:
+
+  >>> containerTraverser.publishTraverse(request, 'unknown')
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: <Container name=>, name: 'unknown'
+
+However, if the request is a PUT request, we must generate a null resource:
+
+  >>> request.method = 'PUT'
+  >>> containerTraverser.publishTraverse(request, 'unknown')
+  <NullResource 'unknown'>
+
+However, a null resource is only created, if the current resource is the last
+one in the traversal stack:
+
+  >>> request.setTraversalStack(('sub11',))
+  >>> containerTraverser.publishTraverse(request, 'unknown')
+  Traceback (most recent call last):
+  ...
+  NotFound: Object: <Container name=>, name: 'unknown'
+
+And that's it.


Property changes on: z3c.rest/trunk/src/z3c/rest/traverser.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c/rest/twist.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/twist.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/twist.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,35 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST server factories for Twisted
+
+Note: The file is not named twisted.py because of package import problems.
+
+$Id$
+"""
+from twisted.web2 import log, server, wsgi
+from twisted.web2.channel.http import HTTPFactory
+from zope.app.twisted import http
+from zope.app.twisted.server import ServerType
+from zope.app.wsgi import WSGIPublisherApplication
+from z3c.rest.rest import RESTPublicationRequestFactory
+
+def createRESTFactory(db):
+    resource = wsgi.WSGIResource(
+        WSGIPublisherApplication(db, RESTPublicationRequestFactory))
+    resource = log.LogWrapperResource(resource)
+    resource = http.Prebuffer(resource)
+
+    return HTTPFactory(server.Site(resource))
+
+rest = ServerType(createRESTFactory, 8081)


Property changes on: z3c.rest/trunk/src/z3c/rest/twist.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c/rest/zserver.py
===================================================================
--- z3c.rest/trunk/src/z3c/rest/zserver.py	                        (rev 0)
+++ z3c.rest/trunk/src/z3c/rest/zserver.py	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,28 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""REST server factories
+
+$Id$
+"""
+from zope.server.http.commonaccesslogger import CommonAccessLogger
+from zope.server.http import wsgihttpserver
+from zope.app.server.wsgi import ServerType
+from zope.app.wsgi import WSGIPublisherApplication
+from z3c.rest.rest import RESTPublicationRequestFactory
+
+rest = ServerType(wsgihttpserver.WSGIHTTPServer,
+                  WSGIPublisherApplication,
+                  CommonAccessLogger,
+                  8080, True,
+                  RESTPublicationRequestFactory)


Property changes on: z3c.rest/trunk/src/z3c/rest/zserver.py
___________________________________________________________________
Name: svn:keywords
   + Id

Added: z3c.rest/trunk/src/z3c.rest.egg-info/PKG-INFO
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/PKG-INFO	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/PKG-INFO	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,31 @@
+Metadata-Version: 1.0
+Name: z3c.rest
+Version: 1.5.1
+Summary: A REST Framework for Zope 3 Applications
+Home-page: http://cheeseshop.python.org/pypi/z3c.rest
+Author: Stephan Richter and the Zope Community
+Author-email: zope3-dev at zope.org
+License: ZPL 2.1
+Description: This package provides a framework to build REST APIs on top of Zope 3.
+        
+        
+        =======
+        CHANGES
+        =======
+        
+        Version 0.1.0 (2007-12-??)
+        --------------------------
+        
+        - Initial Release
+        
+Keywords: zope3 form widget
+Platform: UNKNOWN
+Classifier: Development Status :: 4 - Beta
+Classifier: Environment :: Web Environment
+Classifier: Intended Audience :: Developers
+Classifier: License :: OSI Approved :: Zope Public License
+Classifier: Programming Language :: Python
+Classifier: Natural Language :: English
+Classifier: Operating System :: OS Independent
+Classifier: Topic :: Internet :: WWW/HTTP
+Classifier: Framework :: Zope3

Added: z3c.rest/trunk/src/z3c.rest.egg-info/SOURCES.txt
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/SOURCES.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/SOURCES.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,17 @@
+README.txt
+setup.py
+src/z3c/__init__.py
+src/z3c.rest.egg-info/PKG-INFO
+src/z3c.rest.egg-info/SOURCES.txt
+src/z3c.rest.egg-info/dependency_links.txt
+src/z3c.rest.egg-info/namespace_packages.txt
+src/z3c.rest.egg-info/not-zip-safe
+src/z3c.rest.egg-info/requires.txt
+src/z3c.rest.egg-info/top_level.txt
+src/z3c/rest/__init__.py
+src/z3c/rest/interfaces.py
+src/z3c/rest/rest.py
+src/z3c/rest/twist.py
+src/z3c/rest/zserver.py
+src/z3c/rest/tests/__init__.py
+src/z3c/rest/tests/folder.py


Property changes on: z3c.rest/trunk/src/z3c.rest.egg-info/SOURCES.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c.rest.egg-info/dependency_links.txt
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/dependency_links.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/dependency_links.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+


Property changes on: z3c.rest/trunk/src/z3c.rest.egg-info/dependency_links.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c.rest.egg-info/namespace_packages.txt
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/namespace_packages.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/namespace_packages.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+z3c


Property changes on: z3c.rest/trunk/src/z3c.rest.egg-info/namespace_packages.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c.rest.egg-info/not-zip-safe
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/not-zip-safe	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/not-zip-safe	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+

Added: z3c.rest/trunk/src/z3c.rest.egg-info/requires.txt
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/requires.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/requires.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1,24 @@
+lxml
+setuptools
+zope.publisher
+
+[test]
+z3c.coverage
+z3c.etestbrowser
+zope.app.testing
+
+[app]
+zope.app.appsetup
+zope.app.authentication
+zope.app.component
+zope.app.container
+zope.app.error
+zope.app.form
+zope.app.publisher
+zope.app.publication
+zope.app.security
+zope.app.securitypolicy
+zope.app.twisted
+zope.app.wsgi
+zope.app.zcmlfiles
+zope.contentprovider
\ No newline at end of file


Property changes on: z3c.rest/trunk/src/z3c.rest.egg-info/requires.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: z3c.rest/trunk/src/z3c.rest.egg-info/top_level.txt
===================================================================
--- z3c.rest/trunk/src/z3c.rest.egg-info/top_level.txt	                        (rev 0)
+++ z3c.rest/trunk/src/z3c.rest.egg-info/top_level.txt	2007-11-30 11:40:12 UTC (rev 82045)
@@ -0,0 +1 @@
+z3c


Property changes on: z3c.rest/trunk/src/z3c.rest.egg-info/top_level.txt
___________________________________________________________________
Name: svn:eol-style
   + native



More information about the Checkins mailing list