def attach_files(obj, eng): if 'files' in obj.extra_data: recid = obj.data['control_number'] pid = PersistentIdentifier.get('recid', recid) existing_record = Record.get_record(pid.object_uuid) if '_files' not in existing_record or not existing_record['_files']: bucket = Bucket.create() RecordsBuckets.create(record=existing_record.model, bucket=bucket) for file_ in obj.extra_data['files']: if file_['url'].startswith('http'): data = requests_retry_session().get(file_['url'], headers=file_.get('headers', {})) f = StringIO(data.content) else: f = open(file_['url']) existing_record.files[file_['name']] = f existing_record.files[file_['name']]['filetype'] = file_['filetype'] obj.save() existing_record.commit() db.session.commit() else: __halt_and_notify('No files found.', eng)
def check_records_migration(app): """Check that a set of records have been migrated.""" expected_records = _load_json('expected_records.json') for exp_record in expected_records: db_record = Record.get_record(exp_record['id'], with_deleted=True) assert str(db_record.created) == exp_record['created'] # If the record is deleted there is no metadata to check if db_record.model.json is None: continue # Check that the parent pid is minted properly parent_pid = b2share_parent_pid_fetcher(exp_record['id'], db_record) fetched_pid = b2share_record_uuid_fetcher(exp_record['id'], db_record) record_pid = PersistentIdentifier.get(fetched_pid.pid_type, fetched_pid.pid_value) assert PIDVersioning(record_pid).parent.pid_value == parent_pid.pid_value # Remove the parent pid as it has been added by the migration db_record['_pid'].remove({ 'type': RecordUUIDProvider.parent_pid_type, 'value': parent_pid.pid_value, }) # The OAI-PMH identifier has been modified by the migration if db_record.get('_oai'): oai_prefix = app.config.get('OAISERVER_ID_PREFIX', 'oai:') record_id = exp_record['metadata']['_deposit']['id'] assert db_record['_oai']['id'] == str(oai_prefix) + record_id exp_record['metadata']['_oai']['id'] = db_record['_oai']['id'] assert db_record == exp_record['metadata']
def add_oai_information(obj, eng): """Adds OAI information like identifier""" recid = obj.data['control_number'] pid = PersistentIdentifier.get('recid', recid) existing_record = Record.get_record(pid.object_uuid) if '_oai' not in existing_record: try: oaiid_minter(pid.object_uuid, existing_record) except PIDAlreadyExists: existing_record['_oai'] = { 'id': 'oai:beta.scoap3.org:%s' % recid, 'sets': _get_oai_sets(existing_record) } if 'id' not in existing_record['_oai']: current_app.logger.info('adding new oai id') oaiid_minter(pid.object_uuid, existing_record) if 'sets' not in existing_record['_oai'] or not existing_record['_oai']['sets']: existing_record['_oai']['sets'] = _get_oai_sets(existing_record) existing_record['_oai']['updated'] = datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ') existing_record.commit() obj.save() db.session.commit()
def check_dois(record, allrecords, update): """ Checks that DOIs of records in the current instance are registered. """ if record: record = Record.get_record(record) check_record_doi(record, update) elif allrecords: click.secho('checking DOI for all records') for record in list_db_published_records(): check_record_doi(record, update) else: raise click.ClickException('Either -r or -a option must be selected')
def check_embargo(record_id, is_embargoed): with app.app_context(): with app.test_client() as client: login_user(non_creator, client) # test open_access field in record's metadata record = Record.get_record(record_id) assert record['open_access'] != is_embargoed # test record's file access subtest_file_bucket_permissions( client, record.files.bucket, access_level=None if is_embargoed else 'read', is_authenticated=True )
def check_pids_migration(): """Check that the persistent identifiers have been migrated.""" expected_pids = _load_json('expected_pids.json') # Check unchanging properties for exp_pid in expected_pids: db_pid = PersistentIdentifier.get(exp_pid['pid_type'], exp_pid['pid_value']) for key, value in exp_pid.items(): if key != 'updated': assert str(getattr(db_pid, key)) == str(value) # check that deleted PID's records are (soft or hard) deleted if exp_pid['status'] == PIDStatus.DELETED.value: metadata = None try: record = Record.get_record(exp_pid['pid_value'], with_deleted=True) # Soft deleted record metadata = record.model.json except NoResultFound: # Hard deleted record pass assert metadata is None # Check versioning relations and PIDs if exp_pid['pid_type'] == 'b2dep': try: rec_pid = PersistentIdentifier.get('b2rec', exp_pid['pid_value']) # if the deposit is deleted, either the record PID was reserved # and has been deleted, or it still exists. if db_pid.status == PIDStatus.DELETED: assert rec_pid.status != PIDStatus.RESERVED except PIDDoesNotExistError: # The record PID was only reserved and has been deleted # with the deposit PID. assert db_pid.status == PIDStatus.DELETED continue # Check that a parent pid has been created versioning = PIDVersioning(child=rec_pid) parent = versioning.parent assert rec_pid.status in [PIDStatus.RESERVED, PIDStatus.REGISTERED] if rec_pid.status == PIDStatus.RESERVED: assert parent.status == PIDStatus.RESERVED else: assert parent.status == PIDStatus.REDIRECTED assert parent.get_redirect() == rec_pid
def datacite_register(pid_value, record_uuid): """Mint the DOI with DataCite. :param pid_value: Value of record PID, with pid_type='recid'. :type pid_value: str """ record = Record.get_record(record_uuid) dcp = DataCiteProvider.get(record['doi']) url = current_app.config['ZENODO_RECORDS_UI_LINKS_FORMAT'].format( recid=pid_value) doc = datacite_v31.serialize(dcp.pid, record) dcp.update(url, doc) if dcp.pid.status == PIDStatus.REGISTERED \ else dcp.register(url, doc) db.session.commit()
def datacite_register(pid_value, record_uuid): """Mint DOI and Concept DOI with DataCite. :param pid_value: Value of record PID, with pid_type='recid'. :type pid_value: str :param record_uuid: Record Metadata UUID. :type record_uuid: str """ try: record = Record.get_record(record_uuid) # Bail out if not a Zenodo DOI. if not is_local_doi(record['doi']): return dcp = DataCiteProvider.get(record['doi']) doc = datacite_v41.serialize(dcp.pid, record) url = current_app.config['ZENODO_RECORDS_UI_LINKS_FORMAT'].format( recid=pid_value) if dcp.pid.status == PIDStatus.REGISTERED: dcp.update(url, doc) else: dcp.register(url, doc) # If this is the latest record version, update/register the Concept DOI # using the metadata of the record. recid = PersistentIdentifier.get('recid', str(record['recid'])) pv = PIDVersioning(child=recid) conceptdoi = record.get('conceptdoi') if conceptdoi and pv.exists and pv.is_last_child: conceptrecid = record.get('conceptrecid') concept_dcp = DataCiteProvider.get(conceptdoi) url = current_app.config['ZENODO_RECORDS_UI_LINKS_FORMAT'].format( recid=conceptrecid) doc = datacite_v41.serialize(concept_dcp.pid, record) if concept_dcp.pid.status == PIDStatus.REGISTERED: concept_dcp.update(url, doc) else: concept_dcp.register(url, doc) db.session.commit() except Exception as exc: datacite_register.retry(exc=exc)
def find_version_master_and_previous_record(version_of): """Retrieve the PIDVersioning and previous record of a record PID. :params version_of: record PID. """ try: child_pid = RecordUUIDProvider.get(version_of).pid if child_pid.status == PIDStatus.DELETED: raise RecordNotFoundVersioningError() except PIDDoesNotExistError as e: raise RecordNotFoundVersioningError() from e version_master = PIDVersioning(child=child_pid) prev_pid = version_master.last_child assert prev_pid.pid_type == RecordUUIDProvider.pid_type prev_version = Record.get_record(prev_pid.object_uuid) # check that version_of references the last version of a record assert is_publication(prev_version.model) if prev_pid.pid_value != version_of: raise IncorrectRecordVersioningError(prev_pid.pid_value) return version_master, prev_version
def update_record(pid, schema, data, files, skip_files): """Updates the given record.""" record = Record.get_record(pid.object_uuid) with db.session.begin_nested(): if record.files and not skip_files: bucket_id = record.files.bucket bucket = Bucket.get(bucket_id.id) for o in ObjectVersion.get_by_bucket(bucket).all(): o.remove() o.file.delete() RecordsBuckets.query.filter_by( record=record.model, bucket=bucket ).delete() bucket_id.remove() db.session.commit() record.update(data) if not skip_files: bucket = Bucket.create() handle_record_files(data, bucket, files, skip_files) RecordsBuckets.create( record=record.model, bucket=bucket) return record
def update_record(pid, schema, data, files, skip_files): """Updates the given record.""" record = Record.get_record(pid.object_uuid) with db.session.begin_nested(): if record.files and not skip_files: bucket_id = record.files.bucket bucket = Bucket.get(bucket_id.id) for o in ObjectVersion.get_by_bucket(bucket).all(): o.remove() o.file.delete() RecordsBuckets.query.filter_by( record=record.model, bucket=bucket ).delete() bucket_id.remove() db.session.commit() record.update(data) if not skip_files: bucket = Bucket.create() handle_record_files(data, bucket, files, skip_files) RecordsBuckets.create( record=record.model, bucket=bucket) return record
def check_handles(update, record_pid): """Allocate handles for a record and its files, if necessary.""" rec_pid = RecordUUIDProvider.get(pid_value=record_pid).pid record = Record.get_record(rec_pid.object_uuid) record_updated = False pid_list = [p.get('value') for p in record['_pid'] if p.get('type') == 'ePIC_PID'] if pid_list: click.secho('record {} already has a handle'.format(record_pid), fg='green') else: click.secho('record {} has no handle'.format(record_pid), fg='red') if update: b2share_pid_minter(rec_pid, record) record_updated = True click.secho(' handle added to record', fg='green') else: click.secho('use -u argument to add a handle to the record') files_ok = True for f in record.get('_files', []): if f.get('ePIC_PID'): click.secho('file {} already has a handle'.format(f.get('key')), fg='green') else: click.secho('file {} has no handle'.format(f.get('key')), fg='red') files_ok = False if update and not files_ok: create_file_pids(record) record_updated = True click.secho(' files updated with handles', fg='green') elif not update and not files_ok: click.secho('use -u argument to add handles to the files') if record_updated: record.commit() db.session.commit()
def test_cascade_action_record_delete(app, db, location, record_with_bucket, generic_file, force, num_of_recordbuckets): """Test cascade action on record delete, with force false.""" record = record_with_bucket record_id = record.id bucket_id = record.files.bucket.id # check before assert len(RecordsBuckets.query.all()) == 1 assert len(Bucket.query.all()) == 1 assert len(Bucket.query.filter_by(id=bucket_id).all()) == 1 assert ObjectVersion.get(bucket=bucket_id, key=generic_file) record.delete(force=force) # check after db.session.expunge(record.model) with pytest.raises(NoResultFound): record = Record.get_record(record_id) assert len(RecordsBuckets.query.all()) == num_of_recordbuckets assert len(Bucket.query.all()) == 1 assert len(Bucket.query.filter_by(id=bucket_id).all()) == 1 assert ObjectVersion.get(bucket=bucket_id, key=generic_file)
def update_record(obj, eng): """Updates existing record""" doi = get_first_doi(obj) query = {'query': {'bool': {'must': [{'match': {'dois.value': doi}}], }}} search_result = es.search(index='records-record', doc_type='record-v1.0.0', body=query) recid = search_result['hits']['hits'][0]['_source']['control_number'] obj.extra_data['recid'] = recid obj.data['control_number'] = recid pid = PersistentIdentifier.get('recid', recid) existing_record = Record.get_record(pid.object_uuid) if '_files' in existing_record: obj.data['_files'] = existing_record['_files'] if '_oai' in existing_record: obj.data['_oai'] = existing_record['_oai'] # preserving original creation date creation_date = existing_record['record_creation_date'] obj.data['record_creation_date'] = creation_date obj.data['record_creation_year'] = parse_date(creation_date).year existing_record.clear() existing_record.update(obj.data) try: existing_record.commit() obj.save() db.session.commit() except ValidationError as err: __halt_and_notify("Validation error: %s." % err, eng) except SchemaError as err: __halt_and_notify('SchemaError during record validation! %s' % err, eng)
def test_cascade_action_record_delete(app, db, location, record_with_bucket, generic_file, force, num_of_recordbuckets): """Test cascade action on record delete, with force false.""" record = record_with_bucket record_id = record.id bucket_id = record.files.bucket.id # check before assert len(RecordsBuckets.query.all()) == 1 assert len(Bucket.query.all()) == 1 assert len(Bucket.query.filter_by(id=bucket_id).all()) == 1 assert ObjectVersion.get(bucket=bucket_id, key=generic_file) record.delete(force=force) # check after db.session.expunge(record.model) with pytest.raises(NoResultFound): record = Record.get_record(record_id) assert len(RecordsBuckets.query.all()) == num_of_recordbuckets assert len(Bucket.query.all()) == 1 assert len(Bucket.query.filter_by(id=bucket_id).all()) == 1 assert ObjectVersion.get(bucket=bucket_id, key=generic_file)
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_get_bucket(app, db, location): """Test retrival of the bucket from the record.""" record = Record.create({'title': 'test'}) db.session.commit() record = Record.get_record(record.id) assert str(record.bucket.id) == record['_bucket']
def alembic_upgrade_database_data(alembic, verbose): """Migrate the database data from v2.0.0 to 2.1.0.""" ### Add versioning PIDs ### # Reserve the record PID and versioning PID for unpublished deposits # Hack: disable record indexing during record migration from invenio_indexer.api import RecordIndexer old_index_fn = RecordIndexer.index RecordIndexer.index = lambda s, record: None if verbose: click.secho('migrating deposits and records...') with db.session.begin_nested(): # Migrate published records records_pids = PersistentIdentifier.query.filter( PersistentIdentifier.pid_type == RecordUUIDProvider.pid_type, PersistentIdentifier.status == PIDStatus.REGISTERED, ).all() for rec_pid in records_pids: if verbose: click.secho(' record {}'.format(rec_pid.pid_value)) try: record = Record.get_record(rec_pid.object_uuid) except NoResultFound: # The record is deleted but not the PID. Fix it. rec_pid.status = PIDStatus.DELETED continue # Create parent version PID parent_pid = RecordUUIDProvider.create().pid version_master = PIDVersioning(parent=parent_pid) version_master.insert_draft_child(child=rec_pid) version_master.update_redirect() migrate_record_metadata( Record.get_record(rec_pid.object_uuid), parent_pid ) # Migrate deposits deposit_pids = PersistentIdentifier.query.filter( PersistentIdentifier.pid_type == DepositUUIDProvider.pid_type, PersistentIdentifier.status == PIDStatus.REGISTERED, ).all() for dep_pid in deposit_pids: if verbose: click.secho(' deposit {}'.format(dep_pid.pid_value)) try: deposit = Deposit.get_record(dep_pid.object_uuid) if deposit['publication_state'] != \ PublicationStates.published.name: # The record is not published yet. Reserve the PID. rec_pid = RecordUUIDProvider.create( object_type='rec', pid_value=dep_pid.pid_value, ).pid # Create parent version PID parent_pid = RecordUUIDProvider.create().pid assert parent_pid version_master = PIDVersioning(parent=parent_pid) version_master.insert_draft_child(child=rec_pid) else: # Retrieve previously created version PID rec_pid = RecordUUIDProvider.get(dep_pid.pid_value).pid version_master = PIDVersioning(child=rec_pid) parent_pid = version_master.parent if not parent_pid: click.secho(' record {} was deleted, but the deposit has not been removed'.format(rec_pid.pid_value), fg='red') if parent_pid: migrate_record_metadata( Deposit.get_record(dep_pid.object_uuid), parent_pid ) except NoResultFound: # The deposit is deleted but not the PID. Fix it. dep_pid.status = PIDStatus.DELETED if verbose: click.secho('done migrating deposits.') RecordIndexer.index = old_index_fn
def update_doc(pid, data): """Updates the given doc record.""" from invenio_records import Record record = Record.get_record(pid.object_uuid) record.update(data) return record
def alembic_upgrade_database_data(alembic, verbose): """Migrate the database data from v2.0.0 to 2.1.0.""" ### Add versioning PIDs ### # Reserve the record PID and versioning PID for unpublished deposits # Hack: disable record indexing during record migration from invenio_indexer.api import RecordIndexer old_index_fn = RecordIndexer.index RecordIndexer.index = lambda s, record: None if verbose: click.secho('migrating deposits and records...') with db.session.begin_nested(): # Migrate published records records_pids = PersistentIdentifier.query.filter( PersistentIdentifier.pid_type == RecordUUIDProvider.pid_type, PersistentIdentifier.status == PIDStatus.REGISTERED, ).all() for rec_pid in records_pids: if verbose: click.secho(' record {}'.format(rec_pid.pid_value)) try: record = Record.get_record(rec_pid.object_uuid) except NoResultFound: # The record is deleted but not the PID. Fix it. rec_pid.status = PIDStatus.DELETED continue # Create parent version PID parent_pid = RecordUUIDProvider.create().pid version_master = PIDVersioning(parent=parent_pid) version_master.insert_draft_child(child=rec_pid) version_master.update_redirect() migrate_record_metadata(Record.get_record(rec_pid.object_uuid), parent_pid) # Migrate deposits deposit_pids = PersistentIdentifier.query.filter( PersistentIdentifier.pid_type == DepositUUIDProvider.pid_type, PersistentIdentifier.status == PIDStatus.REGISTERED, ).all() for dep_pid in deposit_pids: if verbose: click.secho(' deposit {}'.format(dep_pid.pid_value)) try: deposit = Deposit.get_record(dep_pid.object_uuid) if deposit['publication_state'] != \ PublicationStates.published.name: # The record is not published yet. Reserve the PID. rec_pid = RecordUUIDProvider.create( object_type='rec', pid_value=dep_pid.pid_value, ).pid # Create parent version PID parent_pid = RecordUUIDProvider.create().pid assert parent_pid version_master = PIDVersioning(parent=parent_pid) version_master.insert_draft_child(child=rec_pid) else: # Retrieve previously created version PID rec_pid = RecordUUIDProvider.get(dep_pid.pid_value).pid version_master = PIDVersioning(child=rec_pid) parent_pid = version_master.parent if not parent_pid: click.secho( ' record {} was deleted, but the deposit has not been removed' .format(rec_pid.pid_value), fg='red') if parent_pid: migrate_record_metadata( Deposit.get_record(dep_pid.object_uuid), parent_pid) except NoResultFound: # The deposit is deleted but not the PID. Fix it. dep_pid.status = PIDStatus.DELETED if verbose: click.secho('done migrating deposits.') RecordIndexer.index = old_index_fn
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 record(self) -> Optional[Record]: try: return Record.get_record(self.model.extra_data['_record']) except NoResultFound: raise WorkflowsRecordNotFound('No Record for id: {}'.format( self.model.extra_data['_record']))
def update_doc(pid, data): """Updates the given doc record.""" from invenio_records import Record record = Record.get_record(pid.object_uuid) record.update(data) return record