diff --git a/sbol3/document.py b/sbol3/document.py index 6e1fd31..07b6c9f 100644 --- a/sbol3/document.py +++ b/sbol3/document.py @@ -719,7 +719,9 @@ def migrate(self, top_levels: Iterable[TopLevel]) -> Any: @staticmethod def change_object_namespace(top_levels: Iterable[TopLevel], - new_namespace: str) -> Any: + new_namespace: str, + update_references: Iterable[TopLevel] = None + ) -> Any: """Change the namespace of all TopLevel objects in `top_levels` to new_namespace, regardless of the previous value, while maintaining referential integrity among all the top level @@ -734,6 +736,8 @@ def change_object_namespace(top_levels: Iterable[TopLevel], :param top_levels: objects to change :param new_namespace: new namespace for objects + :param update_references: objects that should have their references + updated without changing their namespace :return: Nothing """ # Validate the objects and build a map of old name to new name @@ -754,6 +758,12 @@ def change_object_namespace(top_levels: Iterable[TopLevel], top_level.namespace = new_namespace top_level.set_identity(new_identity) top_level.update_all_dependents(identity_map) + # Now update any TopLevels in the update_references group. These are + # objects that may have references to the objects that had their + # namespace changed. + if update_references is not None: + for top_level in update_references: + top_level.update_all_dependents(identity_map) return None def clone(self) -> List[TopLevel]: diff --git a/test/test_document.py b/test/test_document.py index c1c358f..36eccda 100644 --- a/test/test_document.py +++ b/test/test_document.py @@ -616,6 +616,22 @@ def test_change_object_namespace_errors(self): with self.assertRaises(ValueError): doc.change_object_namespace([i1], new_namespace) + def test_change_object_namespace_with_references(self): + """Test Document.change_object_namespace with outside references. + + See https://github.com/SynBioDex/pySBOL3/issues/412 + """ + doc = sbol3.Document() + comp = sbol3.Component('http://sbolstandard.org/testfiles/hello', + sbol3.SBO_DNA) + seq = sbol3.Sequence('http://sbolstandard.org/testfiles/hello_sequence', + elements='ATGC') + doc.add(comp) + doc.add(seq) + comp.sequences = [seq] + doc.change_object_namespace([seq], 'http://parts.igem.org', doc) + self.assertEqual(seq.identity, comp.sequences[0]) + def test_clone(self): namespace = 'https://github.com/synbiodex/pysbol3' sbol3.set_namespace(namespace)