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_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_timed_small_protocol(self): ############################################# # set up the document print('Setting up document') doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') ############################################# # Create the Protocol print('Creating Protocol') protocol = paml.Protocol('test_protocol') # Protocol starts at time zero start = pamlt.startTime(protocol, 0, units=tyto.OM.hour) # Protocol lasts 10 - 15 hours duration = pamlt.duration(protocol, [10, 15], units=tyto.OM.hour) time_constraints = pamlt.TimeConstraints("small_protocol_constraints", constraints=pamlt.And( [start, duration]), protocols=[protocol]) doc.add(protocol) doc.add(time_constraints) ######################################## # Validate and write the document print('Validating and writing time') v = doc.validate() assert not v.errors and not v.warnings, "".join( str(e) for e in doc.validate().errors)
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_expressions(self): ############################################# # set up the document print('Setting up document') doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') ############################################# # Create the Expressions print('Creating Protocol') # expression e1: 60s * duration(a1) a1 = paml.Primitive("a1") d1 = uml.Duration(observation=uml.DurationObservation(event=[a1])) m1 = pamlt.TimeMeasure(expr=sbol3.Measure(60, tyto.OM.second)) e1 = uml.Expression(symbol="*", is_ordered=False, operand=[m1, d1]) #doc.add(e1) # expression lt1: e1 < e2 e2 = pamlt.TimeMeasure(expr=sbol3.Measure(120, tyto.OM.second)) lt1 = uml.Expression(symbol="<", is_ordered=True, operand=[e1, e2]) #doc.add(lt1) # c1: Not(lt1) c1 = pamlt.Not(constrained_elements=lt1) # doc.add(c1) ######################################## # Validate and write the document print('Validating and writing time') v = doc.validate() assert not v.errors and not v.warnings, "".join( str(e) for e in doc.validate().errors)
def test_two_behaviors(self): ############################################# # set up the document print('Setting up document') doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') ############################################# # Create the behavior and constraints print('Creating Constraints') a = paml.Primitive("a") b = paml.Primitive("b") # Constrain start of b to follow end of a by [10, 15] follows_constraint = pamlt.precedes(a, [10, 15], b, units=tyto.OM.hour) doc.add(a) # doc.add(follows_constraint) ######################################## # Validate and write the document print('Validating and writing time') v = doc.validate() assert not v.errors and not v.warnings, "".join( str(e) for e in doc.validate().errors)
def test_initial_value(self): # See https://github.com/SynBioDex/pySBOL3/issues/208 # Use `alt_symbols` to test setting with the empty string. # This isn't the actual bug reported in #208. It is a possibly # related issue, so we add a unit test just in case. sbol3.set_namespace('https://github.com/synbiodex/pysbol3') display_id = 'litre' symbol = display_id label = display_id unit = 'https://sbolstandard.org/examples/litre' factor = 0.001 alt_symbols = [''] sunit = sbol3.SingularUnit(display_id, symbol, label, alternative_symbols=alt_symbols, unit=unit, factor=factor) self.assertIsNotNone(sunit) self.assertIsInstance(sunit, sbol3.SingularUnit) self.assertEqual(factor, sunit.factor) self.assertEqual(unit, sunit.unit) self.assertEqual(symbol, sunit.symbol) self.assertEqual(label, sunit.label) self.assertCountEqual(alt_symbols, sunit.alternative_symbols)
def test_single_behavior(self): ############################################# # set up the document print('Setting up document') doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') ############################################# # Create the behavior and constraints print('Creating Constraints') a = paml.Primitive("a") # Constrain start time of a to [0, 10] start_a = pamlt.startTime(a, [0, 10], units=tyto.OM.hour) # Constrain end time of a to [10, 15] end_a = pamlt.endTime(a, [10, 15], units=tyto.OM.hour) # Constrain duration of a to [1, 5] duration_a = pamlt.duration(a, [1, 5], units=tyto.OM.hour) constraint = pamlt.And([start_a, end_a, duration_a]) time_constraints = pamlt.TimeConstraints("small_protocol_constraints", constraints=[constraint]) doc.add(a) doc.add(time_constraints) ######################################## # Validate and write the document print('Validating and writing time') v = doc.validate() assert not v.errors and not v.warnings, "".join( str(e) for e in doc.validate().errors)
def test_custom_conversion(self): """Test if conversion works correctly when the config us used to change expected sheet structure""" wb = openpyxl.load_workbook(os.path.join( TESTFILE_DIR, 'nonstandard_simple_library.xlsx'), data_only=True) sbol3.set_namespace('http://sbolstandard.org/testfiles') config = { 'basic_parts_name': 'C2', 'basic_parts_description': 'A12', 'basic_first_row': 21, 'basic_role_col': 2, 'basic_notes_col': 3, 'basic_description_col': 5, 'basic_source_prefix_col': 6, 'basic_source_id_col': 7, 'basic_final_col': 10, 'basic_circular_col': 11, 'basic_length_col': 12, 'basic_sequence_col': 13, 'composite_first_part_col': 8 } doc = sbol_utilities.excel_to_sbol.excel_to_sbol(wb, config) assert not doc.validate().errors and not doc.validate().warnings assert len(doc.find('BasicParts').members) == 26 assert len(doc.find('CompositeParts').members) == 6 assert len(doc.find('LinearDNAProducts').members) == 2 assert len(doc.find('FinalProducts').members) == 2 temp_name = tempfile.mkstemp(suffix='.nt')[1] doc.write(temp_name, sbol3.SORTED_NTRIPLES) assert_files_identical(temp_name, os.path.join(TESTFILE_DIR, 'simple_library.nt'))
def test_namespace_set(self): # Test that namespace is properly set on an object after # using set_namespace() namespace = 'https://github.com/synbiodex/pysbol3' sbol3.set_namespace(namespace) collection = sbol3.Collection('collection1') self.assertEqual(namespace, collection.namespace)
def test_activity_bad_inflows(self): """Test whether validator can detect error due to excess or missing inflows""" # set up the document print('Setting up document') doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') # Create the protocol print('Creating protocol') protocol = paml.Protocol('broken') doc.add(protocol) # call order backwards, to make an edge from the final to the initial protocol.order(protocol.final(), protocol.initial()) # access a parameter node and order it backwards too p = uml.ActivityParameterNode() protocol.nodes.append(p) protocol.order(protocol.final(), p) # Validate the document, which should produce two errors print('Validating and writing protocol') v = doc.validate() assert len(v) == 3, f'Expected 3 validation issues, but found {len(v)}' expected = [ 'https://bbn.com/scratch/broken/ActivityParameterNode1: Too few values for property parameter. Expected 1, found 0', 'https://bbn.com/scratch/broken/InitialNode1: InitialNode must have no incoming edges, but has 1', 'https://bbn.com/scratch/broken/FlowFinalNode1: Node has no incoming edges, so cannot be executed' ] observed = [str(e) for e in v] assert observed == expected, f'Unexpected error content: {observed}'
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(self): namespace = 'https://github.com/synbiodex/pysbol3' sbol3.set_namespace(namespace) test_path = os.path.join(SBOL3_LOCATION, 'multicellular', 'multicellular.ttl') doc = sbol3.Document() doc.read(test_path) copies1 = sbol3.copy(doc) self.assertEqual(len(doc), len(copies1)) document_checker = self.make_document_checker(None) for obj in copies1: obj.traverse(document_checker) # Verify that the copies get the new namespace copies2 = sbol3.copy(doc, into_namespace=namespace) document_checker = self.make_document_checker(None) namespace_checker = self.make_namespace_checker(namespace) for obj in copies2: obj.traverse(document_checker) obj.traverse(namespace_checker) # Verify new namespace AND new document namespace3 = 'https://github.com/synbiodex/pysbol3/copytest' doc3 = sbol3.Document() copies3 = sbol3.copy(doc, into_namespace=namespace3, into_document=doc3) document_checker = self.make_document_checker(doc3) namespace_checker = self.make_namespace_checker(namespace3) for obj in copies3: obj.traverse(document_checker) obj.traverse(namespace_checker)
def test_round_trip(self): # Test the int list property, which is not used by the # core SBOL 3 data model sbol3.set_namespace('https://github.com/synbiodex/pysbol3') obj = CustomIdentifiedClass() self.assertEqual([], obj.foo_int) obj.foo_int.append(7) obj.foo_int.append(14) self.assertEqual([7, 14], obj.foo_int) tl_name = 'my_obj' tl = CustomTopClass(tl_name) tl.children.append(obj) doc = sbol3.Document() doc.add(tl) doc2 = sbol3.Document() # Round trip the document with tempfile.TemporaryDirectory() as tmpdirname: test_file = os.path.join(tmpdirname, 'custom.nt') doc.write(test_file, sbol3.NTRIPLES) doc2.read(test_file, sbol3.NTRIPLES) tl2 = doc2.find(tl_name) obj2 = tl2.children[0] # The lists are necessarily unordered because of RDF # Compare specially self.assertCountEqual([7, 14], obj2.foo_int)
def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') agent = sbol3.Agent('agent') usage = sbol3.Usage(agent.identity) self.assertIsNotNone(usage) self.assertEqual(agent.identity, usage.entity) self.assertEqual([], usage.roles)
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_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_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_singleton_wrapping_urls(self): # See https://github.com/SynBioDex/pySBOL3/issues/301 sbol3.set_namespace('https://github.com/synbiodex/pysbol3') process1 = 'https://example.com/thing' thing = sbol3.Sequence('thing1', derived_from=process1) self.assertEqual(1, len(thing.derived_from)) self.assertEqual(process1, thing.derived_from[0])
def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') base_url = 'https://github.com/SynBioDex/pySBOL3/' source_uri = base_url + 'blob/master/sbol3/attachment.py' att = sbol3.Attachment('attachment1', source_uri) self.assertEqual(source_uri, att.source) self.assertEqual(sbol3.SBOL_ATTACHMENT, att.type_uri)
def test_ordered_behavior_parameters(self): doc = sbol3.Document() sbol3.set_namespace('https://bbn.com/scratch/') parameter1 = uml.OrderedPropertyValue( index=0, property_value=uml.Parameter( direction="in", default_value=uml.LiteralInteger(value=0), is_unique=True, is_ordered=True, lower_value=uml.LiteralInteger(value=0), upper_value=uml.LiteralInteger(value=10))) parameter2 = uml.OrderedPropertyValue( index=1, property_value=uml.Parameter( direction="in", default_value=uml.LiteralInteger(value=0), is_unique=True, is_ordered=True, lower_value=uml.LiteralInteger(value=0), upper_value=uml.LiteralInteger(value=10))) behavior = uml.Behavior("b", parameters=[parameter1, parameter2]) assert parameter1 in behavior.parameters and parameter2 in behavior.parameters doc.add(behavior) v = doc.validate() assert not v.errors and not v.warnings, "".join( str(e) for e in doc.validate().errors)
def test_expansion(self): """Test basic expansion of combinatorial derivations""" doc = sbol3.Document() doc.read(os.path.join(TESTFILE_DIR, 'simple_library.nt')) sbol3.set_namespace('http://sbolstandard.org/testfiles') roots = list( sbol_utilities.expand_combinatorial_derivations. root_combinatorial_derivations(doc)) assert len( roots) == 1, f'Unexpected roots: {[r.identity for r in roots]}' derivative_collections = sbol_utilities.expand_combinatorial_derivations.expand_derivations( roots) assert not len(doc.validate()) assert len(doc.find('Round_1_order_collection').members) == 24 output_doc = sbol3.Document() for c in derivative_collections: copy_toplevel_and_dependencies(output_doc, c) assert not len(output_doc.validate()) temp_name = tempfile.mkstemp(suffix='.nt')[1] output_doc.write(temp_name, sbol3.SORTED_NTRIPLES) assert_files_identical( temp_name, os.path.join(TESTFILE_DIR, 'expanded_simple_library.nt'))
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_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_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') display_id = 'seq1' seq = sbol3.Sequence(display_id) self.assertIsNotNone(seq) self.assertEqual(display_id, seq.display_id) self.assertIsNone(seq.elements) self.assertIsNone(seq.encoding)
def test_create(self): sbol3.set_namespace('https://github.com/synbiodex/pysbol3') display_id = 'exp_data' exp_data = sbol3.ExperimentalData(display_id) 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)
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_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_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') display_id = 'plan' plan = sbol3.Plan(display_id) self.assertIsNotNone(plan) self.assertEqual(display_id, plan.display_id) # attachments come from TopLevel self.assertEqual([], plan.attachments)