Behaviour-based interface/protocol implementation?

Discussion in 'Python' started by Alan Franzoni, Jan 24, 2011.

  1. 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
     
    Alan Franzoni, Jan 24, 2011
    #1
    1. Advertising

  2. Alan Franzoni

    Carl Banks Guest

    On Jan 24, 2:13 am, Alan Franzoni <> wrote:
    > 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.


    Write some kind of signature proxy to do it.

    class SomeSignature(object):
    def __init__(self,target):
    self.target = target
    def somemethod(self,value):
    if hasattr(self.target,"somemethod"):
    self.target.somemethod(value)

    SomeSignature(myobj).somemethod(somevalue)

    Generalizing the proxy to easily accommodate all kinds of signatures
    to your heart's delight left as an exercise (and it's likley to
    involve metaclass programming).

    > 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?


    Based on this thread, you have quite specific requirements, so it's
    doubtful someone else has implemented exactly what you want.


    And because it hasn't been mentioned in this thread yet--surprisingly--
    many people in Python prefer the EAFP strategy, "Easier to Ask
    Forgiveness than Permission", that is, to just do it and handle the
    resulting exception:

    try:
    myobj.somemethod(somevalue)
    except AttributeError:
    # doesn't fit signature, so do nothing
    pass

    Personally, I have my doubts about the method in general. It's
    definitely preferrable in many cases (like opening a file, where it
    avoids a race condition) but for something like this I don't see it
    working out too well. But I'm just throwing it out there.


    Carl Banks
     
    Carl Banks, Jan 27, 2011
    #2
    1. Advertising

  3. On Thu, Jan 27, 2011 at 10:30 PM, Carl Banks <> wrote:
    > Write some kind of signature proxy to do it.


    I don't have a specific implementation idea yet, I see how that grows.

    > Based on this thread, you have quite specific requirements, so it's
    > doubtful someone else has implemented exactly what you want.


    Yes, but asking is better than blinding reimplementing :)

    > And because it hasn't been mentioned in this thread yet--surprisingly--
    > many people in Python prefer the EAFP strategy, "Easier to Ask
    > Forgiveness than Permission", that is, to just do it and handle the
    > resulting exception:
    >
    > try:
    >    myobj.somemethod(somevalue)
    > except AttributeError:
    >    # doesn't fit signature, so do nothing
    >    pass


    Sure. That's an approach. But this has drawbacks.

    - it violates the CQS principle:
    http://en.wikipedia.org/wiki/Command-query_separation

    - Maybe my interface has not just a single method, and I might want to
    call multiple methods on my object. I need to check for all signatures
    before proceeding.

    - When calling the method, if an exception is raised - either
    AttributeError or TypeError most of the times - it could not be
    generated from my own call, but from a call deeper into the stack;
    It's easy to just think "that object doesn't support that interface" I
    could mistake an object for not supporting an interface, and I could
    silently swallow a true runtime exception instead. Maybe some stack
    analysis could be performed, but I'd prefer to check as much as I can
    *before* calling.

    - Sometimes I'd like to group objects depending on their *behaviour*
    (not their type), and then feed them somewhere else without actually
    calling their methods. If I can know their behaviour just after
    they've been called, it might be just too late.


    --
    Alan Franzoni
    --
    contact me at public@[mysurname].eu
     
    Alan Franzoni, Jan 27, 2011
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. S. Bernstein
    Replies:
    3
    Views:
    1,929
    S. Bernstein
    Feb 4, 2009
  2. hosi

    Webservice interface using HTTPS Protocol

    hosi, Dec 2, 2004, in forum: ASP .Net Web Services
    Replies:
    1
    Views:
    119
    Dan Rogers
    Dec 2, 2004
  3. dimikaka
    Replies:
    0
    Views:
    228
    dimikaka
    Feb 16, 2005
  4. Ajit

    Protocol Implementation using WCF

    Ajit, Aug 14, 2007, in forum: ASP .Net Web Services
    Replies:
    0
    Views:
    146
  5. Erik Veenstra

    Freenet Client Protocol implementation?

    Erik Veenstra, Jan 28, 2007, in forum: Ruby
    Replies:
    0
    Views:
    96
    Erik Veenstra
    Jan 28, 2007
Loading...

Share This Page