def test_staticmethod(self): class Foo(object): @staticmethod def foo(): pass self.assertFalse(__unit__.is_method(Foo.foo))
def test_classmethod__of_instance(self): class Foo(object): @classmethod def foo(cls): pass self.assertTrue(__unit__.is_method(Foo().foo))
def test_regular_method_attached_to_class__of_instance(self): class Foo(object): pass def foo(self): pass Foo.foo = foo self.assertTrue(__unit__.is_method(Foo().foo))
def test_function_attached_to_object(self): class Foo(object): pass def foo(self): pass obj = Foo() obj.foo = foo self.assertTrue(__unit__.is_method(obj.foo))
def test_classmethod_attached_to_class(self): class Foo(object): pass @classmethod def foo(cls): pass Foo.foo = foo self.assertTrue(__unit__.is_method(Foo.foo))
def _validate_method_decoration(meta, class_): """Validate the usage of ``@override`` and ``@final`` modifiers on methods of the given ``class_``. """ # TODO(xion): employ some code inspection tricks to serve ClassErrors # as if they were thrown at the offending class's/method's definition super_mro = class_.__mro__[1:] own_methods = ((name, member) for name, member in class_.__dict__.items() if is_method(member)) # check that ``@override`` modifier is present where it should be # and absent where it shouldn't (e.g. ``@final`` methods) for name, method in own_methods: shadowed_method, base_class = next( ((getattr(base, name), base) for base in super_mro if hasattr(base, name)), (None, None)) if meta._is_override(method): # ``@override`` is legal only when the method actually shadows # a method from a superclass, and that metod is not ``@final`` if not shadowed_method: raise ClassError("unnecessary @override on %s.%s" % (class_.__name__, name), class_=class_) if meta._is_final(shadowed_method): raise ClassError( "illegal @override on a @final method %s.%s" % (base_class.__name__, name), class_=class_) # if @override had parameter supplied, verify if it was # the same class as the base of shadowed method override_base = meta._get_override_base(method) if override_base and base_class is not override_base: if is_class(override_base): raise ClassError( "incorrect override base: expected %s, got %s" % (base_class.__name__, override_base.__name__)) else: raise ClassError( "invalid override base specified: %s" % (override_base, )) setattr(class_, name, method.method) else: if shadowed_method and name not in meta.OVERRIDE_EXEMPTIONS: if meta._is_final(shadowed_method): msg = "%s.%s is hiding a @final method %s.%s" % ( class_.__name__, name, base_class.__name__, name) else: msg = ("overridden method %s.%s " "must be marked with @override" % (class_.__name__, name)) raise ClassError(msg, class_=class_)
def final(arg): """Mark a class or method as _final_. Final classes are those that end the inheritance chain, i.e. forbid further subclassing. A final class can thus be only instantiated, not inherited from. Similarly, methods marked as final in a superclass cannot be overridden in any of the subclasses. .. note:: Final method itself can also be (in fact, it usually is) an overridden method from a superclass. In those cases, it's recommended to place @\ :func:`final` modifier before @\ :func:`override` for clarity:: class Foo(Base): @final @override def florb(self): super(Foo, self).florb() # ... .. versionadded:: 0.0.3 Now applicable to methods in addition to classes """ if inspect.isclass(arg): if not isinstance(arg, ObjectMetaclass): raise ValueError("@final can only be applied to a class " "that is a subclass of Object") elif not is_method(arg): raise TypeError("@final can only be applied to classes or methods") method = arg.method if isinstance(arg, _WrappedMethod) else arg method.__final__ = True return arg
def test_some_object(self): self.assertFalse(__unit__.is_method(object()))
def test_lambda(self): foo = lambda: None self.assertFalse(__unit__.is_method(foo))
def test_regular_method__of_instance(self): class Foo(object): def foo(self): pass self.assertTrue(__unit__.is_method(Foo().foo))
def test_regular_function(self): def foo(): pass self.assertFalse(__unit__.is_method(foo))
def test_none(self): self.assertFalse(__unit__.is_method(None))