1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 """
20 Various decorators to ease delegation
21 """
22
23 __docformat__ = 'reStructuredText'
24
25 from types import UnboundMethodType
26 import logging
27
28 from . import Profile, DelegatorFactory
29
30
31 _logger = logging.getLogger("pytilities.delegation")
32
33
34
35
37 """
38 Makes a `DelegatorFactory` on the class and adds profiles to it.
39
40 The factory is stored as a class attribute with name _delegator_factory.
41 A Delegator method is installed on the class, it is the same as
42 _delegator_factory.Delegator.
43
44 `Profile`s are created based on the annotations left by `delegated`.
45 """
46
47 def _delegator_factory(cls):
48
49
50 profiles = {"default": Profile()}
51 for name in cls.__dict__:
52 attribute = getattr(cls, name)
53
54 _logger.debug(name)
55 if isinstance(attribute, property):
56 _logger.debug("prop")
57 data_holder = attribute.fget
58 elif isinstance(attribute, UnboundMethodType):
59 _logger.debug("unbound method!")
60 data_holder = attribute.im_func
61 else:
62 _logger.debug("I have no clue what this is")
63 data_holder = attribute
64
65 if hasattr(data_holder, "__pytilities_delegation_profiles"):
66 _logger.debug("is delegated!")
67 profile_data = data_holder.__pytilities_delegation_profiles
68 for profile_name, modifiers in profile_data.iteritems():
69 profiles.setdefault(profile_name, Profile())
70 profiles[profile_name].add_mappings(modifiers, name)
71
72 del data_holder.__pytilities_delegation_profiles
73
74
75 factory = DelegatorFactory()
76
77 for name, profile in profiles.iteritems():
78 factory.set_profile(name, profile)
79
80
81 setattr(cls, "_delegator_factory", factory)
82 cls.Delegator = factory.Delegator
83
84 return cls
85
86 return _delegator_factory
87
88 -def delegated(profile_name="default", modifiers="rwd"):
89 """
90 Includes the decorated attribute in the specified delegation profile.
91
92 Parameters:
93
94 `profile_name` :: string
95 name of the `Profile` to add the attribute to
96
97 `modifiers` :: string
98 the types of access to delegate to the target. Possible modifiers
99 are combinations of:
100
101 - `r`: read
102 - `w`: write
103 - `d`: delete
104 """
105
106 def _delegate(attribute):
107 _logger.debug("%s += %s" % (profile_name, attribute))
108 if not hasattr(attribute, "__pytilities_delegator_profiles"):
109 if isinstance(attribute, property):
110
111
112 data_holder = attribute.fget
113 else:
114 data_holder = attribute
115
116 data_holder.__pytilities_delegation_profiles = {}
117
118 data_holder.__pytilities_delegation_profiles[profile_name] = modifiers
119
120 return attribute
121
122 return _delegate
123