rtags.py
branchtls-sprint
changeset 1739 78b0819162a8
parent 1726 08918409815e
child 1740 2292ae32c98f
equal deleted inserted replaced
1738:2cfd50c8a415 1739:78b0819162a8
    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)