Friday, July 21, 2006

Python interface

Az interface egy hasznos dolog, kulonosen ha frameworkot tervez az ember. Az adott specifikaciot eloszor interfacekkel irjuk le, majd arra adunk egy konkret implementaciot. Az interface alapjan mas is eltudja kesziteni a meglevovel kompatibilis de eltero implementaciot. A kozos interface pedig biztositja hogy meglevo mas libekkel egyutt tudjon mukodni. Pythonban nincsenek interfacek, es ugy vettem eszre hogy legtobben nem is nagyon tartanak ra igenyt. Ugyanakkor a nagyobb frameworkok mint zope, kifejlesztettek interfacekre sajat modszert. Megprobaltam en is irni egy egyszeru decoratort ami ellenorzi hogy egy osztaly implementalta-e maradektalanul a megadott interfacet.

Egy ehhez hasonlot akartam eloszor csinalni, de class decorator (meg?) nincs pythonban igy a syntax ezt nem engedi meg.


@implements( [IInterface1, IInterface2] ) # not supported
class Test:
...


Ezert fuggveny decoratorral probalkoztam. Konstruktort altalban explicit megadja az ember igy erre huztam ra a decorator fuggvenyt. A problema ezzel hogy peldanyositaskor ellenorzi, nem pedig a modul betoltesekor, igy csak runtime derul ki ha baj van. (De talan hamarabb mintha metodus hivasnal jonnenk ra hogy nem letezik az adott fuggveny)


class ITest:
def testMethod(self): pass

class Cloneable:
def clone(): pass

class Test:

@implements( (ITest, Cloneable) )

def __init__(self, s, i):
print s, i

def testMethod(self):
print 'implemented'

def clone(self):
print 'clone test'

t = Test( 'test', 1 )
t.testMethod()
t.clone()


A konstruktorra kell hattatni a decoratort, ami visszad egy olyan fuggvenyt ami leellenorzi az implementaciot es meghivja az eredeti konstruktort. A tovabbi problema ezzel hogy minden egyes peldanyositaskor lefut az ellenorzes, es feleslegesen lassit. Ezt esetleg meg lehetne oldani egy global release/debug flaggel amit ha kikapcsol az ember akkor skipeli az ellenorzest. Ha valami static initializacios blokkba el lehetne helyezni hasonlo modon az ellenorzest es ugy a modul importalasanal le tudna ellenorizni akkor hasznalhato lenne. Ha valakinek van erre hasznalhato otlete az irja meg plz.

A decorator amit en hasznaltam a kovetkezo:


def implements( infaces ):
"""
implements decorator
usage:
class Sample:
@implements( (IInterface1, IInterface2, IInterfaceN )
def __init__(self, args):
...
warning: this will check the implementation at runtime, before every creation of the instance
"""
def f( init ):

from types import MethodType

def getMethods( clz ):
return [i for i in dir(clz) if type(getattr(clz, i)) == MethodType]

def checkInterface( clazz ):
cmethods = getMethods( clazz )
for inf in infaces:
imethods = getMethods( inf )
for i in imethods:
assert i in cmethods, `i` + ' not correctly implemented'

def new_init(ref, *args, **kargs): # this will be the new constructor
checkInterface( ref.__class__ )
return init(ref, *args, **kargs)

return new_init

return f

0 comments: