def _create_record(data={}, published=True): data['$schema'] = (current_app.extensions['invenio-jsonschemas']. path_to_url('records/record-v0.1.0.json')) _deposit = data.pop('_deposit', {}) data_to_use = create_loaded_record(data) record = Deposit.create(data_to_use) # Have to modify `_deposit` content after the record is initially # created because `_deposit` is used to choose to mint or not if _deposit: for key, value in _deposit.items(): record.model.json['_deposit'][key] = value db.session.add(record.model) if published: record.publish() pid, record = record.fetch_published() # Flush to index and database current_search.flush_and_refresh(index='*') db.session.commit() return record
def test_fetch_deposit(create_record): unpublished_record = create_record(published=False) unpublished_record.publish() _, published_record = unpublished_record.fetch_published() _, deposit = Deposit.fetch_deposit(published_record) assert unpublished_record == deposit
def test_deposit_publish_sets_appropriate_types(locations): deposit = Deposit.create({}) deposit_record = deposit.publish() pid, published_record = deposit_record.fetch_published() assert deposit_record['type'] == RecordType.draft.value assert published_record['type'] == RecordType.published.value
def test_deposit_create_creates_recordsbuckets(locations): assert RecordsBuckets.query.first() is None assert RecordMetadata.query.first() is None assert Bucket.query.first() is None deposit = Deposit.create({}) record_bucket = RecordsBuckets.query.first() record = RecordMetadata.query.first() buckets = Bucket.query.all() assert record_bucket assert record_bucket.record == record assert record_bucket.bucket in buckets
def test_register_doi_task_succeeds( config, create_record, patched_externalities): """Test successful doi task.""" original_datacite_doi_prefix = config['PIDSTORE_DATACITE_DOI_PREFIX'] config['PIDSTORE_DATACITE_DOI_PREFIX'] = '10.5072' original_doi_register_signals = config['DOI_REGISTER_SIGNALS'] config['DOI_REGISTER_SIGNALS'] = False # To be sure returned_doi = '10.5072/qwer-tyui' patched_client, patched_indexer = patched_externalities # NOTE: `create_record` does NOT trigger register_doi bc # DOI_REGISTER_SIGNALS set to False record = create_record() doi_pid = PersistentIdentifier.get(pid_type='doi', pid_value=record['id']) register_doi(record['id']) # Validate proper usage of DataCite API assert patched_client.metadata_post.called_with( datacite_v41.serialize(doi_pid, record) ) assert patched_client.doi_post.called_with( returned_doi, 'https://localhost:5000/records/{}'.format(record['id']) ) # Validate DOI update doi_pid = PersistentIdentifier.get(pid_type='doi', pid_value=returned_doi) assert doi_pid recid_pid, record = record_resolver.resolve(str(record['id'])) depid_pid, deposit = Deposit.fetch_deposit(record) assert deposit['doi'] == returned_doi assert record['doi'] == returned_doi assert doi_pid.is_registered() and not doi_pid.is_new() # Validate indexing assert patched_indexer.index.called config['PIDSTORE_DATACITE_DOI_PREFIX'] = original_datacite_doi_prefix config['DOI_REGISTER_SIGNALS'] = original_doi_register_signals
def test_deposit_create_fills_data(locations): data = {} deposit = Deposit.create(data) assert data['_buckets']['deposit']
def register_doi(recid_pid_value): """External DOI registration task. This asynchronous task mints a DOI with the external service and stores it in the local doi PID. It will retry a `max_retries` number of times. If a new record is private, then the landing URL is not provided, so that the DOI is in 'draft' mode on DataCite. TODO: If an old public record is made private, remove its DOI from DataCite search. This is not a big need though since the DOI link will still resolve. Summary of states: 'draft': * has a non-resolvable (no landing page) DOI * is not indexed in DataCite search * may not even have metadata * via MDS API: obtained by not assigning a landing page to a record 'registered': * has a resolvable (landing page) DOI * has metadata * is indexed in DataCite search * via MDS API: obtained by API call on 'findable' record 'findable': * has a resolvable (landing page) DOI * has metadata * is indexed in DataCite search * via MDS API: obtained by assigning a landing page to a record Refer to [DataCite states](https://support.datacite.org/docs/doi-states). `default_retry_delay` is in seconds. :param recid_pid_value: pid_value of recid-PID for the target record. Note that this pid_value is also the pid_value of the doi-PID associated with the target record if it has not been DOI-minted yet. """ try: recid_pid, record = record_resolver.resolve(str(recid_pid_value)) depid_pid, deposit = Deposit.fetch_deposit(record) doi_pid_value = record.get('doi') or recid_pid_value doi_pid = PersistentIdentifier.get(pid_type='doi', pid_value=doi_pid_value) client = DataCiteMDSClient( username=current_app.config['PIDSTORE_DATACITE_USERNAME'], password=current_app.config['PIDSTORE_DATACITE_PASSWORD'], prefix=current_app.config['PIDSTORE_DATACITE_DOI_PREFIX'], test_mode=current_app.config['PIDSTORE_DATACITE_TESTMODE'], url=current_app.config['PIDSTORE_DATACITE_URL']) # Update DataCite metadata and let DataCite mint new DOI if unknown DOI serialized_record = datacite_v41.serialize(doi_pid, record) result = client.metadata_post(serialized_record) minted_doi = extract_doi(result) if not RecordPermissions.is_private(record): landing_url = url_for_record_ui_recid_external(recid_pid_value) client.doi_post(minted_doi, landing_url) # TODO: elif is private now, but previous version was not, # make record 'registered' on DataCite. # Dependent on versioning and PID status logic. if doi_pid.is_new(): # Update doi_pid doi_pid.pid_value = minted_doi doi_pid.register() # Update deposit/record deposit['doi'] = minted_doi record['doi'] = minted_doi deposit.commit() record.commit() # The above only flushes (no db commit). The below is needed to # persist the changes to the db. db.session.commit() # Re-index deposit/record RecordIndexer().index(deposit) RecordIndexer().index(record) except (HttpError, DataCiteError) as e: register_doi.retry(exc=e) except RequestError: current_app.logger.exception('Could not index {}.'.format(record)) except Exception as e: current_app.logger.exception( 'Exception in register_doi for recid_pid_value: {}. Retrying...'. format(recid_pid_value)) register_doi.retry(exc=e)