]> git.ipfire.org Git - thirdparty/tornado.git/commitdiff
options: Report redefinition errors when underscores are used 2048/head
authorBen Darnell <ben@bendarnell.com>
Sat, 20 May 2017 17:44:08 +0000 (13:44 -0400)
committerBen Darnell <ben@bendarnell.com>
Sat, 20 May 2017 17:44:08 +0000 (13:44 -0400)
Fixes #2020

tornado/options.py
tornado/test/options_test.py
tornado/test/util.py

index 0a72cc65edbd10b3c339c0c5a2844f35ab3cbe26..707fbd35ee0a36349539433afa3a64413e036e5d 100644 (file)
@@ -223,9 +223,10 @@ class OptionParser(object):
         override options set earlier on the command line, but can be overridden
         by later flags.
         """
-        if name in self._options:
+        normalized = self._normalize_name(name)
+        if normalized in self._options:
             raise Error("Option %r already defined in %s" %
-                        (name, self._options[name].file_name))
+                        (normalized, self._options[normalized].file_name))
         frame = sys._getframe(0)
         options_file = frame.f_code.co_filename
 
@@ -247,7 +248,6 @@ class OptionParser(object):
             group_name = group
         else:
             group_name = file_name
-        normalized = self._normalize_name(name)
         option = _Option(name, file_name=file_name,
                          default=default, type=type, help=help,
                          metavar=metavar, multiple=multiple,
index bafeea6fd35f4897a094dc6df0e7a1b58a8f519a..1a0ac8fb84233afbac92d79b9c527867d69568d9 100644 (file)
@@ -7,7 +7,7 @@ import sys
 
 from tornado.options import OptionParser, Error
 from tornado.util import basestring_type, PY3
-from tornado.test.util import unittest
+from tornado.test.util import unittest, subTest
 
 if PY3:
     from io import StringIO
@@ -232,6 +232,24 @@ class OptionsTest(unittest.TestCase):
         self.assertRegexpMatches(str(cm.exception),
                                  'Option.*foo.*already defined')
 
+    def test_error_redefine_underscore(self):
+        # Ensure that the dash/underscore normalization doesn't
+        # interfere with the redefinition error.
+        tests = [
+            ('foo-bar', 'foo-bar'),
+            ('foo_bar', 'foo_bar'),
+            ('foo-bar', 'foo_bar'),
+            ('foo_bar', 'foo-bar'),
+            ]
+        for a, b in tests:
+            with subTest(self, a=a, b=b):
+                options = OptionParser()
+                options.define(a)
+                with self.assertRaises(Error) as cm:
+                    options.define(b)
+                self.assertRegexpMatches(str(cm.exception),
+                                         'Option.*foo.bar.*already defined')
+
     def test_dash_underscore_cli(self):
         # Dashes and underscores should be interchangeable.
         for defined_name in ['foo-bar', 'foo_bar']:
index 6c032da63f85b28a7298ddb8015b8c2e851a1d8b..5f534e84ed144d59ff20c7eddba50d033d35679b 100644 (file)
@@ -1,5 +1,6 @@
 from __future__ import absolute_import, division, print_function
 
+import contextlib
 import os
 import platform
 import socket
@@ -94,3 +95,15 @@ def is_coverage_running():
         except AttributeError:
             return False
     return mod.startswith('coverage')
+
+
+def subTest(test, *args, **kwargs):
+    """Compatibility shim for unittest.TestCase.subTest.
+
+    Usage: ``with tornado.test.util.subTest(self, x=x):``
+    """
+    try:
+        subTest = test.subTest  # py34+
+    except AttributeError:
+        subTest = contextlib.contextmanager(lambda *a, **kw: (yield))
+    return subTest(*args, **kwargs)