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)
예제 #6
0
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