def test_it_fails_when_it_cannot_generate_a_unique_doi(self): # the datacite client returns an existing (mock) doi every time, so unlikely! mock_client = MagicMock(metadata_get=MagicMock()) # the db returns an existing (mock) doi every time, so unlikely! mock_read_doi = MagicMock() with patch('ckanext.doi.lib.api.DataCiteMDSClient', mock_client): with patch('ckanext.doi.lib.api.DOIQuery.read_doi', mock_read_doi): api = DataciteClient() with pytest.raises(Exception, match='Failed to generate a DOI'): api.generate_doi()
def test_one_existing_on_datacite_and_one_in_the_db(self): # the first call to the datacite client returns a (mock) doi but then the next one succeeds mock_client = MagicMock(metadata_get=MagicMock( side_effect=first_then(MagicMock(), DataCiteNotFoundError()))) # the first call to the db returns a result but then after that we're all good mock_read_doi = MagicMock(side_effect=first_then(MagicMock(), None)) with patch('ckanext.doi.lib.api.DataCiteMDSClient', MagicMock(return_value=mock_client)): with patch('ckanext.doi.lib.api.DOIQuery.read_doi', mock_read_doi): api = DataciteClient() doi = api.generate_doi() assert isinstance(doi, str)
def test_one_existing_db_doi(self): # no dois in datacite mock_client = MagicMock(metadata_get=MagicMock( side_effect=DataCiteNotFoundError())) # one doi in the database that hits the first call, but then the next time is fine mock_read_doi = MagicMock(side_effect=first_then(MagicMock(), None)) with patch('ckanext.doi.lib.api.DataCiteMDSClient', MagicMock(return_value=mock_client)): with patch('ckanext.doi.lib.api.DOIQuery.read_doi', mock_read_doi): api = DataciteClient() doi = api.generate_doi() assert isinstance(doi, str)
def read_package(cls, package_id, create_if_none=False): ''' Retrieve a record associated with a given package. :param package_id: the id of the package :param create_if_none: generate a new DOI and add a record if no record is found for the given package :return: the record object ''' from ckanext.doi.lib.api import DataciteClient record = Session.query(DOI).filter( DOI.package_id == package_id).first() if record is None and create_if_none: client = DataciteClient() new_doi = client.generate_doi() record = cls.create(new_doi, package_id) return record
def test_test_mode_true(self, mock_client): DataciteClient() assert mock_client.called_once_with(username='******', password='******', prefix='testing', test_mode=True, url=DataciteClient.test_url)
def test_basics(self, mock_client): DataciteClient() assert mock_client.called_once_with(username='******', password='******', prefix='testing', test_mode=False) assert 'url' not in mock_client.call_args.kwargs
def update_doi(package_ids): ''' Update either all DOIs in the system or the ones associated with the given packages. ''' if not package_ids: dois_to_update = Session.query(DOI).all() else: dois_to_update = list( filter(None, map(DOIQuery.read_package, package_ids))) if len(dois_to_update) == 0: click.secho('No DOIs found to update', fg='green') return for record in dois_to_update: pkg_dict = toolkit.get_action('package_show')({}, { 'id': record.package_id }) title = pkg_dict.get('title', record.package_id) if record.published is None: click.secho(f'"{title}" does not have a published DOI; ignoring', fg='yellow') continue if pkg_dict.get('state', 'active') != 'active' or pkg_dict.get( 'private', False): click.secho(f'"{title}" is inactive or private; ignoring', fg='yellow') continue metadata_dict = build_metadata_dict(pkg_dict) xml_dict = build_xml_dict(metadata_dict) client = DataciteClient() same = client.check_for_update(record.identifier, xml_dict) if not same: try: client.set_metadata(record.identifier, xml_dict) click.secho(f'Updated "{title}"', fg='green') except DataCiteError as e: click.secho( f'Error while updating "{title}" (DOI {record.identifier}): {e})', fg='red') else: click.secho(f'"{title}" is already up to date', fg='green')
def test_no_existing_dois(self): # no dois in datacite mock_client = MagicMock(metadata_get=MagicMock( side_effect=DataCiteNotFoundError())) # no dois in the database mock_read_doi = MagicMock(return_value=None) with patch('ckanext.doi.lib.api.DataCiteMDSClient', MagicMock(return_value=mock_client)): with patch('ckanext.doi.lib.api.DOIQuery.read_doi', mock_read_doi): api = DataciteClient() doi = api.generate_doi() assert isinstance(doi, str) # both the client and the database should be called once and only once (yes this # goes against the comment at the start of this class but it felt relevant here to # check that this was the case) assert mock_client.metadata_get.call_count == 1 assert mock_read_doi.call_count == 1
def test_datacite_api_order(self, mock_crud): mock_crud.read_doi = MagicMock(return_value=None) mock_crud.read_package = MagicMock(return_value=None) api = DataciteClient() doi = constants.XML_DICT['identifiers'][0]['identifier'] pkg_id = MagicMock() with pytest.raises(DataCiteError): api.mint_doi(doi, pkg_id) api.set_metadata(doi, constants.XML_DICT) api.mint_doi(doi, pkg_id)
def after_update(self, context, pkg_dict): '''Dataset has been created/updated. Check status of the dataset to determine if we should publish DOI to datacite network. ''' # Is this active and public? If so we need to make sure we have an active DOI if pkg_dict.get('state', 'active') == 'active' and not pkg_dict.get('private', False): package_id = pkg_dict['id'] # remove user-defined update schemas first (if needed) context.pop('schema', None) # Load the package_show version of the dict pkg_show_dict = toolkit.get_action('package_show')(context, { 'id': package_id }) # Load or create the local DOI (package may not have a DOI if extension was loaded # after package creation) doi = DOIQuery.read_package(package_id, create_if_none=True) metadata_dict = build_metadata_dict(pkg_show_dict) xml_dict = build_xml_dict(metadata_dict) client = DataciteClient() if doi.published is None: # metadata gets created before minting client.set_metadata(doi.identifier, xml_dict) client.mint_doi(doi.identifier, package_id) toolkit.h.flash_success('DataCite DOI created') else: same = client.check_for_update(doi.identifier, xml_dict) if not same: # Not the same, so we want to update the metadata client.set_metadata(doi.identifier, xml_dict) toolkit.h.flash_success('DataCite DOI metadata updated') return pkg_dict
def test_both_exist(self, mock_crud): mock_crud.read_doi = MagicMock(return_value=MagicMock()) mock_crud.read_package = MagicMock(return_value=MagicMock()) api = DataciteClient() doi = constants.XML_DICT['identifiers'][0]['identifier'] pkg_id = MagicMock() api.set_metadata(doi, constants.XML_DICT) api.mint_doi(doi, pkg_id) assert not mock_crud.create.called assert not mock_crud.update_package.called assert mock_crud.update_doi.called