Source code for invenio_records.cli

# -*- coding: utf-8 -*-
#
# This file is part of Invenio.
# Copyright (C) 2015-2018 CERN.
#
# Invenio is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.

"""Click command-line interface for record management."""

from __future__ import absolute_import, print_function

import json
import sys
import uuid
import warnings

import click
import pkg_resources
from flask import current_app
from flask.cli import with_appcontext
from invenio_db import db
from sqlalchemy import exc


[docs]def records_deprecation_warning(): """Add deprecation warning for records cli.""" warnings.warn('The Invenio-Records cli module is deprecated.', PendingDeprecationWarning)
try: pkg_resources.get_distribution('invenio_pidstore') except pkg_resources.DistributionNotFound: HAS_PIDSTORE = False else: HAS_PIDSTORE = True try: from itertools import zip_longest except ImportError: from itertools import izip_longest as zip_longest if HAS_PIDSTORE: def process_minter(value): """Load minter from InvenioPIDStore registry based on given value.""" from invenio_pidstore import current_pidstore if 'invenio-pidstore' not in current_app.extensions: raise click.ClickException( 'Invenio-PIDStore has not been initialized.' ) try: return current_pidstore.minters[value] except KeyError: raise click.BadParameter( 'Unknown minter: {0}. Please choose one minter between [{1}].' .format(value, ', '.join(current_pidstore.minters.keys())) ) option_pid_minter = click.option('--pid-minter', multiple=True, default=None) else:
[docs] def option_pid_minter(_): """Empty option.""" return _
@click.group() def records(): """Record management.""" @records.command() @click.argument('source', type=click.File('r'), default=sys.stdin) @click.option('-i', '--id', 'ids', multiple=True) @click.option('--force', is_flag=True, default=False) @option_pid_minter @with_appcontext def create(source, ids, force, pid_minter=None): """Create new bibliographic record(s).""" records_deprecation_warning() # Make sure that all imports are done with application context. from .api import Record from .models import RecordMetadata pid_minter = [process_minter(minter) for minter in pid_minter or []] data = json.load(source) if isinstance(data, dict): data = [data] if ids: assert len(ids) == len(data), 'Not enough identifiers.' for record, id_ in zip_longest(data, ids): id_ = id_ or uuid.uuid4() try: for minter in pid_minter: minter(id_, record) click.echo(Record.create(record, id_=id_).id) except exc.IntegrityError: if force: current_app.logger.warning( "Trying to force insert: {0}".format(id_)) # IMPORTANT: We need to create new transaction for # SQLAlchemy-Continuum as we are using no auto-flush # in Record.get_record. vm = current_app.extensions['invenio-db'].versioning_manager uow = vm.unit_of_work(db.session) uow.create_transaction(db.session) # Use low-level database model to retrieve an instance. model = RecordMetadata.query.get(id_) rec = Record(record, model=model).commit() current_app.logger.info("Created new revision {0}".format( rec.revision_id)) click.echo(rec.id) else: raise click.BadParameter( 'Record with id={0} already exists. If you want to ' 'override its data use --force.'.format(id_), param_hint='ids', ) db.session.flush() db.session.commit() @records.command() @click.argument('patch', type=click.File('r'), default=sys.stdin) @click.option('-i', '--id', 'ids', multiple=True) @with_appcontext def patch(patch, ids): """Patch existing bibliographic record.""" records_deprecation_warning() from .api import Record patch_content = patch.read() if ids: for id_ in ids: rec = Record.get_record(id_).patch(patch_content).commit() current_app.logger.info("Created new revision {0}".format( rec.revision_id)) click.echo(rec.id) db.session.commit() @records.command() @click.option('-i', '--id', 'ids', multiple=True) @click.option('--force', is_flag=True, default=False) @with_appcontext def delete(ids, force): """Delete bibliographic record(s).""" records_deprecation_warning() from .api import Record for id_ in ids: record = Record.get_record(id_, with_deleted=force) record.delete(force=force) db.session.commit()