def test_system_building(self): doc = sbol3.Document() sbol3.set_namespace('http://sbolstandard.org/testfiles') system = sbol3.Component('system', sbol3.SBO_FUNCTIONAL_ENTITY) doc.add(system) # make a couple of stand-alone components gfp_cds = sbol3.Component('gfp_cds', sbol3.SBO_DNA, roles=[tyto.SO.CDS]) doc.add(gfp_cds) # make a functional unit expression = add_feature( system, sbol3.LocalSubComponent([sbol3.SBO_DNA], roles=[tyto.SO.engineered_region])) contains(expression, gfp_cds) rbs = contains( expression, sbol3.LocalSubComponent([sbol3.SBO_DNA], roles=[tyto.SO.ribosome_entry_site])) regulate(rbs, gfp_cds) terminator = contains( expression, sbol3.LocalSubComponent([sbol3.SBO_DNA], roles=[tyto.SO.terminator])) order(gfp_cds, terminator) constitutive(expression) # link it to a product gfp_mut3_ncbi = 'https://www.ncbi.nlm.nih.gov/protein/AAB18957.1' gfp = add_feature( system, sbol3.ExternallyDefined([sbol3.SBO_PROTEIN], gfp_mut3_ncbi)) prod = add_interaction(sbol3.SBO_GENETIC_PRODUCTION, participants={ gfp: sbol3.SBO_PRODUCT, gfp_cds: sbol3.SBO_TEMPLATE }) assert contained_components(system) == {system, gfp_cds} assert in_role(prod, sbol3.SBO_PRODUCT) == gfp assert all_in_role(prod, sbol3.SBO_TEMPLATE) == [ ensure_singleton_feature(system, gfp_cds) ] # confirm that the system constructed is exactly as expected tmp_out = tempfile.mkstemp(suffix='.nt')[1] doc.write(tmp_out, sbol3.SORTED_NTRIPLES) test_dir = os.path.dirname(os.path.realpath(__file__)) comparison_file = os.path.join(test_dir, 'test_files', 'component_construction.nt') assert filecmp.cmp( tmp_out, comparison_file), f'Converted file {tmp_out} is not identical'
def test_creation_namespace_mismatch(self): # Prevent an identity/namespace mismatch on object creation # See https://github.com/SynBioDex/pySBOL3/issues/277 with self.assertRaises(ValueError): sbol3.Component('https://example.com/mismatch/c1', types=[sbol3.SBO_DNA], namespace='https://example.com/different')
def test_annotation(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') # Create custom annotation annotation_uri = 'http://example.org/boolean_property' annotation_value = 'foo' c = sbol3.Component('c1', sbol3.SBO_DNA) c.annotation = sbol3.TextProperty(c, annotation_uri, 0, 1, []) c.annotation = annotation_value self.assertEqual(annotation_value, c.annotation) doc = sbol3.Document() doc.add(c) doc2 = sbol3.Document() with tempfile.TemporaryDirectory() as tmpdirname: test_file = os.path.join(tmpdirname, 'annotation.xml') doc.write(test_file, sbol3.RDF_XML) # Roundtrip doc2.read(test_file, sbol3.RDF_XML) # Recover annotation c = doc2.find('c1') c.annotation = sbol3.TextProperty(c, annotation_uri, 0, 1, []) self.assertEqual(annotation_value, c.annotation)
def test_copy_stability(self): # Test the stability of naming of objects across copies. # See https://github.com/SynBioDex/pySBOL3/issues/231 # # Strategy: create an object with 10+ children of the same # type. Add to a document and serialize the document. Load the # serialized document. Copy the object to a new document. # Serialize the new document. Compare the serializations. If we # use sorted ntriples, the serializations should be the same. # This will demonstrate that we maintain names properly despite # the inherently unordered nature of SBOL. sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', types=[sbol3.SBO_DNA]) # Create a double-digit number of children to test sort of 10, 11, 1, etc. for i in range(12): instance_of_uri = f'https://example.com/instance/i{i}' c1.features.append(sbol3.SubComponent(instance_of=instance_of_uri)) doc1 = sbol3.Document() doc1.add(c1) # Serialize to string doc1_string = doc1.write_string(sbol3.SORTED_NTRIPLES) self.assertIsNotNone(doc1_string) # Load the serialized document into a new document tmp_doc = sbol3.Document() tmp_doc.read_string(doc1_string, sbol3.SORTED_NTRIPLES) # Locate the top level to copy tmp_c1 = tmp_doc.find('c1') self.assertIsNotNone(tmp_c1) self.assertIsInstance(tmp_c1, sbol3.TopLevel) # Copy the top level into a new document doc2 = sbol3.Document() sbol3.copy([tmp_c1], into_document=doc2) doc2_string = doc2.write_string(sbol3.SORTED_NTRIPLES) # Verify that the serializations are identical self.assertEqual(doc1_string, doc2_string)
def test_copy_is_deprecated(self): namespace = 'https://github.com/synbiodex/pysbol3' sbol3.set_namespace(namespace) name = 'c1' c1 = sbol3.Component(name, types=[sbol3.SBO_DNA]) with self.assertWarns(DeprecationWarning): c1.copy()
def test_cloning(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', sbol3.SBO_DNA) new_identity = 'c2' c2 = c1.clone(new_identity) self.assertEqual(posixpath.join(sbol3.get_namespace(), new_identity), c2.identity)
def test_copy_properties(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') root = sbol3.Component('root', sbol3.SBO_DNA) root.name = 'foo' objects = sbol3.copy([root]) root_copy = objects[0] self.assertEqual(root_copy.name, 'foo')
def test_boolean_property(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c = sbol3.Component('c1', sbol3.SBO_DNA) c.boolean_attribute = sbol3.BooleanProperty(c, 'http://example.org#foo', 0, 1, []) c.boolean_attribute = True self.assertEqual(type(c.boolean_attribute), bool)
def test_no_namespace(self): # Make sure there is no default namespace self.assertEqual(None, sbol3.get_namespace()) # Make sure that creating an object with a display_id # and no default namespace raises an exception with self.assertRaises(sbol3.NamespaceError): c = sbol3.Component('c1', sbol3.SBO_DNA)
def test_slice_assignment(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c = sbol3.Component('c1', sbol3.SBO_DNA) self.assertEqual([], c.roles) c.roles.append(sbol3.SO_PROMOTER) self.assertEqual([sbol3.SO_PROMOTER], c.roles) expected = [rdflib.URIRef(item) for item in c.roles] self.assertEqual(expected, c._properties[sbol3.SBOL_ROLE]) c.roles.append(sbol3.SO_CDS) self.assertEqual([sbol3.SO_PROMOTER, sbol3.SO_CDS], c.roles) expected = [rdflib.URIRef(item) for item in c.roles] self.assertEqual(expected, c._properties[sbol3.SBOL_ROLE]) c.roles[1] = sbol3.CHEBI_EFFECTOR self.assertEqual([sbol3.SO_PROMOTER, sbol3.CHEBI_EFFECTOR], c.roles) # Make sure the underlying representation is correct expected = [rdflib.URIRef(item) for item in c.roles] self.assertEqual(expected, c._properties[sbol3.SBOL_ROLE]) c.roles.append(sbol3.SO_RBS) expected = [sbol3.SO_PROMOTER, sbol3.CHEBI_EFFECTOR, sbol3.SO_RBS] self.assertEqual(expected, c.roles) expected = [rdflib.URIRef(item) for item in c.roles] self.assertEqual(expected, c._properties[sbol3.SBOL_ROLE]) # Replace the first two elements by slice replacement c.roles[0:2] = [sbol3.SO_OPERATOR, sbol3.SO_MRNA] expected = [sbol3.SO_OPERATOR, sbol3.SO_MRNA, sbol3.SO_RBS] self.assertEqual(expected, c.roles) expected = [rdflib.URIRef(item) for item in c.roles] self.assertEqual(expected, c._properties[sbol3.SBOL_ROLE])
def test_identity_display_id(self): # Test setting of display_id # * Test by passing display_id to constructor # * Test by having display_id deduced from identity sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1_display_id = 'c1' c1_identity = posixpath.join(sbol3.get_namespace(), c1_display_id) c1 = sbol3.Component(c1_display_id, sbol3.SBO_DNA) self.assertEqual(c1_display_id, c1.display_id) self.assertEqual(c1_identity, c1.identity) # Now test identity and display_id from a URL-type URI c2_display_id = 'c2' c2_identity = posixpath.join(sbol3.get_namespace(), c2_display_id) c2 = sbol3.Component(c2_identity, sbol3.SBO_DNA) self.assertEqual(c2_display_id, c2.display_id) self.assertEqual(c2_identity, c2.identity)
def test_shacl_closure_with_child_objects(self): # See https://github.com/SynBioDex/pySBOL3/issues/348 # See https://github.com/SynBioDex/pySBOL3/issues/353 sbol3.set_namespace('https://github.com/SynBioDex/pySBOL3') doc = sbol3.Document() c_top = sbol3.Component('top', sbol3.SBO_DNA) c_middle = sbol3.Component('middle', sbol3.SBO_DNA) c_bottom = sbol3.Component('bottom', sbol3.SBO_DNA) subc_middle = sbol3.SubComponent(c_middle) c_top.features = [subc_middle] subc_bottom = sbol3.SubComponent(c_bottom) c_middle.features = [subc_bottom] subc_bottom_ref = sbol3.ComponentReference(in_child_of=subc_middle, refers_to=subc_bottom) c_top.features.append(subc_bottom_ref) doc.add(c_top) self.assertFalse(len(doc.validate()))
def test_cloning_with_children(self): # This test does not use `sbol3.set_namespace` as the other # cloning unit tests do. This is on purpose to verify that # cloning does not rely on the default namespace. doc = sbol3.Document() namespace = 'https://github.com/synbiodex/pysbol3' c1_identity = posixpath.join(namespace, 'c1') c2_identity = posixpath.join(namespace, 'c2') s1_identity = posixpath.join(namespace, 's1') c1 = sbol3.Component(c1_identity, sbol3.SBO_DNA) doc.add(c1) seq1 = sbol3.Sequence(s1_identity) doc.add(seq1) c1.sequences.append(seq1) sc1 = sbol3.SubComponent(c1) es1 = sbol3.EntireSequence(seq1) sc1.source_locations.append(es1) c1.features = [sc1] c2 = c1.clone(c2_identity) self.assertEqual(c2_identity, c2.identity) self.assertIsNone(c2.document) # Check on the SubComponent sc2 = c2.features[0] self.assertIsInstance(sc2, sbol3.SubComponent) self.assertNotEqual(sc1.identity, sc2.identity) self.assertTrue(sc2.identity.startswith(c2.identity)) # Ensure that the reference was updated properly self.assertEqual(c2.identity, sc2.instance_of) self.assertIsNone(sc2.document) es2 = sc2.source_locations[0] self.assertIsInstance(es2, sbol3.EntireSequence) self.assertNotEqual(es1.identity, es2.identity) self.assertTrue(es2.identity.startswith(c2.identity)) self.assertEqual(es1.sequence, es2.sequence) self.assertIsNone(es2.document)
def test_create2(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', [sbol3.SBO_DNA]) implementation = sbol3.Implementation('impl1', built=c1) self.assertIsNotNone(implementation) self.assertEqual(c1.identity, implementation.built) self.assertEqual(sbol3.SBOL_IMPLEMENTATION, implementation.type_uri)
def test_features(self): # See https://github.com/SynBioDex/pySBOL3/issues/149 # Note: this example was modified when fixing # https://github.com/SynBioDex/pySBOL3/issues/178 # media_variable is unused in the original example so # it has been commented out here media_template = sbol3.LocalSubComponent( types=[sbol3.SBO_FUNCTIONAL_ENTITY]) media_template.name = 'media template' # variable_uri = 'https://github.com/synbiodex/pysbol3/variable' # media_variable = sbol3.VariableFeature(cardinality=sbol3.SBOL_ONE, # variable=media_template) # media_variable.variable = media_template all_sample_templates = [media_template] sample_template_uri = 'https://sd2e.org/measurement_template' sample_template = sbol3.Component(identity=sample_template_uri, types=sbol3.SBO_FUNCTIONAL_ENTITY) sample_template.name = 'measurement template' sample_template.features = all_sample_templates self.assertEqual(1, len(sample_template.features)) self.assertEqual(media_template.identity, sample_template.features[0].identity)
def test_list_wrapping(self): # Ensure that at least certain properties handle automatic list # wrapping and are typed to do so. # See https://github.com/SynBioDex/pySBOL3/issues/301 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') source_uri = 'https://example.org/source' derived_from_uri = 'https://example.org/derived_from' statute_mile = sbol3.OM_NS + 'mile-Statute' comp1_type = sbol3.SBO_DNA comp1_role = sbol3.SO_PROMOTER comp1_seq1 = sbol3.Sequence('seq1') comp1_model = sbol3.Model('model1', source=source_uri, language='https://example.org/language', framework='https://example.org/framework') comp1_attachment = sbol3.Attachment('att1', source=source_uri) comp1_measure = sbol3.Measure(value=26.2, unit=statute_mile) comp1_activity = sbol3.Activity('activity1') comp1 = sbol3.Component('comp1', types=comp1_type, sequences=comp1_seq1, roles=comp1_role, models=comp1_model, attachments=comp1_attachment, derived_from=derived_from_uri, measures=comp1_measure, generated_by=comp1_activity) self.assertEqual([comp1_type], comp1.types) self.assertEqual([comp1_seq1.identity], comp1.sequences) self.assertEqual([comp1_role], comp1.roles) self.assertEqual([comp1_model.identity], comp1.models) self.assertEqual([comp1_attachment.identity], comp1.attachments) self.assertEqual([derived_from_uri], comp1.derived_from) self.assertEqual([comp1_measure], comp1.measures) self.assertEqual([comp1_activity.identity], comp1.generated_by)
def test_trailing_slash(self): # A trailing slash on an object's identity should automatically be removed sbol3.set_namespace('http://example.org/sbol3') slash_identity = posixpath.join(sbol3.get_namespace(), 'c1', '') self.assertTrue(slash_identity.endswith(posixpath.sep)) c = sbol3.Component(slash_identity, sbol3.SBO_DNA) identity = slash_identity.strip(posixpath.sep) self.assertEqual(identity, c.identity)
def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') template = 'https://github.com/synbiodex/pysbol3/component' cd1 = sbol3.CombinatorialDerivation('cd1', template) self.assertEqual(template, cd1.template) comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) cd2 = sbol3.CombinatorialDerivation('cd2', comp1) self.assertEqual(comp1.identity, cd2.template)
def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') instance_of = sbol3.Component('comp1', sbol3.SBO_DNA) sc1 = sbol3.SubComponent(instance_of) self.assertIsNotNone(sc1) self.assertEqual(instance_of.identity, sc1.instance_of) sc2 = sbol3.SubComponent(instance_of.identity) self.assertEqual(instance_of.identity, sc2.instance_of)
def test_measures_initial_value(self): # See https://github.com/SynBioDex/pySBOL3/issues/301 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') metre = 'http://www.ontology-of-units-of-measure.org/resource/om-2/metre' one_metre = sbol3.Measure(1, unit=metre) two_metres = sbol3.Measure(2, unit=metre) # Test passing a list of measures c1 = sbol3.Component('c1', types=[sbol3.SBO_DNA], measures=[one_metre, two_metres]) self.assertListEqual([one_metre, two_metres], list(c1.measures)) # test passing a singleton measure three_metres = sbol3.Measure(3, unit=metre) c2 = sbol3.Component('c2', types=[sbol3.SBO_DNA], measures=three_metres) self.assertListEqual([three_metres], list(c2.measures))
def test_not_iterable(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', sbol3.SBO_DNA) self.assertIsInstance(c1.types, Iterable) with self.assertRaises(TypeError): c1.types = sbol3.SBO_PROTEIN with self.assertRaises(TypeError): c1.types = object()
def test_display_name(self): """Tests display_name property which must return display_id if name doesn't exist, else return name of the identified object """ sbol3.set_namespace('https://github.com/synbiodex/pysbol3') test_name = 'Test_name' test_display_id = 'Test_display_id' # case 1. only identity provided obj_without_name = sbol3.Component(test_display_id, sbol3.SBO_DNA) display_name = obj_without_name.display_name self.assertEqual(display_name, test_display_id) # case 2. both name and identity provided obj_with_name = sbol3.Component(test_display_id, sbol3.SBO_DNA, name=test_name) display_name = obj_with_name.display_name self.assertEqual(display_name, test_name)
def test_namespace_mismatch_uuid(self): # Now check a UUID with no default namespace set # sbol3.set_namespace(None) self.assertIsNone(sbol3.get_namespace()) c = sbol3.Component(uuid.uuid4().urn, types=[sbol3.SBO_DNA]) report = c.validate() self.assertIsNotNone(report) # Expecting at least one error self.assertEqual(0, len(report))
def test_invalid_strategy(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') # Test with invalid strategy comp1 = sbol3.Component('comp1', sbol3.SBO_DNA) cd1 = sbol3.CombinatorialDerivation('cd1', comp1) cd1.strategy = sbol3.SBOL_INLINE report = cd1.validate() self.assertIsNotNone(report) self.assertEqual(1, len(report.errors))
def test_copy_child_objects(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') doc = sbol3.Document() root = sbol3.Component('root', sbol3.SBO_DNA) sub1 = sbol3.Component('sub1', sbol3.SBO_DNA) sub2 = sbol3.Component('sub2', sbol3.SBO_DNA) sc1 = sbol3.SubComponent(sub1) sc2 = sbol3.SubComponent(sub2) root.features.append(sc1) root.features.append(sc2) doc.add(root) doc.add(sub1) doc.add(sub2) doc2 = sbol3.Document() root_copy = root.copy(target_doc=doc2) self.assertEqual([sc.identity for sc in root.features], [sc.identity for sc in root_copy.features])
def test_cloning_with_references(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', sbol3.SBO_DNA) new_identity = 'c2' seq1 = sbol3.Sequence('s1') c1.sequences.append(seq1) c2 = c1.clone(new_identity) self.assertEqual(posixpath.join(sbol3.get_namespace(), new_identity), c2.identity) self.assertListEqual(list(c1.sequences), list(c2.sequences))
def test_basic_serialization(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c = sbol3.Component('c1', sbol3.SBO_DNA) graph = rdflib.Graph() c.serialize(graph) # Is there a better way to get all the triples? triples = list(graph.triples((None, None, None))) # Expecting a triple for the type, a triple for the displayId, # a triple for the namespace, and a triple for the component type self.assertEqual(4, len(triples))
def test_attribute_name(self): # Verify that a property can figure out what its attribute name is. sbol3.set_namespace('https://github.com/synbiodex/pysbol3') c1 = sbol3.Component('c1', sbol3.SBO_DNA) types_property = c1.__dict__['types'] aname = types_property.attribute_name self.assertEqual('types', aname) features_property = c1.__dict__['features'] aname = features_property.attribute_name self.assertEqual('features', aname)
def test_create2(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') display_id = 'exp_data' c1 = sbol3.Component('c1', [sbol3.SBO_DNA]) exp_data = sbol3.ExperimentalData(display_id, attachments=[c1]) self.assertIsNotNone(exp_data) self.assertEqual(display_id, exp_data.display_id) self.assertTrue(hasattr(exp_data, 'attachments')) self.assertEqual(sbol3.SBOL_EXPERIMENTAL_DATA, exp_data.type_uri) self.assertCountEqual([c1.identity], exp_data.attachments)
def test_list_property_update_identity(self): # This test uses assignment instead of appending sbol3.set_namespace('https://github.com/synbiodex/pysbol3') comp = sbol3.Component('c1', sbol3.SBO_DNA) con1 = sbol3.Constraint(sbol3.SBOL_REPLACES, 'http://example.com/fake1', 'http://example.com/fake2') expected2 = posixpath.join(comp.identity, 'Constraint1') # Setting to list should cause the constraint's identity to change comp.constraints = [con1] self.assertEqual(expected2, con1.identity)