forked from glotzerlab/signac-flow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
.sync-zenodo-metadata.py
executable file
·100 lines (84 loc) · 3.01 KB
/
.sync-zenodo-metadata.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#!/usr/bin/env python3
"""Synchronize authors and contributor metadata.
This script synchronizes the metadata provided in the CITATION.cff and
the contributors.yaml file with the metadata stored in the .zenodo.json
file.
All authors should be listed in the CITATION.cff file, while contributors
should be listed in the contributors.yaml file.
Both files use the [citation file-format][1] for [person objects][2].
[1] https://citation-file-format.github.io/
[2] https://citation-file-format.github.io/1.0.3/specifications/#/person-objects
"""
import json
from dataclasses import dataclass
from typing import Optional
import click
from ruamel.yaml import Loader, load
@dataclass
class Contributor:
last_names: str
first_names: str
affiliation: str
orcid: Optional[str] = None
@classmethod
def from_citation_author(cls, **citation):
return cls(
last_names=citation.pop("family-names"),
first_names=citation.pop("given-names"),
**citation,
)
def as_zenodo_creator(self):
ret = dict(
name=f"{self.first_names} {self.last_names}", affiliation=self.affiliation
)
if self.orcid:
ret["orcid"] = self.orcid.lstrip("https://orcid.org/")
return ret
@click.command()
@click.pass_context
@click.option(
"--check",
default=False,
is_flag=True,
help="Return with non-zero exit code if metadata needs to be updated.",
)
@click.option(
"-i", "--in-place", type=bool, is_flag=True, help="Modify metadata in place."
)
def sync(ctx, in_place=False, check=True):
with open("CITATION.cff", "rb") as file:
citation = load(file.read(), Loader=Loader)
authors = [
Contributor.from_citation_author(**author) for author in citation["authors"]
]
with open("contributors.yaml", "rb") as file:
contributors = load(file.read(), Loader=Loader)["contributors"]
contributors = [
Contributor.from_citation_author(**contributor)
for contributor in contributors
]
with open(".zenodo.json", "rb") as file:
zenodo = json.loads(file.read())
zenodo_updated = zenodo.copy()
zenodo_updated["creators"] = [a.as_zenodo_creator() for a in authors]
zenodo_updated["contributors"] = [
c.as_zenodo_creator() for c in contributors if c not in authors
]
for key in ("version", "keywords"):
zenodo_updated[key] = citation[key]
def dump_json_utf8(content):
return json.dumps(content, sort_keys=True, indent=4, ensure_ascii=False)
modified = dump_json_utf8(zenodo) != dump_json_utf8(zenodo_updated)
if modified:
json_data = dump_json_utf8(zenodo_updated)
if in_place:
with open(".zenodo.json", "wb") as file:
file.write((json_data + "\n").encode("utf-8"))
else:
click.echo(json_data)
if check:
ctx.exit(1)
else:
click.echo("No changes.", err=True)
if __name__ == "__main__":
sync()