99
1010import re
1111
12- simple_case_pattern = re .compile (r'''([A-Za-z0-9_]+\.?)+''' )
13-
1412
1513class ProxyProperty :
1614 '''
@@ -60,38 +58,24 @@ def __init__(self, attribute_name, doc=None):
6058 raise Exception ("The `attribute_name` must start with a dot to "
6159 "make it clear it's an attribute. %s does not "
6260 "start with a dot." % repr (attribute_name ))
61+ self .getter = self .setter = None
62+ exec ('def getter(thing): return thing%s' % attribute_name , globals (), locals ())
63+ exec ('def setter(thing, value): thing%s = value' % attribute_name )
64+ exec ('self.getter, self.setter = getter, setter' )
6365 self .attribute_name = attribute_name [1 :]
6466 self .__doc__ = doc
6567
6668
67- def __get__ (self , obj , our_type = None ):
68- if obj is None :
69+ def __get__ (self , thing , our_type = None ):
70+ if thing is None :
6971 # We're being accessed from the class itself, not from an object
7072 return self
7173 else :
72- if simple_case_pattern .match (self .attribute_name ):
73- current_object = obj
74- for attribute_name in self .attribute_name .split ('.' ):
75- current_object = getattr (current_object , attribute_name )
76- return current_object
77- else :
78- from python_toolbox import address_tools
79- return address_tools .resolve ('obj.%s' % self .attribute_name ,
80- namespace = {'obj' : obj })
81-
82- def __set__ (self , obj , value ):
74+ return self .getter (thing )
8375
84- # todo: should I check if `obj` is `None` and set on class? Same for
76+ def __set__ (self , thing , value ):
77+ # todo: should I check if `thing` is `None` and set on class? Same for
8578 # `__delete__`?
8679
87- if simple_case_pattern .match (self .attribute_name ):
88- current_object = obj
89- for attribute_name in self .attribute_name .split ('.' )[:- 1 ]:
90- current_object = getattr (current_object , attribute_name )
91- setattr (current_object , self .attribute_name .split ('.' )[- 1 ], value )
92- else :
93- from python_toolbox import address_tools
94- left_segment , right_segment = self .attribute_name .rsplit ('.' , 1 )
95- deepest_object = address_tools .resolve ('obj.%s' % left_segment ,
96- namespace = {'obj' : obj })
97- setattr (deepest_object , right_segment , value )
80+ return self .setter (thing , value )
81+
0 commit comments