Ejemplo n.º 1
0
def quicksetup(
    ctx, non_interactive, profile, email, first_name, last_name, institution, db_engine, db_backend, db_host, db_port,
    db_name, db_username, db_password, su_db_name, su_db_username, su_db_password, repository
):
    """Setup a new profile in a fully automated fashion."""
    # pylint: disable=too-many-arguments,too-many-locals
    from aiida.manage.external.postgres import Postgres, manual_setup_instructions

    dbinfo_su = {
        'host': db_host,
        'port': db_port,
        'user': su_db_username,
        'password': su_db_password,
    }
    postgres = Postgres(interactive=not non_interactive, quiet=False, dbinfo=dbinfo_su)

    if not postgres.is_connected:
        echo.echo_critical('failed to determine the PostgreSQL setup')

    try:
        create = True
        if not postgres.dbuser_exists(db_username):
            postgres.create_dbuser(db_username, db_password)
        else:
            db_name, create = postgres.check_db_name(db_name)

        if create:
            postgres.create_db(db_username, db_name)
    except Exception as exception:
        echo.echo_error(
            '\n'.join([
                'Oops! quicksetup was unable to create the AiiDA database for you.',
                'For AiiDA to work, please either create the database yourself as follows:',
                manual_setup_instructions(dbuser=su_db_username, dbname=su_db_name), '',
                'Alternatively, give your (operating system) user permission to create postgresql databases' +
                'and run quicksetup again.', ''
            ])
        )
        raise exception

    # The contextual defaults or `verdi setup` are not being called when `invoking`, so we have to explicitly define
    # them here, even though the `verdi setup` command would populate those when called from the command line.
    setup_parameters = {
        'non_interactive': non_interactive,
        'profile': profile,
        'email': email,
        'first_name': first_name,
        'last_name': last_name,
        'institution': institution,
        'db_engine': db_engine,
        'db_backend': db_backend,
        'db_name': db_name,
        # from now on we connect as the AiiDA DB user, which may be forbidden when going via sockets
        'db_host': db_host or 'localhost',
        'db_port': db_port,
        'db_username': db_username,
        'db_password': db_password,
        'repository': repository,
    }
    ctx.invoke(setup, **setup_parameters)
Ejemplo n.º 2
0
def _try_import(migration_performed, file_to_import, archive, group, migration, non_interactive, **kwargs):
    """Utility function for `verdi import` to try to import archive

    :param migration_performed: Boolean to determine the exception message to throw for
        `~aiida.tools.importexport.common.exceptions.IncompatibleArchiveVersionError`
    :param file_to_import: Absolute path, including filename, of file to be migrated.
    :param archive: Filename of archive to be migrated, and later attempted imported.
    :param group: AiiDA Group into which the import will be associated.
    :param migration: Whether or not to force migration of archive, if needed.
    :param non_interactive: Whether or not the user should be asked for input for any reason.
    :param kwargs: Key-word-arguments that _must_ contain:
        * `'extras_mode_existing'`: `import_data`'s `'extras_mode_existing'` keyword, determining import rules for
        Extras.
        * `'extras_mode_new'`: `import_data`'s `'extras_mode_new'` keyword, determining import rules for Extras.
        * `'comment_mode'`: `import_data`'s `'comment_mode'` keyword, determining import rules for Comments.
    """
    from aiida.tools.importexport import import_data, IncompatibleArchiveVersionError

    # Checks
    expected_keys = ['extras_mode_existing', 'extras_mode_new', 'comment_mode']
    for key in expected_keys:
        if key not in kwargs:
            raise ValueError("{} needed for utility function '{}' to use in 'import_data'".format(key, '_try_import'))

    # Initialization
    migrate_archive = False

    try:
        import_data(file_to_import, group, **kwargs)
    except IncompatibleArchiveVersionError as exception:
        if migration_performed:
            # Migration has been performed, something is still wrong
            crit_message = '{} has been migrated, but it still cannot be imported.\n{}'.format(archive, exception)
            echo.echo_critical(crit_message)
        else:
            # Migration has not yet been tried.
            if migration:
                # Confirm migration
                echo.echo_warning(str(exception).splitlines()[0])
                if non_interactive:
                    migrate_archive = True
                else:
                    migrate_archive = click.confirm(
                        'Do you want to try and migrate {} to the newest export file version?\n'
                        'Note: This will not change your current file.'.format(archive),
                        default=True,
                        abort=True
                    )
            else:
                # Abort
                echo.echo_critical(str(exception))
    except Exception:
        echo.echo_error('an exception occurred while importing the archive {}'.format(archive))
        echo.echo(traceback.format_exc())
        if not non_interactive:
            click.confirm('do you want to continue?', abort=True)
    else:
        echo.echo_success('imported archive {}'.format(archive))

    return migrate_archive
Ejemplo n.º 3
0
def process_watch(processes):
    """Watch the state transitions for a process."""
    from kiwipy import BroadcastFilter
    from aiida.work.rmq import create_communicator

    def _print(body, sender, subject, correlation_id):
        echo.echo('pk={}, subject={}, body={}, correlation_id={}'.format(
            sender, subject, body, correlation_id))

    communicator = create_communicator()

    for process in processes:

        if process.is_terminated:
            echo.echo_error('Process<{}> is already terminated'.format(
                process.pk))
            continue

        communicator.add_broadcast_subscriber(
            BroadcastFilter(_print, sender=process.pk))

    try:
        communicator. await ()
    except (SystemExit, KeyboardInterrupt):

        try:
            communicator.disconnect()
        except RuntimeError:
            pass

        # Reraise to trigger clicks builtin abort sequence
        raise
Ejemplo n.º 4
0
def update(comment, node, comment_id):
    """
    Update a comment.

    id      = The id of the comment
    comment = The comment (a string) to be added to the node(s)
    """
    from aiida.orm.backend import construct_backend
    backend = construct_backend()
    user = backend.users.get_automatic_user()

    # read the comment from terminal if it is not on command line
    if comment is None:
        try:
            current_comment = node.get_comments(comment_id)[0]
        except IndexError:
            echo.echo_error(
                "Comment with id '{}' not found".format(comment_id))
            return 1

        comment = multi_line_input.edit_comment(current_comment['content'])

    # pylint: disable=protected-access
    node._update_comment(comment, comment_id, user)

    return 0
Ejemplo n.º 5
0
def calculation_plugins(entry_point):
    """Print a list of registered calculation plugins or details of a specific calculation plugin."""
    import json
    from aiida.common.exceptions import LoadingPluginFailed, MissingPluginError
    from aiida.plugins.entry_point import get_entry_point_names, load_entry_point

    if entry_point:
        try:
            plugin = load_entry_point('aiida.calculations', entry_point)
        except (LoadingPluginFailed, MissingPluginError) as exception:
            echo.echo_critical(exception)
        else:
            echo.echo_info(entry_point)
            echo.echo_info(
                plugin.__doc__ if plugin.__doc__ else 'no docstring available')
            echo.echo(json.dumps(plugin.process().get_description(), indent=4))

    else:
        entry_points = get_entry_point_names('aiida.calculations')
        if entry_points:
            echo.echo('Registered calculation entry points:')
            for ep in entry_points:
                echo.echo("* {}".format(ep))

            echo.echo('')
            echo.echo_info(
                'Pass the entry point as an argument to display detailed information'
            )
        else:
            echo.echo_error('No calculation plugins found')
Ejemplo n.º 6
0
def calculation_kill(calculations, force):
    """Kill one or multiple running calculations."""
    from aiida import work

    if not force:
        warning = 'Are you sure you want to kill {} calculations?'.format(
            len(calculations))
        click.confirm(warning, abort=True)

    with work.new_control_panel() as control_panel:
        futures = []
        for calculation in calculations:
            try:
                future = control_panel.kill_process(calculation)
                futures.append((calculation, future))
            except (work.RemoteException, work.DeliveryFailed) as e:
                echo.echo_error('Calculation<{}> killing failed {}'.format(
                    calculation, e.message))

        for future in futures:
            result = control_panel._communicator. await (future[1])
            if result:
                echo.echo_success('Calculation<{}> successfully killed'.format(
                    future[0]))
            else:
                echo.echo_error('Calculation<{}> killing failed {}'.format(
                    future[0], result))
Ejemplo n.º 7
0
def process_play(processes, all_entries, timeout, wait):
    """Play (unpause) paused processes."""
    from aiida.orm import ProcessNode, QueryBuilder

    controller = get_manager().get_process_controller()

    if processes and all_entries:
        raise click.BadOptionUsage(
            'all',
            'cannot specify individual processes and the `--all` flag at the same time.'
        )

    if not processes and all_entries:
        filters = CalculationQueryBuilder().get_filters(
            process_state=('created', 'waiting', 'running'), paused=True)
        builder = QueryBuilder().append(ProcessNode, filters=filters)
        processes = builder.all(flat=True)

    futures = {}
    for process in processes:

        if process.is_terminated:
            echo.echo_error(f'Process<{process.pk}> is already terminated')
            continue

        try:
            future = controller.play_process(process.pk)
        except communications.UnroutableError:
            echo.echo_error(f'Process<{process.pk}> is unreachable')
        else:
            futures[future] = process

    process_actions(futures, 'play', 'playing', 'played', wait, timeout)
Ejemplo n.º 8
0
def process_play(processes, all_entries, timeout, wait):
    """Play (unpause) paused processes."""
    from aiida.orm import ProcessNode, QueryBuilder

    controller = get_manager().get_process_controller()

    if processes and all_entries:
        raise click.BadOptionUsage(
            'all',
            'cannot specify individual processes and the `--all` flag at the same time.'
        )

    if not processes and all_entries:
        builder = QueryBuilder().append(ProcessNode,
                                        filters={'attributes.paused': True})
        processes = [entry[0] for entry in builder.all()]

    futures = {}
    for process in processes:

        if process.is_terminated:
            echo.echo_error('Process<{}> is already terminated'.format(
                process.pk))
            continue

        try:
            future = controller.play_process(process.pk)
        except communications.UnroutableError:
            echo.echo_error('Process<{}> is unreachable'.format(process.pk))
        else:
            futures[future] = process

    process_actions(futures, 'play', 'playing', 'played', wait, timeout)
Ejemplo n.º 9
0
def work_play(calculations):
    """
    Play paused work calculations
    """
    from aiida.work import RemoteException, DeliveryFailed, new_blocking_control_panel

    with new_blocking_control_panel() as control_panel:
        for calculation in calculations:

            if calculation.is_terminated:
                echo.echo_error('Calculation<{}> is already terminated'.format(
                    calculation.pk))
                continue

            try:
                if control_panel.play_process(calculation.pk):
                    echo.echo_success('played Calculation<{}>'.format(
                        calculation.pk))
                else:
                    echo.echo_critical(
                        'problem playing Calculation<{}>'.format(
                            calculation.pk))
            except (RemoteException, DeliveryFailed) as exception:
                echo.echo_critical('failed to play Calculation<{}>: {}'.format(
                    calculation.pk, exception.message))
Ejemplo n.º 10
0
def work_plugins(entry_point):
    """
    Print a list of registered workflow plugins or details of a specific workflow plugin
    """
    from aiida.common.exceptions import LoadingPluginFailed, MissingPluginError
    from aiida.plugins.entry_point import get_entry_point_names, load_entry_point

    if entry_point:
        try:
            plugin = load_entry_point('aiida.workflows', entry_point)
        except (LoadingPluginFailed, MissingPluginError) as exception:
            echo.echo_critical(exception)
        else:
            echo.echo_info(entry_point)
            echo.echo(plugin.get_description())
    else:
        entry_points = get_entry_point_names('aiida.workflows')
        if entry_points:
            echo.echo('Registered workflow entry points:')
            for registered_entry_point in entry_points:
                echo.echo("* {}".format(registered_entry_point))

            echo.echo('')
            echo.echo_info(
                'Pass the entry point as an argument to display detailed information'
            )
        else:
            echo.echo_error('No workflow plugins found')
Ejemplo n.º 11
0
def quicksetup(
    ctx, non_interactive, profile, email, first_name, last_name, institution, db_engine, db_backend, db_host, db_port,
    db_name, db_username, db_password, su_db_name, su_db_username, su_db_password, broker_protocol, broker_username,
    broker_password, broker_host, broker_port, broker_virtual_host, repository
):
    """Setup a new profile in a fully automated fashion."""
    # pylint: disable=too-many-arguments,too-many-locals
    from aiida.manage.external.postgres import Postgres, manual_setup_instructions

    dbinfo_su = {
        'host': db_host,
        'port': db_port,
        'user': su_db_username,
        'password': su_db_password,
    }
    postgres = Postgres(interactive=not non_interactive, quiet=False, dbinfo=dbinfo_su)

    if not postgres.is_connected:
        echo.echo_critical('failed to determine the PostgreSQL setup')

    try:
        db_username, db_name = postgres.create_dbuser_db_safe(dbname=db_name, dbuser=db_username, dbpass=db_password)
    except Exception as exception:
        echo.echo_error(
            '\n'.join([
                'Oops! quicksetup was unable to create the AiiDA database for you.',
                'See `verdi quicksetup -h` for how to specify non-standard parameters for the postgresql connection.\n'
                'Alternatively, create the AiiDA database yourself: ',
                manual_setup_instructions(dbuser=su_db_username,
                                          dbname=su_db_name), '', 'and then use `verdi setup` instead', ''
            ])
        )
        raise exception

    # The contextual defaults or `verdi setup` are not being called when `invoking`, so we have to explicitly define
    # them here, even though the `verdi setup` command would populate those when called from the command line.
    setup_parameters = {
        'non_interactive': non_interactive,
        'profile': profile,
        'email': email,
        'first_name': first_name,
        'last_name': last_name,
        'institution': institution,
        'db_engine': db_engine,
        'db_backend': db_backend,
        'db_name': db_name,
        # from now on we connect as the AiiDA DB user, which may be forbidden when going via sockets
        'db_host': postgres.host_for_psycopg2,
        'db_port': postgres.port_for_psycopg2,
        'db_username': db_username,
        'db_password': db_password,
        'broker_protocol': broker_protocol,
        'broker_username': broker_username,
        'broker_password': broker_password,
        'broker_host': broker_host,
        'broker_port': broker_port,
        'broker_virtual_host': broker_virtual_host,
        'repository': repository,
    }
    ctx.invoke(setup, **setup_parameters)
Ejemplo n.º 12
0
def show(nodes):
    """
    Show contents of ParameterData nodes.
    """
    from aiida.orm.data.parameter import ParameterData
    from aiida.cmdline.utils.echo import echo_dictionary
    for node in nodes:
        if not isinstance(node, ParameterData):
            echo.echo_error("Node {} is of class {} instead of {}".format(
                node, type(node), ParameterData))
            continue
        the_dict = node.get_dict()
        echo_dictionary(the_dict, 'json+date')
Ejemplo n.º 13
0
    def safely_convert(self, value, param, ctx):
        """
        convert without raising, instead print a message if fails

        :return: Tuple of ( success (bool), converted value )
        """
        successful = False
        try:
            value = self.type.convert(value, param, ctx)
            successful = True
        except click.BadParameter as err:
            echo.echo_error(err.message)
            self.ctrl_help()
        return successful, value
Ejemplo n.º 14
0
def process_pause(processes, timeout):
    """Pause running processes."""
    from aiida.work import RemoteException, DeliveryFailed, TimeoutError, new_blocking_control_panel

    with new_blocking_control_panel(timeout=timeout) as control_panel:
        for process in processes:

            if process.is_terminated:
                echo.echo_error('Process<{}> is already terminated'.format(
                    process.pk))
                continue

            try:
                if control_panel.pause_process(
                        process.pk,
                        msg='Paused through `verdi process pause`'):
                    echo.echo_success('paused Process<{}>'.format(process.pk))
                else:
                    echo.echo_error('problem pausing Process<{}>'.format(
                        process.pk))
            except TimeoutError:
                echo.echo_error('call to pause Process<{}> timed out'.format(
                    process.pk))
            except (RemoteException, DeliveryFailed) as exception:
                echo.echo_error('failed to pause Process<{}>: {}'.format(
                    process.pk, exception.message))
Ejemplo n.º 15
0
    def do_comment_update(self, arg):
        """Update comment for a given comment ID"""
        from aiida.orm.comments import Comment
        from aiida.cmdline.utils import echo
        from aiida.common import exceptions
        with self.verdi_isolate():
            comment_id, content = arg.id, arg.content
            try:
                comment = Comment.objects.get(id=comment_id)
            except (exceptions.NotExistent, exceptions.MultipleObjectsError):
                echo.echo_error('comment<{}> not found'.format(comment_id))

            comment.set_content(content)

            echo.echo_success('comment<{}> updated'.format(comment_id))
Ejemplo n.º 16
0
def plugin_list(entry_point_group, entry_point):
    """Display a list of all available plugins."""
    from aiida.common import EntryPointError
    from aiida.cmdline.utils.common import print_process_info
    from aiida.engine import Process
    from aiida.plugins.entry_point import get_entry_point_names, load_entry_point

    if entry_point_group is None:
        echo.echo_info('Available entry point groups:')
        for group in sorted(ENTRY_POINT_GROUP_TO_MODULE_PATH_MAP.keys()):
            echo.echo('* {}'.format(group))

        echo.echo('')
        echo.echo_info(
            'Pass one of the groups as an additional argument to show the registered plugins'
        )
        return

    if entry_point:
        try:
            plugin = load_entry_point(entry_point_group, entry_point)
        except EntryPointError as exception:
            echo.echo_critical(str(exception))
        else:
            try:
                if (inspect.isclass(plugin) and issubclass(
                        plugin, Process)) or plugin.is_process_function:
                    print_process_info(plugin)
                else:
                    echo.echo(str(plugin.get_description()))
            except AttributeError:
                echo.echo_error(
                    'No description available for {}'.format(entry_point))
    else:
        entry_points = get_entry_point_names(entry_point_group)
        if entry_points:
            echo.echo(
                'Registered entry points for {}:'.format(entry_point_group))
            for registered_entry_point in entry_points:
                echo.echo('* {}'.format(registered_entry_point))

            echo.echo('')
            echo.echo_info(
                'Pass the entry point as an argument to display detailed information'
            )
        else:
            echo.echo_error(
                'No plugins found for group {}'.format(entry_point_group))
def attributes_to_dict(attr_list):
    """
    Transform the attributes of a node into a dictionary. It assumes the key
    are ordered alphabetically, and that they all belong to the same node.
    """
    d = {}

    error = False
    for a in attr_list:
        try:
            tmp_d = select_from_key(a.key, d)
        except ValueError:
            echo.echo_error(
                f"Couldn't transfer attribute {a.id} with key {a.key} for dbnode {a.dbnode_id}"
            )
            error = True
            continue
        key = a.key.split('.')[-1]

        if isinstance(tmp_d, (list, tuple)):
            key = int(key)

        dt = a.datatype

        if dt == 'dict':
            tmp_d[key] = {}
        elif dt == 'list':
            tmp_d[key] = [None] * a.ival
        else:
            val = None
            if dt == 'txt':
                val = a.tval
            elif dt == 'float':
                val = a.fval
                if math.isnan(val) or math.isinf(val):
                    val = str(val)
            elif dt == 'int':
                val = a.ival
            elif dt == 'bool':
                val = a.bval
            elif dt == 'date':
                val = datetime_to_isoformat(a.dval)

            tmp_d[key] = val

    return d, error
Ejemplo n.º 18
0
def delete(codes):
    """Delete a code.

    Note that it is possible to delete a code only if it has not yet been used
    as an input of a calculation, i.e., if it does not have outgoing links.
    """
    from aiida.common.exceptions import InvalidOperation
    from aiida.orm import Node

    for code in codes:
        try:
            pk = code.pk
            full_label = code.full_label
            Node.objects.delete(pk)  # pylint: disable=no-member
        except InvalidOperation as exception:
            echo.echo_error(str(exception))
        else:
            echo.echo_success('Code<{}> {} deleted'.format(pk, full_label))
Ejemplo n.º 19
0
def process_watch(processes):
    """Watch the state transitions for a process."""
    from time import sleep
    from kiwipy import BroadcastFilter

    def _print(communicator, body, sender, subject, correlation_id):  # pylint: disable=unused-argument
        """Format the incoming broadcast data into a message and echo it to stdout."""
        if body is None:
            body = 'No message specified'

        if correlation_id is None:
            correlation_id = '--'

        echo.echo('Process<{}> [{}|{}]: {}'.format(sender, subject,
                                                   correlation_id, body))

    communicator = get_manager().get_communicator()
    echo.echo_info(
        'watching for broadcasted messages, press CTRL+C to stop...')

    for process in processes:

        if process.is_terminated:
            echo.echo_error('Process<{}> is already terminated'.format(
                process.pk))
            continue

        communicator.add_broadcast_subscriber(
            BroadcastFilter(_print, sender=process.pk))

    try:
        # Block this thread indefinitely until interrupt
        while True:
            sleep(2)
    except (SystemExit, KeyboardInterrupt):
        echo.echo('')  # add a new line after the interrupt character
        echo.echo_info('received interrupt, exiting...')
        try:
            communicator.stop()
        except RuntimeError:
            pass

        # Reraise to trigger clicks builtin abort sequence
        raise
Ejemplo n.º 20
0
def print_status(status, service, msg='', exception=None, print_traceback=False):
    """Print status message.

    Includes colored indicator.

    :param status: a ServiceStatus code
    :param service: string for service name
    :param msg:  message string
    """
    symbol = STATUS_SYMBOLS[status]
    click.secho(f" {symbol['string']} ", fg=symbol['color'], nl=False)
    click.secho(f"{service + ':':12s} {msg}")

    if exception is not None:
        echo.echo_error(f'{type(exception).__name__}: {exception}')

    if print_traceback:
        import traceback
        traceback.print_exc()
Ejemplo n.º 21
0
    def after_callback(self, ctx, param, value):
        """If a callback was registered on init, call it and return it's value."""
        if self._after_callback:
            try:
                self._after_callback(ctx, param, value)
            except click.BadParameter as exception:
                # If the non-prompt callback raises, we want to only start the prompt loop if we were already in it.
                # For example, if the option was explicitly specified on the command line, but the callback fails, we
                # do not want to start prompting for it, but instead just let the exception bubble-up.
                # However, in this case, the `--non-interactive` flag is not necessarily passed, so we cannot just rely
                # on this value but in addition need to check that we did not already enter the prompt.
                if self.is_non_interactive(ctx) or not hasattr(
                        ctx, 'prompt_loop_info_printed'):
                    raise exception

                echo.echo_error(str(exception))
                self.ctrl_help()
                value = self.prompt_loop(ctx, param, value)

        return value
Ejemplo n.º 22
0
def process_kill(processes, timeout, wait):
    """Kill running processes."""

    controller = get_manager().get_process_controller()

    futures = {}
    for process in processes:

        if process.is_terminated:
            echo.echo_error(f'Process<{process.pk}> is already terminated')
            continue

        try:
            future = controller.kill_process(
                process.pk, msg='Killed through `verdi process kill`')
        except communications.UnroutableError:
            echo.echo_error(f'Process<{process.pk}> is unreachable')
        else:
            futures[future] = process

    process_actions(futures, 'kill', 'killing', 'killed', wait, timeout)
Ejemplo n.º 23
0
    def safely_convert(self, value, param, ctx):
        """
        convert without raising, instead print a message if fails

        :return: Tuple of ( success (bool), converted value )
        """
        successful = False

        if value is self.CHARACTER_IGNORE_DEFAULT:
            # The ignore default character signifies that the user wants to "not" set the value, so we return `None`
            return True, None

        try:
            value = self.type.convert(value, param, ctx)
            value = self.callback(ctx, param, value)
            successful = True
        except click.BadParameter as err:
            echo.echo_error(str(err))
            self.ctrl_help()

        return successful, value
Ejemplo n.º 24
0
def remove(remove_all, force, node, comment_id):
    """
    Remove comment(s) of a node. The user can only remove their own comments.

    pk = The pk (an integer) of the node

    id = #ID of the comment to be removed from node #PK
    """
    # Note: in fact, the user can still manually delete any comment
    from aiida.orm.backend import construct_backend

    backend = construct_backend()
    user = backend.users.get_automatic_user()

    if comment_id is None and not remove_all:
        echo.echo_error("One argument between -a and ID must be provided")
        return 101

    if comment_id is not None and remove_all:
        echo.echo_error("Cannot use -a together with a comment id")
        return 102

    if remove_all:
        comment_id = None

    if not force:
        if remove_all:
            click.confirm(
                "Delete all comments of user {} on node <{}>? ".format(
                    user, node.pk),
                abort=True)
        else:
            click.confirm("Delete comment? ", abort=True)

    comments = node.get_comment_obj(comment_id=comment_id, user=user)
    for comment in comments:
        comment.delete()
    echo.echo_info("Deleted {} comments.".format(len(comments)))

    return 0
Ejemplo n.º 25
0
def _migrate_archive(ctx, temp_folder, file_to_import, archive,
                     non_interactive, **kwargs):  # pylint: disable=unused-argument
    """Utility function for `verdi import` to migrate archive
    Invoke click command `verdi export migrate`, passing in the archive,
    outputting the migrated archive in a temporary SandboxFolder.
    Try again to import the now migrated file, after a successful migration.

    :param ctx: Click context used to invoke `verdi export migrate`.
    :param temp_folder: SandboxFolder, where the migrated file will be temporarily outputted.
    :param file_to_import: Absolute path, including filename, of file to be migrated.
    :param archive: Filename of archive to be migrated, and later attempted imported.
    :param non_interactive: Whether or not the user should be asked for input for any reason.
    :return: Absolute path to migrated archive within SandboxFolder.
    """
    from aiida.cmdline.commands.cmd_export import migrate

    # Echo start
    echo.echo_info('migrating archive {}'.format(archive))

    # Initialization
    temp_out_file = 'migrated_importfile.aiida'

    # Migration
    try:
        ctx.invoke(migrate,
                   input_file=file_to_import,
                   output_file=temp_folder.get_abs_path(temp_out_file),
                   silent=False)
    except Exception:
        echo.echo_error(
            'an exception occurred while migrating the archive {}.\n'
            "Use 'verdi export migrate' to update this export file.".format(
                archive))
        echo.echo(traceback.format_exc())
        if not non_interactive:
            click.confirm('do you want to continue?', abort=True)
    else:
        echo.echo_success('archive migrated, proceeding with import')

        return temp_folder.get_abs_path(temp_out_file)
Ejemplo n.º 26
0
 def do_comment_remove(self, arg):
     """Added comment to the current node"""
     from aiida.orm.comments import Comment
     from aiida.cmdline.utils import echo
     from aiida.common import exceptions
     comment, force = arg.id, arg.force
     with self.verdi_isolate():
         if not force:
             try:
                 click.confirm(
                     'Are you sure you want to remove comment<{}>'.format(
                         comment),
                     abort=True)
             except click.exceptions.Abort:
                 return
         try:
             Comment.objects.delete(comment)
         except exceptions.NotExistent as exception:
             echo.echo_error('failed to remove comment<{}>: {}'.format(
                 comment, exception))
         else:
             echo.echo_success('removed comment<{}>'.format(comment))
Ejemplo n.º 27
0
    def safely_convert(self, value, param, ctx):
        """
        convert without raising, instead print a message if fails

        :return: Tuple of ( success (bool), converted value )
        """
        successful = False

        if value is self.CHARACTER_IGNORE_DEFAULT:
            # The ignore default character signifies that the user wants to "not" set the value.
            # Replace value by an empty string for further processing (e.g. if a non-empty value is required).
            value = ''

        try:
            value = self.type.convert(value, param, ctx)
            value = self.callback(ctx, param, value)
            successful = True
        except click.BadParameter as err:
            echo.echo_error(str(err))
            self.ctrl_help()

        return successful, value
Ejemplo n.º 28
0
def process_pause(processes, all_entries, timeout, wait):
    """Pause running processes."""
    from aiida.orm import ProcessNode, QueryBuilder

    controller = get_manager().get_process_controller()

    if processes and all_entries:
        raise click.BadOptionUsage(
            'all',
            'cannot specify individual processes and the `--all` flag at the same time.'
        )

    if not processes and all_entries:
        active_states = options.active_process_states()
        builder = QueryBuilder().append(
            ProcessNode,
            filters={'attributes.process_state': {
                'in': active_states
            }})
        processes = [entry[0] for entry in builder.all()]

    futures = {}
    for process in processes:

        if process.is_terminated:
            echo.echo_error('Process<{}> is already terminated'.format(
                process.pk))
            continue

        try:
            future = controller.pause_process(
                process.pk, msg='Paused through `verdi process pause`')
        except communications.UnroutableError:
            echo.echo_error('Process<{}> is unreachable'.format(process.pk))
        else:
            futures[future] = process

    process_actions(futures, 'pause', 'pausing', 'paused', wait, timeout)
Ejemplo n.º 29
0
def _echo_error(  # pylint: disable=unused-argument
        message, non_interactive, more_archives, raised_exception, **kwargs):
    """Utility function to help write an error message for ``verdi import``

    :param message: Message following red-colored, bold "Error:".
    :type message: str
    :param non_interactive: Whether or not the user should be asked for input for any reason.
    :type non_interactive: bool
    :param more_archives: Whether or not there are more archives to import.
    :type more_archives: bool
    :param raised_exception: Exception raised during error.
    :type raised_exception: `Exception`
    """
    from aiida.tools.importexport import close_progress_bar, IMPORT_LOGGER

    # Close progress bar, if it exists
    close_progress_bar(leave=False)

    IMPORT_LOGGER.debug('%s', traceback.format_exc())

    exception = '{}: {}'.format(raised_exception.__class__.__name__,
                                str(raised_exception))

    echo.echo_error(message)
    echo.echo(exception)

    if more_archives:
        # There are more archives to go through
        if non_interactive:
            # Continue to next archive
            pass
        else:
            # Ask if one should continue to next archive
            click.confirm('Do you want to continue?', abort=True)
    else:
        # There are no more archives
        click.Abort()
Ejemplo n.º 30
0
def process_play(processes, timeout):
    """Play paused processes."""
    from aiida.work import RemoteException, DeliveryFailed, TimeoutError, new_blocking_control_panel

    with new_blocking_control_panel(timeout=timeout) as control_panel:
        for process in processes:

            if process.is_terminated:
                echo.echo_error('Process<{}> is already terminated'.format(
                    process.pk))
                continue

            try:
                if control_panel.play_process(process.pk):
                    echo.echo_success('played Process<{}>'.format(process.pk))
                else:
                    echo.echo_critical('problem playing Process<{}>'.format(
                        process.pk))
            except TimeoutError:
                echo.echo_error('call to play Process<{}> timed out'.format(
                    process.pk))
            except (RemoteException, DeliveryFailed) as exception:
                echo.echo_critical('failed to play Process<{}>: {}'.format(
                    process.pk, exception.message))