diff --git a/pure_interface.py b/pure_interface.py index a3c8e62..546720a 100644 --- a/pure_interface.py +++ b/pure_interface.py @@ -509,7 +509,7 @@ def __new__(mcs, clsname, bases, attributes, **kwargs): attribute_names, method_signatures = _get_abc_interface_props_and_funcs(base) interface_method_signatures.update(method_signatures) interface_attribute_names.update(attribute_names) - elif not issubclass(base, PureInterface) and is_development: + elif is_development and not issubclass(base, PureInterface): _check_method_signatures(base.__dict__, base.__name__, interface_method_signatures) if is_development: @@ -536,13 +536,17 @@ def __new__(mcs, clsname, bases, attributes, **kwargs): 'Did you forget to inherit from object to make the class concrete?'.format(func.__name__)) else: # concrete sub-type namespace = attributes - class_properties = set(k for k, v in namespace.items() if _is_descriptor(v)) + class_properties = set() + for bt, is_interface in base_types: + if not is_interface: + class_properties |= set(k for k, v in bt.__dict__.items() if _is_descriptor(v)) + class_properties |= set(k for k, v in namespace.items() if _is_descriptor(v)) abstract_properties.difference_update(class_properties) partial_implementation = 'pi_partial_implementation' in namespace if partial_implementation: value = namespace.pop('pi_partial_implementation') if not value: - warnings.warn('Partial implmentation is indicated by presence of ' + warnings.warn('Partial implementation is indicated by presence of ' 'pi_partial_implementation attribute, not it''s value') # create class diff --git a/tests/test_implementation_checks.py b/tests/test_implementation_checks.py index 5bb94f5..a5442dc 100644 --- a/tests/test_implementation_checks.py +++ b/tests/test_implementation_checks.py @@ -11,6 +11,13 @@ except ImportError: import mock +class ADescriptor(object): + def __init__(self, value): + self._value = value + + def __get__(self, instance, owner): + return self._value + class IAnimal(PureInterface): @abstractproperty @@ -260,7 +267,16 @@ class SimpleSimon(object, ISimple): pi_partial_implementation = False self.assertEqual(warn.call_count, 1) - self.assertTrue(warn.call_args[0][0].startswith('Partial implmentation is indicated')) + self.assertTrue(warn.call_args[0][0].startswith('Partial implementation is indicated')) + + def test_super_class_properties_detected(self): + class HeightDescr(object): + height = ADescriptor('really tall') + + class Test(HeightDescr, IPlant): + pass + + self.assertEqual(frozenset([]), Test._pi.abstractproperties) class TestPropertyImplementations(unittest.TestCase):