Example #1
0
def start(foreground, number):
    """Start the daemon with NUMBER workers [default=1]."""
    from aiida.engine.daemon.client import get_daemon_client

    client = get_daemon_client()

    echo.echo('Starting the daemon... ', nl=False)

    if foreground:
        command = [
            'verdi', '-p', client.profile.name, 'daemon',
            _START_CIRCUS_COMMAND, '--foreground',
            str(number)
        ]
    else:
        command = [
            'verdi', '-p', client.profile.name, 'daemon',
            _START_CIRCUS_COMMAND,
            str(number)
        ]

    try:
        currenv = get_env_with_venv_bin()
        subprocess.check_output(command, env=currenv, stderr=subprocess.STDOUT)  # pylint: disable=unexpected-keyword-arg
    except subprocess.CalledProcessError as exception:
        click.secho('FAILED', fg='red', bold=True)
        echo.echo_critical(exception.output)

    # We add a small timeout to give the pid-file a chance to be created
    with spinner():
        time.sleep(1)
        response = client.get_status()

    print_client_response_status(response)
Example #2
0
def cmd_list(version, functional, protocol, project, raw):
    """List installed configurations of the SSSP."""
    from tabulate import tabulate

    mapping_project = {
        'count': lambda family: family.count(),
        'version': lambda family: family.label.split('/')[1],
        'functional': lambda family: family.label.split('/')[2],
        'protocol': lambda family: family.label.split('/')[3],
    }

    rows = []

    for [group] in get_sssp_families_builder(version, functional, protocol).iterall():

        row = []

        for projection in project:
            try:
                projected = mapping_project[projection](group)
            except KeyError:
                projected = getattr(group, projection)
            row.append(projected)

        rows.append(row)

    if not rows:
        echo.echo_info('SSSP has not yet been installed: use `aiida-sssp install` to install it.')
        return

    if raw:
        echo.echo(tabulate(rows, disable_numparse=True, tablefmt='plain'))
    else:
        echo.echo(tabulate(rows, headers=[projection.capitalize() for projection in project], disable_numparse=True))
Example #3
0
def restart(ctx, reset, no_wait):
    """Restart the daemon.

    By default will only reset the workers of the running daemon. After the restart the same amount of workers will be
    running. If the `--reset` flag is passed, however, the full circus daemon will be stopped and restarted with just
    a single worker.
    """
    from aiida.engine.daemon.client import get_daemon_client

    client = get_daemon_client()

    wait = not no_wait

    if reset:
        ctx.invoke(stop)
        ctx.invoke(start)
    else:

        if wait:
            echo.echo('Restarting the daemon... ', nl=False)
        else:
            echo.echo('Restarting the daemon')

        response = client.restart_daemon(wait)

        if wait:
            print_client_response_status(response)
Example #4
0
def node_label(nodes, label, raw, force):
    """View or set the label of one or more nodes."""
    table = []

    if label is None:
        for node in nodes:

            if raw:
                table.append([node.label])
            else:
                table.append([node.pk, node.label])

        if raw:
            echo.echo(tabulate.tabulate(table, tablefmt='plain'))
        else:
            echo.echo(tabulate.tabulate(table, headers=['ID', 'Label']))

    else:
        if not force:
            warning = f'Are you sure you want to set the label for {len(nodes)} nodes?'
            click.confirm(warning, abort=True)

        for node in nodes:
            node.label = label

        echo.echo_success(f"Set label '{label}' for {len(nodes)} nodes")
Example #5
0
def devel_describeproperties():
    """
    List all valid properties that can be stored in the AiiDA config file.

    Only properties listed in the ``_property_table`` of ``aida.common.setup`` can be used.
    """
    from aiida.common.setup import _property_table, _NoDefaultValue

    for prop in sorted(_property_table.keys()):

        prop_name = _property_table[prop][1]
        prop_type = _property_table[prop][2]
        prop_default = _property_table[prop][3]
        prop_values = _property_table[prop][4]

        if prop_values is None:
            prop_values_str = ''
        else:
            prop_values_str = ' Valid values: {}.'.format(', '.join(
                str(_) for _ in prop_values))

        if isinstance(prop_default, _NoDefaultValue):
            prop_default_str = ''
        else:
            prop_default_str = ' (default: {})'.format(prop_default)

        echo.echo('* {} ({}): {}{}{}'.format(prop, prop_name, prop_type,
                                             prop_default_str,
                                             prop_values_str))
Example #6
0
def echo_node_dict(nodes, keys, fmt, identifier, raw, use_attrs=True):
    """Show the attributes or extras of one or more nodes."""
    all_nodes = []
    for node in nodes:
        if identifier == 'pk':
            id_name = 'PK'
            id_value = node.pk
        else:
            id_name = 'UUID'
            id_value = node.uuid

        if use_attrs:
            node_dict = node.attributes
            dict_name = 'attributes'
        else:
            node_dict = node.extras
            dict_name = 'extras'

        if keys is not None:
            node_dict = {k: v for k, v in node_dict.items() if k in keys}

        if raw:
            all_nodes.append({id_name: id_value, dict_name: node_dict})
        else:
            echo.echo(f'{id_name}: {id_value}', bold=True)
            echo.echo_dictionary(node_dict, fmt=fmt)
    if raw:
        echo.echo_dictionary(all_nodes, fmt=fmt)
Example #7
0
def node_description(nodes, description, force, raw):
    """View or set the description of one or more nodes."""
    table = []

    if description is None:
        for node in nodes:

            if raw:
                table.append([node.description])
            else:
                table.append([node.pk, node.description])

        if raw:
            echo.echo(tabulate.tabulate(table, tablefmt='plain'))
        else:
            echo.echo(tabulate.tabulate(table, headers=['ID', 'Description']))

    else:
        if not force:
            warning = f'Are you sure you want to set the description for  {len(nodes)} nodes?'
            click.confirm(warning, abort=True)

        for node in nodes:
            node.description = description

        echo.echo_success(f'Set description for {len(nodes)} nodes')
Example #8
0
def status(all_profiles):
    """Print the status of the current daemon or all daemons.

    Returns exit code 0 if all requested daemons are running, else exit code 3.
    """
    from aiida.engine.daemon.client import get_daemon_client

    config = get_config()

    if all_profiles is True:
        profiles = [
            profile for profile in config.profiles
            if not profile.is_test_profile
        ]
    else:
        profiles = [config.current_profile]

    daemons_running = []
    for profile in profiles:
        client = get_daemon_client(profile.name)
        delete_stale_pid_file(client)
        click.secho('Profile: ', fg='red', bold=True, nl=False)
        click.secho('{}'.format(profile.name), bold=True)
        result = get_daemon_status(client)
        echo.echo(result)
        daemons_running.append(client.is_daemon_running)

    if not all(daemons_running):
        sys.exit(3)
Example #9
0
def singlefile_content(datum):
    """Show the content of the file."""
    try:
        echo.echo(datum.get_content())
    except (IOError, OSError) as exception:
        echo.echo_critical(
            'could not read the content for SinglefileData<{}>: {}'.format(
                datum.pk, str(exception)))
Example #10
0
def profile_show(profile):
    """Show details for a profile."""
    if profile is None:
        echo.echo_critical('no profile to show')

    echo.echo_info('Configuration for: {}'.format(profile.name))
    data = sorted([(k.lower(), v) for k, v in profile.dictionary.items()])
    echo.echo(tabulate.tabulate(data))
Example #11
0
def tree(nodes, depth):
    """
    Show trees of nodes.
    """
    for node in nodes:
        NodeTreePrinter.print_node_tree(node, depth)

        if len(nodes) > 1:
            echo.echo("")
Example #12
0
        def decorated_function(*args, **kwargs):
            """Echo a deprecation warning before doing anything else."""
            from aiida.cmdline.utils import echo, templates
            from textwrap import wrap

            template = templates.env.get_template('deprecated.tpl')
            width = 80
            echo.echo(template.render(msg=wrap(message, width), width=width))
            return function(*args, **kwargs)
Example #13
0
def cif_content(data):
    """Show the content of the CIF file."""
    for node in data:
        try:
            echo.echo(node.get_content())
        except IOError as exception:
            echo.echo_warning(
                'could not read the content for CifData<{}>: {}'.format(
                    node.pk, str(exception)))
Example #14
0
def repo_cat(node, relative_path):
    """Output the content of a file in the node repository folder."""
    try:
        content = node.get_object_content(relative_path)
    except Exception as exception:  # pylint: disable=broad-except
        echo.echo_critical('failed to get the content of file `{}`: {}'.format(
            relative_path, exception))
    else:
        echo.echo(content)
Example #15
0
def work_status(calculations):
    """
    Print the status of work calculations
    """
    from aiida.utils.ascii_vis import format_call_graph

    for calculation in calculations:
        graph = format_call_graph(calculation)
        echo.echo(graph)
Example #16
0
    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(f'Process<{sender}> [{subject}|{correlation_id}]: {body}')
def export_workflow_data(apps, _):
    """Export existing legacy workflow data to a JSON file."""
    from tempfile import NamedTemporaryFile

    DbWorkflow = apps.get_model('db', 'DbWorkflow')
    DbWorkflowData = apps.get_model('db', 'DbWorkflowData')
    DbWorkflowStep = apps.get_model('db', 'DbWorkflowStep')

    count_workflow = DbWorkflow.objects.count()
    count_workflow_data = DbWorkflowData.objects.count()
    count_workflow_step = DbWorkflowStep.objects.count()

    # Nothing to do if all tables are empty
    if count_workflow == 0 and count_workflow_data == 0 and count_workflow_step == 0:
        return

    if not configuration.PROFILE.is_test_profile:
        echo.echo('\n')
        echo.echo_warning(
            'The legacy workflow tables contain data but will have to be dropped to continue.'
        )
        echo.echo_warning(
            'If you continue, the content will be dumped to a JSON file, before dropping the tables.'
        )
        echo.echo_warning(
            'This serves merely as a reference and cannot be used to restore the database.'
        )
        echo.echo_warning(
            'If you want a proper backup, make sure to dump the full database and backup your repository'
        )
        if not click.confirm('Are you sure you want to continue',
                             default=True):
            sys.exit(1)

    delete_on_close = configuration.PROFILE.is_test_profile

    data = {
        'workflow':
        serializers.serialize('json', DbWorkflow.objects.all()),
        'workflow_data':
        serializers.serialize('json', DbWorkflowData.objects.all()),
        'workflow_step':
        serializers.serialize('json', DbWorkflowStep.objects.all()),
    }

    with NamedTemporaryFile(prefix='legacy-workflows',
                            suffix='.json',
                            dir='.',
                            delete=delete_on_close,
                            mode='wb') as handle:
        filename = handle.name
        json.dump(data, handle)

    # If delete_on_close is False, we are running for the user and add additional message of file location
    if not delete_on_close:
        echo.echo_info(f'Exported workflow data to {filename}')
Example #18
0
def group_description(group, description):
    """Change the description of a group.

    If no DESCRIPTION is defined, the current description will simply be echoed.
    """
    if description:
        group.description = description
        echo.echo_success(f'Changed the description of Group<{group.label}>')
    else:
        echo.echo(group.description)
Example #19
0
def tree(nodes, depth):
    """Show a tree of nodes starting from a given node."""
    from aiida.common import LinkType
    from aiida.cmdline.utils.ascii_vis import NodeTreePrinter

    for node in nodes:
        NodeTreePrinter.print_node_tree(node, depth, tuple(LinkType.__members__.values()))

        if len(nodes) > 1:
            echo.echo('')
Example #20
0
def database_migrate(force):
    """Migrate the database to the latest schema version."""
    from aiida.manage.manager import get_manager
    from aiida.engine.daemon.client import get_daemon_client

    client = get_daemon_client()
    if client.is_daemon_running:
        echo.echo_critical(
            'Migration aborted, the daemon for the profile is still running.')

    manager = get_manager()
    profile = manager.get_profile()
    backend = manager._load_backend(schema_check=False)  # pylint: disable=protected-access

    if force:
        try:
            backend.migrate()
        except exceptions.ConfigurationError as exception:
            echo.echo_critical(str(exception))
        return

    echo.echo_warning(
        'Migrating your database might take a while and is not reversible.')
    echo.echo_warning(
        'Before continuing, make sure you have completed the following steps:')
    echo.echo_warning('')
    echo.echo_warning(
        ' 1. Make sure you have no active calculations and workflows.')
    echo.echo_warning(
        ' 2. If you do, revert the code to the previous version and finish running them first.'
    )
    echo.echo_warning(' 3. Stop the daemon using `verdi daemon stop`')
    echo.echo_warning(' 4. Make a backup of your database and repository')
    echo.echo_warning('')
    echo.echo_warning('', nl=False)

    expected_answer = 'MIGRATE NOW'
    confirm_message = 'If you have completed the steps above and want to migrate profile "{}", type {}'.format(
        profile.name, expected_answer)

    try:
        response = click.prompt(confirm_message)
        while response != expected_answer:
            response = click.prompt(confirm_message)
    except click.Abort:
        echo.echo('\n')
        echo.echo_critical(
            'Migration aborted, the data has not been affected.')
    else:
        try:
            backend.migrate()
        except exceptions.ConfigurationError as exception:
            echo.echo_critical(str(exception))
        else:
            echo.echo_success('migration completed')
Example #21
0
def _computer_test_no_unexpected_output(transport, scheduler, authinfo):  # pylint: disable=unused-argument
    """
    Test that there is no unexpected output from the connection.

    This can happen if e.g. there is some spurious command in the
    .bashrc or .bash_profile that is not guarded in case of non-interactive
    shells.

    :param transport: an open transport
    :param scheduler: the corresponding scheduler class
    :param authinfo: the AuthInfo object (from which one can get computer and aiidauser)
    :return: True if the test succeeds, False if it fails.
    """
    # Execute a command that should not return any error
    echo.echo('> Checking that no spurious output is present...')
    retval, stdout, stderr = transport.exec_command_wait('echo -n')
    if retval != 0:
        echo.echo_error("* ERROR! The command 'echo -n' returned a non-zero return code ({})!".format(retval))
        return False
    if stdout:
        echo.echo_error(
            u"""* ERROR! There is some spurious output in the standard output,
that we report below between the === signs:
=========================================================
{}
=========================================================
Please check that you don't have code producing output in
your ~/.bash_profile (or ~/.bashrc). If you don't want to
remove the code, but just to disable it for non-interactive
shells, see comments in issue #1980 on GitHub:
https://github.com/aiidateam/aiida-core/issues/1890
(and in the AiiDA documentation, linked from that issue)
""".format(stdout)
        )
        return False
    if stderr:
        echo.echo_error(
            u"""* ERROR! There is some spurious output in the stderr,
that we report below between the === signs:
=========================================================
{}
=========================================================
Please check that you don't have code producing output in
your ~/.bash_profile (or ~/.bashrc). If you don't want to
remove the code, but just to disable it for non-interactive
shells, see comments in issue #1980 on GitHub:
https://github.com/aiidateam/aiida-core/issues/1890
(and in the AiiDA documentation, linked from that issue)
""".format(stderr)
        )
        return False

    echo.echo('      [OK]')
    return True
Example #22
0
def computer_config_show(computer, user, defaults, as_option_string):
    """Show the current configuration for a computer."""
    import tabulate
    from aiida.common.escaping import escape_for_bash

    transport_cls = computer.get_transport_class()
    option_list = [
        param for param in transport_cli.create_configure_cmd(
            computer.get_transport_type()).params
        if isinstance(param, click.core.Option)
    ]
    option_list = [
        option for option in option_list
        if option.name in transport_cls.get_valid_auth_params()
    ]

    if defaults:
        config = {
            option.name:
            transport_cli.transport_option_default(option.name, computer)
            for option in option_list
        }
    else:
        config = computer.get_configuration(user)

    option_items = []
    if as_option_string:
        for option in option_list:
            t_opt = transport_cls.auth_options[option.name]
            if config.get(option.name) or config.get(option.name) is False:
                if t_opt.get('switch'):
                    option_value = option.opts[-1] if config.get(
                        option.name) else '--no-{}'.format(
                            option.name.replace('_', '-'))
                elif t_opt.get('is_flag'):
                    is_default = config.get(
                        option.name) == transport_cli.transport_option_default(
                            option.name, computer)
                    option_value = option.opts[-1] if is_default else ''
                else:
                    option_value = '{}={}'.format(
                        option.opts[-1], option.type(config[option.name]))
                option_items.append(option_value)
        opt_string = ' '.join(option_items)
        echo.echo(escape_for_bash(opt_string))
    else:
        table = []
        for name in transport_cls.get_valid_auth_params():
            if name in config:
                table.append(('* ' + name, config[name]))
            else:
                table.append(('* ' + name, '-'))
        echo.echo(tabulate.tabulate(table, tablefmt='plain'))
Example #23
0
def cmd_show(family, raw):
    """Show details of pseudo potential family."""
    from tabulate import tabulate

    rows = [[pseudo.element, pseudo.filename, pseudo.md5]
            for pseudo in family.nodes]
    headers = ['Element', 'Pseudo', 'MD5']

    if raw:
        echo.echo(tabulate(sorted(rows), tablefmt='plain'))
    else:
        echo.echo(tabulate(sorted(rows), headers=headers))
Example #24
0
def devel_listproperties(all_entries):
    """List all the properties that are explicitly set for the current profile."""
    from aiida.common.setup import _property_table, exists_property, get_property

    for prop in sorted(_property_table.keys()):
        try:
            # To enforce the generation of an exception, even if there is a default value
            if all_entries or exists_property(prop):
                val = get_property(prop)
                echo.echo('{} = {}'.format(prop, val))
        except KeyError:
            pass
Example #25
0
def cmd_uniques(
    group, databases, not_elements, elements, max_atoms, number_species, partial_occupancies, no_cod_hydrogen, verbose
):
    """Pass."""
    from tabulate import tabulate
    from aiida import orm

    filters = {'and': []}

    if not group and not databases:
        raise click.BadParameter('need at least a GROUP or `--databases` to be specified')

    if not group:
        if len(databases) >= 1:
            raise click.BadParameter('can only specify one database when not specifying a GROUP')
        group = orm.load_group('{}/structure/unique'.format(databases[0]))

    if no_cod_hydrogen:
        filters['and'].append({'id': {'!in': get_cod_hydrogen_structure_ids()}})

    if max_atoms is not None:
        filters['and'].append({'attributes.sites': {'shorter': max_atoms + 1}})

    if number_species is not None:
        filters['and'].append({'attributes.kinds': {'of_length': number_species}})

    if elements:
        filters['and'].append({'extras.chemical_system': {'like': '%-{}-%'.format('-%-'.join(sorted(elements)))}})

    if not_elements:
        for element in not_elements:
            filters['and'].append({'extras.chemical_system': {'!like': '%-{}-%'.format(element)}})

    if partial_occupancies is not None:
        filters['and'].append({'extras.{}'.format(KEY_PARTIAL_OCCUPANCIES): partial_occupancies})

    if databases:
        for name in DATABASES:
            key = 'has_key' if name in databases else '!has_key'
            filters['and'].append({'extras.duplicates': {key: name}})

    builder = orm.QueryBuilder().append(
        orm.Group, filters={'id': group.id}, tag='group').append(
        orm.StructureData, with_group='group', filters=filters)

    if not verbose:
        echo.echo('{}'.format(builder.count()))
    else:
        rows = []
        for [structure] in builder.iterall():
            rows.append((structure.get_formula(), len(structure.kinds), len(structure.sites), structure.uuid, structure.get_extra('source')['id']))

        echo.echo(tabulate(rows, headers=['Formula', '# species', '# atoms', 'UUID', 'Source identifier']))
Example #26
0
def _computer_test_get_jobs(transport, scheduler, authinfo):  # pylint: disable=unused-argument
    """
    Internal test to check if it is possible to check the queue state.

    :param transport: an open transport
    :param scheduler: the corresponding scheduler class
    :param authinfo: the AuthInfo object (from which one can get computer and aiidauser)
    :return: True if the test succeeds, False if it fails.
    """
    echo.echo("> Getting job list...")
    found_jobs = scheduler.getJobs(as_dict=True)
    echo.echo("  `-> OK, {} jobs found in the queue.".format(len(found_jobs)))
    return True
Example #27
0
def devel_getproperty(prop):
    """Get the global PROPERTY from the configuration file."""
    from aiida.common.setup import get_property

    try:
        value = get_property(prop)
    except ValueError:
        echo.echo_critical('property {} not found'.format(prop))
    except Exception as exception:  # pylint: disable=broad-except
        echo.echo_critical('{} while getting the property: {}'.format(
            type(exception).__name__, exception.message))
    else:
        echo.echo('{}'.format(value))
Example #28
0
    def print_node_tree(cls, node, max_depth, follow_links=()):
        """Top-level function for printing node tree."""
        from ete3 import Tree
        from aiida.cmdline.utils.common import get_node_summary

        echo.echo(get_node_summary(node))

        tree_string = '({});'.format(
            cls._build_tree(node,
                            max_depth=max_depth,
                            follow_links=follow_links))
        tmp = Tree(tree_string, format=1)
        echo.echo(tmp.get_ascii(show_internal=True))
Example #29
0
def verdi_config_caching(disabled):
    """List caching-enabled process types for the current profile."""
    from aiida.plugins.entry_point import ENTRY_POINT_STRING_SEPARATOR, get_entry_point_names
    from aiida.manage.caching import get_use_cache

    for group in ['aiida.calculations', 'aiida.workflows']:
        for entry_point in get_entry_point_names(group):
            identifier = ENTRY_POINT_STRING_SEPARATOR.join([group, entry_point])
            if get_use_cache(identifier=identifier):
                if not disabled:
                    echo.echo(identifier)
            elif disabled:
                echo.echo(identifier)
Example #30
0
def delete_db(profile, non_interactive=True, verbose=False):
    """
    Delete an AiiDA database associated with an AiiDA profile.

    :param profile: AiiDA Profile
    :type profile: :class:`aiida.manage.configuration.profile.Profile`
    :param non_interactive: do not prompt for configuration values, fail if not all values are given as kwargs.
    :type non_interactive: bool
    :param verbose: if True, print parameters of DB connection
    :type verbose: bool
    """
    from aiida.manage.configuration import get_config
    from aiida.manage.external.postgres import Postgres
    from aiida.common import json

    postgres = Postgres.from_profile(profile,
                                     interactive=not non_interactive,
                                     quiet=False)

    if verbose:
        echo.echo_info('Parameters used to connect to postgres:')
        echo.echo(json.dumps(postgres.dbinfo, indent=4))

    database_name = profile.database_name
    if not postgres.db_exists(database_name):
        echo.echo_info(
            "Associated database '{}' does not exist.".format(database_name))
    elif non_interactive or click.confirm(
            "Delete associated database '{}'?\n"
            'WARNING: All data will be lost.'.format(database_name)):
        echo.echo_info("Deleting database '{}'.".format(database_name))
        postgres.drop_db(database_name)

    user = profile.database_username
    config = get_config()
    users = [
        available_profile.database_username
        for available_profile in config.profiles
    ]

    if not postgres.dbuser_exists(user):
        echo.echo_info(
            "Associated database user '{}' does not exist.".format(user))
    elif users.count(user) > 1:
        echo.echo_info(
            "Associated database user '{}' is used by other profiles "
            'and will not be deleted.'.format(user))
    elif non_interactive or click.confirm(
            "Delete database user '{}'?".format(user)):
        echo.echo_info("Deleting user '{}'.".format(user))
        postgres.drop_dbuser(user)