[z3-checkins] r35100 - in z3/deliverance/DeliveranceDemo/trunk: . ddemo ddemo/controllers ddemo/public ddemo/templates ddemo/tests/functional

ianb at codespeak.net ianb at codespeak.net
Wed Nov 29 09:34:26 CET 2006


Author: ianb
Date: Wed Nov 29 09:34:07 2006
New Revision: 35100

Added:
   z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/remote_getter.py   (contents, props changed)
   z3/deliverance/DeliveranceDemo/trunk/ddemo/debuginterp.py   (contents, props changed)
   z3/deliverance/DeliveranceDemo/trunk/ddemo/public/selector.js
   z3/deliverance/DeliveranceDemo/trunk/ddemo/tests/functional/test_remote_getter.py   (contents, props changed)
Modified:
   z3/deliverance/DeliveranceDemo/trunk/ddemo/__init__.py
   z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/__init__.py
   z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/index.py
   z3/deliverance/DeliveranceDemo/trunk/ddemo/dataprovider.py
   z3/deliverance/DeliveranceDemo/trunk/ddemo/dispatcher.py
   z3/deliverance/DeliveranceDemo/trunk/ddemo/public/   (props changed)
   z3/deliverance/DeliveranceDemo/trunk/ddemo/templates/index.myt
   z3/deliverance/DeliveranceDemo/trunk/ddemo/wsgiapp.py
   z3/deliverance/DeliveranceDemo/trunk/development.ini
   z3/deliverance/DeliveranceDemo/trunk/setup.py
Log:
Updates to make it more automated, especially with the #openplans app

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/__init__.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/__init__.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/__init__.py	Wed Nov 29 09:34:07 2006
@@ -5,4 +5,11 @@
 
 """
 
+__all__ = ['current_environ', 'make_app']
+
+from paste import registry
+
+current_environ = registry.StackedObjectProxy(
+    name='environ')
+
 from ddemo.wsgiapp import make_app

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/__init__.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/__init__.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/__init__.py	Wed Nov 29 09:34:07 2006
@@ -3,6 +3,7 @@
 from pylons.decorators import jsonify, validate
 from pylons.templating import render, render_response
 from pylons.helpers import abort, redirect_to, etag_cache
+from paste.deploy import CONFIG
 import ddemo.helpers as h
 
 class BaseController(WSGIController):

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/index.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/index.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/index.py	Wed Nov 29 09:34:07 2006
@@ -1,18 +1,98 @@
 from ddemo.controllers import *
 import os
+import re
+import urlparse
+from paste.request import construct_url
+
+var_re = re.compile(r'[{](.*?)[}]')
+
+def find_template_values(template, value):
+    """
+    Parses the name/value out of a value, based on the template
+    """
+    if not value:
+        value = ''
+    regex = '^'
+    last_match = 0
+    for match in var_re.finditer(template):
+        regex += re.escape(template[last_match:match.start()])
+        regex += '(?P<%s>.*?)' % match.group(1)
+        last_match = match.end()
+    regex += re.escape(template[last_match:]) + '$'
+    result = {}
+    for match in var_re.finditer(template):
+        result[match.group(1)] = None
+    print 'regex: %r' % regex
+    match = re.search(regex, value)
+    if match:
+        result.update(match.groupdict())
+    return result
+
+def sub_template(template, vars):
+    def repl(match):
+        return vars[match.group(1)]
+    return var_re.sub(repl, template)
 
 class IndexController(BaseController):
+
+    builtin_vars = ['scheme', 'domain', 'port']
+    
     def index(self):
         if request.method == 'POST':
             return self.update()
         rule_fn = os.path.join(c.domain_info.rule_dir, 'rule.xml')
         c.rule_text = open(rule_fn, 'rb').read()
+        conf = CONFIG['app_conf']
+        if conf.get('remote_template'):
+            c.remote_template = find_template_values(
+                conf['remote_template'], c.domain_info.remote)
+            for key in self.builtin_vars:
+                c.remote_template.pop(key, None)
+        if conf.get('rule_template'):
+            c.rule_template = find_template_values(
+                conf['rule_template'], c.rule_text)
+        print c.rule_template, c.remote_template
         return render_response('index.myt')
 
     def update(self):
         params = request.params
+        conf = CONFIG['app_conf']
+        base = request.environ['ddemo.base_url']
         di = c.domain_info
+        base_parts = urlparse.urlsplit(base)
+        scheme, netloc, path, query, fragment = base_parts
+        if ':' in netloc:
+            domain, port = netloc.split(':', 1)
+        else:
+            domain = netloc
+            if scheme == 'http':
+                port = '80'
+            else:
+                port = '443'
+        if conf.get('remote_template'):
+            vars = {}
+            for name, value in params.items():
+                if not name.startswith('remote.'):
+                    continue
+                vars[name[len('remote.'):]] = value
+            vars['scheme'] = scheme
+            vars['netloc'] = netloc
+            vars['path'] = path
+            vars['domain'] = domain
+            vars['port'] = port
+            di.remote = sub_template(conf['remote_template'], vars)
+        else:
+            di.remote = params['remote']
         di.theme_uri = params['theme_uri']
-        di.remote = params['remote']
-        di.set_rule_file('rule.xml', params['rule_xml'])
+        if conf.get('rule_template'):
+            vars = {}
+            for name, value in params.items():
+                if not name.startswith('rule.'):
+                    continue
+                vars[name[len('rule.'):]] = value
+            text = sub_template(conf['rule_template'], vars)
+        else:
+            text = params['rule_xml']
+        text = text.strip()
+        di.set_rule_file('rule.xml', text)
         redirect_to()

Added: z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/remote_getter.py
==============================================================================
--- (empty file)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/controllers/remote_getter.py	Wed Nov 29 09:34:07 2006
@@ -0,0 +1,28 @@
+from ddemo.controllers import *
+from wsgiremote.lxmlformat import xml as lxml_format
+from wsgiremote.json import json as json_format
+from wsgiremote import BadRequestError
+
+class RemoteGetterController(BaseController):
+
+    good_tags = 'body div td'.split()
+    
+    def index(self):
+        url = request.params['url']
+        print 'getting', url
+        try:
+            data = lxml_format.GET(url)
+        except BadRequestError, e:
+            result = {'error': 'Bad request to %s: %s' % (url, e)}
+        else:
+            result = []
+            for el in data.xpath('//*[@id]'):
+                if el.tag.lower() not in self.good_tags:
+                    continue
+                if not len(el):
+                    # Empty elements aren't good candidates
+                    continue
+                result.append(el.attrib['id'])
+        app = json_format.responder(result)
+        return app(request.environ, self.start_response)
+

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/dataprovider.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/dataprovider.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/dataprovider.py	Wed Nov 29 09:34:07 2006
@@ -5,7 +5,6 @@
 
 default_rule_xml = '''\
 <?xml version="1.0" encoding="UTF-8"?>
- 
 <rules xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://www.plone.org/deliverance" >
   <xi:include href="standardrules.xml" />
 
@@ -13,6 +12,17 @@
 </rules>
 '''
 
+marker = '<!-- Generated, do not edit! -->'
+abstract_rule_xml = '''\
+<?xml version="1.0" encoding="UTF-8"?>
+MARKER
+<rules xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://www.plone.org/deliverance" >
+  <xi:include href="standardrules.xml" />
+
+  <copy theme="//*[%(theme_expr)s]" content="//*[%(content_expr)s]" />
+</rules>
+'''.replace('MARKER', marker)
+
 default_standardrules = '''\
 <?xml version="1.0" encoding="UTF-8"?>
 <rules xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://www.plone.org/deliverance">
@@ -118,6 +128,8 @@
     
     remote = file_property('remote.txt')
     theme_uri = file_property('theme_uri.txt')
+    theme_id = file_property('theme_id.txt')
+    rule_ids = file_property('rule_ids.txt')
 
     def set_rule_file(self, filename, content):
         filename = os.path.join(self.rule_dir, filename)
@@ -125,3 +137,4 @@
         f.write(content)
         f.close()
         
+

Added: z3/deliverance/DeliveranceDemo/trunk/ddemo/debuginterp.py
==============================================================================
--- (empty file)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/debuginterp.py	Wed Nov 29 09:34:07 2006
@@ -0,0 +1,31 @@
+from deliverance.interpreter import Renderer as PyRenderer
+from lxml import etree
+from paste.request import construct_url
+from ddemo import current_environ
+
+class Renderer(PyRenderer):
+
+    error_style = "background-color: #ff9; color: #000; border: 1px solid #000;"
+
+    def format_error(self, message, rule, elts=None):
+        error = super(PyRenderer, self).format_error(message, rule, elts)
+        error_container = etree.Element('div')
+        error_container.attrib['style'] = self.error_style
+        if not current_environ.get('ddemo.has_errors'):
+            current_environ['ddemo.has_errors'] = True
+            domain_info = current_environ['ddemo.domain_info']
+            remote = domain_info.remote
+            remote += current_environ.get('PATH_INFO', '')
+            if current_environ.get('QUERY_STRING'):
+                remote += '?' + current_environ['QUERY_STRING']
+            link = etree.Element('a')
+            link.attrib['href'] = remote
+            link.attrib['target'] = '_blank'
+            link.text = 'View original content source'
+            container = etree.Element('div')
+            container.append(link)
+            error_container.append(container)
+        error_container.append(error)
+        return error_container
+            
+        

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/dispatcher.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/dispatcher.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/dispatcher.py	Wed Nov 29 09:34:07 2006
@@ -8,6 +8,8 @@
 from wsgifilter import relocateresponse
 from deliverance.wsgimiddleware import DeliveranceMiddleware
 from ddemo.dataprovider import DataProvider
+from ddemo import current_environ
+from ddemo.debuginterp import Renderer
 
 def norm_path(urlpath):
     if not urlpath:
@@ -24,13 +26,17 @@
         self.provider = DataProvider(data_dir)
 
     def __call__(self, environ, start_response):
+        if 'paste.registry' in environ:
+            environ['paste.registry'].register(current_environ, environ)
         domain = environ['HTTP_HOST']
         if ':' in domain:
             domain = domain.split(':', 1)[0]
         domain_info = self.provider.domain(domain)
         environ['ddemo.domain_info'] = domain_info
+        environ['ddemo.base_url'] = construct_url(
+            environ, with_query_string=False,
+            path_info='')
         path_info = norm_path(environ.get('PATH_INFO', ''))
-        print 'request: %r' % path_info
         if path_info.startswith('/_deliverance'):
             path_info_pop(environ)
             return self.pylons_app(environ, start_response)
@@ -66,7 +72,8 @@
         app = DeliveranceMiddleware(
             app,
             theme_uri=domain_info.theme_uri,
-            rule_uri=rule_uri)
+            rule_uri=rule_uri,
+            renderer=Renderer)
         return app(environ, start_response)
 
     def find_file(self, path):

Added: z3/deliverance/DeliveranceDemo/trunk/ddemo/public/selector.js
==============================================================================
--- (empty file)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/public/selector.js	Wed Nov 29 09:34:07 2006
@@ -0,0 +1,66 @@
+function selectId(button, destName) {
+    var oldHTML = button.innerHTML;
+    button.innerHTML = 'reading...';
+    button.disabled = true;
+    selectIdSafe(destName);
+    button.innerHTML = oldHTML;
+    button.disabled = false;
+    return false;
+}
+
+function selectIdSafe(destName) {
+    var form = document.forms[0];
+    var url = form.elements.theme_uri.value;
+    if (! url) {
+        alert('You must first give a theme URI');
+        return;
+    }
+    var real_url = remote_getter_url + '?url=' + escape(url);
+    req = loadJSONDoc(real_url);
+    req.addCallbacks(function (req) {
+                        selectIdSuccess(req, destName);
+                     },
+                     function (err) {
+                         selectIdFail(err, destName);
+                     });
+}
+
+function selectIdSuccess(ids, destName) {
+    try {
+        selectIdSuccessNoError(ids, destName);
+    } catch (e) {
+        alert('Error: '+e);
+    }
+}
+
+function selectIdSuccessNoError(ids, destName) {
+    if (ids.error) {
+        alert('Error fetching Theme URL: '+ids.error);
+        return;
+    }
+    var form = document.forms[0];
+    var el = form[destName];
+    var selected = el.value;
+    var parent = el.parentNode;
+    var newEl = SELECT({name: destName});
+    for (var i=0; i<ids.length; i++) {
+        var newOp = OPTION({value: ids[i]}, ids[i]);
+        if (ids[i] == selected) {
+            newOp.selected = true;
+        }
+        newEl.appendChild(newOp);
+    }
+    parent.insertBefore(newEl, el);
+    parent.removeChild(el);
+}
+
+function selectIdFail(err, destName) {
+    alert(err);
+}
+
+function visitTheme() {
+    var form = document.forms[0];
+    var url = form.theme_uri.value;
+    window.open(url);
+    return false;
+}
\ No newline at end of file

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/templates/index.myt
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/templates/index.myt	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/templates/index.myt	Wed Nov 29 09:34:07 2006
@@ -1,28 +1,68 @@
 <html>
  <head>
   <title>Administration for <% c.domain_info.domain_name | h %></title>
+  <script type="text/javascript" src="<% h.url_for('MochiKit/MochiKit.js') %>"></script>
+  <script type="text/javascript" src="<% h.url_for('selector.js') %>"></script>
+  <script type="text/javascript">
+    remote_getter_url = '<% h.url_for(controller='remote_getter') %>';
+  </script>
+
  </head>
  <body>
 
 <h1>Administration for <% c.domain_info.domain_name | h %></h1>
 
-<p><a href="/">Visit the site</a></p>
+<p><a href="/" target="_blank">Visit the site</a></p>
 
 <form action="<% h.url_for(controller='index') %>" method="POST">
+
+% if c.remote_template:
+%   for name, value in sorted(c.remote_template.items()):
+     <% name %>:<br>
+     <input type="text" name="remote.<% name | h%>"
+      value="<% value | h %>"
+      style="width: 100%"><br>
+%   #endfor
+% else:
   Remote URL:<br>
    <input type="text" name="remote"
     value="<% c.domain_info.remote | h %>"
     style="width: 100%"><br>
+% #endif
+
   Theme URL:<br>
    <input type="text" name="theme_uri"
     value="<% c.domain_info.theme_uri | h %>"
-    style="width: 100%"><br>
+    style="width: 80%">
+   <a href="#" onclick="return visitTheme()">view</a>
+   <br>
+
+% if c.rule_template:
+%   for name, value in sorted(c.rule_template.items()):
+      <% name %>:<br>
+      <input type="text" name="rule.<% name | h %>"
+       value="<% value | h %>">
+%     if name.endswith('_id'):
+        <a href="#" onclick="return selectId(this, 'rule.<% name | h %>')">
+          read ids
+        </a>
+%     #endif
+      <br>
+%   #endfor
+% else:
   Rule:<br>
    <textarea name="rule_xml" rows=10
     style="width: 100%"><% c.rule_text | h %></textarea><br>
+% #endif
+
   <button type="submit">Save</button>
 </form>
 
+% if c.rule_template:
+<hr noshade>
+Current rules:
+<pre><% c.rule_text | h %></pre>
+% #endif
 
  </body>
 </html>

Added: z3/deliverance/DeliveranceDemo/trunk/ddemo/tests/functional/test_remote_getter.py
==============================================================================
--- (empty file)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/tests/functional/test_remote_getter.py	Wed Nov 29 09:34:07 2006
@@ -0,0 +1,6 @@
+from ddemo.tests import *
+
+class TestRemoteGetterController(TestController):
+    def test_index(self):
+        response = self.app.get(url_for(controller='remote_getter'))
+        # Test response...
\ No newline at end of file

Modified: z3/deliverance/DeliveranceDemo/trunk/ddemo/wsgiapp.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/ddemo/wsgiapp.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/ddemo/wsgiapp.py	Wed Nov 29 09:34:07 2006
@@ -53,8 +53,6 @@
         app = httpexceptions.make_middleware(app, global_conf)
         app = ErrorHandler(app, global_conf, error_template=error_template, **config.errorware)
     
-    app = RegistryManager(app)
-    
     static_app = StaticURLParser(config.paths['static_files'])
     javascripts_app = StaticJavascripts()
     app = Cascade([static_app, javascripts_app, app])
@@ -62,6 +60,7 @@
     app = RecursiveMiddleware(app)
     if asbool(app_conf.get('debug_headers')):
         app = proxyapp.DebugHeaders(app)
+    app = RegistryManager(app)
     if (asbool(full_stack)
         and asbool(app_conf.get('debug', global_conf.get('debug')))):
         from paste.evalexception import EvalException

Modified: z3/deliverance/DeliveranceDemo/trunk/development.ini
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/development.ini	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/development.ini	Wed Nov 29 09:34:07 2006
@@ -39,4 +39,13 @@
 # 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 = false
+set debug = true
+
+[app:openplans]
+use = main
+remote_template = http://norewrite.openplans.org/VirtualHostBase/{scheme}/{domain}:{port}/openplans/projects/{project}/VirtualHostRoot/
+rule_template = <?xml version="1.0" encoding="UTF-8"?>
+    <rules xmlns:xi="http://www.w3.org/2001/XInclude" xmlns="http://www.plone.org/deliverance" >
+      <xi:include href="standardrules.xml" />
+      <copy theme="//*[@id='{theme_id}']" content="//*[@id='content']" />
+    </rules>

Modified: z3/deliverance/DeliveranceDemo/trunk/setup.py
==============================================================================
--- z3/deliverance/DeliveranceDemo/trunk/setup.py	(original)
+++ z3/deliverance/DeliveranceDemo/trunk/setup.py	Wed Nov 29 09:34:07 2006
@@ -11,6 +11,7 @@
       "Pylons>=0.9.3",
       'Deliverance',
       'WSGIFilter',
+      'WSGIRemote',
       ],
     packages=find_packages(),
     include_package_data=True,


More information about the z3-checkins mailing list