[schema] extend .rdef(...) with a parameter to silence the ambiguity warning

Sometimes clients of .rdef really do not care about the target types. We keep this feature but the client has to make it explicit, else he will get the warning.

Follows #109207

authorAurelien Campeas <aurelien.campeas@logilab.fr>
changeset7cf7c70a3bab
branchdefault
phasedraft
hiddenyes
parent revision#99d6f01f853d [schema] add a warning to avoid a potential silent bug (follows #109207)
child revision#8e337a6ec877 Remove dead and deprecated code (closes #149361)
files modified by this revision
schema.py
# HG changeset patch
# User Aurelien Campeas <aurelien.campeas@logilab.fr>
# Date 1372260841 -7200
# Wed Jun 26 17:34:01 2013 +0200
# Node ID 7cf7c70a3babb35eeb426095240091de9c7c0ed5
# Parent 99d6f01f853db229223d8df2a95ba17cf9201343
[schema] extend .rdef(...) with a parameter to silence the ambiguity warning

Sometimes clients of .rdef really do not care about the target types.
We keep this feature but the client has to make it explicit, else
he will get the warning.

Follows #109207

diff --git a/schema.py b/schema.py
@@ -193,11 +193,11 @@
1      def check_unique_together(self):
2          errors = []
3          for unique_together in self._unique_together:
4              for name in unique_together:
5                  try:
6 -                    rschema = self.rdef(name)
7 +                    rschema = self.rdef(name, takefirst=True)
8                  except KeyError:
9                      errors.append('no such attribute or relation %s' % name)
10                  else:
11                      if not (rschema.final or rschema.rtype.inlined):
12                          errors.append('%s is not an attribute or an inlined '
@@ -287,24 +287,24 @@
13          """return a list of relations that may have this type of entity as
14          object
15          """
16          return self.objrels.values()
17 
18 -    def rdef(self, rtype, role='subject', targettype=None):
19 +    def rdef(self, rtype, role='subject', targettype=None, takefirst=False):
20          """return a relation definition schema for a relation of this entity type
21 
22          Notice that when targettype is not specified and the relation may lead
23          to different entity types (ambiguous relation), one of them is picked
24 -        randomly.
25 +        randomly. If also takefirst is False, a warning will be emitted.
26          """
27          rschema = self.schema.rschema(rtype)
28          if targettype is None:
29              if role == 'subject':
30                  types = rschema.objects(self)
31              else:
32                  types = rschema.subjects(self)
33 -            if len(types) != 1:
34 +            if len(types) != 1 and not takefirst:
35                  warnings.warn('[yams 0.38] no targettype specified and there are several '
36                                'relation definitions for rtype %s: %s. Yet you get the first '
37                                'rdef.' % (rtype, [eschema.type for eschema in types]),
38                                Warning, stacklevel=2)
39              targettype = types[0]
@@ -380,11 +380,11 @@
40                      # XXX return a RelationDefinitionSchema
41                      yield rschema, value
42 
43      def default(self, rtype):
44          """return the default value of a subject relation"""
45 -        rdef = self.rdef(rtype)
46 +        rdef = self.rdef(rtype, takefirst=True)
47          default =  rdef.default
48          if callable(default):
49              default = default()
50          if default is MARKER:
51              default = None
@@ -499,20 +499,20 @@
52          return True if this entity type *must* be contained by another.
53          """
54          for rschema in self.object_relations():
55              if (rschema, 'object') in skiprels:
56                  continue
57 -            rdef = self.rdef(rschema, 'object')
58 +            rdef = self.rdef(rschema, 'object', takefirst=True)
59              if rdef.composite == 'subject':
60                  if not strict or rdef.cardinality[1] in '1+':
61                      return True
62          for rschema in self.subject_relations():
63              if (rschema, 'subject') in skiprels:
64                  continue
65              if rschema.final:
66                  continue
67 -            rdef = self.rdef(rschema, 'subject')
68 +            rdef = self.rdef(rschema, 'subject', takefirst=True)
69              if rdef.composite == 'object':
70                  if not strict or rdef.cardinality[0] in '1+':
71                      return True
72          return False
73