dfg-cp-survey-pool/code/convert_contributors.py

126 lines
4.2 KiB
Python

#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "click",
# "pyyaml"
# ]
# ///
import click
import csv
import json
import re
import sys
import yaml
from pathlib import Path
with open(Path('accounts.csv'), newline="", encoding="utf-8") as f:
accounts = {
row[0].translate(str.maketrans("", "", "@-.")).strip().lower(): row[1]
for row in csv.reader(f)
}
# see https://hub.psychoinformatics.de/msz/lehr-und-forschungsbereiche/src/branch/main
discipline_mapping = {
'hfs:n002': 'trr379dfgsurvey:discipline/1420',
'hfs:n01': 'trr379dfgsurvey:discipline/0100',
'hfs:n0128': 'trr379dfgsurvey:discipline/3600',
'hfs:n018': 'trr379dfgsurvey:discipline/0830',
'hfs:n026': 'trr379dfgsurvey:discipline/4000',
'hfs:n042': 'trr379dfgsurvey:discipline/2640',
'hfs:n057': 'trr379dfgsurvey:discipline/7246',
'hfs:n079': 'trr379dfgsurvey:discipline/3500',
'hfs:n1': 'trr379dfgsurvey:discipline/0100',
'hfs:n107': 'trr379dfgsurvey:discipline/4400',
'hfs:n123': 'trr379dfgsurvey:discipline/3530',
'hfs:n126': 'trr379dfgsurvey:discipline/3900',
'hfs:n132': 'trr379dfgsurvey:discipline/1700',
'hfs:n169': 'trr379dfgsurvey:discipline/0400',
'hfs:n172': 'trr379dfgsurvey:discipline/2700',
'hfs:n186': 'trr379dfgsurvey:discipline/3300',
'hfs:n247': 'trr379dfgsurvey:discipline/4525',
'hfs:n300': 'trr379dfgsurvey:discipline/4725',
'hfs:n32': 'trr379dfgsurvey:discipline/1700',
'hfs:n42': 'trr379dfgsurvey:discipline/4000',
'hfs:n48': 'trr379dfgsurvey:discipline/4450',
'hfs:n49': 'trr379dfgsurvey:discipline/4400',
'hfs:n5': 'trr379dfgsurvey:discipline/4400'
}
def replace_discipline(obj):
found_discipline = obj.get('discipline', None)
if not found_discipline:
return
found_mapping = discipline_mapping.get(found_discipline, None)
if not found_mapping:
return
obj['discipline'] = found_mapping
@click.command()
@click.option(
"--delete-key",
multiple=True,
help="Remove a key-value from a record"
)
def main(delete_key: tuple) -> None:
"""Process contributor records originating from 2025 DFG CP Survey
and make it compliant with the 2026 update.
Input from stdin should be a stream of paths to yaml files containing
Contributor records. Paths will be in the format:
'usr-<email-address-with-special-characters-removed>/<arbitrary-depth>/<hash>.yaml'
for example:
usr-sheunisfzjuelichde/Contributor/6c5/409a7acdc258f992238a868c5d8e7dc2f7181.yaml
The workflow involves:
- accessing existing contributor records, at provided paths
- accessing a list of current TRR379 Hub forgejo accounts, from an 'accounts.tsv' file
- maping between the two above, using registered email addresses, in order to determine
an updated dumpthings inbox label into which the updated record should be posted
- reading the yaml record and:
- removing fields where specified
- replacing the discipline PID with the correct mapped value
- writing the mapped inbox name and updated record to stdout
- where such automatic mapping fails, a warning is printed
Required inputs:
- a stream of paths to yaml records
- a list of forgejo account names and email addresses stored in 'accounts.tsv'
in the same directory as the script
Outputs:
- a stdout stream of inbox labels tab-separated by the associated updated record
"""
for line in sys.stdin:
line = line.strip()
if not line:
continue
try:
found_email = re.search('usr-(.+?)\\/Contributor', line).group(1)
except:
found_email = None
if not found_email:
print(f'email not extracted for path: {line}')
continue
username = accounts.get(found_email, None)
if not username:
print(f'username not found in accounts for email: {found_email}')
continue
contributor_data = None
with open(Path(line)) as f:
contributor_data = yaml.safe_load(f)
replace_discipline(contributor_data)
print(f'forgejo-trr379hub-user-{username}\t{json.dumps(contributor_data)}')
if __name__ == "__main__":
main()