From a45903d79838cd538e3c0976b0b725b2eba4aa65 Mon Sep 17 00:00:00 2001 From: Rob Sanderson Date: Thu, 16 May 2019 13:52:49 -0700 Subject: [PATCH] Allow explicit bnodes --- README.md | 13 +++++++++++-- cromulent/model.py | 11 +++++++---- tests/test_model.py | 30 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 73b4a2a..bab3576 100644 --- a/README.md +++ b/README.md @@ -18,12 +18,20 @@ Import the classes from the model module. As the classes are dynamically generat ```python from cromulent.model import factory, Group -g1 = Group("Organization") -g2 = Group("Department") +g1 = Group(ident="Organization") +g2 = Group(ident="Department") g1.member = g2 print factory.toString(g1, compact=False) ``` +The constructor for the classes takes the following parameters: + +* `ident` - an identifier to use for this instance. If specified, it should be a URI represented as a string. If it is the empty string, it will result in no identifier. If not specified, or specified as `None`, then it will be auto-generated by the factory if `auto_assign_id` is true, or if `auto_assign_id` is false, then it will result in no identifier. +* `label` - a human readable label for the resource, to act as internal documentation for the data +* `value` or `content` - a data value for the class. Dimensions and MonetaryAmounts use `value` which must be a number, and Name, Identifier, LinguisticObject and similar use `content` which must be a string. +* Additional keywords may be passed in, and will be sent to class-specific initialization code. + + ### Vocabulary ```python @@ -38,6 +46,7 @@ print factory.toString(h, compact=False) * Assigning to the same property repeatedly does NOT overwrite the value, instead it appends. To overwrite a value, instead set it to a false value first. + ### Factory settings There are quite a few settings for how the module works, which are managed by a `factory` object. diff --git a/cromulent/model.py b/cromulent/model.py index f5ab3ae..05e9034 100644 --- a/cromulent/model.py +++ b/cromulent/model.py @@ -358,9 +358,9 @@ class ExternalResource(object): _type = "" _embed = True - def __init__(self, ident=""): + def __init__(self, ident=None): self._factory = factory - if ident: + if ident is not None: if ident.startswith('urn:uuid'): self.id = ident elif ident.startswith('http'): @@ -378,6 +378,9 @@ def __init__(self, ident=""): ident = "%s:%s" % (self._factory.prefixes_rev[pref], rest) self.id = ident + elif ident == "": + # Allow explicit setting of empty string + self.id = "" else: # Allow for prefixed term curied = ident.split(':', 1) @@ -386,10 +389,10 @@ def __init__(self, ident=""): self._full_id = self._factory.prefixes[curied[0]] + curied[1] else: self.id = factory.base_url + self.__class__._uri_segment + "/" + ident - elif factory.auto_assign_id: self.id = factory.generate_id(self) else: + # Not auto assigning, and not submitted = blank node self.id = "" def _toJSON(self, done, top=None): @@ -408,7 +411,7 @@ class BaseResource(ExternalResource): _classification = "" _classhier = [] - def __init__(self, ident="", label="", value="", content="", **kw): + def __init__(self, ident=None, label="", value="", content="", **kw): """Initialize BaseObject.""" super(BaseResource, self).__init__(ident) diff --git a/tests/test_model.py b/tests/test_model.py index 5500935..657899b 100644 --- a/tests/test_model.py +++ b/tests/test_model.py @@ -210,17 +210,20 @@ def test_build_class(self): class TestAutoIdentifiers(unittest.TestCase): def test_bad_autoid(self): + model.factory.auto_assign_id = True model.factory.auto_id_type = "broken" self.assertRaises(model.ConfigurationError, model.factory.generate_id, "irrelevant") def test_int(self): + model.factory.auto_assign_id = True model.factory.auto_id_type = "int" p = model.Person() p2 = model.Activity() self.assertEqual(int(p.id[-1]), int(p2.id[-1])-1) def test_int_per_type(self): + model.factory.auto_assign_id = True model.factory.auto_id_type = "int-per-type" p = model.Person() p2 = model.Person() @@ -229,6 +232,7 @@ def test_int_per_type(self): self.assertEqual(int(p.id[-1]), int(p3.id[-1])) def test_int_per_segment(self): + model.factory.auto_assign_id = True model.factory._auto_id_segments = {} model.factory.auto_id_type = "int-per-segment" model.Activity._uri_segment = model.Person._uri_segment @@ -239,6 +243,7 @@ def test_int_per_segment(self): self.assertEqual(int(p.id[-1]), int(p3.id[-1])) def test_uuid(self): + model.factory.auto_assign_id = True model.factory.auto_id_type = "uuid" p = model.Person() self.assertTrue(p.id.startswith('urn:uuid:')) @@ -254,6 +259,31 @@ def test_prefixes(self): p4 = model.Person('fish:4') self.assertTrue(p4.id.startswith(model.factory.base_url)) + def test_no_ident(self): + + model.factory.auto_assign_id = True + p1 = model.Person() # auto assigned + p2 = model.Person(ident=None) # auto assigned + p3 = model.Person(ident="") # bnode explicitly + + self.assertTrue(p1.id.startswith('http')) + self.assertTrue(p2.id.startswith('http')) + self.assertEqual(p3.id, '') + + model.factory.auto_assign_id = False + p4 = model.Person() # bnode is default + p5 = model.Person(ident=None) # bnode is default + p6 = model.Person(ident="") # bnode explicitly + + self.assertEqual(p4.id, '') + self.assertEqual(p5.id, '') + self.assertEqual(p6.id, '') + + + + + + class TestBaseResource(unittest.TestCase):