66from .compat import raise_from , with_metaclass
77from .default import default , warn_if_defaults_use_non_interface_members
88from .formatting import bulleted_list
9- from .functional import complement , keyfilter , valfilter
9+ from .functional import complement , keyfilter , merge , valfilter
1010from .typecheck import compatible
1111from .typed_signature import TypedSignature
1212from .utils import is_a , unique
@@ -21,9 +21,14 @@ class InvalidImplementation(TypeError):
2121 """
2222
2323
24- CLASS_ATTRIBUTE_WHITELIST = frozenset (
25- ["__doc__" , "__module__" , "__name__" , "__qualname__" , "__weakref__" ]
26- )
24+ CLASS_ATTRIBUTE_WHITELIST = frozenset ([
25+ '__doc__' ,
26+ '__module__' ,
27+ '__name__' ,
28+ '__qualname__' ,
29+ '__weakref__' ,
30+ '_INTERFACE_IGNORE_MEMBERS' ,
31+ ])
2732
2833is_interface_field_name = complement (CLASS_ATTRIBUTE_WHITELIST .__contains__ )
2934
@@ -72,6 +77,14 @@ def _conflicting_defaults(typename, conflicts):
7277 return InvalidImplementation (message )
7378
7479
80+ def _merge_parent_signatures (bases ):
81+ return merge (filter (None , (getattr (b , '_signatures' ) for b in bases )))
82+
83+
84+ def _merge_parent_defaults (bases ):
85+ return merge (filter (None , (getattr (b , '_defaults' ) for b in bases )))
86+
87+
7588class InterfaceMeta (type ):
7689 """
7790 Metaclass for interfaces.
@@ -80,22 +93,47 @@ class InterfaceMeta(type):
8093 """
8194
8295 def __new__ (mcls , name , bases , clsdict ):
83- signatures = {}
84- defaults = {}
85- for k , v in keyfilter (is_interface_field_name , clsdict ).items ():
96+ signatures = _merge_parent_signatures (bases )
97+ defaults = _merge_parent_defaults (bases )
98+ ignored = clsdict .get ('_INTERFACE_IGNORE_MEMBERS' , set ())
99+
100+ for field , v in keyfilter (is_interface_field_name , clsdict ).items ():
101+ if field in ignored :
102+ continue
103+
86104 try :
87- signatures [ k ] = TypedSignature (v )
105+ signature = TypedSignature (v )
88106 except TypeError as e :
89107 errmsg = (
90108 "Couldn't parse signature for field "
91109 "{iface_name}.{fieldname} of type {attrtype}." .format (
92- iface_name = name , fieldname = k , attrtype = getname (type (v )),
110+ iface_name = name ,
111+ fieldname = field ,
112+ attrtype = getname (type (v )),
93113 )
94114 )
95115 raise_from (TypeError (errmsg ), e )
96116
117+ if field in signatures :
118+ for base in bases :
119+ if field in bases ._signatures :
120+ raise TypeError (
121+ "Interface field {new}.{field} conflicts with "
122+ "parent field {old}.{field}." .format (
123+ new = name ,
124+ old = base .name ,
125+ field = field ,
126+ )
127+ )
128+ else :
129+ # If we hit this there's a bug in
130+ # _extract_parent_signatures above.
131+ raise AssertionError ("Inconsistent bases!" )
132+ else :
133+ signatures [field ] = signature
134+
97135 if isinstance (v , default ):
98- defaults [k ] = v
136+ defaults [field ] = v
99137
100138 warn_if_defaults_use_non_interface_members (
101139 name , defaults , set (signatures .keys ())
@@ -258,6 +296,9 @@ def _format_mismatched_methods(self, mismatched):
258296 )
259297
260298
299+ empty_set = frozenset ([])
300+
301+
261302class Interface (with_metaclass (InterfaceMeta )):
262303 """
263304 Base class for interface definitions.
@@ -312,6 +353,9 @@ def delete(self, key):
312353 --------
313354 :func:`implements`
314355 """
356+ # Don't consider these members part of the interface definition for
357+ # children of `Interface`.
358+ _INTERFACE_IGNORE_MEMBERS = {'__new__' , 'from_class' }
315359
316360 def __new__ (cls , * args , ** kwargs ):
317361 raise TypeError ("Can't instantiate interface %s" % getname (cls ))
@@ -349,7 +393,10 @@ def from_class(cls, existing_class, subset=None, name=None):
349393 )
350394
351395
352- empty_set = frozenset ([])
396+ # Signature requirements are inherited, so make sure the base interface doesn't
397+ # require any methods of children.
398+ assert Interface ._signatures == {}
399+ assert Interface ._defaults == {}
353400
354401
355402class ImplementsMeta (type ):
0 commit comments