Source code for pacman.model.decorators.overrides

import inspect


[docs]class overrides(object): """ A decorator for indicating that a method overrides another method in\ a super class. This checks that the method does actually exist, copies the doc-string for the method, and enforces that the method\ overridden is specified, making maintenance easier. """ __slots__ = [ # The method in the superclass that this method overrides "_super_class_method", # True if the doc string is to be extended, False to set if not set "_extend_doc", # Any additional arguments required by the subclass method "_additional_arguments" ] def __init__( self, super_class_method, extend_doc=True, additional_arguments=None): """ :param super_class_method: The method to override in the superclass :param extend_doc:\ True the method doc string should be appended to the super-method\ doc string, False if the documentation should be set to the\ super-method doc string only if there isn't a doc string already :param additional_arguments:\ Additional arguments taken by the subclass method over the\ superclass method e.g. that are to be injected """ self._super_class_method = super_class_method self._extend_doc = extend_doc self._additional_arguments = additional_arguments if additional_arguments is None: self._additional_arguments = {} if isinstance(super_class_method, property): self._super_class_method = super_class_method.fget def __call__(self, method): # Check and fail if this is a property if isinstance(method, property): raise AttributeError( "Please ensure that the override decorator is the last" " decorator before the method declaration") # Check that the name matches if method.__name__ != self._super_class_method.__name__: raise AttributeError( "Super class method name {} does not match {}. " "Ensure override is the last decorator before the method " "declaration".format( self._super_class_method.__name__, method.__name__)) # Check that the arguments match (except for __init__ as this might # take extra arguments or pass arguments not specified) if method.__name__ != "__init__": method_args = inspect.getargspec(method) super_args = inspect.getargspec(self._super_class_method) all_args = [ arg for arg in method_args.args if arg not in self._additional_arguments ] default_args = None if method_args.defaults is not None: default_args = [ arg for arg in method_args.defaults if arg not in self._additional_arguments ] if len(all_args) != len(super_args.args): raise AttributeError( "Method has {} arguments but super class method has {}" " arguments".format( len(method_args.args), len(super_args.args))) for arg, super_arg in zip(all_args, super_args.args): if arg != super_arg: raise AttributeError( "Missing argument {}".format(super_arg)) if ((default_args is None and super_args.defaults is not None) or (default_args is not None and super_args.defaults is None) or (default_args is not None and super_args.defaults is not None and len(default_args) != len(super_args.defaults))): raise AttributeError( "Default arguments don't match super class method") if (self._super_class_method.__doc__ is not None and method.__doc__ is None): method.__doc__ = self._super_class_method.__doc__ elif (self._extend_doc and self._super_class_method.__doc__ is not None): method.__doc__ = ( self._super_class_method.__doc__ + method.__doc__ ) return method