Skip to content

Commit

Permalink
BUG: Fix crash when using @default with @Property.
Browse files Browse the repository at this point in the history
  • Loading branch information
Scott Sanderson committed Nov 22, 2019
1 parent f4140bf commit a184e73
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 1 deletion.
12 changes: 11 additions & 1 deletion interface/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ def non_member_attributes(defaults, members):
# staticmethods can't use attributes of the interface.
continue

elif isinstance(impl, property):
impl = impl.fget

self_name = TypedSignature(impl).first_argument_name
if self_name is None:
# No parameters.
Expand All @@ -73,13 +76,20 @@ def accessed_attributes_of_local(f, local_name):
The analysis performed by this function is conservative, meaning that
it's not guaranteed to find **all** attributes used.
"""
try:
instrs = dis.get_instructions(f)
except TypeError:
# Got a default wrapping an object that's not a python function. Be
# conservative and assume this is safe.
return set()

used = set()
# Find sequences of the form: LOAD_FAST(local_name), LOAD_ATTR(<name>).
# This will find all usages of the form ``local_name.<name>``.
#
# It will **NOT** find usages in which ``local_name`` is aliased to
# another name.
for first, second in sliding_window(dis.get_instructions(f), 2):
for first, second in sliding_window(instrs, 2):
if first.opname == 'LOAD_FAST' and first.argval == local_name:
if second.opname in ('LOAD_ATTR', 'LOAD_METHOD', 'STORE_ATTR'):
used.add(second.argval)
Expand Down
23 changes: 23 additions & 0 deletions interface/tests/test_interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,29 @@ def method2(self):
assert C().has_default() == 3


def test_default_property():

class IFace(Interface): # pragma: nocover

@default
@property
def default_prop(self):
return True

class C(implements(IFace)): # pragma: nocover
pass

assert C().default_prop

class D(implements(IFace)):

@property
def default_prop(self):
return False

assert not D().default_prop


def test_override_default():

class IFace(Interface): # pragma: nocover
Expand Down

0 comments on commit a184e73

Please sign in to comment.