# HG changeset patch # User Denis Laxalde <denis.laxalde@logilab.fr> # Date 1436948456 -7200 # Wed Jul 15 10:20:56 2015 +0200 # Node ID 40286ee315f324847a6c3edbbccdc2ccf58b76c0 # Parent a13d9ae45c5f409e81ebbe5310ceea8c2e2ed925 Allow to walk the schema from bottom-up diff --git a/entities.py b/entities.py --- a/entities.py +++ b/entities.py @@ -67,11 +67,14 @@ self.skiprtypes = skiprtypes self.skipetypes = skipetypes - def iter_schema(self, parent): + 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 through `(rtype, role)` relation. + + By default, the schema is walked from the container level to the + content level. To walk from the bottom level, set `topdown=False`. """ try: eschema = self.schema[parent] @@ -81,9 +84,10 @@ 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(): - if rdef.composite != role: + if rdef.composite != composite_role: continue child = getattr(rdef, target_role).type if child in self.skipetypes: @@ -91,14 +95,14 @@ children.add(child) yield relation, children - def structure(self, parent): + def structure(self, parent, **kwargs): """Return a nested-dict structure obtained from walking the graph of schema objects from any `parent` entity type in the graph. """ graph = {} - for relation, children in self.iter_schema(parent): + for relation, children in self.iter_schema(parent, **kwargs): for child in sorted(children): - graph.setdefault(relation, {})[child] = self.structure(child) + graph.setdefault(relation, {})[child] = self.structure(child, **kwargs) return graph def iter_entities(self, parent): diff --git a/test/test_compound.py b/test/test_compound.py --- a/test/test_compound.py +++ b/test/test_compound.py @@ -59,6 +59,24 @@ } self.assertEqual(structure, expected) + def test_iter_schema_downup(self): + graph = CompositeGraph(self.schema) + structure = graph.structure('Anecdote', topdown=False) + self.assertEqual(structure, { + ('event', 'object'): {'Biography': { + ('biography', 'object'): {'Agent': {}}, + }}, + ('narrated_by', 'subject'): {'Agent': {}}, + }) + structure = graph.structure('Event', topdown=False) + self.assertEqual(structure, { + ('event', 'object'): { + 'Biography': {('biography', 'object'): {'Agent': {}}} + } + }) + structure = graph.structure('OnlineAccount', topdown=False) + self.assertEqual(structure, {('account', 'object'): {'Agent': {}}}) + def test_iter_entities_singleton(self): graph = CompositeGraph(self.schema) with self.admin_access.repo_cnx() as cnx: