Yet Another PEP: Interface Adapter Mechanism __adapt__

Clark C. Evans cce at clarkevans.com
Thu Mar 22 04:04:42 CET 2001


On Wed, 21 Mar 2001, Rainer Deyke wrote:
> This 'check_base' stuff is a mess. 

No joke.  Sorry for being so brain dead.  The following
code also has one or two errors, but should much better
illustrate the concept...

...

Here is the "merged" version where check_only is an
optional argument to adapt.  Imagine the operator,

  a isa b -> adapt(a,b,check_only=true)

--------------------------------------------------------
adapter/__init__.py
--------------------------------------------------------

import types
def adapt(obj,ident,check_only=0):

    # check to see if the current object is ok as is

    if obj is ident: return obj
    if type(obj) is ident: return obj
    if type(obj) is type(ident): return obj
    if type(ident) is types.ClassType:
        if type(obj) is types.InstanceType:
            if isinstance(obj,ident): return obj
        if type(obj) is types.ClassType:
            if issubclass(obj,ident): return obj

       # if we get a new interface type, code should
       # be added in this spot to check if obj is an 
       # instance of ident, where ident is an types.Interface
       # *THIS IS ANOTHER PEP*

    # the obj may have the answer, so ask it about the ident
    

    adapt = getattr(obj, '__adapt__',None)
    if adapt:
        retval = adapt(ident,check_only)
        if retval: return retval

    # the ident may have the answer, so ask it about the obj

       # some code here for a class, type, or interface,
       # or whatever to check to see if it can adapt the
       # class.  Unfortunately, calling __adapt__ won't
       # work exactly here...  we could add another
       # argument, "forward"... *THIS IS ANOTHER PEP*
 
    # a registry may exist, ask it about adapters.

       # there may be a registry-based  solution 
       # adapters that can be added to the system without
       # modifying either A or B.  *THIS IS ANOTHER PEP*

--------------------------------------------------------------
adapter/example.py
--------------------------------------------------------------

class EggsOnly:  # an unrelated class/interface
    def eggs(self,str): print "eggs!" + str

class HamOnly:  # used as an interface, no inhertance
    def ham(self,str): pass
    def _bugger(self): pass  # irritating a private member

class SpamOnly: # a base class, inheritance used
    def spam(self,str): print "spam!" + str

class EggsSpamAndHam (SpamOnly):
    def ham(self,str): print "ham!" + str
    def __adapt__(self,ident,check_only):
        if ident is HamOnly:
            return self       # implements HamOnly implicitly, no _bugger
        if ident is EggsOnly and not check_only:
            return EggsOnly() # Knows how to create the eggs!

------------------------------------------------------------------
testadapter.py
------------------------------------------------------------------
import adapter.example
from adapter import adapt
def testadapter():
    x = adapter.example.EggsSpamAndHam()
    adapt(x,adapter.example.SpamOnly).spam("Ni!")
    adapt(x,adapter.example.EggsOnly).eggs("Ni!")
    adapt(x,adapter.example.HamOnly).ham("Ni!")
    adapt(x,adapter.example.EggsSpamAndHam).ham("Ni!")
    #
    # imagine operator syntax for check_only:
    #
    #   if x isa adapter.example.SpamOnly: print "SpamOnly"
    #
    if (x,adapter.example.SpamOnly,1): print "SpamOnly"
    if (x,adapter.example.EggsOnly,1): print "EggsOnly"
    if (x,adapter.example.HamOnly,1): print "HamOnly"
    if (x,adapter.example.EggsSpamAndHam,1): print "EggsAndSpam"
    if (x,adapter.example.KnightsWhoSayNi,1): print "NightsWhoSayNi"
    adapt(x,adapter.example.KnightsWhoSayNi,1).spam("Ni!")


--------------------------------------------------------------------
example run
--------------------------------------------------------------------

>>> import testadapter
>>> testadapter.testadapter()
spam!Ni!
eggs!Ni!
ham!Ni!
ham!Ni!
SpamOnly
EggsOnly
HamOnly
EggsAndSpam
Traceback (innermost last):
  File "<interactive input>", line 1, in ?
  File "c:\work\testadapter.py", line 13, in testadapter
    if (x,adapter.example.KnightsWhoSayNi,1): print "NightsWhoSayNi"
AttributeError: KnightsWhoSayNi






More information about the Python-list mailing list