Skip to content

Commit

Permalink
BUG: Fix superclass checking for subclass methods
Browse files Browse the repository at this point in the history
  • Loading branch information
michaels-lyft committed Apr 21, 2021
1 parent 7de8eeb commit d919324
Show file tree
Hide file tree
Showing 5 changed files with 25 additions and 8 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ develop-eggs
.installed.cfg
coverage.xml
nosetests.xml
venv/
.idea/

# C Extensions
*.o
Expand Down
2 changes: 1 addition & 1 deletion interface/functional.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def merge(dicts):
if len(dicts) == 0:
return {}
elif len(dicts) == 1:
return dicts[0]
return dicts[0].copy()
else:
out = dicts[0].copy()
for other in dicts[1:]:
Expand Down
21 changes: 16 additions & 5 deletions interface/tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -901,8 +901,8 @@ class AandB(A): # pragma: nocover
def method_b(self):
pass

# expected to fail since it's missing method_b
with pytest.raises(InvalidImplementation) as exc:

class JustA(implements(AandB)): # pragma: nocover
def method_a(self):
pass
Expand All @@ -917,8 +917,8 @@ class JustA failed to implement interface AandB:
)
assert actual_message == expected_message

# expected to fail since it's missing method_a
with pytest.raises(InvalidImplementation) as exc:

class JustB(implements(AandB)): # pragma: nocover
def method_b(self):
pass
Expand All @@ -933,6 +933,12 @@ class JustB failed to implement interface AandB:
)
assert actual_message == expected_message

# expected to pass since interface A only requires method_a
class JustA2(implements(A)): # pragma: nocover
def method_a(self):
pass

# expected to pass since it implements both methods
class Both(implements(AandB)): # pragma: nocover
def method_a(self):
pass
Expand All @@ -950,8 +956,8 @@ class B(A): # pragma: nocover
def method_b(self):
pass

# expected to fail since method_a has different signature in interface A
with pytest.raises(TypeError) as exc:

class C1(A): # pragma: nocover
def method_a(self, x):
pass
Expand All @@ -964,9 +970,9 @@ def method_a(self, x):
)
assert actual_message == expected_message

# expected to fail since method_b has different signature in interface B
with pytest.raises(TypeError) as exc:

class C2(A): # pragma: nocover
class C2(B): # pragma: nocover
def method_b(self, y, z=None):
pass

Expand All @@ -978,6 +984,11 @@ def method_b(self, y, z=None):
)
assert actual_message == expected_message

# expected to pass since method_b does not exist in interface A
class C3(A): # pragma: nocover
def method_b(self, y, z=None):
pass


def test_subclass_allow_compatible_extension():
class A(Interface): # pragma: nocover
Expand Down
6 changes: 5 additions & 1 deletion interface/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ def g(*args): # pragma: nocover

def test_merge():
assert merge([]) == {}
assert merge([{"a": 1, "b": 2}]) == {"a": 1, "b": 2}

input = {"a": 1, "b": 2}
output = merge([input])
assert output is not input
assert output == input

result = merge([{"a": 1}, {"b": 2}, {"a": 3, "c": 4}])
assert result == {"a": 3, "b": 2, "c": 4}
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def install_requires():

setup(
name="python-interface",
version="1.6.0",
version="1.6.1",
description="Pythonic Interface definitions",
author="Scott Sanderson",
author_email="scott.b.sanderson90@gmail.com",
Expand Down

0 comments on commit d919324

Please sign in to comment.