--- a/rtags.py Fri Feb 12 15:18:00 2010 +0100
+++ b/rtags.py Wed Mar 24 10:23:31 2010 +0100
@@ -1,9 +1,26 @@
-"""relation tags store
+#:organization: Logilab
+#:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
+#:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
+#:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
+
+"""
+A RelationTag object is an object which allows to link a configuration information to a relation definition. For instance, the standard primary view uses a RelationTag object (uicfg.primaryview_section) to get the section to display relations.
+
+.. sourcecode:: python
-:organization: Logilab
-:copyright: 2001-2010 LOGILAB S.A. (Paris, FRANCE), license is LGPL v2.
-:contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
-:license: GNU Lesser General Public License, v2.1 - http://www.gnu.org/licenses
+ # display ``entry_of`` relations in the ``relations`` section in the ``BlogEntry`` primary view
+ uicfg.primaryview_section.tag_subject_of(('BlogEntry', 'entry_of', '*'),
+ 'relations')
+
+ # hide every relation ``entry_of`` in the ``Blog`` primary view
+ uicfg.primaryview_section.tag_object_of(('*', 'entry_of', 'Blog'), 'hidden')
+
+Three primitives are defined:
+ * ``tag_subject_of`` tag a relation in the subject's context
+ * ``tag_object_of`` tag a relation in the object's context
+ * ``tag_attribute`` shortcut for tag_subject_of
+
+
"""
__docformat__ = "restructuredtext en"
@@ -15,6 +32,9 @@
def register_rtag(rtag):
RTAGS.append(rtag)
+def _ensure_str_key(key):
+ return tuple(str(k) for k in key)
+
class RelationTags(object):
"""a tag store for full relation definitions :
@@ -25,12 +45,14 @@
This class associates a single tag to each key.
"""
_allowed_values = None
+ _initfunc = None
def __init__(self, name=None, initfunc=None, allowed_values=None):
self._name = name or '<unknown>'
self._tagdefs = {}
if allowed_values is not None:
self._allowed_values = allowed_values
- self._initfunc = initfunc
+ if initfunc is not None:
+ self._initfunc = initfunc
register_rtag(self)
def __repr__(self):
@@ -45,22 +67,22 @@
self._tagdefs.clear()
def _get_keys(self, stype, rtype, otype, tagged):
- keys = [(rtype, tagged, '*', '*'),
- (rtype, tagged, '*', otype),
- (rtype, tagged, stype, '*'),
- (rtype, tagged, stype, otype)]
+ keys = [('*', rtype, '*', tagged),
+ ('*', rtype, otype, tagged),
+ (stype, rtype, '*', tagged),
+ (stype, rtype, otype, tagged)]
if stype == '*' or otype == '*':
- keys.remove((rtype, tagged, '*', '*'))
+ keys.remove( ('*', rtype, '*', tagged) )
if stype == '*':
- keys.remove((rtype, tagged, '*', otype))
+ keys.remove( ('*', rtype, otype, tagged) )
if otype == '*':
- keys.remove((rtype, tagged, stype, '*'))
+ keys.remove( (stype, rtype, '*', tagged) )
return keys
def init(self, schema, check=True):
# XXX check existing keys against schema
if check:
- for (rtype, tagged, stype, otype), value in self._tagdefs.items():
+ for (stype, rtype, otype, tagged), value in self._tagdefs.items():
for ertype in (stype, rtype, otype):
if ertype != '*' and not ertype in schema:
self.warning('removing rtag %s: %s, %s undefined in schema',
@@ -68,51 +90,52 @@
self.del_rtag(stype, rtype, otype, tagged)
break
if self._initfunc is not None:
- for eschema in schema.entities():
- for rschema, tschemas, role in eschema.relation_definitions(True):
- for tschema in tschemas:
- if role == 'subject':
- sschema, oschema = eschema, tschema
- else:
- sschema, oschema = tschema, eschema
- self._initfunc(self, sschema, rschema, oschema, role)
+ self.apply(schema, self._initfunc)
+
+ def apply(self, schema, func):
+ for eschema in schema.entities():
+ for rschema, tschemas, role in eschema.relation_definitions(True):
+ for tschema in tschemas:
+ if role == 'subject':
+ sschema, oschema = eschema, tschema
+ else:
+ sschema, oschema = tschema, eschema
+ func(self, sschema, rschema, oschema, role)
# rtag declaration api ####################################################
- def tag_attribute(self, key, tag):
+ def tag_attribute(self, key, *args, **kwargs):
key = list(key)
key.append('*')
- self.tag_subject_of(key, tag)
+ key.append('subject')
+ self.tag_relation(key, *args, **kwargs)
- def tag_subject_of(self, key, tag):
+ def tag_subject_of(self, key, *args, **kwargs):
key = list(key)
key.append('subject')
- self.tag_relation(key, tag)
+ self.tag_relation(key, *args, **kwargs)
- def tag_object_of(self, key, tag):
+ def tag_object_of(self, key, *args, **kwargs):
key = list(key)
key.append('object')
- self.tag_relation(key, tag)
+ self.tag_relation(key, *args, **kwargs)
def tag_relation(self, key, tag):
- #if isinstance(key, basestring):
- # stype, rtype, otype = key.split()
- #else:
- stype, rtype, otype, tagged = [str(k) for k in key]
+ assert len(key) == 4, 'bad key: %s' % list(key)
if self._allowed_values is not None:
assert tag in self._allowed_values, \
'%r is not an allowed tag (should be in %s)' % (
tag, self._allowed_values)
- self._tagdefs[(rtype, tagged, stype, otype)] = tag
+ self._tagdefs[_ensure_str_key(key)] = tag
return tag
# rtag runtime api ########################################################
- def del_rtag(self, stype, rtype, otype, tagged):
- del self._tagdefs[(rtype, tagged, stype, otype)]
+ def del_rtag(self, *key):
+ del self._tagdefs[key]
- def get(self, stype, rtype, otype, tagged):
- for key in reversed(self._get_keys(stype, rtype, otype, tagged)):
+ def get(self, *key):
+ for key in reversed(self._get_keys(*key)):
try:
return self._tagdefs[key]
except KeyError:
@@ -132,8 +155,7 @@
tag_container_cls = set
def tag_relation(self, key, tag):
- stype, rtype, otype, tagged = [str(k) for k in key]
- rtags = self._tagdefs.setdefault((rtype, tagged, stype, otype),
+ rtags = self._tagdefs.setdefault(_ensure_str_key(key),
self.tag_container_cls())
rtags.add(tag)
return rtags
@@ -153,24 +175,24 @@
tag_container_cls = dict
def tag_relation(self, key, tag):
- stype, rtype, otype, tagged = [str(k) for k in key]
+ key = _ensure_str_key(key)
try:
- rtags = self._tagdefs[(rtype, tagged, stype, otype)]
+ rtags = self._tagdefs[key]
rtags.update(tag)
return rtags
except KeyError:
- self._tagdefs[(rtype, tagged, stype, otype)] = tag
+ self._tagdefs[key] = tag
return tag
def setdefault(self, key, tagkey, tagvalue):
- stype, rtype, otype, tagged = [str(k) for k in key]
+ key = _ensure_str_key(key)
try:
- rtags = self._tagdefs[(rtype, tagged, stype, otype)]
+ rtags = self._tagdefs[key]
rtags.setdefault(tagkey, tagvalue)
return rtags
except KeyError:
- self._tagdefs[(rtype, tagged, stype, otype)] = {tagkey: tagvalue}
- return self._tagdefs[(rtype, tagged, stype, otype)]
+ self._tagdefs[key] = {tagkey: tagvalue}
+ return self._tagdefs[key]
class RelationTagsBool(RelationTags):