Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions sbol3/object.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import posixpath
import uuid
import warnings
Expand Down Expand Up @@ -111,8 +112,12 @@ def copy(self, target_doc=None, target_namespace=None):
old_uri = self.identity
new_uri = replace_namespace(old_uri, target_namespace, self.getTypeURI())

new_obj = BUILDER_REGISTER[self.type_uri](**dict(identity=new_uri,
type_uri=self.type_uri))
try:
builder = BUILDER_REGISTER[self.type_uri]
except KeyError:
logging.warning(f'No builder found for {self.type_uri}; assuming {self.__class__.__name__}')
builder = self.__class__
new_obj = builder(**dict(identity=new_uri, type_uri=self.type_uri))

# Copy properties
for property_uri, value_store in self._properties.items():
Expand Down
38 changes: 34 additions & 4 deletions test/test_custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import os
import tempfile
import unittest
import warnings
from typing import Union

import rdflib

import sbol3


PYSBOL3_CUSTOM_TOP = 'https://github.com/synbiodex/pysbol3#customTop'
PYSBOL3_CUSTOM_UNREGISTERED_TOP = 'https://github.com/synbiodex/pysbol3#customUnregisteredTop'
PYSBOL3_CUSTOM_BOOL = 'https://github.com/synbiodex/pysbol3#customBool'
PYSBOL3_CUSTOM_CHILD = 'https://github.com/synbiodex/pysbol3#customChildren'
PYSBOL3_CUSTOM_IDENTIFIED = 'https://github.com/synbiodex/pysbol3#customIdentified'
Expand All @@ -26,6 +26,15 @@ def __init__(self, identity, type_uri=PYSBOL3_CUSTOM_TOP):
self.children = sbol3.OwnedObject(self, PYSBOL3_CUSTOM_CHILD, 0, math.inf)


class CustomUnregisteredTopClass(sbol3.CustomTopLevel):
def __init__(self, identity, type_uri=PYSBOL3_CUSTOM_UNREGISTERED_TOP):
super().__init__(identity, type_uri)
# Also test the boolean list while we're here
self.foo_bool = sbol3.BooleanProperty(self, PYSBOL3_CUSTOM_BOOL,
0, math.inf)
self.children = sbol3.OwnedObject(self, PYSBOL3_CUSTOM_CHILD, 0, math.inf)


class CustomIdentifiedClass(sbol3.CustomIdentified):
def __init__(self, type_uri=PYSBOL3_CUSTOM_IDENTIFIED, identity=None):
super().__init__(type_uri, identity=identity)
Expand Down Expand Up @@ -85,18 +94,39 @@ def test_round_trip(self):
obj.foo_bool.append(True)
obj.foo_bool.append(False)
self.assertEqual([True, False], obj.foo_bool)
obj_unregistered_name = 'bool_test_unregistered'
obj_u = CustomUnregisteredTopClass(obj_unregistered_name)
obj_u.foo_bool.append(True)
self.assertEqual([True], obj_u.foo_bool)
doc = sbol3.Document()
doc.add(obj)
doc.add(obj_u)
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)
obj2 = doc2.find(obj_name)
obj_u2 = doc2.find(obj_unregistered_name)
# The lists are necessarily unordered because of RDF
# Compare specially
self.assertCountEqual([True, False], obj2.foo_bool)
self.assertCountEqual([False, True], obj2.foo_bool)
unregistered_values = obj_u2._properties['https://github.com/synbiodex/pysbol3#customBool']
self.assertEqual(['true'], [str(x) for x in unregistered_values])

# Finally, make sure the objects can be copied into a new document
doc3 = sbol3.Document()
# This test deliberately uses the old copy function, as that was where an error previously occurred
with warnings.catch_warnings():
warnings.simplefilter("ignore", DeprecationWarning)
obj2.copy(doc3)
obj_u2.copy(doc3)
obj3 = doc3.find(obj_name)
obj_u3 = doc3.find(obj_unregistered_name)
# The lists are necessarily unordered because of RDF
self.assertCountEqual([False, True], obj3.foo_bool)
unregistered_values = obj_u3._properties['https://github.com/synbiodex/pysbol3#customBool']
self.assertEqual(['true'], [str(x) for x in unregistered_values])

def test_none_identity(self):
# Make sure a ValueError is raised if None is passed
Expand Down