[Python-checkins] cpython: Tidy up the additional string module tests added at the Pycon sprints (closes

nick.coghlan python-checkins at python.org
Tue May 31 11:40:23 CEST 2011


http://hg.python.org/cpython/rev/f1a213d034af
changeset:   70547:f1a213d034af
user:        Nick Coghlan <ncoghlan at gmail.com>
date:        Tue May 31 19:40:11 2011 +1000
summary:
  Tidy up the additional string module tests added at the Pycon sprints (closes #11505)

files:
  Lib/test/test_pep292.py |  33 ++++++++-----
  Lib/test/test_string.py |  68 ++++++++++++++++------------
  Misc/ACKS               |   1 +
  Misc/NEWS               |   4 +-
  4 files changed, 61 insertions(+), 45 deletions(-)


diff --git a/Lib/test/test_pep292.py b/Lib/test/test_pep292.py
--- a/Lib/test/test_pep292.py
+++ b/Lib/test/test_pep292.py
@@ -42,19 +42,6 @@
         s = Template('$who likes $$')
         eq(s.substitute(dict(who='tim', what='ham')), 'tim likes $')
 
-    def test_invalid(self):
-        class MyPattern(Template):
-            pattern = r"""
-            (?:
-            (?P<invalid>)            |
-            (?P<escaped>%(delim)s)   |
-            @(?P<named>%(id)s)       |
-            @{(?P<braced>%(id)s)}
-            )
-            """
-        s = MyPattern('$')
-        self.assertRaises(ValueError, s.substitute, dict())
-
     def test_percents(self):
         eq = self.assertEqual
         s = Template('%(foo)s $foo ${foo}')
@@ -172,6 +159,26 @@
         val = t.safe_substitute({'location': 'Cleveland'})
         self.assertEqual(val, 'PyCon in Cleveland')
 
+    def test_invalid_with_no_lines(self):
+        # The error formatting for invalid templates
+        # has a special case for no data that the default
+        # pattern can't trigger (always has at least '$')
+        # So we craft a pattern that is always invalid
+        # with no leading data.
+        class MyTemplate(Template):
+            pattern = r"""
+              (?P<invalid>) |
+              unreachable(
+                (?P<named>)   |
+                (?P<braced>)  |
+                (?P<escaped>)
+              )
+            """
+        s = MyTemplate('')
+        with self.assertRaises(ValueError) as err:
+            s.substitute({})
+        self.assertIn('line 1, col 1', str(err.exception))
+
     def test_unicode_values(self):
         s = Template('$who likes $what')
         d = dict(who='t\xffm', what='f\xfe\fed')
diff --git a/Lib/test/test_string.py b/Lib/test/test_string.py
--- a/Lib/test/test_string.py
+++ b/Lib/test/test_string.py
@@ -26,15 +26,38 @@
         self.assertEqual(string.capwords('\taBc\tDeF\t'), 'Abc Def')
         self.assertEqual(string.capwords('\taBc\tDeF\t', '\t'), '\tAbc\tDef\t')
 
-    def test_formatter(self):
+    def test_basic_formatter(self):
         fmt = string.Formatter()
         self.assertEqual(fmt.format("foo"), "foo")
-
         self.assertEqual(fmt.format("foo{0}", "bar"), "foobar")
         self.assertEqual(fmt.format("foo{1}{0}-{1}", "bar", 6), "foo6bar-6")
+
+    def test_conversion_specifiers(self):
+        fmt = string.Formatter()
         self.assertEqual(fmt.format("-{arg!r}-", arg='test'), "-'test'-")
+        self.assertEqual(fmt.format("{0!s}", 'test'), 'test')
+        self.assertRaises(ValueError, fmt.format, "{0!h}", 'test')
 
-        # override get_value ############################################
+    def test_name_lookup(self):
+        fmt = string.Formatter()
+        class AnyAttr:
+            def __getattr__(self, attr):
+                return attr
+        x = AnyAttr()
+        self.assertEqual(fmt.format("{0.lumber}{0.jack}", x), 'lumberjack')
+        with self.assertRaises(AttributeError):
+            fmt.format("{0.lumber}{0.jack}", '')
+
+    def test_index_lookup(self):
+        fmt = string.Formatter()
+        lookup = ["eggs", "and", "spam"]
+        self.assertEqual(fmt.format("{0[2]}{0[0]}", lookup), 'spameggs')
+        with self.assertRaises(IndexError):
+            fmt.format("{0[2]}{0[0]}", [])
+        with self.assertRaises(KeyError):
+            fmt.format("{0[2]}{0[0]}", {})
+
+    def test_override_get_value(self):
         class NamespaceFormatter(string.Formatter):
             def __init__(self, namespace={}):
                 string.Formatter.__init__(self)
@@ -54,7 +77,7 @@
         self.assertEqual(fmt.format("{greeting}, world!"), 'hello, world!')
 
 
-        # override format_field #########################################
+    def test_override_format_field(self):
         class CallFormatter(string.Formatter):
             def format_field(self, value, format_spec):
                 return format(value(), format_spec)
@@ -63,18 +86,18 @@
         self.assertEqual(fmt.format('*{0}*', lambda : 'result'), '*result*')
 
 
-        # override convert_field ########################################
+    def test_override_convert_field(self):
         class XFormatter(string.Formatter):
             def convert_field(self, value, conversion):
                 if conversion == 'x':
                     return None
-                return super(XFormatter, self).convert_field(value, conversion)
+                return super().convert_field(value, conversion)
 
         fmt = XFormatter()
         self.assertEqual(fmt.format("{0!r}:{0!x}", 'foo', 'foo'), "'foo':None")
 
 
-        # override parse ################################################
+    def test_override_parse(self):
         class BarFormatter(string.Formatter):
             # returns an iterable that contains tuples of the form:
             # (literal_text, field_name, format_spec, conversion)
@@ -90,7 +113,7 @@
         fmt = BarFormatter()
         self.assertEqual(fmt.format('*|+0:^10s|*', 'foo'), '*   foo    *')
 
-        # test all parameters used
+    def test_check_unused_args(self):
         class CheckAllUsedFormatter(string.Formatter):
             def check_unused_args(self, used_args, args, kwargs):
                 # Track which arguments actually got used
@@ -112,28 +135,13 @@
         self.assertRaises(ValueError, fmt.format, "{0}", 10, 20, i=100)
         self.assertRaises(ValueError, fmt.format, "{i}", 10, 20, i=100)
 
-    def test_vformat_assert(self):
-        cls = string.Formatter()
-        kwargs = {
-            "i": 100
-        }
-        self.assertRaises(ValueError, cls._vformat,
-                cls.format, "{0}", kwargs, set(), -2)
-
-    def test_convert_field(self):
-        cls = string.Formatter()
-        self.assertEqual(cls.format("{0!s}", 'foo'), 'foo')
-        self.assertRaises(ValueError, cls.format, "{0!h}", 'foo')
-
-    def test_get_field(self):
-        cls = string.Formatter()
-        class MyClass:
-            name = 'lumberjack'
-        x = MyClass()
-        self.assertEqual(cls.format("{0.name}", x), 'lumberjack')
-
-        lookup = ["eggs", "and", "spam"]
-        self.assertEqual(cls.format("{0[2]}", lookup), 'spam')
+    def test_vformat_recursion_limit(self):
+        fmt = string.Formatter()
+        args = ()
+        kwargs = dict(i=100)
+        with self.assertRaises(ValueError) as err:
+            fmt._vformat("{i}", args, kwargs, set(), -1)
+        self.assertIn("recursion", str(err.exception))
 
 
 def test_main():
diff --git a/Misc/ACKS b/Misc/ACKS
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -746,6 +746,7 @@
 Pierre Quentel
 Brian Quinlan
 Anders Qvist
+Jérôme Radix
 Burton Radons
 Brodie Rao
 Antti Rasinen
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -852,8 +852,8 @@
 
 - Issue #11503: improve test coverage of posixpath.py. Patch by Evan Dandrea.
 
-- Issue #11505: improves test coverage of string.py. Patch by Alicia
-  Arlen.
+- Issue #11505: improves test coverage of string.py, increases granularity of
+  string.Formatter tests. Initial patch by Alicia Arlen.
 
 - Issue #11548: Improve test coverage of the shutil module. Patch by
   Evan Dandrea.

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list