Пример #1
0
    def test_namespace(self):
        base_uri = 'https://github.com/synbiodex/pysbol3'
        sbol3.set_namespace(base_uri)
        self.assertEqual(base_uri, sbol3.get_namespace())

        # Example from SBOL 3.0 Section 5.1 (page 12)
        # See issue #80
        base_uri = 'https://synbiohub.org'
        sbol3.set_namespace(base_uri)
        self.assertEqual(base_uri, sbol3.get_namespace())
Пример #2
0
 def test_default_namespace_with_local_path(self):
     # Make sure default namespace is honored when the identity has
     # a local path included
     test_namespace = 'https://github.com/synbiodex'
     sbol3.set_namespace(test_namespace)
     self.assertEqual(test_namespace, sbol3.get_namespace())
     identity = posixpath.join(sbol3.get_namespace(), 'pysbol3', 'foo')
     c = sbol3.Component(identity, types=[sbol3.SBO_DNA])
     self.assertEqual(sbol3.get_namespace(), c.namespace)
     self.assertEqual('foo', c.display_id)
     self.assertEqual(identity, c.identity)
     self.assertEqual(0, len(c.validate()))
Пример #3
0
 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)
Пример #4
0
 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)
Пример #5
0
 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)
Пример #6
0
 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)
Пример #7
0
 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))
Пример #8
0
 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))
Пример #9
0
 def test_no_namespace(self):
     # This test requires that no objects have been created without
     # a namespace set. The warning only triggers on the first such
     # creation. There is probably a way to reset the triggering of
     # warnings if we need that in the future.
     #
     # Make sure there is no default namespace
     self.assertEqual(None, sbol3.get_namespace())
     # Make sure creation without a namespace generates a warning
     display_id = 'c1'
     with self.assertWarns(UserWarning) as cm:
         c = sbol3.Component(display_id, sbol3.SBO_DNA)
     # We expect the warning to come from object.py. Update this if
     # the logic changes.
     self.assertIn('object.py', cm.filename)
     # We expect the default namespace to appear in the identity
     self.assertIn(sbol3.PYSBOL3_DEFAULT_NAMESPACE, c.identity)
     # We expect the default namespace at the beginning of the identity
     self.assertTrue(c.identity.startswith(sbol3.PYSBOL3_DEFAULT_NAMESPACE))
     # We expect the display_id to appear in the identity
     self.assertIn(display_id, c.identity)
     # We expect the display_id to be at the end of the identity
     self.assertTrue(c.identity.endswith(display_id))
Пример #10
0
def row_to_basic_part(doc: sbol3.Document, row, basic_parts: sbol3.Collection,
                      linear_products: sbol3.Collection,
                      final_products: sbol3.Collection, config: dict,
                      source_table: dict):
    """
    Read a row for a basic part and turn it into SBOL Component
    :param doc: Document to add parts to
    :param row: Excel row to be processed
    :param basic_parts: collection of parts to add to
    :param linear_products: collection of linear parts to add to
    :param final_products: collection of final parts to add to
    :param config: dictionary of sheet parsing configuration variables
    :param source_table: dictionary mapping source names to namespaces
    :return: None
    """
    # Parse material from sheet row
    name = row[config['basic_name_col']].value
    if name is None:
        return  # skip lines without names
    else:
        name = name.strip()  # make sure we're discarding whitespace
    raw_role = row[config['basic_role_col']].value
    try:  # look up with tyto; if fail, leave blank or add to description
        role = (tyto.SO.get_uri_by_term(raw_role) if raw_role else None)
    except LookupError:
        logging.warning(
            f'Role "{raw_role}" could not be found in Sequence Ontology')
        role = None
    design_notes = (row[config['basic_notes_col']].value
                    if row[config['basic_notes_col']].value else "")
    description = (row[config['basic_description_col']].value
                   if row[config['basic_description_col']].value else "")
    source_prefix = row[config['basic_source_prefix_col']].value
    source_id = row[config['basic_source_id_col']].value
    final_product = row[config['basic_final_col']].value  # boolean
    circular = row[config['basic_circular_col']].value  # boolean
    length = row[config['basic_length_col']].value
    raw_sequence = row[config['basic_sequence_col']].value
    sequence = (None if raw_sequence is None else "".join(
        unicodedata.normalize("NFKD", raw_sequence).upper().split()))
    if not ((sequence is None and length == 0) or len(sequence) == length):
        raise ValueError(
            f'Part "{name}" has mismatched sequence length: check for bad characters and extra whitespace'
        )

    # identity comes from source if set to a literal table, from display_id if not set
    identity = None
    display_id = None
    was_derived_from = None
    namespace = sbol3.get_namespace()
    if source_id and source_prefix:
        source_prefix = source_prefix.strip()
        if source_prefix in source_table:
            if source_table[source_prefix]:
                display_id = sbol3.string_to_display_id(source_id.strip())
                identity = f'{source_table[source_prefix]}/{display_id}'
                namespace = source_table[source_prefix]
            else:  # when there is no prefix, use the bare value (in SBOL3 format)
                raw_url = source_id.strip()
                identity = url_to_identity(
                    strip_filetype_suffix(strip_sbol2_version(raw_url)))
                was_derived_from = raw_url
                namespace = identity.rsplit(
                    '/', 1)[0]  # TODO: use a helper function
        else:
            logging.info(
                f'Part "{name}" ignoring non-literal source: {source_prefix}')
    elif source_id:
        logging.warning(
            f'Part "{name}" has source ID specified but not prefix: {source_id}'
        )
    elif source_prefix:
        logging.warning(
            f'Part "{name}" has source prefix specified but not ID: {source_prefix}'
        )
    if not identity:
        display_id = sbol3.string_to_display_id(name)

    # build a component from the material
    logging.debug(f'Creating basic part "{name}"')
    component = sbol3.Component(
        identity or display_id,
        sbol3.SBO_DNA,
        name=name,
        namespace=namespace,
        description=f'{design_notes}\n{description}'.strip())
    if was_derived_from:
        component.derived_from.append(was_derived_from)
    doc.add(component)
    if role:
        component.roles.append(role)
    if circular:
        component.types.append(sbol3.SO_CIRCULAR)
    if sequence:
        sbol_seq = sbol3.Sequence(f'{component.identity}_sequence',
                                  namespace=namespace,
                                  encoding=sbol3.IUPAC_DNA_ENCODING,
                                  elements=sequence)
        doc.add(sbol_seq)
        component.sequences.append(sbol_seq.identity)

    # add the component to the appropriate collections
    basic_parts.members.append(component.identity)
    if final_product:
        linear_products.members.append(component.identity)
        final_products.members.append(component.identity)