diff --git a/entities.py b/entities.py index c9088752d968cc6daed76360e629e4cb885c7edd_ZW50aXRpZXMucHk=..12bde733d7b204c2c8384bb97883ed55e5cb3eec_ZW50aXRpZXMucHk= 100644 --- a/entities.py +++ b/entities.py @@ -112,7 +112,6 @@ if children: yield relation, children - def parent_structure(self, etype): - """Return the parent structure of the graph from `etype`.""" - return self._structure(etype, False) + def parent_structure(self, etype, _visited=None): + """Return the parent structure of the graph from `etype`. @@ -118,5 +117,9 @@ - def child_structure(self, etype): - """Return the child structure of the graph from `etype`.""" - return self._structure(etype, True) + The structure is a dictionary mapping entity type in the graph with + root `etype` to relation information allowing to walk the graph + upstream from this entity type. + """ + if _visited is None: + _visited = set() + structure = {} @@ -122,8 +125,6 @@ - def _structure(self, etype, topdown): - """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._composite_relations(etype, topdown): + def update_structure(left, relation, right): + structure.setdefault(left, {}).setdefault(relation, []).append(right) + + for (rtype, role), children in self.child_relations(etype): for child in sorted(children): @@ -129,7 +130,13 @@ for child in sorted(children): - graph.setdefault(relation, {})[child] = self._structure( - child, topdown) - return graph + update_structure(child, (rtype, neg_role(role)), etype) + if child in _visited: + continue + _visited.add(child) + for left, rels in self.parent_structure(child, _visited).iteritems(): + for relation, rights in rels.iteritems(): + for right in rights: + update_structure(left, relation, right) + return structure def topdown_definition(self, parent): """Return the container definition of the composite graph from diff --git a/test/test_compound.py b/test/test_compound.py index c9088752d968cc6daed76360e629e4cb885c7edd_dGVzdC90ZXN0X2NvbXBvdW5kLnB5..12bde733d7b204c2c8384bb97883ed55e5cb3eec_dGVzdC90ZXN0X2NvbXBvdW5kLnB5 100644 --- a/test/test_compound.py +++ b/test/test_compound.py @@ -55,5 +55,5 @@ [(('relates', 'object'), ['Anecdote']), (('event', 'object'), ['Biography'])]) - def test_parent_structure_singleton(self): + def test_parent_structure_agent(self): graph = CompositeGraph(self.schema) @@ -59,14 +59,3 @@ graph = CompositeGraph(self.schema) - structure = graph.parent_structure('OnlineAccount') - expected = {('account', 'object'): {'Agent': {}}} - self.assertEqual(structure, expected) - - def test_child_structure_singleton(self): - graph = CompositeGraph(self.schema) - structure = graph.child_structure('OnlineAccount') - self.assertEqual(structure, {}) - - def test_child_structure(self): - graph = CompositeGraph(self.schema) - structure = graph.child_structure('Agent') + structure = graph.parent_structure('Agent') expected = { @@ -72,4 +61,7 @@ expected = { - ('account', 'subject'): { - 'OnlineAccount': {} + 'OnlineAccount': { + ('account', 'object'): ['Agent'], + }, + 'Biography': { + ('biography', 'object'): ['Agent'], }, @@ -75,12 +67,5 @@ }, - ('biography', 'subject'): { - 'Biography': { - ('event', 'subject'): { - 'Event': {}, - 'Anecdote': { - ('relates', 'subject'): - {'Event': {}} - }, - }, - }, + 'Event': { + ('event', 'object'): ['Biography'], + ('relates', 'object'): ['Anecdote'], }, @@ -86,10 +71,8 @@ }, - ('narrated_by', 'object'): { - 'Anecdote': { - ('relates', 'subject'): - {'Event': {}} - }, + 'Anecdote': { + ('event', 'object'): ['Biography'], + ('narrated_by', 'subject'): ['Agent'], }, } self.assertEqual(structure, expected) @@ -92,6 +75,6 @@ }, } self.assertEqual(structure, expected) - def test_parent_structure(self): + def test_parent_structure_anecdote(self): graph = CompositeGraph(self.schema) @@ -97,2 +80,3 @@ graph = CompositeGraph(self.schema) + self.set_description('Anecdote') structure = graph.parent_structure('Anecdote') @@ -98,12 +82,5 @@ structure = graph.parent_structure('Anecdote') - self.assertEqual(structure, { - ('event', 'object'): {'Biography': { - ('biography', 'object'): {'Agent': {}}, - }}, - ('narrated_by', 'subject'): {'Agent': {}}, - }) - structure = graph.parent_structure('Event') - self.assertEqual(structure, { - ('event', 'object'): { - 'Biography': {('biography', 'object'): {'Agent': {}}} + expected = { + 'Event': { + ('relates', 'object'): ['Anecdote'], }, @@ -109,13 +86,7 @@ }, - ('relates', 'object'): { - 'Anecdote': { - ('event', 'object'): { - 'Biography': { - ('biography', 'object'): {'Agent': {}}, - }, - }, - ('narrated_by', 'subject'): {'Agent': {}}, - }, - }, - }) + } + self.assertEqual(structure, expected) + + def test_parent_structure_leaf(self): + graph = CompositeGraph(self.schema) structure = graph.parent_structure('OnlineAccount') @@ -121,5 +92,5 @@ structure = graph.parent_structure('OnlineAccount') - self.assertEqual(structure, {('account', 'object'): {'Agent': {}}}) + self.assertEqual(structure, {}) def test_topdown_definition(self): graph = CompositeGraph(self.schema)