# HG changeset patch
# User Denis Laxalde <denis.laxalde@logilab.fr>
# Date 1437046204 -7200
#      Thu Jul 16 13:30:04 2015 +0200
# Node ID 2837d702d15dff73854a52bca4ff89460b0c24b0
# Parent  338c932c8562e8d0c5d6178c6faf275d3c10ab8b
Improve relation definitions walk algorithm in CompositeGraph.iter_schema()

Properly walk through relation definitions accounting for parent role and
entity type in iter_schema. Better use Yams API in passing.

diff --git a/entities.py b/entities.py
--- a/entities.py
+++ b/entities.py
@@ -70,7 +70,7 @@
     def iter_schema(self, parent, topdown=True):
         """Yield `(rtype, role), children` values corresponding to arcs of the
         graph of compositely-related entity types reachable from an `parent`
-        entity type. `children` is a set of possible entity types reachable
+        entity type. `children` is a list of possible entity types reachable
         through `(rtype, role)` relation.
 
         By default, the schema is walked from the container level to the
@@ -80,20 +80,20 @@
             eschema = self.schema[parent]
         except KeyError:
             return
-        for rschema, _, role in eschema.relation_definitions():
+        for rschema, teschemas, role in eschema.relation_definitions():
             if rschema.meta or rschema in self.skiprtypes:
                 continue
-            target_role = neg_role(role)
             composite_role = role if topdown else neg_role(role)
-            relation, children = (rschema.type, role), set()
-            for rdef in rschema.rdefs.itervalues():
+            relation, children = (rschema.type, role), []
+            for target in teschemas:
+                if target in self.skipetypes:
+                    continue
+                rdef = rschema.role_rdef(eschema, target, role)
                 if rdef.composite != composite_role:
                     continue
-                child = getattr(rdef, target_role).type
-                if child in self.skipetypes:
-                    continue
-                children.add(child)
-            yield relation, children
+                children.append(target.type)
+            if children:
+                yield relation, children
 
     def structure(self, parent, **kwargs):
         """Return a nested-dict structure obtained from walking the graph of
@@ -112,12 +112,11 @@
         An "arc" is a tuple `(child entity, (rtype, role), parent entity)`.
         """
         for (rtype, role), children in self.iter_schema(parent.cw_etype):
-            for child_etype in children:
-                rset = parent.related(rtype, role=role, targettypes=[child_etype])
-                for child in rset.entities():
-                    yield child, (rtype, neg_role(role)), parent
-                    for x in self.iter_entities(child):
-                        yield x
+            rset = parent.related(rtype, role=role, targettypes=children)
+            for child in rset.entities():
+                yield child, (rtype, neg_role(role)), parent
+                for x in self.iter_entities(child):
+                    yield x
 
 
 def copy_entity(original, **attributes):