From 5b03c2431d1541c190c9473bb36ee6b6a2df174f Mon Sep 17 00:00:00 2001 From: David Wolever Date: Thu, 2 Jan 2014 18:48:53 -0500 Subject: [PATCH] Add helpful error message when dealing with old-style classes --HG-- extra : rebase_source : f94bedeb736bf453bf8d1a38fa50f9bfd47cd249 --- CHANGELOG.txt | 3 +++ nose_parameterized/parameterized.py | 17 +++++++++++++++-- nose_parameterized/test.py | 27 +++++++++++++++++++++++++++ setup.py | 2 +- 4 files changed, 46 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.txt b/CHANGELOG.txt index dab2725..b9dda9b 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,3 +1,6 @@ +0.3.2 (2014-01-02) + * Add helpful error message when used with old-style classes. + 0.3.1 (2013-08-01) * Fix bug: `nose_parameterized.param` wasn't being imported. diff --git a/nose_parameterized/parameterized.py b/nose_parameterized/parameterized.py index 4b838fc..11efd90 100644 --- a/nose_parameterized/parameterized.py +++ b/nose_parameterized/parameterized.py @@ -11,9 +11,14 @@ from . import six if six.PY3: def new_instancemethod(f, *args): return f + + # Python 3 doesn't have an InstanceType, so just use a dummy type. + class InstanceType(): + pass else: import new new_instancemethod = new.instancemethod + from types import InstanceType _param = namedtuple("param", "args kwargs") @@ -140,6 +145,14 @@ class parameterized(object): def make_bound_method(self, instance, func): cls = type(instance) + if issubclass(cls, InstanceType): + raise TypeError(( + "@parameterized can't be used with old-style classes, but " + "%r has an old-style class. Consider using a new-style " + "class, or '@parameterized.expand' " + "(see http://stackoverflow.com/q/54867/71522 for more " + "information on old-style classes)." + ) %(instance, )) im_f = new_instancemethod(func, None, cls) setattr(cls, func.__name__, im_f) return getattr(instance, func.__name__) @@ -164,8 +177,8 @@ class parameterized(object): code_context = frame[4] and frame[4][0].strip() if not (code_context and code_context.startswith("class ")): return [] - _, parents = code_context.split("(", 1) - parents, _ = parents.rsplit(")", 1) + _, _, parents = code_context.partition("(") + parents, _, _ = parents.partition(")") return eval("[" + parents + "]", frame[0].f_globals, frame[0].f_locals) @classmethod diff --git a/nose_parameterized/test.py b/nose_parameterized/test.py index ee99ebb..e86f29a 100644 --- a/nose_parameterized/test.py +++ b/nose_parameterized/test.py @@ -1,6 +1,8 @@ from unittest import TestCase from nose.tools import assert_equal +from nose.plugins.skip import SkipTest +from . import six from .parameterized import parameterized, param def assert_contains(haystack, needle): @@ -20,6 +22,8 @@ missing_tests = set([ "test_on_TestCase('foo0', bar=None)", "test_on_TestCase('foo1', bar=None)", "test_on_TestCase('foo2', bar=42)", + "test_on_old_style_class('foo')", + "test_on_old_style_class('bar')", ]) test_params = [ @@ -75,3 +79,26 @@ def test_helpful_error_on_non_iterable_input(): def teardown_module(): missing = sorted(list(missing_tests)) assert_equal(missing, []) + + +def test_old_style_classes(): + if six.PY3: + raise SkipTest("Py3 doesn't have old-style classes") + class OldStyleClass: + @parameterized(["foo"]) + def parameterized_method(self, param): + pass + try: + list(OldStyleClass().parameterized_method()) + except TypeError as e: + assert_contains(str(e), "new-style") + assert_contains(str(e), "parameterized.expand") + assert_contains(str(e), "OldStyleClass") + else: + raise AssertionError("expected TypeError not raised by old-style class") + + +class TestOldStyleClass: + @parameterized.expand(["foo", "bar"]) + def test_old_style_classes(self, param): + missing_tests.remove("test_on_old_style_class(%r)" %(param, )) diff --git a/setup.py b/setup.py index 1be0797..2db953e 100644 --- a/setup.py +++ b/setup.py @@ -9,7 +9,7 @@ os.chdir(os.path.dirname(sys.argv[0]) or ".") setup( name="nose-parameterized", - version="0.3.1", + version="0.3.2", url="https://github.com/wolever/nose-parameterized", author="David Wolever", author_email="david@wolever.net",