def test_do_not_add_bibtex_citation(self):
     converter = OrcidConverter(
         record=self.inspire_record,
         url_pattern='http://inspirehep.net/record/{recid}',
     )
     xml_root = converter.get_xml()
     top_level_tags = [
         etree.QName(node).localname for node in xml_root.getchildren()
     ]
     assert 'citation' not in top_level_tags
Beispiel #2
0
def calculate_hash_for_record(record):
    """Generate hash for an ORCID-serialised HEP record

    Args:
        record (dict): HEP record

    Returns:
        string: hash of the record
    """
    orcid_rec = OrcidConverter(record, app.config['LEGACY_RECORD_URL_PATTERN'])
    return hash_xml_element(orcid_rec.get_xml())
def test_format_thesis(app, api_client):
    response = api_client.get('/literature/1395663')
    assert response.status_code == 200
    phdthesis = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>MAGIC $\\gamma$-ray observations of distant AGN and a study of source variability and the extragalactic background light using FERMI and air Cherenkov telescopes</common:title>
        </work:title>
        <work:type>dissertation</work:type>
        <work:url>http://inspirehep.net/record/1395663</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>Mankuzhiyil, Nijil</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        phdthesis['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert hash_xml_element(expected) == hash_xml_element(result)
def test_format_book(app, api_client):
    response = api_client.get('/literature/736770')
    assert response.status_code == 200
    book = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>Differential geometry and Lie groups for physicists</common:title>
        </work:title>
        <work:type>book</work:type>
        <common:publication-date>
            <common:year>2011</common:year>
            <common:month>03</common:month>
            <common:day>03</common:day>
        </common:publication-date>
        <common:external-ids>
            <common:external-id>
                <common:external-id-type>isbn</common:external-id-type>
                <common:external-id-value>9780521187961</common:external-id-value>
            </common:external-id>
            <common:external-id>
                <common:external-id-type>isbn</common:external-id-type>
                <common:external-id-value>9780521845076</common:external-id-value>
            </common:external-id>
            <common:external-id>
                <common:external-id-type>isbn</common:external-id-type>
                <common:external-id-value>9780511242960</common:external-id-value>
            </common:external-id>
        </common:external-ids>
        <work:url>http://inspirehep.net/record/736770</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>Fecko, M.</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        book['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert _OrcidHasher(
        mock.Mock())._hash_xml_element(expected) == _OrcidHasher(
            mock.Mock())._hash_xml_element(result)
def test_format_proceedings(app, api_client):
    response = api_client.get('/literature/701585')
    assert response.status_code == 200
    proceedings = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>HERA and the LHC: A Workshop on the implications of HERA for LHC physics: Proceedings Part A</common:title>
        </work:title>
        <work:type>edited-book</work:type>
        <common:publication-date>
            <common:year>2005</common:year>
        </common:publication-date>
        <common:external-ids>
            <common:external-id>
                <common:external-id-type>arxiv</common:external-id-type>
                <common:external-id-value>hep-ph/0601012</common:external-id-value>
                <common:external-id-url>http://arxiv.org/abs/hep-ph/0601012</common:external-id-url>
                <common:external-id-relationship>self</common:external-id-relationship>
            </common:external-id>
        </common:external-ids>
        <work:url>http://inspirehep.net/record/701585</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>De Roeck, A.</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>editor</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
            <work:contributor>
                <work:credit-name>Jung, H.</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>additional</work:contributor-sequence>
                    <work:contributor-role>editor</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        proceedings['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert _OrcidHasher(
        mock.Mock())._hash_xml_element(expected) == _OrcidHasher(
            mock.Mock())._hash_xml_element(result)
def test_format_thesis_with_author_orcid(app, api_client):
    response = api_client.get('/literature/1395663')
    assert response.status_code == 200
    phdthesis = json.loads(response.data)

    phdthesis['metadata']['authors'][0]['ids'] = [{
        'schema':
        'ORCID',
        'value':
        '0000-0002-1825-0097',
    }]
    phdthesis['metadata']['authors'][0]['emails'] = ['*****@*****.**']

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>MAGIC $\\gamma$-ray observations of distant AGN and a study of source variability and the extragalactic background light using FERMI and air Cherenkov telescopes</common:title>
        </work:title>
        <work:type>dissertation</work:type>
        <work:url>http://inspirehep.net/record/1395663</work:url>
        <work:contributors>
            <work:contributor>
                <common:contributor-orcid>
                    <common:uri>http://orcid.org/0000-0002-1825-0097</common:uri>
                    <common:path>0000-0002-1825-0097</common:path>
                    <common:host>orcid.org</common:host>
                </common:contributor-orcid>
                <work:credit-name>Mankuzhiyil, Nijil</work:credit-name>
                <work:contributor-email>[email protected]</work:contributor-email>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        phdthesis['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert _OrcidHasher(
        mock.Mock())._hash_xml_element(expected) == _OrcidHasher(
            mock.Mock())._hash_xml_element(result)
def test_format_article(app, api_client):
    response = api_client.get('/literature/4328')
    assert response.status_code == 200
    article = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>Partial Symmetries of Weak Interactions</common:title>
        </work:title>
        <work:journal-title>Nucl.Phys.</work:journal-title>
        <work:type>journal-article</work:type>
        <common:publication-date>
            <common:year>1961</common:year>
        </common:publication-date>
        <common:external-ids>
            <common:external-id>
                <common:external-id-type>doi</common:external-id-type>
                <common:external-id-value>10.1016/0029-5582(61)90469-2</common:external-id-value>
                <common:external-id-url>http://dx.doi.org/10.1016/0029-5582(61)90469-2</common:external-id-url>
                <common:external-id-relationship>self</common:external-id-relationship>
            </common:external-id>
        </common:external-ids>
        <work:url>http://inspirehep.net/record/4328</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>Glashow, S.L.</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        article['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert _OrcidHasher(
        mock.Mock())._hash_xml_element(expected) == _OrcidHasher(
            mock.Mock())._hash_xml_element(result)
def test_format_conference_paper(app, api_client):
    response = api_client.get('/literature/524480')
    assert response.status_code == 200
    inproceedings = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>CMB anisotropies: A Decadal survey</common:title>
        </work:title>
        <work:journal-title>4th RESCEU International Symposium on Birth and Evolution of the Universe</work:journal-title>
        <work:type>conference-paper</work:type>
        <common:external-ids>
            <common:external-id>
                <common:external-id-type>arxiv</common:external-id-type>
                <common:external-id-value>astro-ph/0002520</common:external-id-value>
                <common:external-id-url>http://arxiv.org/abs/astro-ph/0002520</common:external-id-url>
                <common:external-id-relationship>self</common:external-id-relationship>
            </common:external-id>
        </common:external-ids>
        <work:url>http://inspirehep.net/record/524480</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>Hu, Wayne</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        inproceedings['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert _OrcidHasher(
        mock.Mock())._hash_xml_element(expected) == _OrcidHasher(
            mock.Mock())._hash_xml_element(result)
def test_format_book_chapter(app, api_client):
    response = api_client.get('/literature/1375491')
    assert response.status_code == 200
    inbook = json.loads(response.data)

    expected = xml_parse("""
    <work:work xmlns:common="http://www.orcid.org/ns/common" xmlns:work="http://www.orcid.org/ns/work">
        <work:title>
            <common:title>Supersymmetry</common:title>
        </work:title>
        <work:type>book-chapter</work:type>
        <common:publication-date>
            <common:year>2015</common:year>
        </common:publication-date>
        <common:external-ids>
            <common:external-id>
                <common:external-id-type>doi</common:external-id-type>
                <common:external-id-value>10.1007/978-3-319-15001-7_10</common:external-id-value>
                <common:external-id-url>http://dx.doi.org/10.1007/978-3-319-15001-7_10</common:external-id-url>
                <common:external-id-relationship>self</common:external-id-relationship>
            </common:external-id>
            <common:external-id>
                <common:external-id-type>arxiv</common:external-id-type>
                <common:external-id-value>1506.03091</common:external-id-value>
                <common:external-id-url>http://arxiv.org/abs/1506.03091</common:external-id-url>
                <common:external-id-relationship>self</common:external-id-relationship>
            </common:external-id>
        </common:external-ids>
        <work:url>http://inspirehep.net/record/1375491</work:url>
        <work:contributors>
            <work:contributor>
                <work:credit-name>Bechtle, Philip</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>first</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
            <work:contributor>
                <work:credit-name>Plehn, Tilman</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>additional</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
                <work:contributor>
                <work:credit-name>Sander, Christian</work:credit-name>
                <work:contributor-attributes>
                    <work:contributor-sequence>additional</work:contributor-sequence>
                    <work:contributor-role>author</work:contributor-role>
                </work:contributor-attributes>
            </work:contributor>
        </work:contributors>
    </work:work>
    """)

    result = OrcidConverter(
        inbook['metadata'],
        url_pattern='http://inspirehep.net/record/{recid}',
    ).get_xml()
    assert valid_against_schema(result)
    assert xml_compare(expected, result)
    assert hash_xml_element(expected) == hash_xml_element(result)
Beispiel #10
0
def push_record_with_orcid(recid, orcid, oauth_token):
    """Push record to ORCID with a specific ORCID ID.

    Args:
        recid (string): HEP record to push
        orcid (string): ORCID identifier to push onto
        oauth_token (string): ORCID user OAUTH token

    Returns:
        Tuple[string, string]: a tuple with two elements:
            - the put-code of the inserted item,
            - and the new hash of the ORCID record
    """
    inspire_record = get_db_record('lit', recid)
    orcid_cache = OrcidCache(orcid, recid)

    putcode = orcid_cache.read_work_putcode()
    if not orcid_cache.has_work_content_changed(inspire_record):
        LOGGER.info(
            'Hash unchanged: not pushing #%s as not a meaningful update'
            ' for orcid:', recid, orcid)
        return putcode

    # TODO Move bibtex serialization into the the converter
    try:
        bibtex = bibtex_v1.serialize(recid, inspire_record)
    except Exception:
        bibtex = None
        LOGGER.error(
            'Pushing record #%s without BibTex, as fetching it failed!', recid)

    # TODO Split orcid API client networking part from our business logic.
    # This TODO is also a requirement for proper app monitoring.
    orcid_api = _get_api()

    orcid_xml = OrcidConverter(inspire_record,
                               app.config['LEGACY_RECORD_URL_PATTERN'],
                               put_code=putcode,
                               bibtex_citation=bibtex).get_xml()

    lock_name = 'orcid:{}'.format(orcid)

    # It's an update: PUT.
    if putcode:
        LOGGER.info(
            "Pushing record #%s with put-code %s onto %s.",
            recid,
            putcode,
            orcid,
        )
        with log_time_context('Pushing updated record', LOGGER), \
                distributed_lock(lock_name, blocking=True):
            orcid_api.update_record(
                orcid_id=orcid,
                token=oauth_token,
                request_type='work',
                data=orcid_xml,
                put_code=putcode,
                content_type='application/orcid+xml',
            )

    # It's a new record: POST.
    else:
        LOGGER.info(
            "No put-code found, pushing new record #%s to ORCID %s.",
            recid,
            orcid,
        )

        try:
            with log_time_context('Pushing new record', LOGGER), \
                    distributed_lock(lock_name, blocking=True):
                putcode = orcid_api.add_record(
                    orcid_id=orcid,
                    token=oauth_token,
                    request_type='work',
                    data=orcid_xml,
                    content_type='application/orcid+xml',
                )
        except Exception as exc:
            if DuplicatedExternalIdentifiersError.match(exc):
                recache_author_putcodes(orcid, oauth_token)
                putcode = orcid_cache.read_work_putcode()
                if not putcode:
                    raise PutcodeNotFoundInCacheException(
                        'Putcode not found in cache for recid {} after having'
                        ' recached all putcodes for the orcid {}'.format(
                            recid, orcid))
                return push_record_with_orcid(recid, orcid, oauth_token)
            else:
                raise
        if not putcode:
            raise ValueError('Empty putcode not allowed')

    LOGGER.info("Push of %s onto %s completed with put-code %s.", recid, orcid,
                putcode)

    orcid_cache.write_work_putcode(putcode, inspire_record)
    return putcode
Beispiel #11
0
def push_record_with_orcid(recid,
                           orcid,
                           oauth_token,
                           put_code=None,
                           old_hash=None):
    """Push record to ORCID with a specific ORCID ID.

    Args:
        recid (string): HEP record to push
        orcid (string): ORCID identifier to push onto
        oauth_token (string): ORCID user OAUTH token
        put_code (Union[string, NoneType]): put-code to push record onto,
            if None will push as a new record
        old_hash (Optional[string]): previous hash of the record

    Returns:
        Tuple[string, string]: a tuple with two elements:
            - the put-code of the inserted item,
            - and the new hash of the ORCID record
    """
    record = get_db_record('lit', recid)

    new_hash = calculate_hash_for_record(record)
    if new_hash == old_hash:
        LOGGER.info(
            'Hash unchanged: not pushing #%s as not a meaningful update',
            recid)
        return put_code, new_hash

    try:
        bibtex = bibtex_v1.serialize(recid, record)
    except Exception:
        bibtex = None
        LOGGER.error(
            'Pushing record #%s without BibTex, as fetching it failed!', recid)

    orcid_api = _get_api()

    orcid_xml = OrcidConverter(record,
                               app.config['LEGACY_RECORD_URL_PATTERN'],
                               put_code=put_code,
                               bibtex_citation=bibtex).get_xml()

    lock_name = 'orcid:{}'.format(orcid)

    if put_code:
        LOGGER.info(
            "Pushing record #%s with put-code %s onto %s.",
            recid,
            put_code,
            orcid,
        )
        with log_time_context('Pushing updated record', LOGGER), \
                distributed_lock(lock_name, blocking=True):
            orcid_api.update_record(
                orcid_id=orcid,
                token=oauth_token,
                request_type='work',
                data=orcid_xml,
                put_code=put_code,
                content_type='application/orcid+xml',
            )
    else:
        LOGGER.info(
            "No put-code found, pushing new record #%s to ORCID %s.",
            recid,
            orcid,
        )
        with log_time_context('Pushing new record', LOGGER), \
                distributed_lock(lock_name, blocking=True):
            put_code = orcid_api.add_record(
                orcid_id=orcid,
                token=oauth_token,
                request_type='work',
                data=orcid_xml,
                content_type='application/orcid+xml',
            )

    LOGGER.info("Push of %s onto %s completed with put-code %s.", recid, orcid,
                put_code)

    return put_code, new_hash