14 |
14 |
15 allowing to set tags using wildcard (eg '*') as subject type / object type |
15 allowing to set tags using wildcard (eg '*') as subject type / object type |
16 |
16 |
17 This class associates a single tag to each key. |
17 This class associates a single tag to each key. |
18 """ |
18 """ |
19 |
19 _allowed_values = None |
20 def __init__(self): |
20 def __init__(self, initfunc=None, allowed_values=None): |
21 self._tagdefs = {} |
21 self._tagdefs = {} |
|
22 if allowed_values is not None: |
|
23 self._allowed_values = allowed_values |
|
24 self._initfunc = initfunc |
22 |
25 |
23 def __repr__(self): |
26 def __repr__(self): |
24 return repr(self._tagdefs) |
27 return repr(self._tagdefs) |
25 |
28 |
26 # dict compat |
29 # dict compat |
27 def __getitem__(self, key): |
30 def __getitem__(self, key): |
28 return self.get(*key) |
31 return self.get(*key) |
29 __contains__ = __getitem__ |
32 __contains__ = __getitem__ |
30 |
33 |
31 def _get_tagged(self, stype, otype, tagged=None): |
34 def _get_keys(self, stype, rtype, otype, tagged): |
32 stype, otype = str(stype), str(otype) |
|
33 if tagged is None: |
|
34 if stype[0] == '!': |
|
35 tagged = 'subject' |
|
36 stype = stype[1:] |
|
37 elif otype[0] == '!': |
|
38 tagged = 'object' |
|
39 otype = otype[1:] |
|
40 else: |
|
41 raise AssertionError('either stype or rtype should have the ' |
|
42 'role mark ("!")') |
|
43 else: |
|
44 assert tagged in ('subject', 'object'), repr(tagged) |
|
45 return stype, otype, tagged |
|
46 |
|
47 def _get_keys(self, stype, rtype, otype, tagged=None): |
|
48 stype, otype, tagged = self._get_tagged(stype, otype, tagged) |
|
49 keys = [(rtype, tagged, '*', '*'), |
35 keys = [(rtype, tagged, '*', '*'), |
50 (rtype, tagged, '*', otype), |
36 (rtype, tagged, '*', otype), |
51 (rtype, tagged, stype, '*'), |
37 (rtype, tagged, stype, '*'), |
52 (rtype, tagged, stype, otype)] |
38 (rtype, tagged, stype, otype)] |
53 if stype == '*' or otype == '*': |
39 if stype == '*' or otype == '*': |
56 keys.remove((rtype, tagged, '*', otype)) |
42 keys.remove((rtype, tagged, '*', otype)) |
57 if otype == '*': |
43 if otype == '*': |
58 keys.remove((rtype, tagged, stype, '*')) |
44 keys.remove((rtype, tagged, stype, '*')) |
59 return keys |
45 return keys |
60 |
46 |
61 def tag_relation(self, stype, rtype, otype, tag, tagged=None): |
47 def init(self, schema): |
62 stype, otype, tagged = self._get_tagged(stype, otype, tagged) |
48 # XXX check existing keys against schema |
63 self._tagdefs[(str(rtype), tagged, stype, otype)] = tag |
49 for rtype, tagged, stype, otype in self._tagdefs: |
|
50 assert rtype in schema |
|
51 if stype != '*': |
|
52 assert stype in schema |
|
53 if otype != '*': |
|
54 assert otype in schema |
|
55 if self._initfunc is not None: |
|
56 for eschema in schema.entities(): |
|
57 for rschema, tschemas, role in eschema.relation_definitions(True): |
|
58 for tschema in tschemas: |
|
59 if role == 'subject': |
|
60 stype, otype = eschema, tschema |
|
61 else: |
|
62 stype, otype = tschema, eschema |
|
63 self._initfunc(stype, rtype, otype, role) |
64 |
64 |
65 def tag_attribute(self, stype, attr, tag): |
65 # rtag declaration api #################################################### |
66 self.tag_relation(stype, attr, '*', tag, 'subject') |
|
67 |
66 |
68 def del_rtag(self, stype, rtype, otype): |
67 def tag_attribute(self, key, tag): |
69 stype, otype, tagged = self._get_tagged(stype, otype) |
68 key = list(key) |
70 del self._tagdefs[(str(rtype), tagged, stype, otype)] |
69 key.append('*') |
|
70 self.tag_subject_of(key, tag) |
71 |
71 |
72 def get(self, stype, rtype, otype, tagged=None): |
72 def tag_subject_of(self, key, tag): |
|
73 key = list(key) |
|
74 key.append('subject') |
|
75 self.tag_relation(key, tag) |
|
76 |
|
77 def tag_object_of(self, key, tag): |
|
78 key = list(key) |
|
79 key.append('object') |
|
80 self.tag_relation(key, tag) |
|
81 |
|
82 def tag_relation(self, key, tag): |
|
83 #if isinstance(key, basestring): |
|
84 # stype, rtype, otype = key.split() |
|
85 #else: |
|
86 stype, rtype, otype, tagged = [str(k) for k in key] |
|
87 if self._allowed_values is not None: |
|
88 assert tag in self._allowed_values |
|
89 self._tagdefs[(rtype, tagged, stype, otype)] = tag |
|
90 |
|
91 # rtag runtime api ######################################################## |
|
92 |
|
93 def del_rtag(self, stype, rtype, otype, tagged): |
|
94 del self._tagdefs[(rtype, tagged, stype, otype)] |
|
95 |
|
96 def get(self, stype, rtype, otype, tagged): |
73 for key in reversed(self._get_keys(stype, rtype, otype, tagged)): |
97 for key in reversed(self._get_keys(stype, rtype, otype, tagged)): |
74 try: |
98 try: |
75 return self._tagdefs[key] |
99 return self._tagdefs[key] |
76 except KeyError: |
100 except KeyError: |
77 continue |
101 continue |
85 |
109 |
86 |
110 |
87 class RelationTagsSet(RelationTags): |
111 class RelationTagsSet(RelationTags): |
88 """This class associates a set of tags to each key.""" |
112 """This class associates a set of tags to each key.""" |
89 |
113 |
90 def tag_relation(self, stype, rtype, otype, tag, tagged=None): |
114 def tag_relation(self, key, tag): |
91 stype, otype, tagged = self._get_tagged(stype, otype, tagged) |
115 stype, rtype, otype, tagged = [str(k) for k in key] |
92 rtags = self._tagdefs.setdefault((rtype, tagged, stype, otype), set()) |
116 rtags = self._tagdefs.setdefault((rtype, tagged, stype, otype), set()) |
93 rtags.add(tag) |
117 rtags.add(tag) |
94 |
118 |
95 def get(self, stype, rtype, otype, tagged=None): |
119 def get(self, stype, rtype, otype, tagged): |
96 rtags = set() |
120 rtags = set() |
97 for key in self._get_keys(stype, rtype, otype, tagged): |
121 for key in self._get_keys(stype, rtype, otype, tagged): |
98 try: |
122 try: |
99 rtags.update(self._tagdefs[key]) |
123 rtags.update(self._tagdefs[key]) |
100 except KeyError: |
124 except KeyError: |
101 continue |
125 continue |
102 return rtags |
126 return rtags |
|
127 |
|
128 |
|
129 class RelationTagsBool(RelationTags): |
|
130 _allowed_values = frozenset((True, False)) |
|
131 |
|
132 def tag_subject_of(self, key, tag=True): |
|
133 super(RelationTagsBool, self).tag_subject_of(key, tag) |
|
134 |
|
135 def tag_object_of(self, key, tag=True): |
|
136 super(RelationTagsBool, self).tag_object_of(key, tag) |
|
137 |
|
138 def tag_attribute(self, key, tag=True): |
|
139 super(RelationTagsBool, self).tag_attribute(key, tag) |