import os import datetime from django.contrib.auth.models import User from django.core import management from django.test.client import RequestFactory, Client from django.test.utils import captured_stdout from django.urls import reverse from django.db import connection from tests.base_test import ArchesTestCase, CREATE_TOKEN_SQL, DELETE_TOKEN_SQL from arches.app.utils.skos import SKOSReader from arches.app.models.graph import Graph from arches.app.models.models import TileModel from arches.app.utils.betterJSONSerializer import JSONDeserializer from arches.app.utils.data_management.resources.importer import BusinessDataImporter from arches.app.utils.data_management.resource_graphs.importer import ( import_graph as ResourceGraphImporter, ) from arches.app.utils.data_management.resources.formats import rdffile from arches.app.utils.data_management.resources.formats.rdffile import JsonLdReader from pyld.jsonld import expand # these tests can be run from the command line via # python manage.py test tests.importer.jsonld_import_tests --settings="tests.test_settings" class JsonLDImportTests(ArchesTestCase): @classmethod def setUpTestData(cls): super().setUpTestData() cls.factory = RequestFactory() cls.token = "abc123" cls.client = Client(HTTP_AUTHORIZATION="Bearer %s" % cls.token) sql_str = CREATE_TOKEN_SQL.format(token=cls.token, user_id=1) with connection.cursor() as cursor: cursor.execute(sql_str) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/jsonld_test_thesaurus.xml") ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file( "tests/fixtures/jsonld_base/rdm/jsonld_test_collections.xml" ) ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5098-thesaurus.xml") ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5098-collections.xml") ret = skos.save_concepts_from_skos(rdf) # Load up the models and data only once with open( os.path.join("tests/fixtures/jsonld_base/models/test_1_basic_object.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join( "tests/fixtures/jsonld_base/models/test_1_basic_object_cardinality_n.json" ), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join( "tests/fixtures/jsonld_base/models/test_2_complex_object.json" ), "r", ) as f: archesfile2 = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile2["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/timezone_test.json"), "r" ) as f: archesfile2 = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile2["graph"]) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5098-thesaurus.xml") ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5098-collections.xml") ret = skos.save_concepts_from_skos(rdf) with open( os.path.join("tests/fixtures/jsonld_base/models/5098_concept_list.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) management.call_command( "datatype", "register", source="tests/fixtures/datatypes/color.py" ) management.call_command( "datatype", "register", source="tests/fixtures/datatypes/semantic_like.py" ) with open( os.path.join("tests/fixtures/jsonld_base/models/5299-basic.json"), "r" ) as f: archesfile2 = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile2["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/5299_complex.json"), "r" ) as f: archesfile2 = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile2["graph"]) skos = SKOSReader() rdf = skos.read_file( "tests/fixtures/jsonld_base/rdm/5600-external-thesaurus.xml" ) ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file( "tests/fixtures/jsonld_base/rdm/5600-external-collections.xml" ) ret = skos.save_concepts_from_skos(rdf) # Load up the models and data only once with open( os.path.join("tests/fixtures/jsonld_base/models/5121_false_ambiguity.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/5121_external_model.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/6235_parenttile_id.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/Person.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/nest_test.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join( "tests/fixtures/jsonld_base/models/required_ambiguous_nodes.json" ), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) for graph_id in [ "bf734b4e-f6b5-11e9-8f09-a4d18cec433a", "f13f8a92-3e76-11ec-9a49-faffc210b420", "37b50648-78ef-11ec-9508-faffc210b420", ]: graph = Graph.objects.get(pk=graph_id) graph.publish(user=User.objects.get(pk=1)) @classmethod def tearDownClass(cls): with connection.cursor() as cursor: cursor.execute(DELETE_TOKEN_SQL) super().tearDownClass() def setUp(self): pass def tearDown(self): pass def _create_url(self, graph_id, resource_id): base_url = reverse( "resources_graphid", kwargs={"graphid": graph_id, "resourceid": resource_id}, ) return base_url + "?format=json-ld" def test_context_caching(self): data = { "@context": "https://linked.art/ns/v1/linked-art.json", "id": "https://linked.art/example/object/3", "type": "HumanMadeObject", "_label": "Black and White Photograph of 'St. Sebastian'", "classified_as": [ { "id": "http://vocab.getty.edu/aat/300128359", "type": "Type", "_label": "Black and White Photograph", } ], } fetch = rdffile.fetch def tempFetch(url): raise Exception("This should not happen becauase we cached the doc") # rdffile.fetch = tempFetch # # first we test that we can override the fetch function and confirm that it gets called # with self.assertRaises(Exception): # jsonld_document = expand(data) # now set the function back and test normally rdffile.fetch = fetch jsonld_document = expand(data) self.assertTrue(data["@context"] in rdffile.docCache) # now set it to the temp fetch and confirm that the tempFetch isn't called on subsequent uses as it was initially rdffile.fetch = tempFetch jsonld_document = expand(data) rdffile.fetch = fetch # now invalidate the cache and make sure it refreshes the doc rdffile.docCache[data["@context"]]["expires"] = datetime.datetime.now() jsonld_document = expand(data) self.assertTrue( rdffile.docCache[data["@context"]]["expires"] > datetime.datetime.now() ) self.assertTrue(data["@context"] in rdffile.docCache) def test_literal_cardinality_failure(self): """Multiple literals without language should fail to import to card 1 node.""" data = """{ "@id": "http://localhost:8000/resources/221d1154-fa8e-11e9-9cbb-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": ["test!", "prueba!"] }""" graph_id = "bf734b4e-f6b5-11e9-8f09-a4d18cec433a" resource_id = "221d1154-fa8e-11e9-9cbb-3af9d3b32b71" with self.assertRaises(ValueError): data = JSONDeserializer().deserialize(data) reader = JsonLdReader() # import ipdb; ipdb.sset_trace() with captured_stdout(): reader.read_resource(data, resourceid=resource_id, graphid=graph_id) def test_1_basic_import(self): """Plain string should import and be automatically converted to i18n string of default language""" data = """{ "@id": "http://localhost:8000/resources/221d1154-fa8e-11e9-9cbb-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "test!" }""" url = self._create_url( graph_id="bf734b4e-f6b5-11e9-8f09-a4d18cec433a", resource_id="221d1154-fa8e-11e9-9cbb-3af9d3b32b71", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if isinstance(js, list): js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/221d1154-fa8e-11e9-9cbb-3af9d3b32b71" ) self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P3_has_note" in js) self.assertTrue( js["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"]["@value"] == "test!" ) def test_1_basic_import_with_language(self): """Add language values to jsonld and test import with a cardinality 1 node.""" data = """{ "@id": "http://localhost:8000/resources/221d1154-fa8e-11e9-9cbb-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [{"@value": "test!", "@language": "en"}, {"@value": "prueba!", "@language": "es"}] }""" url = self._create_url( graph_id="bf734b4e-f6b5-11e9-8f09-a4d18cec433a", resource_id="221d1154-fa8e-11e9-9cbb-3af9d3b32b71", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if isinstance(js, list): js = js[0] self.assertTrue("@id" in js) self.assertEqual( js["@id"], "http://localhost:8000/resources/221d1154-fa8e-11e9-9cbb-3af9d3b32b71", ) self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P3_has_note" in js) self.assertEqual( set( note["@language"] for note in js["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"] ), set(["en", "es"]), ) self.assertEqual( set( note["@value"] for note in js["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"] ), set(["prueba!", "test!"]), ) def test_1_basic_import_with_language_cardinality_n(self): """Add language values to jsonld and test import with a cardinality n node.""" data = """{ "@id": "http://localhost:8000/resources/b94b8bc3-ab26-4b0a-8080-9e8bde2979b4", "@type": "http://www.cidoc-crm.org/cidoc-crm/E1_CRM_Entity", "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": [ { "@id": "http://localhost:8000/tile/4d788140-cefe-4856-9266-4d7e75cefceb/node/abd41efa-7968-11ec-80f9-faffc210b420", "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ {"@language": "es","@value": "Azul"}, {"@language": "en","@value": "Blue"} ] }, { "@id": "http://localhost:8000/tile/610cb383-222b-47e0-906f-8b303bb1b20b/node/abd41efa-7968-11ec-80f9-faffc210b420", "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ {"@language": "es", "@value": "Blanco"}, {"@language": "en", "@value": "White"} ] } ] }""" url = self._create_url( graph_id="37b50648-78ef-11ec-9508-faffc210b420", resource_id="b94b8bc3-ab26-4b0a-8080-9e8bde2979b4", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if isinstance(js, list): js = js[0] P1_is_identified = "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by" P3_has_note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" self.assertTrue("@id" in js) self.assertEqual( js["@id"], "http://localhost:8000/resources/b94b8bc3-ab26-4b0a-8080-9e8bde2979b4", ) languages = set() values = set() for identifier in js[P1_is_identified]: self.assertTrue(isinstance(identifier[P3_has_note], list)) for note in identifier[P3_has_note]: languages.add(note["@language"]) values.add(note["@value"]) self.assertEqual(languages, set(["en", "es"])) self.assertEqual(values, set(["White", "Blanco", "Azul", "Blue"])) def test_1b_basic_post(self): data = """{ "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "test!" }""" url = self._create_url( graph_id="bf734b4e-f6b5-11e9-8f09-a4d18cec433a", resource_id="", ) response = self.client.post( url, data=data, content_type="application/json", HTTP_AUTHORIZATION=f"Bearer {self.token}", ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P3_has_note" in js) self.assertTrue( js["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"]["@value"] == "test!" ) def test_2_complex_import_data(self): # Note that this tests #5136, as the P101 -> P2 is a concept with a concept data = """ { "@id": "http://localhost:8000/resources/12345678-abcd-11e9-9cbb-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P101_had_as_general_use": { "@id": "http://localhost:8000/concepts/fb457e76-e018-41e7-9be3-0f986816450a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/14c92c17-5e2f-413a-95c2-3c5e41ee87d2", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Meta Type A" }, "http://www.w3.org/2000/01/rdf-schema#label": "Test Type A" }, "http://www.cidoc-crm.org/cidoc-crm/P160_has_temporal_projection": { "@id": "http://localhost:8000/tile/9c1ec6b9-1094-427f-acf6-e9c3fca643b6/node/127193ea-fa6d-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by": "example", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-10-01" } }, "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/6bac5802-a6f8-427c-ba5f-d4b30d5b070e", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Single Type A" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Test Data", "http://www.cidoc-crm.org/cidoc-crm/P45_consists_of": [ { "@id": "http://localhost:8000/concepts/9b61c995-71d8-4bce-987b-0ffa3da4c71c", "@type": "http://www.cidoc-crm.org/cidoc-crm/E57_Material", "http://www.w3.org/2000/01/rdf-schema#label": "material b" }, { "@id": "http://localhost:8000/concepts/36c8d7a3-32e7-49e4-bd4c-2169a06b240a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E57_Material", "http://www.w3.org/2000/01/rdf-schema#label": "material a" } ], "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts": 12 } """ url = self._create_url( graph_id="ee72fb1e-fa6c-11e9-b369-3af9d3b32b71", resource_id="12345678-abcd-11e9-9cbb-3af9d3b32b71", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/12345678-abcd-11e9-9cbb-3af9d3b32b71" ) hagu = "http://www.cidoc-crm.org/cidoc-crm/P101_had_as_general_use" p2 = "http://www.cidoc-crm.org/cidoc-crm/P2_has_type" temp = "http://www.cidoc-crm.org/cidoc-crm/P160_has_temporal_projection" qual = "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" pts = "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts" self.assertTrue(hagu in js) use = js[hagu] self.assertTrue("@id" in use) self.assertTrue( use["@id"] == "http://localhost:8000/concepts/fb457e76-e018-41e7-9be3-0f986816450a" ) self.assertTrue(p2 in use) self.assertTrue( use[p2]["@id"] == "http://localhost:8000/concepts/14c92c17-5e2f-413a-95c2-3c5e41ee87d2" ) self.assertTrue(temp in js) proj = js[temp] self.assertTrue(qual in proj) self.assertTrue(proj[qual]["@value"] == "example") self.assertTrue(note in js) self.assertTrue(js[note]["@value"] == "Test Data") self.assertTrue(pts in js) self.assertTrue(js[pts] == 12) def test_2b_complex_multiple(self): data = """ { "@id": "http://localhost:8000/resources/5e9baff0-109b-11ea-957a-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P101_had_as_general_use": { "@id": "http://localhost:8000/concepts/fb457e76-e018-41e7-9be3-0f986816450a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/dcd28b8a-0840-4a7f-a0d6-0341438552e6", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Meta Type B" }, "http://www.w3.org/2000/01/rdf-schema#label": "Test Type A" }, "http://www.cidoc-crm.org/cidoc-crm/P160_has_temporal_projection": [ { "@id": "http://localhost:8000/tile/7e0371da-c62f-46c1-899b-d1e9419a76d5/node/127193ea-fa6d-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by": "example 2" }, { "@id": "http://localhost:8000/tile/8cc347a4-265d-4a06-8327-e198e1d1d0c5/node/127193ea-fa6d-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by": "example", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "1903-10-28" } }, { "@id": "http://localhost:8000/tile/6011c512-47e9-46c3-b6f3-034dcc6f2a9d/node/127193ea-fa6d-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-11-15" } }, { "@id": "http://localhost:8000/tile/7d42af30-4d00-434f-95d4-7a3b3f9bfec8/node/127193ea-fa6d-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by": "example" } ], "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/6bac5802-a6f8-427c-ba5f-d4b30d5b070e", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Single Type A" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ "asdfasdfa", "1903-10-21" ], "http://www.cidoc-crm.org/cidoc-crm/P45_consists_of": { "@id": "http://localhost:8000/concepts/36c8d7a3-32e7-49e4-bd4c-2169a06b240a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E57_Material", "http://www.w3.org/2000/01/rdf-schema#label": "material a" }, "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts": [ 2, 1 ] } """ url = self._create_url( graph_id="ee72fb1e-fa6c-11e9-b369-3af9d3b32b71", resource_id="5e9baff0-109b-11ea-957a-acde48001122", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/5e9baff0-109b-11ea-957a-acde48001122" ) pts = "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" temp = "http://www.cidoc-crm.org/cidoc-crm/P160_has_temporal_projection" qual = "http://www.cidoc-crm.org/cidoc-crm/P79_beginning_is_qualified_by" botb = "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin" self.assertTrue(pts in js) self.assertTrue(set(js[pts]) == set([1, 2])) self.assertTrue(note in js) self.assertTrue( set(x["@value"] for x in js[note]) == set(["asdfasdfa", "1903-10-21"]) ) self.assertTrue(temp in js) temps = js[temp] self.assertTrue(len(temps) == 4) for t in temps: if qual in t: self.assertTrue(t[qual]["@value"] in ["example", "example 2"]) if botb in t: self.assertTrue(t[botb]["@value"] in ["2019-11-15", "1903-10-28"]) def test_3_5098_concepts(self): data = """ { "@id": "http://localhost:8000/resources/0b4439a8-beca-11e9-b4dc-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": { "@id": "http://localhost:8000/tile/cad329aa-1802-416e-bbce-5f71e21b1a47/node/accb030c-bec9-11e9-b4dc-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": [ { "@id": "http://localhost:8000/concepts/c3c4b8a8-39bb-41e7-af45-3a0c60fa4ddf", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Concept 2" }, { "@id": "http://localhost:8000/concepts/0bb450bc-8fe3-46cb-968e-2b56849e6e96", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Concept 1" } ] } } """ url = self._create_url( graph_id="92ccf5aa-bec9-11e9-bd39-0242ac160002", resource_id="0b4439a8-beca-11e9-b4dc-0242ac160002", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got JSON for test 3: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/0b4439a8-beca-11e9-b4dc-0242ac160002" ) types = js["http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by"][ "http://www.cidoc-crm.org/cidoc-crm/P2_has_type" ] self.assertTrue(type(types) == list) self.assertTrue(len(types) == 2) cids = [ "http://localhost:8000/concepts/c3c4b8a8-39bb-41e7-af45-3a0c60fa4ddf", "http://localhost:8000/concepts/0bb450bc-8fe3-46cb-968e-2b56849e6e96", ] self.assertTrue(types[0]["@id"] in cids) self.assertTrue(types[1]["@id"] in cids) self.assertTrue(types[0]["@id"] != types[1]["@id"]) def test_4_5098_resinst(self): # Make instances for this new one to reference with captured_stdout(): BusinessDataImporter( "tests/fixtures/jsonld_base/data/test_2_instances.json" ).import_business_data() data = """ { "@id": "http://localhost:8000/resources/abcd1234-1234-1129-b6e7-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P130_shows_features_of": [ { "@id": "http://localhost:8000/resources/12bbf5bc-fa85-11e9-91b8-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object" }, { "@id": "http://localhost:8000/resources/24d0d25a-fa75-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object" } ], "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "res inst list import" } """ url = self._create_url( graph_id="ee72fb1e-fa6c-11e9-b369-3af9d3b32b71", resource_id="abcd1234-1234-1129-b6e7-3af9d3b32b71", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 4: {response.content}") self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got json for test 4: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/abcd1234-1234-1129-b6e7-3af9d3b32b71" ) self.assertTrue( "http://www.cidoc-crm.org/cidoc-crm/P130_shows_features_of" in js ) feats = js["http://www.cidoc-crm.org/cidoc-crm/P130_shows_features_of"] self.assertTrue(type(feats) == list) self.assertTrue(len(feats) == 2) rids = [ "http://localhost:8000/resources/12bbf5bc-fa85-11e9-91b8-3af9d3b32b71", "http://localhost:8000/resources/24d0d25a-fa75-11e9-b369-3af9d3b32b71", ] self.assertTrue(feats[0]["@id"] in rids) self.assertTrue(feats[1]["@id"] in rids) # test that the default ontologyProperties and inverseOntologyProperties are used tiles = TileModel.objects.filter( resourceinstance_id="abcd1234-1234-1129-b6e7-3af9d3b32b71" ) for tile in tiles: if "ae93f844-fa6d-11e9-b369-3af9d3b32b71" in tile.data: self.assertEqual( tile.data["ae93f844-fa6d-11e9-b369-3af9d3b32b71"][0][ "ontologyProperty" ], "http://www.cidoc-crm.org/cidoc-crm/P62_depicts", ) self.assertEqual( tile.data["ae93f844-fa6d-11e9-b369-3af9d3b32b71"][0][ "inverseOntologyProperty" ], "http://www.cidoc-crm.org/cidoc-crm/P62i_is_depicted_by", ) def test_5_5098_resinst_branch(self): # 2019-11-01 - Conversely this fails, as it is in a branch with captured_stdout(): BusinessDataImporter( "tests/fixtures/jsonld_base/data/test_2_instances.json" ).import_business_data() data = """ { "@id": "http://localhost:8000/resources/7fffffff-faa1-11e9-84de-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": { "@id": "http://localhost:8000/tile/a4896405-5c73-49f4-abd3-651911e82fde/node/51c3ede8-faa1-11e9-84de-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P128i_is_carried_by": [ { "@id": "http://localhost:8000/resources/24d0d25a-fa75-11e9-b369-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object" }, { "@id": "http://localhost:8000/resources/12bbf5bc-fa85-11e9-91b8-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object" } ] } } """ # Load up the models and data only once with open( os.path.join("tests/fixtures/jsonld_base/models/5098_b_resinst.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) url = self._create_url( graph_id="40dbcffa-faa1-11e9-84de-3af9d3b32b71", resource_id="7fffffff-faa1-11e9-84de-3af9d3b32b71", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got json for test 5: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/7fffffff-faa1-11e9-84de-3af9d3b32b71" ) self.assertTrue( "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by" in js ) feats = js["http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by"][ "http://www.cidoc-crm.org/cidoc-crm/P128i_is_carried_by" ] self.assertTrue(type(feats) == list) self.assertTrue(len(feats) == 2) def test_6_5126_collection_filter(self): # 2019-11-01 - Fails due to #5126, the concept is not checked against the collection skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5126-thesaurus.xml") ret = skos.save_concepts_from_skos(rdf) skos = SKOSReader() rdf = skos.read_file("tests/fixtures/jsonld_base/rdm/5126-collections.xml") ret = skos.save_concepts_from_skos(rdf) # Load up the models and data only once with open( os.path.join( "tests/fixtures/jsonld_base/models/5126_collection_ambiguity.json" ), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) data = """ { "@id": "http://localhost:8000/resources/69a4af50-c055-11e9-b4dc-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://vocab.getty.edu/aat/300404216", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "aquarelles (paintings)" } } """ url = self._create_url( graph_id="09e3dc8a-c055-11e9-b4dc-0242ac160002", resource_id="69a4af50-c055-11e9-b4dc-0242ac160002", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 6 response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got JSON for test 6: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/69a4af50-c055-11e9-b4dc-0242ac160002" ) self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P2_has_type" in js) typ = js["http://www.cidoc-crm.org/cidoc-crm/P2_has_type"] self.assertTrue(typ["@id"] == "http://vocab.getty.edu/aat/300404216") def test_7_5121_branches(self): # 2019-11-01 - This fails due to #5121, the presence of content is not used to rule out the resource-instance branch data = """ { "@id": "http://localhost:8000/resources/87654321-c000-1100-b400-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": { "@id": "http://localhost:8000/tile/17fa1306-d48f-434e-ad37-fc4c9b09d979/node/d1af9e9e-bf96-11e9-b4dc-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/0bb450bc-8fe3-46cb-968e-2b56849e6e96", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Concept 1" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Test Content" } } """ url = self._create_url( graph_id="9f716aa2-bf96-11e9-bd39-0242ac160002", resource_id="87654321-c000-1100-b400-0242ac160002", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 7 response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got JSON for test 7: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/87654321-c000-1100-b400-0242ac160002" ) lo = js["http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by"] self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P3_has_note" in lo) self.assertTrue( lo["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"]["@value"] == "Test Content" ) def test_7b_5121_branches(self): # This loads the referenced resource, 2a615f66...001122 with captured_stdout(): BusinessDataImporter( "tests/fixtures/jsonld_base/data/test_5121b_reference_instances.json" ).import_business_data() # The third node is the resource-instance, as has_note is required in the semantic branch # So none of the three nodes are ambiguous and should all load at the same time data = """ { "@id": "http://localhost:8000/resources/87654321-c000-1100-b400-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": [{ "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/0bb450bc-8fe3-46cb-968e-2b56849e6e96", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "Concept 1" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Test Content" }, { "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "No Concept, still unique" }, { "@id": "http://localhost:8000/resources/2a615f66-114d-11ea-8de7-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object" }] } """ url = self._create_url( graph_id="9f716aa2-bf96-11e9-bd39-0242ac160002", resource_id="87654321-c000-1100-b400-0242ac160002", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 7b response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] rtb = "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" self.assertTrue(rtb in js) self.assertEqual(len(js[rtb]), 3) for r in js[rtb]: hasnote = note in r isres = r["@id"].startswith("http://localhost:8000/resources/") self.assertTrue((hasnote and not isres) or (isres and not hasnote)) self.assertTrue(not (hasnote and isres)) def test_8_4564_resinst_models(self): with open( os.path.join("tests/fixtures/jsonld_base/models/4564-person.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/4564-group.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) with open( os.path.join("tests/fixtures/jsonld_base/models/4564-referenced.json"), "r" ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) aux_data = """ { "@id": "http://localhost:8000/resources/923a5fa8-bfa8-11e9-bd39-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E74_Group", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Test Group" } """ url = self._create_url( graph_id="2c03ddcc-bfa8-11e9-b4dc-0242ac160002", resource_id="923a5fa8-bfa8-11e9-bd39-0242ac160002", ) response = self.client.put( url, data=aux_data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertTrue(response.status_code == 201) data = """ { "@id": "http://localhost:8000/resources/940a2c82-bfa8-11e9-bd39-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P51_has_former_or_current_owner": { "@id": "http://localhost:8000/resources/923a5fa8-bfa8-11e9-bd39-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E74_Group" } } """ url = self._create_url( graph_id="e3d4505e-bfa7-11e9-b4dc-0242ac160002", resource_id="940a2c82-bfa8-11e9-bd39-0242ac160002", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 8 response: {response.content}") # this does not currently work self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] # print(f"Got JSON for test 8: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/940a2c82-bfa8-11e9-bd39-0242ac160002" ) self.assertTrue( "http://www.cidoc-crm.org/cidoc-crm/P51_has_former_or_current_owner" in js ) owner = js["http://www.cidoc-crm.org/cidoc-crm/P51_has_former_or_current_owner"] self.assertTrue( owner["@id"] == "http://localhost:8000/resources/923a5fa8-bfa8-11e9-bd39-0242ac160002" ) def test_9_5299_basic(self): url = self._create_url( graph_id="0cadd978-071a-11ea-8d9a-acde48001122", resource_id="faceb004-dead-11e9-bd39-0242ac160002", ) data = """ { "@id": "http://localhost:8000/resources/faceb004-dead-11e9-bd39-0242ac160002", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by": { "@id": "http://localhost:8000/tile/1580cf8b-1ead-42b7-a22a-cc92bff0aafb/node/1ae420ba-071a-11ea-8d9a-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Production" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "#ff00ff" } """ response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 9 response: {response.content}") self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] prod = "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/faceb004-dead-11e9-bd39-0242ac160002" ) self.assertTrue(prod in js) prodjs = js[prod] self.assertTrue(note in prodjs) self.assertTrue(prodjs[note]["@value"] == "Production") self.assertTrue(note in js) self.assertTrue(js[note] == "#ff00ff") def test_a_5299_complex(self): url = self._create_url( graph_id="f348bbda-0721-11ea-b628-acde48001122", resource_id="deadface-0000-11e9-bd39-0242ac160002", ) data = """ { "@id": "http://localhost:8000/resources/deadface-0000-11ea-b628-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P10i_contains": [ { "@type": "http://www.cidoc-crm.org/cidoc-crm/E4_Period", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "Import Note" }, { "@type": "http://www.cidoc-crm.org/cidoc-crm/E4_Period", "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2018-01-01" } } } ] } } """ response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"Test 9 response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/deadface-0000-11e9-bd39-0242ac160002" ) prod = "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" conts = "http://www.cidoc-crm.org/cidoc-crm/P10i_contains" ts = "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span" botb = "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin" prodjs = js[prod] contl = prodjs[conts] self.assertTrue(len(contl) == 2) if note in contl[0]: # print(f"note data: {contl[0]}") self.assertTrue(contl[0][note]["@value"] == "Import Note") jsts = contl[1][ts] else: # print(f"note data: {contl[1]}") self.assertTrue(contl[1][note]["@value"] == "Import Note") jsts = contl[0][ts] self.assertTrue(jsts[botb]["@value"] == "2018-01-01") def test_b_5600_concept_label(self): with open( os.path.join("tests/fixtures/jsonld_base/models/5600-external-label.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) data = """ { "@id": "http://localhost:8000/resources/61787e78-0e3f-11ea-b4f1-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E42_Identifier", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "madonna bla bla", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "sale bla bla" } }, "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://vocab.getty.edu/aat/300033898", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "History" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "visual work of madonna bla bla" } """ url = self._create_url( graph_id="9d2c2ca0-0e3d-11ea-b4f1-acde48001122", resource_id="61787e78-0e3f-11ea-b4f1-acde48001122", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"\n\n\nTest b response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/61787e78-0e3f-11ea-b4f1-acde48001122" ) def test_c_path_with_array(self): with open( os.path.join("tests/fixtures/jsonld_base/models/string_to_path_basic.json"), "r", ) as f: archesfile = JSONDeserializer().deserialize(f) ResourceGraphImporter(archesfile["graph"]) data = """ { "@id": "http://localhost:8000/resources/5683f462-107d-11ea-b7e9-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person", "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": [ { "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "babo pour la russie" }, { "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://vocab.getty.edu/aat/300033898", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "History" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "remy" } ], "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "remy" } """ url = self._create_url( graph_id="d5456066-107c-11ea-b7e9-acde48001122", resource_id="5683f462-107d-11ea-b7e9-acde48001122", ) with captured_stdout(): response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) # print(f"\n\n\nTest c response: {response.content}") self.assertTrue(response.status_code == 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/5683f462-107d-11ea-b7e9-acde48001122" ) idby = "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by" self.assertTrue(idby in js) self.assertTrue(len(js[idby]) == 2) results = [] for note in js[idby]: results.append(note["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"]) # result = note["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"] # if "remy" in result: # self.assertDictEqual(result, {'@language': 'en', '@value': 'remy'}) # else: # self.assertDictEqual(result, {'@language': 'en', '@value': 'babo pour la russie'}) # results.append(note["http://www.cidoc-crm.org/cidoc-crm/P3_has_note"]) self.assertCountEqual( [ {"@language": "en", "@value": "remy"}, {"@language": "en", "@value": "babo pour la russie"}, ], results, ) def test_d_path_with_array_2(self): data = """ { "@id": "http://localhost:8000/resources/10000000-109b-11ea-957a-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts": [ 2, 1 ] } """ url = self._create_url( graph_id="ee72fb1e-fa6c-11e9-b369-3af9d3b32b71", resource_id="10000000-109b-11ea-957a-acde48001122", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/10000000-109b-11ea-957a-acde48001122" ) pts = "http://www.cidoc-crm.org/cidoc-crm/P57_has_number_of_parts" self.assertTrue(pts in js) self.assertTrue(set(js[pts]) == set([1, 2])) def test_e_path_with_array_resinst(self): # 2019-11-27 - Passing with extra @id checks in rdffile data = """ { "@id": "http://localhost:8000/resources/8e870000-114e-11ea-8de7-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person", "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": [ { "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "test 1" }, { "@id": "http://localhost:8000/resources/2a615f66-114d-11ea-8de7-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object" } ] } """ url = self._create_url( graph_id="9f716aa2-bf96-11e9-bd39-0242ac160002", resource_id="8e870000-114e-11ea-8de7-acde48001122", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/8e870000-114e-11ea-8de7-acde48001122" ) rtb = "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by" note = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" self.assertTrue(rtb in js) self.assertEqual(len(js[rtb]), 2) rtb1 = js[rtb][0] rtb2 = js[rtb][1] if note in rtb1: self.assertTrue(rtb2["@id"].startswith("http://localhost:8000/resources")) else: self.assertTrue(rtb1["@id"].startswith("http://localhost:8000/resources")) def test_f_big_nest_mess(self): data = """ { "@id": "http://localhost:8000/resources/c3b693cc-1542-11ea-b353-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by": [ { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P10_falls_within": [ { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P14_carried_out_by": { "@id": "http://localhost:8000/resources/5e9baff0-109b-11ea-957a-acde48001122", "@type": "http://www.cidoc-crm.org/cidoc-crm/E21_Person" }, "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "asdf", "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-12-03" }, "http://www.cidoc-crm.org/cidoc-crm/P82b_end_of_the_end": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-12-05" }, "http://www.cidoc-crm.org/cidoc-crm/P83_had_at_least_duration": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E54_Dimension", "http://www.cidoc-crm.org/cidoc-crm/P90_has_value": 1 } } }, { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "second part", "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P83_had_at_least_duration": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E54_Dimension", "http://www.cidoc-crm.org/cidoc-crm/P90_has_value": 6 } } } ] }, { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P10_falls_within": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "bar", "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-12-07" }, "http://www.cidoc-crm.org/cidoc-crm/P82b_end_of_the_end": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2019-12-08" } } } } ], "http://www.cidoc-crm.org/cidoc-crm/P138i_has_representation": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E36_Visual_Item", "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": { "@id": "http://localhost:8000/concepts/36c8d7a3-32e7-49e4-bd4c-2169a06b240a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E55_Type", "http://www.w3.org/2000/01/rdf-schema#label": "material a" } } } """ url = self._create_url( graph_id="9b596906-1540-11ea-b353-acde48001122", resource_id="c3b693cc-1542-11ea-b353-acde48001122", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) def get_tiles_by_nodegroup(tiles, nodegroupid, nodeid=None, nodevalue=None): ret = [] for tile in tiles: if str(tile.nodegroup_id) == str(nodegroupid): if nodeid in tile.data and tile.data[nodeid] == nodevalue: return tile else: ret.append(tile) return ret def get_tile_by_id(tiles, tileid): for tile in tiles: if tile.tileid == tileid: return tile tiles = TileModel.objects.filter( resourceinstance_id="c3b693cc-1542-11ea-b353-acde48001122" ) self.assertEqual(len(tiles), 11) tile1 = get_tiles_by_nodegroup( tiles, "e717dda0-1540-11ea-b353-acde48001122", "f025e108-1540-11ea-b353-acde48001122", 6, ) tile1_parent = get_tile_by_id(tiles, tile1.parenttile_id) self.assertEqual(tile1_parent.data, {}) tile1_grandparent = get_tile_by_id(tiles, tile1_parent.parenttile_id) self.assertEqual( tile1_grandparent.data["02ec0ace-1541-11ea-b353-acde48001122"]["en"], {"direction": "ltr", "value": "second part"}, ) tile2 = get_tiles_by_nodegroup( tiles, "e717dda0-1540-11ea-b353-acde48001122", "f025e108-1540-11ea-b353-acde48001122", 1, ) tile2_parent = get_tile_by_id(tiles, tile2.parenttile_id) self.assertEqual( tile2_parent.data, { "d155a4c0-1540-11ea-b353-acde48001122": "2019-12-03", "ddc44d9c-1540-11ea-b353-acde48001122": "2019-12-05", }, ) tile2_grandparent = get_tile_by_id(tiles, tile2_parent.parenttile_id) self.assertEqual( tile2_grandparent.data["02ec0ace-1541-11ea-b353-acde48001122"]["en"], {"direction": "ltr", "value": "asdf"}, ) self.assertEqual( tile2_grandparent.data["26927e22-1541-11ea-b353-acde48001122"][0][ "resourceId" ], "5e9baff0-109b-11ea-957a-acde48001122", ) tile2_greatgrandparent = get_tile_by_id(tiles, tile2_grandparent.parenttile_id) self.assertEqual(tile2_greatgrandparent.data, {}) tile1_greatgrandparent = get_tile_by_id(tiles, tile1_grandparent.parenttile_id) self.assertEqual(tile2_greatgrandparent, tile1_greatgrandparent) tile3 = get_tiles_by_nodegroup( tiles, "c5a9174c-1540-11ea-b353-acde48001122", "d155a4c0-1540-11ea-b353-acde48001122", "2019-12-07", ) self.assertEqual( tile3.data, { "d155a4c0-1540-11ea-b353-acde48001122": "2019-12-07", "ddc44d9c-1540-11ea-b353-acde48001122": "2019-12-08", }, ) tile3_parent = get_tile_by_id(tiles, tile3.parenttile_id) self.assertEqual( tile3_parent.data["02ec0ace-1541-11ea-b353-acde48001122"]["en"], {"direction": "ltr", "value": "bar"}, ) tile3_grandparent = get_tile_by_id(tiles, tile3_parent.parenttile_id) self.assertEqual(tile3_grandparent.data, {}) tile4 = get_tiles_by_nodegroup(tiles, "48f3ab3a-1541-11ea-b353-acde48001122")[0] self.assertEqual( tile4.data, { "54272cd4-1541-11ea-b353-acde48001122": [ "d2908ab9-19a6-4a82-953d-5ebe8d164e85" ], "8e08a496-1541-11ea-b353-acde48001122": None, }, ) def test_g_6235_parenttile(self): data = """{ "@id": "http://localhost:8000/resources/05f314d0-7a7b-4408-8d9b-f0b61f1fb27d", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "a" }, "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2020-07-08" } }, "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E33_Linguistic_Object", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "b" } }, "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": { "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": "test 1" } }""" url = self._create_url( graph_id="0bc001c2-c163-11ea-8354-3af9d3b32b71", resource_id="05f314d0-7a7b-4408-8d9b-f0b61f1fb27d", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertEqual(response.status_code, 201) js = response.json() if type(js) == list: js = js[0] # And validate that all three of E52, E33 and E41 are there prod = js["http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by"] self.assertTrue( "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by" in prod ) self.assertTrue("http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span" in prod) self.assertTrue( "http://www.cidoc-crm.org/cidoc-crm/P67i_is_referred_to_by" in prod ) def test_8181_import_bug(self): # this test and test_8181_import_bug_2 need to submit data in an exact order # which is why we call reader.read_resource directly with expand_data=False # see https://github.com/archesproject/arches/issues/8181 data = { "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ {"@value": "ALLAN, DAVID"} ], "@id": "urn:uuid:0b0e214d-4601-3f73-bdc9-f27c8ad9e0de", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E21_Person"], "http://www.cidoc-crm.org/cidoc-crm/P14i_performed": [ { "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": [ { "http://www.w3.org/2000/01/rdf-schema#label": [ {"@value": "collecting"} ], "@id": "http://vocab.getty.edu/aat/300077121", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E55_Type"], } ], "@type": ["http://www.cidoc-crm.org/cidoc-crm/E7_Activity"], }, { "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": [ { "http://www.w3.org/2000/01/rdf-schema#label": [ {"@value": "creating (artistic activity)"} ], "@id": "http://vocab.getty.edu/aat/300404387", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E55_Type"], } ], "@type": ["http://www.cidoc-crm.org/cidoc-crm/E7_Activity"], }, ], } graph_id = "f13f8a92-3e76-11ec-9a49-faffc210b420" resource_id = "0b0e214d-4601-3f73-bdc9-f27c8ad9e0de" reader = JsonLdReader() reader.read_resource( data, resourceid=resource_id, graphid=graph_id, expand_data=False ) reader.resources[0].save() tiles = TileModel.objects.filter(resourceinstance_id=resource_id) self.assertEqual(len(tiles), 3) actual_tiledata = [] for tile in tiles: actual_tiledata.append(tile.data) expected_tiledata = [ { "f13ffd9c-3e76-11ec-9a49-faffc210b420": { "en": {"value": "ALLAN, DAVID", "direction": "ltr"} } }, { "f1420740-3e76-11ec-9a49-faffc210b420": None, "f1420f92-3e76-11ec-9a49-faffc210b420": None, "f1417e1a-3e76-11ec-9a49-faffc210b420": [ "b83cab06-1cfe-4aeb-9653-cb9f0cc45595" ], }, { "f1420740-3e76-11ec-9a49-faffc210b420": None, "f1420f92-3e76-11ec-9a49-faffc210b420": None, "f1417e1a-3e76-11ec-9a49-faffc210b420": [ "fc3559c4-03c4-428c-a48e-0f480c8a3751" ], }, ] self.assertCountEqual(actual_tiledata, expected_tiledata) def test_8181_import_bug_2(self): # this test is ostensibly the same as test_8181_import_bug with the only # difference being the order of the data in the json-ld document being submitted # without fix #8181 will fail in a different way which is a bit of a concern # this test and test_8181_import_bug need to submit data in an exact order # which is why we call reader.read_resource directly with expand_data=False # see https://github.com/archesproject/arches/issues/8181 data = { "http://www.cidoc-crm.org/cidoc-crm/P14i_performed": [ { "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": [ { "http://www.w3.org/2000/01/rdf-schema#label": [ {"@value": "collecting"} ], "@id": "http://vocab.getty.edu/aat/300077121", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E55_Type"], } ], "@type": ["http://www.cidoc-crm.org/cidoc-crm/E7_Activity"], }, { "http://www.cidoc-crm.org/cidoc-crm/P2_has_type": [ { "http://www.w3.org/2000/01/rdf-schema#label": [ {"@value": "creating (artistic activity)"} ], "@id": "http://vocab.getty.edu/aat/300404387", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E55_Type"], } ], "@type": ["http://www.cidoc-crm.org/cidoc-crm/E7_Activity"], }, ], "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ {"@value": "ALLAN, DAVID"} ], "@id": "urn:uuid:0b0e214d-4601-3f73-bdc9-f27c8ad9e0de", "@type": ["http://www.cidoc-crm.org/cidoc-crm/E21_Person"], } graph_id = "f13f8a92-3e76-11ec-9a49-faffc210b420" resource_id = "0b0e214d-4601-3f73-bdc9-f27c8ad9e0de" reader = JsonLdReader() reader.read_resource( data, resourceid=resource_id, graphid=graph_id, expand_data=False ) reader.resources[0].save() tiles = TileModel.objects.filter(resourceinstance_id=resource_id) self.assertEqual(len(tiles), 3) actual_tiledata = [] for tile in tiles: actual_tiledata.append(tile.data) expected_tiledata = [ { "f13ffd9c-3e76-11ec-9a49-faffc210b420": { "en": {"value": "ALLAN, DAVID", "direction": "ltr"} } }, { "f1420740-3e76-11ec-9a49-faffc210b420": None, "f1420f92-3e76-11ec-9a49-faffc210b420": None, "f1417e1a-3e76-11ec-9a49-faffc210b420": [ "b83cab06-1cfe-4aeb-9653-cb9f0cc45595" ], }, { "f1420740-3e76-11ec-9a49-faffc210b420": None, "f1420f92-3e76-11ec-9a49-faffc210b420": None, "f1417e1a-3e76-11ec-9a49-faffc210b420": [ "fc3559c4-03c4-428c-a48e-0f480c8a3751" ], }, ] self.assertCountEqual(actual_tiledata, expected_tiledata) def test_required_ambiguous_nodes(self): data = """ { "@id": "http://localhost:8000/resources/09f1d360-4271-49ea-b799-f1fdb57b634b", "@type": "http://www.cidoc-crm.org/cidoc-crm/E3_Condition_State", "http://www.cidoc-crm.org/cidoc-crm/P116i_is_started_by": { "@id": "http://localhost:8000/tile/30b5a44e-83dc-4393-ab71-a04b2b62bb8d/node/c10201c0-a1b7-11ed-86f1-faffc210b420", "@type": "http://www.cidoc-crm.org/cidoc-crm/E4_Period", "http://www.cidoc-crm.org/cidoc-crm/P117i_includes": { "@id": "http://localhost:8000/concepts/36c8d7a3-32e7-49e4-bd4c-2169a06b240a", "@type": "http://www.cidoc-crm.org/cidoc-crm/E5_Event", "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by": { "@id": "http://localhost:8000/tile/4cc161a3-b695-4dbf-a855-b08c65904f7a/node/98948e54-a1b9-11ed-86f1-faffc210b420", "@type": "http://www.cidoc-crm.org/cidoc-crm/E41_Appellation", "http://www.cidoc-crm.org/cidoc-crm/P102_has_title": { "@id": "http://localhost:8000/concepts/babcafca-138f-43e6-b32e-22050d482304", "@type": "http://www.cidoc-crm.org/cidoc-crm/E35_Title", "http://www.cidoc-crm.org/cidoc-crm/P3_has_note": [ { "@language": "en", "@value": "taco" } ], "http://www.w3.org/2000/01/rdf-schema#label": "spoken" } }, "http://www.w3.org/2000/01/rdf-schema#label": "material a" } } } """ url = self._create_url( graph_id="9e4f9e7a-27de-4683-b156-b3e0de9169c6", resource_id="09f1d360-4271-49ea-b799-f1fdb57b634b", ) response = self.client.put( url, data=data, HTTP_AUTHORIZATION=f"Bearer {self.token}" ) self.assertTrue(response.status_code == 201) tiles = TileModel.objects.filter( resourceinstance_id="09f1d360-4271-49ea-b799-f1fdb57b634b" ) self.assertEqual(len(tiles), 4) js = response.json() if type(js) == list: js = js[0] # print(f"Got JSON for test 7: {js}") self.assertTrue("@id" in js) self.assertTrue( js["@id"] == "http://localhost:8000/resources/09f1d360-4271-49ea-b799-f1fdb57b634b" ) l1 = "http://www.cidoc-crm.org/cidoc-crm/P116i_is_started_by" l2 = "http://www.cidoc-crm.org/cidoc-crm/P117i_includes" l3 = "http://www.cidoc-crm.org/cidoc-crm/P1_is_identified_by" l3a = "http://www.w3.org/2000/01/rdf-schema#label" l4 = "http://www.cidoc-crm.org/cidoc-crm/P102_has_title" l5 = "http://www.cidoc-crm.org/cidoc-crm/P3_has_note" self.assertTrue(l1 in js) self.assertTrue(l2 in js[l1]) self.assertTrue(l3 in js[l1][l2]) self.assertTrue(l3a in js[l1][l2]) self.assertEqual(js[l1][l2][l3a], "material a") self.assertTrue(l4 in js[l1][l2][l3]) self.assertTrue(l5 in js[l1][l2][l3][l4]) self.assertEqual(js[l1][l2][l3][l4][l5]["@value"], "taco") def test_default_timezone(self): data = """ { "@id": "http://localhost:8000/resources/e6fc1069-1987-4565-9007-25708de554e8", "@type": "http://www.cidoc-crm.org/cidoc-crm/E22_Man-Made_Object", "http://www.cidoc-crm.org/cidoc-crm/P108i_was_produced_by": { "@id": "http://localhost:8000/tile/7c2e9e8c-3a67-4b90-87c4-84ac946947cc/node/4e1efad2-c163-11ea-8354-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E12_Production", "http://www.cidoc-crm.org/cidoc-crm/P4_has_time-span": [{ "@id": "http://localhost:8000/tile/68c38757-df0a-410b-a8e0-2b8b7c5249f2/node/8a00b22a-c163-11ea-8354-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2024-05-01 15:25:13" } },{ "@id": "http://localhost:8000/tile/68c38757-df0a-410b-a8e0-2b8b7c5249f2/node/8a00b22a-c163-11ea-8354-3af9d3b32b71", "@type": "http://www.cidoc-crm.org/cidoc-crm/E52_Time-Span", "http://www.cidoc-crm.org/cidoc-crm/P82a_begin_of_the_begin": { "@type": "http://www.w3.org/2001/XMLSchema#dateTime", "@value": "2024-05-01T15:25:13" } }] } } """ graph_id = "0bc001c2-c163-11ea-8354-3af9d3b32b71" resource_id = "e6fc1069-1987-4565-9007-25708de554e8" data = JSONDeserializer().deserialize(data) reader = JsonLdReader(default_timezone="-09:00") reader.read_resource(data, resourceid=resource_id, graphid=graph_id) for resource in reader.resources: resource.save(request=None) datetime_value = resource.tiles[1].data[ "ddb04a66-c163-11ea-8354-3af9d3b32b71" ] self.assertEqual(datetime_value[-6:], "-09:00") datetime_value = resource.tiles[2].data[ "ddb04a66-c163-11ea-8354-3af9d3b32b71" ] self.assertEqual(datetime_value[-6:], "-09:00")