diff --git a/.gitignore b/.gitignore index 3adefd14..16ddcf6e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ __pycache__/ # test secrets test_secret* + +.idea/ +*.egg-info/ diff --git a/sbol_utilities/sbol3_sbol2_conversion.py b/sbol_utilities/sbol3_sbol2_conversion.py index 29ee4c33..0168490e 100644 --- a/sbol_utilities/sbol3_sbol2_conversion.py +++ b/sbol_utilities/sbol3_sbol2_conversion.py @@ -196,9 +196,14 @@ def visit_externally_defined(self, a: sbol3.ExternallyDefined): # Priority: 3 raise NotImplementedError('Conversion of ExternallyDefined from SBOL3 to SBOL2 not yet implemented') - def visit_implementation(self, a: sbol3.Implementation): + def visit_implementation(self, imp3: sbol3.Implementation): # Priority: 1 - raise NotImplementedError('Conversion of Implementation from SBOL3 to SBOL2 not yet implemented') + # Make the Implement object and add it to the document + imp2 = sbol2.Implementation(imp3.identity, version=self._sbol2_version(imp3)) + imp2.built = imp3.built + self.doc2.addImplementation(imp2) + # Map over all other TopLevel properties and extensions not covered by the constructor + self._convert_toplevel(imp3, imp2) def visit_interaction(self, a: sbol3.Interaction): # Priority: 2 @@ -462,9 +467,13 @@ def visit_generic_location(self, a: sbol2.GenericLocation): # Priority: 3 raise NotImplementedError('Conversion of GenericLocation from SBOL2 to SBOL3 not yet implemented') - def visit_implementation(self, a: sbol2.Implementation): + def visit_implementation(self, imp2: sbol2.Implementation): # Priority: 1 - raise NotImplementedError('Conversion of Implementation from SBOL2 to SBOL3 not yet implemented') + # Make the Implementation object and add it to the document + imp3 = sbol3.Implementation(imp2.identity, namespace=self._sbol3_namespace(imp2), built=imp2.built) + self.doc3.add(imp3) + # Map over all other TopLevel properties and extensions not covered by the constructor + self._convert_toplevel(imp2, imp3) def visit_interaction(self, a: sbol2.Interaction): # Priority: 2 diff --git a/test/test_files/sbol3_implementation.nt b/test/test_files/sbol3_implementation.nt new file mode 100644 index 00000000..64a32fb0 --- /dev/null +++ b/test/test_files/sbol3_implementation.nt @@ -0,0 +1,13 @@ + . + . + "impl1" . + . + . + "TetR protein" . + "TetR" . + . + . + "TetR_protein" . + . + "1" . + "1" . diff --git a/test/test_files/sbol_3to2_implementation.xml b/test/test_files/sbol_3to2_implementation.xml new file mode 100644 index 00000000..d9ef888d --- /dev/null +++ b/test/test_files/sbol_3to2_implementation.xml @@ -0,0 +1,19 @@ + + + + 1 + + TetR + TetR_protein + + + TetR protein + + + + + + 1 + impl1 + + diff --git a/test/test_files/sbol_3to2to3_implementation.nt b/test/test_files/sbol_3to2to3_implementation.nt new file mode 100644 index 00000000..080ee87d --- /dev/null +++ b/test/test_files/sbol_3to2to3_implementation.nt @@ -0,0 +1,13 @@ + "1" . + . + . + . + . + . + . + "impl1" . + "1" . + "TetR_protein" . + "TetR protein" . + . + "TetR" . diff --git a/test/test_sbol2_sbol3_direct.py b/test/test_sbol2_sbol3_direct.py index a42fa61f..280e6937 100644 --- a/test/test_sbol2_sbol3_direct.py +++ b/test/test_sbol2_sbol3_direct.py @@ -35,8 +35,8 @@ def test_3to2_conversion(self): self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'BBa_J23101_patched.nt'))) def test_2to3_conversion(self): - """Test ability to convert a simple part from SBOL3 to SBOL2""" - # Load an SBOL3 document and check its contents + """Test ability to convert a simple part from SBOL2 to SBOL3""" + # Load an SBOL2 document and check its contents doc2 = sbol2.Document() doc2.read(TEST_FILES / 'BBa_J23101.xml') # Convert to SBOL3 and check contents @@ -53,6 +53,44 @@ def test_2to3_conversion(self): doc2_loop.write(tmp2) self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'BBa_J23101.xml'))) + def test_3to2_implementation_conversion(self): + """Test ability to convert an implementation from SBOL3 to SBOL2""" + # Load an SBOL3 document and check its contents + doc3 = sbol3.Document() + doc3.read(TEST_FILES / 'sbol3_implementation.nt') + # Convert to SBOL2 and check contents + doc2 = convert3to2(doc3, True) + #report = doc2.validate() + #self.assertEqual(len(report), 0, f'Validation failed: {report}') + with tempfile.TemporaryDirectory() as tmpdir: + tmp2 = Path(tmpdir) / 'doc2.xml' + doc2.write(tmp2) + self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_implementation.xml'))) + doc3_loop = convert2to3(doc2, use_native_converter=True) + self.assertEqual(len(doc3_loop.validate()), 0) + tmp3 = Path(tmpdir) / 'doc3_loop.nt' + doc3_loop.write(tmp3) + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_implementation.nt'))) + + def test_2to3_implementation_conversion(self): + """Test ability to convert an implementation from SBOL2 to SBOL3""" + # Load an SBOL2 document and check its contents + doc2 = sbol2.Document() + doc2.read(TEST_FILES / 'sbol_3to2_implementation.xml') + # Convert to SBOL3 and check contents + doc3 = convert2to3(doc2, use_native_converter=True) + self.assertEqual(len(doc3.validate()), 0) + with tempfile.TemporaryDirectory() as tmpdir: + tmp3 = Path(tmpdir) / 'doc3.nt' + doc3.write(tmp3) + self.assertFalse(file_diff(str(tmp3), str(TEST_FILES / 'sbol3_implementation.nt'))) + doc2_loop = convert3to2(doc3, True) + # report = doc2.validate() + # self.assertEqual(len(report), 0, f'Validation failed: {report}') + tmp2 = Path(tmpdir) / 'doc2_loop.xml' + doc2_loop.write(tmp2) + self.assertFalse(file_diff(str(tmp2), str(TEST_FILES / 'sbol_3to2_implementation.xml'))) + if __name__ == '__main__': unittest.main()