PEP 245

Carlos Alberto Reis Ribeiro cribeiro at mail.inet.com.br
Wed Apr 4 23:18:09 EDT 2001


This is my own experiment with adapters and interfaces. I could not join 
the SourceForge project, and I dont know how things are being implemented 
right now. Use as you wish (even as a example of don't-do-this <wink>).

Warning: this is work in progress, and as such, there are a *lot* of things 
that could be improved, some of them quite obvious. My objective with this 
example is just to show some ideas that I had while reading all the 
material in the past weeks.

There are two basic implementations of "interfaces", named Interface_V1 and 
Interface_V2. Basically they represent two different methods to write a 
interface specification using Python 2.0 as it is today. Enjoy <wink> or 
flame <duck>.

SAMPLE OUTPUT:

 >>> f = FakeSequence([1,2,3,4])
 >>> for i in f: print i
...
Traceback (innermost last):
   File "<interactive input>", line 1, in ?
AttributeError: 'FakeSequence' instance has no attribute '__getitem__'
 >>> for i in f.__adapt__(I1_Sequence): print i
...
1
2
3
4
 >>> for i in f.__adapt__(I2_Sequence): print i
...
1
2
3
4
 >>>

CODE:

""" Adapter proof-of-concept
     (c) 2001 Carlos Ribeiro - cribeiro at mail.inet.com.br
     Released in public domain for use "as-is"
"""

from types import *

#-----------------------------------------------------------------------

class CAnyType:
   """ AnyType can be used to specify a parameter of 'any type'"""
   def __cmp__(self, other):
   	return (type(other) != TypeType)
   def __rcmp__(self, other):
   	return (type(other) != TypeType)

AnyType = CAnyType()

#-----------------------------------------------------------------------

class Interface_V1:
   """ base class for interface specification """
   __methodlist__ = []

class I1_Sequence(Interface_V1):
   """ Protocol to implement sequence-like objects """
   __methodlist__ = ['__len__', '__getitem__', '__setitem__', '__delitem__']
   def __len__ (self): pass
   def __getitem__(self, key): pass
   def __setitem__(self, key, value): pass
   def __delitem__(self, key): pass

#-----------------------------------------------------------------------

class Interface_V2:
   """ base class for interface specification """
   pass

class I2_Sequence(Interface_V2):
   """ Protocol to implement sequence-like objects """
   __len__      = ((), (IntType))
   __getitem__  = ((IntType,), (AnyType,))
   __setitem__  = ((IntType,AnyType), ())
   __delitem__  = ((IntType,), ())

#-----------------------------------------------------------------------

class Adapter:
   """ empty class that can be used to build any kind of adapter """
   pass


def MakeInterfaceAdapter_V1(interface, object, rename_map = {}):
   """ Returns a protocol adapter for an object supporting the interface.
       By default it will map methods in the object to the methods with
       the same name in the interface/protocol. The optional parameter
       'rename_map' is a map[interface_name] = object_name, that contains
       all methods that need to be renamed.
   """
   a = Adapter()
   for imethod in interface.__methodlist__:
     # check the rename list
     if rename_map.has_key(imethod):
       omethod = rename_map[imethod]
     else:
       omethod = imethod
     setattr(a, imethod, getattr(object, omethod))
   return a

def MakeInterfaceAdapter_V2(interface, object, rename_map = {}):
   """ Returns a protocol adapter for an object supporting the interface.
       By default it will map methods in the object to the methods with
       the same name in the interface/protocol. The optional parameter
       'rename_map' is a map[interface_name] = object_name, that contains
       all methods that need to be renamed.
   """
   a = Adapter()
   for imethod, iparam in interface.__dict__.items():
     # check to see if it's a valid method definition
     if (type(iparam) is TupleType) and (len(iparam) == 2):
       # check the rename list
       if rename_map.has_key(imethod):
         omethod = rename_map[imethod]
       else:
         omethod = imethod
       setattr(a, imethod, getattr(object, omethod))
   return a

#-----------------------------------------------------------------------

class FakeSequence:
   """ Acts like a sequence, but it's not a UserList
       Does not make any error check, etc.
   """

   # dictionary to make the call to MakeInterfaceAdapter cleaner
   ir_sequence = {
     '__len__'    :'seqlen',
     '__getitem__':'seqgetitem',
     '__setitem__':'seqsetitem',
     '__delitem__':'seqdelitem'
     }

   def __init__(self, p_list):
     self.list = p_list

   def seqlen(self, p_list):
     return (self.list)

   def seqgetitem(self, i):
     return self.list[i]

   def seqsetitem(self, i, p_value):
     self.list[i] = p_value

   def seqdelitem(self, i):
     del(self.list[i])

   def __adapt__(self, protocol):
     if protocol == I1_Sequence:
       return MakeInterfaceAdapter_V1(protocol, self, self.ir_sequence)
     elif protocol == I2_Sequence:
       return MakeInterfaceAdapter_V2(protocol, self, self.ir_sequence)
     else:
       return None

#-----------------------------------------------------------------------


Carlos Ribeiro






More information about the Python-list mailing list