Add dtc subcommand delete-record #12

Merged
cmo merged 2 commits from delete-record into master 2026-01-28 07:33:53 +00:00
2 changed files with 152 additions and 2 deletions

View file

@ -0,0 +1,150 @@
import json
import logging
import sys
from functools import partial
import rich_click as click
from ...communicate import (
HTTPError,
collection_delete_record,
curated_delete_record,
incoming_delete_record,
incoming_read_labels,
)
subcommand_name = 'delete-records'
logger = logging.getLogger('delete-records')
@click.command(short_help='Delete records from a dump-things collection')
@click.pass_obj
@click.argument(
'service_url',
metavar='SERVICE_URL',
)
@click.argument(
'collection',
metavar='COLLECTION',
)
@click.argument(
'pids',
metavar='PIDS',
nargs=-1,
)
@click.option(
'--curated', '-c',
default=False,
is_flag=True,
help='delete record from the curated area of the collection. (Note: requires a token with curator rights)',
)
@click.option(
'--incoming', '-i',
metavar='LABEL',
help='delete from the collection\'s inbox with label LABEL, if LABEL is "-", return labels of all collection inboxes and exit',
)
@click.option(
'--ignore-errors',
default=False,
is_flag=True,
help='ignore errors when deleting a pid and continue with remaining pids',
)
def cli(
obj,
service_url,
collection,
pids,
curated,
incoming,
ignore_errors,
):
"""Delete records from a collection on a dump-things-service
This command delete the records given by PIDS from the collection COLLECTION
of the dump-things service SERVICE_URL. If no PIDS are provided on the
command line, the pids that should be deleted are read from stdin (one pid
per line, lines are stripped).
By default, the records will be deleted from the inbox associated with the
token. If the option -c/--curated is given, the records are deleted from
the curated area of the collection (this requires a token with
curator rights).
"""
try:
return delete_records(
obj,
service_url,
collection,
pids,
curated,
incoming,
ignore_errors,
)
except HTTPError as e:
click.echo(f'ERROR: {e}: {e.response.text}', err=True)
return 1
def delete_records(
obj,
service_url,
collection,
pids,
curated,
incoming,
ignore_errors,
):
token = obj
if token is None:
click.echo(f'WARNING: no token provided', err=True)
if incoming and curated:
click.echo(
'ERROR: -i/--incoming and -c/--curated are mutually exclusive',
err=True,
)
return 1
kwargs = dict(
service_url=service_url,
collection=collection,
token=token,
)
if incoming == '-':
result = incoming_read_labels(**kwargs)
click.echo('\n'.join(
map(
partial(json.dumps, ensure_ascii=False),
result
)
))
return 0
if incoming:
operation = partial(incoming_delete_record, label=incoming)
elif curated:
operation = curated_delete_record
else:
operation = collection_delete_record
if not pids:
pids = sys.stdin
for pid in pids:
try:
operation(
service_url=service_url,
collection=collection,
pid=pid.strip(),
token=token,
)
except HTTPError as e:
if ignore_errors:
click.echo(f'ERROR: while deleting pid {pid}: {e}', err=True)
continue
raise
return 0

View file

@ -50,7 +50,7 @@ subcommand_name = 'get-records'
@click.option(
'--incoming', '-i',
metavar='LABEL',
help='read from the collection inbox with label LABEL, if LABEL is "-", return labels of all collection inboxes',
help='read from the collection\'s inbox with label LABEL, if LABEL is "-", return labels of all collection inboxes and exit',
)
@click.option(
'--curated', '-c',
@ -188,7 +188,7 @@ def get_records(
if incoming == '-':
result = incoming_read_labels(**kwargs)
print('\n'.join(
click.echo('\n'.join(
map(
partial(json.dumps, ensure_ascii=False),
result)))