def configure_debug_logfile_path(debug_log_file_path: Optional[str]) -> str: """Determine the pathname for the debug logfile based on the given argument and user's OS""" if debug_log_file_path is not None: given_dir = os.path.dirname(debug_log_file_path) # If it's not just a filename relative to the current directory make sure # that the directory exists if given_dir != "" and not os.path.isdir(given_dir): raise ConfigurationError( f"The provided directory {given_dir} for the debuglog filename " f"either does not exist or is not a directory") return debug_log_file_path # From here and on determine default based on user's system time = datetime.datetime.utcnow().isoformat() debug_log_file_name = f"raiden-debug_{time}.log" home = os.path.expanduser("~") if home == "~": # Could not expand user path, just use /tmp datadir = "/tmp" if sys.platform == "darwin": datadir = os.path.join(home, "Library", "Logs", "Raiden") elif sys.platform == "win32" or sys.platform == "cygwin": datadir = os.path.join(home, "AppData", "Roaming", "Raiden") elif os.name == "posix": datadir = os.path.join(home, ".raiden") else: raise RuntimeError("Unsupported Operating System") if not os.path.exists(datadir): os.makedirs(datadir) return os.path.join(datadir, debug_log_file_name)
def test_run_error_reporting(cli_runner, monkeypatch): caught_exceptions = { APIServerPortInUseError(): ReturnCode.PORT_ALREADY_IN_USE, ConfigurationError(): ReturnCode.RAIDEN_CONFIGURATION_ERROR, ConnectTimeout(): ReturnCode.GENERIC_COMMUNICATION_ERROR, ConnectionError(): ReturnCode.GENERIC_COMMUNICATION_ERROR, EthereumNonceTooLow(): ReturnCode.ETH_ACCOUNT_ERROR, EthNodeInterfaceError(): ReturnCode.ETH_INTERFACE_ERROR, KeystoreAuthenticationError(): ReturnCode.ETH_ACCOUNT_ERROR, KeystoreFileNotFound(): ReturnCode.ETH_ACCOUNT_ERROR, RaidenUnrecoverableError(): ReturnCode.FATAL, ReplacementTransactionUnderpriced(): ReturnCode.ETH_ACCOUNT_ERROR, RequestsConnectionError(): ReturnCode.GENERIC_COMMUNICATION_ERROR, Exception(): ReturnCode.FATAL, } for exception, code in caught_exceptions.items(): monkeypatch.setattr(cli, "run_services", mock_raises(exception)) result = cli_runner(cli.run, "--accept-disclaimer") assert result.exception.code == code
def apply_config_file( command_function: Union[click.Command, click.Group], cli_params: Dict[str, Any], ctx, config_file_option_name="config_file", ): """ Applies all options set in the config file to `cli_params` """ options_using_default = ctx.meta.get(CONTEXT_KEY_DEFAULT_OPTIONS, set()) paramname_to_param = {param.name: param for param in command_function.params} path_params = { param.name for param in command_function.params if isinstance(param.type, (click.Path, click.File)) } config_file_path = Path(cli_params[config_file_option_name]) config_file_values: MutableMapping[str, Any] = dict() try: with config_file_path.open() as config_file: config_file_values = load(config_file) except OSError as ex: # Silently ignore if 'file not found' and the config file path is the default and # the option wasn't explicitly supplied on the command line config_file_param = paramname_to_param[config_file_option_name] config_file_default_path = Path( config_file_param.type.expand_default( # type: ignore config_file_param.get_default(ctx), cli_params ) ) default_config_missing = ( ex.errno == errno.ENOENT and config_file_path.resolve() == config_file_default_path.resolve() and config_file_option_name in options_using_default ) if default_config_missing: cli_params["config_file"] = None else: raise ConfigurationError(f"Error opening config file: {ex}") except TomlDecodeError as ex: raise ConfigurationError(f"Error loading config file: {ex}") for config_name, config_value in config_file_values.items(): config_name_int = config_name.replace("-", "_") if config_name_int not in paramname_to_param: click.secho( f"Unknown setting '{config_name}' found in config file - ignoring.", fg="yellow" ) continue if config_name_int in path_params: # Allow users to use `~` in paths in the config file config_value = os.path.expanduser(config_value) if config_name_int == LOG_CONFIG_OPTION_NAME: # Uppercase log level names config_value = {k: v.upper() for k, v in config_value.items()} else: # Pipe config file values through cli converter to ensure correct types # We exclude `log-config` because it already is a dict when loading from toml try: config_value = paramname_to_param[config_name_int].type.convert( config_value, paramname_to_param[config_name_int], ctx ) except click.BadParameter as ex: raise ConfigurationError(f"Invalid config file setting '{config_name}': {ex}") # Only use the config file value if the option wasn't explicitly given on the command line option_has_default = paramname_to_param[config_name_int].default is not None if not option_has_default or config_name_int in options_using_default: cli_params[config_name_int] = config_value