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
|
#!/usr/bin/env python3
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "fuzzywuzzy",
# "gitpython",
# "python-levenshtein",
# ]
# ///
"""Update and sort the creators list of the zenodo record."""
import git
import json
from subprocess import run, PIPE
from pathlib import Path
from fuzzywuzzy import fuzz, process
def decommify(name):
return " ".join(name.split(", ")[::-1])
# These names should go last
CREATORS_LAST = ["Krzysztof J. Gorgolewski", "Satrajit Ghosh"]
# Contributors that have requested not to be cited (or bothered)
BLACKLIST = {"Jonathan R. Williford"}
if __name__ == "__main__":
git_root = Path(git.Repo(".", search_parent_directories=True).working_dir)
zenodo_file = git_root / ".zenodo.json"
zenodo = json.loads(zenodo_file.read_text()) if zenodo_file.exists() else {}
creator_map = {
decommify(creator["name"]): creator for creator in zenodo.get("creators", [])
}
shortlog = run(["git", "shortlog", "-ns"], stdout=PIPE)
commit_counts = dict(
line.split("\t", 1)[::-1]
for line in shortlog.stdout.decode().split("\n")
if line
)
existing_creators = set(creator_map.keys())
committers = []
# Stable sort:
# Number of commits in descending order
# Ties broken by alphabetical order of first name
for committer, _ in sorted(commit_counts.items(), key=lambda x: (-int(x[1]), x[0])):
matches = process.extract(
committer, creator_map.keys(), scorer=fuzz.token_sort_ratio, limit=2
)
match, score = matches[0]
if score <= 80:
if committer not in BLACKLIST:
print("No entry to sort:", committer)
continue
existing_creators.discard(match)
committers.append(match)
for unmatched in sorted(existing_creators):
print("No matching commits:", unmatched)
# Keep the entries to avoid removing people for bad matching
committers.append(unmatched)
for last_author in CREATORS_LAST:
if committers[-1] != last_author:
committers.remove(last_author)
committers.append(last_author)
creators = [
creator_map.get(committer, {"name": committer}) for committer in committers
]
zenodo["creators"] = creators
zenodo_file.write_text(
"%s\n" % json.dumps(zenodo, indent=2, ensure_ascii=False), encoding='utf-8'
)
|