Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes.

This commit is contained in:
Serhiy Storchaka 2015-07-18 23:19:05 +03:00
parent d113c967b4
commit 3018cc49e8
3 changed files with 66 additions and 38 deletions

View File

@ -2206,15 +2206,13 @@ class Parameter:
id(self), self.name) id(self), self.name)
def __eq__(self, other): def __eq__(self, other):
return (issubclass(other.__class__, Parameter) and if not isinstance(other, Parameter):
self._name == other._name and return NotImplemented
return (self._name == other._name and
self._kind == other._kind and self._kind == other._kind and
self._default == other._default and self._default == other._default and
self._annotation == other._annotation) self._annotation == other._annotation)
def __ne__(self, other):
return not self.__eq__(other)
class BoundArguments: class BoundArguments:
'''Result of `Signature.bind` call. Holds the mapping of arguments '''Result of `Signature.bind` call. Holds the mapping of arguments
@ -2295,13 +2293,11 @@ class BoundArguments:
return kwargs return kwargs
def __eq__(self, other): def __eq__(self, other):
return (issubclass(other.__class__, BoundArguments) and if not isinstance(other, BoundArguments):
self.signature == other.signature and return NotImplemented
return (self.signature == other.signature and
self.arguments == other.arguments) self.arguments == other.arguments)
def __ne__(self, other):
return not self.__eq__(other)
class Signature: class Signature:
'''A Signature object represents the overall signature of a function. '''A Signature object represents the overall signature of a function.
@ -2493,9 +2489,10 @@ class Signature:
return_annotation=return_annotation) return_annotation=return_annotation)
def __eq__(self, other): def __eq__(self, other):
if (not issubclass(type(other), Signature) or if not isinstance(other, Signature):
self.return_annotation != other.return_annotation or return NotImplemented
len(self.parameters) != len(other.parameters)): if (self.return_annotation != other.return_annotation or
len(self.parameters) != len(other.parameters)):
return False return False
other_positions = {param: idx other_positions = {param: idx
@ -2522,9 +2519,6 @@ class Signature:
return True return True
def __ne__(self, other):
return not self.__eq__(other)
def _bind(self, args, kwargs, *, partial=False): def _bind(self, args, kwargs, *, partial=False):
'''Private method. Don't use directly.''' '''Private method. Don't use directly.'''

View File

@ -76,6 +76,10 @@ def generator_function_example(self):
for i in range(2): for i in range(2):
yield i yield i
class EqualsToAll:
def __eq__(self, other):
return True
class TestPredicates(IsTestBase): class TestPredicates(IsTestBase):
def test_sixteen(self): def test_sixteen(self):
count = len([x for x in dir(inspect) if x.startswith('is')]) count = len([x for x in dir(inspect) if x.startswith('is')])
@ -2459,47 +2463,62 @@ class TestSignatureObject(unittest.TestCase):
def test_signature_equality(self): def test_signature_equality(self):
def foo(a, *, b:int) -> float: pass def foo(a, *, b:int) -> float: pass
self.assertNotEqual(inspect.signature(foo), 42) self.assertFalse(inspect.signature(foo) == 42)
self.assertTrue(inspect.signature(foo) != 42)
self.assertTrue(inspect.signature(foo) == EqualsToAll())
self.assertFalse(inspect.signature(foo) != EqualsToAll())
def bar(a, *, b:int) -> float: pass def bar(a, *, b:int) -> float: pass
self.assertEqual(inspect.signature(foo), inspect.signature(bar)) self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
def bar(a, *, b:int) -> int: pass def bar(a, *, b:int) -> int: pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def bar(a, *, b:int): pass def bar(a, *, b:int): pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def bar(a, *, b:int=42) -> float: pass def bar(a, *, b:int=42) -> float: pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def bar(a, *, c) -> float: pass def bar(a, *, c) -> float: pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def bar(a, b:int) -> float: pass def bar(a, b:int) -> float: pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def spam(b:int, a) -> float: pass def spam(b:int, a) -> float: pass
self.assertNotEqual(inspect.signature(spam), inspect.signature(bar)) self.assertFalse(inspect.signature(spam) == inspect.signature(bar))
self.assertTrue(inspect.signature(spam) != inspect.signature(bar))
def foo(*, a, b, c): pass def foo(*, a, b, c): pass
def bar(*, c, b, a): pass def bar(*, c, b, a): pass
self.assertEqual(inspect.signature(foo), inspect.signature(bar)) self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
def foo(*, a=1, b, c): pass def foo(*, a=1, b, c): pass
def bar(*, c, b, a=1): pass def bar(*, c, b, a=1): pass
self.assertEqual(inspect.signature(foo), inspect.signature(bar)) self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
def foo(pos, *, a=1, b, c): pass def foo(pos, *, a=1, b, c): pass
def bar(pos, *, c, b, a=1): pass def bar(pos, *, c, b, a=1): pass
self.assertEqual(inspect.signature(foo), inspect.signature(bar)) self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
def foo(pos, *, a, b, c): pass def foo(pos, *, a, b, c): pass
def bar(pos, *, c, b, a=1): pass def bar(pos, *, c, b, a=1): pass
self.assertNotEqual(inspect.signature(foo), inspect.signature(bar)) self.assertFalse(inspect.signature(foo) == inspect.signature(bar))
self.assertTrue(inspect.signature(foo) != inspect.signature(bar))
def foo(pos, *args, a=42, b, c, **kwargs:int): pass def foo(pos, *args, a=42, b, c, **kwargs:int): pass
def bar(pos, *args, c, b, a=42, **kwargs:int): pass def bar(pos, *args, c, b, a=42, **kwargs:int): pass
self.assertEqual(inspect.signature(foo), inspect.signature(bar)) self.assertTrue(inspect.signature(foo) == inspect.signature(bar))
self.assertFalse(inspect.signature(foo) != inspect.signature(bar))
def test_signature_unhashable(self): def test_signature_unhashable(self):
def foo(a): pass def foo(a): pass
@ -2629,11 +2648,17 @@ class TestParameterObject(unittest.TestCase):
P = inspect.Parameter P = inspect.Parameter
p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY) p = P('foo', default=42, kind=inspect.Parameter.KEYWORD_ONLY)
self.assertEqual(p, p) self.assertTrue(p == p)
self.assertNotEqual(p, 42) self.assertFalse(p != p)
self.assertFalse(p == 42)
self.assertTrue(p != 42)
self.assertTrue(p == EqualsToAll())
self.assertFalse(p != EqualsToAll())
self.assertEqual(p, P('foo', default=42, self.assertTrue(p == P('foo', default=42,
kind=inspect.Parameter.KEYWORD_ONLY)) kind=inspect.Parameter.KEYWORD_ONLY))
self.assertFalse(p != P('foo', default=42,
kind=inspect.Parameter.KEYWORD_ONLY))
def test_signature_parameter_unhashable(self): def test_signature_parameter_unhashable(self):
p = inspect.Parameter('foo', default=42, p = inspect.Parameter('foo', default=42,
@ -2936,19 +2961,26 @@ class TestBoundArguments(unittest.TestCase):
def test_signature_bound_arguments_equality(self): def test_signature_bound_arguments_equality(self):
def foo(a): pass def foo(a): pass
ba = inspect.signature(foo).bind(1) ba = inspect.signature(foo).bind(1)
self.assertEqual(ba, ba) self.assertTrue(ba == ba)
self.assertFalse(ba != ba)
self.assertTrue(ba == EqualsToAll())
self.assertFalse(ba != EqualsToAll())
ba2 = inspect.signature(foo).bind(1) ba2 = inspect.signature(foo).bind(1)
self.assertEqual(ba, ba2) self.assertTrue(ba == ba2)
self.assertFalse(ba != ba2)
ba3 = inspect.signature(foo).bind(2) ba3 = inspect.signature(foo).bind(2)
self.assertNotEqual(ba, ba3) self.assertFalse(ba == ba3)
self.assertTrue(ba != ba3)
ba3.arguments['a'] = 1 ba3.arguments['a'] = 1
self.assertEqual(ba, ba3) self.assertTrue(ba == ba3)
self.assertFalse(ba != ba3)
def bar(b): pass def bar(b): pass
ba4 = inspect.signature(bar).bind(1) ba4 = inspect.signature(bar).bind(1)
self.assertNotEqual(ba, ba4) self.assertFalse(ba == ba4)
self.assertTrue(ba != ba4)
class TestSignaturePrivateHelpers(unittest.TestCase): class TestSignaturePrivateHelpers(unittest.TestCase):

View File

@ -66,6 +66,8 @@ Core and Builtins
Library Library
------- -------
- Issue #24206: Fixed __eq__ and __ne__ methods of inspect classes.
- Issue #21750: mock_open.read_data can now be read from each instance, as it - Issue #21750: mock_open.read_data can now be read from each instance, as it
could in Python 3.3. could in Python 3.3.