Commits

Olemis Lang  committed d59586e

BH Dashboard #45 : Refreshing patch for layout XML against r1418864

  • Participants
  • Parent commits 5bda384
  • Branches t45_widget_markup

Comments (0)

Files changed (3)

 #hgsvn/rm_files.diff
-t45/t45_r1357341_layout_xml.diff
+t45/t45_r1418864_layout_xml.diff

File t45/t45_r1357341_layout_xml.diff

-# HG changeset patch
-# Parent 445f7b6f6fc16feab588e3abbbb485cb7ab6858d
-BH Dashboard #45 : Parsing bh:layout tags in layout XML markup
-
-diff -r 445f7b6f6fc1 bhdashboard/layouts/templates/widget_macros.html
---- a/bhdashboard/layouts/templates/widget_macros.html	Mon Jul 09 16:16:39 2012 -0400
-+++ b/bhdashboard/layouts/templates/widget_macros.html	Wed Jul 11 00:28:12 2012 -0400
-@@ -70,7 +70,7 @@
-     <py:choose test="">
-       <py:when test="bhdb">
-         <!--! TODO: Implement nested XML tags (e.g. bh:w and bh:l) -->
--        ${bhdb.embed_layout(context, layout=unicode(select('@urn')), schema=unicode(select('bh:schema/text()')), widgets=unicode(select('bh:widgets/text()')))}
-+        ${bhdb.embed_layout(context, layout=unicode(select('@urn')), schema=unicode(select('bh:schema/text()')), widgets=select('bh:widgets'))}
-       </py:when>
-       <py:otherwise>
-         ${bhnotfound()}
-diff -r 445f7b6f6fc1 bhdashboard/util.py
---- a/bhdashboard/util.py	Mon Jul 09 16:16:39 2012 -0400
-+++ b/bhdashboard/util.py	Wed Jul 11 00:28:12 2012 -0400
-@@ -30,6 +30,9 @@
- from urlparse import urlparse
- from wsgiref.util import setup_testing_defaults
- 
-+from genshi.core import Stream
-+from genshi.filters.transform import StreamBuffer
-+
- from trac.core import Component, implements, ExtensionPoint
- from trac.web.api import Request
- from trac.web.chrome import add_link, Chrome
-@@ -196,4 +199,43 @@
-             minval = value
-     return dict(min=minval, max=maxval)
- 
-+#------------------------------------------------------
-+#    Genshi tricks
-+#------------------------------------------------------
- 
-+def split_elements(stream):
-+    """List sub-streams of current stream element.
-+
-+    Note: Stream must be positioned immediately before parsing that element
-+    i.e. next event kind has to be ENTER
-+    """
-+    stream = iter(stream)
-+    kind, data, _ = stream.next()
-+    # Skip namespace events
-+    while kind == Stream.START_NS:
-+        kind, data, _ = stream.next()
-+
-+    # At the beginning of parent element
-+    assert kind == Stream.START
-+    for kind, data, pos in stream:
-+        if kind == Stream.START :
-+            # At the beginning of the next sub-element
-+            depth = 1
-+            buffer = StreamBuffer()
-+            buffer.append((kind, data, pos))
-+            for kind, data, pos in stream:
-+                if kind == Stream.START:
-+                    depth += 1
-+                elif kind == Stream.END:
-+                    depth -= 1
-+                buffer.append((kind, data, pos))
-+                if depth == 0:
-+                    break
-+            yield buffer
-+        elif kind == Stream.END:
-+            # End of parent element, nothing else to do
-+            break
-+        else:
-+            # Skip other events
-+            pass
-+
-diff -r 445f7b6f6fc1 bhdashboard/web_ui.py
---- a/bhdashboard/web_ui.py	Mon Jul 09 16:16:39 2012 -0400
-+++ b/bhdashboard/web_ui.py	Wed Jul 11 00:28:12 2012 -0400
-@@ -32,7 +32,7 @@
- from uuid import uuid4
- 
- from genshi.builder import tag
--from genshi.core import Stream
-+from genshi.core import QName, Stream
- from trac.core import Component, implements
- from trac.config import Option, IntOption
- from trac.mimeview.api import Context
-@@ -47,6 +47,7 @@
- 
- from bhdashboard.api import DashboardSystem, InvalidIdentifier
- from bhdashboard import _json
-+from bhdashboard.util import split_elements
- 
- class DashboardModule(Component):
-     """Web frontend for dashboard infrastructure.
-@@ -306,14 +307,12 @@
-         if isinstance(schema, basestring):
-             schema = _json.loads(schema)
-         widgets = kwargs.get('widgets')
--        if widgets is not None:
--            # TODO: Use this one once widgets markup parser will be ready
--            #widgets = parse_widgets_markup(widgets)
--            if isinstance(widgets, basestring):
--                widgets = _json.loads(widgets)
-+        if isinstance(widgets, basestring):
-+            schema['widgets'] = _json.loads(widgets)
-+        elif isinstance(widgets, Stream):
-+            schema = parse_widgets_tag(widgets, schema)
-         else:
--            widgets = {}
--        schema['widgets'] = widgets
-+            schema['widgets'] = {}
-         template, layout_data = dbmod.expand_layout_data(
-                 context.req, layout, schema, True)
-         widgets = dbmod.expand_widget_data(context.req, layout_data)
-@@ -366,9 +365,50 @@
-         elif kind == Stream.TEXT:
-             argvalue += data
-         elif kind == Stream.END:
-+            qname = data
-             if qname.namespace == XMLNS_DASHBOARD_UI \
-                     and qname.localname == 'arg':
-                 args[argnm] = argvalue
-                 inside = False
-     return args
- 
-+def parse_widgets_tag(stream, schema):
-+    """Parse Genshi markup for widgets in layout tags
-+    """
-+    if isinstance(schema, basestring):
-+        schema = _json.loads(schema)
-+    widgets = {}
-+    WIDGET_TAG = QName(XMLNS_DASHBOARD_UI + '}w')
-+    LAYOUT_TAG = QName(XMLNS_DASHBOARD_UI + '}l')
-+
-+    def option_value(value):
-+        try:
-+            return _json.loads(value)
-+        except:
-+            return value
-+
-+    for widget_spec in split_elements(stream):
-+        kind, (qname, attrs), _ = iter(widget_spec).next()
-+        wid = attrs.get('id')
-+        if qname == WIDGET_TAG:
-+            wtype = attrs.get('urn')
-+            wopts = dict((k.localname, option_value(v)) \
-+                    for k,v in attrs if k not in ('id', 'urn'))
-+            wargs = parse_args_tag(widget_spec.select('args'))
-+            widget = {'args' : [wtype, None, {'args' : wargs}] }
-+            widget.update(wopts)
-+        elif qname == LAYOUT_TAG:
-+            ltype = attrs.get('urn')
-+            title = attrs.get('title')
-+            lschema = parse_widgets_tag(widget_spec.select('widgets'), 
-+                    unicode(widget_spec.select('schema/text()')))
-+            widget = {'args' : ['Container', None, 
-+                    {'args': {
-+                            'layout' : ltype,
-+                            'schema' : _json.dumps(lschema)}}]}
-+            if title is not None:
-+                widget['args'][2]['args']['title'] = title
-+        widgets[wid] = widget
-+    schema['widgets'] = widgets
-+    return schema
-+

File t45/t45_r1418864_layout_xml.diff

+# HG changeset patch
+# Parent 7e0475a9ea2362cd116202facde8cc5ba4c93023
+BH Dashboard #45 : Parsing bh:layout tags in layout XML markup
+
+diff -r 7e0475a9ea23 bhdashboard/templates/widget_macros.html
+--- a/bhdashboard/templates/widget_macros.html	Sun Dec 09 09:40:48 2012 +0000
++++ b/bhdashboard/templates/widget_macros.html	Thu Dec 13 16:02:49 2012 -0500
+@@ -89,7 +89,7 @@
+     <py:choose test="">
+       <py:when test="bhdb">
+         <!--! TODO: Implement nested XML tags (e.g. bh:w and bh:l) -->
+-        ${bhdb.embed_layout(context, layout=unicode(select('@urn')), schema=unicode(select('bh:schema/text()')), widgets=unicode(select('bh:widgets/text()')))}
++        ${bhdb.embed_layout(context, layout=unicode(select('@urn')), schema=unicode(select('bh:schema/text()')), widgets=select('bh:widgets'))}
+       </py:when>
+       <py:otherwise>
+         ${bhnotfound()}
+diff -r 7e0475a9ea23 bhdashboard/util.py
+--- a/bhdashboard/util.py	Sun Dec 09 09:40:48 2012 +0000
++++ b/bhdashboard/util.py	Thu Dec 13 16:02:49 2012 -0500
+@@ -30,6 +30,9 @@
+ from urlparse import urlparse
+ from wsgiref.util import setup_testing_defaults
+ 
++from genshi.core import Stream
++from genshi.filters.transform import StreamBuffer
++
+ from trac.core import Component, implements, ExtensionPoint
+ from trac.util.text import to_unicode
+ from trac.web.api import Request
+@@ -198,4 +201,43 @@
+             minval = value
+     return dict(min=minval, max=maxval)
+ 
++#------------------------------------------------------
++#    Genshi tricks
++#------------------------------------------------------
+ 
++def split_elements(stream):
++    """List sub-streams of current stream element.
++
++    Note: Stream must be positioned immediately before parsing that element
++    i.e. next event kind has to be ENTER
++    """
++    stream = iter(stream)
++    kind, data, _ = stream.next()
++    # Skip namespace events
++    while kind == Stream.START_NS:
++        kind, data, _ = stream.next()
++
++    # At the beginning of parent element
++    assert kind == Stream.START
++    for kind, data, pos in stream:
++        if kind == Stream.START :
++            # At the beginning of the next sub-element
++            depth = 1
++            buffer = StreamBuffer()
++            buffer.append((kind, data, pos))
++            for kind, data, pos in stream:
++                if kind == Stream.START:
++                    depth += 1
++                elif kind == Stream.END:
++                    depth -= 1
++                buffer.append((kind, data, pos))
++                if depth == 0:
++                    break
++            yield buffer
++        elif kind == Stream.END:
++            # End of parent element, nothing else to do
++            break
++        else:
++            # Skip other events
++            pass
++
+diff -r 7e0475a9ea23 bhdashboard/web_ui.py
+--- a/bhdashboard/web_ui.py	Sun Dec 09 09:40:48 2012 +0000
++++ b/bhdashboard/web_ui.py	Thu Dec 13 16:02:49 2012 -0500
+@@ -32,7 +32,7 @@
+ from uuid import uuid4
+ 
+ from genshi.builder import tag
+-from genshi.core import Stream
++from genshi.core import QName, Stream
+ from trac.core import Component, implements
+ from trac.config import Option, IntOption
+ from trac.mimeview.api import Context
+@@ -47,6 +47,7 @@
+ 
+ from bhdashboard.api import DashboardSystem, InvalidIdentifier
+ from bhdashboard import _json
++from bhdashboard.util import split_elements
+ 
+ class DashboardModule(Component):
+     """Web frontend for dashboard infrastructure.
+@@ -320,14 +321,12 @@
+         if isinstance(schema, basestring):
+             schema = _json.loads(schema)
+         widgets = kwargs.get('widgets')
+-        if widgets is not None:
+-            # TODO: Use this one once widgets markup parser will be ready
+-            #widgets = parse_widgets_markup(widgets)
+-            if isinstance(widgets, basestring):
+-                widgets = _json.loads(widgets)
++        if isinstance(widgets, basestring):
++            schema['widgets'] = _json.loads(widgets)
++        elif isinstance(widgets, Stream):
++            schema = parse_widgets_tag(widgets, schema)
+         else:
+-            widgets = {}
+-        schema['widgets'] = widgets
++            schema['widgets'] = {}
+         template, layout_data = dbmod.expand_layout_data(
+                 context, layout, schema, True)
+         widgets = dbmod.expand_widget_data(context, layout_data)
+@@ -380,9 +379,50 @@
+         elif kind == Stream.TEXT:
+             argvalue += data
+         elif kind == Stream.END:
++            qname = data
+             if qname.namespace == XMLNS_DASHBOARD_UI \
+                     and qname.localname == 'arg':
+                 args[argnm] = argvalue
+                 inside = False
+     return args
+ 
++def parse_widgets_tag(stream, schema):
++    """Parse Genshi markup for widgets in layout tags
++    """
++    if isinstance(schema, basestring):
++        schema = _json.loads(schema)
++    widgets = {}
++    WIDGET_TAG = QName(XMLNS_DASHBOARD_UI + '}w')
++    LAYOUT_TAG = QName(XMLNS_DASHBOARD_UI + '}l')
++
++    def option_value(value):
++        try:
++            return _json.loads(value)
++        except:
++            return value
++
++    for widget_spec in split_elements(stream):
++        kind, (qname, attrs), _ = iter(widget_spec).next()
++        wid = attrs.get('id')
++        if qname == WIDGET_TAG:
++            wtype = attrs.get('urn')
++            wopts = dict((k.localname, option_value(v)) \
++                    for k,v in attrs if k not in ('id', 'urn'))
++            wargs = parse_args_tag(widget_spec.select('args'))
++            widget = {'args' : [wtype, None, {'args' : wargs}] }
++            widget.update(wopts)
++        elif qname == LAYOUT_TAG:
++            ltype = attrs.get('urn')
++            title = attrs.get('title')
++            lschema = parse_widgets_tag(widget_spec.select('widgets'), 
++                    unicode(widget_spec.select('schema/text()')))
++            widget = {'args' : ['Container', None, 
++                    {'args': {
++                            'layout' : ltype,
++                            'schema' : _json.dumps(lschema)}}]}
++            if title is not None:
++                widget['args'][2]['args']['title'] = title
++        widgets[wid] = widget
++    schema['widgets'] = widgets
++    return schema
++