[z3-checkins] r51663 - in z3/deliverance/branches/urienv/deliverance: . test-data/urienv

tseaver at codespeak.net tseaver at codespeak.net
Wed Feb 20 01:02:15 CET 2008


Author: tseaver
Date: Wed Feb 20 01:02:13 2008
New Revision: 51663

Added:
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/example.html
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_rule_uri_environ.html
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_theme_uri_environ.html
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_uppercase.html
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules.xml
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules2.xml
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme.html
   z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme2.html
Modified:
   z3/deliverance/branches/urienv/deliverance/test_wsgi.py
   z3/deliverance/branches/urienv/deliverance/utils.py
   z3/deliverance/branches/urienv/deliverance/wsgimiddleware.py
Log:
Snapshot work for tweaking Deliverance URIs / serializer via WSGI environ.

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/example.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/example.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,10 @@
+<html>
+ <head>
+  <title>I am a title</title>
+  <link rel="rss" href="/rss.xml" />
+ </head>
+ <body>Early text<p>Paragraph one</p>
+   <p>Paragraph two</p>
+   extra
+ </body>
+</html>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_rule_uri_environ.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_rule_uri_environ.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,13 @@
+<html>
+ <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>I am a title</title>
+  <link rel="rss" href="/rss.xml" />
+ </head>
+ <body>
+   Some text
+   <div id="content">
+   <p>Paragraph one</p>
+   </div>
+ </body>
+</html>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_theme_uri_environ.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_theme_uri_environ.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,14 @@
+<html>
+ <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>I am a title</title>
+  <link rel="rss" href="/rss.xml" />
+ </head>
+ <body>
+   Theme 2 text
+   <div id="content">
+   <p>Paragraph one</p>
+   <p>Paragraph two</p>
+   </div>
+ </body>
+</html>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_uppercase.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/example_expected_uppercase.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 TRANSITIONAL//EN" "HTTP://WWW.W3.ORG/TR/HTML4/LOOSE.DTD">
+<HTML>
+<HEAD>
+<META HTTP-EQUIV="CONTENT-TYPE" CONTENT="TEXT/HTML; CHARSET=UTF-8">
+<TITLE>I AM A TITLE</TITLE>
+<LINK REL="RSS" HREF="/RSS.XML" />
+</HEAD>
+<BODY>
+  SOME TEXT
+  <DIV ID="CONTENT">
+<P>PARAGRAPH ONE</P>
+<P>PARAGRAPH TWO</P>
+</DIV>
+</BODY>
+</HTML>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules.xml	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+  <rules xmlns="http://www.plone.org/deliverance">
+    <append-or-replace theme="//head" content="//head/title" />
+    <append theme="//head" content="//head/link" />
+    <append theme="//head" content="//head/script" onerror="ignore" />    
+    <append theme="//head" content="//head/style" onerror="ignore" />    
+    <append theme="//head" content="//head/meta" onerror="ignore" />
+    <copy theme="//div[@id='content']" content="//body/*" />
+  </rules>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules2.xml
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/rules2.xml	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+  <rules xmlns="http://www.plone.org/deliverance">
+    <append-or-replace theme="//head" content="//head/title" />
+    <append theme="//head" content="//head/link" />
+    <append theme="//head" content="//head/script" onerror="ignore" />    
+    <append theme="//head" content="//head/style" onerror="ignore" />    
+    <append theme="//head" content="//head/meta" onerror="ignore" />
+    <copy theme="//div[@id='content']" content="//body/p[1]" />
+  </rules>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,9 @@
+<html>
+ <head>
+  <title>Example</title>
+ </head>
+ <body>
+  Some text
+  <div id="content">replace this</div>
+</body>
+</html>

Added: z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme2.html
==============================================================================
--- (empty file)
+++ z3/deliverance/branches/urienv/deliverance/test-data/urienv/theme2.html	Wed Feb 20 01:02:13 2008
@@ -0,0 +1,9 @@
+<html>
+ <head>
+  <title>Example</title>
+ </head>
+ <body>
+  Theme 2 text
+  <div id="content">replace this</div>
+</body>
+</html>

Modified: z3/deliverance/branches/urienv/deliverance/test_wsgi.py
==============================================================================
--- z3/deliverance/branches/urienv/deliverance/test_wsgi.py	(original)
+++ z3/deliverance/branches/urienv/deliverance/test_wsgi.py	Wed Feb 20 01:02:13 2008
@@ -23,6 +23,7 @@
 aggregate_data = os.path.join(os.path.dirname(__file__), 'test-data', 'aggregate')
 aggregate2_data = os.path.join(os.path.dirname(__file__), 'test-data', 'aggregate2')
 ignore_data = os.path.join(os.path.dirname(__file__), 'test-data', 'ignore')
+urienv_data = os.path.join(os.path.dirname(__file__), 'test-data', 'urienv')
 
 static_app = StaticURLParser(static_data)
 tasktracker_app = StaticURLParser(tasktracker_data)
@@ -34,6 +35,7 @@
 aggregate_app = StaticURLParser(aggregate_data)
 aggregate2_app = StaticURLParser(aggregate2_data)
 ignore_app = StaticURLParser(ignore_data)
+urienv_app = StaticURLParser(urienv_data)
 
 def html_string_compare(astr, bstr):
     """
@@ -313,11 +315,51 @@
                   headers={'If-Modified-Since': formatdate(then-15)})
     status = res.status
     assert(status == 200)
+
+def do_rule_uri_environ(renderer_type, name):
+    from deliverance.utils import setRuleURI
+    wsgi_app = DeliveranceMiddleware(urienv_app, 'theme.html', 'rules.xml',
+                                     renderer_type)
+    environ = {}
+    setRuleURI(environ, 'rules2.xml')
+    app = TestApp(wsgi_app, extra_environ=environ)
+    res = app.get('/example.html')
+    res2 = app.get('/example_expected_rule_uri_environ.html?notheme')
+    html_string_compare(res.body, res2.body)
+
+def do_theme_uri_environ(renderer_type, name):
+    from deliverance.utils import setThemeURI
+    wsgi_app = DeliveranceMiddleware(urienv_app, 'theme.html', 'rules.xml',
+                                     renderer_type)
+    environ = {}
+    setThemeURI(environ, 'theme2.html')
+    app = TestApp(wsgi_app, extra_environ=environ)
+    res = app.get('/example.html')
+    res2 = app.get('/example_expected_theme_uri_environ.html?notheme')
+    html_string_compare(res.body, res2.body)
     
+def do_serializer_environ(renderer_type, name):
+    from deliverance.utils import setSerializer
+    wsgi_app = DeliveranceMiddleware(urienv_app, 'theme.html', 'rules.xml',
+                                     renderer_type)
+    environ = {}
+    setSerializer(environ, 'deliverance.test_wsgi:_uppercaseTextNodes')
+    app = TestApp(wsgi_app, extra_environ=environ)
+    res = app.get('/example.html')
+    res2 = app.get('/example_expected_uppercase.html?notheme')
+    html_string_compare(res.body, res2.body)
+
 
+def _uppercaseTextNodes(content):
+    from htmlserialize import tostring
+    return tostring(content,
+                    doctype_pair=("-//W3C//DTD HTML 4.01 Transitional//EN",
+                                  "http://www.w3.org/TR/html4/loose.dtd")
+                   ).upper()
 
 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_aggregate2, do_cache, do_ignore, do_ignore_header ] 
+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, do_ignore, do_ignore_header, do_rule_uri_environ, do_theme_uri_environ, do_serializer_environ ] 
+
 def test_all():
     for renderer_type in RENDERER_TYPES:
         for test_func in TEST_FUNCS: 

Modified: z3/deliverance/branches/urienv/deliverance/utils.py
==============================================================================
--- z3/deliverance/branches/urienv/deliverance/utils.py	(original)
+++ z3/deliverance/branches/urienv/deliverance/utils.py	Wed Feb 20 01:02:13 2008
@@ -535,3 +535,37 @@
         text = etree.tostring(rule)
         text = text.replace(' xmlns="http://www.plone.org/deliverance"', '')
         return text
+
+# API for sharing overridden theme / rule URIs with other middleware layers.
+
+_THEME_URI_KEY = 'deliverance.theme_uri'
+
+def setThemeURI(environ, uri):
+    environ[_THEME_URI_KEY] = uri
+
+def getThemeURI(environ, default=None):
+    return environ.get(_THEME_URI_KEY, default)
+
+_RULE_URI_KEY = 'deliverance.rule_uri'
+
+def setRuleURI(environ, uri):
+    environ[_RULE_URI_KEY] = uri
+
+def getRuleURI(environ, default=None):
+    return environ.get(_RULE_URI_KEY, default)
+
+_SERIALIZER_KEY = 'deliverance.serializer'
+
+def setSerializer(environ, dotted_or_egg):
+    environ[_SERIALIZER_KEY] = dotted_or_egg
+
+def getSerializer(environ, default=None):
+    dotted_or_egg = environ.get(_SERIALIZER_KEY, default)
+    if isinstance(dotted_or_egg, basestring):
+        return _resolveDottedOrEgg(dotted_or_egg)
+    return dotted_or_egg
+
+def _resolveDottedOrEgg(dotted_or_egg):
+    from pkg_resources import EntryPoint
+    return EntryPoint.parse('x=%s' % dotted_or_egg).load(False)
+

Modified: z3/deliverance/branches/urienv/deliverance/wsgimiddleware.py
==============================================================================
--- z3/deliverance/branches/urienv/deliverance/wsgimiddleware.py	(original)
+++ z3/deliverance/branches/urienv/deliverance/wsgimiddleware.py	Wed Feb 20 01:02:13 2008
@@ -15,6 +15,9 @@
 from htmlserialize import tostring
 from deliverance.utils import DeliveranceError
 from deliverance.utils import DELIVERANCE_ERROR_PAGE
+from deliverance.utils import getThemeURI
+from deliverance.utils import getRuleURI
+from deliverance.utils import getSerializer
 from deliverance.resource_fetcher import InternalResourceFetcher, FileResourceFetcher, ExternalResourceFetcher
 from deliverance import cache_utils
 import sys 
@@ -33,6 +36,11 @@
 
 IGNORE_URL_PATTERN = re.compile("^.*\.(%s)$" % '|'.join(IGNORE_EXTENSIONS))
 
+def _toHTML(content):
+    return tostring(content,
+                    doctype_pair=("-//W3C//DTD HTML 4.01 Transitional//EN",
+                                  "http://www.w3.org/TR/html4/loose.dtd"))
+
 class DeliveranceMiddleware(object):
     """
     a DeliveranceMiddleware object exposes a single deliverance 
@@ -41,7 +49,7 @@
 
     def __init__(self, app, theme_uri, rule_uri,
                  renderer='py', merge_cache_control=False,
-                 is_internal_uri=None):
+                 is_internal_uri=None, serializer=None):
         """
         initializer
         
@@ -60,6 +68,9 @@
           should be considered 'internal'(passed to the
           subapplication) and false if the requestshould be send
           over the network. 
+        serializer:  dotted name or entry point indicdating a callable used
+          to post-process rendered output.  Defaults to the '_toHTML' function
+          above.
         """
         self.app = app
         self.theme_uri = theme_uri
@@ -78,6 +89,9 @@
             self._rendererType = renderer
 
         self._is_internal_uri = is_internal_uri
+        if serializer is None:
+            serializer = _toHTML
+        self.serializer = serializer
 
     def get_renderer(self, environ):
         return self.create_renderer(environ)
@@ -88,11 +102,11 @@
         information passed to the initializer.  A new copy 
         of the theme and rules is retrieved. 
         """
-        theme = self.theme(environ)
-        rule = self.rule(environ)
+        theme, theme_uri = self.theme(environ)
+        rule, rule_uri = self.rule(environ)
         full_theme_uri = urlparse.urljoin(
             construct_url(environ, with_path_info=False),
-            self.theme_uri)
+            theme_uri)
 
         def reference_resolver(href, parse, encoding=None):
             text = self.get_resource(environ, href)
@@ -109,7 +123,7 @@
         try:
             parsedTheme = parseHTML(theme)
         except Exception, message:
-            newmessage = "Unable to parse theme page (" + self.theme_uri + ")"
+            newmessage = "Unable to parse theme page (" + theme_uri + ")"
             if message:
                 newmessage += ":" + str(message)
             raise DeliveranceError(newmessage)
@@ -124,33 +138,40 @@
             theme=parsedTheme,
             theme_uri=full_theme_uri,
             rule=parsedRule, 
-            rule_uri=self.rule_uri,
+            rule_uri=rule_uri,
             reference_resolver=reference_resolver)
 
-    def rule(self, environ):
-        """
+    def rule(self, environ=None):
+        """ environ -> (rule, rule_uri)
         retrieves the data referred to by the rule_uri passed to the 
         initializer. 
         """
+        if environ is None:
+            environ = {}
+        rule_uri = getRuleURI(environ, self.rule_uri)
         try:
-            return self.get_resource(environ, self.rule_uri)
+            return (self.get_resource(environ, rule_uri), rule_uri)
         except Exception, message:
-            newmessage = "Unable to retrieve rules from " + self.rule_uri 
+            newmessage = "Unable to retrieve rules from " + rule_uri 
             if message:
                 newmessage += ": " + str(message)
 
             raise DeliveranceError(newmessage)
 
-    def theme(self, environ):
-        """
+    def theme(self, environ=None):
+        """ environ -> (theme, theme_uri)
+
         retrieves the data referred to by the theme_uri passed to the 
         initializer. 
         """
+        if environ is None:
+            environ = {}
+        theme_uri = getThemeURI(environ, self.theme_uri)
         try:
-            return self.get_resource(environ, self.theme_uri)
+            return (self.get_resource(environ, theme_uri), theme_uri)
         except Exception, message:
             message.public_html = 'Unable to retrieve theme page from %s: %s' % (
-                self.theme_uri, message)
+                theme_uri, message)
             raise
 
     def __call__(self, environ, start_response):
@@ -232,12 +253,12 @@
     def filter_body(self, environ, body):
         """
         returns the result of the deliverance transformation on the string 'body' 
-        in the context of environ. The result is a string containing HTML. 
+        in the context of environ. The result is a string containing HTML,
+        or whatever the configured serializer makes it.
         """
         content = self.get_renderer(environ).render(parseHTML(body))
-
-        return tostring(content, doctype_pair=("-//W3C//DTD HTML 4.01 Transitional//EN",
-                                               "http://www.w3.org/TR/html4/loose.dtd"))
+        serializer = getSerializer(environ, self.serializer)
+        return serializer(content)
 
 
     def rebuild_check(self, environ, start_response): 
@@ -284,8 +305,8 @@
             return (status, headers, body)
             
         # got 304 Not Modified for content, check other resources 
-        rules = etree.XML(self.rule(environ))
-        resources = self.get_resource_uris(rules)        
+        rules = etree.XML(self.rule(environ)[0])
+        resources = self.get_resource_uris(rules, environ)        
         if self.any_modified(environ, resources, etag_map): 
             # something changed, 
             # get the content explicitly and give it back 
@@ -425,14 +446,18 @@
         return cleaned
     
 
-    def get_resource_uris(self, rules): 
+    def get_resource_uris(self, rules, environ=None): 
         """
         retrieves a list of uris pointing to the resources that 
         are components of rendering (excluding content) 
         """
+        if environ is None:
+            environ = {}
         resources = Set()
-        resources.add(self.rule_uri)
-        resources.add(self.theme_uri)
+        rule_uri = getRuleURI(environ, self.rule_uri)
+        resources.add(rule_uri)
+        theme_uri = getThemeURI(environ, self.theme_uri)
+        resources.add(theme_uri)
 
         for rule in rules: 
             href = rule.get("href",None)


More information about the z3-checkins mailing list