def test_deposit_delete(app, draft_deposits, test_records, test_users, test_communities): """Test deposit deletion.""" with app.app_context(): # create a deposit with a parent pid which has no other children first_deposit = create_deposit( {'community': str(test_communities['MyTestCommunity1'])}, test_users['deposits_creator']) parent_pid = first_deposit['_pid'][0]['value'] deposit_pid_value = first_deposit['_deposit']['id'] # delete the deposit first_deposit.delete() deposit = PersistentIdentifier.query.filter_by( pid_value=deposit_pid_value).first() parent = PersistentIdentifier.query.filter_by( pid_value=parent_pid).one_or_none() # check that deleting it deletes parent from the db because there are # no remaining published versions and draft. assert not parent assert deposit.status == PIDStatus.DELETED # check that the buckets are removed assert not db.session.query( Bucket.query.join(RecordsBuckets).filter( RecordsBuckets.bucket_id == Bucket.id, RecordsBuckets.record_id == first_deposit.id).exists()).scalar() # create a deposit with a parent which has other children v1 = test_records[0].data v1_rec = B2ShareRecord.get_record(test_records[0].record_id) v1_pid, v1_id = pid_of(v1) data = copy_data_from_previous(v1_rec.model.json) v2 = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) deposit_pid_value = v2['_deposit']['id'] parent_pid = v2['_pid'][0]['value'] v2.delete() deposit = PersistentIdentifier.query.filter_by( pid_value=deposit_pid_value).first() parent = PersistentIdentifier.query.filter_by( pid_value=parent_pid).first() # check that the parent status is not changed after deleting assert parent.status != PIDStatus.DELETED assert parent.get_redirect() == v1_pid assert deposit.status == PIDStatus.DELETED
def test_deposit_delete(app, draft_deposits, test_records, test_users, test_communities): """Test deposit deletion.""" with app.app_context(): # create a deposit with a parent pid which has no other children first_deposit = create_deposit( {'community': str(test_communities['MyTestCommunity1'])}, test_users['deposits_creator']) parent_pid = first_deposit['_pid'][0]['value'] deposit_pid_value = first_deposit['_deposit']['id'] # delete the deposit first_deposit.delete() deposit = PersistentIdentifier.query.filter_by(pid_value=deposit_pid_value).first() parent = PersistentIdentifier.query.filter_by(pid_value=parent_pid).one_or_none() # check that deleting it deletes parent from the db because there are # no remaining published versions and draft. assert not parent assert deposit.status == PIDStatus.DELETED # check that the buckets are removed assert not db.session.query( Bucket.query.join(RecordsBuckets). filter(RecordsBuckets.bucket_id == Bucket.id, RecordsBuckets.record_id == first_deposit.id).exists() ).scalar() # create a deposit with a parent which has other children v1 = test_records[0].data v1_rec = B2ShareRecord.get_record(test_records[0].record_id) v1_pid, v1_id = pid_of(v1) data = copy_data_from_previous(v1_rec.model.json) v2 = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) deposit_pid_value = v2['_deposit']['id'] parent_pid = v2['_pid'][0]['value'] v2.delete() deposit = PersistentIdentifier.query.filter_by(pid_value=deposit_pid_value).first() parent = PersistentIdentifier.query.filter_by(pid_value=parent_pid).first() # check that the parent status is not changed after deleting assert parent.status != PIDStatus.DELETED assert parent.get_redirect() == v1_pid assert deposit.status == PIDStatus.DELETED
def test_new_deposit_versions_preserve_schema(app, test_records, test_users): """Creating new versions of existing records.""" with app.app_context(): # Retrieve a record which will be the first version, and its deposit v1_rec = B2ShareRecord.get_record(test_records[0].record_id) _, v1_id = pid_of(test_records[0].data) # update the community's schema community_id = v1_rec.model.json['community'] old_schema = CommunitySchema.get_community_schema(community_id) json_schema = json.loads(old_schema.model.community_schema) new_schema = CommunitySchema.create_version(community_id, json_schema) assert new_schema.version > old_schema.version # create new, unversioned, draft and records data = copy_data_from_previous(v1_rec.model.json) unver_dep = create_deposit(data, test_users['deposits_creator']) unver_dep.submit() unver_dep.publish() _, unver_rec = unver_dep.fetch_published() # the unversioned draft or record in a version chain have the updated schema assert unver_dep['$schema'] != Deposit._build_deposit_schema( v1_rec.model.json) assert unver_rec.model.json['$schema'] != v1_rec.model.json['$schema'] # create new draft and record in the version chain of v1 data = copy_data_from_previous(v1_rec.model.json) v2_dep = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) v2_dep.submit() v2_dep.publish() _, v2_rec = v2_dep.fetch_published() # the new draft and record in a version chain preserve the version of the schema assert v2_dep['$schema'] == Deposit._build_deposit_schema( v1_rec.model.json) assert v2_rec.model.json['$schema'] == v1_rec.model.json['$schema']
def test_deposit_versions_create(app, test_records, test_users): """Creating new versions of existing records.""" with app.app_context(): # Retrieve a record which will be the first version v1 = test_records[0].data v1_rec = B2ShareRecord.get_record(test_records[0].record_id) v1_pid, v1_id = pid_of(v1) assert list_published_pids(v1_pid) == [v1_pid] # create draft in version chain: # version chain becomes: [v1] -- [v2 draft] # v2 = create_deposit({}, version_of=v1_id) data = copy_data_from_previous(v1_rec.model.json) v2 = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) assert filenames(v2) == [] ObjectVersion.create(v2.files.bucket, 'myfile1', stream=BytesIO(b'mycontent')) assert filenames(v2) == ['myfile1'] assert list_published_pids(v1_pid) == [v1_pid] # cannot create another draft if one exists # not possible: [v1] -- [v2 draft] # `- [new draft] with pytest.raises(DraftExistsVersioningError): data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v1_id) # cannot create a version from a draft pid # not possible: [v1] -- [v2 draft] -- [new draft] with pytest.raises(IncorrectRecordVersioningError): # record pid not created yet data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v2['_deposit']['id']) # publish previous draft # version chain becomes: [v1] -- [v2] v2.submit() v2.publish() v2_pid, v2_id = pid_of(v2) assert list_published_pids(v1_pid) == [v1_pid, v2_pid] # cannot create draft based on the first version in a chain # not possible: [v1] -- [v2] # `- [new draft] with pytest.raises(IncorrectRecordVersioningError): data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v1_id) # create and publish other versions: # version chain becomes: [v1] -- [v2] -- [v3] data = copy_data_from_previous(v1_rec.model.json) v3 = create_deposit(data, test_users['deposits_creator'], version_of=v2_id) # assert files are imported from v2 assert filenames(v3) == ['myfile1'] ObjectVersion.create(v3.files.bucket, 'myfile2', stream=BytesIO(b'mycontent')) assert filenames(v3) == ['myfile1', 'myfile2'] assert list_published_pids(v1_pid) == [v1_pid, v2_pid] v3.submit() v3.publish() v3_pid, v3_id = pid_of(v3) v3_rec = Record.get_record(v3_id) assert filenames(v3_rec) == ['myfile1', 'myfile2'] assert list_published_pids(v1_pid) == [v1_pid, v2_pid, v3_pid] # cannot create draft based on an intermediate version in a chain # not possible: [v1] -- [v2] -- [v3] # `- [new draft] with pytest.raises(IncorrectRecordVersioningError): create_deposit({}, test_users['deposits_creator'], version_of=v2_id) # Create yet another version # Version chain becomes: [v1] -- [v2] -- [v3] -- [v4] data = copy_data_from_previous(v1_rec.model.json) v4 = create_deposit(data, test_users['deposits_creator'], version_of=v3_id) v4.submit() v4.publish() assert filenames(v4) == ['myfile1', 'myfile2'] v4_pid, v4_id = pid_of(v4) assert list_published_pids(v1_pid) == [ v1_pid, v2_pid, v3_pid, v4_pid] # assert that creating a new version from a deleted pid is not allowed resolver = Resolver(pid_type=v4_pid.pid_type, object_type='rec', getter=partial(B2ShareRecord.get_record, with_deleted=True)) v4_pid, v4_rec = LazyPIDValue(resolver, v4_pid.pid_value).data # delete [v4] v4_rec.delete() with pytest.raises(RecordNotFoundVersioningError): v5 = create_deposit(data, test_users['deposits_creator'], version_of=v4_id)
def test_deposit_versions_create(app, test_records, test_users): """Creating new versions of existing records.""" with app.app_context(): # Retrieve a record which will be the first version v1 = test_records[0].data v1_rec = B2ShareRecord.get_record(test_records[0].record_id) v1_pid, v1_id = pid_of(v1) assert list_published_pids(v1_pid) == [v1_pid] # create draft in version chain: # version chain becomes: [v1] -- [v2 draft] # v2 = create_deposit({}, version_of=v1_id) data = copy_data_from_previous(v1_rec.model.json) v2 = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) assert filenames(v2) == [] ObjectVersion.create(v2.files.bucket, 'myfile1', stream=BytesIO(b'mycontent')) assert filenames(v2) == ['myfile1'] assert list_published_pids(v1_pid) == [v1_pid] # cannot create another draft if one exists # not possible: [v1] -- [v2 draft] # `- [new draft] with pytest.raises(DraftExistsVersioningError): data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v1_id) # cannot create a version from a draft pid # not possible: [v1] -- [v2 draft] -- [new draft] with pytest.raises( IncorrectRecordVersioningError): # record pid not created yet data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v2['_deposit']['id']) # publish previous draft # version chain becomes: [v1] -- [v2] v2.submit() v2.publish() v2_pid, v2_id = pid_of(v2) assert list_published_pids(v1_pid) == [v1_pid, v2_pid] # cannot create draft based on the first version in a chain # not possible: [v1] -- [v2] # `- [new draft] with pytest.raises(IncorrectRecordVersioningError): data = copy_data_from_previous(v1_rec.model.json) create_deposit(data, test_users['deposits_creator'], version_of=v1_id) # create and publish other versions: # version chain becomes: [v1] -- [v2] -- [v3] data = copy_data_from_previous(v1_rec.model.json) v3 = create_deposit(data, test_users['deposits_creator'], version_of=v2_id) # assert files are imported from v2 assert filenames(v3) == ['myfile1'] ObjectVersion.create(v3.files.bucket, 'myfile2', stream=BytesIO(b'mycontent')) assert filenames(v3) == ['myfile1', 'myfile2'] assert list_published_pids(v1_pid) == [v1_pid, v2_pid] v3.submit() v3.publish() v3_pid, v3_id = pid_of(v3) v3_rec = Record.get_record(v3_id) assert filenames(v3_rec) == ['myfile1', 'myfile2'] assert list_published_pids(v1_pid) == [v1_pid, v2_pid, v3_pid] # cannot create draft based on an intermediate version in a chain # not possible: [v1] -- [v2] -- [v3] # `- [new draft] with pytest.raises(IncorrectRecordVersioningError): create_deposit({}, test_users['deposits_creator'], version_of=v2_id) # Create yet another version # Version chain becomes: [v1] -- [v2] -- [v3] -- [v4] data = copy_data_from_previous(v1_rec.model.json) v4 = create_deposit(data, test_users['deposits_creator'], version_of=v3_id) v4.submit() v4.publish() assert filenames(v4) == ['myfile1', 'myfile2'] v4_pid, v4_id = pid_of(v4) assert list_published_pids(v1_pid) == [v1_pid, v2_pid, v3_pid, v4_pid] # assert that creating a new version from a deleted pid is not allowed resolver = Resolver(pid_type=v4_pid.pid_type, object_type='rec', getter=partial(B2ShareRecord.get_record, with_deleted=True)) v4_pid, v4_rec = LazyPIDValue(resolver, v4_pid.pid_value).data # delete [v4] v4_rec.delete() with pytest.raises(RecordNotFoundVersioningError): v5 = create_deposit(data, test_users['deposits_creator'], version_of=v4_id)
def test_record_delete_version(app, test_records, test_users): """Test deletion of a record version.""" with app.app_context(): resolver = Resolver( pid_type='b2rec', object_type='rec', getter=B2ShareRecord.get_record, ) v1 = test_records[0].data v1_pid, v1_id = pid_of(v1) _, v1_rec = resolver.resolve(v1_id) data = copy_data_from_previous(v1_rec.model.json) v2 = create_deposit(data, test_users['deposits_creator'], version_of=v1_id) ObjectVersion.create(v2.files.bucket, 'myfile1', stream=BytesIO(b'mycontent')) v2.submit() v2.publish() v2_pid, v2_id = pid_of(v2) data = copy_data_from_previous(v2.model.json) v3 = create_deposit(data, test_users['deposits_creator'], version_of=v2_id) v3.submit() v3.publish() v3_pid, v3_id = pid_of(v3) v3_pid, v3_rec = resolver.resolve(v3_pid.pid_value) # chain is now: [v1] -- [v2] -- [v3] version_child = PIDVersioning(child=v2_pid) version_master = PIDVersioning(parent=version_child.parent) assert len(version_master.children.all()) == 3 v3_rec.delete() assert len(version_master.children.all()) == 2 # chain is now [v1] -- [v2] # assert that we can create again a new version from v2 data = copy_data_from_previous(v2.model.json) v3 = create_deposit(data, test_users['deposits_creator'], version_of=v2_id) v3.submit() v3.publish() v3_pid, v3_id = pid_of(v3) v3_pid, v3_rec = resolver.resolve(v3_pid.pid_value) assert len(version_master.children.all()) == 3 v2_pid, v2_rec = resolver.resolve(v2_pid.pid_value) # Delete an intermediate version v2_rec.delete() assert len(version_master.children.all()) == 2 # chain is now [v1] -- [v3] # Add a new version data = copy_data_from_previous(v3.model.json) v4 = create_deposit(data, test_users['deposits_creator'], version_of=v3_id) v4.submit() v4.publish() assert len(version_master.children.all()) == 3 # final chain [v1] -- [v3] -- [v4] v4_pid, v4_id = pid_of(v4) v4_pid, v4_rec = resolver.resolve(v4_pid.pid_value) data = copy_data_from_previous(v4) draft_child = create_deposit(data, test_users['deposits_creator'], version_of=v4_id) draft_child.submit() # delete all children except the draft child assert len(version_master.children.all()) == 3 v4_rec.delete() assert len(version_master.children.all()) == 2 v3_rec.delete() assert len(version_master.children.all()) == 1 v1_rec.delete() assert len(version_master.children.all()) == 0 assert version_master.parent.status != PIDStatus.DELETED draft_child.publish() draft_child_pid, draft_child_id = pid_of(draft_child) draft_child_pid, draft_child_rec = \ resolver.resolve(draft_child_pid.pid_value) # assert that we can create again a new version assert len(version_master.children.all()) == 1 # no child remains and there is no draft_child draft_child_rec.delete() assert version_master.parent.status == PIDStatus.DELETED