changeset 857:24733a5854d9

Avoid unicode literals in `repr`s of `QName` and `Namespace` when not necessary.
author cmlenz
date Thu, 12 Nov 2009 15:09:26 +0000
parents 1e2be9fb3348
children df860bdad9ca
files doc/streams.txt genshi/core.py genshi/filters/tests/transform.py genshi/filters/transform.py genshi/input.py genshi/path.py genshi/tests/core.py genshi/util.py
diffstat 8 files changed, 80 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/doc/streams.txt
+++ b/doc/streams.txt
@@ -48,15 +48,15 @@
   >>> for kind, data, pos in stream:
   ...     print('%s %r %r' % (kind, data, pos))
   ... 
-  START (QName(u'p'), Attrs([(QName(u'class'), u'intro')])) (None, 1, 0)
+  START (QName('p'), Attrs([(QName('class'), u'intro')])) (None, 1, 0)
   TEXT u'Some text and ' (None, 1, 17)
-  START (QName(u'a'), Attrs([(QName(u'href'), u'http://example.org/')])) (None, 1, 31)
+  START (QName('a'), Attrs([(QName('href'), u'http://example.org/')])) (None, 1, 31)
   TEXT u'a link' (None, 1, 61)
-  END QName(u'a') (None, 1, 67)
+  END QName('a') (None, 1, 67)
   TEXT u'.' (None, 1, 71)
-  START (QName(u'br'), Attrs()) (None, 1, 72)
-  END QName(u'br') (None, 1, 77)
-  END QName(u'p') (None, 1, 77)
+  START (QName('br'), Attrs()) (None, 1, 72)
+  END QName('br') (None, 1, 77)
+  END QName('p') (None, 1, 77)
 
 
 Filtering
@@ -379,7 +379,7 @@
 
 .. code-block:: python
 
-  START, (QName(u'p'), Attrs([(QName(u'class'), u'intro')])), pos
+  START, (QName('p'), Attrs([(QName('class'), u'intro')])), pos
 
 END
 ---
@@ -390,7 +390,7 @@
 
 .. code-block:: python
 
-  END, QName(u'p'), pos
+  END, QName('p'), pos
 
 TEXT
 ----
--- a/genshi/core.py
+++ b/genshi/core.py
@@ -20,7 +20,7 @@
 from itertools import chain
 import operator
 
-from genshi.util import plaintext, stripentities, striptags
+from genshi.util import plaintext, stripentities, striptags, stringrepr
 
 __all__ = ['Stream', 'Markup', 'escape', 'unescape', 'Attrs', 'Namespace',
            'QName']
@@ -463,7 +463,7 @@
         return Markup(num * unicode(self))
 
     def __repr__(self):
-        return '<%s %r>' % (self.__class__.__name__, unicode(self))
+        return "<%s %s>" % (self.__class__.__name__, unicode.__repr__(self))
 
     def join(self, seq, escape_quotes=True):
         """Return a `Markup` object which is the concatenation of the strings
@@ -600,7 +600,7 @@
     
     >>> html = Namespace('http://www.w3.org/1999/xhtml')
     >>> html
-    <Namespace "http://www.w3.org/1999/xhtml">
+    Namespace('http://www.w3.org/1999/xhtml')
     >>> html.uri
     u'http://www.w3.org/1999/xhtml'
     
@@ -608,7 +608,7 @@
     that namespace:
     
     >>> html.body
-    QName(u'http://www.w3.org/1999/xhtml}body')
+    QName('http://www.w3.org/1999/xhtml}body')
     >>> html.body.localname
     u'body'
     >>> html.body.namespace
@@ -618,7 +618,7 @@
     attribute names that are not valid Python identifiers:
     
     >>> html['body']
-    QName(u'http://www.w3.org/1999/xhtml}body')
+    QName('http://www.w3.org/1999/xhtml}body')
     
     A `Namespace` object can also be used to test whether a specific `QName`
     belongs to that namespace using the ``in`` operator:
@@ -665,7 +665,7 @@
         return hash(self.uri)
 
     def __repr__(self):
-        return '<Namespace "%s">' % self.uri
+        return 'Namespace(%s)' % stringrepr(self.uri)
 
     def __str__(self):
         return self.uri.encode('utf-8')
@@ -688,14 +688,14 @@
     
     >>> qname = QName('foo')
     >>> qname
-    QName(u'foo')
+    QName('foo')
     >>> qname.localname
     u'foo'
     >>> qname.namespace
     
     >>> qname = QName('http://www.w3.org/1999/xhtml}body')
     >>> qname
-    QName(u'http://www.w3.org/1999/xhtml}body')
+    QName('http://www.w3.org/1999/xhtml}body')
     >>> qname.localname
     u'body'
     >>> qname.namespace
@@ -726,4 +726,4 @@
         return (self.lstrip('{'),)
 
     def __repr__(self):
-        return 'QName(%s)' % unicode.__repr__(self.lstrip('{'))
+        return 'QName(%s)' % stringrepr(self.lstrip('{'))
--- a/genshi/filters/tests/transform.py
+++ b/genshi/filters/tests/transform.py
@@ -544,29 +544,29 @@
     def test_map_element(self):
         self.assertEqual(
             self._map('foo'),
-            [(QName(u'foo'), Attrs([(QName(u'name'), u'foo'),
-                                    (QName(u'size'), u'100')])),
+            [(QName('foo'), Attrs([(QName('name'), u'foo'),
+                                   (QName('size'), u'100')])),
              u'FOO',
-             QName(u'foo')]
-            )
+             QName('foo')]
+        )
 
     def test_map_with_text_kind(self):
         self.assertEqual(
             self._map('.', TEXT),
             [u'ROOT', u'FOO', u'BAR']
-            )
+        )
 
     def test_map_with_root_and_end_kind(self):
         self.assertEqual(
             self._map('.', END),
-            [QName(u'foo'), QName(u'bar'), QName(u'root')]
-            )
+            [QName('foo'), QName('bar'), QName('root')]
+        )
 
     def test_map_with_attribute(self):
         self.assertEqual(
             self._map('foo/@name'),
-            [(QName(u'foo@*'), Attrs([('name', u'foo')]))]
-            )
+            [(QName('foo@*'), Attrs([('name', u'foo')]))]
+        )
 
 
 class SubstituteTest(unittest.TestCase):
--- a/genshi/filters/transform.py
+++ b/genshi/filters/transform.py
@@ -235,13 +235,13 @@
 
         >>> html = HTML('<body>Some <em>test</em> text</body>')
         >>> print(html | Transformer().select('.//em').trace())
-        (None, ('START', (QName(u'body'), Attrs()), (None, 1, 0)))
+        (None, ('START', (QName('body'), Attrs()), (None, 1, 0)))
         (None, ('TEXT', u'Some ', (None, 1, 6)))
-        ('ENTER', ('START', (QName(u'em'), Attrs()), (None, 1, 11)))
+        ('ENTER', ('START', (QName('em'), Attrs()), (None, 1, 11)))
         ('INSIDE', ('TEXT', u'test', (None, 1, 15)))
-        ('EXIT', ('END', QName(u'em'), (None, 1, 19)))
+        ('EXIT', ('END', QName('em'), (None, 1, 19)))
         (None, ('TEXT', u' text', (None, 1, 24)))
-        (None, ('END', QName(u'body'), (None, 1, 29)))
+        (None, ('END', QName('body'), (None, 1, 29)))
         <body>Some <em>test</em> text</body>
 
         :param path: an XPath expression (as string) or a `Path` instance
@@ -259,13 +259,13 @@
 
         >>> html = HTML('<body>Some <em>test</em> text</body>')
         >>> print(html | Transformer('//em').invert().trace())
-        ('OUTSIDE', ('START', (QName(u'body'), Attrs()), (None, 1, 0)))
+        ('OUTSIDE', ('START', (QName('body'), Attrs()), (None, 1, 0)))
         ('OUTSIDE', ('TEXT', u'Some ', (None, 1, 6)))
-        (None, ('START', (QName(u'em'), Attrs()), (None, 1, 11)))
+        (None, ('START', (QName('em'), Attrs()), (None, 1, 11)))
         (None, ('TEXT', u'test', (None, 1, 15)))
-        (None, ('END', QName(u'em'), (None, 1, 19)))
+        (None, ('END', QName('em'), (None, 1, 19)))
         ('OUTSIDE', ('TEXT', u' text', (None, 1, 24)))
-        ('OUTSIDE', ('END', QName(u'body'), (None, 1, 29)))
+        ('OUTSIDE', ('END', QName('body'), (None, 1, 29)))
         <body>Some <em>test</em> text</body>
 
         :rtype: `Transformer`
@@ -279,13 +279,13 @@
 
         >>> html = HTML('<body>Some <em>test</em> text</body>')
         >>> print(html | Transformer('//em').end().trace())
-        ('OUTSIDE', ('START', (QName(u'body'), Attrs()), (None, 1, 0)))
+        ('OUTSIDE', ('START', (QName('body'), Attrs()), (None, 1, 0)))
         ('OUTSIDE', ('TEXT', u'Some ', (None, 1, 6)))
-        ('OUTSIDE', ('START', (QName(u'em'), Attrs()), (None, 1, 11)))
+        ('OUTSIDE', ('START', (QName('em'), Attrs()), (None, 1, 11)))
         ('OUTSIDE', ('TEXT', u'test', (None, 1, 15)))
-        ('OUTSIDE', ('END', QName(u'em'), (None, 1, 19)))
+        ('OUTSIDE', ('END', QName('em'), (None, 1, 19)))
         ('OUTSIDE', ('TEXT', u' text', (None, 1, 24)))
-        ('OUTSIDE', ('END', QName(u'body'), (None, 1, 29)))
+        ('OUTSIDE', ('END', QName('body'), (None, 1, 29)))
         <body>Some <em>test</em> text</body>
 
         :return: the stream augmented by transformation marks
@@ -470,7 +470,7 @@
         ...     print(attrs)
         ...     return attrs.get(name)
         >>> print(html | Transformer('body/em').attr('class', print_attr))
-        Attrs([(QName(u'class'), u'before')])
+        Attrs([(QName('class'), u'before')])
         Attrs()
         <html><head><title>Some Title</title></head><body>Some <em
         class="before">body</em> <em>text</em>.</body></html>
@@ -660,13 +660,13 @@
 
         >>> html = HTML('<body>Some <em>test</em> text</body>')
         >>> print(html | Transformer('em').trace())
-        (None, ('START', (QName(u'body'), Attrs()), (None, 1, 0)))
+        (None, ('START', (QName('body'), Attrs()), (None, 1, 0)))
         (None, ('TEXT', u'Some ', (None, 1, 6)))
-        ('ENTER', ('START', (QName(u'em'), Attrs()), (None, 1, 11)))
+        ('ENTER', ('START', (QName('em'), Attrs()), (None, 1, 11)))
         ('INSIDE', ('TEXT', u'test', (None, 1, 15)))
-        ('EXIT', ('END', QName(u'em'), (None, 1, 19)))
+        ('EXIT', ('END', QName('em'), (None, 1, 19)))
         (None, ('TEXT', u' text', (None, 1, 24)))
-        (None, ('END', QName(u'body'), (None, 1, 29)))
+        (None, ('END', QName('body'), (None, 1, 29)))
         <body>Some <em>test</em> text</body>
 
         :param prefix: a string to prefix each event with in the output
--- a/genshi/input.py
+++ b/genshi/input.py
@@ -88,8 +88,8 @@
     >>> parser = XMLParser(StringIO('<root id="2"><child>Foo</child></root>'))
     >>> for kind, data, pos in parser:
     ...     print('%s %s' % (kind, data))
-    START (QName(u'root'), Attrs([(QName(u'id'), u'2')]))
-    START (QName(u'child'), Attrs())
+    START (QName('root'), Attrs([(QName('id'), u'2')]))
+    START (QName('child'), Attrs())
     TEXT Foo
     END child
     END root
@@ -289,8 +289,8 @@
     >>> parser = HTMLParser(StringIO('<UL compact><LI>Foo</UL>'))
     >>> for kind, data, pos in parser:
     ...     print('%s %s' % (kind, data))
-    START (QName(u'ul'), Attrs([(QName(u'compact'), u'compact')]))
-    START (QName(u'li'), Attrs())
+    START (QName('ul'), Attrs([(QName('compact'), u'compact')]))
+    START (QName('li'), Attrs())
     TEXT Foo
     END li
     END ul
--- a/genshi/path.py
+++ b/genshi/path.py
@@ -619,7 +619,7 @@
         >>> for event in xml:
         ...     if test(event, namespaces, variables):
         ...         print('%s %r' % (event[0], event[1]))
-        START (QName(u'child'), Attrs([(QName(u'id'), u'2')]))
+        START (QName('child'), Attrs([(QName('id'), u'2')]))
         
         :param ignore_context: if `True`, the path is interpreted like a pattern
                                in XSLT, meaning for example that it will match
--- a/genshi/tests/core.py
+++ b/genshi/tests/core.py
@@ -182,13 +182,25 @@
 
 class NamespaceTestCase(unittest.TestCase):
 
+    def test_repr(self):
+        self.assertEqual("Namespace('http://www.example.org/namespace')",
+                         repr(Namespace('http://www.example.org/namespace')))
+
+    def test_repr_eval(self):
+        ns = Namespace('http://www.example.org/namespace')
+        self.assertEqual(eval(repr(ns)), ns)
+
+    def test_repr_eval_non_ascii(self):
+        ns = Namespace(u'http://www.example.org/nämespäcé')
+        self.assertEqual(eval(repr(ns)), ns)
+
     def test_pickle(self):
         ns = Namespace('http://www.example.org/namespace')
         buf = StringIO()
         pickle.dump(ns, buf, 2)
         buf.seek(0)
         unpickled = pickle.load(buf)
-        self.assertEquals('<Namespace "http://www.example.org/namespace">',
+        self.assertEquals("Namespace('http://www.example.org/namespace')",
                           repr(unpickled))
         self.assertEquals('http://www.example.org/namespace', unpickled.uri)
 
@@ -207,19 +219,23 @@
         self.assertEquals('elem', unpickled.localname)
 
     def test_repr(self):
-        self.assertEqual("QName(u'elem')", repr(QName('elem')))
-        self.assertEqual("QName(u'http://www.example.org/namespace}elem')",
+        self.assertEqual("QName('elem')", repr(QName('elem')))
+        self.assertEqual("QName('http://www.example.org/namespace}elem')",
                          repr(QName('http://www.example.org/namespace}elem')))
 
+    def test_repr_eval(self):
+        qn = QName('elem')
+        self.assertEqual(eval(repr(qn)), qn)
+
+    def test_repr_eval_non_ascii(self):
+        qn = QName(u'élem')
+        self.assertEqual(eval(repr(qn)), qn)
+
     def test_leading_curly_brace(self):
         qname = QName('{http://www.example.org/namespace}elem')
         self.assertEquals('http://www.example.org/namespace', qname.namespace)
         self.assertEquals('elem', qname.localname)
 
-    def test_non_ascii(self):
-        qname = QName(u'http://www.example.org/namespace}gürü')
-        self.assertEqual(u'gürü', qname.localname)
-
 
 def suite():
     suite = unittest.TestSuite()
--- a/genshi/util.py
+++ b/genshi/util.py
@@ -250,6 +250,15 @@
     return _STRIPTAGS_RE.sub('', text)
 
 
+def stringrepr(string):
+    slen = len(string)
+    ascii = string.encode('ascii', 'backslashreplace')
+    r = "'" +  ascii.replace("'", "\\'") + "'"
+    if (unicode is not str) and (len(ascii) > len(string)):
+        return 'u' + r
+    return r
+
+
 # Compatibility fallback implementations for older Python versions
 
 try:
Copyright (C) 2012-2017 Edgewall Software