-
Notifications
You must be signed in to change notification settings - Fork 0
/
translator.py
96 lines (85 loc) · 3.17 KB
/
translator.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#sdobrev 2006
'timed proxy, translating attr-access into attr.get( context)'
def _get( obj, context): #very careful about attribute access/try/except here!
try: g = obj.get
except AttributeError: pass
else:
#try:
obj = g( context)
#except AttributeError: maybe translate into another error?
return obj
class Translator1( object):
''' proxy, translating attr-access into attr.get( context)
1 level over dict
'''
__slots__ = ( '_context', '_sources')
def __init__( me, context, sources): #e.g. sources=locals()
me._context = context
me._sources = sources
#x.get(context): lazy at getattr
def as_keys( klas, context, **sources): #use this to flatten c=a.b.c
return klas( context, sources)
as_keys = classmethod( as_keys )
def __getattr__( me, name):
r = me._sources[ name ]
return _get( r, me._context)
Translator = Translator1.as_keys
if __name__ == '__main__':
#not stable..
class Translator0( object):
''' proxy, translating attr-access into get( attr, context)
recursive over 1 obj
not reliable and maybe slow - the breaking of recursion cannot be made well
'''
__slots__ = ( '_context', '_obj')
def __init__( me, context, obj):
me._context = context
me._obj = obj #obj.get(context): extern
#me._obj = _get( obj, context) #obj.get(context): now
#obj.attr.get(context): lazy at getattr
def __getattr__( me, name):
r = getattr( me._obj, name)
if ( callable( r)
or name.startswith('__')
or type(r) in (int,float,bool,str)
): return r #when to break the recursion/loop is VERY important/tricky
context = me._context
if 0:
return Translator0( context, _get( r, context))
else: #reuse self
me._obj = _get( r, context)
return me
class Translator2( Translator1):
''' proxy, translating attr-access into get( attr, context)
any/multi-level over dict
see Translator0 for caveats
'''
__slots__ = ()
def __getattr__( me, name):
r = Translator1.__getattr__( me, name )
context = me._context
return Translator0( context, r)
##### test
class C:
def __init__(me, name, v =1):
me.name = name
me.v = v
def get( me, time):
print 'get', me.__class__.__name__, me.name, '(',time,')'
return me#.v
a = C('a',2)
b = C('b',4)
a.x = C('a.x',8)
a.x.z = C('a.x.z',16)
a.y = 32
c = C('c',1)
print '--t1-keys--'
t = Translator1.as_keys( context=314, a=a, b=b )
z = t.a.v + t.b.v + t.a.x.z.v + t.a.y #a,b,a,a
print '--t1-locals--'
t = Translator1( context=314, sources=locals() )
z = t.a.v + t.b.v + t.a.x.z.v + t.a.y + t.c.v #a,b,a,a,c
print '--t2--'
t = Translator2( context=314, sources=locals() )
z = t.a.v + t.b.v + t.a.x.z.v + t.a.y + t.c.v #a,b,a,x,z,a,c
# vim:ts=4:sw=4:expandtab