author | sylvain.thenault@logilab.fr |
Tue, 12 May 2009 17:15:41 +0200 | |
branch | tls-sprint |
changeset 1747 | d48613e65196 |
parent 1744 | 056ed8fca8d3 |
child 1748 | aa1806e76699 |
permissions | -rw-r--r-- |
1152 | 1 |
"""relation tags store |
2 |
||
3 |
:organization: Logilab |
|
4 |
:copyright: 2001-2009 LOGILAB S.A. (Paris, FRANCE), all rights reserved. |
|
5 |
:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr |
|
6 |
""" |
|
7 |
__docformat__ = "restructuredtext en" |
|
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
8 |
|
1740
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
9 |
import logging |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
10 |
|
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
11 |
from logilab.common.logging_ext import set_log_methods |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
12 |
|
1533 | 13 |
|
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
14 |
class RelationTags(object): |
1533 | 15 |
"""a tag store for full relation definitions : |
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
16 |
|
1533 | 17 |
(subject type, relation type, object type, tagged) |
1152 | 18 |
|
19 |
allowing to set tags using wildcard (eg '*') as subject type / object type |
|
20 |
||
1533 | 21 |
This class associates a single tag to each key. |
1152 | 22 |
""" |
1739 | 23 |
_allowed_values = None |
24 |
def __init__(self, initfunc=None, allowed_values=None): |
|
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
25 |
self._tagdefs = {} |
1739 | 26 |
if allowed_values is not None: |
27 |
self._allowed_values = allowed_values |
|
28 |
self._initfunc = initfunc |
|
1451 | 29 |
|
1528
864ae7c15ef5
other fixlets
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1451
diff
changeset
|
30 |
def __repr__(self): |
864ae7c15ef5
other fixlets
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1451
diff
changeset
|
31 |
return repr(self._tagdefs) |
864ae7c15ef5
other fixlets
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1451
diff
changeset
|
32 |
|
1533 | 33 |
# dict compat |
34 |
def __getitem__(self, key): |
|
35 |
return self.get(*key) |
|
36 |
__contains__ = __getitem__ |
|
1451 | 37 |
|
1739 | 38 |
def _get_keys(self, stype, rtype, otype, tagged): |
1533 | 39 |
keys = [(rtype, tagged, '*', '*'), |
40 |
(rtype, tagged, '*', otype), |
|
41 |
(rtype, tagged, stype, '*'), |
|
42 |
(rtype, tagged, stype, otype)] |
|
43 |
if stype == '*' or otype == '*': |
|
44 |
keys.remove((rtype, tagged, '*', '*')) |
|
45 |
if stype == '*': |
|
46 |
keys.remove((rtype, tagged, '*', otype)) |
|
47 |
if otype == '*': |
|
48 |
keys.remove((rtype, tagged, stype, '*')) |
|
49 |
return keys |
|
1451 | 50 |
|
1739 | 51 |
def init(self, schema): |
52 |
# XXX check existing keys against schema |
|
1740
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
53 |
for rtype, tagged, stype, otype in self._tagdefs.keys(): |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
54 |
for ertype in (stype, rtype, otype): |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
55 |
if ertype != '*' and not ertype in schema: |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
56 |
self.warning('removing rtag for %s, undefined in schema', |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
57 |
ertype) |
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
58 |
self.del_rtag(stype, rtype, otype, tagged) |
1739 | 59 |
if self._initfunc is not None: |
60 |
for eschema in schema.entities(): |
|
61 |
for rschema, tschemas, role in eschema.relation_definitions(True): |
|
62 |
for tschema in tschemas: |
|
63 |
if role == 'subject': |
|
1744 | 64 |
sschema, oschema = eschema, tschema |
1739 | 65 |
else: |
1744 | 66 |
sschema, oschema = tschema, eschema |
67 |
self._initfunc(self, sschema, rschema, oschema, role) |
|
1739 | 68 |
|
69 |
# rtag declaration api #################################################### |
|
70 |
||
71 |
def tag_attribute(self, key, tag): |
|
72 |
key = list(key) |
|
73 |
key.append('*') |
|
74 |
self.tag_subject_of(key, tag) |
|
1548
bd225e776739
new tag_attribute convenience method
sylvain.thenault@logilab.fr
parents:
1533
diff
changeset
|
75 |
|
1739 | 76 |
def tag_subject_of(self, key, tag): |
77 |
key = list(key) |
|
78 |
key.append('subject') |
|
79 |
self.tag_relation(key, tag) |
|
80 |
||
81 |
def tag_object_of(self, key, tag): |
|
82 |
key = list(key) |
|
83 |
key.append('object') |
|
84 |
self.tag_relation(key, tag) |
|
1533 | 85 |
|
1739 | 86 |
def tag_relation(self, key, tag): |
87 |
#if isinstance(key, basestring): |
|
88 |
# stype, rtype, otype = key.split() |
|
89 |
#else: |
|
90 |
stype, rtype, otype, tagged = [str(k) for k in key] |
|
91 |
if self._allowed_values is not None: |
|
1742
25a765e756c4
fix self on initfunc
Aurelien Campeas <aurelien.campeas@logilab.fr>
parents:
1740
diff
changeset
|
92 |
assert tag in self._allowed_values, '%r is not an allowed tag' % tag |
1739 | 93 |
self._tagdefs[(rtype, tagged, stype, otype)] = tag |
1533 | 94 |
|
1739 | 95 |
# rtag runtime api ######################################################## |
96 |
||
97 |
def del_rtag(self, stype, rtype, otype, tagged): |
|
98 |
del self._tagdefs[(rtype, tagged, stype, otype)] |
|
99 |
||
100 |
def get(self, stype, rtype, otype, tagged): |
|
1721
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
101 |
for key in reversed(self._get_keys(stype, rtype, otype, tagged)): |
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
102 |
try: |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
103 |
return self._tagdefs[key] |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
104 |
except KeyError: |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
105 |
continue |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
106 |
return None |
1451 | 107 |
|
1721
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
108 |
def etype_get(self, etype, rtype, role, ttype='*'): |
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
109 |
if role == 'subject': |
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
110 |
return self.get(etype, rtype, ttype, role) |
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
111 |
return self.get(ttype, rtype, etype, role) |
1533 | 112 |
|
113 |
||
1451 | 114 |
|
1533 | 115 |
class RelationTagsSet(RelationTags): |
116 |
"""This class associates a set of tags to each key.""" |
|
117 |
||
1739 | 118 |
def tag_relation(self, key, tag): |
119 |
stype, rtype, otype, tagged = [str(k) for k in key] |
|
1533 | 120 |
rtags = self._tagdefs.setdefault((rtype, tagged, stype, otype), set()) |
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
121 |
rtags.add(tag) |
1451 | 122 |
|
1739 | 123 |
def get(self, stype, rtype, otype, tagged): |
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
124 |
rtags = set() |
1721
694f6a50e138
final rtags api (eventually :$)
sylvain.thenault@logilab.fr
parents:
1548
diff
changeset
|
125 |
for key in self._get_keys(stype, rtype, otype, tagged): |
1148
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
126 |
try: |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
127 |
rtags.update(self._tagdefs[key]) |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
128 |
except KeyError: |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
129 |
continue |
55a8238f8f7c
keep notion of relation tags, tough with simplier implementation and usage
sylvain.thenault@logilab.fr
parents:
diff
changeset
|
130 |
return rtags |
1739 | 131 |
|
132 |
||
133 |
class RelationTagsBool(RelationTags): |
|
134 |
_allowed_values = frozenset((True, False)) |
|
135 |
||
136 |
||
1740
2292ae32c98f
warn and drop rtags not in schema, this may be intentional; drop possibility to not specify value for bool rtags
sylvain.thenault@logilab.fr
parents:
1739
diff
changeset
|
137 |
set_log_methods(RelationTags, logging.getLogger('cubicweb.rtags')) |