# -*- coding: utf-8 -*- ########################################################################### # Copyright (c), The AiiDA team. All rights reserved. # # This file is part of the AiiDA code. # # # # The code is hosted on GitHub at https://github.com/aiidateam/aiida-core # # For further information on the license, see the LICENSE.txt file # # For further information please visit http://www.aiida.net # ########################################################################### """Definition of known configuration options and methods to parse and get option values.""" import collections __all__ = ('get_option', 'get_option_names', 'parse_option') NO_DEFAULT = () DEFAULT_DAEMON_WORKERS = 1 DEFAULT_DAEMON_TIMEOUT = 20 # Default timeout in seconds for circus client calls DEFAULT_DAEMON_WORKER_PROCESS_SLOTS = 200 VALID_LOG_LEVELS = ['CRITICAL', 'ERROR', 'WARNING', 'REPORT', 'INFO', 'DEBUG'] Option = collections.namedtuple( 'Option', ['name', 'key', 'valid_type', 'valid_values', 'default', 'description', 'global_only'] ) CONFIG_OPTIONS = { 'runner.poll.interval': { 'key': 'runner_poll_interval', 'valid_type': 'int', 'valid_values': None, 'default': 60, 'description': 'The polling interval in seconds to be used by process runners', 'global_only': False, }, 'daemon.default_workers': { 'key': 'daemon_default_workers', 'valid_type': 'int', 'valid_values': None, 'default': DEFAULT_DAEMON_WORKERS, 'description': 'The default number of workers to be launched by `verdi daemon start`', 'global_only': False, }, 'daemon.timeout': { 'key': 'daemon_timeout', 'valid_type': 'int', 'valid_values': None, 'default': DEFAULT_DAEMON_TIMEOUT, 'description': 'The timeout in seconds for calls to the circus client', 'global_only': False, }, 'daemon.worker_process_slots': { 'key': 'daemon_worker_process_slots', 'valid_type': 'int', 'valid_values': None, 'default': DEFAULT_DAEMON_WORKER_PROCESS_SLOTS, 'description': 'The maximum number of concurrent process tasks that each daemon worker can handle', 'global_only': False, }, 'db.batch_size': { 'key': 'db_batch_size', 'valid_type': 'int', 'valid_values': None, 'default': 100000, 'description': 'Batch size for bulk CREATE operations in the database. Avoids hitting MaxAllocSize of PostgreSQL' '(1GB) when creating large numbers of database records in one go.', 'global_only': False, }, 'verdi.shell.auto_import': { 'key': 'verdi_shell_auto_import', 'valid_type': 'string', 'valid_values': None, 'default': '', 'description': 'Additional modules/functions/classes to be automatically loaded in `verdi shell`', 'global_only': False, }, 'logging.aiida_loglevel': { 'key': 'logging_aiida_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'REPORT', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `aiida` logger', 'global_only': False, }, 'logging.db_loglevel': { 'key': 'logging_db_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'REPORT', 'description': 'Minimum level to log to the DbLog table', 'global_only': False, }, 'logging.tornado_loglevel': { 'key': 'logging_tornado_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `tornado` logger', 'global_only': False, }, 'logging.plumpy_loglevel': { 'key': 'logging_plumpy_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `plumpy` logger', 'global_only': False, }, 'logging.kiwipy_loglevel': { 'key': 'logging_kiwipy_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `kiwipy` logger', 'global_only': False, }, 'logging.paramiko_loglevel': { 'key': 'logging_paramiko_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `paramiko` logger', 'global_only': False, }, 'logging.alembic_loglevel': { 'key': 'logging_alembic_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `alembic` logger', 'global_only': False, }, 'logging.sqlalchemy_loglevel': { 'key': 'logging_sqlalchemy_loglevel', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'WARNING', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `sqlalchemy` logger', 'global_only': False, }, 'logging.circus_loglevel': { 'key': 'logging_circus_log_level', 'valid_type': 'string', 'valid_values': VALID_LOG_LEVELS, 'default': 'INFO', 'description': 'Minimum level to log to daemon log and the `DbLog` table for the `circus` logger', 'global_only': False, }, 'user.email': { 'key': 'user_email', 'valid_type': 'string', 'valid_values': None, 'default': NO_DEFAULT, 'description': 'Default user email to use when creating new profiles.', 'global_only': True, }, 'user.first_name': { 'key': 'user_first_name', 'valid_type': 'string', 'valid_values': None, 'default': NO_DEFAULT, 'description': 'Default user first name to use when creating new profiles.', 'global_only': True, }, 'user.last_name': { 'key': 'user_last_name', 'valid_type': 'string', 'valid_values': None, 'default': NO_DEFAULT, 'description': 'Default user last name to use when creating new profiles.', 'global_only': True, }, 'user.institution': { 'key': 'user_institution', 'valid_type': 'string', 'valid_values': None, 'default': NO_DEFAULT, 'description': 'Default user institution to use when creating new profiles.', 'global_only': True, }, 'warnings.showdeprecations': { 'key': 'show_deprecations', 'valid_type': 'bool', 'valid_values': None, 'default': True, 'description': 'Boolean whether to print AiiDA deprecation warnings', 'global_only': False, }, } [docs]def get_option(option_name): """Return a configuration option.configuration :param option_name: the name of the configuration option :return: the configuration option :raises ValueError: if the configuration option does not exist """ try: option = Option(option_name, **CONFIG_OPTIONS[option_name]) except KeyError: raise ValueError('the option {} does not exist'.format(option_name)) else: return option [docs]def get_option_names(): """Return a list of available option names. :return: list of available option names """ return CONFIG_OPTIONS.keys() [docs]def parse_option(option_name, option_value): """Parse and validate a value for a configuration option. :param option_name: the name of the configuration option :param option_value: the option value :return: a tuple of the option and the parsed value """ option = get_option(option_name) value = False if option.valid_type == 'bool': if isinstance(option_value, str): if option_value.strip().lower() in ['0', 'false', 'f']: value = False elif option_value.strip().lower() in ['1', 'true', 't']: value = True else: raise ValueError('option {} expects a boolean value'.format(option.name)) else: value = bool(option_value) elif option.valid_type == 'string': value = str(option_value) elif option.valid_type == 'int': value = int(option_value) elif option.valid_type == 'list_of_str': value = option_value.split() else: raise NotImplementedError('Type string {} not implemented yet'.format(option.valid_type)) if option.valid_values is not None: if value not in option.valid_values: raise ValueError( '{} is not among the list of accepted values for option {}.\nThe valid values are: ' '{}'.format(value, option.name, ', '.join(option.valid_values)) ) return option, value