From philikon at codespeak.net Sun Apr 1 17:33:36 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 1 Apr 2007 17:33:36 +0200 (CEST) Subject: [z3-checkins] r41764 - z3/NudgeNudge/trunk Message-ID: <20070401153336.D0D171007C@code0.codespeak.net> Author: philikon Date: Sun Apr 1 17:33:35 2007 New Revision: 41764 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: cosmetics Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Sun Apr 1 17:33:35 2007 @@ -1,3 +1,7 @@ +[buildout] +parts = data instance test +develop = . deliverance + [test] working-directory = parts/instance eggs = nudgenudge @@ -13,10 +17,6 @@ [zope3] location = /usr/local/Zope-3.3.1 -[buildout] -parts = data instance test -develop = . deliverance - [instance] database = data eggs = setuptools From kobold at codespeak.net Sun Apr 1 19:24:56 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Sun, 1 Apr 2007 19:24:56 +0200 (CEST) Subject: [z3-checkins] r41771 - in z3/sqlos/trunk/src/sqlos: . ftests Message-ID: <20070401172456.098E21007C@code0.codespeak.net> Author: kobold Date: Sun Apr 1 19:24:55 2007 New Revision: 41771 Modified: z3/sqlos/trunk/src/sqlos/connection.py z3/sqlos/trunk/src/sqlos/ftests/localutilities.txt Log: Let's try to fix the new code: it didn't work with multiple threads. Modified: z3/sqlos/trunk/src/sqlos/connection.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/connection.py (original) +++ z3/sqlos/trunk/src/sqlos/connection.py Sun Apr 1 19:24:55 2007 @@ -21,6 +21,7 @@ """ __metaclass__ = type +import thread import warnings from zope.app import zapi @@ -66,58 +67,41 @@ # This code was heavily based on ZODB.Transaction connCache = {} -try: - import thread -except: - def getConnection(context, name): - global connCache - if not connCache.get(name): - newconn = zapi.queryUtility(IZopeDatabaseAdapter, name, - default=None, - context=context) - if newconn is None: - warnings.warn("Couldn't find a rdb connection by the " - "name %s. Please verify your setup." % name, - SQLOSWarning, 3) - connCache[name] = IZopeSQLConnection(newconn()) - return connCache[name] - - def releaseConnection(name): - global connCache - if connCache.has_key(name): - connCache[name].close() - del connCache[name] -else: - def getConnection(context, name): - global connCache - tid = thread.get_ident() - key = (tid, name) - if not connCache.get(key): - newconn = zapi.queryUtility(IZopeDatabaseAdapter, name, - default=None, - context=context) - if newconn is None: - warnings.warn("Couldn't find a rdb connection by the " - "name %s. Please verify your setup." % name, - SQLOSWarning, 3) - conn = IZopeSQLConnection(newconn()) - if conn.supportTransactions: - connCache[key] = conn.transaction() - else: # At least MySQL does not support transactions - connCache[key] = conn - - return connCache[key] - - def releaseConnection(name): - global connCache - tid = thread.get_ident() - key = (tid, name) - if connCache.has_key(key): - connCache[key].close() - del connCache[key] + +def getConnection(context, name): + global connCache + tid = thread.get_ident() + key = (tid, name) + if not connCache.get(key): + newconn = zapi.queryUtility(IZopeDatabaseAdapter, name, + default=None, + context=context) + if newconn is None: + warnings.warn("Couldn't find a rdb connection by the " + "name %s. Please verify your setup." % name, + SQLOSWarning, 3) + conn = IZopeSQLConnection(newconn()) + if conn.supportTransactions: + connCache[key] = conn.transaction() + else: # At least MySQL does not support transactions + connCache[key] = conn + + return connCache[key] + + +def releaseConnection(name): + global connCache + tid = thread.get_ident() + key = (tid, name) + if connCache.has_key(key): + connCache[key].close() + del connCache[key] def clearCacheSubscriber(*args): """A subscriber to clear the connection cache at site boundaries.""" - for connection in connCache.values(): - connection.cache.clear() + tid = thread.get_ident() + for name in connCache.keys(): + if name[0] != tid: + continue + connCache[name].cache.clear() Modified: z3/sqlos/trunk/src/sqlos/ftests/localutilities.txt ============================================================================== --- z3/sqlos/trunk/src/sqlos/ftests/localutilities.txt (original) +++ z3/sqlos/trunk/src/sqlos/ftests/localutilities.txt Sun Apr 1 19:24:55 2007 @@ -41,9 +41,6 @@ >>> localUtility is dbAdapter True - >>> localUtility is dbAdapter - True - Ok. Now we have a site in root/testsite with a registered sqlite adapter. We make sure that our localUtility is not identical to the global sqlite utility that has been registered through ftesting.zcml. From philikon at codespeak.net Mon Apr 2 01:02:32 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:02:32 +0200 (CEST) Subject: [z3-checkins] r41782 - in z3/NudgeNudge/trunk: . etc Message-ID: <20070401230232.4ED9710080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:02:29 2007 New Revision: 41782 Modified: z3/NudgeNudge/trunk/ (props changed) z3/NudgeNudge/trunk/buildout.cfg z3/NudgeNudge/trunk/etc/paste.ini Log: * Use development version (checkout for now) of zope.paste which supports running Zope 3 completely on PasteDeploy * New buildout part that installs PasteScript and lets you run NudgeNudge like so: $ bin/paster serve etc/paste.ini Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Mon Apr 2 01:02:29 2007 @@ -1,6 +1,6 @@ [buildout] -parts = data instance test -develop = . deliverance +parts = data server instance test +develop = . deliverance zope.paste [test] working-directory = parts/instance @@ -17,6 +17,13 @@ [zope3] location = /usr/local/Zope-3.3.1 +[server] +recipe = zc.recipe.egg +eggs = ${instance:eggs} + PasteScript + WSGIUtils +extra-paths = ${zope3:location}/lib/python + [instance] database = data eggs = setuptools Modified: z3/NudgeNudge/trunk/etc/paste.ini ============================================================================== --- z3/NudgeNudge/trunk/etc/paste.ini (original) +++ z3/NudgeNudge/trunk/etc/paste.ini Mon Apr 2 01:02:29 2007 @@ -1,8 +1,20 @@ -[filter-app:Paste.Main] +[composite:main] +use = egg:Paste#urlmap +/ = themed +/notheme = zope + +[filter-app:themed] use = egg:Deliverance theme_uri = /@@/nudgenudge/www.python.org/pypi/index.html rule_uri = /@@/nudgenudge/rules.xml next = zope [app:zope] -paste.app_factory = zope.paste.application:zope_publisher_app_factory +use = egg:zope.paste +site_definition = ../parts/instance/etc/site.zcml +file_storage = ../parts/data/Data.fs + +[server:main] +use = egg:PasteScript#wsgiutils +host = 127.0.0.1 +port = 8080 From philikon at codespeak.net Mon Apr 2 01:04:42 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:04:42 +0200 (CEST) Subject: [z3-checkins] r41783 - in z3/NudgeNudge/trunk: . etc Message-ID: <20070401230442.4626D10080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:04:40 2007 New Revision: 41783 Added: z3/NudgeNudge/trunk/nudge.ini - copied, changed from r41782, z3/NudgeNudge/trunk/etc/paste.ini Removed: z3/NudgeNudge/trunk/etc/ Log: Move PasteDeploy configuration out of etc and give it a better name. You now start NudgeNudge like so: $ bin/paster serve nudge.ini Copied: z3/NudgeNudge/trunk/nudge.ini (from r41782, z3/NudgeNudge/trunk/etc/paste.ini) ============================================================================== --- z3/NudgeNudge/trunk/etc/paste.ini (original) +++ z3/NudgeNudge/trunk/nudge.ini Mon Apr 2 01:04:40 2007 @@ -11,8 +11,8 @@ [app:zope] use = egg:zope.paste -site_definition = ../parts/instance/etc/site.zcml -file_storage = ../parts/data/Data.fs +site_definition = parts/instance/etc/site.zcml +file_storage = parts/data/Data.fs [server:main] use = egg:PasteScript#wsgiutils From philikon at codespeak.net Mon Apr 2 01:08:40 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:08:40 +0200 (CEST) Subject: [z3-checkins] r41784 - z3/NudgeNudge/trunk Message-ID: <20070401230840.7A87810080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:08:37 2007 New Revision: 41784 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: We no longer need the PasteDeploy/Deliverance stuff in the instance recipe. Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Mon Apr 2 01:08:37 2007 @@ -20,6 +20,9 @@ [server] recipe = zc.recipe.egg eggs = ${instance:eggs} + zope.paste + PasteDeploy + Deliverance PasteScript WSGIUtils extra-paths = ${zope3:location}/lib/python @@ -29,9 +32,6 @@ eggs = setuptools grok zc.catalog - zope.paste - PasteDeploy - Deliverance nudgenudge recipe = zc.recipe.zope3instance user = grok:grok @@ -55,7 +55,6 @@ zope.app.keyreference zope.app.session zope.app.twisted - zope.paste grok grok-meta nudgenudge From philikon at codespeak.net Mon Apr 2 01:14:22 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:14:22 +0200 (CEST) Subject: [z3-checkins] r41785 - z3/NudgeNudge/trunk Message-ID: <20070401231422.6118610080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:14:20 2007 New Revision: 41785 Modified: z3/NudgeNudge/trunk/INSTALL.txt Log: Update installation docs Modified: z3/NudgeNudge/trunk/INSTALL.txt ============================================================================== --- z3/NudgeNudge/trunk/INSTALL.txt (original) +++ z3/NudgeNudge/trunk/INSTALL.txt Mon Apr 2 01:14:20 2007 @@ -17,30 +17,28 @@ $ python2.4 bootstrap/bootstrap.py 4. Run the buildout to install required packages (grok, deliverance, - paste.deploy, zope.paste, etc.) and create the Zope 3 instance - automatically:: + paste.deploy, zope.paste, etc.) and create the Zope 3 configuration + for NudgeNudge automatically:: $ bin/buildout ...lots of output here... -5. Start Zope:: +5. We are now able start up Zope using the following command:: $ parts/instance/bin/runzope - You will now be able to create a NudgeNudge application object by - pointing your webbrowser to http://localhost:8080. + Then we can create a NudgeNudge application object by pointing our + webbrowser to http://localhost:8080. Let's call it "nudge". -6. To switch on the theming middleware, edit ``parts/etc/zope.conf`` - and add the following server definition:: - - - type Paste.Main - address 8081 - - - You'll have to restart Zope after this change. You'll then be able - to access the unthemed application on port 8080 like before and the - themed one on port 8081. +6. To run the NudgeNudge application using the PasteDeploy stack and + therefore themed using Deliverance, start the server using the + following command:: + + $ bin/paster serve nudge.ini + + You'll then be able to access the themed application at + http://localhost:8080/nudge and unthemed at + http://localhost:8080/notheme/nudge. Note that the Deliverance middleware requires lxml to do the theming which is known to have problems on certain platforms, From philikon at codespeak.net Mon Apr 2 01:22:17 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:22:17 +0200 (CEST) Subject: [z3-checkins] r41786 - z3/NudgeNudge/trunk Message-ID: <20070401232217.8064F10080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:22:15 2007 New Revision: 41786 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: Move and fix [test] part (it's not really used anyway, but why not) Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Mon Apr 2 01:22:15 2007 @@ -2,15 +2,6 @@ parts = data server instance test develop = . deliverance zope.paste -[test] -working-directory = parts/instance -eggs = nudgenudge -recipe = zc.recipe.testrunner -extra-paths = parts/zope3/src -defaults = ['--tests-pattern', '^f?tests$', - '-v' - ] - [data] recipe = zc.recipe.filestorage @@ -59,3 +50,11 @@ grok-meta nudgenudge +[test] +working-directory = parts/instance +eggs = nudgenudge +recipe = zc.recipe.testrunner +extra-paths = ${zope3:location}/lib/python +defaults = ['--tests-pattern', '^f?tests$', + '-v' + ] From philikon at codespeak.net Mon Apr 2 01:23:05 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:23:05 +0200 (CEST) Subject: [z3-checkins] r41787 - z3/NudgeNudge/trunk Message-ID: <20070401232305.2A07F10080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:23:03 2007 New Revision: 41787 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: Move [data] part, just cosmetics Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Mon Apr 2 01:23:03 2007 @@ -2,9 +2,6 @@ parts = data server instance test develop = . deliverance zope.paste -[data] -recipe = zc.recipe.filestorage - [zope3] location = /usr/local/Zope-3.3.1 @@ -50,6 +47,9 @@ grok-meta nudgenudge +[data] +recipe = zc.recipe.filestorage + [test] working-directory = parts/instance eggs = nudgenudge From philikon at codespeak.net Mon Apr 2 01:23:52 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Mon, 2 Apr 2007 01:23:52 +0200 (CEST) Subject: [z3-checkins] r41788 - z3/NudgeNudge/trunk Message-ID: <20070401232352.A720710080@code0.codespeak.net> Author: philikon Date: Mon Apr 2 01:23:50 2007 New Revision: 41788 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: More cosmetics: change order in which parts are executed Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Mon Apr 2 01:23:50 2007 @@ -1,5 +1,5 @@ [buildout] -parts = data server instance test +parts = data instance server test develop = . deliverance zope.paste [zope3] From kobold at codespeak.net Mon Apr 2 08:22:56 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Mon, 2 Apr 2007 08:22:56 +0200 (CEST) Subject: [z3-checkins] r41791 - z3/sqlos/trunk/src/sqlos Message-ID: <20070402062256.0AF4A10077@code0.codespeak.net> Author: kobold Date: Mon Apr 2 08:22:53 2007 New Revision: 41791 Modified: z3/sqlos/trunk/src/sqlos/_transaction.py Log: Fixed a bug. Modified: z3/sqlos/trunk/src/sqlos/_transaction.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/_transaction.py (original) +++ z3/sqlos/trunk/src/sqlos/_transaction.py Mon Apr 2 08:22:53 2007 @@ -44,9 +44,23 @@ This function should not cause SQL to be sent as it is not defined whether the SQL connection will commit before or after this is executed. + + This method should work even if the object doesn't have an id attribute: it + sometimes happens that SQLObject instances don't have one. + + >>> class Dummy: + ... def expire(self): + ... print "Expires" + + >>> obj = Dummy() + >>> expireSQLObject(obj) + Expires + """ - for connection in connCache.values(): - connection.cache.expire(obj.id, obj.__class__) + # Sometimes, the object doesn't have the id: in this case, ignore it. + if hasattr(obj, 'id'): + for connection in connCache.values(): + connection.cache.expire(obj.id, obj.__class__) # Expire object values. The transaction has either been aborted or # committed. From kobold at codespeak.net Mon Apr 2 14:11:35 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Mon, 2 Apr 2007 14:11:35 +0200 (CEST) Subject: [z3-checkins] r41800 - z3/sqlos/trunk/src/sqlos Message-ID: <20070402121135.4FB3D10077@code0.codespeak.net> Author: kobold Date: Mon Apr 2 14:11:30 2007 New Revision: 41800 Modified: z3/sqlos/trunk/src/sqlos/_transaction.py Log: Fix. Modified: z3/sqlos/trunk/src/sqlos/_transaction.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/_transaction.py (original) +++ z3/sqlos/trunk/src/sqlos/_transaction.py Mon Apr 2 14:11:30 2007 @@ -54,7 +54,6 @@ >>> obj = Dummy() >>> expireSQLObject(obj) - Expires """ # Sometimes, the object doesn't have the id: in this case, ignore it. @@ -62,9 +61,9 @@ for connection in connCache.values(): connection.cache.expire(obj.id, obj.__class__) - # Expire object values. The transaction has either been aborted or - # committed. - obj.expire() + # Expire object values. The transaction has either been aborted or + # committed. + obj.expire() class SQLObjectTransactionManager: From ianb at codespeak.net Thu Apr 5 23:25:30 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 5 Apr 2007 23:25:30 +0200 (CEST) Subject: [z3-checkins] r41917 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405212530.6EFB810077@code0.codespeak.net> Author: ianb Date: Thu Apr 5 23:25:28 2007 New Revision: 41917 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py Log: remove commented line Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py Thu Apr 5 23:25:28 2007 @@ -1,6 +1,5 @@ from paste.cascade import Cascade from paste.urlparser import StaticURLParser -#from paste.deploy.config import ConfigMiddleware from paste.deploy.converters import asbool from paste.recursive import RecursiveMiddleware from paste.registry import RegistryManager From ianb at codespeak.net Thu Apr 5 23:25:58 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 5 Apr 2007 23:25:58 +0200 (CEST) Subject: [z3-checkins] r41918 - z3/deliverance/DeliveranceVHoster/trunk Message-ID: <20070405212558.73D9E10078@code0.codespeak.net> Author: ianb Date: Thu Apr 5 23:25:57 2007 New Revision: 41918 Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py Log: Add PasteScript dependency, simplify Paste dependency Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Thu Apr 5 23:25:57 2007 @@ -8,7 +8,8 @@ #author_email="", #url="", install_requires=[ - 'Paste==dev,>1.1.1', # There's a bug fix we need + 'Paste>1.1.1', + 'PasteScript', 'Deliverance', 'WSGIFilter', 'HTTPEncode', From ianb at codespeak.net Thu Apr 5 23:26:18 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 5 Apr 2007 23:26:18 +0200 (CEST) Subject: [z3-checkins] r41919 - z3/deliverance/DeliveranceVHoster/trunk/tests/test-static/blah Message-ID: <20070405212618.1E69010077@code0.codespeak.net> Author: ianb Date: Thu Apr 5 23:26:17 2007 New Revision: 41919 Added: z3/deliverance/DeliveranceVHoster/trunk/tests/test-static/blah/index.html (contents, props changed) Log: Add index file to make testing directory easier Added: z3/deliverance/DeliveranceVHoster/trunk/tests/test-static/blah/index.html ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test-static/blah/index.html Thu Apr 5 23:26:17 2007 @@ -0,0 +1 @@ +hi From ianb at codespeak.net Thu Apr 5 23:37:09 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 5 Apr 2007 23:37:09 +0200 (CEST) Subject: [z3-checkins] r41921 - in z3/deliverance/DeliveranceVHoster/trunk: docs dvhoster tests Message-ID: <20070405213709.B36D910077@code0.codespeak.net> Author: ianb Date: Thu Apr 5 23:37:08 2007 New Revision: 41921 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Log: Fixed some tests that were unnecessarily failing. Add two new hooks -- find_remote_uri and should_theme_uri, which can do custom remote URI resolution, or disable theming entirely. Sort remote_uris by length (longest path first) so that there can never be dead (unreachable) paths. Allow a headers key in that dictionary, to set extra headers on the request. Removed a bunch of debugging print statements Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py Thu Apr 5 23:37:08 2007 @@ -36,4 +36,23 @@ ('X-Openplans-Project', project), ] - +def find_remote_uri(remote_uri, remote_uri_info, environ, + app_conf): + from paste.request import path_info_pop + if remote_uri is not None: + return remote_uri + path_info = environ.get('PATH_INFO', '') + if path_info.startswith('/tasks'): + remote_uri = 'http://localhost:5000' + # Move /tasks to SCRIPT_NAME + path_info_pop(environ) + else: + remote_uri = 'http://localhost:8080' + return remote_uri + +def should_theme_uri(remote_uri, environ, app_conf): + try: + no_theme = int(environ.get('HTTP_X_NO_THEME', '0')) + except ValueError: + no_theme = 0 + return not no_theme Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py Thu Apr 5 23:37:08 2007 @@ -231,6 +231,7 @@ required_keys = () optional_keys = () trail_slash_keys = () + sort_key = None def validate_python(self, value, state=None): # Should be like [{'path': path, 'remote_uri': uri, 'comment': str}] @@ -263,12 +264,16 @@ continue if not d[key].endswith('/'): d[key] += '/' + if self.sort_key: + value = sorted(value, key=self.sort_key) return value class RemoteURIValidator(ListDictValidator): - required_keys = ('path', 'remote_uri') - optional_keys = ('comment', ) + required_keys = ('path', ) + optional_keys = ('comment', 'headers', 'remote_uri') trail_slash_keys = ('path', 'remote_uri') + def sort_key(self, item): + return -len(item['path']) class RewriteValidator(ListDictValidator): required_keys = ('rewrite', ) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Thu Apr 5 23:37:08 2007 @@ -33,6 +33,14 @@ if init_domain: init_domain = load_func(init_domain, 'init_domain') self.init_domain = init_domain + find_remote_uri = app_conf.get('find_remote_uri') + if find_remote_uri: + find_remote_uri = load_func(find_remote_uri, 'find_remote_uri') + self.find_remote_uri = find_remote_uri + should_theme_uri = app_conf.get('should_theme_uri') + if should_theme_uri: + should_theme_uri = load_func(should_theme_uri, 'should_theme_uri') + self.should_theme_uri = should_theme_uri self.app_conf = app_conf self.provider = DataProvider(data_dir) self.rewrite_links = asbool(app_conf.get('rewrite_links', True)) @@ -59,7 +67,6 @@ environ, with_query_string=False, path_info='') path_info = norm_path(environ.get('PATH_INFO', '')) - print 'path_info', repr(path_info), repr(environ['PATH_INFO']) if path_info.startswith('/.deliverance'): path_info_pop(environ) subapp = ProviderApp(domain_info) @@ -129,21 +136,22 @@ for header_name, header_value in domain_info.additional_request_headers: header_name = 'HTTP_%s' % header_name.upper().replace('-', '_') environ[header_name] = header_value - + for remote_uri_info in remote_uris: - path = remote_uri_info['path'] + path = str(remote_uri_info['path']) if not path.endswith('/'): path += '/' if path_info + '/' == path: - print 'redirect', [remote_uri_info, path, path_info] exc = httpexceptions.HTTPMovedPermanently( headers=[('location', construct_url(environ, path_info=path_info+'/'))]) return exc(environ, start_response) if path_info.startswith(path): # Found a match - remote_uri = remote_uri_info['remote_uri'] + remote_uri = remote_uri_info.get('remote_uri') environ['SCRIPT_NAME'] += path[:-1] environ['PATH_INFO'] = path_info[len(path)-1:] + if self.find_remote_uri: + remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) break if not remote_uri: exc = httpexceptions.HTTPNotFound( @@ -152,8 +160,10 @@ % (path_info, ', '.join([repr(r['path']) for r in remote_uris]))) return exc(environ, start_response) - print 'Proxy to %r with %r (SCRIPT_NAME=%r)' % ( - remote_uri, construct_url(environ), environ['SCRIPT_NAME']) + should_theme_uri = True + if self.should_theme_uri: + should_theme_uri = self.should_theme_uri( + remote_uri, environ, self.app_conf) app = proxyapp.ForcedProxy( remote=remote_uri, force_host=True) @@ -163,11 +173,12 @@ rule_uri = construct_url( environ, with_query_string=False, path_info='/_rules/rule.xml') - app = DeliveranceMiddleware( - app, - theme_uri=domain_info.theme_uri, - rule_uri=rule_uri, - renderer=Renderer) + if should_theme_uri: + app = DeliveranceMiddleware( + app, + theme_uri=domain_info.theme_uri, + rule_uri=rule_uri, + renderer=Renderer) return app(environ, start_response) def find_file(self, path): Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Thu Apr 5 23:37:08 2007 @@ -8,6 +8,7 @@ for attr in ['get_app', 'connect']: setattr(httplib.HTTPConnection, attr, getattr(wsgi_intercept.WSGI_HTTPConnection, attr).im_func) +from wsgifilter.proxyapp import DebugHeaders data_filename = os.path.join(os.path.dirname(__file__), 'test-data') wsgi_app = make_app({}, data_dir=data_filename) @@ -30,13 +31,6 @@ ''' -static_app = StaticURLParser(os.path.join(os.path.dirname(__file__), - 'test-static')) -def make_static_app(): - return static_app - -wsgi_intercept.add_wsgi_intercept('wsgify.org', 80, make_static_app) - def test_everything(): yield (reset_env,) @@ -74,8 +68,10 @@ data = ''' [{"path": "/bar", "remote_uri": "http://wsgify.org/blah", "comment": "x"}, - {"path": "/", "remote_uri": "http://wsgify.org/"}] + {"path": "/", "remote_uri": "http://wsgify.org/"} + ] ''' + #{"path": "/testme", "headers": {"X-Test-Me": "testme"} put('/.deliverance/remote_uris', data) # It gets normalized, so it doesn't actually stay the same: @@ -88,6 +84,8 @@ #res = res.follow() #print res #assert res.status == 200 + ## So instead we just get a page we know works: + res = app.get('/bar/index.html', status=200) data = ''' [{"path": "/test1.html", "rewrite": "/test1"}, @@ -146,3 +144,14 @@ res.mustcontain('localhost') assert app.get('/.deliverance/domain').body == 'localhost2' print 'site renamed to localhost2' + + +def setup_module(module): + static_app = DebugHeaders(StaticURLParser(os.path.join(os.path.dirname(__file__), + 'test-static'))) + + wsgi_intercept.add_wsgi_intercept('wsgify.org', 80, lambda : static_app) + +def teardown_module(module): + wsgi_intercept.remove_wsgi_intercept('wsgify.org', 80) + Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Thu Apr 5 23:37:08 2007 @@ -1,19 +1,29 @@ import os import shutil -import shutil from paste.fixture import TestApp from dvhoster.wsgiapp import make_app import httplib import simplejson +import urllib +import wsgi_intercept +for attr in ['get_app', 'connect']: + setattr(httplib.HTTPConnection, attr, + getattr(wsgi_intercept.WSGI_HTTPConnection, attr).im_func) example = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'docs', 'example_init_domain.py') data_filename = os.path.join(os.path.dirname(__file__), 'test-data') +if os.path.exists(data_filename): + shutil.rmtree(data_filename) +os.mkdir(data_filename) + wsgi_app = make_app({}, init_domain=example, + find_remote_uri=example, + should_theme_uri=example, zope_location='http://localhost:8080', - default_theme_uri='http://yahoo.com', + default_theme_uri='http://openplans.org', data_dir=data_filename) app = TestApp(wsgi_app) @@ -30,3 +40,39 @@ print got print expected assert got == expected + +def test_find_remote_uri(): + # First make double-sure wsgi_intercept is working: + f = urllib.urlopen('http://localhost:8080/foo') + c = f.read() + f.close() + assert "SERVER_PORT: '8080'" in c + # Now to test find_remote_uri; first we have to get rid of the + # remote_uri value that init_domain set: + extra = {'HTTP_HOST': 'foo2.openplans.org'} + app.post('/.deliverance/remote_uris', '[{"path": ""}]', extra_environ={'HTTP_HOST': 'foo2.openplans.org', 'REQUEST_METHOD': 'PUT', 'CONTENT_TYPE': 'application/json'}, status=204) + res = app.get('/tasks', extra_environ=extra) + res.mustcontain("SERVER_PORT: '5000'") + res = app.get('/blah', extra_environ=extra) + res.mustcontain("SERVER_PORT: '8080'") + +def test_should_theme_uri(): + # We need HTML so it can be themed: + setup_module(None, text=False) + res = app.get('/', extra_environ={'HTTP_HOST': 'foo3.openplans.org'}) + # A sign it was themed: + res.mustcontain('Plone') + res = app.get('/', extra_environ={'HTTP_X_NO_THEME': '1', 'HTTP_HOST': 'foo3.openplans.org'}) + assert 'Plone' not in res + +def setup_module(module, text=True): + from paste.script import testapp + app = testapp.TestApplication(text=text) + for port in [5000, 8080]: + wsgi_intercept.add_wsgi_intercept( + 'localhost', port, lambda : app) + +def teardown_module(module): + for port in [5000, 8080]: + wsgi_intercept.remove_wsgi_intercept( + 'localhost', port) From ianb at codespeak.net Fri Apr 6 00:20:13 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:20:13 +0200 (CEST) Subject: [z3-checkins] r41922 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070405222013.B4CDD10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:20:11 2007 New Revision: 41922 Added: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py - copied, changed from r41921, z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py Log: Added a more specific openplans example Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py Fri Apr 6 00:20:11 2007 @@ -1,7 +1,6 @@ # the init_domain setting points to a file or module (a file like this # one). It allows you to define a function that will be run on any -# newly created domain. Here you can put in default settings. This -# example is what we use for openplans.org +# newly created domain. Here you can put in default settings. import re Copied: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (from r41921, z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py) ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Fri Apr 6 00:20:11 2007 @@ -1,9 +1,13 @@ -# the init_domain setting points to a file or module (a file like this -# one). It allows you to define a function that will be run on any -# newly created domain. Here you can put in default settings. This -# example is what we use for openplans.org +# the init_domain, find_remote_uri, and should_theme_uri settings +# point to a file or module (a file like this one). It allows you to +# define a function that will be run on any newly created domain, +# define how requests are mapped to backend domains, and conditionally +# theme requests. Here you can put in default settings. This example +# is what we use for openplans.org import re +from paste.deploy.converters import asbool +from paste.request import path_info_pop rule_data = """\ @@ -13,46 +17,61 @@ """ - def init_domain(domain_info, app_conf): + r""" + Initializes an openplans project, based on a domain regular + expression (default ``^(.*)\.openplans\.org$`` but you can + override with the ``domain_regex`` config setting). + + Also requires a ``default_theme_uri`` setting. + """ domain = domain_info.domain - match = re.search(r'^(.*)\.openplans\.org$', domain, re.I) + regex = app_conf.get('domain_regex', r'^(.*)\.openplans\.org$') + match = re.search(domain_regex, domain, re.I) if not match: # Don't try to set up domains we don't recognize return project = match.group(1) - remote_uri = ( - '%s/VirtualHostBase/http/%s:80/openplans/projects/%s/VirtualHostRoot' - % (app_conf['zope_location'], - domain, - project)) - domain_info.remote_uris = [ + remote_uris = [ {'path': '', - 'remote_uri': remote_uri}] + 'headers': {'X-Openplans-Project': project}}, + ] + domain_info.remote_uris = remote_uris domain_info.theme_uri = app_conf['default_theme_uri'] domain_info.set_rule_file( 'rule.xml', rule_data) - domain_info.additional_request_headers = [ - ('X-Openplans-Project', project), - ] - + def find_remote_uri(remote_uri, remote_uri_info, environ, app_conf): - from paste.request import path_info_pop + """ + Maps request to a remote_uri (when none has been explicitly set). + + You must configure a task_tracker_uri and zope_uri (typically + ``http://localhost:X``). + """ if remote_uri is not None: + # It's already explicitly set return remote_uri + zope_uri = app_conf['zope_uri'] + task_tracker_uri = app_conf['task_tracker_uri'] + project = environ['HTTP_X_OPENPLANS_PROJECT'] path_info = environ.get('PATH_INFO', '') if path_info.startswith('/tasks'): - remote_uri = 'http://localhost:5000' + remote_uri = task_tracker_uri # Move /tasks to SCRIPT_NAME path_info_pop(environ) else: - remote_uri = 'http://localhost:8080' + remote_uri = '%s/VirtualHostBase/http/%s/openplans/projects/%s/VirtualHostRoot' % ( + zope_uri, + environ['HTTP_HOST'], + project) return remote_uri def should_theme_uri(remote_uri, environ, app_conf): - try: - no_theme = int(environ.get('HTTP_X_NO_THEME', '0')) - except ValueError: - no_theme = 0 - return not no_theme + """ + This will avoid theming Zope URLs, but only if you have set the + configuration ``no_filter_zope = true`` + """ + if not asbool(app_conf.get('no_filter_zope')): + return True + return not remote_uri.startswith(app_conf['zope_uri']) From ianb at codespeak.net Fri Apr 6 00:25:41 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:25:41 +0200 (CEST) Subject: [z3-checkins] r41923 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405222541.D8CF110077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:25:41 2007 New Revision: 41923 Added: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py - copied unchanged from r41921, z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py Removed: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Renamed dataprovider to more normal name 'model' Deleted: /z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py ============================================================================== --- /z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dataprovider.py Fri Apr 6 00:25:41 2007 +++ (empty file) @@ -1,327 +0,0 @@ -import re -import os -from ohm import persist -from ohm import server -from ohm import descriptors -from ohm import lildav -from ohm.validators import LineConverter -from formencode import validators -from formencode.foreach import ForEach -from formencode.compound import All - -domain_re = re.compile(r'^localhost|[a-z][a-z0-9.\-]+\.[a-z]+$', re.I) - -default_rule_xml = '''\ - - - - - - -''' - -marker = '' -abstract_rule_xml = '''\ - -MARKER - - - - - -'''.replace('MARKER', marker) - -default_standardrules = '''\ - - - - - - - - -''' - -class DataProvider(object): - - def __init__(self, dir): - self.dir = dir - if not os.path.exists(self.dir): - print 'Creating data directory %s' % self.dir - os.makedirs(self.dir) - - def alias_fn(self, alias): - return os.path.join(self.dir, alias+'-alias.txt') - - def domain(self, domain_name, aliases=()): - """ - Return the domain object for the given domain_name. The - domain name given may not be the canonical domain. - """ - domain_name = self.normalize(domain_name) - alias_fn = self.alias_fn(domain_name) - if os.path.exists(alias_fn): - f = open(alias_fn, 'rb') - alias = f.read() - f.close() - aliases = list(aliases) - if alias in aliases: - raise ValueError( - "Infinite alias loop (found: %s -> %s)" - % (aliases, alias)) - aliases.append(alias) - return self.domain(alias, aliases=aliases) - dir = os.path.join(self.dir, domain_name) - if not os.path.exists(dir): - os.mkdir(dir) - return DomainDataProvider(self, domain_name, dir) - - def normalize(self, domain_name): - """ - Normalize a domain name (lower case, no funny characters). - """ - domain_name = domain_name.strip().lower() - if not domain_re.search(domain_name): - raise ValueError( - 'Bad domain name: %r' % domain_name) - return domain_name - - def add_alias(self, alias, domain): - """ - Add an alias domain ``alias`` which points to ``domain``. - There must not be an existing alias. - """ - alias = self.normalize(alias) - domain = self.normalize(domain) - fn = self.alias_fn(alias) - assert not os.path.exists(fn), ( - "Alias file already exists (%r)" % fn) - f = open(fn, 'wb') - f.write(domain) - f.close() - - def remove_alias(self, alias, domain=None): - """ - Remove the alias for the domain ``alias``. ``domain`` (if - given) is what the alias should currently be pointing to (we - won't remove the alias then if it points elsewhere). - """ - alias = self.normalize(alias) - if domain: - domain = self.normalize(domain) - fn = self.alias_fn(alias) - if not os.path.exists(fn): - raise ValueError( - "Alias does not exist (not file %r)" % fn) - if domain: - f = open(fn, 'rb') - existing = f.read().strip() - f.close() - if existing != domain: - raise ValueError( - "Tried to remove alias from %s->%s, but %s actually " - "points to %s" % (alias, domain, alias, existing)) - os.unlink(fn) - - def rename_domain(self, old_domain_name, new_domain_name): - """ - Rename the old domain to the new domain, returning the new domain - object. - """ - old_domain_name = self.normalize(old_domain_name) - new_domain_name = self.normalize(new_domain_name) - old_dir = os.path.join(self.dir, old_domain_name) - new_dir = os.path.join(self.dir, new_domain_name) - assert os.path.exists(old_dir) - assert not os.path.exists(new_dir) - os.rename(old_dir, new_dir) - return self.domain(new_domain_name) - -class DomainDataProvider(object): - - def __init__(self, provider, domain_name, base_dir): - self._domain_name = domain_name - self.base_dir = base_dir - self.provider = provider - - def __repr__(self): - return '<%s %s for %s in %r>' % ( - self.__class__.__name__, - hex(id(self)), - self._domain_name, - self.base_dir) - - def initialize(self): - for dir in [self.base_dir, self.rule_dir, - self.static_dir]: - if not os.path.exists(dir): - os.mkdir(dir) - for filename, content in [ - ('rule.xml', default_rule_xml), - ('standardrules.xml', default_standardrules)]: - filename = os.path.join(self.rule_dir, filename) - if not os.path.exists(filename): - f = open(filename, 'w') - f.write(content) - f.close() - - @property - def initialized(self): - return hasattr(self, 'remote_uris') - - @property - def rule_dir(self): - return os.path.join(self.base_dir, 'rules') - - @property - def static_dir(self): - return os.path.join(self.base_dir, 'static') - - remote_uris = descriptors.json_converter( - persist.file_property('remote_uris.txt')) - theme_uri = persist.file_property('theme_uri.txt') - redirects = descriptors.json_converter( - persist.file_property('redirects.txt', default='[]')) - - additional_request_headers = descriptors.json_converter( - persist.file_property('additional_request_headers.txt', default='[]')) - - def aliases__rename(self, old_aliases, new_aliases): - dropped = list(old_aliases) - added = list(new_aliases) - for new_alias in new_aliases: - if new_alias in dropped: - dropped.remove(new_alias) - added.remove(new_alias) - for alias in dropped: - self.provider.remove_alias(alias, self.domain) - for alias in added: - self.provider.add_alias(alias, self.domain) - - aliases = descriptors.watcher( - descriptors.line_converter(persist.file_property('aliases.txt', default='')), - after_watcher=aliases__rename) - - def set_rule_file(self, filename, content): - filename = os.path.join(self.rule_dir, filename) - f = open(filename, 'wb') - f.write(content) - f.close() - - def domain__get(self): - return self._domain_name - - def domain__set(self, new_domain): - aliases = self.aliases - old_domain = self.domain - new_obj = self.provider.rename_domain(self.domain, new_domain) - # Clone new object as self: - self.__dict__.update(new_obj.__dict__) - for alias in aliases: - self.provider.remove_alias(alias, domain=old_domain) - self.provider.add_alias(alias, new_domain) - - domain = property(domain__get, domain__set) - -class DomainValidator(validators.Regex): - regex = r'^[a-z0-9\-]+|[a-z0-9][a-z0-9\-\.\_]*\.[a-z]+$' - -class ListDictValidator(validators.FancyValidator): - required_keys = () - optional_keys = () - trail_slash_keys = () - sort_key = None - - def validate_python(self, value, state=None): - # Should be like [{'path': path, 'remote_uri': uri, 'comment': str}] - # comment is optional - try: - assert isinstance(value, list), 'Must be list' - for d in value: - keys = d.keys() - for key in self.required_keys: - assert key in d, "Must have key %r in %r" % d - assert isinstance(d[key], basestring), ( - '%s must be string (not %r)' % (key, d[key])) - keys.remove(key) - for key in self.optional_keys: - if key not in d: - continue - assert isinstance(d[key], basestring), ( - '%s must be string (not %r)' % (key, d[key])) - keys.remove(key) - assert not keys, ( - "Key(s) not allowed: %s in %r" - % (', '.join(map(repr, keys)), d)) - except AssertionError, e: - raise validators.Invalid(str(e), value, state) - - def _to_python(self, value, state=None): - for d in value: - for key in self.trail_slash_keys: - if key not in d: - continue - if not d[key].endswith('/'): - d[key] += '/' - if self.sort_key: - value = sorted(value, key=self.sort_key) - return value - -class RemoteURIValidator(ListDictValidator): - required_keys = ('path', ) - optional_keys = ('comment', 'headers', 'remote_uri') - trail_slash_keys = ('path', 'remote_uri') - def sort_key(self, item): - return -len(item['path']) - -class RewriteValidator(ListDictValidator): - required_keys = ('rewrite', ) - # @@: Really we should require one of path or prefix - optional_keys = ('path', 'prefix', 'comment') - trail_slash_keys = ('prefix', 'rewrite') - -class HeaderValidator(validators.FancyValidator): - header_name_re = re.compile(r'^[a-zA-Z][a-zA-Z0-9-]+$') - header_value_re = re.compile(r'^[^\n\r\000-\037\200-\377]*$') - - def validate_python(self, value, state=None): - assert isinstance(value, list), ( - "Value must be a list (not %r)" % value) - for item in list: - assert isinstance(value, (list, tuple)), ( - "Item must be a list or tuple (not %r)" % value) - assert len(item) == 2, ( - "Item must be a two-tuple (not %r)" % value) - header, value = item - assert header_name_re.search(header), ( - "Header name invalid: %r" % header) - assert header_value_re.search(value), ( - "Header value invalid: %r" % value) - -class ProviderApp(server.ApplicationWrapper): - - theme_uri = server.Setter( - validator=validators.URL()) - domain = server.Setter( - validator=DomainValidator()) - aliases = server.Setter( - validator=All(ForEach(DomainValidator()), LineConverter())) - remote_uris = server.JSONSetter( - validator=RemoteURIValidator()) - redirects = server.JSONSetter( - validator=RewriteValidator()) - additional_request_headers = server.JSONSetter( - validator=HeaderValidator()) - - @server.appfactory() - def rules(self): - if not os.path.exists(self.rule_dir): - os.makedirs(self.rule_dir) - return lildav.LilDAV(self.rule_dir) - - @server.appfactory() - def static(self): - if not os.path.exists(self.static_dir): - os.makedirs(self.static_dir) - return lildav.LilDAV(self.static_dir) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 00:25:41 2007 @@ -10,7 +10,7 @@ from wsgifilter import proxyapp from wsgifilter import relocateresponse from deliverance.wsgimiddleware import DeliveranceMiddleware -from dvhoster.dataprovider import DataProvider, ProviderApp +from dvhoster.model import DataProvider, ProviderApp from dvhoster import current_environ from dvhoster.debuginterp import Renderer from dvhoster.util import load_func From ianb at codespeak.net Fri Apr 6 00:32:22 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:32:22 +0200 (CEST) Subject: [z3-checkins] r41924 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070405223222.825F210077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:32:21 2007 New Revision: 41924 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: typo Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Fri Apr 6 00:32:21 2007 @@ -26,7 +26,7 @@ Also requires a ``default_theme_uri`` setting. """ domain = domain_info.domain - regex = app_conf.get('domain_regex', r'^(.*)\.openplans\.org$') + domain_regex = app_conf.get('domain_regex', r'^(.*)\.openplans\.org$') match = re.search(domain_regex, domain, re.I) if not match: # Don't try to set up domains we don't recognize From ianb at codespeak.net Fri Apr 6 00:33:35 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:33:35 +0200 (CEST) Subject: [z3-checkins] r41925 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405223335.6704310077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:33:34 2007 New Revision: 41925 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Log: Rename some classes in dvhost.model to make more sense. Add some docstrings too Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 00:33:34 2007 @@ -10,7 +10,7 @@ from wsgifilter import proxyapp from wsgifilter import relocateresponse from deliverance.wsgimiddleware import DeliveranceMiddleware -from dvhoster.model import DataProvider, ProviderApp +from dvhoster.model import DomainInfoSet, DomainInfoApp from dvhoster import current_environ from dvhoster.debuginterp import Renderer from dvhoster.util import load_func @@ -42,7 +42,7 @@ should_theme_uri = load_func(should_theme_uri, 'should_theme_uri') self.should_theme_uri = should_theme_uri self.app_conf = app_conf - self.provider = DataProvider(data_dir) + self.provider = DomainInfoSet(data_dir) self.rewrite_links = asbool(app_conf.get('rewrite_links', True)) if app_conf.get('clean_environ_headers_regex'): self.clean_environ_headers_regex = re.compile(app_conf['clean_environ_headers_regex']) @@ -69,7 +69,7 @@ path_info = norm_path(environ.get('PATH_INFO', '')) if path_info.startswith('/.deliverance'): path_info_pop(environ) - subapp = ProviderApp(domain_info) + subapp = DomainInfoApp(domain_info) return subapp(environ, start_response) if domain_info.domain != domain: Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Fri Apr 6 00:33:34 2007 @@ -43,7 +43,16 @@ ''' -class DataProvider(object): +class DomainInfoSet(object): + """ + Represents a set of DomainInfo objects. + + Concretely, all domain info is in one directory, and this + represents that directory. It creates new DomainInfo objects and + does some management around them. + + This also handles aliases -- domains that point to other domains. + """ def __init__(self, dir): self.dir = dir @@ -52,12 +61,31 @@ os.makedirs(self.dir) def alias_fn(self, alias): + """ + Filename where an alias is kept. + + Each alias is just the domain name plus ``-alias.txt``, and + contains the name of another domain name. + """ return os.path.join(self.dir, alias+'-alias.txt') + def normalize(self, domain_name): + """ + Normalize a domain name (lower case, no funny characters). + """ + domain_name = domain_name.strip().lower() + if not domain_re.search(domain_name): + raise ValueError( + 'Bad domain name: %r' % domain_name) + return domain_name + def domain(self, domain_name, aliases=()): """ - Return the domain object for the given domain_name. The - domain name given may not be the canonical domain. + Return the domain object for the given domain_name. + + The domain name given may not be the canonical domain (that + is, you might get back and object with a different value for + ``.domain``). """ domain_name = self.normalize(domain_name) alias_fn = self.alias_fn(domain_name) @@ -75,17 +103,7 @@ dir = os.path.join(self.dir, domain_name) if not os.path.exists(dir): os.mkdir(dir) - return DomainDataProvider(self, domain_name, dir) - - def normalize(self, domain_name): - """ - Normalize a domain name (lower case, no funny characters). - """ - domain_name = domain_name.strip().lower() - if not domain_re.search(domain_name): - raise ValueError( - 'Bad domain name: %r' % domain_name) - return domain_name + return DomainInfo(self, domain_name, dir) def add_alias(self, alias, domain): """ @@ -138,12 +156,15 @@ os.rename(old_dir, new_dir) return self.domain(new_domain_name) -class DomainDataProvider(object): +class DomainInfo(object): + """ + Represents the information about a single domain. + """ - def __init__(self, provider, domain_name, base_dir): + def __init__(self, domain_set, domain_name, base_dir): self._domain_name = domain_name self.base_dir = base_dir - self.provider = provider + self.domain_set = domain_set def __repr__(self): return '<%s %s for %s in %r>' % ( @@ -153,6 +174,9 @@ self.base_dir) def initialize(self): + """ + Create the directory and basic files for this domain. + """ for dir in [self.base_dir, self.rule_dir, self.static_dir]: if not os.path.exists(dir): @@ -195,9 +219,9 @@ dropped.remove(new_alias) added.remove(new_alias) for alias in dropped: - self.provider.remove_alias(alias, self.domain) + self.domain_set.remove_alias(alias, self.domain) for alias in added: - self.provider.add_alias(alias, self.domain) + self.domain_set.add_alias(alias, self.domain) aliases = descriptors.watcher( descriptors.line_converter(persist.file_property('aliases.txt', default='')), @@ -215,12 +239,12 @@ def domain__set(self, new_domain): aliases = self.aliases old_domain = self.domain - new_obj = self.provider.rename_domain(self.domain, new_domain) + new_obj = self.domain_set.rename_domain(self.domain, new_domain) # Clone new object as self: self.__dict__.update(new_obj.__dict__) for alias in aliases: - self.provider.remove_alias(alias, domain=old_domain) - self.provider.add_alias(alias, new_domain) + self.domain_set.remove_alias(alias, domain=old_domain) + self.domain_set.add_alias(alias, new_domain) domain = property(domain__get, domain__set) @@ -299,7 +323,11 @@ assert header_value_re.search(value), ( "Header value invalid: %r" % value) -class ProviderApp(server.ApplicationWrapper): +class DomainInfoApp(server.ApplicationWrapper): + """ + Provides the ``/.deliverance/`` web/REST API for a single + DomainInfo object. + """ theme_uri = server.Setter( validator=validators.URL()) From ianb at codespeak.net Fri Apr 6 00:37:53 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:37:53 +0200 (CEST) Subject: [z3-checkins] r41926 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070405223753.BA96A10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:37:53 2007 New Revision: 41926 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: Print out warning/error if domain_regex doesn't match Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Fri Apr 6 00:37:53 2007 @@ -30,6 +30,7 @@ match = re.search(domain_regex, domain, re.I) if not match: # Don't try to set up domains we don't recognize + print 'The domain %r cannot be recognized by the domain_regex %r' % (domain, domain_regex) return project = match.group(1) remote_uris = [ From ianb at codespeak.net Fri Apr 6 00:42:58 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:42:58 +0200 (CEST) Subject: [z3-checkins] r41927 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405224258.3974110077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:42:57 2007 New Revision: 41927 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Log: Be more lax in domain name checking (e.g., allow 'flow') Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Fri Apr 6 00:42:57 2007 @@ -9,7 +9,7 @@ from formencode.foreach import ForEach from formencode.compound import All -domain_re = re.compile(r'^localhost|[a-z][a-z0-9.\-]+\.[a-z]+$', re.I) +domain_re = re.compile(r'^[a-z][a-z0-9-]+|[a-z][a-z0-9.\-]+\.[a-z]+$', re.I) default_rule_xml = '''\ From ianb at codespeak.net Fri Apr 6 00:59:12 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:59:12 +0200 (CEST) Subject: [z3-checkins] r41928 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405225912.5BD0610077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:59:11 2007 New Revision: 41928 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py Log: Add the HTTPException middleware, so that pieces can raise exceptions (e.g., redirect) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/wsgiapp.py Fri Apr 6 00:59:11 2007 @@ -5,12 +5,13 @@ from paste.registry import RegistryManager from wsgifilter import proxyapp from paste.exceptions.errormiddleware import ErrorMiddleware - +from paste.httpexceptions import HTTPExceptionHandler from dvhoster.dispatcher import DeliveranceDispatcher def make_app(global_conf, **app_conf): """Create a WSGI application and return it""" app = DeliveranceDispatcher(app_conf) + app = HTTPExceptionHandler(app) app = RecursiveMiddleware(app) app = RegistryManager(app) debug = app_conf['debug'] = asbool(app_conf.get('debug', global_conf.get('debug'))) From ianb at codespeak.net Fri Apr 6 00:59:53 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 00:59:53 +0200 (CEST) Subject: [z3-checkins] r41929 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070405225953.8F36910077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 00:59:52 2007 New Revision: 41929 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Refactoring of the giant __call__ method; separating out the fetching of domain_info Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 00:59:52 2007 @@ -53,15 +53,7 @@ if 'paste.registry' in environ: environ['paste.registry'].register(current_environ, environ) self.clean_environ_headers(environ) - domain = environ['HTTP_HOST'] - if ':' in domain: - domain = domain.split(':', 1)[0] - domain = self.provider.normalize(domain) - domain_info = self.provider.domain(domain) - if not domain_info.initialized: - domain_info.initialize() - if self.init_domain: - self.init_domain(domain_info, self.app_conf) + domain_info = self.get_domain_info(environ) environ['dvhoster.domain_info'] = domain_info environ['dvhoster.base_url'] = construct_url( environ, with_query_string=False, @@ -71,19 +63,6 @@ path_info_pop(environ) subapp = DomainInfoApp(domain_info) return subapp(environ, start_response) - - if domain_info.domain != domain: - # We got an alias - assert domain in domain_info.aliases, ( - "Domain %r not found in aliases %r" - % (domain, domain_info.aliases)) - new_environ = environ.copy() - new_environ['HTTP_HOST'] = domain_info.domain - new_url = construct_url(new_environ) - exc = httpexceptions.HTTPMovedPermanently( - headers=[('Location', new_url)], - comment='Redirecting to canonical domain') - return exc(environ, start_response) if path_info.startswith('/_rules'): path_info_pop(environ) @@ -195,3 +174,29 @@ if self.clean_environ_headers_regex.search(key): # @@: Should log this del environ[key] + + def get_domain_info(self, environ): + domain = environ['HTTP_HOST'] + if ':' in domain: + domain = domain.split(':', 1)[0] + domain = self.provider.normalize(domain) + domain_info = self.provider.domain(domain) + if not domain_info.initialized: + domain_info.initialize() + if self.init_domain: + self.init_domain(domain_info, self.app_conf) + + if domain_info.domain != domain: + # We got an alias + assert domain in domain_info.aliases, ( + "Domain %r not found in aliases %r" + % (domain, domain_info.aliases)) + new_environ = environ.copy() + new_environ['HTTP_HOST'] = domain_info.domain + new_url = construct_url(new_environ) + exc = httpexceptions.HTTPMovedPermanently( + headers=[('Location', new_url)], + comment='Redirecting to canonical domain') + raise exc + + return domain_info From ianb at codespeak.net Fri Apr 6 05:35:48 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 05:35:48 +0200 (CEST) Subject: [z3-checkins] r41930 - z3/deliverance/DeliveranceVHoster/trunk/tests Message-ID: <20070406033548.22E4310077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 05:35:46 2007 New Revision: 41930 Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Log: Remove DebugHeaders printing Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Fri Apr 6 05:35:46 2007 @@ -147,11 +147,11 @@ def setup_module(module): - static_app = DebugHeaders(StaticURLParser(os.path.join(os.path.dirname(__file__), - 'test-static'))) + static_app = StaticURLParser(os.path.join(os.path.dirname(__file__), + 'test-static')) wsgi_intercept.add_wsgi_intercept('wsgify.org', 80, lambda : static_app) def teardown_module(module): wsgi_intercept.remove_wsgi_intercept('wsgify.org', 80) - + From ianb at codespeak.net Fri Apr 6 05:36:03 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 05:36:03 +0200 (CEST) Subject: [z3-checkins] r41931 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070406033603.8289610078@code0.codespeak.net> Author: ianb Date: Fri Apr 6 05:36:02 2007 New Revision: 41931 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Refactoring that changes no functionality Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 05:36:02 2007 @@ -27,6 +27,12 @@ class DeliveranceDispatcher(object): + """ + Main WSGI application that handles dispatching to the API handler, + redirects, static files, and finding the proper remote URI to + proxy to. + """ + def __init__(self, app_conf): data_dir = app_conf['data_dir'] init_domain = app_conf.get('init_domain') @@ -50,6 +56,9 @@ self.clean_environ_headers_regex = None def __call__(self, environ, start_response): + """ + WSGI interface + """ if 'paste.registry' in environ: environ['paste.registry'].register(current_environ, environ) self.clean_environ_headers(environ) @@ -58,7 +67,7 @@ environ['dvhoster.base_url'] = construct_url( environ, with_query_string=False, path_info='') - path_info = norm_path(environ.get('PATH_INFO', '')) + environ['PATH_INFO'] = path_info = norm_path(environ.get('PATH_INFO', '')) if path_info.startswith('/.deliverance'): path_info_pop(environ) subapp = DomainInfoApp(domain_info) @@ -70,68 +79,26 @@ subapp = StaticURLParser( domain_info.rule_dir) return subapp(environ, start_response) - - static_path = os.path.join(domain_info.static_dir, - path_info.lstrip('/')) - static_fn = self.find_file(static_path) - if static_fn is not None: - # Explicit override of a file - app = FileApp(static_fn) - return app(environ, start_response) - try: - remote_uris = domain_info.remote_uris - except AttributeError: + + static_app = self.find_static_file(domain_info, path_info) + if static_app: + return static_app(environ, start_response) + + if not domain_info.initialized: exc = httpexceptions.HTTPNotFound( "This domain has not yet been configured (no remote " "URI has been configured for %s)" % domain_info.domain) return exc(environ, start_response) - remote_uri = None - current_uri = construct_url(environ) - for redirect_info in domain_info.redirects: - if 'path' in redirect_info: - if redirect_info['path'] == path_info: - new = redirect_info['rewrite'] - new = urlparse.urljoin(current_uri, redirect_info['rewrite']) - exc = httpexceptions.HTTPMovedPermanently( - headers=[('Location', new)]) - return exc(environ, start_response) - elif 'prefix' in redirect_info: - assert redirect_info['prefix'].endswith('/') - new_uri = None - if path_info == redirect_info['prefix'][:-1]: - new_uri = redirect_info['rewrite'] + '/' - elif path_info.startswith(redirect_info['prefix']): - new_uri = redirect_info['rewrite'] - if not new_uri.endswith('/'): - new_uri += '/' - new_uri += path_info[len(redirect_info['prefix']):] - if new_uri is not None: - new_uri = urlparse.urljoin(current_uri, new_uri) - exc = httpexceptions.HTTPMovedPermanently( - headers=[('Location', new_uri)]) - return exc(environ, start_response) - for header_name, header_value in domain_info.additional_request_headers: - header_name = 'HTTP_%s' % header_name.upper().replace('-', '_') - environ[header_name] = header_value + redir_app = self.check_redirects( + path_info, domain_info, environ) + if redir_app: + return redir_app(environ, start_response) - for remote_uri_info in remote_uris: - path = str(remote_uri_info['path']) - if not path.endswith('/'): - path += '/' - if path_info + '/' == path: - exc = httpexceptions.HTTPMovedPermanently( - headers=[('location', construct_url(environ, path_info=path_info+'/'))]) - return exc(environ, start_response) - if path_info.startswith(path): - # Found a match - remote_uri = remote_uri_info.get('remote_uri') - environ['SCRIPT_NAME'] += path[:-1] - environ['PATH_INFO'] = path_info[len(path)-1:] - if self.find_remote_uri: - remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) - break + self.set_additional_headers(domain_info, environ) + + remote_uri = self.match_remote_uri(path_info, domain_info, environ) if not remote_uri: exc = httpexceptions.HTTPNotFound( "No URL is mapped to %r (somewhat oddly); only %s prefixes " @@ -139,6 +106,7 @@ % (path_info, ', '.join([repr(r['path']) for r in remote_uris]))) return exc(environ, start_response) + should_theme_uri = True if self.should_theme_uri: should_theme_uri = self.should_theme_uri( @@ -146,12 +114,15 @@ app = proxyapp.ForcedProxy( remote=remote_uri, force_host=True) + if self.rewrite_links: app = relocateresponse.RelocateMiddleware( app, old_href=remote_uri) + rule_uri = construct_url( environ, with_query_string=False, path_info='/_rules/rule.xml') + if should_theme_uri: app = DeliveranceMiddleware( app, @@ -160,14 +131,25 @@ renderer=Renderer) return app(environ, start_response) - def find_file(self, path): - if os.path.isdir(path): - path = os.path.join(path, 'index.html') - if os.path.exists(path): - return path + def find_static_file(self, domain_info, path_info): + """ + If the request matches a static file, returns a WSGI + application to handle that file. Else returns None. + """ + static_path = os.path.join(domain_info.static_dir, + path_info.lstrip('/')) + if os.path.isdir(static_path): + static_path = os.path.join( + static_path, 'index.html') + if os.path.exists(static_path): + return FileApp(static_path) return None def clean_environ_headers(self, environ): + """ + Remove any request headers that overlap with internal request + headers (as configured with ``clean_environ_headers_regex``). + """ if not self.clean_environ_headers_regex: return for key in environ.keys(): @@ -176,6 +158,12 @@ del environ[key] def get_domain_info(self, environ): + """ + Get the DomainInfo object associated with the request. + + May raise a redirect if the requested host is not the + canonical host. + """ domain = environ['HTTP_HOST'] if ':' in domain: domain = domain.split(':', 1)[0] @@ -200,3 +188,75 @@ raise exc return domain_info + + def check_redirects(self, path_info, domain_info, environ): + """ + Checks if the request matches any configured redirection. If + so, return a WSGI application that does the redirect; else + return None. + """ + current_uri = construct_url(environ) + for redirect_info in domain_info.redirects: + if 'path' in redirect_info: + if redirect_info['path'] == path_info: + new = redirect_info['rewrite'] + new = urlparse.urljoin(current_uri, redirect_info['rewrite']) + exc = httpexceptions.HTTPMovedPermanently( + headers=[('Location', new)]) + return exc + elif 'prefix' in redirect_info: + assert redirect_info['prefix'].endswith('/') + new_uri = None + if path_info == redirect_info['prefix'][:-1]: + new_uri = redirect_info['rewrite'] + '/' + elif path_info.startswith(redirect_info['prefix']): + new_uri = redirect_info['rewrite'] + if not new_uri.endswith('/'): + new_uri += '/' + new_uri += path_info[len(redirect_info['prefix']):] + if new_uri is not None: + new_uri = urlparse.urljoin(current_uri, new_uri) + exc = httpexceptions.HTTPMovedPermanently( + headers=[('Location', new_uri)]) + return exc + return None + + def set_additional_headers(self, domain_info, environ): + """ + Set any additional headers that the domain has been configured + to send. + """ + for header_name, header_value in domain_info.additional_request_headers: + header_name = 'HTTP_%s' % header_name.upper().replace('-', '_') + environ[header_name] = header_value + + def match_remote_uri(self, path_info, domain_info, environ): + """ + Look at the ``domain_info.remote_uris`` and what remote_uri + this request matches, returning that remote_uri (or None if + nothing is found). + + Also calls ``find_remote_uri`` if configured. + """ + remote_uri = None + + for remote_uri_info in domain_info.remote_uris: + path = str(remote_uri_info['path']) + if not path.endswith('/'): + path += '/' + if path_info + '/' == path: + exc = httpexceptions.HTTPMovedPermanently( + headers=[('location', construct_url(environ, path_info=path_info+'/'))]) + raise exc + if path_info.startswith(path): + # Found a match + remote_uri = remote_uri_info.get('remote_uri') + environ['SCRIPT_NAME'] += path[:-1] + environ['PATH_INFO'] = path_info[len(path)-1:] + if self.find_remote_uri: + remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) + return remote_uri + if self.find_remote_uri: + # Last change for find_remote_uri to do something + remote_uri = self.find_remote_uri(remote_uri, None, environ, self.app_conf) + return remote_uri From ianb at codespeak.net Fri Apr 6 05:45:30 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 05:45:30 +0200 (CEST) Subject: [z3-checkins] r41932 - in z3/deliverance/DeliveranceVHoster/trunk: dvhoster tests Message-ID: <20070406034530.CAF4A10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 05:45:30 2007 New Revision: 41932 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Log: Added test for remote_uris header setting (plus implementation) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 05:45:30 2007 @@ -255,6 +255,12 @@ environ['PATH_INFO'] = path_info[len(path)-1:] if self.find_remote_uri: remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) + if remote_uri_info.get('headers'): + for header_name, header_value in remote_uri_info['headers'].items(): + header_name = header_name.upper().replace('-', '_') + if not header_name.startswith('HTTP_'): + header_name = 'HTTP_' + header_name + environ[str(header_name)] = str(header_value) return remote_uri if self.find_remote_uri: # Last change for find_remote_uri to do something Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Fri Apr 6 05:45:30 2007 @@ -255,6 +255,7 @@ required_keys = () optional_keys = () trail_slash_keys = () + validate_keys = {} sort_key = None def validate_python(self, value, state=None): @@ -266,14 +267,12 @@ keys = d.keys() for key in self.required_keys: assert key in d, "Must have key %r in %r" % d - assert isinstance(d[key], basestring), ( - '%s must be string (not %r)' % (key, d[key])) + self.validate_key(key, d[key], state) keys.remove(key) for key in self.optional_keys: if key not in d: continue - assert isinstance(d[key], basestring), ( - '%s must be string (not %r)' % (key, d[key])) + self.validate_key(key, d[key], state) keys.remove(key) assert not keys, ( "Key(s) not allowed: %s in %r" @@ -281,6 +280,14 @@ except AssertionError, e: raise validators.Invalid(str(e), value, state) + def validate_key(self, key, value, state): + if key in self.validate_keys: + if self.validate_keys[key]: + self.validate_keys[key].validate_python(value, state) + else: + assert isinstance(value, basestring), ( + '%s must be string (not %r)' % (key, value)) + def _to_python(self, value, state=None): for d in value: for key in self.trail_slash_keys: @@ -296,6 +303,8 @@ required_keys = ('path', ) optional_keys = ('comment', 'headers', 'remote_uri') trail_slash_keys = ('path', 'remote_uri') + validate_keys = dict( + headers=None) def sort_key(self, item): return -len(item['path']) Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Fri Apr 6 05:45:30 2007 @@ -68,13 +68,13 @@ data = ''' [{"path": "/bar", "remote_uri": "http://wsgify.org/blah", "comment": "x"}, - {"path": "/", "remote_uri": "http://wsgify.org/"} + {"path": "/", "remote_uri": "http://wsgify.org/"}, + {"path": "/testme", "headers": {"X-Test-Me": "testme"}, "remote_uri": "http://wsgify.org:9999"} ] ''' - #{"path": "/testme", "headers": {"X-Test-Me": "testme"} put('/.deliverance/remote_uris', data) - # It gets normalized, so it doesn't actually stay the same: + # It gets normalized, so it doesn't actually stay quite the same: #assert app.get('/.deliverance/remote_uris').body == data res = app.get('/bar', status=301) @@ -87,6 +87,9 @@ ## So instead we just get a page we know works: res = app.get('/bar/index.html', status=200) + res = app.get('/testme/', status=200) + res.mustcontain("HTTP_X_TEST_ME: 'testme'") + data = ''' [{"path": "/test1.html", "rewrite": "/test1"}, {"prefix": "/test2", "rewrite": "/test3", "comment": "rename"}, @@ -147,10 +150,12 @@ def setup_module(module): + from paste.script import testapp static_app = StaticURLParser(os.path.join(os.path.dirname(__file__), 'test-static')) wsgi_intercept.add_wsgi_intercept('wsgify.org', 80, lambda : static_app) + wsgi_intercept.add_wsgi_intercept('wsgify.org', 9999, lambda : testapp.TestApplication(text=True)) def teardown_module(module): wsgi_intercept.remove_wsgi_intercept('wsgify.org', 80) From ianb at codespeak.net Fri Apr 6 05:51:02 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 05:51:02 +0200 (CEST) Subject: [z3-checkins] r41933 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070406035102.3094A10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 05:51:01 2007 New Revision: 41933 Added: z3/deliverance/DeliveranceVHoster/trunk/docs/index.txt (contents, props changed) Log: index of docs Added: z3/deliverance/DeliveranceVHoster/trunk/docs/index.txt ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/index.txt Fri Apr 6 05:51:01 2007 @@ -0,0 +1,19 @@ +DeliveranceVHoster +================== + +Introduction +------------ + +This is a product to do a virtual-hosting frontend with `Deliverance +`_ theming, and multiple +configurable backends (e.g., a Zope HTTP server, a WSGI HTTP server, +an Apache/PHP HTTP server). + +It is configurable through a REST API. + +Documentation +------------- + +* `REST API and Configuration `_ +* `Hooks for programmatic domain setup `_ +* `Configuration of the server `_ From ianb at codespeak.net Fri Apr 6 07:51:22 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 07:51:22 +0200 (CEST) Subject: [z3-checkins] r41934 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070406055122.0657810077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 07:51:21 2007 New Revision: 41934 Added: z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt (contents, props changed) z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (contents, props changed) Log: Added some docs Added: z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt Fri Apr 6 07:51:21 2007 @@ -0,0 +1,78 @@ +Hooks +===== + +There are three hooks that you can configure (in the ``.ini`` file) to +programmatically handle parts of DeliveranceVHoster's handling of +requests. + +Each is configured by pointing to a Python file (ending in ``.py``), +giving a module name, or pointing directly to an object. If you point +to a Python file or module then the system will look for an object +(usually a function) with the name of the setting (e.g., +``init_domain``). You can point all the settings to the same file or +module, and have different functions in that file. + +All the hook functions get access to the configuration (referred to as +``app_conf``), a dictionary of all the settings in the +DeliveranceVHoster section of the ``.ini`` file. You can put +arbitrary settings in that file, to pass them through to the hooks. + +``init_domain`` +--------------- + +When a new virtual host is visited, a ``dvhoster.model.DomainInfo`` +object is created for that virtual host. After it is created, this +function is called, and can setup any initial settings. To see what +attributes are available see the ``dvhoster.model`` file; generally +they are attributes with the same names as used in the `REST API +`_. + +The function should look like:: + + def init_domain(domain_info, app_conf): + domain_info.remote_uris = [] + +Or potentially something more useful. + +``find_remote_uri`` +------------------- + +This function is called after the ``remote_uris`` have been searched +and a match found (or potentially no match found). It returns the +remote_uri that should be used. It should look like:: + + def find_remote_uri(remote_uri, remote_uri_info, environ, + app_conf): + if remote_uri is not None: + # It was set explicitly in the remote_uris setting + return remote_uri + if remote_uri_info is None: + # There was no match found at all; fail: + return None + # You can make changes to environ if you want, or read it + # for more information. + # This would actually be a little silly, though: + return remote_uri_info['comment'] + +``should_theme_uri`` +-------------------- + +This function is called and should return True (the request should be +themed) or False (the request should be left alone). It should look +like:: + + def should_theme_uri(remote_uri, environ, app_conf): + if 'python' in environ.get('HTTP_USER_AGENT'): + # probably a request with urllib or something + return False + return True + +Exceptions +---------- + +In any of these methods you may raise exceptions from +`paste.httpexceptions +`_. Perhaps, +for instance, a redirection is in order (``HTTPMovedPermanently``). +Or an unauthorized request (``HTTPForbidden``). + Added: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Fri Apr 6 07:51:21 2007 @@ -0,0 +1,113 @@ +REST API +======== + +DeliveranceVHoster configuration is done through a REST API. This API +is made up of a series of `resources +`_ that can be read +with GET and set with PUT. + +The API is available at ``/.deliverance/`` under the domain. Each +domain presents the configuration for that domain. So when you access +``http://foo.com/.deliverance/aliases`` you are accessing the +``aliases`` parameter for ``foo.com``. There's no global +configuration presented though this API, only domain-specific +configuration. + +Resources +--------- + +Each of these resources can be read with GET and set with PUT. + +``/.deliverance/static/*`` + + Static files. You can use PUT to update or save files, and DELETE + to remove them. Use MKCOL to create directories. When a file is + put here it becomes a global override. So if you PUT a file at + ``/.deliverance/static/styles/style.css``, then a request to + ``/styles/style.css`` will return that file. Any other request to + ``/styles/*`` will be handled normally. ``index.html`` can be used + to override directory indexes. + + You can GET directories here, which will give you directory listings + in simple HTML. PROPLIST (from WebDAV) is not supported. + +``/.deliverance/rules/rules.xml`` + + The rules file. This is an XML document. A file + ``/.deliverance/rules/standardrules.xml`` is always set, which are + standard rules applicable to HTML. You can include these rules with + XInclude. + + Similar to ``/.deliverance/static`` you can create directories here + and add arbitrary files. The files appear in ``/_rules`` (e.g., + ``/_rules/rules.xml``). + +``/.deliverance/domain`` + + The main domain, like ``foo.com`` in the example. A simple string. + You can PUT a new value here to rename the entire site. If you + rename a site, the original name automatically becomes an alias. + + You can GET this value to see if you are accessing the canonical + domain or an alias; for ``/.deliverance`` requests the redirection + does not occur. + +``/.deliverance/aliases`` + + This is a list of domains that are aliases for this domain. The + list text, one domain per line. Any request to one of these aliases + will be redirected to the canonical/main domain. + +``/.deliverance/theme_uri`` + + The URI of the theme. This is a simple string, with no encoding. + +``/.deliverance/remote_uris`` + + A JSON structure, looking like:: + + [{"path": "", "remote_uri": "http://localhost:8080"}, + {"path": "/tasks", "remote_uri": "http://localhost:9090"}] + + This means that requests to ``/tasks/*`` will be forwarded to the + server at ``http://localhost:9090``, while all other requests + (anything under the null path ``""``) will be forwarded to + ``http://localhost:8080``. Requests ``/tasks`` will be redirected + to ``/tasks/``. + + Each setting can also have a key ``headers``, which is a dictionary + of headers to set on the request. These are header the application + being forwarded to can consume. Additionally a ``comment`` key can + hold any value. + + ``remote_uri`` is optional. Using `hooks `_ you can set + a remote URI programmatically without setting it in domain-specific + configuration. + + This resource must be set for a new virtual host to be usable. You + can do this with a `hook `_, or otherwise all requests + (except to this configuration API) will fail. + +``/.deliverance/addition_request_headers`` + + A JSON structure looking like:: + + [["X-Foo", "Bar"], + ["X-Foo-2", "Bar 2"]] + + Each item is a header (name and value) that will be set on all + requests to this domain. + +``/.deliverance/redirects`` + + A JSON structure, looking like:: + + [{"path": "/foo.html", "rewrite": "/foo/", + "comment": "from old site"}, + {"prefix": "/blog/index.cgi/", "rewrite": "/blog/"}] + + Each item represents a redirection, typically set to support an old + set of URLs after a transition. Each item must contain either + ``path`` (a fixed path to redirect) or ``prefix`` (a directory to + redirect). It is redirected to the value of ``rewrite``. You may + optionally include a comment. From ianb at codespeak.net Fri Apr 6 17:03:30 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 17:03:30 +0200 (CEST) Subject: [z3-checkins] r41938 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070406150330.2897510077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 17:03:29 2007 New Revision: 41938 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Set remote_uris headers before calling find_remote_uri Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 17:03:29 2007 @@ -253,14 +253,14 @@ remote_uri = remote_uri_info.get('remote_uri') environ['SCRIPT_NAME'] += path[:-1] environ['PATH_INFO'] = path_info[len(path)-1:] - if self.find_remote_uri: - remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) if remote_uri_info.get('headers'): for header_name, header_value in remote_uri_info['headers'].items(): header_name = header_name.upper().replace('-', '_') if not header_name.startswith('HTTP_'): header_name = 'HTTP_' + header_name environ[str(header_name)] = str(header_value) + if self.find_remote_uri: + remote_uri = self.find_remote_uri(remote_uri, remote_uri_info, environ, self.app_conf) return remote_uri if self.find_remote_uri: # Last change for find_remote_uri to do something From ianb at codespeak.net Fri Apr 6 17:19:47 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 17:19:47 +0200 (CEST) Subject: [z3-checkins] r41939 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070406151947.2953C10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 17:19:46 2007 New Revision: 41939 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Move rewrite_links into the should_theme_uri conditional block, just like theming Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 17:19:46 2007 @@ -115,15 +115,15 @@ remote=remote_uri, force_host=True) - if self.rewrite_links: - app = relocateresponse.RelocateMiddleware( - app, old_href=remote_uri) - - rule_uri = construct_url( - environ, with_query_string=False, - path_info='/_rules/rule.xml') - if should_theme_uri: + if self.rewrite_links: + app = relocateresponse.RelocateMiddleware( + app, old_href=remote_uri) + + rule_uri = construct_url( + environ, with_query_string=False, + path_info='/_rules/rule.xml') + app = DeliveranceMiddleware( app, theme_uri=domain_info.theme_uri, From ianb at codespeak.net Fri Apr 6 17:20:26 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 17:20:26 +0200 (CEST) Subject: [z3-checkins] r41940 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070406152026.2A9C610077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 17:20:25 2007 New Revision: 41940 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt Log: note last commit in docs Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/hooks.txt Fri Apr 6 17:20:25 2007 @@ -67,6 +67,9 @@ return False return True +If you return false it will also shortcut the link-rewriting phase +(which can also be problematic). + Exceptions ---------- From ianb at codespeak.net Fri Apr 6 17:33:52 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 17:33:52 +0200 (CEST) Subject: [z3-checkins] r41941 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070406153352.C27EB10077@code0.codespeak.net> Author: ianb Date: Fri Apr 6 17:33:52 2007 New Revision: 41941 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Save remote_uri in the environment; use that in the error formatter, instead of redoing the remote_uri matching (which is more complex now) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py Fri Apr 6 17:33:52 2007 @@ -16,23 +16,12 @@ error_container.attrib['style'] = self.error_style if not current_environ.get('dvhoster.has_errors'): current_environ['dvhoster.has_errors'] = True - domain_info = current_environ['dvhoster.domain_info'] - remote_uris = domain_info.remote_uris - path_info = current_environ['PATH_INFO'] - for remote_info in remote_uris: - if (path_info.startswith(remote_info['path']) - or not path_info and remote_info['path'] == '/'): - remote = remote_info['remote_uri'] - break - else: - assert 0, ( - "Nothing in remote_uris (%r) matches PATH_INFO=%r" - % (remote_uris, path_info)) - remote += current_environ.get('PATH_INFO', '') + remote_uri = current_environ['dvhoster.remote_uri'] + remote_uri += current_environ.get('PATH_INFO', '') if current_environ.get('QUERY_STRING'): - remote += '?' + current_environ['QUERY_STRING'] + remote_uri += '?' + current_environ['QUERY_STRING'] link = etree.Element('a') - link.attrib['href'] = remote + link.attrib['href'] = remote_uri link.attrib['target'] = '_blank' link.text = 'View original content source' container = etree.Element('div') Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 17:33:52 2007 @@ -107,6 +107,8 @@ for r in remote_uris]))) return exc(environ, start_response) + environ['dvhoster.remote_uri'] = remote_uri + should_theme_uri = True if self.should_theme_uri: should_theme_uri = self.should_theme_uri( From ianb at codespeak.net Fri Apr 6 18:27:05 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 18:27:05 +0200 (CEST) Subject: [z3-checkins] r41942 - in z3/deliverance/DeliveranceVHoster/trunk: . dvhoster tests Message-ID: <20070406162705.A70D610078@code0.codespeak.net> Author: ianb Date: Fri Apr 6 18:27:04 2007 New Revision: 41942 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py z3/deliverance/DeliveranceVHoster/trunk/setup.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Log: Fixed the error message generator, which had problems when recursive errors occurred. Requires update from Paste Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py Fri Apr 6 18:27:04 2007 @@ -14,12 +14,26 @@ error_container = etree.Element('div') error_container.attrib['style'] = self.error_style - if not current_environ.get('dvhoster.has_errors'): - current_environ['dvhoster.has_errors'] = True - remote_uri = current_environ['dvhoster.remote_uri'] - remote_uri += current_environ.get('PATH_INFO', '') - if current_environ.get('QUERY_STRING'): - remote_uri += '?' + current_environ['QUERY_STRING'] + environ = None + for match_environ in current_environ._object_stack(): + if 'dvhoster.remote_uri' in match_environ: + # This was the original request that we are interested in + environ = match_environ + break + else: + warnings.warn( + "No environment with dvhoster.remote_uri can be found, " + "which is unexpected") + # But lets not actually keep the error message from working + assert 0 + return error + environ = current_environ._current_obj() + if not environ.get('dvhoster.has_errors'): + environ['dvhoster.has_errors'] = True + remote_uri = environ.get('dvhoster.remote_uri', '') + remote_uri += environ.get('PATH_INFO', '') + if environ.get('QUERY_STRING'): + remote_uri += '?' + environ['QUERY_STRING'] link = etree.Element('a') link.attrib['href'] = remote_uri link.attrib['target'] = '_blank' Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Fri Apr 6 18:27:04 2007 @@ -8,7 +8,7 @@ #author_email="", #url="", install_requires=[ - 'Paste>1.1.1', + 'Paste==dev,>=1.3.1dev-r6419', 'PasteScript', 'Deliverance', 'WSGIFilter', Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Fri Apr 6 18:27:04 2007 @@ -65,6 +65,13 @@ res = app.get('/', extra_environ={'HTTP_X_NO_THEME': '1', 'HTTP_HOST': 'foo3.openplans.org'}) assert 'Plone' not in res +def test_error_message(): + # This will give us some content that can't be themed, testing the + # error messages: + setup_module(None, text=False) + res = app.get('/', extra_environ={'HTTP_HOST': 'foo4.openplans.org'}) + res.mustcontain('View original content source') + def setup_module(module, text=True): from paste.script import testapp app = testapp.TestApplication(text=text) From ianb at codespeak.net Fri Apr 6 19:37:59 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 19:37:59 +0200 (CEST) Subject: [z3-checkins] r41943 - in z3/deliverance/DeliveranceVHoster/trunk: docs dvhoster tests Message-ID: <20070406173759.C21451006F@code0.codespeak.net> Author: ianb Date: Fri Apr 6 19:37:59 2007 New Revision: 41943 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Log: Added POST methods for remote_uris setting Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Fri Apr 6 19:37:59 2007 @@ -88,6 +88,12 @@ can do this with a `hook `_, or otherwise all requests (except to this configuration API) will fail. +``/.deliverance/remote_uris?{add or remove}`` + + You can post to one of these resources to add or remove items from + the list, without effecting other parts of the list. Each takes a + JSON list. With ``?add`` the list extends the current items. + ``/.deliverance/addition_request_headers`` A JSON structure looking like:: Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Fri Apr 6 19:37:59 2007 @@ -4,7 +4,7 @@ from ohm import server from ohm import descriptors from ohm import lildav -from ohm.validators import LineConverter +from ohm.validators import LineConverter, JSONConverter from formencode import validators from formencode.foreach import ForEach from formencode.compound import All @@ -338,6 +338,34 @@ DomainInfo object. """ + def add_remote_uris(self, body): + validator = RemoteURIValidator() + body = validator.to_python(body) + self.remote_uris = validator.to_python(self.remote_uris + body) + + def remove_remote_uris(self, body): + cur = self.remote_uris + for item in body: + path = item['path'] + # Normalization that normally RemoteURIValidator does: + if not path.endswith('/'): + item['path'] = path = path + '/' + for existing in cur: + if existing['path'] == path: + # Found a match + break + else: + raise ValueError( + "There's no current remote_uri matching %r " + "(of paths: %s)" % + (path, ', '.join([repr(e['path']) for e in cur]))) + for item in body: + path = item['path'] + for existing in cur[:]: + if existing['path'] == path: + cur.remove(existing) + self.remote_uris = cur + theme_uri = server.Setter( validator=validators.URL()) domain = server.Setter( @@ -345,7 +373,9 @@ aliases = server.Setter( validator=All(ForEach(DomainValidator()), LineConverter())) remote_uris = server.JSONSetter( - validator=RemoteURIValidator()) + validator=RemoteURIValidator(), + POST={'add': (JSONConverter(), add_remote_uris), + 'remove': (JSONConverter(), remove_remote_uris)}) redirects = server.JSONSetter( validator=RewriteValidator()) additional_request_headers = server.JSONSetter( Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Fri Apr 6 19:37:59 2007 @@ -9,6 +9,7 @@ setattr(httplib.HTTPConnection, attr, getattr(wsgi_intercept.WSGI_HTTPConnection, attr).im_func) from wsgifilter.proxyapp import DebugHeaders +from simplejson import loads as json_loads data_filename = os.path.join(os.path.dirname(__file__), 'test-data') wsgi_app = make_app({}, data_dir=data_filename) @@ -90,6 +91,20 @@ res = app.get('/testme/', status=200) res.mustcontain("HTTP_X_TEST_ME: 'testme'") + # Now lets try adding and removing via POST + app.post('/.deliverance/remote_uris?add', + '[{"path": "/testpost", "remote_uri": "http://blah.com"}]', + status=204) + res = app.get('/.deliverance/remote_uris') + res.mustcontain('testpost') + app.post('/.deliverance/remote_uris?remove', + '[{"path": "/testpost"}]', + status=204) + res = app.get('/.deliverance/remote_uris') + data = json_loads(res.body) + for item in data: + assert not item['path'].startswith('/testpost') + data = ''' [{"path": "/test1.html", "rewrite": "/test1"}, {"prefix": "/test2", "rewrite": "/test3", "comment": "rename"}, From ianb at codespeak.net Fri Apr 6 20:03:48 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 20:03:48 +0200 (CEST) Subject: [z3-checkins] r41944 - in z3/deliverance/DeliveranceVHoster/trunk: docs dvhoster tests Message-ID: <20070406180348.3571810050@code0.codespeak.net> Author: ianb Date: Fri Apr 6 20:03:47 2007 New Revision: 41944 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Log: Added POST API for redirects Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Fri Apr 6 20:03:47 2007 @@ -117,3 +117,8 @@ ``path`` (a fixed path to redirect) or ``prefix`` (a directory to redirect). It is redirected to the value of ``rewrite``. You may optionally include a comment. + +``/.deliverance/redirects?{add or remove}`` + + Like ``remote_uris`` you can POST to these locations to add and + remove redirects, without reseting all redirects. Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/model.py Fri Apr 6 20:03:47 2007 @@ -6,6 +6,7 @@ from ohm import lildav from ohm.validators import LineConverter, JSONConverter from formencode import validators +from formencode.api import Invalid from formencode.foreach import ForEach from formencode.compound import All @@ -355,10 +356,11 @@ # Found a match break else: - raise ValueError( + raise Invalid( "There's no current remote_uri matching %r " "(of paths: %s)" % - (path, ', '.join([repr(e['path']) for e in cur]))) + (path, ', '.join([repr(e['path']) for e in cur])), + body, None) for item in body: path = item['path'] for existing in cur[:]: @@ -366,6 +368,49 @@ cur.remove(existing) self.remote_uris = cur + def add_redirects(self, body): + validator = RewriteValidator() + body = validator.to_python(body) + self.redirects = validator.to_python(self.redirects + body) + + def remove_redirects(self, body): + cur = self.redirects + for item in body: + if item.get('path'): + path = item['path'] + for existing in cur: + if existing.get('path') == path: + break + else: + raise Invalid( + "There's no current redirect matching path=%r" + % path, body, None) + else: + prefix = item['prefix'] + if not prefix.endswith('/'): + item['prefix'] = prefix = prefix + '/' + for existing in cur: + if existing.get('prefix') == prefix: + break + else: + raise Invalid( + "There's no current redirect matching prefix=%r" + % prefix, body, None) + for item in body: + if item.get('path'): + path = item['path'] + for existing in cur[:]: + if existing.get('path') == path: + cur.remove(existing) + break + else: + prefix = item['prefix'] + for existing in cur[:]: + if existing.get('prefix') == prefix: + cur.remove(existing) + break + self.redirects = cur + theme_uri = server.Setter( validator=validators.URL()) domain = server.Setter( @@ -377,7 +422,9 @@ POST={'add': (JSONConverter(), add_remote_uris), 'remove': (JSONConverter(), remove_remote_uris)}) redirects = server.JSONSetter( - validator=RewriteValidator()) + validator=RewriteValidator(), + POST={'add': (JSONConverter(), add_redirects), + 'remove': (JSONConverter(), remove_redirects)}) additional_request_headers = server.JSONSetter( validator=HeaderValidator()) Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_functional_api.py Fri Apr 6 20:03:47 2007 @@ -111,6 +111,26 @@ {"path": "/other.html", "rewrite": "http://otherexample.com/other.html"}] ''' put('/.deliverance/redirects', data) + + app.post('/.deliverance/redirects?add', + '[{"path": "/something-special", "rewrite": "http://whatever.com"}]', + status=204) + res = app.get('/.deliverance/redirects') + res.mustcontain('whatever.com', 'otherexample.com') + # Let's try a bad request: + app.post('/.deliverance/redirects?remove', + '[{"path": "/blahblah"}]', status=400) + # Then a good one: + app.post('/.deliverance/redirects?remove', + '[{"path": "/something-special"}]', + status=204) + res = app.get('/.deliverance/redirects') + res.mustcontain('otherexample.com') + data = json_loads(res.body) + for item in data: + if not item.get('path'): + continue + assert not item.get('path').startswith('/something-special') data = 'some data!' put('/.deliverance/static/data.html', data) From ianb at codespeak.net Fri Apr 6 21:22:09 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 21:22:09 +0200 (CEST) Subject: [z3-checkins] r41945 - in z3/deliverance/DeliveranceVHoster/trunk: . dvhoster Message-ID: <20070406192209.307A310053@code0.codespeak.net> Author: ianb Date: Fri Apr 6 21:22:07 2007 New Revision: 41945 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/cli.py z3/deliverance/DeliveranceVHoster/trunk/setup.py Log: make cli a proper script: Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/cli.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/cli.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/cli.py Fri Apr 6 21:22:07 2007 @@ -125,13 +125,18 @@ else: print "[X] unknown command" +cli_usage = """\ +usage: %prog domain [options] + +Gives you an interactive console to run commands against the server""" + def main(argv=None): if argv is None: argv = sys.argv - usage = "usage: %prog domain [options]" - parser = optparse.OptionParser(usage=usage) - parser.add_option('-F','--force-host', + parser = optparse.OptionParser(usage=cli_usage) + parser.add_option('-F','--force-host', + metavar="HOST", help="specify the administration server to contact", dest='force_host', default=None) Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Fri Apr 6 21:22:07 2007 @@ -26,7 +26,12 @@ entry_points=""" [paste.app_factory] main=dvhoster:make_app + [paste.app_install] main=paste.script.appinstall:Installer + + [console_scripts] + dvhoster-api = dvhoster.cli:main + """, ) From ianb at codespeak.net Fri Apr 6 22:16:37 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 6 Apr 2007 22:16:37 +0200 (CEST) Subject: [z3-checkins] r41946 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070406201637.901FB10060@code0.codespeak.net> Author: ianb Date: Fri Apr 6 22:16:33 2007 New Revision: 41946 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Make rewrite_links false by default Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 6 22:16:33 2007 @@ -49,7 +49,7 @@ self.should_theme_uri = should_theme_uri self.app_conf = app_conf self.provider = DomainInfoSet(data_dir) - self.rewrite_links = asbool(app_conf.get('rewrite_links', True)) + self.rewrite_links = asbool(app_conf.get('rewrite_links', False)) if app_conf.get('clean_environ_headers_regex'): self.clean_environ_headers_regex = re.compile(app_conf['clean_environ_headers_regex']) else: From ltucker at codespeak.net Fri Apr 6 23:16:12 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 6 Apr 2007 23:16:12 +0200 (CEST) Subject: [z3-checkins] r41947 - z3/deliverance/trunk/deliverance Message-ID: <20070406211612.3244110053@code0.codespeak.net> Author: ltucker Date: Fri Apr 6 23:16:11 2007 New Revision: 41947 Modified: z3/deliverance/trunk/deliverance/resource_fetcher.py z3/deliverance/trunk/deliverance/wsgimiddleware.py Log: oops. I lied, use whole inbound environment in all fetches by default for now Modified: z3/deliverance/trunk/deliverance/resource_fetcher.py ============================================================================== --- z3/deliverance/trunk/deliverance/resource_fetcher.py (original) +++ z3/deliverance/trunk/deliverance/resource_fetcher.py Fri Apr 6 23:16:11 2007 @@ -127,13 +127,13 @@ return body class ExternalResourceFetcher(object): - def __init__(self, uri, headers_only=False): + def __init__(self, in_environ, uri, headers_only=False): self.uri = uri url_chunks = urlparse.urlsplit(uri) loc = urlparse.urlsplit(uri) - self.environ = {} + self.environ = in_environ.copy() if headers_only: self.environ['REQUEST_METHOD'] = 'HEAD' Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py ============================================================================== --- z3/deliverance/trunk/deliverance/wsgimiddleware.py (original) +++ z3/deliverance/trunk/deliverance/wsgimiddleware.py Fri Apr 6 23:16:11 2007 @@ -368,7 +368,7 @@ return InternalResourceFetcher(environ, uri[len(internalBaseURL):], self.app) else: - return ExternalResourceFetcher(uri) + return ExternalResourceFetcher(environ, uri) def get_resource_uris(self, rules): From ianb at codespeak.net Sat Apr 7 00:08:14 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Sat, 7 Apr 2007 00:08:14 +0200 (CEST) Subject: [z3-checkins] r41948 - in z3/deliverance/DeliveranceVHoster/trunk: dvhoster tests Message-ID: <20070406220814.758E910053@code0.codespeak.net> Author: ianb Date: Sat Apr 7 00:08:13 2007 New Revision: 41948 Added: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py (contents, props changed) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Log: Added logging of error messages Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/debuginterp.py Sat Apr 7 00:08:13 2007 @@ -2,6 +2,7 @@ from lxml import etree from paste.request import construct_url from dvhoster import current_environ +import re class Renderer(PyRenderer): @@ -11,7 +12,6 @@ error = super(PyRenderer, self).format_error(message, rule, elts) if error is None: return None - error_container = etree.Element('div') error_container.attrib['style'] = self.error_style environ = None @@ -25,15 +25,14 @@ "No environment with dvhoster.remote_uri can be found, " "which is unexpected") # But lets not actually keep the error message from working - assert 0 return error - environ = current_environ._current_obj() - if not environ.get('dvhoster.has_errors'): - environ['dvhoster.has_errors'] = True - remote_uri = environ.get('dvhoster.remote_uri', '') - remote_uri += environ.get('PATH_INFO', '') - if environ.get('QUERY_STRING'): - remote_uri += '?' + environ['QUERY_STRING'] + top_environ = current_environ._current_obj() + remote_uri = environ.get('dvhoster.remote_uri', '') + remote_uri += environ.get('PATH_INFO', '') + if environ.get('QUERY_STRING'): + remote_uri += '?' + environ['QUERY_STRING'] + if not top_environ.get('dvhoster.has_errors'): + top_environ['dvhoster.has_errors'] = True link = etree.Element('a') link.attrib['href'] = remote_uri link.attrib['target'] = '_blank' @@ -41,8 +40,36 @@ container = etree.Element('div') container.append(link) error_container.append(container) + self.log_error(environ, error, remote_uri) error_container.append(error) return error_container - - + def log_error(self, environ, error, remote_uri): + logger = environ['dvhoster.logger'] + cur_url = environ['dvhoster.original_url'] + error = el_as_string(error) + error = '\n'.join([' '+l for l in error.splitlines()]) + logger.warn('Error in matching rule in URL %s content at %s:\n%s' + % (cur_url, remote_uri, error)) + +_space_re = re.compile(r'[ ][ ]+') + +def el_as_string(el): + s = [] + _el_to_string(el, s) + s = ''.join(s) + s = s.replace('\t', ' ') + s = _space_re.sub(' ', s) + return s.strip() + +def _el_to_string(el, s): + if el.text: + s.append(el.text) + if el.tag == 'br': + s.append('\n') + for sub_el in el.getchildren(): + _el_to_string(sub_el, s) + if sub_el.tail: + s.append(sub_el.tail) + if el.tag == 'a' and el.attrib.get('href'): + s.append(' (%s) ' % el.attrib['href']) Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Sat Apr 7 00:08:13 2007 @@ -14,6 +14,7 @@ from dvhoster import current_environ from dvhoster.debuginterp import Renderer from dvhoster.util import load_func +from dvhoster.logcreate import make_logger def norm_path(urlpath): if not urlpath: @@ -54,6 +55,8 @@ self.clean_environ_headers_regex = re.compile(app_conf['clean_environ_headers_regex']) else: self.clean_environ_headers_regex = None + logger = make_logger(app_conf.get('logger'), 'dvhoster') + self.logger = logger def __call__(self, environ, start_response): """ @@ -67,6 +70,8 @@ environ['dvhoster.base_url'] = construct_url( environ, with_query_string=False, path_info='') + environ['dvhoster.original_url'] = construct_url(environ) + environ['dvhoster.logger'] = self.logger environ['PATH_INFO'] = path_info = norm_path(environ.get('PATH_INFO', '')) if path_info.startswith('/.deliverance'): path_info_pop(environ) Added: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py Sat Apr 7 00:08:13 2007 @@ -0,0 +1,28 @@ +import logging + +def make_logger(name, default_name): + if name is None: + name = default_name + setup_console = False + setup_file = None + if name == '-' or name.endswith('+stdout'): + if name.endswith('+stdout'): + name = name[:-len('+stdout')].strip() + else: + name = default_name + setup_console = True + if name.startswith('/'): + setup_file = name + name = default_name + logger = logging.getLogger(name) + if setup_console: + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + logger.addHandler(console) + logger.propagate = False + if setup_file: + file_log = logging.RotatingFileHandler(setup_file) + file_log.setLevel(logging.DEBUG) + logger.addHandler(file_log) + logger.propagate = False + return logger Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Sat Apr 7 00:08:13 2007 @@ -24,7 +24,8 @@ should_theme_uri=example, zope_location='http://localhost:8080', default_theme_uri='http://openplans.org', - data_dir=data_filename) + data_dir=data_filename, + logger='-') app = TestApp(wsgi_app) def test_init_domain(): From ianb at codespeak.net Sat Apr 7 00:08:57 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Sat, 7 Apr 2007 00:08:57 +0200 (CEST) Subject: [z3-checkins] r41949 - z3/deliverance/DeliveranceVHoster/trunk Message-ID: <20070406220857.AAF4A1005A@code0.codespeak.net> Author: ianb Date: Sat Apr 7 00:08:56 2007 New Revision: 41949 Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini Log: add config example for logger Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/development.ini (original) +++ z3/deliverance/DeliveranceVHoster/trunk/development.ini Sat Apr 7 00:08:56 2007 @@ -31,6 +31,11 @@ # execute malicious code after an exception is raised. set debug = true +# To set a logger: +#logger = /path/dvhoster.log +# For stdout logging: +#logger = - + [app:openplans] use = main clean_environ_headers_regex = ^HTTP_X_OPENPLANS From ianb at codespeak.net Tue Apr 10 18:03:01 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 10 Apr 2007 18:03:01 +0200 (CEST) Subject: [z3-checkins] r41987 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070410160301.408B18078@code0.codespeak.net> Author: ianb Date: Tue Apr 10 18:03:00 2007 New Revision: 41987 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Log: Added examples of using the API with httplib2 and simplejson Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Tue Apr 10 18:03:00 2007 @@ -1,6 +1,8 @@ REST API ======== +.. contents:: + DeliveranceVHoster configuration is done through a REST API. This API is made up of a series of `resources `_ that can be read @@ -122,3 +124,61 @@ Like ``remote_uris`` you can POST to these locations to add and remove redirects, without reseting all redirects. + +Python Usage +------------ + +It may not be entirely obvious how you run these requests. Here's +some examples using `httplib2 +`_ and `simplejson +`_. + +:: + + import simplejson + import httplib2 + # We have to instantiate something in httplib2 before we can + # really use it: + client = httplib2.Http() + + base_uri = 'http://foo.mysite.com' + def location(name, query_string=None): + return base_uri + '/.deliverance/' + name + + # Now we'll set the theme_uri: + resp, content = client.request( + location('theme_uri'), 'PUT', + body='http://static.mysite.com/theme.html') + # And check it worked: + resp, content = client.request( + location('theme_uri'), 'GET') + assert content == 'http://static.mysite.com/theme.html' + + # Here's an example using JSON to set remote_uris: + data = [ + dict(path='/', remote_uri='http://localhost:8080'), + dict(path='/blog', remote_uri='http://localhost:8081'), + ] + resp, content = client.request( + location('remote_uris'), 'PUT', + body=simplejson.dumps(data)) + # And here's how we'd check it: + resp, content = client.request( + location('remote_uris'), 'GET') + data = simplejson.loads(content) + # Note that some data gets normalized on the server, so if we + # compared what we sent to what we get back, they would not be + # identical + print data + + # Lastly, an example using POST to add a redirect: + data = [{'prefix': '/archive', + 'rewrite': '/blog/archive'}] + resp, content = client.request( + location('redirects?add'), 'POST', + body=simplejson.dumps(data), + headers={'content-type': 'application/json'}) + + # (technically except for theme_uri they were all application/json + # requests, so you should have set that header everywhere) + From ianb at codespeak.net Tue Apr 10 18:15:18 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 10 Apr 2007 18:15:18 +0200 (CEST) Subject: [z3-checkins] r41988 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070410161518.25F53807C@code0.codespeak.net> Author: ianb Date: Tue Apr 10 18:15:17 2007 New Revision: 41988 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Log: fix simplejson link Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Tue Apr 10 18:15:17 2007 @@ -131,7 +131,7 @@ It may not be entirely obvious how you run these requests. Here's some examples using `httplib2 `_ and `simplejson -`_. +`_. :: From ejucovy at codespeak.net Wed Apr 11 20:23:37 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Wed, 11 Apr 2007 20:23:37 +0200 (CEST) Subject: [z3-checkins] r41998 - in z3/deliverance/DeliveranceVHoster/trunk: . docs tests Message-ID: <20070411182337.EF70280A3@code0.codespeak.net> Author: ejucovy Date: Wed Apr 11 20:23:36 2007 New Revision: 41998 Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Log: * merged zope_uri and zope_location conf settings * openplans hooks and conf settings for zope/tasktracker Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/development.ini (original) +++ z3/deliverance/DeliveranceVHoster/trunk/development.ini Wed Apr 11 20:23:36 2007 @@ -12,12 +12,12 @@ [server:main] use = egg:Paste#http host = 0.0.0.0 -port = 5000 +port = 8000 [app:main] use = egg:DeliveranceVHoster data_dir = %(here)s/data -debug_headers = true +#debug_headers = true # To view bodies: #debug_bodies = true # To disable the rewriting of links: @@ -29,7 +29,7 @@ # WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* # Debug mode will enable the interactive debugging tool, allowing ANYONE to # execute malicious code after an exception is raised. -set debug = true +set debug = false # To set a logger: #logger = /path/dvhoster.log @@ -38,7 +38,17 @@ [app:openplans] use = main +### THIS IS IMPORTANT STUFF SPECIFIC TO OUR DEPLOYMENT ### + +rewrite_links = false clean_environ_headers_regex = ^HTTP_X_OPENPLANS -init_domain = %(here)s/docs/example_init_domain.py -zope_location = http://localhost:8080 -#default_theme_uri = ? +init_domain = %(here)s/docs/openplans_hooks.py +find_remote_uri = %(here)s/docs/openplans_hooks.py +should_theme_uri = %(here)s/docs/openplans_hooks.py +no_filter_zope = True +zope_uri = http://localhost:5050 +task_tracker_uri = http://localhost:5000 +default_theme_uri = http://www.openplans.org +domain_regex = ^(.*)\.flow\.openplans\.org$ + +### END THIS IMPORTANT STUFF ### Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/example_init_domain.py Wed Apr 11 20:23:36 2007 @@ -22,7 +22,7 @@ project = match.group(1) remote_uri = ( '%s/VirtualHostBase/http/%s:80/openplans/projects/%s/VirtualHostRoot' - % (app_conf['zope_location'], + % (app_conf['zope_uri'], domain, project)) domain_info.remote_uris = [ Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Wed Apr 11 20:23:36 2007 @@ -13,24 +13,32 @@ - + + + + """ def init_domain(domain_info, app_conf): r""" - Initializes an openplans project, based on a domain regular - expression (default ``^(.*)\.openplans\.org$`` but you can - override with the ``domain_regex`` config setting). + Initializes an openplans project based on a domain regular + expression which must be specified with the ``domain_regex`` + config setting. Also requires a ``default_theme_uri`` setting. """ domain = domain_info.domain - domain_regex = app_conf.get('domain_regex', r'^(.*)\.openplans\.org$') + domain_regex = app_conf['domain_regex'] match = re.search(domain_regex, domain, re.I) if not match: # Don't try to set up domains we don't recognize print 'The domain %r cannot be recognized by the domain_regex %r' % (domain, domain_regex) + zope_uri = app_conf['zope_uri'] + remote_uris = [{'path': '', + 'remote_uri': '%s/VirtualHostBase/http/%s/openplans/VirtualHostRoot/' % (zope_uri, domain)}] + domain_info.remote_uris = remote_uris return project = match.group(1) remote_uris = [ Modified: z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/tests/test_init_func.py Wed Apr 11 20:23:36 2007 @@ -22,7 +22,7 @@ init_domain=example, find_remote_uri=example, should_theme_uri=example, - zope_location='http://localhost:8080', + zope_uri='http://localhost:8080', default_theme_uri='http://openplans.org', data_dir=data_filename, logger='-') From kobold at codespeak.net Thu Apr 12 20:13:58 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Thu, 12 Apr 2007 20:13:58 +0200 (CEST) Subject: [z3-checkins] r42006 - z3/sqlos/trunk/src/sqlos Message-ID: <20070412181358.2CC5680A5@code0.codespeak.net> Author: kobold Date: Thu Apr 12 20:13:57 2007 New Revision: 42006 Modified: z3/sqlos/trunk/src/sqlos/adapter.py Log: Fixed a stupid bug. Modified: z3/sqlos/trunk/src/sqlos/adapter.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/adapter.py (original) +++ z3/sqlos/trunk/src/sqlos/adapter.py Thu Apr 12 20:13:57 2007 @@ -91,7 +91,7 @@ sep = '->' s = repr(s) name = name.ljust(8) - threadName = elf.debugThreading and \ + threadName = self.debugThreading and \ ':' + threading.currentThread().getName().ljust(8) or '' print '%(threadName)s/%(name)s%(sep)s %(s)s' % locals() From novalis at codespeak.net Thu Apr 12 20:19:18 2007 From: novalis at codespeak.net (novalis at codespeak.net) Date: Thu, 12 Apr 2007 20:19:18 +0200 (CEST) Subject: [z3-checkins] r42007 - z3/deliverance/branches/parallel/deliverance Message-ID: <20070412181918.67E5180AA@code0.codespeak.net> Author: novalis Date: Thu Apr 12 20:19:18 2007 New Revision: 42007 Modified: z3/deliverance/branches/parallel/deliverance/test_wsgi.py Log: Checkin before reporting to lxml list Modified: z3/deliverance/branches/parallel/deliverance/test_wsgi.py ============================================================================== --- z3/deliverance/branches/parallel/deliverance/test_wsgi.py (original) +++ z3/deliverance/branches/parallel/deliverance/test_wsgi.py Thu Apr 12 20:19:18 2007 @@ -45,12 +45,12 @@ a = None b = None try: - a = etree.HTML(astr) + a = etree.HTML(astr, etree.HTMLParser()) except: print a raise try: - b = etree.HTML(bstr) + b = etree.HTML(bstr, etree.HTMLParser()) except: print b raise From ejucovy at codespeak.net Fri Apr 13 01:30:58 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Fri, 13 Apr 2007 01:30:58 +0200 (CEST) Subject: [z3-checkins] r42014 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070412233058.C668980B1@code0.codespeak.net> Author: ejucovy Date: Fri Apr 13 01:30:57 2007 New Revision: 42014 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: * domain_info.domain isn't preserving port, so hacking that in for now * set HTTP_X_OPENPLANS_APPLICATION=tasktracker when going to tasktracker Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Fri Apr 13 01:30:57 2007 @@ -37,7 +37,7 @@ print 'The domain %r cannot be recognized by the domain_regex %r' % (domain, domain_regex) zope_uri = app_conf['zope_uri'] remote_uris = [{'path': '', - 'remote_uri': '%s/VirtualHostBase/http/%s/openplans/VirtualHostRoot/' % (zope_uri, domain)}] + 'remote_uri': '%s/VirtualHostBase/http/%s:8000/openplans/VirtualHostRoot/' % (zope_uri, domain)}] domain_info.remote_uris = remote_uris return project = match.group(1) @@ -66,6 +66,7 @@ project = environ['HTTP_X_OPENPLANS_PROJECT'] path_info = environ.get('PATH_INFO', '') if path_info.startswith('/tasks'): + environ['HTTP_X_OPENPLANS_APPLICATION'] = 'tasktracker' remote_uri = task_tracker_uri # Move /tasks to SCRIPT_NAME path_info_pop(environ) From kobold at codespeak.net Fri Apr 13 12:31:32 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 12:31:32 +0200 (CEST) Subject: [z3-checkins] r42022 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413103132.BAE1780AF@code0.codespeak.net> Author: kobold Date: Fri Apr 13 12:31:32 2007 New Revision: 42022 Modified: z3/sqlos/trunk/src/sqlos/README.txt Log: Updated documentation. Modified: z3/sqlos/trunk/src/sqlos/README.txt ============================================================================== --- z3/sqlos/trunk/src/sqlos/README.txt (original) +++ z3/sqlos/trunk/src/sqlos/README.txt Fri Apr 13 12:31:32 2007 @@ -10,20 +10,19 @@ Introduction ------------ -``sqlos`` is a toolkit for using SQLObject_ (an Object Relational -Mapper) inside Zope 3 or Zope 2. It tries to take care of many of the -fiddly details that always seem to take a lot of time. The major ways -it helps are: +``sqlos`` is a toolkit for using SQLObject_ (an Object Relational Mapper) +inside Zope 3 or Zope 2. It tries to take care of many of the fiddly details +that always seem to take a lot of time. The major ways it helps are: - + Integrates the Zope transaction system and SQLObject, allowing - SQLObject to be used in lazyUpdate mode. + + Integrates the Zope transaction system and SQLObject, allowing SQLObject + to be used in lazyUpdate mode. + Uses Zope Database adapters in SQLObject. + Provide zcml configuration directives. - + Provide ZODB persistent objects that can act as a "window" into - the database. + + Provide ZODB persistent objects that can act as a "window" into the + database. + A testing infrastructure for testing SQLObject based applications. @@ -31,19 +30,19 @@ .. _SQLObject: http://sqlobject.org -This file describes how to use the ``sqlos`` package to use SQLObject -together with Zope. +This file describes how to use the ``sqlos`` package to use SQLObject together +with Zope. Zope 3 or Zope 2?? ------------------ -For a quite few reasons, it is better and easier to use sqlos in Zope 3, -but it can be used with Zope 2. Heavily leveraging the work by the Five -project, a Zope 2 product (FiveSQLOS) was created to enable this. +For a quite few reasons, it is better and easier to use sqlos in Zope 3, but it +can be used with Zope 2. Heavily leveraging the work by the Five project, a +Zope 2 product (FiveSQLOS) was created to enable this. -The following table shows which sqlos version can and should be used -with which Zope 2 and Zope 3 versions. +The following table shows which sqlos version can and should be used with which +Zope 2 and Zope 3 versions. ============ ======== ========= . Zope 2.9 Zope 2.10 @@ -85,45 +84,43 @@ Background ---------- -``sqlos`` was originally developed for the ``SIP`` project. You can -find more information about SIP, including some screencasts on the -`SIP project homepage`_. +``sqlos`` was originally developed for the ``SIP`` project. You can find more +information about SIP, including some screencasts on the `SIP project +homepage`_. .. _SIP project homepage: http://sampleinventory.sf.net -Currently we're using a ``SQLObjectContainer`` object, that behaves -like a normal folder, except that its contents doesn't come from the -ZODB, but instead, they come from an SQL connection, through -SQLObject. - -Given the pluggable nature of Zope 3, it was quite easy to integrate -it with SQLObject. Originally, SQLObject had its own ``DBConnection`` -objects, that handle all the operations with the SQL backend, and even -some other backends, like ``DBM``. These connection objects implement -the ``DBAPI``, and work over a SQL cursor that is generated on the -``makeConnection`` method of the DBConnection-based classes. Each -database connection implements a given set of methods to generate -queries and convert data types. To allow using a connection from Zope -3 in SQLObject, we used an ``adapter``, which adapts a +Currently we're using a ``SQLObjectContainer`` object, that behaves like a +normal folder, except that its contents doesn't come from the ZODB, but +instead, they come from an SQL connection, through SQLObject. + +Given the pluggable nature of Zope 3, it was quite easy to integrate it with +SQLObject. Originally, SQLObject had its own ``DBConnection`` objects, that +handle all the operations with the SQL backend, and even some other backends, +like ``DBM``. These connection objects implement the ``DBAPI``, and work over a +SQL cursor that is generated on the ``makeConnection`` method of the +DBConnection-based classes. Each database connection implements a given set of +methods to generate queries and convert data types. To allow using a connection +from Zope 3 in SQLObject, we used an ``adapter``, which adapts a ``IZopeDatabaseAdapter`` utility service to the same interface that a DBConnection object implements. This adapter just subclasses the -``*Connection`` classes from SQLObject (eg: MySQLConnection), -overriding the ``__init__`` and ``makeConnection`` method to -initialize an instance variable with a reference to the ZopeConnection -object and to return a ZopeCursor instance respectively. - -For the SQLObjectContainer class, we made it so it is possible to -choose a set of class names that will be available inside that container. - -Based on this, the methods of the IContainer class were implemented so -as all operations are done using SQLObject methods. For example, the -``keys`` method does a select query and returns the available ids, the -items method uses the SQLObject class ``select()`` method to generate one -object for each row in the database and return them. - -At this point, we have an object that behaves just like a folder, and -its flexible enough that you can make their objects come from any -connection and any registered class you wish. +``*Connection`` classes from SQLObject (eg: MySQLConnection), overriding the +``__init__`` and ``makeConnection`` method to initialize an instance variable +with a reference to the ZopeConnection object and to return a ZopeCursor +instance respectively. + +For the SQLObjectContainer class, we made it so it is possible to choose a set +of class names that will be available inside that container. + +Based on this, the methods of the IContainer class were implemented so as all +operations are done using SQLObject methods. For example, the ``keys`` method +does a select query and returns the available ids, the items method uses the +SQLObject class ``select()`` method to generate one object for each row in the +database and return them. + +At this point, we have an object that behaves just like a folder, and its +flexible enough that you can make their objects come from any connection and +any registered class you wish. Installation @@ -132,8 +129,8 @@ Zope3 _____ -You can easily install sqlos from the python cheeseshop using easy_install. -To do this, you will have to first install setuptools_. +You can easily install sqlos from the python cheeseshop using easy_install. To +do this, you will have to first install setuptools_. For example, this command will install the latest version of sqlos and it's dependencies in ~/lib/python2.4/site-packages. Note that @@ -145,8 +142,8 @@ copy the sqlos-\*.zcml package includes (in the includes directory in the tarball) to the package-includes directory of your Zope instance. -NOTE: the sqlos.ftesting-configure.zcml shouldn't be copied unless you want - to test the sample application. +NOTE: the sqlos.ftesting-configure.zcml shouldn't be copied unless you want to +test the sample application. Zope2 @@ -160,34 +157,36 @@ A Sample Application -------------------- -The functional test setup for sqlos is really a sample application. You can -run and play with this to see how sqlos works. +The functional test setup for sqlos is really a sample application. You can run +and play with this to see how sqlos works. First install a Z3 database adapter, create a database, edit -src/sqlos/ftesting.zcml to change the connection settings as -described below in "Setting up a connection for SQLObject". +src/sqlos/ftesting.zcml to change the connection settings as described below in +"Setting up a connection for SQLObject". -NOTE: This currently does not work with the default testing database - (memory based SQLite) due to threading issues. +NOTE: This currently does not work with the default testing database (memory +based SQLite) due to threading issues. In order to run the testing application, +change the rdb connection to point to a real file instead of an in-memory +database within the file ftesting.zcml. Then, from a checkout of sqlos run: $ make run-sampleapp -This should download Zope3 install sqlos and set up the functional -test suite as a sample application. You can then log into zope3 on -http://localhost:8080 with gandalf:123. +This should download Zope3 install sqlos and set up the functional test suite +as a sample application. You can then log into zope3 on http://localhost:8080 +with gandalf:123. Try adding a "SQLObject MultiContainer" and then some people. -NOTE: changing debug=1 in src/sqlos/adapter.py will cause the SQL - executed to be printed on the terminal +NOTE: changing debug=1 in src/sqlos/adapter.py will cause the SQL executed to +be printed on the terminal Setting up a connection for SQLObject ------------------------------------- -This example is not complete yet (XXX), but should give you an idea:: +This is an example connection configuration with psycopgda:: -There are a few things that you need to know about this piece of -ZCML: +There are a few things that you need to know about this piece of ZCML: -First, the ```` part is what does generate the -automatic editform for the Person class. As you can see, we don't -reference the class explicitly, but instead, we are saying that for -the ``IPerson`` schema (a schema is just a flavor of interface), there -will be an auto-generated editform called ``edit.html`` and it will be -registered with the menu ``zmi_views``. ```` is a -``directive``, which is also registered using ZCML and is created as -part of the ``metaconfiguration`` of Zope 3. I'll not enter this into -detail now. All you need to know is that this is a ``special view`` -that spits out an edit form in HTML based on the schema you defined. - -Second, the ```` directive is used to register -some information about the class, like what factory will be using for -creating instances of it and what are the permissions needed to do -stuff with this class. The directive register the -class as a IFactory utility and also registers the class as a -IISQLObject utility. +First, the ```` part is what does generate the automatic +editform for the Person class. As you can see, we don't reference the class +explicitly, but instead, we are saying that for the ``IPerson`` schema (a +schema is just a flavor of interface), there will be an auto-generated editform +called ``edit.html`` and it will be registered with the menu ``zmi_views``. +```` is a ``directive``, which is also registered using +ZCML and is created as part of the ``metaconfiguration`` of Zope 3. I'll not +enter this into detail now. All you need to know is that this is a ``special +view`` that spits out an edit form in HTML based on the schema you defined. + +Second, the ```` directive is used to register some +information about the class, like what factory will be using for creating +instances of it and what are the permissions needed to do stuff with this +class. The directive register the class as a IFactory utility +and also registers the class as a IISQLObject utility. Let's take a look at the ```` directive: -As you can see, there are 3 attributes on the directive. The -``permission`` attribute specifies the permission that is -required. The ``interface`` attribure specifies what is the interface -that is protected by this permission. All the methods and properties -defined on this interface are protected for reading by this -permission. And last, the ``set_schema`` attribute specifies what is -the interface which is going to be protected for *setting* attributes -on the instances of this class. This is needed for the auto-generated -form to work. If you don't specify a permission to protect -``set_schema`` on the interface, you won`t be able to modify the -instance. +As you can see, there are 3 attributes on the directive. The ``permission`` +attribute specifies the permission that is required. The ``interface`` +attribure specifies what is the interface that is protected by this permission. +All the methods and properties defined on this interface are protected for +reading by this permission. And last, the ``set_schema`` attribute specifies +what is the interface which is going to be protected for *setting* attributes +on the instances of this class. This is needed for the auto-generated form to +work. If you don't specify a permission to protect ``set_schema`` on the +interface, you won`t be able to modify the instance. Create A Container ------------------ -In addition to defining the content for Zope, you need a place for -zope to locate the content. ``sqlos`` already provides nearly all of -the implementation in the SQLObjectContainer class, however this -ready-made container is constrained such that it can not contain any -content. SQLObjectContainer must be extended to adjust this -constraint and make the data in the database appear to be in this -container. +In addition to defining the content for Zope, you need a place for zope to +locate the content. ``sqlos`` already provides nearly all of the +implementation in the SQLObjectContainer class, however this ready-made +container is constrained such that it can not contain any content. +SQLObjectContainer must be extended to adjust this constraint and make the data +in the database appear to be in this container. As always, the first step is to declare the interface:: @@ -349,8 +342,8 @@ ... pass ... __setitem__.precondition = ItemTypePrecondition( IPerson ) -The zope container infrastructure checks the __setitem__ precondition -to determine what type of content the container is allowed to contain. +The zope container infrastructure checks the __setitem__ precondition to +determine what type of content the container is allowed to contain. Next, define the implementation:: @@ -359,10 +352,10 @@ >>> class PersonContainer(SQLObjectContainer) : ... implements(IPersonContainer) -All that needs to be done at this point is to connect an -implementation with the interface. SQLObjectContainer provides all -the (core) logic necessary. Later you may want to add custom methods -and logic for convenience in manipulating the SQL-backed records. +All that needs to be done at this point is to connect an implementation with +the interface. SQLObjectContainer provides all the (core) logic necessary. +Later you may want to add custom methods and logic for convenience in +manipulating the SQL-backed records. Finally, write the ZCML configuration to put all the pieces together:: @@ -403,27 +396,25 @@ Demonstration ------------- -At this point you have a complete web interface for your database. -It is time to test it and demonstrate that it does, indeed, work. +At this point you have a complete web interface for your database. It is time +to test it and demonstrate that it does, indeed, work. -Start zope and point your browser to the ZMI. In the list of addable -items on the left you should see our ``Person Container`` type. Add -``Person Container`` to your site. When you view the container's -@@contents.html view, you should see a simple listing of all the -people in your database. +Start zope and point your browser to the ZMI. In the list of addable items on +the left you should see our ``Person Container`` type. Add ``Person +Container`` to your site. When you view the container's @@contents.html view, +you should see a simple listing of all the people in your database. A Nice Touch (Title / DublinCore) --------------------------------- -Although the base @@contents.html view is fully functional, it leaves -plenty of usability to be desired. You will almost certainly want to -replace the built-in container contents listing with a custom view -tailored to the type of content your container handles. However, the -built-in contents can trivially be given a nice touch that vastly -improves the usability. The view queries the content for its -DublinCore_ metadata, such as Title. We will provide this metadata -with an adapter to adapt the IPerson interface to IZopeDublinCore. +Although the base @@contents.html view is fully functional, it leaves plenty of +usability to be desired. You will almost certainly want to replace the +built-in container contents listing with a custom view tailored to the type of +content your container handles. However, the built-in contents can trivially +be given a nice touch that vastly improves the usability. The view queries the +content for its DublinCore_ metadata, such as Title. We will provide this +metadata with an adapter to adapt the IPerson interface to IZopeDublinCore. The code is as follows:: From kobold at codespeak.net Fri Apr 13 13:14:53 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 13:14:53 +0200 (CEST) Subject: [z3-checkins] r42023 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413111453.498F480B5@code0.codespeak.net> Author: kobold Date: Fri Apr 13 13:14:51 2007 New Revision: 42023 Modified: z3/sqlos/trunk/src/sqlos/README.txt Log: Renamed class Person to SamplePerson to not conflict with the testing package. Modified: z3/sqlos/trunk/src/sqlos/README.txt ============================================================================== --- z3/sqlos/trunk/src/sqlos/README.txt (original) +++ z3/sqlos/trunk/src/sqlos/README.txt Fri Apr 13 13:14:51 2007 @@ -236,7 +236,7 @@ >>> from sqlobject import * >>> from sqlos.zsqlobject import SQLOS - >>> class Person(SQLOS): + >>> class SimplePerson(SQLOS): ... implements(IPerson) ... username = StringCol('username', length=20, notNull=True) ... fname = StringCol('fname', length=20, notNull=True) From kobold at codespeak.net Fri Apr 13 13:26:30 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 13:26:30 +0200 (CEST) Subject: [z3-checkins] r42024 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413112630.985D280AB@code0.codespeak.net> Author: kobold Date: Fri Apr 13 13:26:30 2007 New Revision: 42024 Added: z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml - copied unchanged from r42022, z3/sqlos/trunk/src/sqlos/sampleapp.zcml Removed: z3/sqlos/trunk/src/sqlos/sampleapp.zcml Log: Renamed sampleapp.zcml to sqlos.ftesting-configure.zcml. Deleted: /z3/sqlos/trunk/src/sqlos/sampleapp.zcml ============================================================================== --- /z3/sqlos/trunk/src/sqlos/sampleapp.zcml Fri Apr 13 13:26:30 2007 +++ (empty file) @@ -1,14 +0,0 @@ - - - - - - - - - - From kobold at codespeak.net Fri Apr 13 13:40:08 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 13:40:08 +0200 (CEST) Subject: [z3-checkins] r42026 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413114008.8B55080BB@code0.codespeak.net> Author: kobold Date: Fri Apr 13 13:40:08 2007 New Revision: 42026 Added: z3/sqlos/trunk/src/sqlos/sampleapp.zcml - copied unchanged from r42024, z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml Modified: z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml Log: Changes. Modified: z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml ============================================================================== --- z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml (original) +++ z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml Fri Apr 13 13:40:08 2007 @@ -1,14 +1 @@ - - - - - - - - - - + From kobold at codespeak.net Fri Apr 13 13:42:29 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 13:42:29 +0200 (CEST) Subject: [z3-checkins] r42027 - z3/sqlos/trunk Message-ID: <20070413114229.8E55880BC@code0.codespeak.net> Author: kobold Date: Fri Apr 13 13:42:29 2007 New Revision: 42027 Modified: z3/sqlos/trunk/Makefile z3/sqlos/trunk/setup.py Log: Preparing the new release. Modified: z3/sqlos/trunk/Makefile ============================================================================== --- z3/sqlos/trunk/Makefile (original) +++ z3/sqlos/trunk/Makefile Fri Apr 13 13:42:29 2007 @@ -4,7 +4,7 @@ ZH=${HERE}/../../ PYTHON=python2.4 z3includes=Zope3/zopeskel/etc/package-includes -Z3BRANCH=trunk +Z3BRANCH=branches/3.3 all : test clean @@ -41,7 +41,7 @@ Zope3: $(MAKE) z3-checkout -$(z3includes)/%.zcml: includes/%.zcml Zope3 +$(z3includes)/%.zcml: src/sqlos/%.zcml Zope3 cp $< $@ .PHONY: sqlos-meta Modified: z3/sqlos/trunk/setup.py ============================================================================== --- z3/sqlos/trunk/setup.py (original) +++ z3/sqlos/trunk/setup.py Fri Apr 13 13:42:29 2007 @@ -4,12 +4,12 @@ name="sqlos", description="an integration package for Zope3 and SQLObject", long_description=""" -sqlos is a toolkit for using SQLObject (an Object Relational -Mapper) inside Zope 3 or Zope 2. It tries to take care of many of the -fiddly details that always seem to take a lot of time. +sqlos is a toolkit for using SQLObject (an Object Relational Mapper) inside +Zope 3 or Zope 2. It tries to take care of many of the fiddly details that +always seem to take a lot of time. """, url='http://codespeak.net/z3/sqlos/', - version="0.3", + version="0.4.0", license="ZPL", maintainer="SQLOS development team", maintainer_email="z3-sqlos at codespeak.net", @@ -19,6 +19,6 @@ zip_safe=False, include_package_data=True, install_requires = [ - 'SQLObject>=0.7', + 'SQLObject>=0.7.1', ] ) From kobold at codespeak.net Fri Apr 13 13:55:19 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 13:55:19 +0200 (CEST) Subject: [z3-checkins] r42028 - in z3/sqlos/trunk/src/sqlos/testing: . tests Message-ID: <20070413115519.034B180B8@code0.codespeak.net> Author: kobold Date: Fri Apr 13 13:55:19 2007 New Revision: 42028 Modified: z3/sqlos/trunk/src/sqlos/testing/sampleperson.py z3/sqlos/trunk/src/sqlos/testing/tests/test_sampleperson.py Log: Ugly fix for a bug with a recent zope. Modified: z3/sqlos/trunk/src/sqlos/testing/sampleperson.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/testing/sampleperson.py (original) +++ z3/sqlos/trunk/src/sqlos/testing/sampleperson.py Fri Apr 13 13:55:19 2007 @@ -104,7 +104,8 @@ class SampleIsolatedPerson(SQLOSContainer): - classProvides(IISQLObjectIsolated) + # XXX: this doesn't work on a recent Zope + # classProvides(IISQLObjectIsolated) implements(IPerson, ISQLObjectIsolated) # Using a StringCol for a list is probably not the right way to do things Modified: z3/sqlos/trunk/src/sqlos/testing/tests/test_sampleperson.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/testing/tests/test_sampleperson.py (original) +++ z3/sqlos/trunk/src/sqlos/testing/tests/test_sampleperson.py Fri Apr 13 13:55:19 2007 @@ -42,8 +42,6 @@ >>> from sqlos.interfaces import IISQLObjectIsolated >>> verifyObject(ISQLObjectIsolated, s) True - >>> verifyObject(IISQLObjectIsolated, SampleIsolatedPerson) - True The domains attrubite normally represents the list of container id's in which the object can be found. It is a tuple. From kobold at codespeak.net Fri Apr 13 14:26:11 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 14:26:11 +0200 (CEST) Subject: [z3-checkins] r42029 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413122611.7EAE980BF@code0.codespeak.net> Author: kobold Date: Fri Apr 13 14:26:10 2007 New Revision: 42029 Modified: z3/sqlos/trunk/src/sqlos/connection.py Log: Fixed a bug. Modified: z3/sqlos/trunk/src/sqlos/connection.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/connection.py (original) +++ z3/sqlos/trunk/src/sqlos/connection.py Fri Apr 13 14:26:10 2007 @@ -50,11 +50,14 @@ ut = getUtility(IConnectionName, context=context) name = ut.name except ComponentLookupError: - return None + return self + # get the connection from the global thread cache try: return getConnection(context, name) except ComponentLookupError: + warnings.warn("Couldn't find ISQLConnectionName utility. " + "Please verify your setup.", SQLOSWarning, 2) return None def __set__(self, inst, value): @@ -77,9 +80,9 @@ default=None, context=context) if newconn is None: - warnings.warn("Couldn't find a rdb connection by the " - "name %s. Please verify your setup." % name, - SQLOSWarning, 3) + warnings.warn("Couldn't find a rdb connection by the name %s. " + "Please verify your setup." % name, SQLOSWarning, 3) + return None conn = IZopeSQLConnection(newconn()) if conn.supportTransactions: connCache[key] = conn.transaction() From kobold at codespeak.net Fri Apr 13 14:33:57 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 14:33:57 +0200 (CEST) Subject: [z3-checkins] r42030 - z3/sqlos/trunk/src/sqlos Message-ID: <20070413123357.186A780C0@code0.codespeak.net> Author: kobold Date: Fri Apr 13 14:33:56 2007 New Revision: 42030 Modified: z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml Log: Fixed a typo. Modified: z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml ============================================================================== --- z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml (original) +++ z3/sqlos/trunk/src/sqlos/sqlos.ftesting-configure.zcml Fri Apr 13 14:33:56 2007 @@ -1 +1 @@ - + From kobold at codespeak.net Fri Apr 13 14:35:06 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Fri, 13 Apr 2007 14:35:06 +0200 (CEST) Subject: [z3-checkins] r42031 - z3/sqlos/tag/0.4.0 Message-ID: <20070413123506.CFE9D80C1@code0.codespeak.net> Author: kobold Date: Fri Apr 13 14:35:06 2007 New Revision: 42031 Added: z3/sqlos/tag/0.4.0/ - copied from r42030, z3/sqlos/trunk/ Log: Tag for sqlos 0.4.0. From ianb at codespeak.net Fri Apr 13 21:22:58 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Fri, 13 Apr 2007 21:22:58 +0200 (CEST) Subject: [z3-checkins] r42038 - in z3/deliverance/DeliveranceVHoster/trunk: docs dvhoster Message-ID: <20070413192258.4D49E80C9@code0.codespeak.net> Author: ianb Date: Fri Apr 13 21:22:56 2007 New Revision: 42038 Added: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/uritemplate.py (contents, props changed) Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Allow URI templates for remote_uri Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/rest-api.txt Fri Apr 13 21:22:56 2007 @@ -90,6 +90,32 @@ can do this with a `hook `_, or otherwise all requests (except to this configuration API) will fail. + ``remote_uri`` may be a `URI Template + `_, + meaning that variables can be put in ``{varname}}. These variables + are available: + + ``{host}``: + The host *and* port of the request (e.g., ``foo.com:80``). + + ``{domain}``: + The host without port + + ``{port}``: + The port + + ``{scheme}``: + The scheme, like ``http`` or ``https`` + + ``{path}``: + The full path of the request + + ``{script_name}``: + The SCRIPT_NAME (typically empty) + + ``{path_info}``: + The PATH_INFO (typically the same as ``{path}``) + ``/.deliverance/remote_uris?{add or remove}`` You can post to one of these resources to add or remove items from Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Apr 13 21:22:56 2007 @@ -15,6 +15,7 @@ from dvhoster.debuginterp import Renderer from dvhoster.util import load_func from dvhoster.logcreate import make_logger +from dvhoster import uritemplate def norm_path(urlpath): if not urlpath: @@ -112,6 +113,17 @@ for r in remote_uris]))) return exc(environ, start_response) + vars = { + 'host': environ['HTTP_HOST'], + 'domain': environ['HTTP_HOST'].split(':', 1)[0], + 'scheme': environ['wsgi.url_scheme'], + 'port': environ['HTTP_HOST'].split(':', 1)[1], + 'path': environ['SCRIPT_NAME'] + environ['PATH_INFO'], + 'script_name': environ['SCRIPT_NAME'], + 'path_info': environ['PATH_INFO'], + } + remote_uri = uritemplate.sub_vars(remote_uri, vars) + environ['dvhoster.remote_uri'] = remote_uri should_theme_uri = True @@ -163,6 +175,15 @@ if self.clean_environ_headers_regex.search(key): # @@: Should log this del environ[key] + host = environ.get('HTTP_HOST') + if host is None: + host = environ['SERVER_NAME'] + ':' + environ['SERVER_PORT'] + elif ':' not in host: + if environ['wsgi.url_scheme'] == 'https': + host += ':443' + else: + host += ':80' + environ['HTTP_HOST'] = host def get_domain_info(self, environ): """ Added: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/uritemplate.py ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/uritemplate.py Fri Apr 13 21:22:56 2007 @@ -0,0 +1,26 @@ +""" +Substitutes URL templates +""" + +import re +import urllib + +template_re = re.compile(r'[{](.*?)[}]') + +def sub_vars(uri, vars, default=None): + if default is None: + def subber(match): + try: + return urllib.quote(str(vars[match.group(1)])) + except KeyError: + raise KeyError( + "Variable %s in template %r not found (from variables %s)" + % (match.group(1) or '(empty)', + uri, + ', '.join(map(str, vars.keys())))) + else: + def subber(match): + return urllib.quote(str(vars.get(match.group(1), default))) + return template_re.sub(subber, uri) + + From ejucovy at codespeak.net Fri Apr 13 22:46:55 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Fri, 13 Apr 2007 22:46:55 +0200 (CEST) Subject: [z3-checkins] r42039 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070413204655.EF8E080CD@code0.codespeak.net> Author: ejucovy Date: Fri Apr 13 22:46:55 2007 New Revision: 42039 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: Don't set up remote_uri in init_domain; that's what find_remote_uri is for. Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Fri Apr 13 22:46:55 2007 @@ -35,10 +35,6 @@ if not match: # Don't try to set up domains we don't recognize print 'The domain %r cannot be recognized by the domain_regex %r' % (domain, domain_regex) - zope_uri = app_conf['zope_uri'] - remote_uris = [{'path': '', - 'remote_uri': '%s/VirtualHostBase/http/%s:8000/openplans/VirtualHostRoot/' % (zope_uri, domain)}] - domain_info.remote_uris = remote_uris return project = match.group(1) remote_uris = [ From ejucovy at codespeak.net Mon Apr 16 17:23:32 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Mon, 16 Apr 2007 17:23:32 +0200 (CEST) Subject: [z3-checkins] r42098 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070416152332.9883980C6@code0.codespeak.net> Author: ejucovy Date: Mon Apr 16 17:23:31 2007 New Revision: 42098 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: * set domain_uris = [] to bypass initialized check * don't assume we're going to a project in find_uri Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Mon Apr 16 17:23:31 2007 @@ -35,6 +35,7 @@ if not match: # Don't try to set up domains we don't recognize print 'The domain %r cannot be recognized by the domain_regex %r' % (domain, domain_regex) + domain_info.remote_uris = [] return project = match.group(1) remote_uris = [ @@ -59,18 +60,22 @@ return remote_uri zope_uri = app_conf['zope_uri'] task_tracker_uri = app_conf['task_tracker_uri'] - project = environ['HTTP_X_OPENPLANS_PROJECT'] + project = environ.get('HTTP_X_OPENPLANS_PROJECT') path_info = environ.get('PATH_INFO', '') if path_info.startswith('/tasks'): environ['HTTP_X_OPENPLANS_APPLICATION'] = 'tasktracker' remote_uri = task_tracker_uri # Move /tasks to SCRIPT_NAME path_info_pop(environ) - else: + elif project: remote_uri = '%s/VirtualHostBase/http/%s/openplans/projects/%s/VirtualHostRoot' % ( zope_uri, environ['HTTP_HOST'], - project) + project ) + else: + remote_uri = '%s/VirtualHostBase/http/%s/openplans/VirtualHostRoot' % ( + zope_uri, + environ['HTTP_HOST'] ) return remote_uri def should_theme_uri(remote_uri, environ, app_conf): From ianb at codespeak.net Mon Apr 16 19:39:38 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Mon, 16 Apr 2007 19:39:38 +0200 (CEST) Subject: [z3-checkins] r42104 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070416173938.DA18C80C8@code0.codespeak.net> Author: ianb Date: Mon Apr 16 19:39:32 2007 New Revision: 42104 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Switch header cleaning order, so HTTP_HOST is always cleaned Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Mon Apr 16 19:39:32 2007 @@ -56,6 +56,10 @@ self.clean_environ_headers_regex = re.compile(app_conf['clean_environ_headers_regex']) else: self.clean_environ_headers_regex = None + if app_conf.get('safe_header_ips'): + self.safe_header_ips = app_conf.get('safe_header_ips').strip().split() + else: + self.safe_header_ips = None logger = make_logger(app_conf.get('logger'), 'dvhoster') self.logger = logger @@ -169,12 +173,6 @@ Remove any request headers that overlap with internal request headers (as configured with ``clean_environ_headers_regex``). """ - if not self.clean_environ_headers_regex: - return - for key in environ.keys(): - if self.clean_environ_headers_regex.search(key): - # @@: Should log this - del environ[key] host = environ.get('HTTP_HOST') if host is None: host = environ['SERVER_NAME'] + ':' + environ['SERVER_PORT'] @@ -184,6 +182,16 @@ else: host += ':80' environ['HTTP_HOST'] = host + if not self.clean_environ_headers_regex: + return + remote_addr = environ.get('REMOTE_ADDR') + if (remote_addr and self.safe_header_ips + and remote_addr in self.safe_header_ips): + return + for key in environ.keys(): + if self.clean_environ_headers_regex.search(key): + # @@: Should log this + del environ[key] def get_domain_info(self, environ): """ From ianb at codespeak.net Tue Apr 17 01:23:12 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 17 Apr 2007 01:23:12 +0200 (CEST) Subject: [z3-checkins] r42110 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070416232312.5CFA680C3@code0.codespeak.net> Author: ianb Date: Tue Apr 17 01:23:12 2007 New Revision: 42110 Added: z3/deliverance/DeliveranceVHoster/trunk/docs/configuration.txt (contents, props changed) Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: added config doc Added: z3/deliverance/DeliveranceVHoster/trunk/docs/configuration.txt ============================================================================== --- (empty file) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/configuration.txt Tue Apr 17 01:23:12 2007 @@ -0,0 +1,61 @@ +Configuration of dvhoster +========================= + +Configuration is in a `PasteDeploy `_ +.ini file. These are the supported parameters: + +``data_dir`` (no default): + Where all the data about hosts is kept. This should exist and be + writable. All the information goes in subdirectories, one + subdirectory for each host. + +``rewrite_links`` (default false): + If true, then pages will have their links rewritten. You can use + this if the application doesn't understand what the original + request was, and so passed through bad links (e.g., pointing to + localhost). + +``clean_environ_headers_regex`` (no default): + Any keys in the WSGI environ that match this regular expression + will be removed. A value might be ``^HTTP_X_REMOTE_USER`` to + match any ``X-Remote-User`` header (and remove it). + +``safe_header_ips`` (no default): + Any requests from these ip addresses (a list separated by + whitespace) will not have their headers cleaned. + +``logger``: + This is the logger that messages should go to about any + Deliverance internal errors. You can also use a filename, and the + log message will be directed there, or ``-`` and the log messages + will go to stdout. + + +Debugging +--------- + +DVHoster accepts a ``debug`` configuration key which turns on the +EvalException middleware. This **must not be deployed in production** +as it opens up bit security hole. + +``debug_headers`` will print out incoming and outgoing headers. If +``debug_bodies`` is also on then outgoing bodies will also be +printed. This is noisy, so should only be on for testing. + + +Hooks +----- + +There are three parameters: ``init_domain``, ``find_remote_uri``, and +``should_theme_uri``. These are described in the document on `hooks +`_. + + +Hook Configuration +------------------ + +Each hook gets a dictionary of configuration parameters. You can add +new variables that will be interpreted by your custom hooks. + +Examples are in ``docs/openplans_hooks.py``, where it uses variables +like ``zope_uri`` and ``domain_regex``. Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Tue Apr 17 01:23:12 2007 @@ -7,7 +7,8 @@ import re from paste.deploy.converters import asbool -from paste.request import path_info_pop +from paste.request import path_info_pop, construct_url +from paste import httpexceptions rule_data = """\ @@ -62,7 +63,12 @@ task_tracker_uri = app_conf['task_tracker_uri'] project = environ.get('HTTP_X_OPENPLANS_PROJECT') path_info = environ.get('PATH_INFO', '') - if path_info.startswith('/tasks'): + if path_info == '/tasks': + # Need to redirect + new_url = construct_url(environ, path_info='/tasks/') + raise httpexceptions.HTTPMovedPermanently( + headers=[('Location': new_url)]) + if path_info.startswith('/tasks/'): environ['HTTP_X_OPENPLANS_APPLICATION'] = 'tasktracker' remote_uri = task_tracker_uri # Move /tasks to SCRIPT_NAME From ejucovy at codespeak.net Tue Apr 17 17:43:39 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Tue, 17 Apr 2007 17:43:39 +0200 (CEST) Subject: [z3-checkins] r42130 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070417154339.7CA9D80A3@code0.codespeak.net> Author: ejucovy Date: Tue Apr 17 17:43:38 2007 New Revision: 42130 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: fixed syntax error Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Tue Apr 17 17:43:38 2007 @@ -67,7 +67,7 @@ # Need to redirect new_url = construct_url(environ, path_info='/tasks/') raise httpexceptions.HTTPMovedPermanently( - headers=[('Location': new_url)]) + headers=[{'Location': new_url}]) if path_info.startswith('/tasks/'): environ['HTTP_X_OPENPLANS_APPLICATION'] = 'tasktracker' remote_uri = task_tracker_uri From ejucovy at codespeak.net Tue Apr 17 17:56:23 2007 From: ejucovy at codespeak.net (ejucovy at codespeak.net) Date: Tue, 17 Apr 2007 17:56:23 +0200 (CEST) Subject: [z3-checkins] r42132 - z3/deliverance/DeliveranceVHoster/trunk/docs Message-ID: <20070417155623.21DC380A7@code0.codespeak.net> Author: ejucovy Date: Tue Apr 17 17:56:22 2007 New Revision: 42132 Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Log: fixed broken syntax error fix Modified: z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/docs/openplans_hooks.py Tue Apr 17 17:56:22 2007 @@ -67,7 +67,7 @@ # Need to redirect new_url = construct_url(environ, path_info='/tasks/') raise httpexceptions.HTTPMovedPermanently( - headers=[{'Location': new_url}]) + headers=[('Location', new_url)]) if path_info.startswith('/tasks/'): environ['HTTP_X_OPENPLANS_APPLICATION'] = 'tasktracker' remote_uri = task_tracker_uri From ltucker at codespeak.net Tue Apr 17 19:15:25 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Tue, 17 Apr 2007 19:15:25 +0200 (CEST) Subject: [z3-checkins] r42134 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070417171525.1BA4E8095@code0.codespeak.net> Author: ltucker Date: Tue Apr 17 19:15:25 2007 New Revision: 42134 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: fix typo Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Tue Apr 17 19:15:25 2007 @@ -114,7 +114,7 @@ "No URL is mapped to %r (somewhat oddly); only %s prefixes " "are available" % (path_info, ', '.join([repr(r['path']) - for r in remote_uris]))) + for r in domain_info.remote_uris]))) return exc(environ, start_response) vars = { From ianb at codespeak.net Wed Apr 18 00:31:36 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Wed, 18 Apr 2007 00:31:36 +0200 (CEST) Subject: [z3-checkins] r42141 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070417223136.23A33809A@code0.codespeak.net> Author: ianb Date: Wed Apr 18 00:31:35 2007 New Revision: 42141 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py Log: Fix how the log is setup Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/logcreate.py Wed Apr 18 00:31:35 2007 @@ -1,4 +1,5 @@ import logging +import logging.handlers def make_logger(name, default_name): if name is None: @@ -21,7 +22,7 @@ logger.addHandler(console) logger.propagate = False if setup_file: - file_log = logging.RotatingFileHandler(setup_file) + file_log = logging.handlers.RotatingFileHandler(setup_file) file_log.setLevel(logging.DEBUG) logger.addHandler(file_log) logger.propagate = False From philikon at codespeak.net Thu Apr 19 12:14:10 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Thu, 19 Apr 2007 12:14:10 +0200 (CEST) Subject: [z3-checkins] r42163 - z3/NudgeNudge/trunk/src/nudgenudge Message-ID: <20070419101410.66E518093@code0.codespeak.net> Author: philikon Date: Thu Apr 19 12:14:09 2007 New Revision: 42163 Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py Log: Fix after formlib refactoring in Grok Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py ============================================================================== --- z3/NudgeNudge/trunk/src/nudgenudge/app.py (original) +++ z3/NudgeNudge/trunk/src/nudgenudge/app.py Thu Apr 19 12:14:09 2007 @@ -72,7 +72,7 @@ @grok.action('Create') def create(self, **kw): r = Review() - self.applyChanges(r, **kw) + self.applyData(r, **kw) base = name = kw['package_name'] + '-' + kw['version'] count = 0 From philikon at codespeak.net Thu Apr 19 13:22:15 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Thu, 19 Apr 2007 13:22:15 +0200 (CEST) Subject: [z3-checkins] r42165 - z3/NudgeNudge/branches/indexes-refactoring Message-ID: <20070419112215.20A3D8096@code0.codespeak.net> Author: philikon Date: Thu Apr 19 13:22:14 2007 New Revision: 42165 Added: z3/NudgeNudge/branches/indexes-refactoring/ - copied from r42164, z3/NudgeNudge/trunk/ Log: Branch for refactoring NudgeNudge to use Martijn's work on defining indexes in Grok. From philikon at codespeak.net Thu Apr 19 13:22:54 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Thu, 19 Apr 2007 13:22:54 +0200 (CEST) Subject: [z3-checkins] r42166 - z3/NudgeNudge/branches/indexes-refactoring Message-ID: <20070419112254.39B18809B@code0.codespeak.net> Author: philikon Date: Thu Apr 19 13:22:53 2007 New Revision: 42166 Modified: z3/NudgeNudge/branches/indexes-refactoring/ (props changed) z3/NudgeNudge/branches/indexes-refactoring/buildout.cfg Log: Install Grok from svn to get martijn's branch Modified: z3/NudgeNudge/branches/indexes-refactoring/buildout.cfg ============================================================================== --- z3/NudgeNudge/branches/indexes-refactoring/buildout.cfg (original) +++ z3/NudgeNudge/branches/indexes-refactoring/buildout.cfg Thu Apr 19 13:22:53 2007 @@ -1,6 +1,6 @@ [buildout] parts = data instance server test -develop = . deliverance zope.paste +develop = . deliverance zope.paste grok [zope3] location = /usr/local/Zope-3.3.1 From philikon at codespeak.net Thu Apr 19 13:23:47 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Thu, 19 Apr 2007 13:23:47 +0200 (CEST) Subject: [z3-checkins] r42167 - z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge Message-ID: <20070419112347.BD0CC80A2@code0.codespeak.net> Author: philikon Date: Thu Apr 19 13:23:47 2007 New Revision: 42167 Modified: z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py Log: Use grok.Indexes to define indexes. Sadly, zc.catalog's indexes aren't available so we'll have to use the crummy field index. Modified: z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py ============================================================================== --- z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py (original) +++ z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py Thu Apr 19 13:23:47 2007 @@ -1,4 +1,5 @@ import grok +from grok import index from zope import schema, component, interface from zope.app.intid import IntIds from zope.app.intid.interfaces import IIntIds @@ -23,10 +24,6 @@ grok.define_permission('nudge.EditReview') grok.define_permission('nudge.DeleteReview') -def setup_catalog(catalog): - catalog['package_name'] = ValueIndex('package_name', IReview, False) - catalog['author'] = ValueIndex('author', IReview, False) - def setup_pau(pau): pau['principals'] = PrincipalFolder('nudge.principals.') pau.authenticatorPlugins = ('principals',) @@ -41,14 +38,19 @@ return factory class NudgeNudge(grok.Application, grok.Container): - grok.local_utility(IntIds, IIntIds) # needed for the catalog - grok.local_utility(Catalog, ICatalog, setup=setup_catalog) grok.local_utility(PluggableAuthentication, IAuthentication, setup=setup_pau) grok.local_utility(role_factory(u'Nudge Reviewers'), IRole, name='nudge.Reviewers', name_in_container='nudge.Reviewers') +class ReviewIndexes(grok.Indexes): + grok.application(NudgeNudge) + grok.context(IReview) + + package_name = index.Field() + author = index.Field() + @grok.subscribe(NudgeNudge, grok.IObjectAddedEvent) def grant_permissions(app, event): role_manager = IRolePermissionManager(app) @@ -60,7 +62,7 @@ self.results = [] if package: catalog = component.getUtility(ICatalog) - query = {'any_of': (package,)} + query = (package, package) self.results = catalog.searchResults(package_name=query) class CreateReview(grok.AddForm): @@ -72,7 +74,7 @@ @grok.action('Create') def create(self, **kw): r = Review() - self.applyData(r, **kw) + self.applyChanges(r, **kw) base = name = kw['package_name'] + '-' + kw['version'] count = 0 From ianb at codespeak.net Thu Apr 19 18:50:03 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 19 Apr 2007 18:50:03 +0200 (CEST) Subject: [z3-checkins] r42180 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070419165003.1C64280A5@code0.codespeak.net> Author: ianb Date: Thu Apr 19 18:50:02 2007 New Revision: 42180 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: Set X-Script-Name Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Thu Apr 19 18:50:02 2007 @@ -129,6 +129,8 @@ remote_uri = uritemplate.sub_vars(remote_uri, vars) environ['dvhoster.remote_uri'] = remote_uri + if environ['SCRIPT_NAME']: + environ['HTTP_X_SCRIPT_NAME'] = environ['SCRIPT_NAME'] should_theme_uri = True if self.should_theme_uri: From philikon at codespeak.net Thu Apr 19 18:57:52 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Thu, 19 Apr 2007 18:57:52 +0200 (CEST) Subject: [z3-checkins] r42181 - z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge Message-ID: <20070419165752.B44F080A9@code0.codespeak.net> Author: philikon Date: Thu Apr 19 18:57:52 2007 New Revision: 42181 Modified: z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py Log: remove unused imports Modified: z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py ============================================================================== --- z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py (original) +++ z3/NudgeNudge/branches/indexes-refactoring/src/nudgenudge/app.py Thu Apr 19 18:57:52 2007 @@ -1,9 +1,6 @@ import grok from grok import index from zope import schema, component, interface -from zope.app.intid import IntIds -from zope.app.intid.interfaces import IIntIds -from zope.app.catalog.catalog import Catalog from zope.app.catalog.interfaces import ICatalog from zope.app.authentication import PluggableAuthentication from zope.app.authentication.principalfolder import (PrincipalFolder, @@ -15,8 +12,6 @@ from zope.app.securitypolicy.interfaces import IRolePermissionManager from zope.app.securitypolicy.role import LocalRole -from zc.catalog.catalogindex import ValueIndex - from nudgenudge.interfaces import IReview from nudgenudge.review import Review From ianb at codespeak.net Thu Apr 19 19:04:08 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Thu, 19 Apr 2007 19:04:08 +0200 (CEST) Subject: [z3-checkins] r42183 - z3/deliverance/trunk/deliverance Message-ID: <20070419170408.371FE80B3@code0.codespeak.net> Author: ianb Date: Thu Apr 19 19:04:07 2007 New Revision: 42183 Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py Log: Don't theme non-200 responses Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py ============================================================================== --- z3/deliverance/trunk/deliverance/wsgimiddleware.py (original) +++ z3/deliverance/trunk/deliverance/wsgimiddleware.py Thu Apr 19 19:04:07 2007 @@ -176,8 +176,12 @@ status, headers, body = self.rebuild_check(environ, start_response) - # non-html responses, or rebuild is not necessary: bail out if status is None: + # non-html responses, or rebuild is not necessary: bail out + return body + if not status.startswith('200'): + # any non-200 response shouldn't be themed... + start_response(status, headers) return body # perform actual themeing From ltucker at codespeak.net Fri Apr 27 21:24:40 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 27 Apr 2007 21:24:40 +0200 (CEST) Subject: [z3-checkins] r42381 - z3/deliverance/trunk/deliverance Message-ID: <20070427192440.33D158069@code0.codespeak.net> Author: ltucker Date: Fri Apr 27 21:24:39 2007 New Revision: 42381 Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py Log: do not pass via header in external sub-requests to avoid appearing to be a loop if requesting upstream Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py ============================================================================== --- z3/deliverance/trunk/deliverance/wsgimiddleware.py (original) +++ z3/deliverance/trunk/deliverance/wsgimiddleware.py Fri Apr 27 21:24:39 2007 @@ -372,8 +372,19 @@ return InternalResourceFetcher(environ, uri[len(internalBaseURL):], self.app) else: - return ExternalResourceFetcher(environ, uri) + out_environ = self.cleaned_environ(environ) + return ExternalResourceFetcher(out_environ, uri) + def cleaned_environ(self, environ): + """ + this implements the policy for manipulating + outbound environments. + """ + cleaned = environ.copy() + if 'HTTP_VIA' in cleaned: + del cleaned['HTTP_VIA'] + return cleaned + def get_resource_uris(self, rules): """ From ltucker at codespeak.net Fri Apr 27 21:56:40 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 27 Apr 2007 21:56:40 +0200 (CEST) Subject: [z3-checkins] r42382 - z3/deliverance/trunk/deliverance Message-ID: <20070427195640.0EB80806D@code0.codespeak.net> Author: ltucker Date: Fri Apr 27 21:56:39 2007 New Revision: 42382 Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py Log: whitespace Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py ============================================================================== --- z3/deliverance/trunk/deliverance/wsgimiddleware.py (original) +++ z3/deliverance/trunk/deliverance/wsgimiddleware.py Fri Apr 27 21:56:39 2007 @@ -381,7 +381,7 @@ outbound environments. """ cleaned = environ.copy() - if 'HTTP_VIA' in cleaned: + if 'HTTP_VIA' in cleaned: del cleaned['HTTP_VIA'] return cleaned From kobold at codespeak.net Thu May 3 21:20:03 2007 From: kobold at codespeak.net (kobold at codespeak.net) Date: Thu, 3 May 2007 21:20:03 +0200 (CEST) Subject: [z3-checkins] r42645 - z3/sqlos/trunk/src/sqlos Message-ID: <20070503192003.EB3788075@code0.codespeak.net> Author: kobold Date: Thu May 3 21:20:03 2007 New Revision: 42645 Modified: z3/sqlos/trunk/src/sqlos/_transaction.py z3/sqlos/trunk/src/sqlos/connection.py Log: Fixed a threading issue: with high volumes, sqlos still does not scale well. Let's try with a local cache of connection, instead of a global one, and using a different approach at transaction boundaries: remove the object from the cache only for the current thread. Modified: z3/sqlos/trunk/src/sqlos/_transaction.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/_transaction.py (original) +++ z3/sqlos/trunk/src/sqlos/_transaction.py Thu May 3 21:20:03 2007 @@ -21,7 +21,7 @@ from sqlobject import SQLObjectNotFound from sqlos.interfaces import ISQLObject -from sqlos.connection import connCache + def beforeCommitHook(obj): """Called before transactions are started. @@ -37,6 +37,7 @@ if not obj.sqlmeta._obsolete: obj.sync() + def expireSQLObject(obj): """Expire the SQLObject. @@ -56,13 +57,10 @@ >>> expireSQLObject(obj) """ - # Sometimes, the object doesn't have the id: in this case, ignore it. + # Expire object values. The transaction has either been aborted or + # committed. Sometimes, the object doesn't have the id: in this case, + # ignore it. if hasattr(obj, 'id'): - for connection in connCache.values(): - connection.cache.expire(obj.id, obj.__class__) - - # Expire object values. The transaction has either been aborted or - # committed. obj.expire() Modified: z3/sqlos/trunk/src/sqlos/connection.py ============================================================================== --- z3/sqlos/trunk/src/sqlos/connection.py (original) +++ z3/sqlos/trunk/src/sqlos/connection.py Thu May 3 21:20:03 2007 @@ -21,12 +21,12 @@ """ __metaclass__ = type -import thread import warnings from zope.app import zapi from zope.component import ComponentLookupError, getUtility from zope.rdb.interfaces import IZopeDatabaseAdapter +from zope.thread import local from sqlos.interfaces import IZopeSQLConnection, IConnectionName @@ -68,14 +68,12 @@ # Connection cache, one per thread, a-la Transaction. # This code was heavily based on ZODB.Transaction -connCache = {} +connCache = local() def getConnection(context, name): global connCache - tid = thread.get_ident() - key = (tid, name) - if not connCache.get(key): + if not hasattr(connCache, 'connection'): newconn = zapi.queryUtility(IZopeDatabaseAdapter, name, default=None, context=context) @@ -85,26 +83,21 @@ return None conn = IZopeSQLConnection(newconn()) if conn.supportTransactions: - connCache[key] = conn.transaction() + connCache.connection = conn.transaction() else: # At least MySQL does not support transactions - connCache[key] = conn + connCache.connection = conn - return connCache[key] + return connCache.connection def releaseConnection(name): global connCache - tid = thread.get_ident() - key = (tid, name) - if connCache.has_key(key): - connCache[key].close() - del connCache[key] + if hasattr(connCache, 'connection'): + connCache.connection.close() + del connCache.connection def clearCacheSubscriber(*args): """A subscriber to clear the connection cache at site boundaries.""" - tid = thread.get_ident() - for name in connCache.keys(): - if name[0] != tid: - continue - connCache[name].cache.clear() + if hasattr(connCache, 'connection'): + connCache.connection.cache.clear() From ltucker at codespeak.net Mon May 7 17:17:20 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Mon, 7 May 2007 17:17:20 +0200 (CEST) Subject: [z3-checkins] r42810 - z3/deliverance/trunk/deliverance Message-ID: <20070507151720.9D6498067@code0.codespeak.net> Author: ltucker Date: Mon May 7 17:17:20 2007 New Revision: 42810 Modified: z3/deliverance/trunk/deliverance/resource_fetcher.py z3/deliverance/trunk/deliverance/wsgimiddleware.py Log: SCRIPT_INFO -> SCRIPT_NAME, unquote remote urls, fix caching (revert r40855, must intercept 304s for content) Modified: z3/deliverance/trunk/deliverance/resource_fetcher.py ============================================================================== --- z3/deliverance/trunk/deliverance/resource_fetcher.py (original) +++ z3/deliverance/trunk/deliverance/resource_fetcher.py Mon May 7 17:17:20 2007 @@ -84,7 +84,7 @@ uri_parts = urlparse.urlparse(self.uri) self.environ['PATH_INFO'] = uri_parts[2] - self.environ['SCRIPT_INFO'] = '' + self.environ['SCRIPT_NAME'] = '' self.environ['wsgi.scheme'] = 'file' if len(uri_parts[4]) > 0: self.environ['QUERY_STRING'] = uri_parts[4] + '¬heme' @@ -146,10 +146,10 @@ self.environ['wsgi.url_scheme'] = loc[0] self.environ['wsgi.version'] = (1, 0) self.environ['HTTP_HOST'] = loc[1] - self.environ['PATH_INFO'] = loc[2] + self.environ['PATH_INFO'] = urllib.unquote(loc[2]) self.environ['QUERY_STRING'] = loc[3] - self.environ['SCRIPT_INFO'] = '' + self.environ['SCRIPT_NAME'] = '' #if loc[0].find(':') != -1: # self.environ['SERVER_NAME'],self.environ['SERVER_PORT'] = loc[0].split(':') Modified: z3/deliverance/trunk/deliverance/wsgimiddleware.py ============================================================================== --- z3/deliverance/trunk/deliverance/wsgimiddleware.py (original) +++ z3/deliverance/trunk/deliverance/wsgimiddleware.py Mon May 7 17:17:20 2007 @@ -206,7 +206,7 @@ """ type = header_value(headers, 'content-type') if type is None: - return False # yerg, 304s can have no content-type + return True # yerg, 304s can have no content-type return type.startswith('text/html') or type.startswith('application/xhtml+xml') def filter_body(self, environ, body): From ltucker at codespeak.net Tue May 15 00:35:12 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Tue, 15 May 2007 00:35:12 +0200 (CEST) Subject: [z3-checkins] r43393 - in z3/deliverance/trunk/deliverance: . test-data/aggregate2 Message-ID: <20070514223512.41966807A@code0.codespeak.net> Author: ltucker Date: Tue May 15 00:35:11 2007 New Revision: 43393 Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/ z3/deliverance/trunk/deliverance/test-data/aggregate2/expected.html z3/deliverance/trunk/deliverance/test-data/aggregate2/index.html z3/deliverance/trunk/deliverance/test-data/aggregate2/irrelevant.html z3/deliverance/trunk/deliverance/test-data/aggregate2/rules.xml z3/deliverance/trunk/deliverance/test-data/aggregate2/theme.html Modified: z3/deliverance/trunk/deliverance/test_wsgi.py Log: checking in failing test for xpath union and aggregation error Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/expected.html ============================================================================== --- (empty file) +++ z3/deliverance/trunk/deliverance/test-data/aggregate2/expected.html Tue May 15 00:35:11 2007 @@ -0,0 +1,6 @@ + + +
+
+ + \ No newline at end of file Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/index.html ============================================================================== --- (empty file) +++ z3/deliverance/trunk/deliverance/test-data/aggregate2/index.html Tue May 15 00:35:11 2007 @@ -0,0 +1,8 @@ + + + + +
+
+ + \ No newline at end of file Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/irrelevant.html ============================================================================== --- (empty file) +++ z3/deliverance/trunk/deliverance/test-data/aggregate2/irrelevant.html Tue May 15 00:35:11 2007 @@ -0,0 +1,12 @@ + + + + +
+ I'm irrelevant +
+ +
+
+ + \ No newline at end of file Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/rules.xml ============================================================================== --- (empty file) +++ z3/deliverance/trunk/deliverance/test-data/aggregate2/rules.xml Tue May 15 00:35:11 2007 @@ -0,0 +1,6 @@ + + + + + + Added: z3/deliverance/trunk/deliverance/test-data/aggregate2/theme.html ============================================================================== --- (empty file) +++ z3/deliverance/trunk/deliverance/test-data/aggregate2/theme.html Tue May 15 00:35:11 2007 @@ -0,0 +1,4 @@ + + + + \ No newline at end of file Modified: z3/deliverance/trunk/deliverance/test_wsgi.py ============================================================================== --- z3/deliverance/trunk/deliverance/test_wsgi.py (original) +++ z3/deliverance/trunk/deliverance/test_wsgi.py Tue May 15 00:35:11 2007 @@ -20,6 +20,7 @@ ajax_data = os.path.join(os.path.dirname(__file__), 'test-data', 'ajax') url_data = os.path.join(os.path.dirname(__file__), 'test-data', 'wsgiurl') aggregate_data = os.path.join(os.path.dirname(__file__), 'test-data', 'aggregate') +aggregate2_data = os.path.join(os.path.dirname(__file__), 'test-data', 'aggregate2') static_app = StaticURLParser(static_data) tasktracker_app = StaticURLParser(tasktracker_data) @@ -29,6 +30,7 @@ ajax_app = StaticURLParser(ajax_data) url_app = StaticURLParser(url_data) aggregate_app = StaticURLParser(aggregate_data) +aggregate2_app = StaticURLParser(aggregate2_data) @@ -155,6 +157,14 @@ res2 = app.get('/expected.html?notheme') html_string_compare(res.body, res2.body) +def do_aggregate2(renderer_type, name): + wsgi_app = DeliveranceMiddleware(aggregate2_app, 'theme.html', 'rules.xml', + renderer_type) + app = TestApp(wsgi_app) + res = app.get('/index.html') + res2 = app.get('/expected.html?notheme') + html_string_compare(res.body, res2.body) + def do_cache(renderer_type, name): # XXX this should be busted up into multiple tests I spose @@ -272,7 +282,7 @@ RENDERER_TYPES = ['py', 'xslt'] -TEST_FUNCS = [ do_url, do_basic, do_text, do_tasktracker, do_xinclude, do_with_spaces, do_nycsr, do_necoro, do_guidesearch, do_ajax, do_aggregate, do_cache ] +TEST_FUNCS = [ do_url, do_basic, do_text, do_tasktracker, do_xinclude, do_with_spaces, do_nycsr, do_necoro, do_guidesearch, do_ajax, do_aggregate, do_aggregate2, do_cache ] def test_all(): for renderer_type in RENDERER_TYPES: for test_func in TEST_FUNCS: From z3-checkins at codespeak.net Sun May 27 01:52:52 2007 From: z3-checkins at codespeak.net (Investor Helena) Date: Sun, 27 May 2007 01:52:52 +0200 (CEST) Subject: [z3-checkins] Daily News 8495017294 Message-ID: <20070527025421.327163.qmail@er1esacakd.adsl.datanet.hu> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/z3-checkins/attachments/20070527/ddbeb31e/attachment.htm From philikon at codespeak.net Tue May 29 05:53:46 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 05:53:46 +0200 (CEST) Subject: [z3-checkins] r43828 - z3/NudgeNudge/trunk/src/nudgenudge/macro_templates Message-ID: <20070529035346.D96328082@code0.codespeak.net> Author: philikon Date: Tue May 29 05:53:45 2007 New Revision: 43828 Modified: z3/NudgeNudge/trunk/src/nudgenudge/macro_templates/master.pt Log: Use grok's new View.application_url() method to compute URLs relative to the nearest Application object Modified: z3/NudgeNudge/trunk/src/nudgenudge/macro_templates/master.pt ============================================================================== --- z3/NudgeNudge/trunk/src/nudgenudge/macro_templates/master.pt (original) +++ z3/NudgeNudge/trunk/src/nudgenudge/macro_templates/master.pt Tue May 29 05:53:45 2007 @@ -8,17 +8,17 @@
  • Nudge Nudge + tal:attributes="href view/application_url">Nudge Nudge
    • Write a review
    • + tal:attributes="href string:${view/application_url}/createreview">Write a review
-

+

Nudge Nudge

@@ -39,13 +39,13 @@
  • + tal:attributes="href string:${view/application_url}/login"> Log in
  • + tal:attributes="href string:${view/application_url}/signup"> Register
  • @@ -55,7 +55,7 @@
    • + tal:attributes="href string:${view/application_url}/logout.html"> Log out
    • From philikon at codespeak.net Tue May 29 05:54:16 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 05:54:16 +0200 (CEST) Subject: [z3-checkins] r43829 - z3/NudgeNudge/trunk Message-ID: <20070529035416.88FE58082@code0.codespeak.net> Author: philikon Date: Tue May 29 05:54:16 2007 New Revision: 43829 Modified: z3/NudgeNudge/trunk/buildout.cfg Log: Use Zope 3.3-friendly version of zc.catalog Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Tue May 29 05:54:16 2007 @@ -19,7 +19,7 @@ database = data eggs = setuptools grok - zc.catalog + zc.catalog==1.1.1 nudgenudge recipe = zc.recipe.zope3instance user = grok:grok From philikon at codespeak.net Tue May 29 06:11:21 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 06:11:21 +0200 (CEST) Subject: [z3-checkins] r43830 - z3/NudgeNudge/trunk/src/nudgenudge Message-ID: <20070529041121.9888D808D@code0.codespeak.net> Author: philikon Date: Tue May 29 06:11:21 2007 New Revision: 43830 Added: z3/NudgeNudge/trunk/src/nudgenudge/form.pt (contents, props changed) Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py z3/NudgeNudge/trunk/src/nudgenudge/review.py Log: Add a form template that uses the ZPT macro. THat way forms can be nicely styled using Deliverance Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py ============================================================================== --- z3/NudgeNudge/trunk/src/nudgenudge/app.py (original) +++ z3/NudgeNudge/trunk/src/nudgenudge/app.py Tue May 29 06:11:21 2007 @@ -67,6 +67,7 @@ grok.require('nudge.AddReview') form_fields = grok.AutoFields(IReview) + template = grok.PageTemplateFile('form.pt') #form_fields['package_name'].for_display = True # XXX doesn't work??? @grok.action('Create') Added: z3/NudgeNudge/trunk/src/nudgenudge/form.pt ============================================================================== --- (empty file) +++ z3/NudgeNudge/trunk/src/nudgenudge/form.pt Tue May 29 06:11:21 2007 @@ -0,0 +1,37 @@ + + +
      +
      + +

      Edit something

      + +
      Status
      + +
      +
      + +
      + +
      Error
      + +
      + +
      +
      + + + + + +
      +
      + + Modified: z3/NudgeNudge/trunk/src/nudgenudge/review.py ============================================================================== --- z3/NudgeNudge/trunk/src/nudgenudge/review.py (original) +++ z3/NudgeNudge/trunk/src/nudgenudge/review.py Tue May 29 06:11:21 2007 @@ -47,3 +47,4 @@ class Edit(grok.EditForm): grok.require('nudge.EditReview') form_fields = grok.AutoFields(IReview) + template = grok.PageTemplateFile('form.pt') From philikon at codespeak.net Tue May 29 07:16:32 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 07:16:32 +0200 (CEST) Subject: [z3-checkins] r43831 - z3/NudgeNudge/trunk Message-ID: <20070529051632.801578080@code0.codespeak.net> Author: philikon Date: Tue May 29 07:16:31 2007 New Revision: 43831 Modified: z3/NudgeNudge/trunk/ (props changed) z3/NudgeNudge/trunk/buildout.cfg Log: zope.paste was finally released as a new version, now with proper PasteDeploy support. Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Tue May 29 07:16:31 2007 @@ -1,6 +1,6 @@ [buildout] parts = data instance server test -develop = . deliverance zope.paste +develop = . deliverance [zope3] location = /usr/local/Zope-3.3.1 From philikon at codespeak.net Tue May 29 07:33:45 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 07:33:45 +0200 (CEST) Subject: [z3-checkins] r43832 - z3/NudgeNudge/trunk Message-ID: <20070529053345.397378082@code0.codespeak.net> Author: philikon Date: Tue May 29 07:33:45 2007 New Revision: 43832 Modified: z3/NudgeNudge/trunk/nudge.ini Log: Add an example of how to serve using twisted Modified: z3/NudgeNudge/trunk/nudge.ini ============================================================================== --- z3/NudgeNudge/trunk/nudge.ini (original) +++ z3/NudgeNudge/trunk/nudge.ini Tue May 29 07:33:45 2007 @@ -18,3 +18,8 @@ use = egg:PasteScript#wsgiutils host = 127.0.0.1 port = 8080 + +[server:twisted] +use = egg:PasteScript#twisted +host = 127.0.0.1 +port = 8080 From philikon at codespeak.net Tue May 29 07:34:15 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Tue, 29 May 2007 07:34:15 +0200 (CEST) Subject: [z3-checkins] r43833 - z3/NudgeNudge/trunk Message-ID: <20070529053415.7B1BD8082@code0.codespeak.net> Author: philikon Date: Tue May 29 07:34:15 2007 New Revision: 43833 Modified: z3/NudgeNudge/trunk/nudge.ini Log: Add explanatory comment Modified: z3/NudgeNudge/trunk/nudge.ini ============================================================================== --- z3/NudgeNudge/trunk/nudge.ini (original) +++ z3/NudgeNudge/trunk/nudge.ini Tue May 29 07:34:15 2007 @@ -19,6 +19,7 @@ host = 127.0.0.1 port = 8080 +# Here's an example of how to serve usinig twisted.web2 [server:twisted] use = egg:PasteScript#twisted host = 127.0.0.1 From philikon at codespeak.net Sat Jun 2 15:32:07 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sat, 2 Jun 2007 15:32:07 +0200 (CEST) Subject: [z3-checkins] r43992 - z3/NudgeNudge/trunk/src/nudgenudge Message-ID: <20070602133207.5956280B4@code0.codespeak.net> Author: philikon Date: Sat Jun 2 15:31:59 2007 New Revision: 43992 Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py Log: Merge the 'indexes-refactoring' branch, even though grok doesn't expose zc.catalog's ValueIndex yet (using FieldIndex for now). Modified: z3/NudgeNudge/trunk/src/nudgenudge/app.py ============================================================================== --- z3/NudgeNudge/trunk/src/nudgenudge/app.py (original) +++ z3/NudgeNudge/trunk/src/nudgenudge/app.py Sat Jun 2 15:31:59 2007 @@ -1,8 +1,6 @@ import grok +from grok import index from zope import schema, component, interface -from zope.app.intid import IntIds -from zope.app.intid.interfaces import IIntIds -from zope.app.catalog.catalog import Catalog from zope.app.catalog.interfaces import ICatalog from zope.app.authentication import PluggableAuthentication from zope.app.authentication.principalfolder import (PrincipalFolder, @@ -14,8 +12,6 @@ from zope.app.securitypolicy.interfaces import IRolePermissionManager from zope.app.securitypolicy.role import LocalRole -from zc.catalog.catalogindex import ValueIndex - from nudgenudge.interfaces import IReview from nudgenudge.review import Review @@ -23,10 +19,6 @@ grok.define_permission('nudge.EditReview') grok.define_permission('nudge.DeleteReview') -def setup_catalog(catalog): - catalog['package_name'] = ValueIndex('package_name', IReview, False) - catalog['author'] = ValueIndex('author', IReview, False) - def setup_pau(pau): pau['principals'] = PrincipalFolder('nudge.principals.') pau.authenticatorPlugins = ('principals',) @@ -41,14 +33,20 @@ return factory class NudgeNudge(grok.Application, grok.Container): - grok.local_utility(IntIds, IIntIds) # needed for the catalog - grok.local_utility(Catalog, ICatalog, setup=setup_catalog) grok.local_utility(PluggableAuthentication, IAuthentication, setup=setup_pau) grok.local_utility(role_factory(u'Nudge Reviewers'), IRole, name='nudge.Reviewers', name_in_container='nudge.Reviewers') +class ReviewIndexes(grok.Indexes): + grok.site(NudgeNudge) + grok.context(IReview) + + # TODO would prefer to use zc.catalog's ValueIndex here + package_name = index.Field() + author = index.Field() + @grok.subscribe(NudgeNudge, grok.IObjectAddedEvent) def grant_permissions(app, event): role_manager = IRolePermissionManager(app) @@ -60,7 +58,8 @@ self.results = [] if package: catalog = component.getUtility(ICatalog) - query = {'any_of': (package,)} + # TODO zc.catalog's ValueIndex has a nicer query interface + query = (package, package) self.results = catalog.searchResults(package_name=query) class CreateReview(grok.AddForm): From philikon at codespeak.net Sat Jun 2 15:32:50 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sat, 2 Jun 2007 15:32:50 +0200 (CEST) Subject: [z3-checkins] r43993 - z3/NudgeNudge/branches/indexes-refactoring Message-ID: <20070602133250.3E25480B4@code0.codespeak.net> Author: philikon Date: Sat Jun 2 15:32:49 2007 New Revision: 43993 Removed: z3/NudgeNudge/branches/indexes-refactoring/ Log: Get rid of no longer needed branch From philikon at codespeak.net Sat Jun 2 17:00:14 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sat, 2 Jun 2007 17:00:14 +0200 (CEST) Subject: [z3-checkins] r43994 - z3/NudgeNudge/trunk Message-ID: <20070602150014.7376480C3@code0.codespeak.net> Author: philikon Date: Sat Jun 2 17:00:13 2007 New Revision: 43994 Modified: z3/NudgeNudge/trunk/setup.py Log: Fully eggify NudgeNudge by depending on Zope 3 eggs Modified: z3/NudgeNudge/trunk/setup.py ============================================================================== --- z3/NudgeNudge/trunk/setup.py (original) +++ z3/NudgeNudge/trunk/setup.py Sat Jun 2 17:00:13 2007 @@ -5,8 +5,6 @@ setup(name='NudgeNudge', version=version, description="", - long_description="""\ -""", # Get strings from http://www.python.org/pypi?%3Aaction=list_classifiers classifiers=[], keywords="", @@ -20,9 +18,13 @@ zip_safe=False, install_requires=['setuptools', 'grok', - # -*- Extra requirements: -*- + 'ZODB3', + 'zope.interface', + 'zope.schema', + 'zope.component', + 'zope.app.catalog', + 'zope.app.authentication', + 'zope.app.security', + 'zope.app.securitypolicy', ], - entry_points=""" - # -*- Entry points: -*- - """, ) From philikon at codespeak.net Sat Jun 2 17:01:24 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sat, 2 Jun 2007 17:01:24 +0200 (CEST) Subject: [z3-checkins] r43995 - in z3/NudgeNudge/trunk: . src/nudgenudge Message-ID: <20070602150124.B3FD480C3@code0.codespeak.net> Author: philikon Date: Sat Jun 2 17:01:24 2007 New Revision: 43995 Added: z3/NudgeNudge/trunk/src/nudgenudge/site.zcml (contents, props changed) Modified: z3/NudgeNudge/trunk/buildout.cfg z3/NudgeNudge/trunk/nudge.ini Log: The nudgenudge package now comes with a site.zcml that's used to run the app. Use the new recipes from zc.zope3recipes to create the Zope 3 instance (and change the PasteDeploy config to match the new paths). Modified: z3/NudgeNudge/trunk/buildout.cfg ============================================================================== --- z3/NudgeNudge/trunk/buildout.cfg (original) +++ z3/NudgeNudge/trunk/buildout.cfg Sat Jun 2 17:01:24 2007 @@ -1,13 +1,15 @@ [buildout] -parts = data instance server test +parts = app data instance server test develop = . deliverance +find-links = http://download.zope.org/distribution/ [zope3] -location = /usr/local/Zope-3.3.1 +# this dead chicken is needed by some other recipe(s) +location = [server] recipe = zc.recipe.egg -eggs = ${instance:eggs} +eggs = ${app:eggs} zope.paste PasteDeploy Deliverance @@ -15,46 +17,23 @@ WSGIUtils extra-paths = ${zope3:location}/lib/python -[instance] +[app] database = data eggs = setuptools grok - zc.catalog==1.1.1 - nudgenudge -recipe = zc.recipe.zope3instance -user = grok:grok -zcml = zope.annotation - zope.copypastemove - zope.formlib - zope.i18n-meta - zope.i18n.locales - zope.publisher - zope.security-meta - zope.size - zope.traversing - zope.traversing.browser - zope.app - zope.app-meta - zope.app.securitypolicy - zope.app.securitypolicy-meta - zope.app.authentication - zope.app.catalog - zope.app.intid - zope.app.keyreference - zope.app.session - zope.app.twisted - grok - grok-meta nudgenudge +recipe = zc.zope3recipes:app +site.zcml = [data] recipe = zc.recipe.filestorage +[instance] +recipe = zc.zope3recipes:instance +application = app +zope.conf = ${data:zconfig} + [test] -working-directory = parts/instance -eggs = nudgenudge recipe = zc.recipe.testrunner -extra-paths = ${zope3:location}/lib/python -defaults = ['--tests-pattern', '^f?tests$', - '-v' - ] +eggs = nudgenudge +defaults = ['--tests-pattern', '^f?tests$', '-v'] Modified: z3/NudgeNudge/trunk/nudge.ini ============================================================================== --- z3/NudgeNudge/trunk/nudge.ini (original) +++ z3/NudgeNudge/trunk/nudge.ini Sat Jun 2 17:01:24 2007 @@ -11,7 +11,7 @@ [app:zope] use = egg:zope.paste -site_definition = parts/instance/etc/site.zcml +site_definition = parts/app/site.zcml file_storage = parts/data/Data.fs [server:main] Added: z3/NudgeNudge/trunk/src/nudgenudge/site.zcml ============================================================================== --- (empty file) +++ z3/NudgeNudge/trunk/src/nudgenudge/site.zcml Sat Jun 2 17:01:24 2007 @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From philikon at codespeak.net Sun Jun 3 00:22:34 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 00:22:34 +0200 (CEST) Subject: [z3-checkins] r43999 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070602222234.36A9C80CA@code0.codespeak.net> Author: philikon Date: Sun Jun 3 00:22:33 2007 New Revision: 43999 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/ - copied from r43998, z3/NudgeNudge/trunk/ Log: Branch for extra files that are in my Zope on a Paste presentation (DZUG, EuroPython) From z3-checkins at codespeak.net Sun Jun 3 11:47:43 2007 From: z3-checkins at codespeak.net (z3-checkins at codespeak.net) Date: Sun, 3 Jun 2007 11:47:43 +0200 (CEST) Subject: [z3-checkins] Summer Bazaar Message-ID: <20070603114816.5401.qmail@ppp-58.9.147.129.revip2.asianet.co.th> An HTML attachment was scrubbed... URL: http://codespeak.net/pipermail/z3-checkins/attachments/20070603/f7c1842e/attachment.htm From philikon at codespeak.net Sun Jun 3 14:25:23 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 14:25:23 +0200 (CEST) Subject: [z3-checkins] r44001 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070603122523.5F76E80C4@code0.codespeak.net> Author: philikon Date: Sun Jun 3 14:25:21 2007 New Revision: 44001 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/debug.ini z3/NudgeNudge/branches/zope-on-a-paste-demos/logging.ini z3/NudgeNudge/branches/zope-on-a-paste-demos/simple.ini Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.ini Log: A few alternate PasteDeploy configurations for demonstration Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/debug.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/debug.ini Sun Jun 3 14:25:21 2007 @@ -0,0 +1,17 @@ +[filter-app:main] +use = egg:Paste#translogger +next = evalexception + +[filter-app:evalexception] +use = egg:z3c.evalexception +next = zope + +[app:zope] +use = egg:zope.paste +site_definition = parts/app/site.zcml +file_storage = parts/data/Data.fs + +[server:main] +use = egg:PasteScript#wsgiutils +host = 127.0.0.1 +port = 8080 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/logging.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/logging.ini Sun Jun 3 14:25:21 2007 @@ -0,0 +1,13 @@ +[filter-app:main] +use = egg:Paste#translogger +next = zope + +[app:zope] +use = egg:zope.paste +site_definition = parts/app/site.zcml +file_storage = parts/data/Data.fs + +[server:main] +use = egg:PasteScript#wsgiutils +host = 127.0.0.1 +port = 8080 Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.ini ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.ini (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.ini Sun Jun 3 14:25:21 2007 @@ -18,9 +18,3 @@ use = egg:PasteScript#wsgiutils host = 127.0.0.1 port = 8080 - -# Here's an example of how to serve usinig twisted.web2 -[server:twisted] -use = egg:PasteScript#twisted -host = 127.0.0.1 -port = 8080 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/simple.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/simple.ini Sun Jun 3 14:25:21 2007 @@ -0,0 +1,11 @@ +[app:main] +use = egg:zope.paste +site_definition = parts/app/site.zcml +file_storage = parts/data/Data.fs + +[server:main] +use = egg:PasteScript#wsgiutils +#use = egg:PasteScript#twisted +#use = egg:zope.server +host = 127.0.0.1 +port = 8080 From philikon at codespeak.net Sun Jun 3 14:25:42 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 14:25:42 +0200 (CEST) Subject: [z3-checkins] r44002 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070603122542.10BC280CE@code0.codespeak.net> Author: philikon Date: Sun Jun 3 14:25:42 2007 New Revision: 44002 Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Log: We need z3c.evalexception Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Sun Jun 3 14:25:42 2007 @@ -12,6 +12,7 @@ eggs = ${app:eggs} zope.paste PasteDeploy + z3c.evalexception Deliverance PasteScript WSGIUtils From philikon at codespeak.net Sun Jun 3 14:26:14 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 14:26:14 +0200 (CEST) Subject: [z3-checkins] r44003 - z3/NudgeNudge/branches/zope-on-a-paste-demos/src/nudgenudge Message-ID: <20070603122614.1F3AE80C4@code0.codespeak.net> Author: philikon Date: Sun Jun 3 14:26:13 2007 New Revision: 44003 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/src/nudgenudge/error.py (contents, props changed) Log: View that provokes an error --- for debugging Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/src/nudgenudge/error.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/src/nudgenudge/error.py Sun Jun 3 14:26:13 2007 @@ -0,0 +1,8 @@ +import grok +import zope.interface + +class Error(grok.View): + grok.context(zope.interface.Interface) + + def render(self): + raise ValueError("This is an exception I want you to debug.") From philikon at codespeak.net Sun Jun 3 14:26:36 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 14:26:36 +0200 (CEST) Subject: [z3-checkins] r44004 - in z3/NudgeNudge/branches/zope-on-a-paste-demos: . logs Message-ID: <20070603122636.0347B80C4@code0.codespeak.net> Author: philikon Date: Sun Jun 3 14:26:36 2007 New Revision: 44004 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf z3/NudgeNudge/branches/zope-on-a-paste-demos/logs/ z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Log: Apache mod_python and mod_wsgi conf files Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf Sun Jun 3 14:26:36 2007 @@ -0,0 +1,98 @@ +ServerRoot "/Users/philipp/dev/NudgeNudge" +ServerName 127.0.0.1 +Listen 127.0.0.1:8080 + +LoadModule authn_file_module /opt/local/apache2/modules/mod_authn_file.so +LoadModule authn_dbm_module /opt/local/apache2/modules/mod_authn_dbm.so +LoadModule authn_anon_module /opt/local/apache2/modules/mod_authn_anon.so +LoadModule authn_dbd_module /opt/local/apache2/modules/mod_authn_dbd.so +LoadModule authn_default_module /opt/local/apache2/modules/mod_authn_default.so +LoadModule authz_host_module /opt/local/apache2/modules/mod_authz_host.so +LoadModule authz_groupfile_module /opt/local/apache2/modules/mod_authz_groupfile.so +LoadModule authz_user_module /opt/local/apache2/modules/mod_authz_user.so +LoadModule authz_dbm_module /opt/local/apache2/modules/mod_authz_dbm.so +LoadModule authz_owner_module /opt/local/apache2/modules/mod_authz_owner.so +LoadModule authz_default_module /opt/local/apache2/modules/mod_authz_default.so +LoadModule auth_basic_module /opt/local/apache2/modules/mod_auth_basic.so +LoadModule auth_digest_module /opt/local/apache2/modules/mod_auth_digest.so +LoadModule file_cache_module /opt/local/apache2/modules/mod_file_cache.so +LoadModule cache_module /opt/local/apache2/modules/mod_cache.so +LoadModule disk_cache_module /opt/local/apache2/modules/mod_disk_cache.so +LoadModule mem_cache_module /opt/local/apache2/modules/mod_mem_cache.so +LoadModule dbd_module /opt/local/apache2/modules/mod_dbd.so +LoadModule dumpio_module /opt/local/apache2/modules/mod_dumpio.so +LoadModule ext_filter_module /opt/local/apache2/modules/mod_ext_filter.so +LoadModule include_module /opt/local/apache2/modules/mod_include.so +LoadModule filter_module /opt/local/apache2/modules/mod_filter.so +LoadModule deflate_module /opt/local/apache2/modules/mod_deflate.so +LoadModule log_config_module /opt/local/apache2/modules/mod_log_config.so +LoadModule log_forensic_module /opt/local/apache2/modules/mod_log_forensic.so +LoadModule logio_module /opt/local/apache2/modules/mod_logio.so +LoadModule env_module /opt/local/apache2/modules/mod_env.so +LoadModule mime_magic_module /opt/local/apache2/modules/mod_mime_magic.so +LoadModule cern_meta_module /opt/local/apache2/modules/mod_cern_meta.so +LoadModule expires_module /opt/local/apache2/modules/mod_expires.so +LoadModule headers_module /opt/local/apache2/modules/mod_headers.so +LoadModule ident_module /opt/local/apache2/modules/mod_ident.so +LoadModule usertrack_module /opt/local/apache2/modules/mod_usertrack.so +#LoadModule unique_id_module /opt/local/apache2/modules/mod_unique_id.so +LoadModule setenvif_module /opt/local/apache2/modules/mod_setenvif.so +LoadModule version_module /opt/local/apache2/modules/mod_version.so +LoadModule proxy_module /opt/local/apache2/modules/mod_proxy.so +LoadModule proxy_connect_module /opt/local/apache2/modules/mod_proxy_connect.so +LoadModule proxy_ftp_module /opt/local/apache2/modules/mod_proxy_ftp.so +LoadModule proxy_http_module /opt/local/apache2/modules/mod_proxy_http.so +LoadModule proxy_ajp_module /opt/local/apache2/modules/mod_proxy_ajp.so +LoadModule proxy_balancer_module /opt/local/apache2/modules/mod_proxy_balancer.so +LoadModule ssl_module /opt/local/apache2/modules/mod_ssl.so +LoadModule mime_module /opt/local/apache2/modules/mod_mime.so +LoadModule dav_module /opt/local/apache2/modules/mod_dav.so +LoadModule status_module /opt/local/apache2/modules/mod_status.so +LoadModule autoindex_module /opt/local/apache2/modules/mod_autoindex.so +LoadModule asis_module /opt/local/apache2/modules/mod_asis.so +LoadModule info_module /opt/local/apache2/modules/mod_info.so +LoadModule cgi_module /opt/local/apache2/modules/mod_cgi.so +LoadModule dav_fs_module /opt/local/apache2/modules/mod_dav_fs.so +LoadModule vhost_alias_module /opt/local/apache2/modules/mod_vhost_alias.so +LoadModule negotiation_module /opt/local/apache2/modules/mod_negotiation.so +LoadModule dir_module /opt/local/apache2/modules/mod_dir.so +LoadModule imagemap_module /opt/local/apache2/modules/mod_imagemap.so +LoadModule actions_module /opt/local/apache2/modules/mod_actions.so +LoadModule speling_module /opt/local/apache2/modules/mod_speling.so +LoadModule userdir_module /opt/local/apache2/modules/mod_userdir.so +LoadModule alias_module /opt/local/apache2/modules/mod_alias.so +LoadModule rewrite_module /opt/local/apache2/modules/mod_rewrite.so + +LoadModule python_module /opt/local/apache2/modules/mod_python.so +LoadModule wsgi_module /opt/local/apache2/modules/mod_wsgi.so + +ServerAdmin philipp at weitershausen.de +DocumentRoot "/Users/philipp/dev/NudgeNudge" +MaxSpareServers 1 + + + Options FollowSymLinks + AllowOverride None + Order deny,allow + Deny from all + + + + Options Indexes FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + +DirectoryIndex index.html +ErrorLog logs/error_log +LogLevel warn +DefaultType text/plain + + + TypesConfig /opt/local/apache2/conf/mime.types + + +Include "mod_python.conf" + +#WSGISCriptAlias / /Users/philipp/dev/NudgeNudge/nudge.wsgi Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf Sun Jun 3 14:26:36 2007 @@ -0,0 +1,92 @@ + + SetHandler python-program + PythonHandler paste.modpython + PythonPath "[ '/Users/philipp/shared-eggs/setuptools-0.6c6-py2.4.egg', \ + '/Users/philipp/shared-eggs/grok-0.9dev_r75634-py2.4.egg', \ + '/Users/philipp/dev/NudgeNudge/src', \ + '/Users/philipp/shared-eggs/zope.paste-0.3-py2.4.egg', \ + '/Users/philipp/shared-eggs/PasteDeploy-1.3-py2.4.egg', \ + '/Users/philipp/dev/NudgeNudge/deliverance', \ + '/Users/philipp/shared-eggs/PasteScript-1.3.4-py2.4.egg', \ + '/Users/philipp/shared-eggs/WSGIUtils-0.7-py2.4.egg', \ + '/Users/philipp/shared-eggs/Paste-1.3-py2.4.egg', \ + '/Users/philipp/shared-eggs/WSGIFilter-0.1dev-py2.4.egg', \ + '/Users/philipp/shared-eggs/nose-0.9.3-py2.4.egg', \ + '/Users/philipp/shared-eggs/elementtree-1.2.6_20050316-py2.4.egg', \ + '/Users/philipp/shared-eggs/FormEncode-0.7.1-py2.4.egg', \ + '/Users/philipp/shared-eggs/lxml-1.3beta-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.app.server-3.4.0b1dev_r75388-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.twisted-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.wsgi-3.4.0b1dev_r75415-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.appsetup-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.interface-3.4.0b1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.app.securitypolicy-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.security-3.4.0a1_1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.authentication-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.catalog-3.4.0a2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.component-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.schema-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/ZODB3-3.8.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/simplejson-1.7.1-py2.4.egg', \ + '/Users/philipp/shared-eggs/HTTPEncode-0.1dev_r6484-py2.4.egg', \ + '/Users/philipp/shared-eggs/ZConfig-2.4a2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zdaemon-2.0a6-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.server-3.5.0a2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.publisher-3.4.0a1_1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.event-3.4.0b1.dev_r75122-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.configuration-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.publication-3.4.0a1_2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.applicationcontrol-3.4_dev_r73715-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.zapi-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.security-3.4.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.exceptions-3.4dev_r73107-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.copypastemove-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.container-3.4.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.traversing-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.folder-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.component-0.1dev_r74310-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.location-3.4.0b1.dev_r75152-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.i18nmessageid-3.4.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.i18n-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.form-0.1.dev_r74902-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.annotation-3.4.0b1.dev_r75758-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.deprecation-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.deferredimport-3.4dev-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.publisher-0.1dev_r73800-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.pagetemplate-3.4.0b1dev_r75616-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.i18n-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.dublincore-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.session-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.testing-3.4_r75911-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.lifecycleevent-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.index-3.4.0a2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.testing-3.4.0b1_r75826-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.intid-3.4.0a2-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.proxy-3.4.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/httplib2-0.3.0-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.exception-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.error-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.http-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.size-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.interface-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.thread-3.4dev_r73086-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/pytz-2007d-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.broken-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.filerepresentation-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.dottedname-3.4dev_r73113-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.cachedescriptors-3.4.0b1_r75830-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.datetime-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.formlib-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.hookable-3.4.0a1-py2.4-macosx-10.4-i386.egg', \ + '/Users/philipp/shared-eggs/zope.app.basicskin-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.pagetemplate-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.contenttype-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.tales-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.dependable-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.debug-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.app.keyreference-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/zodbcode-3.4.0b1dev_r75670-py2.4.egg', \ + '/Users/philipp/shared-eggs/zope.tal-3.4.0a1-py2.4.egg', \ + '/Users/philipp/shared-eggs/RestrictedPython-3.4dev_r73257-py2.4.egg'] + sys.path" + PythonOption paste.ini /Users/philipp/dev/NudgeNudge/nudge.ini + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Sun Jun 3 14:26:36 2007 @@ -0,0 +1,94 @@ +import sys +sys.path[0:0] = [ + '/Users/philipp/shared-eggs/setuptools-0.6c6-py2.4.egg', + '/Users/philipp/shared-eggs/grok-0.9dev_r75634-py2.4.egg', + '/Users/philipp/dev/NudgeNudge/src', + '/Users/philipp/shared-eggs/zope.paste-0.3-py2.4.egg', + '/Users/philipp/shared-eggs/PasteDeploy-1.3-py2.4.egg', + '/Users/philipp/dev/NudgeNudge/deliverance', + '/Users/philipp/shared-eggs/PasteScript-1.3.4-py2.4.egg', + '/Users/philipp/shared-eggs/WSGIUtils-0.7-py2.4.egg', + '/Users/philipp/shared-eggs/Paste-1.3-py2.4.egg', + '/Users/philipp/shared-eggs/WSGIFilter-0.1dev-py2.4.egg', + '/Users/philipp/shared-eggs/nose-0.9.3-py2.4.egg', + '/Users/philipp/shared-eggs/elementtree-1.2.6_20050316-py2.4.egg', + '/Users/philipp/shared-eggs/FormEncode-0.7.1-py2.4.egg', + '/Users/philipp/shared-eggs/lxml-1.3beta-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.app.server-3.4.0b1dev_r75388-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.twisted-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.wsgi-3.4.0b1dev_r75415-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.appsetup-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.interface-3.4.0b1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.app.securitypolicy-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.security-3.4.0a1_1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.authentication-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.catalog-3.4.0a2-py2.4.egg', + '/Users/philipp/shared-eggs/zope.component-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.schema-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/ZODB3-3.8.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/simplejson-1.7.1-py2.4.egg', + '/Users/philipp/shared-eggs/HTTPEncode-0.1dev_r6484-py2.4.egg', + '/Users/philipp/shared-eggs/ZConfig-2.4a2-py2.4.egg', + '/Users/philipp/shared-eggs/zdaemon-2.0a6-py2.4.egg', + '/Users/philipp/shared-eggs/zope.server-3.5.0a2-py2.4.egg', + '/Users/philipp/shared-eggs/zope.publisher-3.4.0a1_1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.event-3.4.0b1.dev_r75122-py2.4.egg', + '/Users/philipp/shared-eggs/zope.configuration-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.publication-3.4.0a1_2-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.applicationcontrol-3.4_dev_r73715-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.zapi-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.security-3.4.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.exceptions-3.4dev_r73107-py2.4.egg', + '/Users/philipp/shared-eggs/zope.copypastemove-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.container-3.4.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.traversing-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.folder-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.component-0.1dev_r74310-py2.4.egg', + '/Users/philipp/shared-eggs/zope.location-3.4.0b1.dev_r75152-py2.4.egg', + '/Users/philipp/shared-eggs/zope.i18nmessageid-3.4.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.i18n-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.form-0.1.dev_r74902-py2.4.egg', + '/Users/philipp/shared-eggs/zope.annotation-3.4.0b1.dev_r75758-py2.4.egg', + '/Users/philipp/shared-eggs/zope.deprecation-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.deferredimport-3.4dev-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.publisher-0.1dev_r73800-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.pagetemplate-3.4.0b1dev_r75616-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.i18n-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.dublincore-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.session-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.testing-3.4_r75911-py2.4.egg', + '/Users/philipp/shared-eggs/zope.lifecycleevent-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.index-3.4.0a2-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.testing-3.4.0b1_r75826-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.intid-3.4.0a2-py2.4.egg', + '/Users/philipp/shared-eggs/zope.proxy-3.4.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/httplib2-0.3.0-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.exception-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.error-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.http-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.size-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.interface-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.thread-3.4dev_r73086-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/pytz-2007d-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.broken-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.filerepresentation-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.dottedname-3.4dev_r73113-py2.4.egg', + '/Users/philipp/shared-eggs/zope.cachedescriptors-3.4.0b1_r75830-py2.4.egg', + '/Users/philipp/shared-eggs/zope.datetime-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.formlib-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.hookable-3.4.0a1-py2.4-macosx-10.4-i386.egg', + '/Users/philipp/shared-eggs/zope.app.basicskin-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.pagetemplate-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.contenttype-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.tales-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.dependable-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.debug-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zope.app.keyreference-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/zodbcode-3.4.0b1dev_r75670-py2.4.egg', + '/Users/philipp/shared-eggs/zope.tal-3.4.0a1-py2.4.egg', + '/Users/philipp/shared-eggs/RestrictedPython-3.4dev_r73257-py2.4.egg', + '/lib/python', + ] + +from paste.deploy import loadapp +application = loadapp("config:/Users/philipp/dev/NudgeNudge/nudge.ini") From philikon at codespeak.net Sun Jun 3 15:48:20 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 15:48:20 +0200 (CEST) Subject: [z3-checkins] r44005 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070603134820.A25D480CF@code0.codespeak.net> Author: philikon Date: Sun Jun 3 15:48:19 2007 New Revision: 44005 Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Log: Use simple.ini (no deliverance) when demoing apache2 backend Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf Sun Jun 3 15:48:19 2007 @@ -88,5 +88,5 @@ '/Users/philipp/shared-eggs/zodbcode-3.4.0b1dev_r75670-py2.4.egg', \ '/Users/philipp/shared-eggs/zope.tal-3.4.0a1-py2.4.egg', \ '/Users/philipp/shared-eggs/RestrictedPython-3.4dev_r73257-py2.4.egg'] + sys.path" - PythonOption paste.ini /Users/philipp/dev/NudgeNudge/nudge.ini + PythonOption paste.ini /Users/philipp/dev/NudgeNudge/simple.ini Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Sun Jun 3 15:48:19 2007 @@ -91,4 +91,4 @@ ] from paste.deploy import loadapp -application = loadapp("config:/Users/philipp/dev/NudgeNudge/nudge.ini") +application = loadapp("config:/Users/philipp/dev/NudgeNudge/simple.ini") From philikon at codespeak.net Sun Jun 3 15:49:06 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 15:49:06 +0200 (CEST) Subject: [z3-checkins] r44006 - in z3/NudgeNudge/branches/zope-on-a-paste-demos: . capitalizer Message-ID: <20070603134906.8AB3180CF@code0.codespeak.net> Author: philikon Date: Sun Jun 3 15:49:06 2007 New Revision: 44006 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalize.ini z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/ (props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/capitalizer.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/setup.py (contents, props changed) Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Log: Capitalizer middleware complete with PasteDeploy entry point Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Sun Jun 3 15:49:06 2007 @@ -1,6 +1,6 @@ [buildout] parts = app data instance server test -develop = . deliverance +develop = . deliverance capitalizer find-links = http://download.zope.org/distribution/ [zope3] @@ -13,6 +13,7 @@ zope.paste PasteDeploy z3c.evalexception + capitalizer Deliverance PasteScript WSGIUtils Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalize.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalize.ini Sun Jun 3 15:49:06 2007 @@ -0,0 +1,13 @@ +[filter-app:main] +use = egg:capitalizer +next = zope + +[app:zope] +use = egg:zope.paste +site_definition = parts/app/site.zcml +file_storage = parts/data/Data.fs + +[server:main] +use = egg:PasteScript#wsgiutils +host = 127.0.0.1 +port = 8080 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/capitalizer.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/capitalizer.py Sun Jun 3 15:49:06 2007 @@ -0,0 +1,9 @@ +def Capitalizer(application): + def middleware(environ, start_response): + for text in application(environ, start_response): + yield text.upper() + return middleware + +def capitalizer_factory(app, global_conf): + return Capitalizer(app) + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/setup.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/capitalizer/setup.py Sun Jun 3 15:49:06 2007 @@ -0,0 +1,9 @@ +from setuptools import setup +setup(name='capitalizer', + version = '1.0', + py_modules=['capitalizer'], + zip_safe = True, + entry_points = """ + [paste.filter_app_factory] + main = capitalizer:capitalizer_factory + """) From philikon at codespeak.net Sun Jun 3 16:30:27 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 16:30:27 +0200 (CEST) Subject: [z3-checkins] r44007 - z3/NudgeNudge/trunk Message-ID: <20070603143027.7FC7580CB@code0.codespeak.net> Author: philikon Date: Sun Jun 3 16:30:27 2007 New Revision: 44007 Modified: z3/NudgeNudge/trunk/setup.py Log: Need zope.app.zcmlfiles Modified: z3/NudgeNudge/trunk/setup.py ============================================================================== --- z3/NudgeNudge/trunk/setup.py (original) +++ z3/NudgeNudge/trunk/setup.py Sun Jun 3 16:30:27 2007 @@ -26,5 +26,6 @@ 'zope.app.authentication', 'zope.app.security', 'zope.app.securitypolicy', + 'zope.app.zcmlfiles', ], ) From philikon at codespeak.net Sun Jun 3 16:31:32 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 16:31:32 +0200 (CEST) Subject: [z3-checkins] r44008 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070603143132.654CD80CB@code0.codespeak.net> Author: philikon Date: Sun Jun 3 16:31:26 2007 New Revision: 44008 Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/setup.py Log: Need zope.app.zcmlfiles Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/setup.py ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/setup.py (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/setup.py Sun Jun 3 16:31:26 2007 @@ -26,5 +26,6 @@ 'zope.app.authentication', 'zope.app.security', 'zope.app.securitypolicy', + 'zope.app.zcmlfiles', ], ) From philikon at codespeak.net Sun Jun 3 22:30:57 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 22:30:57 +0200 (CEST) Subject: [z3-checkins] r44012 - in z3/NudgeNudge/branches/zope-on-a-paste-demos: . tgdemo tgdemo/tgdemo tgdemo/tgdemo.egg-info tgdemo/tgdemo/config tgdemo/tgdemo/sqlobject-history tgdemo/tgdemo/static tgdemo/tgdemo/static/css tgdemo/tgdemo/static/images tgdemo/tgdemo/static/javascript tgdemo/tgdemo/templates tgdemo/tgdemo/tests Message-ID: <20070603203057.4246980CB@code0.codespeak.net> Author: philikon Date: Sun Jun 3 22:30:55 2007 New Revision: 44012 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/combined.ini z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/README.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/deploy_cfg.ini z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/dev.cfg z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/sample-prod.cfg z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/setup.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/start-tgdemo.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/test.cfg z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/PKG-INFO z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/SOURCES.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/dependency_links.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/entry_points.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/not-zip-safe z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/paster_plugins.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/requires.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/sqlobject.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/top_level.txt (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/__init__.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/__init__.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/app.cfg z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/log.cfg z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/controllers.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/json.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/model.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/release.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/sqlobject-history/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/css/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/css/style.css (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/favicon.ico (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/header_inner.png (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/info.png (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/ok.png (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/tg_under_the_hood.png (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/under_the_hood_blue.png (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/javascript/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/__init__.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/login.kid z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/master.kid z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/welcome.kid z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/__init__.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_controllers.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_model.py (contents, props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/wsgiapp.py (contents, props changed) Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/ (props changed) z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Log: Add another example: URL dispatching to Zope and TurboGears in the same process. Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/buildout.cfg Sun Jun 3 22:30:55 2007 @@ -1,6 +1,6 @@ [buildout] parts = app data instance server test -develop = . deliverance capitalizer +develop = . deliverance capitalizer turbogears tgdemo find-links = http://download.zope.org/distribution/ [zope3] @@ -17,6 +17,7 @@ Deliverance PasteScript WSGIUtils + tgdemo extra-paths = ${zope3:location}/lib/python [app] Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/combined.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/combined.ini Sun Jun 3 22:30:55 2007 @@ -0,0 +1,17 @@ +[composite:main] +use = egg:Paste#urlmap +/zope = zope +/tg = tgdemo + +[app:tgdemo] +use = egg:tgdemo + +[app:zope] +use = egg:zope.paste +site_definition = parts/app/site.zcml +file_storage = parts/data/Data.fs + +[server:main] +use = egg:PasteScript#twisted +host = 127.0.0.1 +port = 8080 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/README.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/README.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1,4 @@ +tgdemo + +This is a TurboGears (http://www.turbogears.org) project. It can be +started by running the start-tgdemo.py script. \ No newline at end of file Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/deploy_cfg.ini ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/deploy_cfg.ini Sun Jun 3 22:30:55 2007 @@ -0,0 +1,15 @@ +# To start the app uisng this file directly, ATM, you can do: +# $ paster serve --reload deploy.ini +# (tg-admin serve will do this in the future) + +[DEFAULT] + +[server:main] +use= egg:PasteScript#cherrypy +host = 0.0.0.0 +port = 8080 + +[app:main] +use = egg:tgdemo +# This points to the tg style config file (if any). +tg.config_file = %(here)s/dev.cfg Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/dev.cfg ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/dev.cfg Sun Jun 3 22:30:55 2007 @@ -0,0 +1,60 @@ +[global] +# This is where all of your settings go for your development environment +# Settings that are the same for both development and production +# (such as template engine, encodings, etc.) all go in +# tgdemo/config/app.cfg + +# DATABASE + +# pick the form for your database +# sqlobject.dburi="postgres://username at hostname/databasename" +# sqlobject.dburi="mysql://username:password at hostname:port/databasename" +# sqlobject.dburi="sqlite:///file_name_and_path" + +# If you have sqlite, here's a simple default to get you started +# in development +sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite" + + +# if you are using a database or table type without transactions +# (MySQL default, for example), you should turn off transactions +# by prepending notrans_ on the uri +# sqlobject.dburi="notrans_mysql://username:password at hostname:port/databasename" + +# for Windows users, sqlite URIs look like: +# sqlobject.dburi="sqlite:///drive_letter:/path/to/file" + +# SERVER + +# Some server parameters that you may want to tweak +# server.socket_port=8080 + +server.environment="development" +autoreload.package="tgdemo" + +# Set to True if you'd like to abort execution if a controller gets an +# unexpected parameter. False by default +tg.strict_parameters = True + +# LOGGING +# Logging configuration generally follows the style of the standard +# Python logging module configuration. Note that when specifying +# log format messages, you need to use *() for formatting variables. +# Deployment independent log configuration is in tgdemo/config/log.cfg +[logging] + +[[loggers]] +[[[tgdemo]]] +level='DEBUG' +qualname='tgdemo' +handlers=['debug_out'] + +[[[allinfo]]] +level='INFO' +handlers=['debug_out'] + +[[[access]]] +level='INFO' +qualname='turbogears.access' +handlers=['access_out'] +propagate=0 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/sample-prod.cfg ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/sample-prod.cfg Sun Jun 3 22:30:55 2007 @@ -0,0 +1,84 @@ +[global] +# This is where all of your settings go for your production environment. +# You'll copy this file over to your production server and provide it +# as a command-line option to your start script. +# Settings that are the same for both development and production +# (such as template engine, encodings, etc.) all go in +# tgdemo/config/app.cfg + +# DATABASE + +# pick the form for your database +# sqlobject.dburi="postgres://username at hostname/databasename" +# sqlobject.dburi="mysql://username:password at hostname:port/databasename" +# sqlobject.dburi="sqlite:///file_name_and_path" + +# If you have sqlite, here's a simple default to get you started +# in development +sqlobject.dburi="sqlite://%(current_dir_uri)s/devdata.sqlite" + + +# if you are using a database or table type without transactions +# (MySQL default, for example), you should turn off transactions +# by prepending notrans_ on the uri +# sqlobject.dburi="notrans_mysql://username:password at hostname:port/databasename" + +# for Windows users, sqlite URIs look like: +# sqlobject.dburi="sqlite:///drive_letter:/path/to/file" + + +# SERVER + +server.environment="production" + +# Sets the number of threads the server uses +# server.thread_pool = 1 + +# if this is part of a larger site, you can set the path +# to the TurboGears instance here +# server.webpath="" + +# Set to True if you are deploying your App behind a proxy +# e.g. Apache using mod_proxy +# tools.proxy.on = False + +# Set to True if your proxy adds the x_forwarded_host header +# tools.proxy.use_x_forwarded_host = True + +# If your proxy does not add the x_forwarded_host header, set +# the following to the *public* host url. +# (Note: This will be overridden by the use_x_forwarded_host option +# if it is set to True and the proxy adds the header correctly. +# tools.proxy.base_url = "http://www.example.com" + +# Set to True if you'd like to abort execution if a controller gets an +# unexpected parameter. False by default +# tg.strict_parameters = False + +# LOGGING +# Logging configuration generally follows the style of the standard +# Python logging module configuration. Note that when specifying +# log format messages, you need to use *() for formatting variables. +# Deployment independent log configuration is in tgdemo/config/log.cfg +[logging] + +[[handlers]] + +[[[access_out]]] +# set the filename as the first argument below +args="('server.log',)" +class='FileHandler' +level='INFO' +formatter='message_only' + +[[loggers]] +[[[tgdemo]]] +level='ERROR' +qualname='tgdemo' +handlers=['error_out'] + +[[[access]]] +level='INFO' +qualname='turbogears.access' +handlers=['access_out'] +propagate=0 Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/setup.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/setup.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,63 @@ +from setuptools import setup, find_packages + +import os +execfile(os.path.join("tgdemo", "release.py")) + +setup( + name="tgdemo", + version=version, + + # uncomment the following lines if you fill them out in release.py + #description=description, + #author=author, + #author_email=email, + #url=url, + #download_url=download_url, + #license=license, + + install_requires = [ + "TurboGears >= 1.1a0", + ], + scripts = ["start-tgdemo.py"], + zip_safe=False, + packages=find_packages(), + keywords = [ + # Use keywords if you'll be adding your package to the + # Python Cheeseshop + + # if this has widgets, uncomment the next line + # 'turbogears.widgets', + + # if this has a tg-admin command, uncomment the next line + # 'turbogears.command', + + # if this has identity providers, uncomment the next line + # 'turbogears.identity.provider', + + # If this is a template plugin, uncomment the next line + # 'python.templating.engines', + + # If this is a full application, uncomment the next line + # 'turbogears.app', + ], + classifiers = [ + 'Development Status :: 3 - Alpha', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Software Development :: Libraries :: Python Modules', + 'Framework :: TurboGears', + # if this is an application that you'll distribute through + # the Cheeseshop, uncomment the next line + # 'Framework :: TurboGears :: Applications', + + # if this is a package that includes widgets that you'll distribute + # through the Cheeseshop, uncomment the next line + # 'Framework :: TurboGears :: Widgets', + ], + test_suite = 'nose.collector', + entry_points = """ + [paste.app_factory] + main = tgdemo.wsgiapp:WSGIApp.app_factory + """, + ) + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/start-tgdemo.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/start-tgdemo.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,26 @@ +#!/opt/local/bin/python +import pkg_resources +pkg_resources.require("TurboGears") + +#XXX: All this is derecated, tg-admin serve should be used instead +from turbogears import update_config, start_server +import cherrypy +cherrypy.lowercase_api = True +from os.path import * +import sys + +# first look on the command line for a desired config file, +# if it's not on the command line, then +# look for setup.py in this directory. If it's not there, this script is +# probably installed +if len(sys.argv) > 1: + update_config(configfile=sys.argv[1], + modulename="tgdemo.config") +elif exists(join(dirname(__file__), "setup.py")): + update_config(configfile="dev.cfg",modulename="tgdemo.config") +else: + update_config(configfile="prod.cfg",modulename="tgdemo.config") + +from tgdemo.controllers import Root + +start_server(Root()) Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/test.cfg ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/test.cfg Sun Jun 3 22:30:55 2007 @@ -0,0 +1,4 @@ +# You can place test-specific configuration options here (like test db uri, etc) + +sqlobject.dburi = "sqlite:///:memory:" + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/PKG-INFO ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/PKG-INFO Sun Jun 3 22:30:55 2007 @@ -0,0 +1,15 @@ +Metadata-Version: 1.0 +Name: tgdemo +Version: 1.0 +Summary: UNKNOWN +Home-page: UNKNOWN +Author: UNKNOWN +Author-email: UNKNOWN +License: UNKNOWN +Description: UNKNOWN +Platform: UNKNOWN +Classifier: Development Status :: 3 - Alpha +Classifier: Operating System :: OS Independent +Classifier: Programming Language :: Python +Classifier: Topic :: Software Development :: Libraries :: Python Modules +Classifier: Framework :: TurboGears Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/SOURCES.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/SOURCES.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1,23 @@ +README.txt +setup.py +start-tgdemo.py +tgdemo/__init__.py +tgdemo/controllers.py +tgdemo/json.py +tgdemo/model.py +tgdemo/release.py +tgdemo/wsgiapp.py +tgdemo.egg-info/PKG-INFO +tgdemo.egg-info/SOURCES.txt +tgdemo.egg-info/dependency_links.txt +tgdemo.egg-info/entry_points.txt +tgdemo.egg-info/not-zip-safe +tgdemo.egg-info/paster_plugins.txt +tgdemo.egg-info/requires.txt +tgdemo.egg-info/sqlobject.txt +tgdemo.egg-info/top_level.txt +tgdemo/config/__init__.py +tgdemo/templates/__init__.py +tgdemo/tests/__init__.py +tgdemo/tests/test_controllers.py +tgdemo/tests/test_model.py Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/dependency_links.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/dependency_links.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1 @@ + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/entry_points.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/entry_points.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1,4 @@ + + [paste.app_factory] + main = tgdemo.wsgiapp:WSGIApp.app_factory + \ No newline at end of file Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/not-zip-safe ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/not-zip-safe Sun Jun 3 22:30:55 2007 @@ -0,0 +1 @@ + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/paster_plugins.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/paster_plugins.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1,2 @@ +TurboGears +PasteScript Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/requires.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/requires.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1 @@ +TurboGears >= 1.1a0 \ No newline at end of file Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/sqlobject.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/sqlobject.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1,2 @@ +db_module=tgdemo.model +history_dir=$base/tgdemo/sqlobject-history Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/top_level.txt ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo.egg-info/top_level.txt Sun Jun 3 22:30:55 2007 @@ -0,0 +1 @@ +tgdemo Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/__init__.py ============================================================================== Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/__init__.py ============================================================================== Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/app.cfg ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/app.cfg Sun Jun 3 22:30:55 2007 @@ -0,0 +1,50 @@ +[global] +# The settings in this file should not vary depending on the deployment +# environment. dev.cfg and prod.cfg are the locations for +# the different deployment settings. Settings in this file will +# be overridden by settings in those other files. + +# The commented out values below are the defaults + +# VIEW + +# which view (template engine) to use if one is not specified in the +# template name +# tg.defaultview = "kid" + +# The following kid settings determine the settings used by the kid serializer. + +# One of (html|html-strict|xhtml|xhtml-strict|xml|json) +# kid.outputformat="html" + +# kid.encoding="utf-8" + +# The sitetemplate is used for overall styling of a site that +# includes multiple TurboGears applications +# tg.sitetemplate="" + +# Allow every exposed function to be called as json, +# tg.allow_json = False + +# List of Widgets to include on every page. +# for exemple ['turbogears.mochikit'] +# tg.include_widgets = [] + +# Set to True if the scheduler should be started +# tg.scheduler = False + +# Set session or cookie +# session_filter.on = True + + +# compress the data sends to the web browser +# [/] +# tools.gzip.mime_types = ["application/x-javascript", "text/javascript", "text/html", "text/css", "text/plain"] + +[/static] +tools.staticdir.on = True +tools.staticdir.dir = "%(top_level_dir)s/static" + +[/favicon.ico] +tools.staticfile.on = True +tools.staticfile.filename = "%(top_level_dir)s/static/images/favicon.ico" Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/log.cfg ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/config/log.cfg Sun Jun 3 22:30:55 2007 @@ -0,0 +1,29 @@ +# LOGGING +# Logging is often deployment specific, but some handlers and +# formatters can be defined here. + +[logging] +[[formatters]] +[[[message_only]]] +format='*(message)s' + +[[[full_content]]] +format='*(asctime)s *(name)s *(levelname)s *(message)s' + +[[handlers]] +[[[debug_out]]] +class='StreamHandler' +level='DEBUG' +args='(sys.stdout,)' +formatter='full_content' + +[[[access_out]]] +class='StreamHandler' +level='INFO' +args='(sys.stdout,)' +formatter='message_only' + +[[[error_out]]] +class='StreamHandler' +level='ERROR' +args='(sys.stdout,)' Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/controllers.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/controllers.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,13 @@ +#coding=utf-8 +from turbogears import controllers, expose, flash +# from model import * +# import logging +# log = logging.getLogger("tgdemo.controllers") + +class Root(controllers.RootController): + @expose(template="tgdemo.templates.welcome") + def index(self): + import time + # log.debug("Happy TurboGears Controller Responding For Duty") + flash("Your application is now running") + return dict(now=time.ctime()) Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/json.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/json.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,10 @@ +# A JSON-based API(view) for your app. +# Most rules would look like: +# @jsonify.when("isinstance(obj, YourClass)") +# def jsonify_yourclass(obj): +# return [obj.val1, obj.val2] +# @jsonify can convert your objects to following types: +# lists, dicts, numbers and strings + +from turbojson.jsonify import jsonify + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/model.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/model.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,9 @@ +from turbogears.database import PackageHub +from sqlobject import * + +hub = PackageHub('tgdemo') +__connection__ = hub + +# class YourDataClass(SQLObject): +# pass + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/release.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/release.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,14 @@ +# Release information about tgdemo + +version = "1.0" + +# description = "Your plan to rule the world" +# long_description = "More description about your plan" +# author = "Your Name Here" +# email = "YourEmail at YourDomain" +# copyright = "Vintage 2006 - a good year indeed" + +# if it's open source, you might want to specify these +# url = "http://yourcool.site/" +# download_url = "http://yourcool.site/download" +# license = "MIT" Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/css/style.css ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/css/style.css Sun Jun 3 22:30:55 2007 @@ -0,0 +1,134 @@ +/* + * Quick mash-up of CSS for the TG quick start page. + */ + +html, body { + color: black; + background-color: #ddd; + font: x-small "Lucida Grande", "Lucida Sans Unicode", geneva, verdana, sans-serif; + margin: 0; + padding: 0; +} + +td, th {padding:3px;border:none;} +tr th {text-align:left;background-color:#f0f0f0;color:#333;} +tr.odd td {background-color:#edf3fe;} +tr.even td {background-color:#fff;} + +#header { + height: 80px; + width: 777px; + background: blue URL('../images/header_inner.png') no-repeat; + border-left: 1px solid #aaa; + border-right: 1px solid #aaa; + margin: 0 auto 0 auto; +} + +a.link, a, a.active { + color: #369; +} + + +#main_content { + color: black; + font-size: 127%; + background-color: white; + width: 757px; + margin: 0 auto 0 auto; + border-left: 1px solid #aaa; + border-right: 1px solid #aaa; + padding: 10px; +} + +#sidebar { + border: 1px solid #aaa; + background-color: #eee; + margin: 0.5em; + padding: 1em; + float: right; + width: 200px; + font-size: 88%; +} + +#sidebar h2 { + margin-top: 0; +} + +#sidebar ul { + margin-left: 1.5em; + padding-left: 0; +} + +h1,h2,h3,h4,h5,h6,#getting_started_steps { + font-family: "Century Schoolbook L", Georgia, serif; + font-weight: bold; +} + +h2 { + font-size: 150%; +} + +#getting_started_steps a { + text-decoration: none; +} + +#getting_started_steps a:hover { + text-decoration: underline; +} + +#getting_started_steps li { + font-size: 80%; + margin-bottom: 0.5em; +} + +#getting_started_steps h2 { + font-size: 120%; +} + +#getting_started_steps p { + font: 100% "Lucida Grande", "Lucida Sans Unicode", geneva, verdana, sans-serif; +} + +#footer { + border: 1px solid #aaa; + border-top: 0px none; + color: #999; + background-color: white; + padding: 10px; + font-size: 80%; + text-align: center; + width: 757px; + margin: 0 auto 1em auto; +} + +.code { + font-family: monospace; +} + +span.code { + font-weight: bold; + background: #eee; +} + +#status_block { + margin: 0 auto 0.5em auto; + padding: 15px 10px 15px 55px; + background: #cec URL('../images/ok.png') left center no-repeat; + border: 1px solid #9c9; + width: 450px; + font-size: 120%; + font-weight: bolder; +} + +.notice { + margin: 0.5em auto 0.5em auto; + padding: 15px 10px 15px 55px; + width: 450px; + background: #eef URL('../images/info.png') left center no-repeat; + border: 1px solid #cce; +} + +.fielderror { + color: red; + font-weight: bold; +} Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/favicon.ico ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/header_inner.png ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/info.png ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/ok.png ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/tg_under_the_hood.png ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/static/images/under_the_hood_blue.png ============================================================================== Binary file. No diff available. Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/__init__.py ============================================================================== Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/login.kid ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/login.kid Sun Jun 3 22:30:55 2007 @@ -0,0 +1,112 @@ + + + + + + Login + + + + +
      +

      Login

      +

      ${message}

      +
      + + + + + + + + + + + + +
      + + + +
      + + + +
      + +
      + + + + +
      +
      + + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/master.kid ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/master.kid Sun Jun 3 22:30:55 2007 @@ -0,0 +1,48 @@ + + + + + + + Your title goes here + + + + + + +
      + + Login + + + Welcome ${tg.identity.user.display_name}. + Logout + +
      + +
      +
      + +
      + + +
      + + + + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/welcome.kid ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/templates/welcome.kid Sun Jun 3 22:30:55 2007 @@ -0,0 +1,47 @@ + + + + +Welcome to TurboGears + + + + +
      +
        +
      1. +

        Model

        +

        Design models in the model.py.
        + Edit dev.cfg to use a different backend, or start with a pre-configured SQLite database.
        + Use script tg-admin sql create to create the database tables.

        +
      2. +
      3. +

        View

        +

        Edit html-like templates in the /templates folder;
        + Put all static contents in the /static folder.

        +
      4. +
      5. +

        Controller

        +

        Edit controllers.py and build your + website structure with the simplicity of Python objects.
        + TurboGears will automatically reload itself when you modify your project.

        +
      6. +
      +
      If you create something cool, please let people know, and consider contributing something back to the community.
      +
      + + + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/__init__.py ============================================================================== Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_controllers.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_controllers.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,32 @@ +import unittest +import turbogears +from turbogears import testutil +from tgdemo.controllers import Root +import cherrypy + +cherrypy.root = Root() + +class TestPages(unittest.TestCase): + + def setUp(self): + turbogears.startup.startTurboGears() + + def tearDown(self): + """Tests for apps using identity need to stop CP/TG after each test to + stop the VisitManager thread. + See http://trac.turbogears.org/turbogears/ticket/1217 for details. + """ + turbogears.startup.stopTurboGears() + + def test_method(self): + "the index method should return a string called now" + import types + result = testutil.call(cherrypy.root.index) + assert type(result["now"]) == types.StringType + + def test_indextitle(self): + "The indexpage should have the right title" + testutil.createRequest("/") + response = cherrypy.response.body[0].lower() + assert "welcome to turbogears" in response + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_model.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/tests/test_model.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,22 @@ +# If your project uses a database, you can set up database tests +# similar to what you see below. Be sure to set the db_uri to +# an appropriate uri for your testing database. sqlite is a good +# choice for testing, because you can use an in-memory database +# which is very fast. + +from turbogears import testutil, database +# from tgdemo.model import YourDataClass, User + +# database.set_db_uri("sqlite:///:memory:") + +# class TestUser(testutil.DBTest): +# def get_model(self): +# return User +# def test_creation(self): +# "Object creation should set the name" +# obj = User(user_name = "creosote", +# email_address = "spam at python.not", +# display_name = "Mr Creosote", +# password = "Wafer-thin Mint") +# assert obj.display_name == "Mr Creosote" + Added: z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/wsgiapp.py ============================================================================== --- (empty file) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/tgdemo/tgdemo/wsgiapp.py Sun Jun 3 22:30:55 2007 @@ -0,0 +1,6 @@ +from turbogears.wsgi import TGWSGIApp +from tgdemo.controllers import Root + +class WSGIApp(TGWSGIApp): + package_name = "tgdemo" + root = Root() From philikon at codespeak.net Sun Jun 3 22:34:07 2007 From: philikon at codespeak.net (philikon at codespeak.net) Date: Sun, 3 Jun 2007 22:34:07 +0200 (CEST) Subject: [z3-checkins] r44013 - z3/NudgeNudge/branches/zope-on-a-paste-demos Message-ID: <20070603203407.A5DBC80CF@code0.codespeak.net> Author: philikon Date: Sun Jun 3 22:34:07 2007 New Revision: 44013 Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Log: Moved directory on my local disk :/ Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/apache2.conf Sun Jun 3 22:34:07 2007 @@ -1,4 +1,4 @@ -ServerRoot "/Users/philipp/dev/NudgeNudge" +ServerRoot "/Users/philipp/dev/zope-on-a-paste-demos" ServerName 127.0.0.1 Listen 127.0.0.1:8080 @@ -67,7 +67,7 @@ LoadModule wsgi_module /opt/local/apache2/modules/mod_wsgi.so ServerAdmin philipp at weitershausen.de -DocumentRoot "/Users/philipp/dev/NudgeNudge" +DocumentRoot "/Users/philipp/dev/zope-on-a-paste-demos" MaxSpareServers 1 @@ -77,7 +77,7 @@ Deny from all - + Options Indexes FollowSymLinks AllowOverride None Order allow,deny @@ -95,4 +95,4 @@ Include "mod_python.conf" -#WSGISCriptAlias / /Users/philipp/dev/NudgeNudge/nudge.wsgi +#WSGISCriptAlias / /Users/philipp/dev/zope-on-a-paste-demos/nudge.wsgi Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/mod_python.conf Sun Jun 3 22:34:07 2007 @@ -3,10 +3,10 @@ PythonHandler paste.modpython PythonPath "[ '/Users/philipp/shared-eggs/setuptools-0.6c6-py2.4.egg', \ '/Users/philipp/shared-eggs/grok-0.9dev_r75634-py2.4.egg', \ - '/Users/philipp/dev/NudgeNudge/src', \ + '/Users/philipp/dev/zope-on-a-paste-demos/src', \ '/Users/philipp/shared-eggs/zope.paste-0.3-py2.4.egg', \ '/Users/philipp/shared-eggs/PasteDeploy-1.3-py2.4.egg', \ - '/Users/philipp/dev/NudgeNudge/deliverance', \ + '/Users/philipp/dev/zope-on-a-paste-demos/deliverance', \ '/Users/philipp/shared-eggs/PasteScript-1.3.4-py2.4.egg', \ '/Users/philipp/shared-eggs/WSGIUtils-0.7-py2.4.egg', \ '/Users/philipp/shared-eggs/Paste-1.3-py2.4.egg', \ @@ -88,5 +88,5 @@ '/Users/philipp/shared-eggs/zodbcode-3.4.0b1dev_r75670-py2.4.egg', \ '/Users/philipp/shared-eggs/zope.tal-3.4.0a1-py2.4.egg', \ '/Users/philipp/shared-eggs/RestrictedPython-3.4dev_r73257-py2.4.egg'] + sys.path" - PythonOption paste.ini /Users/philipp/dev/NudgeNudge/simple.ini + PythonOption paste.ini /Users/philipp/dev/zope-on-a-paste-demos/simple.ini Modified: z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi ============================================================================== --- z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi (original) +++ z3/NudgeNudge/branches/zope-on-a-paste-demos/nudge.wsgi Sun Jun 3 22:34:07 2007 @@ -2,10 +2,10 @@ sys.path[0:0] = [ '/Users/philipp/shared-eggs/setuptools-0.6c6-py2.4.egg', '/Users/philipp/shared-eggs/grok-0.9dev_r75634-py2.4.egg', - '/Users/philipp/dev/NudgeNudge/src', + '/Users/philipp/dev/zope-on-a-paste-demos/src', '/Users/philipp/shared-eggs/zope.paste-0.3-py2.4.egg', '/Users/philipp/shared-eggs/PasteDeploy-1.3-py2.4.egg', - '/Users/philipp/dev/NudgeNudge/deliverance', + '/Users/philipp/dev/zope-on-a-paste-demos/deliverance', '/Users/philipp/shared-eggs/PasteScript-1.3.4-py2.4.egg', '/Users/philipp/shared-eggs/WSGIUtils-0.7-py2.4.egg', '/Users/philipp/shared-eggs/Paste-1.3-py2.4.egg', @@ -91,4 +91,4 @@ ] from paste.deploy import loadapp -application = loadapp("config:/Users/philipp/dev/NudgeNudge/simple.ini") +application = loadapp("config:/Users/philipp/dev/zope-on-a-paste-demos/simple.ini") From ltucker at codespeak.net Thu Jun 14 23:01:26 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Thu, 14 Jun 2007 23:01:26 +0200 (CEST) Subject: [z3-checkins] r44249 - in z3/deliverance/DeliveranceVHoster/trunk: . dvhoster Message-ID: <20070614210126.7A7048271@code0.codespeak.net> Author: ltucker Date: Thu Jun 14 23:01:24 2007 New Revision: 44249 Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py z3/deliverance/DeliveranceVHoster/trunk/setup.py Log: add transcluder to the vhoster stack Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/development.ini (original) +++ z3/deliverance/DeliveranceVHoster/trunk/development.ini Thu Jun 14 23:01:24 2007 @@ -51,4 +51,19 @@ default_theme_uri = http://www.openplans.org domain_regex = ^(.*)\.flow\.openplans\.org$ +# transluder configuration + +# transcluder_ok_hosts controls which hosts +# transcluder will include and recursively +# transclude from. +# +# this can be: +# all - any host is ok +# none - no hosts are ok +# localhost - only localhsost +# - only hosts matching the regex given +# +transcluder_ok_hosts = openplans.org|(.*)\.openplans.org|(.*)\.localhost.openplans\.org|localhost +transcluder_pool_size = 0 + ### END THIS IMPORTANT STUFF ### Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Thu Jun 14 23:01:24 2007 @@ -17,6 +17,9 @@ from dvhoster.logcreate import make_logger from dvhoster import uritemplate +import transcluder +from transcluder.middleware import TranscluderMiddleware + def norm_path(urlpath): if not urlpath: urlpath = '/' @@ -63,6 +66,28 @@ logger = make_logger(app_conf.get('logger'), 'dvhoster') self.logger = logger + # transcluder configuration + ok_hosts = app_conf.get('transcluder_ok_hosts') + + if not ok_hosts or ok_hosts == 'all': + self.transcluder_ok_hosts = transcluder.helpers.all_urls + elif ok_hosts == 'none': + self.transcluder_ok_hosts = transcluder.helpers.no_urls + elif ok_hosts == 'localhost': + self.transcluder_ok_hosts = transcluder.helpers.localhost_only + else: + self.transcluder_ok_hosts = transcluder.helpers.make_regex_predicate(ok_hosts) + + self.transcluder_deptracker = transcluder.deptracker.DependencyTracker() + + poolsize = 0 + try: + poolsize = int(app_conf.get('transcluder_pool_size')) + except: + pass + + self.transcluder_pool = transcluder.tasklist.TaskList(poolsize=poolsize) + def __call__(self, environ, start_response): """ WSGI interface @@ -140,6 +165,12 @@ remote=remote_uri, force_host=True) + app = TranscluderMiddleware(app, + deptracker=self.transcluder_deptracker, + tasklist=self.transcluder_pool, + include_predicate=self.transcluder_ok_hosts, + recursion_predicate=self.transcluder_ok_hosts) + if should_theme_uri: if self.rewrite_links: app = relocateresponse.RelocateMiddleware( Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Thu Jun 14 23:01:24 2007 @@ -15,10 +15,12 @@ 'HTTPEncode', 'OHM==dev,>0.1', 'wsgi_intercept', + 'Transcluder' ], dependency_links=[ 'http://codespeak.net/svn/z3/deliverance/trunk#egg=Deliverance-dev', 'http://darcs.idyll.org/~t/projects/wsgi_intercept/wsgi_intercept.py#egg=wsgi_intercept-dev', + 'http://svn.openplans.org/svn/transcluder/trunk#egg=Trancluder-dev' ], packages=find_packages(), include_package_data=True, From ltucker at codespeak.net Thu Jun 14 23:12:21 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Thu, 14 Jun 2007 23:12:21 +0200 (CEST) Subject: [z3-checkins] r44250 - z3/deliverance/DeliveranceVHoster/trunk Message-ID: <20070614211221.B87808270@code0.codespeak.net> Author: ltucker Date: Thu Jun 14 23:12:21 2007 New Revision: 44250 Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py Log: fix Transcluder dependency Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Thu Jun 14 23:12:21 2007 @@ -15,12 +15,12 @@ 'HTTPEncode', 'OHM==dev,>0.1', 'wsgi_intercept', - 'Transcluder' + 'Transcluder==dev' ], dependency_links=[ 'http://codespeak.net/svn/z3/deliverance/trunk#egg=Deliverance-dev', 'http://darcs.idyll.org/~t/projects/wsgi_intercept/wsgi_intercept.py#egg=wsgi_intercept-dev', - 'http://svn.openplans.org/svn/transcluder/trunk#egg=Trancluder-dev' + 'https://svn.openplans.org/svn/transcluder/trunk#egg=Transcluder-dev' ], packages=find_packages(), include_package_data=True, From ltucker at codespeak.net Fri Jun 15 00:33:33 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:33:33 +0200 (CEST) Subject: [z3-checkins] r44253 - in z3/deliverance/buildout: branches branches/maspelli_recipe tags Message-ID: <20070614223333.D26708279@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:33:33 2007 New Revision: 44253 Added: z3/deliverance/buildout/branches/ z3/deliverance/buildout/branches/maspelli_recipe/ - copied from r44252, z3/deliverance/buildout/trunk/ z3/deliverance/buildout/tags/ Log: branching to use martin aspelis recipe From ltucker at codespeak.net Fri Jun 15 00:38:44 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:38:44 +0200 (CEST) Subject: [z3-checkins] r44254 - in z3/deliverance/buildout/branches/maspelli_recipe: . helpers Message-ID: <20070614223844.418E1827B@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:38:43 2007 New Revision: 44254 Removed: z3/deliverance/buildout/branches/maspelli_recipe/helpers/ Modified: z3/deliverance/buildout/branches/maspelli_recipe/ (props changed) z3/deliverance/buildout/branches/maspelli_recipe/EXTERNALS.txt z3/deliverance/buildout/branches/maspelli_recipe/buildout.cfg Log: switch to plone.recipe.deliverance Modified: z3/deliverance/buildout/branches/maspelli_recipe/EXTERNALS.txt ============================================================================== --- z3/deliverance/buildout/branches/maspelli_recipe/EXTERNALS.txt (original) +++ z3/deliverance/buildout/branches/maspelli_recipe/EXTERNALS.txt Fri Jun 15 00:38:43 2007 @@ -1,4 +1,4 @@ bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap -zc.recipe.cmmi svn://svn.zope.org/repos/main/zc.recipe.cmmi/trunk +plone.recipe.deliverance https://svn.plone.org/svn/collective/buildout/plone.recipe/deliverance deliverance http://codespeak.net/svn/z3/deliverance/trunk Modified: z3/deliverance/buildout/branches/maspelli_recipe/buildout.cfg ============================================================================== --- z3/deliverance/buildout/branches/maspelli_recipe/buildout.cfg (original) +++ z3/deliverance/buildout/branches/maspelli_recipe/buildout.cfg Fri Jun 15 00:38:43 2007 @@ -1,54 +1,6 @@ [buildout] -develop = zc.recipe.cmmi deliverance helpers -parts = fix-bin-path libxml2 libXslt lxml lxml-inst deliverance-inst fix-deliverance-scripts - -[libxml2] -recipe = zc.recipe.cmmi -url = ftp://xmlsoft.org/libxml2/libxml2-2.6.27.tar.gz -extra_options = --without-python - -[libXslt] -recipe = zc.recipe.cmmi -url = ftp://xmlsoft.org/libxml2/libxslt-1.1.18.tar.gz -extra_options = --with-libxml-prefix=${buildout:directory}/parts/libxml2/ - --without-python - -[lxml] -recipe = zc.recipe.egg:custom -eggs = lxml -include-dirs = ${buildout:directory}/parts/libxml2/include/libxml2:${buildout:directory}/parts/libXslt/include -rpath = ${buildout:directory}/parts/libxml2/lib:${buildout:directory}/parts/libXslt/lib - -[lxml-inst] -recipe = zc.recipe.egg -eggs = lxml - -[deliverance-inst] -recipe = zc.recipe.egg -eggs = Deliverance - -[ddemo] -recipe = zc.recipe.egg -eggs = PasteScript - Paste ==dev,>1.0 - DeliveranceDemo -find-links = http://codespeak.net/svn/z3/deliverance/DeliveranceDemo/trunk/docs/find-links.html -scripts = paster - -[supervisor] -recipe = zc.recipe.egg -eggs = supervisor -find-links = http://codespeak.net/svn/z3/deliverance/DeliveranceDemo/trunk/docs/find-links.html -# Doesn't work for some reason, dammit: -scripts = supervisord supervisorctl - -[fix-bin-path] -recipe = topp.helpers:addbinpath -path = ${buildout:directory}/parts/libxml2/bin:${buildout:directory}/parts/libXslt/bin - -[fix-deliverance-scripts] -recipe = topp.helpers:fixlibsearch -eggs = Deliverance -libpath = ${buildout:directory}/parts/libxml2/lib:${buildout:directory}/parts/libXslt/lib - +develop = plone.recipe.deliverance +parts = deliverance +[deliverance] +recipe = plone.recipe.deliverance \ No newline at end of file From ltucker at codespeak.net Fri Jun 15 00:41:51 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:41:51 +0200 (CEST) Subject: [z3-checkins] r44255 - in z3/deliverance/buildout/branches: maspeli_recipe maspelli_recipe Message-ID: <20070614224151.3DBA0827B@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:41:50 2007 New Revision: 44255 Added: z3/deliverance/buildout/branches/maspeli_recipe/ - copied from r44254, z3/deliverance/buildout/branches/maspelli_recipe/ Removed: z3/deliverance/buildout/branches/maspelli_recipe/ Log: correct misspellig From ltucker at codespeak.net Fri Jun 15 00:45:37 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:45:37 +0200 (CEST) Subject: [z3-checkins] r44256 - z3/deliverance/buildout/branches/maspeli_recipe Message-ID: <20070614224537.0D512827B@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:45:37 2007 New Revision: 44256 Modified: z3/deliverance/buildout/branches/maspeli_recipe/ (props changed) z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt Log: fix externals Modified: z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt ============================================================================== --- z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt (original) +++ z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt Fri Jun 15 00:45:37 2007 @@ -1,4 +1,3 @@ bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap -plone.recipe.deliverance https://svn.plone.org/svn/collective/buildout/plone.recipe/deliverance -deliverance http://codespeak.net/svn/z3/deliverance/trunk - +plone.recipe.deliverance https://svn.plone.org/svn/collective/buildout/plone.recipe.deliverance +deliverance http://codespeak.net/svn/z3/deliverance/trunk \ No newline at end of file From ltucker at codespeak.net Fri Jun 15 00:50:29 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:50:29 +0200 (CEST) Subject: [z3-checkins] r44257 - z3/deliverance/buildout/branches/maspeli_recipe Message-ID: <20070614225029.8E6AB8280@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:50:29 2007 New Revision: 44257 Modified: z3/deliverance/buildout/branches/maspeli_recipe/ (props changed) z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt Log: fix externals Modified: z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt ============================================================================== --- z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt (original) +++ z3/deliverance/buildout/branches/maspeli_recipe/EXTERNALS.txt Fri Jun 15 00:50:29 2007 @@ -1,3 +1,3 @@ bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap -plone.recipe.deliverance https://svn.plone.org/svn/collective/buildout/plone.recipe.deliverance -deliverance http://codespeak.net/svn/z3/deliverance/trunk \ No newline at end of file +plone.recipe.deliverance https://svn.plone.org/svn/collective/buildout/plone.recipe.deliverance/trunk +deliverance http://codespeak.net/svn/z3/deliverance/trunk From ltucker at codespeak.net Fri Jun 15 00:57:39 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 15 Jun 2007 00:57:39 +0200 (CEST) Subject: [z3-checkins] r44259 - z3/deliverance/DeliveranceVHoster/trunk Message-ID: <20070614225739.927AA8280@code0.codespeak.net> Author: ltucker Date: Fri Jun 15 00:57:39 2007 New Revision: 44259 Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py Log: attempt to fix dep Modified: z3/deliverance/DeliveranceVHoster/trunk/setup.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/setup.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/setup.py Fri Jun 15 00:57:39 2007 @@ -15,7 +15,7 @@ 'HTTPEncode', 'OHM==dev,>0.1', 'wsgi_intercept', - 'Transcluder==dev' + 'Transcluder' ], dependency_links=[ 'http://codespeak.net/svn/z3/deliverance/trunk#egg=Deliverance-dev', From ltucker at codespeak.net Fri Jun 22 21:37:46 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 22 Jun 2007 21:37:46 +0200 (CEST) Subject: [z3-checkins] r44440 - z3/deliverance/DeliveranceVHoster/trunk/dvhoster Message-ID: <20070622193746.1888C812D@code0.codespeak.net> Author: ltucker Date: Fri Jun 22 21:37:44 2007 New Revision: 44440 Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Log: added flag to enable/disable transcluder Modified: z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py (original) +++ z3/deliverance/DeliveranceVHoster/trunk/dvhoster/dispatcher.py Fri Jun 22 21:37:44 2007 @@ -67,6 +67,7 @@ self.logger = logger # transcluder configuration + self.transcluder_enabled = asbool(app_conf.get('transcluder_enabled',False)) ok_hosts = app_conf.get('transcluder_ok_hosts') if not ok_hosts or ok_hosts == 'all': @@ -165,11 +166,12 @@ remote=remote_uri, force_host=True) - app = TranscluderMiddleware(app, - deptracker=self.transcluder_deptracker, - tasklist=self.transcluder_pool, - include_predicate=self.transcluder_ok_hosts, - recursion_predicate=self.transcluder_ok_hosts) + if self.transcluder_enabled: + app = TranscluderMiddleware(app, + deptracker=self.transcluder_deptracker, + tasklist=self.transcluder_pool, + include_predicate=self.transcluder_ok_hosts, + recursion_predicate=self.transcluder_ok_hosts) if should_theme_uri: if self.rewrite_links: From ltucker at codespeak.net Fri Jun 22 21:38:29 2007 From: ltucker at codespeak.net (ltucker at codespeak.net) Date: Fri, 22 Jun 2007 21:38:29 +0200 (CEST) Subject: [z3-checkins] r44441 - z3/deliverance/DeliveranceVHoster/trunk Message-ID: <20070622193829.A1A9F812D@code0.codespeak.net> Author: ltucker Date: Fri Jun 22 21:38:29 2007 New Revision: 44441 Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini Log: add transcluder_enabled flag to example Modified: z3/deliverance/DeliveranceVHoster/trunk/development.ini ============================================================================== --- z3/deliverance/DeliveranceVHoster/trunk/development.ini (original) +++ z3/deliverance/DeliveranceVHoster/trunk/development.ini Fri Jun 22 21:38:29 2007 @@ -63,6 +63,7 @@ # localhost - only localhsost # - only hosts matching the regex given # +transcluder_enabled = True transcluder_ok_hosts = openplans.org|(.*)\.openplans.org|(.*)\.localhost.openplans\.org|localhost transcluder_pool_size = 0 From ianb at codespeak.net Tue Jun 26 18:59:30 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 26 Jun 2007 18:59:30 +0200 (CEST) Subject: [z3-checkins] r44548 - z3/deliverance/trunk/deliverance Message-ID: <20070626165930.9B0FC80B6@code0.codespeak.net> Author: ianb Date: Tue Jun 26 18:59:28 2007 New Revision: 44548 Modified: z3/deliverance/trunk/deliverance/interpreter.py z3/deliverance/trunk/deliverance/utils.py Log: Improve the error message when you try to use attach_text_to_previous and there is no parent. Also avoid calling that function when there is no text to attach (which hopefully will keep this case from happening) Modified: z3/deliverance/trunk/deliverance/interpreter.py ============================================================================== --- z3/deliverance/trunk/deliverance/interpreter.py (original) +++ z3/deliverance/trunk/deliverance/interpreter.py Tue Jun 26 18:59:28 2007 @@ -445,7 +445,8 @@ for el in els: if isinstance(el, basestring): continue - self.attach_text_to_previous(el, el.tail) + if el.tail: + self.attach_text_to_previous(el, el.tail) el.getparent().remove(el) removed += 1 return removed Modified: z3/deliverance/trunk/deliverance/utils.py ============================================================================== --- z3/deliverance/trunk/deliverance/utils.py (original) +++ z3/deliverance/trunk/deliverance/utils.py Tue Jun 26 18:59:28 2007 @@ -284,12 +284,15 @@ def attach_text_to_previous(self,el,text): """ attaches the text given to the nearest previous node to el, - ie its preceding sibling or parent + ie its preceding sibling or parent """ if text is None: return - el_i = el.getparent().index(el) + parent = el.getparent() + assert parent is not None, ( + "Element %r has no parent" % el) + el_i = parent.index(el) if el_i > 0: sib_el = el.getparent()[el_i - 1] if sib_el.tail: From ianb at codespeak.net Tue Jun 26 20:26:02 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 26 Jun 2007 20:26:02 +0200 (CEST) Subject: [z3-checkins] r44549 - in z3/deliverance: branches/Attic trunk/Attic Message-ID: <20070626182602.9C4E480DA@code0.codespeak.net> Author: ianb Date: Tue Jun 26 20:26:02 2007 New Revision: 44549 Added: z3/deliverance/branches/Attic/ - copied from r44548, z3/deliverance/trunk/Attic/ Removed: z3/deliverance/trunk/Attic/ Log: Move old (Attic) stuff out of trunk From ianb at codespeak.net Tue Jun 26 21:55:53 2007 From: ianb at codespeak.net (ianb at codespeak.net) Date: Tue, 26 Jun 2007 21:55:53 +0200 (CEST) Subject: [z3-checkins] r44552 - z3/deliverance/trunk Message-ID: <20070626195553.3E92D80EA@code0.codespeak.net> Author: ianb Date: Tue Jun 26 21:55:51 2007 New Revision: 44552 Modified: z3/deliverance/trunk/README.txt z3/deliverance/trunk/setup.py Log: fiddling around with README.txt, added some stuff to setup.py for release Modified: z3/deliverance/trunk/README.txt ============================================================================== --- z3/deliverance/trunk/README.txt (original) +++ z3/deliverance/trunk/README.txt Tue Jun 26 21:55:51 2007 @@ -32,37 +32,39 @@ Quick Start to build Deliverance ----------------------------------- -The easiest way to get Deliverance installed is to checkout the -buildout and follow the instructions found there. +If you have recent versions of `lxml `_ +installed, along with its underlying library `libxml2 +`_, you should pretty much be okay. If you are +getting segfaults or warnings, you might need newer software. -$ svn co http://codespeak.net/svn/z3/deliverance/buildout/trunk +If so, one way to get Deliverance installed is to checkout the +buildout and follow the instructions found there:: + $ svn co http://codespeak.net/svn/z3/deliverance/buildout/trunk Otherwise, to install Deliverance manually, first get workingenv.py from http://cheeseshop.python.org/pypi/workingenv.py. Create a working -environment for Deliverance and its dependencies: - -$ workingenv.py deliverance_env -$ source deliverance_env/bin/activate +environment for Deliverance and its dependencies:: + $ workingenv.py deliverance_env + $ source deliverance_env/bin/activate Then install recent versions of libxml2, libxslt and lxml. You are likely to encounter segfaults and other failures if recent versions are not used. Checkout and setup Deliverance, then make sure your installation is -complete by running the tests: - -$ svn co http://codespeak.net/svn/z3/deliverance/trunk/ deliverance -$ cd deliverance -$ python setup.py develop -$ nosetests +complete by running the tests:: + $ svn co http://codespeak.net/svn/z3/deliverance/trunk/ deliverance + $ cd deliverance + $ python setup.py develop + $ nosetests -You can also run the tests like this: +You can also run the tests like this:: -$ deliverance_env/bin/deliverance-tests -$ deliverance_env/bin/deliverance-speed + $ deliverance_env/bin/deliverance-tests + $ deliverance_env/bin/deliverance-speed ---------------------------------------------- @@ -72,18 +74,19 @@ The deliverance proxy is a standalone application which serves a themed version of some web location using a theme and a set of rules. -eg: -$ deliverance-proxy --serve=localhost:5001 --proxy=localhost:8080 - --theme=http://www.example.org - --rule=file:///some/path/somerulesfile.xml +:: + + $ deliverance-proxy --serve=localhost:5001 --proxy=localhost:8080 + --theme=http://www.example.org + --rule=file:///some/path/somerulesfile.xml This example provides a themed version of a local webserver at port 8080 served on port 5001. The theme page is http://www.example.org and the rules are specified in somerulesfile.xml. -For more options, run: +For more options, run:: -$ deliverance-proxy --help + $ deliverance-proxy --help ------------------------------------------------ @@ -102,9 +105,9 @@ The command line tool used to execute Deliverance is called -deliverance-handtransform. For instructions, run: +deliverance-handtransform. For instructions, run:: -$ deliverance-handtransform --help + $ deliverance-handtransform --help The theme, rules and other parameters are specified using command line options -t, -r, etc. The result of the transform is output to @@ -113,16 +116,16 @@ To avoid lengthy command lines, the tool can accept a "blend" file, using the -f flag, which describes the theme and rules to apply. -eg: +eg:: -$ deliverance-handtransform -f ./blendfile.xml http://www.example.org + $ deliverance-handtransform -f ./blendfile.xml http://www.example.org The second argument refers to the content; blendfile.xml contains -something like: +something like:: - + @@ -130,31 +133,31 @@ Simple Tests ------------------------------------------------ -There are a number of tests in the test-data directory that follow the form: +There are a number of tests in the test-data directory that follow the form:: - - - - - ... rules as described at http://www.openplans.org/projects/deliverance/specification - - - - ... theme html - - - - ... content html - + + + + + ... rules as described at http://www.openplans.org/projects/deliverance/specification + + + + ... theme html + + + + ... content html + - - ... expected output of applying rules to theme and content - - + + ... expected output of applying rules to theme and content + + -... + ... - + ---------------------------------------------- WSGI Tests @@ -173,78 +176,77 @@ This is an unstyled page produced by myBoringTodoList.com/deliverance_user/: -this page is the content page: - - - - my boring todo page - - -
      -

      Things To Do

      -
        -
      • Feed the cat
      • -
      • Wash the dishes
      • -
      -
      - - +this page is the content page:: + + + my boring todo page + + +
      +

      Things To Do

      +
        +
      • Feed the cat
      • +
      • Wash the dishes
      • +
      +
      + + Here is another web page that typifies how we'd like to see the todo list at excitingHomePage.com/deliverance_user/. -this page is the theme: +this page is the theme:: - - - - my exciting home page - - -

      Deliverance User's Exciting Page

      -
      - I wish my todo list looked this cool -
      - - + + + + my exciting home page + + +

      Deliverance User's Exciting Page

      +
      + I wish my todo list looked this cool +
      + + Here are some deliverance rules that put the todo list into the exciting home page and take away the wish. This tells deliverance to replace the "wishes" div in the exciting home page with the -"todo" div in the content page. +"todo" div in the content page:: - + - - - - -Here is the output: - - - - - - my exciting home page - - -

      Deliverance User's Exciting Page

      -
      -

      Things To Do

      -
        -
      • Feed the cat
      • -
      • Wash the dishes
      • -
          -
      - - + + + + +Here is the output:: + + + + + + my exciting home page + + +

      Deliverance User's Exciting Page

      +
      +

      Things To Do

      +
        +
      • Feed the cat
      • +
      • Wash the dishes
      • +
          +
      + + see http://www.openplans.org/projects/deliverance for more information. There are many other examples in deliverance/test-data Modified: z3/deliverance/trunk/setup.py ============================================================================== --- z3/deliverance/trunk/setup.py (original) +++ z3/deliverance/trunk/setup.py Tue Jun 26 21:55:51 2007 @@ -4,16 +4,52 @@ setup(name="Deliverance", version=__version__, - description="", + description="Deliverance rewrites HTML to add theming", long_description="""\ +Deliverance rewrites HTML pages to theme the pages -- adding things +like navigation, stylesheets, and applying a common look-and-feel to +content from a variety of sources. + +Unlike typical templating systems, Deliverance works only on HTML; +there's no variables to substitute or Python structures involved. It +takes a simple set of rules and applies these to the HTML, so you can +style the output of pages regardless of where the page comes from. + +The theme itself is an HTML page with zero code in it. It is simply +an example of what a page should look like; this makes it accessible +to designers or any kind of tool, and may itself even be dynamically +generated. For instance, you might use a blog page as a theme, and +wrap that theme around a wiki to give the two a common look and feel. + +The rules are written in an XML format, that looks something like:: + + + + + + +This example, in addition to doing the 'standard' things (which +includes merging the ```` of both pages) also copies the tag +``
      `` into the theme page's +``
      ``. + +Deliverance is implemented as both a rendering object and WSGI +middleware. Included in the package is a script that uses the WSGI +middleware as an HTTP proxy. """, classifiers=[ - # dev status, license, HTTP categories - ], - keywords='', - author="Paul Everitt", - author_email="", - url="", + 'Development Status :: 4 - Beta', + 'Intended Audience :: Developers', + 'Topic :: Internet :: WWW/HTTP', + 'Topic :: Internet :: WWW/HTTP :: WSGI', + 'Topic :: Internet :: WWW/HTTP :: WSGI :: Middleware', + ], + keywords='templating html web wsgi middleware http proxy', + author="Deliverance Developer Community", + author_email="deliverance-devel at lists.openplans.org", + url="http://openplans.org/projects/deliverance", license="", packages=find_packages(exclude=[]), zip_safe=False,