From 5f3133435474d42619dfa4abe0f089790a466d3c Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Mon, 13 Sep 2021 15:09:14 +0200 Subject: [PATCH 1/7] citation from csl --- doi2cff/cli.py | 101 +++++++++++++++++++++++++++++++++------------- tests/test_cli.py | 18 +++++++++ 2 files changed, 92 insertions(+), 27 deletions(-) diff --git a/doi2cff/cli.py b/doi2cff/cli.py index cd4ac34..36f0673 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -4,6 +4,7 @@ import sys import re from datetime import datetime +from typing import Any, Tuple import click from nameparser import HumanName @@ -29,6 +30,60 @@ def is_software_zenodo(zenodo_record): return zenodo_record['metadata']['resource_type']['type'] == 'software' +def zenodo_record_to_cff_yaml(zenodo_record: dict, template) -> Tuple[ruamel.yaml.YAML, Any]: + yaml = ruamel.yaml.YAML() + data = yaml.load(template) + data['title'] = zenodo_record['metadata']['title'] + data['doi'] = zenodo_record['doi'] + tagurl = tagurl_of_zenodo(zenodo_record) + if 'version' in zenodo_record['metadata']: + data['version'] = re.sub('^(v)', '', zenodo_record['metadata']['version']) + else: + data['version'] = tagurl2version(tagurl) + data['license'] = zenodo_record['metadata']['license']['id'] + data['date-released'] = datetime.strptime(zenodo_record['metadata']['publication_date'], "%Y-%m-%d").date() + data['repository-code'] = tagurl2repo(tagurl) + data['authors'] = authors_of_zenodo(zenodo_record) + references = references_of_zenodo(zenodo_record) + fixme = 'FIXME generic is too generic, ' \ + 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' + if references: + data['references'] = yaml.seq(references) + for idx, r in enumerate(references): + if r['type'] == 'generic': + data['references'].yaml_add_eol_comment(fixme, idx) + + return yaml, data + + +def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any]: + # TODO: to complete! + yaml = ruamel.yaml.YAML() + data = yaml.load(template) + + data['title'] = cffjson['title'] + data['doi'] = cffjson['DOI'] + #tagurl = tagurl_of_zenodo(cffjson) + # if 'version' in cffjson['metadata']: + # data['version'] = re.sub('^(v)', '', cffjson['metadata']['version']) + # else: + # data['version'] = tagurl2version(tagurl) + data['license'] = cffjson['license'] + data['date-released'] = datetime(*cffjson['published-print']['date-parts'][0], 1).date() + #data['repository-code'] = tagurl2repo(tagurl) + data['authors'] = authors_of_csl(cffjson) + #references = references_of_zenodo(cffjson) + # fixme = 'FIXME generic is too generic, ' \ + # 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' + # if references: + # data['references'] = yaml.seq(references) + # for idx, r in enumerate(references): + # if r['type'] == 'generic': + # data['references'].yaml_add_eol_comment(fixme, idx) + + return yaml, data + + @main.command() @click.argument('doi') @click.option('--cff_fn', @@ -36,7 +91,12 @@ def is_software_zenodo(zenodo_record): default='CITATION.cff', help='Name of citation formatted output file', show_default=True) -def init(doi, cff_fn): +@click.option('--experimental/--no-experimental', + is_flag=True, + default=False, + help='experimental non-zenodo', + show_default=True) +def init(doi, cff_fn, experimental): """Generate CITATION.cff file based on a Zenodo DOI of a Github release. * DOI, The Digital Object Identifier (DOI) name of a Zenodo upload of a GitHub release @@ -56,35 +116,22 @@ def init(doi, cff_fn): license: x ''' - if not doi_is_from_zenodo(doi): - raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload') - - zenodo_record = fetch_zenodo_by_doiurl(doi) + if doi_is_from_zenodo(doi): + zenodo_record = fetch_zenodo_by_doiurl(doi) - if not is_software_zenodo(zenodo_record): - raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload of type software') + if not is_software_zenodo(zenodo_record): + raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload of type software') - yaml = ruamel.yaml.YAML() - data = yaml.load(template) - data['title'] = zenodo_record['metadata']['title'] - data['doi'] = zenodo_record['doi'] - tagurl = tagurl_of_zenodo(zenodo_record) - if 'version' in zenodo_record['metadata']: - data['version'] = re.sub('^(v)', '', zenodo_record['metadata']['version']) + yaml, data = zenodo_record_to_cff_yaml(zenodo_record, template) else: - data['version'] = tagurl2version(tagurl) - data['license'] = zenodo_record['metadata']['license']['id'] - data['date-released'] = datetime.strptime(zenodo_record['metadata']['publication_date'], "%Y-%m-%d").date() - data['repository-code'] = tagurl2repo(tagurl) - data['authors'] = authors_of_zenodo(zenodo_record) - references = references_of_zenodo(zenodo_record) - fixme = 'FIXME generic is too generic, ' \ - 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' - if references: - data['references'] = yaml.seq(references) - for idx, r in enumerate(references): - if r['type'] == 'generic': - data['references'].yaml_add_eol_comment(fixme, idx) + if experimental: + click.echo("allow experimental") + csljson = fetch_csljson(doi) + + yaml, data = csljson_to_cff_yaml(csljson, template) + else: + raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload') + yaml.dump(data, cff_fn) diff --git a/tests/test_cli.py b/tests/test_cli.py index a2189d3..f81571d 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -94,3 +94,21 @@ def test_init_withnonzenodoref(runner, zenodo_58369, cslfor_58369, cff_58369): expected = cff_58369 assert yaml.load(result) == yaml.load(expected) + + +def test_init_csl(runner): + # TODO: complete! + doi = '10.1051/0004-6361/202037850' + + with runner.isolated_filesystem(): + #with runner.isolated_filesystem(), requests_mock.mock() as m: + #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_mock) + #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) + + runner.invoke(init, [doi]) + + with open('CITATION.cff', 'r') as f: + result = f.read() + + #expected = cff_58369 + #assert yaml.load(result) == yaml.load(expected) From 6c519442efda11f923ffc65ec5cff50363200684 Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Wed, 15 Sep 2021 20:54:23 +0200 Subject: [PATCH 2/7] some comments, references --- doi2cff/cli.py | 30 +++++++++++++----------------- tests/test_cli.py | 10 ++++++---- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/doi2cff/cli.py b/doi2cff/cli.py index 36f0673..7787d16 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -21,6 +21,7 @@ def main(): Current supported DOI types: * Zenodo upload of a GitHub release (https://guides.github.com/activities/citable-code/) + * Any DOIs with suitable metadata (experimental). """ pass @@ -63,23 +64,15 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] data['title'] = cffjson['title'] data['doi'] = cffjson['DOI'] - #tagurl = tagurl_of_zenodo(cffjson) - # if 'version' in cffjson['metadata']: - # data['version'] = re.sub('^(v)', '', cffjson['metadata']['version']) - # else: - # data['version'] = tagurl2version(tagurl) data['license'] = cffjson['license'] data['date-released'] = datetime(*cffjson['published-print']['date-parts'][0], 1).date() - #data['repository-code'] = tagurl2repo(tagurl) data['authors'] = authors_of_csl(cffjson) - #references = references_of_zenodo(cffjson) - # fixme = 'FIXME generic is too generic, ' \ - # 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' - # if references: - # data['references'] = yaml.seq(references) - # for idx, r in enumerate(references): - # if r['type'] == 'generic': - # data['references'].yaml_add_eol_comment(fixme, idx) + references = cffjson['reference'] + if references: + data['references'] = yaml.seq(references) + # for idx, r in enumerate(references): + # if r['type'] == 'generic': + # data['references'].yaml_add_eol_comment(fixme, idx) return yaml, data @@ -94,7 +87,7 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] @click.option('--experimental/--no-experimental', is_flag=True, default=False, - help='experimental non-zenodo', + help='experimental parsing of non-zenodo links', show_default=True) def init(doi, cff_fn, experimental): """Generate CITATION.cff file based on a Zenodo DOI of a Github release. @@ -125,12 +118,15 @@ def init(doi, cff_fn, experimental): yaml, data = zenodo_record_to_cff_yaml(zenodo_record, template) else: if experimental: - click.echo("allow experimental") + click.echo("Trying experimental parsing of arbitrary DOI") csljson = fetch_csljson(doi) + ruamel.yaml.dump(csljson, open("/tmp/csl.json", "w")) + yaml, data = csljson_to_cff_yaml(csljson, template) else: - raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload') + raise click.UsageError('Unable to process DOI name, normally we only accept DOI name which is a Zenodo upload' + 'You can try experimental parsing of other DOIs (see --experimental option).') yaml.dump(data, cff_fn) diff --git a/tests/test_cli.py b/tests/test_cli.py index f81571d..5d79c4a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -100,15 +100,17 @@ def test_init_csl(runner): # TODO: complete! doi = '10.1051/0004-6361/202037850' - with runner.isolated_filesystem(): +# with runner.isolated_filesystem(): + # with runner.isolated_filesystem(): #with runner.isolated_filesystem(), requests_mock.mock() as m: #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_mock) #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) + if True: - runner.invoke(init, [doi]) + runner.invoke(init, [doi, '--experimental', '--cff_fn', '/tmp/CITATION.cff'], catch_exceptions=False) - with open('CITATION.cff', 'r') as f: + with open('/tmp/CITATION.cff', 'r') as f: result = f.read() #expected = cff_58369 - #assert yaml.load(result) == yaml.load(expected) + assert str(yaml.load(result)) == "" #yaml.load("expected") From 095899ef4fbe72a5ec748dbe659e3c3cd53124a1 Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Mon, 27 Dec 2021 16:49:12 +0100 Subject: [PATCH 3/7] fixed tests --- doi2cff/cli.py | 38 ++-- tests/conftest.py | 431 ++++++++++++++++++++++++++++++++++++++++++++++ tests/test_cli.py | 39 +++-- tox.ini | 2 + 4 files changed, 479 insertions(+), 31 deletions(-) diff --git a/doi2cff/cli.py b/doi2cff/cli.py index 7787d16..eabdce7 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -53,27 +53,32 @@ def zenodo_record_to_cff_yaml(zenodo_record: dict, template) -> Tuple[ruamel.yam for idx, r in enumerate(references): if r['type'] == 'generic': data['references'].yaml_add_eol_comment(fixme, idx) - + return yaml, data def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any]: - # TODO: to complete! + # TODO: to complete, see version and so! yaml = ruamel.yaml.YAML() data = yaml.load(template) data['title'] = cffjson['title'] + #TODO: warn for multi-line + data['doi'] = cffjson['DOI'] data['license'] = cffjson['license'] - data['date-released'] = datetime(*cffjson['published-print']['date-parts'][0], 1).date() + data['date-released'] = datetime(*cffjson['published']['date-parts'][0], 1).date() data['authors'] = authors_of_csl(cffjson) - references = cffjson['reference'] + + references = cffjson.get('reference', None) + fixme = 'FIXME generic is too generic, ' \ + 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' if references: data['references'] = yaml.seq(references) - # for idx, r in enumerate(references): - # if r['type'] == 'generic': - # data['references'].yaml_add_eol_comment(fixme, idx) - + for idx, r in enumerate(references): + if r.get('type', 'generic') == 'generic': + data['references'].yaml_add_eol_comment(fixme, idx) + return yaml, data @@ -113,21 +118,20 @@ def init(doi, cff_fn, experimental): zenodo_record = fetch_zenodo_by_doiurl(doi) if not is_software_zenodo(zenodo_record): - raise click.UsageError('Unable to process DOI name, only accept DOI name which is a Zenodo upload of type software') + raise click.UsageError('Unable to process DOI name, only accept DOI name ' + 'which is a Zenodo upload of type software') - yaml, data = zenodo_record_to_cff_yaml(zenodo_record, template) + yaml, data = zenodo_record_to_cff_yaml(zenodo_record, template) else: if experimental: click.echo("Trying experimental parsing of arbitrary DOI") csljson = fetch_csljson(doi) - - ruamel.yaml.dump(csljson, open("/tmp/csl.json", "w")) - - yaml, data = csljson_to_cff_yaml(csljson, template) + yaml, data = csljson_to_cff_yaml(csljson, template) else: - raise click.UsageError('Unable to process DOI name, normally we only accept DOI name which is a Zenodo upload' - 'You can try experimental parsing of other DOIs (see --experimental option).') - + raise click.UsageError('Unable to process DOI name, normally we only accept DOI name ' + 'which is a Zenodo upload' + 'You can try experimental parsing of other DOIs ' + '(see --experimental option).') yaml.dump(data, cff_fn) diff --git a/tests/conftest.py b/tests/conftest.py index 34f0d1b..b7bc4a3 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1028,3 +1028,434 @@ def cff_58369(): - given-names: Jan PG family-names: Klomp ''' + + +@pytest.fixture +def cff_202037850(): + return '''# YAML 1.2 +# Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) +cff-version: 1.0.3 +message: If you use this software, please cite it using these metadata. +# FIXME title as repository name might not be the best name, please make human readable +title: Online data analysis system of the INTEGRAL telescope +doi: 10.1051/0004-6361/202037850 +# FIXME splitting of full names is error prone, please check if given/family name are correct +authors: +- given-names: A. + family-names: Neronov +- given-names: V. + family-names: Savchenko +- given-names: A. + family-names: Tramacere +- given-names: M. + family-names: Meharga +- given-names: C. + family-names: Ferrigno +- given-names: S. + family-names: Paltani +version: x +date-released: 2021-04-27 +repository-code: x +license: +- start: + date-parts: + - - 2021 + - 4 + - 27 + date-time: '2021-04-27T00:00:00Z' + timestamp: 1619481600000 + content-version: vor + delay-in-days: 0 + URL: https://www.edpsciences.org/en/authors/copyright-and-licensing +''' + + +@pytest.fixture +def cff_aa8f94(): + return '''# YAML 1.2 +# Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) +cff-version: 1.0.3 +message: If you use this software, please cite it using these metadata. +# FIXME title as repository name might not be the best name, please make human readable +title: "INTEGRAL\\n Detection of the First Prompt Gamma-Ray Signal Coincident with the Gravitational-wave Event GW170817" +doi: 10.3847/2041-8213/aa8f94 +# FIXME splitting of full names is error prone, please check if given/family name are correct +authors: +- given-names: V. + family-names: Savchenko +- given-names: C. + family-names: Ferrigno +- given-names: E. + family-names: Kuulkers +- given-names: A. + family-names: Bazzano +- given-names: E. + family-names: Bozzo +- given-names: S. + family-names: Brandt +- given-names: J. + family-names: Chenevez +- given-names: T. J.-L. + family-names: Courvoisier +- given-names: R. + family-names: Diehl +- given-names: A. + family-names: Domingo +- given-names: L. + family-names: Hanlon +- given-names: E. + family-names: Jourdain +- given-names: A. + family-names: von Kienlin +- given-names: P. + family-names: Laurent +- given-names: F. + family-names: Lebrun +- given-names: A. + family-names: Lutovinov +- given-names: A. + family-names: Martin-Carrillo +- given-names: S. + family-names: Mereghetti +- given-names: L. + family-names: Natalucci +- given-names: J. + family-names: Rodi +- given-names: J.-P. + family-names: Roques +- given-names: R. + family-names: Sunyaev +- given-names: P. + family-names: Ubertini +version: x +date-released: 2017-10-16 +repository-code: x +license: +- start: + date-parts: + - - 2017 + - 10 + - 16 + date-time: '2017-10-16T00:00:00Z' + timestamp: 1508112000000 + content-version: tdm + delay-in-days: 0 + URL: http://iopscience.iop.org/info/page/text-and-data-mining +- start: + date-parts: + - - 2017 + - 10 + - 16 + date-time: '2017-10-16T00:00:00Z' + timestamp: 1508112000000 + content-version: vor + delay-in-days: 0 + URL: http://iopscience.iop.org/page/copyright +references: +- key: '1' + doi-asserted-by: publisher + DOI: 10.1103/PhysRevLett.116.061102 +- key: '2' + doi-asserted-by: publisher + DOI: 10.1103/PhysRevLett.116.241103 +- key: '3' + doi-asserted-by: publisher + DOI: 10.1007/lrr-2016-1 +- key: '4' + doi-asserted-by: publisher + DOI: 10.1103/PhysRevLett.118.221101 +- key: '5' + doi-asserted-by: publisher + DOI: 10.1103/PhysRevLett.119.161101 +- key: '6' + doi-asserted-by: publisher + DOI: 10.1088/0264-9381/32/2/024001 + volume: '32' + author: Acernese F. + year: '2015' + journal-title: CQGra + ISSN: http://id.crossref.org/issn/0264-9381 + issn-type: print +- key: '7' + doi-asserted-by: publisher + DOI: 10.1146/annurev-astro-081913-035926 +- key: '8' + first-page: '177' + volume: '10' + author: Blinnikov S. I. + year: '1984' + journal-title: SvAL +- key: '9' + first-page: '21505' + author: Connaughton V. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '10' + first-page: '21529' + author: Coulter D. A. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '11' + doi-asserted-by: publisher + first-page: '790' + DOI: 10.1086/510201 + volume: '655' + author: Crook A. C. + year: '2007' + journal-title: ApJ + ISSN: http://id.crossref.org/issn/0004-637X + issn-type: print +- key: '12' + doi-asserted-by: publisher + DOI: 10.1016/j.jheap.2015.07.002 +- key: '13' + volume: '21592' + author: D’Elia V. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '14' + first-page: '21530' + author: DESGW+Community Team + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '15' + first-page: '21550' + author: Evans P. A. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '16' + doi-asserted-by: publisher + DOI: 10.1146/annurev-nucl-102115-044819 +- key: '17' + first-page: '21557' + author: Foley R. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '18' + doi-asserted-by: publisher + DOI: 10.1126/science.1216793 +- key: '19' + doi-asserted-by: publisher + first-page: '39' + DOI: 10.1088/0004-637X/809/1/39 + volume: '809' + author: Giacomazzo B. + year: '2015' + journal-title: ApJ + ISSN: http://id.crossref.org/issn/0004-637X + issn-type: print +- key: '20' + doi-asserted-by: publisher + DOI: 10.3847/2041-8213/aa8f41 +- key: '21' + doi-asserted-by: publisher + first-page: '759' + DOI: 10.1086/427976 + volume: '622' + author: Górski K. M. + year: '2005' + journal-title: ApJ + ISSN: http://id.crossref.org/issn/0004-637X + issn-type: print +- key: '22' + doi-asserted-by: publisher + DOI: 10.1093/mnras/stw404 +- key: '23' + doi-asserted-by: publisher + DOI: 10.1038/nature03519 +- key: '24' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031356 +- key: '25' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031367 +- key: '26' + doi-asserted-by: publisher + volume: '32' + author: LIGO Scientific Collaboration + year: '2015' + journal-title: CQGra + DOI: 10.1088/0264-9381/32/7/074001 +- key: '27' + first-page: '21505' + author: LIGO Scientific Collaboration & Virgo Collaboration + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '28' + first-page: '21513' + author: LIGO Scientific Collaboration & Virgo Collaboration + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '29' + first-page: '21527' + author: LIGO Scientific Collaboration & Virgo Collaboration + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '30' + first-page: '21509' + author: LIGO Scientific Collaboration & Virgo Collaboration + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '31' + first-page: '21474' + author: LIGO Scientific Collaboration & Virgo Collaboration + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '32' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031358 +- key: '33' + author: LVC + year: '2017' + journal-title: ApJL + issn-type: print + ISSN: http://id.crossref.org/issn/0004-637X +- key: '34' + first-page: '21582' + author: Lyman J. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '35' + doi-asserted-by: publisher + DOI: 10.1093/mnras/276.1.273 +- key: '36' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031418 +- key: '37' + doi-asserted-by: publisher + first-page: L74 + DOI: 10.1088/0004-637X/696/1/L74 + volume: '696' + author: Mereghetti S. + year: '2009' + journal-title: ApJL + ISSN: http://id.crossref.org/issn/0004-637X + issn-type: print +- key: '38' + doi-asserted-by: publisher + DOI: 10.1007/s41114-017-0006-z +- key: '39' + doi-asserted-by: publisher + DOI: 10.1093/mnras/stu247 +- key: '40' + doi-asserted-by: publisher + DOI: 10.1016/j.physrep.2007.02.005 +- key: '41' + doi-asserted-by: publisher + DOI: 10.1126/science.1125201 +- key: '42' + doi-asserted-by: publisher + first-page: '15' + DOI: 10.1088/0004-637X/763/1/15 + volume: '763' + author: Qin Y. + year: '2013' + journal-title: ApJ + ISSN: http://id.crossref.org/issn/0004-637X + issn-type: print +- key: '43' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031259 +- key: '44' + doi-asserted-by: publisher + DOI: 10.1093/mnras/sts683 +- key: '45' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361/201730572 +- key: '46' + first-page: '21507' + author: Savchenko V. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '47' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361/200911988 +- key: '48' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361/201218877 +- key: '49' + doi-asserted-by: publisher + DOI: 10.3847/2041-8213/aa905e +- key: '50' + doi-asserted-by: publisher + DOI: 10.3847/2041-8213/aa9059 +- key: '51' + doi-asserted-by: publisher + DOI: 10.1093/mnras/227.2.403 +- key: '52' + first-page: '21515' + author: Svinkin D. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '53' + author: Tanaka M. + year: '2017' + journal-title: ApJ +- key: '54' + doi-asserted-by: publisher + DOI: 10.1038/nature24290 +- key: '55' + first-page: '21682' + author: Troja E. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '56' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031224 +- key: '57' + doi-asserted-by: publisher + DOI: 10.3847/2041-8213/aa8edf +- key: '58' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031482 +- key: '59' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031231 +- key: '60' + volume: '21520' + author: von Kienlin A. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +- key: '61' + doi-asserted-by: publisher + DOI: 10.1051/0004-6361:20031288 +- key: '62' + first-page: '21531' + author: Yang S. + year: '2017' + journal-title: GCN + issn-type: print + ISSN: http://id.crossref.org/issn/0147-0728 +''' \ No newline at end of file diff --git a/tests/test_cli.py b/tests/test_cli.py index 5d79c4a..dfd1eab 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -5,7 +5,7 @@ from io import StringIO import pytest -import yaml +import ruamel.yaml from click.testing import CliRunner import requests_mock @@ -13,6 +13,7 @@ from doi2cff import cli from doi2cff.cli import init, update_version +yaml = ruamel.yaml.YAML(typ='safe', pure=True) @pytest.fixture def runner(): @@ -95,22 +96,32 @@ def test_init_withnonzenodoref(runner, zenodo_58369, cslfor_58369, cff_58369): expected = cff_58369 assert yaml.load(result) == yaml.load(expected) +def test_init_csl_withref(runner, cff_aa8f94): + # TODO: complete! + #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) + doi = '10.3847/2041-8213/aa8f94' + + #with runner.isolated_filesystem(), requests_mock.mock() as m: + with runner.isolated_filesystem(): + runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) + + with open('CITATION.cff', 'r') as f: + result = f.read() + + #expected = cff_58369 + assert yaml.load(result) == yaml.load(cff_aa8f94) -def test_init_csl(runner): - # TODO: complete! - doi = '10.1051/0004-6361/202037850' -# with runner.isolated_filesystem(): - # with runner.isolated_filesystem(): - #with runner.isolated_filesystem(), requests_mock.mock() as m: - #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_mock) - #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) - if True: +def test_init_csl_noref(runner, cff_202037850): + # TODO: complete! + #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) + doi = '10.1051/0004-6361/202037850' - runner.invoke(init, [doi, '--experimental', '--cff_fn', '/tmp/CITATION.cff'], catch_exceptions=False) + #with runner.isolated_filesystem(), requests_mock.mock() as m: + with runner.isolated_filesystem(): + runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) - with open('/tmp/CITATION.cff', 'r') as f: + with open('CITATION.cff', 'r') as f: result = f.read() - #expected = cff_58369 - assert str(yaml.load(result)) == "" #yaml.load("expected") + assert yaml.load(result) == yaml.load(cff_202037850) diff --git a/tox.ini b/tox.ini index 7084084..fbd2326 100644 --- a/tox.ini +++ b/tox.ini @@ -3,6 +3,8 @@ envlist = py35, flake8 [travis] python = + 3.9: py39 + 3.8: py38 3.7: py37 3.6: py36 3.5: py35 From 4344f60b15967b9c2987ea83fddb8230143cdd33 Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Mon, 27 Dec 2021 17:15:54 +0100 Subject: [PATCH 4/7] remove optional fields --- doi2cff/cli.py | 8 +++++++- tests/conftest.py | 4 ---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/doi2cff/cli.py b/doi2cff/cli.py index eabdce7..a2543b5 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -63,7 +63,8 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] data = yaml.load(template) data['title'] = cffjson['title'] - #TODO: warn for multi-line + if '\n' in data['title']: + data.yaml_add_eol_comment("FIXME: title contains new line: this is strange", "title") data['doi'] = cffjson['DOI'] data['license'] = cffjson['license'] @@ -79,6 +80,11 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] if r.get('type', 'generic') == 'generic': data['references'].yaml_add_eol_comment(fixme, idx) + # In CFF 1.2.0 these fields are optional + # https://github.com/citation-file-format/citation-file-format/releases/tag/1.2.0 + del data['version'] + del data['repository-code'] + return yaml, data diff --git a/tests/conftest.py b/tests/conftest.py index b7bc4a3..d0318a7 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1053,9 +1053,7 @@ def cff_202037850(): family-names: Ferrigno - given-names: S. family-names: Paltani -version: x date-released: 2021-04-27 -repository-code: x license: - start: date-parts: @@ -1127,9 +1125,7 @@ def cff_aa8f94(): family-names: Sunyaev - given-names: P. family-names: Ubertini -version: x date-released: 2017-10-16 -repository-code: x license: - start: date-parts: From da1017b2f26208dc276c7921a7e6f90c13e10497 Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Mon, 27 Dec 2021 17:34:37 +0100 Subject: [PATCH 5/7] increment CFF version --- docs/usage.rst | 15 ++++++++++++++- doi2cff/cli.py | 13 +++++++++---- tests/conftest.py | 18 +++++++++--------- 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/docs/usage.rst b/docs/usage.rst index ee91249..1b4f8b0 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -13,9 +13,22 @@ To create a CITATION.cff file of a release, you must supply the doi that is asso The generated file must be checked for correctness and you are encouraged to enrich it further. +The command above works well for Zenodo doi's, which contain especially rich metadata. +It is also possible to produce a CITATION.cff file from any available information. This feature is experimental: + +.. code-block:: bash + + doi2cff init --experimental + + # For example + doi2cff init 10.1051/0004-6361/202037850 --experimental + + Whenever a new release is made of the software the CITATION.cff must be updated with new doi/version/release date. -This process can be automated by running +This process can be automated by running (only for Zenodo dois) .. code-block:: bash doi2cff update + + diff --git a/doi2cff/cli.py b/doi2cff/cli.py index a2543b5..7c6bb05 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -47,7 +47,7 @@ def zenodo_record_to_cff_yaml(zenodo_record: dict, template) -> Tuple[ruamel.yam data['authors'] = authors_of_zenodo(zenodo_record) references = references_of_zenodo(zenodo_record) fixme = 'FIXME generic is too generic, ' \ - 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' + 'see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types' if references: data['references'] = yaml.seq(references) for idx, r in enumerate(references): @@ -58,7 +58,6 @@ def zenodo_record_to_cff_yaml(zenodo_record: dict, template) -> Tuple[ruamel.yam def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any]: - # TODO: to complete, see version and so! yaml = ruamel.yaml.YAML() data = yaml.load(template) @@ -73,7 +72,7 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] references = cffjson.get('reference', None) fixme = 'FIXME generic is too generic, ' \ - 'see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types' + 'see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types' if references: data['references'] = yaml.seq(references) for idx, r in enumerate(references): @@ -107,7 +106,7 @@ def init(doi, cff_fn, experimental): """ template = '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: x @@ -156,6 +155,12 @@ def update(doi, cff_fn): * DOI, The Digital Object Identifier (DOI) name of a Zenodo upload of a GitHub release """ + + if not doi_is_from_zenodo(doi): + raise click.UsageError('CITATION.cff update is only possible with Zenodo DOI. ' + 'For non-Zenodo DOIs, please consider recreating the citation, enabling experimental features: ' + '`doi2cff init --experimental`') + update_version(doi, cff_fn) diff --git a/tests/conftest.py b/tests/conftest.py index d0318a7..21d98c9 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -250,7 +250,7 @@ def zenodo_1194353(): def cff_1200251(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: Xenon @@ -304,7 +304,7 @@ def cff_1200251(): def cff_1194353(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: 'NLeSC/Xenon: This is release 2.6.0 of Xenon.' @@ -357,7 +357,7 @@ def cff_1194353(): def cff_1194353_updated_1200251(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: 'NLeSC/Xenon: This is release 2.6.0 of Xenon.' @@ -496,7 +496,7 @@ def zenodo_1197761(): def cff_1197761(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: Xenon gRPC server @@ -517,7 +517,7 @@ def cff_1197761(): repository-code: https://github.com/NLeSC/xenon-grpc license: Apache-2.0 references: -- # FIXME generic is too generic, see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types +- # FIXME generic is too generic, see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types type: generic doi: 10.5281/zenodo.597993 title: Xenon @@ -991,7 +991,7 @@ def cslfor_58369(): def cff_58369(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: 'knime-sstea: v1.0.5' @@ -1007,7 +1007,7 @@ def cff_58369(): repository-code: https://github.com/3D-e-Chem/knime-sstea license: Apache-2.0 references: -- # FIXME generic is too generic, see https://citation-file-format.github.io/1.0.3/specifications/#/reference-types for more specific types +- # FIXME generic is too generic, see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types type: generic doi: 10.1186/1471-2105-12-332 title: 'ss-TEA: Entropy based identification of receptor specific ligand binding @@ -1034,7 +1034,7 @@ def cff_58369(): def cff_202037850(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: Online data analysis system of the INTEGRAL telescope @@ -1072,7 +1072,7 @@ def cff_202037850(): def cff_aa8f94(): return '''# YAML 1.2 # Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.0.3 +cff-version: 1.2.0 message: If you use this software, please cite it using these metadata. # FIXME title as repository name might not be the best name, please make human readable title: "INTEGRAL\\n Detection of the First Prompt Gamma-Ray Signal Coincident with the Gravitational-wave Event GW170817" From 00af97571b6a2c8d5440c18e0598e625f19dadee Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Mon, 27 Dec 2021 17:47:03 +0100 Subject: [PATCH 6/7] remove near-duplicate test --- tests/conftest.py | 560 ++++++++++++++-------------------------------- tests/test_cli.py | 23 +- 2 files changed, 177 insertions(+), 406 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 21d98c9..a760a8f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1069,389 +1069,177 @@ def cff_202037850(): @pytest.fixture -def cff_aa8f94(): - return '''# YAML 1.2 -# Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) -cff-version: 1.2.0 -message: If you use this software, please cite it using these metadata. -# FIXME title as repository name might not be the best name, please make human readable -title: "INTEGRAL\\n Detection of the First Prompt Gamma-Ray Signal Coincident with the Gravitational-wave Event GW170817" -doi: 10.3847/2041-8213/aa8f94 -# FIXME splitting of full names is error prone, please check if given/family name are correct -authors: -- given-names: V. - family-names: Savchenko -- given-names: C. - family-names: Ferrigno -- given-names: E. - family-names: Kuulkers -- given-names: A. - family-names: Bazzano -- given-names: E. - family-names: Bozzo -- given-names: S. - family-names: Brandt -- given-names: J. - family-names: Chenevez -- given-names: T. J.-L. - family-names: Courvoisier -- given-names: R. - family-names: Diehl -- given-names: A. - family-names: Domingo -- given-names: L. - family-names: Hanlon -- given-names: E. - family-names: Jourdain -- given-names: A. - family-names: von Kienlin -- given-names: P. - family-names: Laurent -- given-names: F. - family-names: Lebrun -- given-names: A. - family-names: Lutovinov -- given-names: A. - family-names: Martin-Carrillo -- given-names: S. - family-names: Mereghetti -- given-names: L. - family-names: Natalucci -- given-names: J. - family-names: Rodi -- given-names: J.-P. - family-names: Roques -- given-names: R. - family-names: Sunyaev -- given-names: P. - family-names: Ubertini -date-released: 2017-10-16 -license: -- start: - date-parts: - - - 2017 - - 10 - - 16 - date-time: '2017-10-16T00:00:00Z' - timestamp: 1508112000000 - content-version: tdm - delay-in-days: 0 - URL: http://iopscience.iop.org/info/page/text-and-data-mining -- start: - date-parts: - - - 2017 - - 10 - - 16 - date-time: '2017-10-16T00:00:00Z' - timestamp: 1508112000000 - content-version: vor - delay-in-days: 0 - URL: http://iopscience.iop.org/page/copyright -references: -- key: '1' - doi-asserted-by: publisher - DOI: 10.1103/PhysRevLett.116.061102 -- key: '2' - doi-asserted-by: publisher - DOI: 10.1103/PhysRevLett.116.241103 -- key: '3' - doi-asserted-by: publisher - DOI: 10.1007/lrr-2016-1 -- key: '4' - doi-asserted-by: publisher - DOI: 10.1103/PhysRevLett.118.221101 -- key: '5' - doi-asserted-by: publisher - DOI: 10.1103/PhysRevLett.119.161101 -- key: '6' - doi-asserted-by: publisher - DOI: 10.1088/0264-9381/32/2/024001 - volume: '32' - author: Acernese F. - year: '2015' - journal-title: CQGra - ISSN: http://id.crossref.org/issn/0264-9381 - issn-type: print -- key: '7' - doi-asserted-by: publisher - DOI: 10.1146/annurev-astro-081913-035926 -- key: '8' - first-page: '177' - volume: '10' - author: Blinnikov S. I. - year: '1984' - journal-title: SvAL -- key: '9' - first-page: '21505' - author: Connaughton V. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '10' - first-page: '21529' - author: Coulter D. A. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '11' - doi-asserted-by: publisher - first-page: '790' - DOI: 10.1086/510201 - volume: '655' - author: Crook A. C. - year: '2007' - journal-title: ApJ - ISSN: http://id.crossref.org/issn/0004-637X - issn-type: print -- key: '12' - doi-asserted-by: publisher - DOI: 10.1016/j.jheap.2015.07.002 -- key: '13' - volume: '21592' - author: D’Elia V. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '14' - first-page: '21530' - author: DESGW+Community Team - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '15' - first-page: '21550' - author: Evans P. A. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '16' - doi-asserted-by: publisher - DOI: 10.1146/annurev-nucl-102115-044819 -- key: '17' - first-page: '21557' - author: Foley R. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '18' - doi-asserted-by: publisher - DOI: 10.1126/science.1216793 -- key: '19' - doi-asserted-by: publisher - first-page: '39' - DOI: 10.1088/0004-637X/809/1/39 - volume: '809' - author: Giacomazzo B. - year: '2015' - journal-title: ApJ - ISSN: http://id.crossref.org/issn/0004-637X - issn-type: print -- key: '20' - doi-asserted-by: publisher - DOI: 10.3847/2041-8213/aa8f41 -- key: '21' - doi-asserted-by: publisher - first-page: '759' - DOI: 10.1086/427976 - volume: '622' - author: Górski K. M. - year: '2005' - journal-title: ApJ - ISSN: http://id.crossref.org/issn/0004-637X - issn-type: print -- key: '22' - doi-asserted-by: publisher - DOI: 10.1093/mnras/stw404 -- key: '23' - doi-asserted-by: publisher - DOI: 10.1038/nature03519 -- key: '24' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031356 -- key: '25' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031367 -- key: '26' - doi-asserted-by: publisher - volume: '32' - author: LIGO Scientific Collaboration - year: '2015' - journal-title: CQGra - DOI: 10.1088/0264-9381/32/7/074001 -- key: '27' - first-page: '21505' - author: LIGO Scientific Collaboration & Virgo Collaboration - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '28' - first-page: '21513' - author: LIGO Scientific Collaboration & Virgo Collaboration - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '29' - first-page: '21527' - author: LIGO Scientific Collaboration & Virgo Collaboration - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '30' - first-page: '21509' - author: LIGO Scientific Collaboration & Virgo Collaboration - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '31' - first-page: '21474' - author: LIGO Scientific Collaboration & Virgo Collaboration - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '32' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031358 -- key: '33' - author: LVC - year: '2017' - journal-title: ApJL - issn-type: print - ISSN: http://id.crossref.org/issn/0004-637X -- key: '34' - first-page: '21582' - author: Lyman J. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '35' - doi-asserted-by: publisher - DOI: 10.1093/mnras/276.1.273 -- key: '36' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031418 -- key: '37' - doi-asserted-by: publisher - first-page: L74 - DOI: 10.1088/0004-637X/696/1/L74 - volume: '696' - author: Mereghetti S. - year: '2009' - journal-title: ApJL - ISSN: http://id.crossref.org/issn/0004-637X - issn-type: print -- key: '38' - doi-asserted-by: publisher - DOI: 10.1007/s41114-017-0006-z -- key: '39' - doi-asserted-by: publisher - DOI: 10.1093/mnras/stu247 -- key: '40' - doi-asserted-by: publisher - DOI: 10.1016/j.physrep.2007.02.005 -- key: '41' - doi-asserted-by: publisher - DOI: 10.1126/science.1125201 -- key: '42' - doi-asserted-by: publisher - first-page: '15' - DOI: 10.1088/0004-637X/763/1/15 - volume: '763' - author: Qin Y. - year: '2013' - journal-title: ApJ - ISSN: http://id.crossref.org/issn/0004-637X - issn-type: print -- key: '43' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031259 -- key: '44' - doi-asserted-by: publisher - DOI: 10.1093/mnras/sts683 -- key: '45' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361/201730572 -- key: '46' - first-page: '21507' - author: Savchenko V. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '47' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361/200911988 -- key: '48' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361/201218877 -- key: '49' - doi-asserted-by: publisher - DOI: 10.3847/2041-8213/aa905e -- key: '50' - doi-asserted-by: publisher - DOI: 10.3847/2041-8213/aa9059 -- key: '51' - doi-asserted-by: publisher - DOI: 10.1093/mnras/227.2.403 -- key: '52' - first-page: '21515' - author: Svinkin D. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '53' - author: Tanaka M. - year: '2017' - journal-title: ApJ -- key: '54' - doi-asserted-by: publisher - DOI: 10.1038/nature24290 -- key: '55' - first-page: '21682' - author: Troja E. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '56' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031224 -- key: '57' - doi-asserted-by: publisher - DOI: 10.3847/2041-8213/aa8edf -- key: '58' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031482 -- key: '59' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031231 -- key: '60' - volume: '21520' - author: von Kienlin A. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -- key: '61' - doi-asserted-by: publisher - DOI: 10.1051/0004-6361:20031288 -- key: '62' - first-page: '21531' - author: Yang S. - year: '2017' - journal-title: GCN - issn-type: print - ISSN: http://id.crossref.org/issn/0147-0728 -''' \ No newline at end of file +def cslfor_202037850(): + """Content was generated with: + + curl -L -H 'Accept: application/vnd.citationstyles.csl+json' \ + https://doi.org/10.1051/0004-6361/202037850 + """ + return { + "indexed": { + "date-parts": [ + [ + 2021, + 12, + 9 + ] + ], + "date-time": "2021-12-09T19:25:39Z", + "timestamp": 1639077939575 + }, + "reference-count": 0, + "publisher": "EDP Sciences", + "license": [ + { + "start": { + "date-parts": [ + [ + 2021, + 4, + 27 + ] + ], + "date-time": "2021-04-27T00:00:00Z", + "timestamp": 1619481600000 + }, + "content-version": "vor", + "delay-in-days": 0, + "URL": "https://www.edpsciences.org/en/authors/copyright-and-licensing" + } + ], + "content-domain": { + "domain": [], + "crossmark-restriction": False + }, + "accepted": { + "date-parts": [ + [ + 2021, + 3, + 8 + ] + ] + }, + "DOI": "10.1051/0004-6361/202037850", + "type": "journal-article", + "created": { + "date-parts": [ + [ + 2021, + 4, + 27 + ] + ], + "date-time": "2021-04-27T08:30:49Z", + "timestamp": 1619512249000 + }, + "source": "Crossref", + "is-referenced-by-count": 0, + "title": "Online data analysis system of the INTEGRAL telescope", + "prefix": "10.1051", + "author": [ + { + "given": "A.", + "family": "Neronov", + "sequence": "first", + "affiliation": [] + }, + { + "given": "V.", + "family": "Savchenko", + "sequence": "additional", + "affiliation": [] + }, + { + "given": "A.", + "family": "Tramacere", + "sequence": "additional", + "affiliation": [] + }, + { + "given": "M.", + "family": "Meharga", + "sequence": "additional", + "affiliation": [] + }, + { + "given": "C.", + "family": "Ferrigno", + "sequence": "additional", + "affiliation": [] + }, + { + "given": "S.", + "family": "Paltani", + "sequence": "additional", + "affiliation": [] + } + ], + "member": "250", + "published-online": { + "date-parts": [ + [ + 2021, + 4, + 27 + ] + ] + }, + "container-title": "Astronomy & Astrophysics", + "original-title": [], + "link": [ + { + "URL": "https://www.aanda.org/10.1051/0004-6361/202037850/pdf", + "content-type": "unspecified", + "content-version": "vor", + "intended-application": "similarity-checking" + } + ], + "deposited": { + "date-parts": [ + [ + 2021, + 6, + 1 + ] + ], + "date-time": "2021-06-01T18:58:58Z", + "timestamp": 1622573938000 + }, + "score": 1, + "subtitle": [], + "short-title": [], + "issued": { + "date-parts": [ + [ + 2021, + 4, + 27 + ] + ] + }, + "references-count": 0, + "alternative-id": [ + "aa37850-20" + ], + "URL": "http://dx.doi.org/10.1051/0004-6361/202037850", + "relation": {}, + "ISSN": [ + "0004-6361", + "1432-0746" + ], + "subject": [ + "Space and Planetary Science", + "Astronomy and Astrophysics" + ], + "container-title-short": "A&A", + "published": { + "date-parts": [ + [ + 2021, + 4, + 27 + ] + ] + } +} diff --git a/tests/test_cli.py b/tests/test_cli.py index dfd1eab..1eff754 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -96,29 +96,12 @@ def test_init_withnonzenodoref(runner, zenodo_58369, cslfor_58369, cff_58369): expected = cff_58369 assert yaml.load(result) == yaml.load(expected) -def test_init_csl_withref(runner, cff_aa8f94): +def test_init_csl_noref(runner, cff_202037850, cslfor_202037850): # TODO: complete! - #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) - doi = '10.3847/2041-8213/aa8f94' - - #with runner.isolated_filesystem(), requests_mock.mock() as m: - with runner.isolated_filesystem(): - runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) - - with open('CITATION.cff', 'r') as f: - result = f.read() - - #expected = cff_58369 - assert yaml.load(result) == yaml.load(cff_aa8f94) - - -def test_init_csl_noref(runner, cff_202037850): - # TODO: complete! - #m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) doi = '10.1051/0004-6361/202037850' - #with runner.isolated_filesystem(), requests_mock.mock() as m: - with runner.isolated_filesystem(): + with runner.isolated_filesystem(), requests_mock.mock() as m: + m.get('https://doi.org/10.1051/0004-6361/202037850', json=cslfor_202037850) runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) with open('CITATION.cff', 'r') as f: From 1f49448350564107f2007646ca6f6ad85e21a6d7 Mon Sep 17 00:00:00 2001 From: Volodymyr Savchenko Date: Tue, 28 Dec 2021 09:17:41 +0100 Subject: [PATCH 7/7] add another test --- doi2cff/cli.py | 5 +- tests/conftest.py | 173 ++++++++++++++++++++++++++++++++++++++++++++++ tests/test_cli.py | 25 ++++++- 3 files changed, 199 insertions(+), 4 deletions(-) diff --git a/doi2cff/cli.py b/doi2cff/cli.py index 7c6bb05..c27b453 100644 --- a/doi2cff/cli.py +++ b/doi2cff/cli.py @@ -66,7 +66,10 @@ def csljson_to_cff_yaml(cffjson: dict, template) -> Tuple[ruamel.yaml.YAML, Any] data.yaml_add_eol_comment("FIXME: title contains new line: this is strange", "title") data['doi'] = cffjson['DOI'] - data['license'] = cffjson['license'] + + if 'license' in cffjson: + data['license'] = cffjson['license'] + data['date-released'] = datetime(*cffjson['published']['date-parts'][0], 1).date() data['authors'] = authors_of_csl(cffjson) diff --git a/tests/conftest.py b/tests/conftest.py index a760a8f..7666736 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1243,3 +1243,176 @@ def cslfor_202037850(): ] } } + + + +@pytest.fixture +def cff_1995729(): + return '''# YAML 1.2 +# Metadata for citation of this software according to the CFF format (https://citation-file-format.github.io/) +cff-version: 1.2.0 +message: If you use this software, please cite it using these metadata. +# FIXME title as repository name might not be the best name, please make human readable +title: Albert Einstein to Max Born 1 +doi: 10.1063/1.1995729 +# FIXME splitting of full names is error prone, please check if given/family name are correct +authors: +- given-names: Albert + family-names: Einstein +date-released: 2005-05-01 +license: x +references: +- # FIXME generic is too generic, see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types + key: c1 + unstructured: 'M. Born , The Born–Einstein Letters 1916–1955: Freindship, Politics + and Physics in Uncertain Times, Macmillan, New York (2005), p. 88. Original letter + © The Hebrew University of Jerusalem, Israel.' +- # FIXME generic is too generic, see https://citation-file-format.github.io/1.2.0/specifications/#/reference-types for more specific types + key: c2 + volume-title: 'The End of the Uncertain World: The Life and Science of Max Born' + author: Greenspan N. T. + year: '2005' +''' + + +@pytest.fixture +def cslfor_1995729(): + """Content was generated with: + + curl -L -H 'Accept: application/vnd.citationstyles.csl+json' \ + https://doi.org/10.1063/1.1995729 + """ + return { + "indexed": { + "date-parts": [ + [ + 2021, + 12, + 16 + ] + ], + "date-time": "2021-12-16T18:54:42Z", + "timestamp": 1639680882985 + }, + "reference-count": 2, + "publisher": "AIP Publishing", + "issue": "5", + "content-domain": { + "domain": [], + "crossmark-restriction": True + }, + "published-print": { + "date-parts": [ + [ + 2005, + 5 + ] + ] + }, + "DOI": "10.1063/1.1995729", + "type": "journal-article", + "created": { + "date-parts": [ + [ + 2007, + 3, + 13 + ] + ], + "date-time": "2007-03-13T19:20:15Z", + "timestamp": 1173813615000 + }, + "page": "16-16", + "source": "Crossref", + "is-referenced-by-count": 0, + "title": "Albert Einstein to Max Born 1", + "prefix": "10.1063", + "volume": "58", + "author": [ + { + "given": "Albert", + "family": "Einstein", + "sequence": "first", + "affiliation": [] + } + ], + "member": "317", + "reference": [ + { + "key": "c1", + "unstructured": "M. Born , The Born–Einstein Letters 1916–1955: Freindship, Politics and Physics in Uncertain Times, Macmillan, New York (2005), p. 88. Original letter © The Hebrew University of Jerusalem, Israel." + }, + { + "key": "c2", + "volume-title": "The End of the Uncertain World: The Life and Science of Max Born", + "author": "Greenspan N. T.", + "year": "2005" + } + ], + "container-title": "Physics Today", + "original-title": [], + "language": "en", + "link": [ + { + "URL": "http://physicstoday.scitation.org/doi/pdf/10.1063/1.1995729", + "content-type": "unspecified", + "content-version": "vor", + "intended-application": "similarity-checking" + } + ], + "deposited": { + "date-parts": [ + [ + 2016, + 12, + 28 + ] + ], + "date-time": "2016-12-28T18:02:11Z", + "timestamp": 1482948131000 + }, + "score": 1, + "subtitle": [], + "short-title": [], + "issued": { + "date-parts": [ + [ + 2005, + 5 + ] + ] + }, + "references-count": 2, + "journal-issue": { + "issue": "5", + "published-print": { + "date-parts": [ + [ + 2005, + 5 + ] + ] + } + }, + "alternative-id": [ + "10.1063/1.1995729" + ], + "URL": "http://dx.doi.org/10.1063/1.1995729", + "relation": {}, + "ISSN": [ + "0031-9228", + "1945-0699" + ], + "subject": [ + "General Physics and Astronomy" + ], + "container-title-short": "Physics Today", + "published": { + "date-parts": [ + [ + 2005, + 5 + ] + ] + } +} diff --git a/tests/test_cli.py b/tests/test_cli.py index 1eff754..2d4843e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -88,7 +88,8 @@ def test_init_withnonzenodoref(runner, zenodo_58369, cslfor_58369, cff_58369): m.get('https://zenodo.org/api/records/58369', json=zenodo_58369) m.get('https://doi.org/10.1186/1471-2105-12-332', json=cslfor_58369) - runner.invoke(init, [doi]) + runner_result = runner.invoke(init, [doi]) + assert 'Trying experimental parsing of arbitrary DOI' not in runner_result.output with open('CITATION.cff', 'r') as f: result = f.read() @@ -96,15 +97,33 @@ def test_init_withnonzenodoref(runner, zenodo_58369, cslfor_58369, cff_58369): expected = cff_58369 assert yaml.load(result) == yaml.load(expected) + + def test_init_csl_noref(runner, cff_202037850, cslfor_202037850): - # TODO: complete! doi = '10.1051/0004-6361/202037850' with runner.isolated_filesystem(), requests_mock.mock() as m: m.get('https://doi.org/10.1051/0004-6361/202037850', json=cslfor_202037850) - runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) + + runner_result = runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) + assert 'Trying experimental parsing of arbitrary DOI' in runner_result.output with open('CITATION.cff', 'r') as f: result = f.read() assert yaml.load(result) == yaml.load(cff_202037850) + + +def test_init_csl_nolicense(runner, cff_1995729, cslfor_1995729): + # TODO: complete! + doi = '10.1063/1.1995729' + + with runner.isolated_filesystem(), requests_mock.mock() as m: + m.get('https://doi.org/10.1063/1.1995729', json=cslfor_1995729) + runner.invoke(init, [doi, '--experimental', '--cff_fn', 'CITATION.cff'], catch_exceptions=False) + + with open('CITATION.cff', 'r') as f: + result = f.read() + + assert yaml.load(result) == yaml.load(cff_1995729) +