Skip to content

Commit

Permalink
Update Author list and checkings
Browse files Browse the repository at this point in the history
Changed name codemeta_update.py
  • Loading branch information
jose-luis-rs committed Dec 5, 2024
1 parent d5b046d commit b8adc9f
Show file tree
Hide file tree
Showing 5 changed files with 331 additions and 2 deletions.
29 changes: 29 additions & 0 deletions .github/workflows/check_metadata.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# SPDX-FileCopyrightText: 2024 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH, Darmstadt, Germany
#
# SPDX-License-Identifier: CC0-1.0

name: Check AUTHORS and CONTRIBUTORS in metadata

on:
push:
paths:
- AUTHORS
- CONTRIBUTORS
- codemeta.json
- .zenodo.json
pull_request:
paths:
- AUTHORS
- CONTRIBUTORS
- codemeta.json
- .zenodo.json

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Try updating metadata
run: python meta_update.py
- name: Check for Updates
run: git diff --exit-code
51 changes: 51 additions & 0 deletions .zenodo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"creators": [
{
"name": "Alvarez Pol, Hector",
"orcid": "0000-0001-9643-6252"
},
{
"name": "Chatillon, Audrey"
},
{
"name": "Rodriguez Sanchez, Jose Luis",
"orcid": "0000-0002-4702-5294"
}
],
"contributors": [
{
"type": "Other",
"name": "Garcia Jimenez, Gabriel"
},
{
"type": "Other",
"name": "Gra\u00f1a Gonzalez, Antia"
},
{
"type": "Other",
"name": "Mayer, Jan"
},
{
"type": "Other",
"name": "Morfouace, Pierre"
},
{
"type": "Other",
"name": "Taniuchi, Ryo"
},
{
"type": "Other",
"name": "Wang, Yanzhao"
}
],
"description": "SOFIA folder inside R3BRoot describes the SOFIA detectors which are going to be employed for the fission setup within the R3B/GLAD magnet. The R3BRoot software is based on the FairRoot framework and can be used to perform Monte Carlo simulations and experimental data analysis of the R3B (Reactions with Relativistic Radioactive Beams) nuclear physics experiments at the GSI-FAIR research center (Facility for Antiproton and Ion Research).",
"related_identifiers": [
{
"identifier": "https://github.com/R3BRootGroup/sofia/",
"relation": "isSupplementTo",
"resource_type": "software",
"scheme": "url"
}
],
"title": "sofia"
}
4 changes: 2 additions & 2 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
Alvarez Pol, Hector
Alvarez Pol, Hector [https://orcid.org/0000-0001-9643-6252]
Chatillon, Audrey
Rodriguez Sanchez, Jose Luis
Rodriguez Sanchez, Jose Luis [https://orcid.org/0000-0002-4702-5294]
96 changes: 96 additions & 0 deletions codemeta.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
{
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"codeRepository": "https://github.com/R3BRootGroup/sofia",
"contIntegration": "https://github.com/R3BRootGroup/sofia/actions",
"dateCreated": "2017-05-15",
"datePublished": "2017-05-15",
"dateModified": "2024-12-05",
"downloadUrl": "https://github.com/R3BRootGroup/sofia/archive/refs/tags/nov23.tar.gz",
"issueTracker": "https://github.com/R3BRootGroup/sofia/issues",
"name": "sofia",
"softwareVersion": "jun24",
"description": "Software for the SOFIA/R3B fission experiments at FAIR",
"readme": "https://github.com/R3BRootGroup/sofia/blob/dev/README.md",
"releaseNotes": "",
"applicationCategory": "Nuclear physics",
"developmentStatus": "active",
"referencePublication": "https://doi.org/10.1088/1742-6596/523/1/012034",
"keywords": [
"MC simulation",
"Structure and dynamics of nuclei",
"Nuclear reactions",
"Nuclear fission"
],
"programmingLanguage": [
"C",
"C++"
],
"runtimePlatform": [
"ROOT"
],
"operatingSystem": [
"Linux",
"macOS"
],
"softwareRequirements": [
"FairRoot, FairSoft, R3BRoot"
],
"maintainer": {
"@type": "Person",
"givenName": "Jose Luis",
"familyName": "Rodriguez Sanchez",
"@id": "https://orcid.org/0000-0002-4702-5294"
},
"author": [
{
"@type": "Person",
"givenName": "Hector",
"familyName": "Alvarez Pol",
"@id": "https://orcid.org/0000-0001-9643-6252"
},
{
"@type": "Person",
"givenName": "Audrey",
"familyName": "Chatillon"
},
{
"@type": "Person",
"givenName": "Jose Luis",
"familyName": "Rodriguez Sanchez",
"@id": "https://orcid.org/0000-0002-4702-5294"
}
],
"contributor": [
{
"@type": "Person",
"givenName": "Gabriel",
"familyName": "Garcia Jimenez"
},
{
"@type": "Person",
"givenName": "Antia",
"familyName": "Gra\u00f1a Gonzalez"
},
{
"@type": "Person",
"givenName": "Jan",
"familyName": "Mayer"
},
{
"@type": "Person",
"givenName": "Pierre",
"familyName": "Morfouace"
},
{
"@type": "Person",
"givenName": "Ryo",
"familyName": "Taniuchi"
},
{
"@type": "Person",
"givenName": "Yanzhao",
"familyName": "Wang"
}
]
}
153 changes: 153 additions & 0 deletions meta_update.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#! /usr/bin/env python3

from argparse import ArgumentParser
import json
import re
from collections import OrderedDict


class Manipulator(object):
def __str__(self):
return self.__class__.__name__

def load(self, filename=None):
if filename is None:
filename = self.default_filename
with open(filename, 'rb') as fp:
self.data = json.load(fp, object_pairs_hook=OrderedDict)

def save(self, filename=None, indent=2):
if filename is None:
filename = self.default_filename
with open(filename, 'w', encoding='utf8') as fp:
json.dump(self.data, fp, indent=indent)
fp.write('\n')

@staticmethod
def _dict_entry_cmp(dict1, dict2, field1, field2=None):
if field2 is None:
field2 = field1
if (field1 in dict1) and (field2 in dict2):
return dict1[field1] == dict2[field2]
else:
return False

def _handle_person_list_file(self, filename, field_name, **kwargs):
fp = open(filename, 'r', encoding='utf8')
person_list = self.data.setdefault(field_name, [])
for i, line in enumerate(fp, start=0):
line = line.strip()
m = self.findregex.match(line)
if m is None:
raise RuntimeError("Could not analyze line %r" % line)
found_entry = self._find_person_entry(person_list, m.groupdict())
entry = self.update_person_entry(found_entry, m.groupdict(),
**kwargs)
if found_entry is None:
person_list.insert(i, entry)


class CodeMetaManipulator(Manipulator):
default_filename = 'codemeta.json'
findregex = re.compile(r'^(?P<familyName>[-\w\s]*[-\w]),\s*'
r'(?P<givenName>[-\w\s]*[-\w])\s*'
r'(?:<(?P<email>\S+@\S+)>)?\s*'
r'(\[(?P<orcid>\S+)\])?$')

@classmethod
def _find_person_entry(cls, person_list, matchdict):
# orcid is unique
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, '@id', 'orcid'):
return entry
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'email'):
return entry
if cls._dict_entry_cmp(entry, matchdict, 'familyName') \
and cls._dict_entry_cmp(entry, matchdict, 'givenName'):
return entry
return None

@staticmethod
def update_person_entry(entry, matchdict):
if entry is None:
entry = OrderedDict()
entry['@type'] = 'Person'
for field in ('orcid', 'givenName', 'familyName', 'email'):
val = matchdict.get(field, None)
if val is not None:
if field == 'orcid':
entry['@id'] = val
else:
entry[field] = val
return entry

def update_authors(self):
self._handle_person_list_file('AUTHORS', 'author')
self._handle_person_list_file('CONTRIBUTORS', 'contributor')

def version(self, new_version):
self.data['softwareVersion'] = new_version


class ZenodoManipulator(Manipulator):
default_filename = '.zenodo.json'
findregex = re.compile(r'^(?P<name>[-\w\s,]*[-\w])\s*'
r'(?:<(?P<email>\S+@\S+)>)?\s*'
r'(\[https://orcid\.org/(?P<orcid>\S+)\])?$')

@classmethod
def _find_person_entry(cls, person_list, matchdict):
# Match on orcid first
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'orcid'):
return entry
for entry in person_list:
if cls._dict_entry_cmp(entry, matchdict, 'name'):
return entry
return None

@staticmethod
def update_person_entry(entry, matchdict, contributor_type=None):
if entry is None:
entry = OrderedDict()
if contributor_type:
entry['type'] = contributor_type
for field in ('name', 'orcid'):
val = matchdict.get(field, None)
if val is not None:
entry[field] = val
return entry

def update_authors(self):
self._handle_person_list_file('AUTHORS', 'creators')
self._handle_person_list_file('CONTRIBUTORS', 'contributors',
contributor_type='Other')

def save(self, filename=None):
super().save(filename, 4)

def version(self, new_version):
self.data['version'] = new_version


def main():
parser = ArgumentParser(description='Update codemeta.json and '
'.zenodo.json')
parser.add_argument('--set-version', dest='newversion')
args = parser.parse_args()

for manipulator in (CodeMetaManipulator(), ZenodoManipulator()):
try:
manipulator.load()
except FileNotFoundError as e:
print('*** Skipping {}: {}'.format(manipulator, e))
continue
if args.newversion is not None:
manipulator.version(args.newversion)
manipulator.update_authors()
manipulator.save()


if __name__ == '__main__':
main()

0 comments on commit b8adc9f

Please sign in to comment.