Hello, I'd like to have a system which lets me do certain actions if the duck-type of a certain objects matches what I expect, i.e. I'd like to have a formalization of what it's sometimes done through getattr() calls:
if getattr(myobj, "somemethod", None) is not None: myobj.somemethod(somevalue) The above approach is sometimes too naive, because a) clutters code with many getattr calls and ifs b) I might want to check for multiple attributes and c) only checks for the method name and not for the method's signature. After looking at PyProtocols, zope.interface and python's own abc module, I'm left with a doubt: does any behaviour-based "interface testing" system exist for Python? I mean: all these three libraries use a register-based or inheritance-based approach; in abc, if I want instances of a class of mine "FooClass" to be "BarInterface" instances, I can either a) inherit from BarInterface or b) run "BarInterface.register(FooClass)". This poses some issues in a purely duck-typed context, IMHO. If an object perfectly satisfies the "BarInterface" signature, but it doesn't inherit from MyInterface and its class wasn't registered as a BarInterface implementor, the check "isinstance(myobj, BarInterface)" will yield a False result. This might not be a big deal if a) python >= 2.6 is used b) just checking for builtin interfaces - e.g. those defined in the "collections" module is required and c) you just require checking on basic types or on python builtin types (which correctly register builtin ABCs). What happens if I define my own ABC for my own purpose? There might be builtin objects, or third party libraries, which already offer objects that satisfy such interface, but I'd need to import such modules and register such classes as implementing my ABC, which is suboptimal. What I'd like to do is: class MyType(object): def someMethod(self, a, b): pass def otherMethod(self): pass class OtherType(object): def someMethod(self): pass def otherMethod(self): pass @DuckType class MyDuckType(object): def someMethod(self, a, b): pass def otherMethod(self): pass class TestDuckTypes(TestCase): def test_mytype_is_compatible_with_ducktype(self): myobj = MyType() self.assertEquals(True, MyDuckType.maybe_implemented_by(myobj)) def test_othertype_is_not_compatible_with_ducktype(self): myobj = OtherType() self.assertEquals(False, MyDuckType.maybe_implemented_by(myobj)) I'd like to do a kind of runtime-check for signatures. Of course there couldn't be an absolute certainty of interface implementation, because a runtime dynamic proxy method (accepting *args and **kwargs in its signature, as an example) might just fool my signature check. So, my questions are: a) does anything like that already exist in the python ecosystem? b) can anybody see any flaw either in what I'd like to do ("you shouldn't do that because...") or in the way I want to do it ("It won't work because...") -- Alan Franzoni -- contact me at public@[mysurname].eu -- http://mail.python.org/mailman/listinfo/python-list