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)
示例#4
0
 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
示例#7
0
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)
示例#10
0
    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