def test_external_reference(self): ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:5678', '@type': 'contributor', 'person': { '@id': 8, '@type': 'person' } }] }, disambiguate=False)
def test_unresolved_reference(self): with pytest.raises(UnresolvableReference): ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:5678', '@type': 'contributor', 'person': { '@id': '_:1234', '@type': 'person' } }] }, disambiguate=False)
def create_graph_dependencies(): return ChangeGraph.from_jsonld( { '@graph': [{ '@id': '_:123', '@type': 'person', 'given_name': 'Jane', 'family_name': 'Doe', }, { '@id': '_:456', '@type': 'contributor', 'person': { '@id': '_:123', '@type': 'person' }, 'creative_work': { '@id': '_:789', '@type': 'preprint' }, }, { '@id': '_:789', '@type': 'preprint', 'title': 'All About Cats', }] }, disambiguate=False)
def test_update_dependencies_accept(self, john_doe, normalized_data_id): graph = ChangeGraph.from_jsonld({ '@graph': [{ '@id': john_doe.pk, '@type': 'person', 'given_name': 'Jane', }, { '@id': '_:456', '@type': 'contributor', 'person': { '@id': john_doe.pk, '@type': 'person' }, 'creative_work': { '@id': '_:789', '@type': 'preprint' }, }, { '@id': '_:789', '@type': 'preprint', 'title': 'All About Cats', }] }) change_set = ChangeSet.objects.from_graph(graph, normalized_data_id) change_set.accept() john_doe.refresh_from_db() assert john_doe.given_name == 'Jane' assert Preprint.objects.filter( contributor__person=john_doe).count() == 1 assert Preprint.objects.filter( contributor__person=john_doe).first().title == 'All About Cats'
def test_topological_sort_many_to_many(self): graph = ChangeGraph.from_jsonld( { '@graph': [{ '@id': '_:91011', '@type': 'preprint', 'contributors': [{ '@id': '_:5678', '@type': 'contributor' }] }, { '@id': '_:5678', '@type': 'contributor', 'person': { '@id': '_:1234', '@type': 'person' } }, { '@id': '_:1234', '@type': 'person', 'given_name': 'Doe', 'family_name': 'Jane', }] }, disambiguate=False) assert len(graph.nodes) == 3 assert graph.nodes[0].id == '_:91011' assert graph.nodes[1].id == '_:1234' assert graph.nodes[2].id == '_:5678'
def test_subject_accept(self, normalized_data_id): Subject.objects.bulk_create([ Subject(name='Felines', lineages=[]) ]) assert Subject.objects.filter(name='Felines').count() == 1 graph = ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:987', '@type': 'subject', 'name': 'Felines' }, { '@id': '_:678', '@type': 'throughsubjects', 'subject': {'@id': '_:987', '@type': 'subject'}, 'creative_work': {'@id': '_:789', '@type': 'preprint'}, }, { '@id': '_:789', '@type': 'preprint', 'title': 'All About Cats', }] }) change_set = ChangeSet.objects.from_graph(graph, normalized_data_id) change_set.accept() assert Preprint.objects.filter(subjects__name='Felines').count() == 1 assert Preprint.objects.filter(subjects__name='Felines').first().title == 'All About Cats'
def test_can_delete_work(self, john_doe, normalized_data_id): graph = ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:abc', '@type': 'link', 'url': 'https://share.osf.io/faq', 'type': 'provider', }, { '@id': '_:456', '@type': 'throughlinks', 'link': {'@id': '_:abc', '@type': 'link'}, 'creative_work': {'@id': '_:789', '@type': 'preprint'}, }, { '@id': '_:789', '@type': 'preprint', 'title': 'All About Cats', }] }) change_set = ChangeSet.objects.from_graph(graph, normalized_data_id) link, preprint, _ = change_set.accept() assert preprint.is_deleted is False ChangeSet.objects.from_graph(ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:abc', '@type': 'link', 'type': 'provider', 'url': 'https://share.osf.io/faq', }, { '@id': '_:456', '@type': 'throughlinks', 'link': {'@id': '_:abc', '@type': 'link'}, 'creative_work': {'@id': '_:789', '@type': 'preprint'}, }, { '@id': '_:789', 'is_deleted': True, '@type': 'preprint', 'links': [{'@id': '_:456', '@type': 'throughlinks'}] }] }), normalized_data_id).accept() preprint.refresh_from_db() assert preprint.is_deleted is True
def update_graph(jane_doe): return ChangeGraph.from_jsonld({ '@graph': [{ '@id': jane_doe.pk, '@type': 'person', 'family_name': 'Dough', }] })
def from_graph(self, graph, disambiguate=False): nd = NormalizedData.objects.create(normalized_data=graph, source=share_source) return ChangeSet.objects.from_graph( ChangeGraph.from_jsonld( graph, disambiguate=disambiguate, ), nd.pk)
def merge_graph(jane_doe, john_doe): return ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:1234', '@type': 'MergeAction', 'into': {'@id': jane_doe.pk, '@type': 'person'}, 'from': [{'@id': john_doe.pk, '@type': 'person'}] }] })
def create_graph(): return ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:1234', '@type': 'person', 'given_name': 'Jane', 'family_name': 'Doe', }] }, disambiguate=False)
def test_invalid_subject(self, normalized_data_id): with pytest.raises(ValidationError) as e: ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:987', '@type': 'subject', 'name': 'Felines' }, { '@id': '_:678', '@type': 'throughsubjects', 'subject': {'@id': '_:987', '@type': 'subject'}, 'creative_work': {'@id': '_:789', '@type': 'preprint'}, }, { '@id': '_:789', '@type': 'preprint', 'title': 'All About Cats', }] }) assert e.value.message == 'Invalid subject: Felines'
def test_single_node(self): graph = ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:1234', '@type': 'person', 'given_name': 'Doe', 'family_name': 'Jane', }] }, disambiguate=False) assert len(graph.nodes) == 1
def test_detect_cyclic(self): with pytest.raises(CyclicalDependency): ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:1234', '@type': 'person', 'given_name': 'Doe', 'family_name': 'Jane', 'contributor': { '@id': '_:5678', '@type': 'contributor', } }, { '@id': '_:5678', '@type': 'contributor', 'person': { '@id': '_:1234', '@type': 'person' } }] }, disambiguate=False)
def run(self, normalized_id, started_by_id=None): started_by = None normalized = NormalizedData.objects.get(pk=normalized_id) if started_by_id: started_by = ShareUser.objects.get(pk=started_by_id) logger.info('%s started make JSON patches for %s at %s', started_by, normalized, datetime.datetime.utcnow().isoformat()) try: cs = ChangeSet.objects.from_graph(ChangeGraph.from_jsonld(normalized.normalized_data, extra_namespace=normalized.source.username), normalized.id) if cs and normalized.source.is_robot: # TODO: verify change set is not overwriting user created object cs.accept() except Exception as e: logger.exception('Failed make json patches (%d)', normalized_id) raise self.retry(countdown=10, exc=e) logger.info('Finished make JSON patches for %s by %s at %s', normalized, started_by, datetime.datetime.utcnow().isoformat())
def test_topological_sort_unchanged(self): graph = ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:1234', '@type': 'person', 'given_name': 'Doe', 'family_name': 'Jane', }, { '@id': '_:5678', '@type': 'contributor', 'person': { '@id': '_:1234', '@type': 'person' } }] }, disambiguate=False) assert len(graph.nodes) == 2 assert graph.nodes[0].id == '_:1234' assert graph.nodes[1].id == '_:5678'
def test_parse_merge(self): graph = ChangeGraph.from_jsonld( { '@graph': [{ '@id': '_:123', '@type': 'MergeAction', 'into': { '@id': 1, '@type': 'person' }, 'from': [{ '@id': 2, '@type': 'person' }] }] }, disambiguate=False) assert len(graph.nodes) == 1 assert len(graph.nodes[0].related) == 2 assert len(graph.nodes[0].relations) == 1 assert len(graph.nodes[0]._reverse_relations) == 1
def test_merge_accept(self, normalized_data_id, merge_graph, john_doe, jane_doe): change_set = ChangeSet.objects.from_graph(merge_graph, normalized_data_id) ChangeSet.objects.from_graph( ChangeGraph.from_jsonld({ '@graph': [{ '@id': '_:123', '@type': 'preprint', 'title': 'All About Cats' }, { '@id': '_:456', '@type': 'contributor', 'person': { '@id': john_doe.pk, '@type': 'person' }, 'creative_work': { '@id': '_:123', '@type': 'preprint' }, }] }), normalized_data_id).accept() assert Preprint.objects.filter( contributor__person=john_doe).count() == 1 assert Preprint.objects.filter( contributor__person=john_doe).count() == 1 assert Preprint.objects.filter( contributor__person=jane_doe).count() == 0 change_set.accept() john_doe.refresh_from_db() jane_doe.refresh_from_db() # Jane should not have been modified assert jane_doe.same_as is None assert jane_doe.versions.count() == 1 # John should have been updated assert john_doe.versions.count() == 2 # John's same_as field and same_as_version should have been updated assert john_doe.same_as == jane_doe assert john_doe.version.same_as == jane_doe assert john_doe.same_as_version == jane_doe.version assert john_doe.version.same_as_version == jane_doe.version # John's latest change should be set to the merge change assert john_doe.change.change_set == change_set assert john_doe.version.change.change_set == change_set # Ensure that date modifieds have been update assert john_doe.versions.first( ).date_modified > john_doe.versions.last().date_modified # John is no longer a contributor on anything assert Preprint.objects.filter( contributor__person=john_doe).count() == 0 assert Preprint.objects.filter( contributor__person_version=john_doe.version).count() == 0 # Jane is now a contributor assert Preprint.objects.filter( contributor__person=jane_doe).count() == 1 assert Preprint.objects.filter( contributor__person_version=jane_doe.version).count() == 1 # The affected contributor should have been updated assert Contributor.objects.get(person=jane_doe).versions.count() == 2 assert Contributor.objects.get( person=jane_doe).change.change_set == change_set