# HG changeset patch
# User athomas
# Date 1181134314 0
# Node ID e293bbb40507e6ea1144d11f084ae7b629bbcd6e
# Parent bdaf75981ec7675476d2e4b8164c9d4b21f9f074
Fixed a bug where select() operated on the entire stream rather than only on
the previous selection. Introduced the end() transformation to reset the
current selection.
diff --git a/genshi/filters/transform.py b/genshi/filters/transform.py
--- a/genshi/filters/transform.py
+++ b/genshi/filters/transform.py
@@ -121,7 +121,7 @@
>>> buffer = StreamBuffer()
>>> print html | Transformer('head/title/text()').copy(buffer) \\
- ... .select('body').prepend(tag.h1(buffer))
+ ... .end().select('body').prepend(tag.h1(buffer))
Some TitleSome Title
Some
body text.
@@ -187,7 +187,8 @@
#{ Selection operations
def select(self, path):
- """Mark events matching the given XPath expression.
+ """Mark events matching the given XPath expression, within the current
+ selection.
>>> html = HTML('Some test text')
>>> print html | Transformer().select('.//em').trace()
@@ -228,6 +229,27 @@
"""
return self | InvertTransformation()
+ def end(self):
+ """End current selection, allowing all events to be selected.
+
+ Example:
+
+ >>> html = HTML('Some test text')
+ >>> print html | Transformer('//em').end().trace()
+ ('OUTSIDE', ('START', (QName(u'body'), Attrs()), (None, 1, 0)))
+ ('OUTSIDE', ('TEXT', u'Some ', (None, 1, 6)))
+ ('OUTSIDE', ('START', (QName(u'em'), Attrs()), (None, 1, 11)))
+ ('OUTSIDE', ('TEXT', u'test', (None, 1, 15)))
+ ('OUTSIDE', ('END', QName(u'em'), (None, 1, 19)))
+ ('OUTSIDE', ('TEXT', u' text', (None, 1, 24)))
+ ('OUTSIDE', ('END', QName(u'body'), (None, 1, 29)))
+ Some test text
+
+ :return: the stream augmented by transformation marks
+ :rtype: `Transformer`
+ """
+ return self | EndTransformation()
+
#{ Deletion operations
def empty(self):
@@ -420,7 +442,7 @@
>>> html = HTML('Some Title'
... 'Some body text.')
>>> print html | Transformer('title/text()').copy(buffer) \\
- ... .select('body').prepend(tag.h1(buffer))
+ ... .end().select('body').prepend(tag.h1(buffer))
Some TitleSome
Title
Some body text.
@@ -430,7 +452,7 @@
>>> print buffer
Some Title
>>> print html | Transformer('head/title/text()').copy(buffer) \\
- ... .select('body/em').copy(buffer).select('body') \\
+ ... .end().select('body/em').copy(buffer).end().select('body') \\
... .prepend(tag.h1(buffer))
Some
Titlebody
Some body
@@ -454,7 +476,7 @@
>>> html = HTML('Some Title'
... 'Some body text.')
>>> print html | Transformer('.//em/text()').cut(buffer) \\
- ... .select('.//em').after(tag.h1(buffer))
+ ... .end().select('.//em').after(tag.h1(buffer))
Some TitleSome
body
text.
@@ -508,7 +530,7 @@
def _mark(self, stream):
for event in stream:
- yield None, event
+ yield OUTSIDE, event
def _unmark(self, stream):
for mark, event in stream:
@@ -537,6 +559,9 @@
test = self.path.test()
stream = iter(stream)
for mark, event in stream:
+ if mark is None:
+ yield mark, event
+ continue
result = test(event, {}, {})
if result is True:
if event[0] is START:
@@ -580,6 +605,18 @@
yield OUTSIDE, event
+class EndTransformation(object):
+ """End the current selection."""
+
+ def __call__(self, stream):
+ """Apply the transform filter to the marked stream.
+
+ :param stream: the marked event stream to filter
+ """
+ for mark, event in stream:
+ yield OUTSIDE, event
+
+
class EmptyTransformation(object):
"""Empty selected elements of all content."""