*** Wartungsfenster jeden ersten Mittwoch vormittag im Monat ***

Skip to content
Snippets Groups Projects
Commit 8f4d78d2 authored by Moser, Maximilian's avatar Moser, Maximilian
Browse files

Add vocabulary management commands

parent eaeea6f0
Branches
No related tags found
1 merge request!17Update commands for updating draft files & add basic vocabulary management commands
This commit is part of merge request !17. Comments created here will be created in the context of that merge request.
...@@ -15,6 +15,7 @@ from .files import files ...@@ -15,6 +15,7 @@ from .files import files
from .records import records from .records import records
from .reports import reports from .reports import reports
from .users import users from .users import users
from .vocabularies import vocabularies
@click.group() @click.group()
...@@ -27,3 +28,4 @@ utilities.add_command(files) ...@@ -27,3 +28,4 @@ utilities.add_command(files)
utilities.add_command(records) utilities.add_command(records)
utilities.add_command(reports) utilities.add_command(reports)
utilities.add_command(users) utilities.add_command(users)
utilities.add_command(vocabularies)
# -*- coding: utf-8 -*-
#
# Copyright (C) 2025 TU Wien.
#
# Invenio-Utilities-TUW is free software; you can redistribute it and/or
# modify it under the terms of the MIT License; see LICENSE file for more
# details.
"""Management commands for vocabularies."""
import os
import sys
import click
import dictdiffer
import yaml
from flask.cli import with_appcontext
from invenio_access.permissions import system_identity
from invenio_pidstore.errors import PIDDoesNotExistError
from invenio_records_resources.proxies import current_service_registry
from invenio_vocabularies.records.api import VocabularyType
from sqlalchemy.exc import NoResultFound
special_vocabulary_types = [
"affiliations",
"awards",
"funders",
"names",
"subjects",
]
def _get_service_for_type(vocab_type: str):
"""Get the registered service for the given vocabulary type."""
if vocab_type in special_vocabulary_types:
return current_service_registry.get(vocab_type), False
if vocab_type not in {vt.id for vt in VocabularyType.query.all()}:
raise LookupError(f"could not find vocabulary type '{vocab_type}'")
return current_service_registry.get("vocabularies"), True
@click.group("vocabularies")
def vocabularies():
"""Management commands for vocabularies."""
@vocabularies.command("list-types")
@with_appcontext
def list_vocabulary_types():
"""List the available vocabulary types."""
types = {vt.id for vt in VocabularyType.query.all()}
for t in sorted(types):
if t in special_vocabulary_types:
click.secho(t, fg="green")
else:
click.echo(t)
@vocabularies.command("update")
@click.argument(
"filepath",
required=True, # help="file with the vocabulary entry definitions"
)
@click.argument(
"vocabulary_id",
required=True,
)
@click.option(
"--type",
"-t",
"vocab_type",
required=False,
default=None,
help="vocabulary type for the entry to add or update",
)
@with_appcontext
def add_or_update(vocab_type: str | None, filepath: str, vocabulary_id: str):
"""Add or update the vocabulary."""
if not vocab_type:
file_name = os.path.basename(filepath)
vocab_type, _ = os.path.splitext(file_name)
try:
service, needs_type = _get_service_for_type(vocab_type)
except LookupError as e:
click.secho(e, fg="red", err=True)
sys.exit(1)
with open(filepath, "r") as f:
vocab_entries = yaml.safe_load(f)
try:
vocab_entry, *_ = [e for e in vocab_entries if e.get("id") == vocabulary_id]
except ValueError:
click.secho(f"could not find entry '{vocabulary_id}'", fg="red", err=True)
sys.exit(1)
# the special vocabularies don't need their type specified as part of the ID,
# but generic vocabulary types do
id_ = (vocab_type, vocabulary_id) if needs_type else vocabulary_id
try:
# first we try to update an existing vocabulary entry
old_entry = service.read(system_identity, id_)._obj
old_entry.setdefault("id", vocabulary_id)
old_entry.pop("$schema")
old_entry.pop("pid", None)
old_entry.pop("type", None)
# check if an update is actually necessary
diffs = list(dictdiffer.diff(vocab_entry, old_entry))
if diffs:
if needs_type:
vocab_entry["type"] = vocab_type
new_entry = service.update(system_identity, id_, vocab_entry)._obj
click.echo(f"updated '{vocab_type}' vocabulary: {new_entry}")
else:
click.secho("no updates necessary", fg="green")
except (NoResultFound, PIDDoesNotExistError):
# if the lookup failed, we need to add the vocabulary entry
if needs_type:
vocab_entry["type"] = vocab_type
new_entry = service.create(system_identity, vocab_entry)._obj
click.echo(f"added '{vocab_type}' vocabulary: {new_entry}")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment