Skip to content

Commit

Permalink
Merge pull request #430 from SynBioDex/copy-custom-toplevel
Browse files Browse the repository at this point in the history
Support copy of custom classes
  • Loading branch information
jakebeal authored Apr 11, 2023
2 parents f864ff5 + 5fbc4d9 commit c84ccd1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
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

0 comments on commit c84ccd1

Please sign in to comment.