changeset 217:f150cff4da18 trunk

Fix `py:match` directive which would screw up in some scenarios due to incorrect handling of the substream. Closes #49.
author cmlenz
date Mon, 04 Sep 2006 23:27:38 +0000
parents 636fe6766b4d
children 6eff1d2b394a
files markup/path.py markup/template.py markup/tests/template.py
diffstat 3 files changed, 54 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/markup/path.py
+++ b/markup/path.py
@@ -193,9 +193,8 @@
                         # Both the node test and the predicates matched
                         if matched:
                             if last_step:
-                                if ignore_context or kind is not START \
-                                        or axis is ATTRIBUTE or axis is SELF \
-                                        or len(stack) > 2:
+                                if not ctxtnode or kind is not START \
+                                        or axis is ATTRIBUTE or axis is SELF:
                                     retval = matched
                             elif not ctxtnode or axis is SELF \
                                               or axis is DESCENDANT_OR_SELF:
@@ -221,7 +220,8 @@
 
                     # We're done with this step if it's the last step or the
                     # axis isn't "self"
-                    if last_step or axis is not SELF:
+                    if last_step or (axis is not SELF and
+                                     axis is not DESCENDANT_OR_SELF):
                         break
 
                 if kind is START and axis is not DESCENDANT \
--- a/markup/template.py
+++ b/markup/template.py
@@ -996,6 +996,21 @@
         if match_templates is None:
             match_templates = ctxt._match_templates
 
+        tail = []
+        def _strip(stream):
+            depth = 1
+            while 1:
+                kind, data, pos = stream.next()
+                if kind is START:
+                    depth += 1
+                elif kind is END:
+                    depth -= 1
+                if depth > 0:
+                    yield kind, data, pos
+                else:
+                    tail[:] = [(kind, data, pos)]
+                    break
+
         for kind, data, pos in stream:
 
             # We (currently) only care about start and end events for matching
@@ -1017,15 +1032,11 @@
                     # Consume and store all events until an end event
                     # corresponding to this start event is encountered
                     content = [(kind, data, pos)]
-                    depth = 1
-                    stream = self._match(stream, ctxt)
-                    while depth > 0:
-                        kind, data, pos = stream.next()
-                        if kind is START:
-                            depth += 1
-                        elif kind is END:
-                            depth -= 1
-                        content.append((kind, data, pos))
+                    content += list(self._match(_strip(stream), ctxt)) + tail
+
+                    kind, data, pos = tail[0]
+                    for test in [mt[0] for mt in match_templates]:
+                        test(kind, data, pos, ctxt)
 
                     # Make the select() function available in the body of the
                     # match template
--- a/markup/tests/template.py
+++ b/markup/tests/template.py
@@ -601,6 +601,36 @@
           <body><h2>Are you ready to mark up?</h2><hr/></body>
         </html>""", str(tmpl.generate()))
 
+    def test_multiple_matches(self):
+        tmpl = Template("""<html xmlns:py="http://markup.edgewall.org/">
+          <input py:match="form//input" py:attrs="select('@*')"
+                 value="${values[str(select('@name'))]}" />
+          <form><p py:for="field in fields">
+            <label>${field.capitalize()}</label>
+            <input type="text" name="${field}" />
+          </p></form>
+        </html>""")
+        fields = ['hello_%s' % i for i in range(5)]
+        values = dict([('hello_%s' % i, i) for i in range(5)])
+        self.assertEqual("""<html>
+          <form><p>
+            <label>Hello_0</label>
+            <input value="0" type="text" name="hello_0"/>
+          </p><p>
+            <label>Hello_1</label>
+            <input value="1" type="text" name="hello_1"/>
+          </p><p>
+            <label>Hello_2</label>
+            <input value="2" type="text" name="hello_2"/>
+          </p><p>
+            <label>Hello_3</label>
+            <input value="3" type="text" name="hello_3"/>
+          </p><p>
+            <label>Hello_4</label>
+            <input value="4" type="text" name="hello_4"/>
+          </p></form>
+        </html>""", str(tmpl.generate(fields=fields, values=values)))
+
     # FIXME
     #def test_match_after_step(self):
     #    tmpl = Template("""<div xmlns:py="http://markup.edgewall.org/">
Copyright (C) 2012-2017 Edgewall Software