13 |
30 |
14 RTAGS = [] |
31 RTAGS = [] |
15 def register_rtag(rtag): |
32 def register_rtag(rtag): |
16 RTAGS.append(rtag) |
33 RTAGS.append(rtag) |
17 |
34 |
|
35 def _ensure_str_key(key): |
|
36 return tuple(str(k) for k in key) |
|
37 |
18 class RelationTags(object): |
38 class RelationTags(object): |
19 """a tag store for full relation definitions : |
39 """a tag store for full relation definitions : |
20 |
40 |
21 (subject type, relation type, object type, tagged) |
41 (subject type, relation type, object type, tagged) |
22 |
42 |
23 allowing to set tags using wildcard (eg '*') as subject type / object type |
43 allowing to set tags using wildcard (eg '*') as subject type / object type |
24 |
44 |
25 This class associates a single tag to each key. |
45 This class associates a single tag to each key. |
26 """ |
46 """ |
27 _allowed_values = None |
47 _allowed_values = None |
|
48 _initfunc = None |
28 def __init__(self, name=None, initfunc=None, allowed_values=None): |
49 def __init__(self, name=None, initfunc=None, allowed_values=None): |
29 self._name = name or '<unknown>' |
50 self._name = name or '<unknown>' |
30 self._tagdefs = {} |
51 self._tagdefs = {} |
31 if allowed_values is not None: |
52 if allowed_values is not None: |
32 self._allowed_values = allowed_values |
53 self._allowed_values = allowed_values |
33 self._initfunc = initfunc |
54 if initfunc is not None: |
|
55 self._initfunc = initfunc |
34 register_rtag(self) |
56 register_rtag(self) |
35 |
57 |
36 def __repr__(self): |
58 def __repr__(self): |
37 return '%s: %s' % (self._name, repr(self._tagdefs)) |
59 return '%s: %s' % (self._name, repr(self._tagdefs)) |
38 |
60 |
43 |
65 |
44 def clear(self): |
66 def clear(self): |
45 self._tagdefs.clear() |
67 self._tagdefs.clear() |
46 |
68 |
47 def _get_keys(self, stype, rtype, otype, tagged): |
69 def _get_keys(self, stype, rtype, otype, tagged): |
48 keys = [(rtype, tagged, '*', '*'), |
70 keys = [('*', rtype, '*', tagged), |
49 (rtype, tagged, '*', otype), |
71 ('*', rtype, otype, tagged), |
50 (rtype, tagged, stype, '*'), |
72 (stype, rtype, '*', tagged), |
51 (rtype, tagged, stype, otype)] |
73 (stype, rtype, otype, tagged)] |
52 if stype == '*' or otype == '*': |
74 if stype == '*' or otype == '*': |
53 keys.remove((rtype, tagged, '*', '*')) |
75 keys.remove( ('*', rtype, '*', tagged) ) |
54 if stype == '*': |
76 if stype == '*': |
55 keys.remove((rtype, tagged, '*', otype)) |
77 keys.remove( ('*', rtype, otype, tagged) ) |
56 if otype == '*': |
78 if otype == '*': |
57 keys.remove((rtype, tagged, stype, '*')) |
79 keys.remove( (stype, rtype, '*', tagged) ) |
58 return keys |
80 return keys |
59 |
81 |
60 def init(self, schema, check=True): |
82 def init(self, schema, check=True): |
61 # XXX check existing keys against schema |
83 # XXX check existing keys against schema |
62 if check: |
84 if check: |
63 for (rtype, tagged, stype, otype), value in self._tagdefs.items(): |
85 for (stype, rtype, otype, tagged), value in self._tagdefs.items(): |
64 for ertype in (stype, rtype, otype): |
86 for ertype in (stype, rtype, otype): |
65 if ertype != '*' and not ertype in schema: |
87 if ertype != '*' and not ertype in schema: |
66 self.warning('removing rtag %s: %s, %s undefined in schema', |
88 self.warning('removing rtag %s: %s, %s undefined in schema', |
67 (stype, rtype, otype, tagged), value, ertype) |
89 (stype, rtype, otype, tagged), value, ertype) |
68 self.del_rtag(stype, rtype, otype, tagged) |
90 self.del_rtag(stype, rtype, otype, tagged) |
69 break |
91 break |
70 if self._initfunc is not None: |
92 if self._initfunc is not None: |
71 for eschema in schema.entities(): |
93 self.apply(schema, self._initfunc) |
72 for rschema, tschemas, role in eschema.relation_definitions(True): |
94 |
73 for tschema in tschemas: |
95 def apply(self, schema, func): |
74 if role == 'subject': |
96 for eschema in schema.entities(): |
75 sschema, oschema = eschema, tschema |
97 for rschema, tschemas, role in eschema.relation_definitions(True): |
76 else: |
98 for tschema in tschemas: |
77 sschema, oschema = tschema, eschema |
99 if role == 'subject': |
78 self._initfunc(self, sschema, rschema, oschema, role) |
100 sschema, oschema = eschema, tschema |
|
101 else: |
|
102 sschema, oschema = tschema, eschema |
|
103 func(self, sschema, rschema, oschema, role) |
79 |
104 |
80 # rtag declaration api #################################################### |
105 # rtag declaration api #################################################### |
81 |
106 |
82 def tag_attribute(self, key, tag): |
107 def tag_attribute(self, key, *args, **kwargs): |
83 key = list(key) |
108 key = list(key) |
84 key.append('*') |
109 key.append('*') |
85 self.tag_subject_of(key, tag) |
110 key.append('subject') |
86 |
111 self.tag_relation(key, *args, **kwargs) |
87 def tag_subject_of(self, key, tag): |
112 |
|
113 def tag_subject_of(self, key, *args, **kwargs): |
88 key = list(key) |
114 key = list(key) |
89 key.append('subject') |
115 key.append('subject') |
90 self.tag_relation(key, tag) |
116 self.tag_relation(key, *args, **kwargs) |
91 |
117 |
92 def tag_object_of(self, key, tag): |
118 def tag_object_of(self, key, *args, **kwargs): |
93 key = list(key) |
119 key = list(key) |
94 key.append('object') |
120 key.append('object') |
95 self.tag_relation(key, tag) |
121 self.tag_relation(key, *args, **kwargs) |
96 |
122 |
97 def tag_relation(self, key, tag): |
123 def tag_relation(self, key, tag): |
98 #if isinstance(key, basestring): |
124 assert len(key) == 4, 'bad key: %s' % list(key) |
99 # stype, rtype, otype = key.split() |
|
100 #else: |
|
101 stype, rtype, otype, tagged = [str(k) for k in key] |
|
102 if self._allowed_values is not None: |
125 if self._allowed_values is not None: |
103 assert tag in self._allowed_values, \ |
126 assert tag in self._allowed_values, \ |
104 '%r is not an allowed tag (should be in %s)' % ( |
127 '%r is not an allowed tag (should be in %s)' % ( |
105 tag, self._allowed_values) |
128 tag, self._allowed_values) |
106 self._tagdefs[(rtype, tagged, stype, otype)] = tag |
129 self._tagdefs[_ensure_str_key(key)] = tag |
107 return tag |
130 return tag |
108 |
131 |
109 # rtag runtime api ######################################################## |
132 # rtag runtime api ######################################################## |
110 |
133 |
111 def del_rtag(self, stype, rtype, otype, tagged): |
134 def del_rtag(self, *key): |
112 del self._tagdefs[(rtype, tagged, stype, otype)] |
135 del self._tagdefs[key] |
113 |
136 |
114 def get(self, stype, rtype, otype, tagged): |
137 def get(self, *key): |
115 for key in reversed(self._get_keys(stype, rtype, otype, tagged)): |
138 for key in reversed(self._get_keys(*key)): |
116 try: |
139 try: |
117 return self._tagdefs[key] |
140 return self._tagdefs[key] |
118 except KeyError: |
141 except KeyError: |
119 continue |
142 continue |
120 return None |
143 return None |
151 class RelationTagsDict(RelationTagsSet): |
173 class RelationTagsDict(RelationTagsSet): |
152 """This class associates a set of tags to each key.""" |
174 """This class associates a set of tags to each key.""" |
153 tag_container_cls = dict |
175 tag_container_cls = dict |
154 |
176 |
155 def tag_relation(self, key, tag): |
177 def tag_relation(self, key, tag): |
156 stype, rtype, otype, tagged = [str(k) for k in key] |
178 key = _ensure_str_key(key) |
157 try: |
179 try: |
158 rtags = self._tagdefs[(rtype, tagged, stype, otype)] |
180 rtags = self._tagdefs[key] |
159 rtags.update(tag) |
181 rtags.update(tag) |
160 return rtags |
182 return rtags |
161 except KeyError: |
183 except KeyError: |
162 self._tagdefs[(rtype, tagged, stype, otype)] = tag |
184 self._tagdefs[key] = tag |
163 return tag |
185 return tag |
164 |
186 |
165 def setdefault(self, key, tagkey, tagvalue): |
187 def setdefault(self, key, tagkey, tagvalue): |
166 stype, rtype, otype, tagged = [str(k) for k in key] |
188 key = _ensure_str_key(key) |
167 try: |
189 try: |
168 rtags = self._tagdefs[(rtype, tagged, stype, otype)] |
190 rtags = self._tagdefs[key] |
169 rtags.setdefault(tagkey, tagvalue) |
191 rtags.setdefault(tagkey, tagvalue) |
170 return rtags |
192 return rtags |
171 except KeyError: |
193 except KeyError: |
172 self._tagdefs[(rtype, tagged, stype, otype)] = {tagkey: tagvalue} |
194 self._tagdefs[key] = {tagkey: tagvalue} |
173 return self._tagdefs[(rtype, tagged, stype, otype)] |
195 return self._tagdefs[key] |
174 |
196 |
175 |
197 |
176 class RelationTagsBool(RelationTags): |
198 class RelationTagsBool(RelationTags): |
177 _allowed_values = frozenset((True, False)) |
199 _allowed_values = frozenset((True, False)) |
178 |
200 |