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