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)
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
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
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
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')
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))
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)
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)
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))
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')
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)
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')
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
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))
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))
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
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))
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
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()
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
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)
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
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
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)
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))
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
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)
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()
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))