def __new__(cls, name, bases, dct): rv = cls = InterfaceClass.__new__(cls) cls.__id__ = nextId() cls.__methods__ = methods = [] cls.__properties__ = properties = [] cls.default = 'DEFAULT' cls.complexType = True possibleActions = [] actionAttachers = [] for key, value in list(dct.items()): if key[0] == '_': continue if isinstance(value, MetaTypedInterface): ## A Nested TypedInterface indicates a GroupBinding properties.append(GroupBinding(key, value, value.__id__)) ## zope.interface doesn't like these del dct[key] setattr(cls, key, value) elif isinstance(value, collections.Callable): names, _, _, typeList = inspect.getargspec(value) _testCallArgs = () if typeList is None: typeList = [] if len(names) == len(typeList) + 1: warnings.warn( "TypeInterface method declarations should not have a 'self' parameter", DeprecationWarning, stacklevel=2) del names[0] _testCallArgs = (_Marker,) if len(names) != len(typeList): ## Allow non-autocallable methods in the interface; ignore them continue argumentTypes = [ Argument(n, argtype, argtype.id) for n, argtype in zip(names[-len(typeList):], typeList) ] result = value(*_testCallArgs) label = None description = None if getattr(value, 'autocallable', None): # autocallables have attributes that can set label and description label = value.attributes.get('label', None) description = value.attributes.get('description', None) adapted = iformless.ITyped(result, None) if adapted is None: adapted = Object(result) # ITyped has label and description we can use if label is None: label = adapted.label if description is None: description = adapted.description defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(value.__doc__) if defaultLabel is None: # docstring had no label, try the action if it is an autocallable if getattr(value, 'autocallable', None): if label is None and value.action is not None: # no explicit label, but autocallable has action we can use defaultLabel = value.action if defaultLabel is None: # final fallback: use the function name as label defaultLabel = nameToLabel(key) if label is None: label = defaultLabel if description is None: description = defaultDescription theMethod = Method( adapted, argumentTypes, label=label, description=description ) if getattr(value, 'autocallable', None): methods.append( MethodBinding( key, theMethod, value.id, value.action, value.attributes)) else: possibleActions.append((value, MethodBinding(key, theMethod))) else: if not value.label: value.label = nameToLabel(key) if iformless.IActionableType.providedBy(value): actionAttachers.append(value) properties.append( Property(key, value, value.id) ) for attacher in actionAttachers: attacher.attachActionBindings(possibleActions) methods.sort(key=_sorter) properties.sort(key=_sorter) cls.__spec__ = spec = methods + properties spec.sort(key=_sorter) cls.name = name # because attributes "label" and "description" would become Properties, # check for ones with an underscore prefix. cls.label = dct.get('_label', None) cls.description = dct.get('_description', None) defaultLabel, defaultDescription = labelAndDescriptionFromDocstring(dct.get('__doc__')) if defaultLabel is None: defaultLabel = nameToLabel(name) if cls.label is None: cls.label = defaultLabel if cls.description is None: cls.description = defaultDescription return rv
def __new__(cls, name, bases, dct): rv = cls = InterfaceClass.__new__(cls) cls.__id__ = nextId() cls.__methods__ = methods = [] cls.__properties__ = properties = [] cls.default = 'DEFAULT' cls.complexType = True possibleActions = [] actionAttachers = [] for key, value in dct.items(): if key[0] == '_': continue if isinstance(value, MetaTypedInterface): ## A Nested TypedInterface indicates a GroupBinding properties.append(GroupBinding(key, value, value.__id__)) ## zope.interface doesn't like these del dct[key] setattr(cls, key, value) elif callable(value): names, _, _, typeList = inspect.getargspec(value) _testCallArgs = () if typeList is None: typeList = [] if len(names) == len(typeList) + 1: warnings.warn( "TypeInterface method declarations should not have a 'self' parameter", DeprecationWarning, stacklevel=2) del names[0] _testCallArgs = (_Marker, ) if len(names) != len(typeList): ## Allow non-autocallable methods in the interface; ignore them continue argumentTypes = [ Argument(n, argtype, argtype.id) for n, argtype in zip(names[-len(typeList):], typeList) ] result = value(*_testCallArgs) label = None description = None if getattr(value, 'autocallable', None): # autocallables have attributes that can set label and description label = value.attributes.get('label', None) description = value.attributes.get('description', None) adapted = iformless.ITyped(result, None) if adapted is None: adapted = Object(result) # ITyped has label and description we can use if label is None: label = adapted.label if description is None: description = adapted.description defaultLabel, defaultDescription = labelAndDescriptionFromDocstring( value.__doc__) if defaultLabel is None: # docstring had no label, try the action if it is an autocallable if getattr(value, 'autocallable', None): if label is None and value.action is not None: # no explicit label, but autocallable has action we can use defaultLabel = value.action if defaultLabel is None: # final fallback: use the function name as label defaultLabel = nameToLabel(key) if label is None: label = defaultLabel if description is None: description = defaultDescription theMethod = Method(adapted, argumentTypes, label=label, description=description) if getattr(value, 'autocallable', None): methods.append( MethodBinding(key, theMethod, value.id, value.action, value.attributes)) else: possibleActions.append( (value, MethodBinding(key, theMethod))) else: if not value.label: value.label = nameToLabel(key) if iformless.IActionableType.providedBy(value): actionAttachers.append(value) properties.append(Property(key, value, value.id)) for attacher in actionAttachers: attacher.attachActionBindings(possibleActions) methods.sort(_sorter) properties.sort(_sorter) cls.__spec__ = spec = methods + properties spec.sort(_sorter) cls.name = name # because attributes "label" and "description" would become Properties, # check for ones with an underscore prefix. cls.label = dct.get('_label', None) cls.description = dct.get('_description', None) defaultLabel, defaultDescription = labelAndDescriptionFromDocstring( dct.get('__doc__')) if defaultLabel is None: defaultLabel = nameToLabel(name) if cls.label is None: cls.label = defaultLabel if cls.description is None: cls.description = defaultDescription return rv