mirror of
https://git.zavage.net/Zavage-Software/app_skellington.git
synced 2024-12-21 22:29:20 -07:00
style: black and isort
This commit is contained in:
parent
82543ce157
commit
25ded9e2b3
12
README.md
12
README.md
@ -11,7 +11,7 @@ Application framework for Python, features include:
|
|||||||
Principles:
|
Principles:
|
||||||
- Lend to creating beautiful, easy to read and understand code in the application.
|
- Lend to creating beautiful, easy to read and understand code in the application.
|
||||||
- Minimize coupling of applications to this framework.
|
- Minimize coupling of applications to this framework.
|
||||||
- Compatable with Linux, Windows, and Mac. Try to be compatible as possible otherwise.
|
- Compatible with Linux, Windows, and Mac. Try to be compatible as possible otherwise.
|
||||||
- Try to be compatible with alternate Python runtimes such as PyPy and older python environments. \*WIP
|
- Try to be compatible with alternate Python runtimes such as PyPy and older python environments. \*WIP
|
||||||
|
|
||||||
# PyPi Hosted Link
|
# PyPi Hosted Link
|
||||||
@ -103,6 +103,13 @@ Install:
|
|||||||
pip install .
|
pip install .
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Formatting and Linters:
|
||||||
|
```
|
||||||
|
black app_skellington
|
||||||
|
isort app_skellington
|
||||||
|
flake8 app_skellington
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Version
|
# Version
|
||||||
@ -123,7 +130,6 @@ MIT no attribution required - https://opensource.org/license/mit-0
|
|||||||
* Project page: https://zavage-software.com/portfolio/app_skellington
|
* Project page: https://zavage-software.com/portfolio/app_skellington
|
||||||
* Please report bugs, improvements, or feedback!
|
* Please report bugs, improvements, or feedback!
|
||||||
* Contact: mathew@zavage.net
|
* Contact: mathew@zavage.net
|
||||||
|
|
||||||
* Packing and distribution conforms to PEP 621 https://peps.python.org/pep-0621/
|
* Packing and distribution conforms to PEP 621 https://peps.python.org/pep-0621/
|
||||||
* Reference https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/
|
* Reference https://packaging.python.org/en/latest/guides/distributing-packages-using-setuptools/
|
||||||
|
|
||||||
|
@ -39,7 +39,9 @@ if os.environ.get("APPSKELLINGTON_DEBUG", None):
|
|||||||
handler = logging.StreamHandler()
|
handler = logging.StreamHandler()
|
||||||
handler.setFormatter(fmt)
|
handler.setFormatter(fmt)
|
||||||
_bootstrap_logger.addHandler(handler)
|
_bootstrap_logger.addHandler(handler)
|
||||||
_bootstrap_logger.debug("log - APPSKELLINGTON_DEBUG set in environment: Enabling verbose logging.")
|
_bootstrap_logger.debug(
|
||||||
|
"log - APPSKELLINGTON_DEBUG set in environment: Enabling verbose logging."
|
||||||
|
)
|
||||||
|
|
||||||
# Logging is by default off, excepting CRITICAL
|
# Logging is by default off, excepting CRITICAL
|
||||||
else:
|
else:
|
||||||
|
@ -7,12 +7,7 @@ import sys
|
|||||||
|
|
||||||
import appdirs
|
import appdirs
|
||||||
|
|
||||||
from . import (
|
from . import _util, cfg, cli, log
|
||||||
_util,
|
|
||||||
cfg,
|
|
||||||
cli,
|
|
||||||
log,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Application scaffolding:
|
# Application scaffolding:
|
||||||
from ._bootstrap import _bootstrap_logger
|
from ._bootstrap import _bootstrap_logger
|
||||||
@ -47,7 +42,9 @@ class ApplicationContainer:
|
|||||||
directories.
|
directories.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, configspec_filepath=None, configini_filepath=None, *args, **kwargs):
|
def __init__(
|
||||||
|
self, configspec_filepath=None, configini_filepath=None, *args, **kwargs
|
||||||
|
):
|
||||||
self.appname = kwargs.get("appname") or DEFAULT_APP_NAME
|
self.appname = kwargs.get("appname") or DEFAULT_APP_NAME
|
||||||
self.appauthor = kwargs.get("appauthor") or DEFAULT_APP_AUTHOR
|
self.appauthor = kwargs.get("appauthor") or DEFAULT_APP_AUTHOR
|
||||||
|
|
||||||
@ -100,7 +97,9 @@ class ApplicationContainer:
|
|||||||
app['datalayer'] => returns the made-up "datalayer" service.
|
app['datalayer'] => returns the made-up "datalayer" service.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
service_factory = self._dependencies[service_name] # Retrieve factory function
|
service_factory = self._dependencies[
|
||||||
|
service_name
|
||||||
|
] # Retrieve factory function
|
||||||
return service_factory() # Call factory() to return instance of service
|
return service_factory() # Call factory() to return instance of service
|
||||||
except KeyError as ex:
|
except KeyError as ex:
|
||||||
msg = "failed to inject service: {}".format(service_name)
|
msg = "failed to inject service: {}".format(service_name)
|
||||||
@ -160,7 +159,9 @@ class ApplicationContainer:
|
|||||||
"""
|
"""
|
||||||
sig = inspect.signature(constructor.__init__)
|
sig = inspect.signature(constructor.__init__)
|
||||||
params = sig.parameters
|
params = sig.parameters
|
||||||
params = [params[paramname].name for paramname in params] # Convert Param() type => str
|
params = [
|
||||||
|
params[paramname].name for paramname in params
|
||||||
|
] # Convert Param() type => str
|
||||||
cls_dependencies = params[1:] # Skip 'self' parameter on class methods.
|
cls_dependencies = params[1:] # Skip 'self' parameter on class methods.
|
||||||
|
|
||||||
return functools.partial(self._construct_model, constructor, *cls_dependencies)
|
return functools.partial(self._construct_model, constructor, *cls_dependencies)
|
||||||
|
@ -31,7 +31,9 @@ class Config:
|
|||||||
"allow_options_beyond_spec": True,
|
"allow_options_beyond_spec": True,
|
||||||
}
|
}
|
||||||
|
|
||||||
def __init__(self, configspec_filepath=None, configini_filepath=None, capabilities=None):
|
def __init__(
|
||||||
|
self, configspec_filepath=None, configini_filepath=None, capabilities=None
|
||||||
|
):
|
||||||
self._config_obj = None # must be type configobj.ConfigObj()
|
self._config_obj = None # must be type configobj.ConfigObj()
|
||||||
self._configini_data = None
|
self._configini_data = None
|
||||||
self._configini_filepath = None
|
self._configini_filepath = None
|
||||||
@ -93,11 +95,15 @@ class Config:
|
|||||||
self._configspec_filepath = filepath
|
self._configspec_filepath = filepath
|
||||||
self._configspec_data = data
|
self._configspec_data = data
|
||||||
self._has_changed_internally = True
|
self._has_changed_internally = True
|
||||||
_bootstrap_logger.debug("cfg - Set configspec and read contents: %s", filepath)
|
_bootstrap_logger.debug(
|
||||||
|
"cfg - Set configspec and read contents: %s", filepath
|
||||||
|
)
|
||||||
self.load_config()
|
self.load_config()
|
||||||
return
|
return
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
_bootstrap_logger.critical("cfg - Failed to find config.spec: file not found (%s)", filepath)
|
_bootstrap_logger.critical(
|
||||||
|
"cfg - Failed to find config.spec: file not found (%s)", filepath
|
||||||
|
)
|
||||||
raise OSError("Failed to read provided config.spec file")
|
raise OSError("Failed to read provided config.spec file")
|
||||||
|
|
||||||
self.load_config()
|
self.load_config()
|
||||||
@ -187,12 +193,16 @@ class Config:
|
|||||||
# raise_errors
|
# raise_errors
|
||||||
)
|
)
|
||||||
_bootstrap_logger.debug(
|
_bootstrap_logger.debug(
|
||||||
"cfg - Parsed configuration. config.spec = %s, config.ini = %s", config_spec, config_ini
|
"cfg - Parsed configuration. config.spec = %s, config.ini = %s",
|
||||||
|
config_spec,
|
||||||
|
config_ini,
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
except configobj.ParseError as ex:
|
except configobj.ParseError as ex:
|
||||||
msg = "cfg - Failed to load config: error in config.spec configuration: {}".format(config_filepath)
|
msg = "cfg - Failed to load config: error in config.spec configuration: {}".format(
|
||||||
|
config_filepath
|
||||||
|
)
|
||||||
_bootstrap_logger.error(msg)
|
_bootstrap_logger.error(msg)
|
||||||
return False
|
return False
|
||||||
except OSError as ex:
|
except OSError as ex:
|
||||||
@ -217,7 +227,9 @@ class Config:
|
|||||||
self._config_obj, configobj.ConfigObj
|
self._config_obj, configobj.ConfigObj
|
||||||
), "expecting configobj.ConfigObj, received %s" % type(self._config_obj)
|
), "expecting configobj.ConfigObj, received %s" % type(self._config_obj)
|
||||||
# NOTE(MG) copy arg below instructs configobj to use defaults from spec file
|
# NOTE(MG) copy arg below instructs configobj to use defaults from spec file
|
||||||
test_results = self._config_obj.validate(val, copy=True, preserve_errors=True)
|
test_results = self._config_obj.validate(
|
||||||
|
val, copy=True, preserve_errors=True
|
||||||
|
)
|
||||||
if test_results is True:
|
if test_results is True:
|
||||||
_bootstrap_logger.info(
|
_bootstrap_logger.info(
|
||||||
"cfg- Successfully validated configuration against spec. input = %s, validation spec = %s",
|
"cfg- Successfully validated configuration against spec. input = %s, validation spec = %s",
|
||||||
@ -227,19 +239,27 @@ class Config:
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
elif test_results is False:
|
elif test_results is False:
|
||||||
_bootstrap_logger.debug("cfg - Potentially discovered invalid config.spec")
|
_bootstrap_logger.debug(
|
||||||
|
"cfg - Potentially discovered invalid config.spec"
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self._validate_parse_errors(test_results)
|
self._validate_parse_errors(test_results)
|
||||||
return False
|
return False
|
||||||
except ValueError as ex:
|
except ValueError as ex:
|
||||||
_bootstrap_logger.error("cfg - Failed while validating config against spec. ")
|
_bootstrap_logger.error(
|
||||||
|
"cfg - Failed while validating config against spec. "
|
||||||
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _validate_parse_errors(self, test_results):
|
def _validate_parse_errors(self, test_results):
|
||||||
_bootstrap_logger.critical("cfg - Config file failed validation.")
|
_bootstrap_logger.critical("cfg - Config file failed validation.")
|
||||||
for section_list, key, rslt in configobj.flatten_errors(self._config_obj, test_results):
|
for section_list, key, rslt in configobj.flatten_errors(
|
||||||
_bootstrap_logger.critical("cfg - Config error info: %s %s %s", section_list, key, rslt)
|
self._config_obj, test_results
|
||||||
|
):
|
||||||
|
_bootstrap_logger.critical(
|
||||||
|
"cfg - Config error info: %s %s %s", section_list, key, rslt
|
||||||
|
)
|
||||||
if key is not None:
|
if key is not None:
|
||||||
_bootstrap_logger.critical(
|
_bootstrap_logger.critical(
|
||||||
"cfg - Config failed validation: [%s].%s appears invalid. msg = %s",
|
"cfg - Config failed validation: [%s].%s appears invalid. msg = %s",
|
||||||
|
@ -75,7 +75,9 @@ class CommandTree:
|
|||||||
"""
|
"""
|
||||||
Adds an argument to the root parser.
|
Adds an argument to the root parser.
|
||||||
"""
|
"""
|
||||||
_bootstrap_logger.info("adding argument to root parser: %s and %s", args, kwargs)
|
_bootstrap_logger.info(
|
||||||
|
"adding argument to root parser: %s and %s", args, kwargs
|
||||||
|
)
|
||||||
self.root_parser.add_argument(*args, **kwargs)
|
self.root_parser.add_argument(*args, **kwargs)
|
||||||
|
|
||||||
def init_submenu(self, param_name, is_required=False):
|
def init_submenu(self, param_name, is_required=False):
|
||||||
@ -89,7 +91,9 @@ class CommandTree:
|
|||||||
func_args = {"dest": param_name, "metavar": param_name, "required": is_required}
|
func_args = {"dest": param_name, "metavar": param_name, "required": is_required}
|
||||||
if sys.version_info.major == 3 and sys.version_info.minor < 7:
|
if sys.version_info.major == 3 and sys.version_info.minor < 7:
|
||||||
if is_required:
|
if is_required:
|
||||||
_bootstrap_logger.warn("Unable to enforce required submenu: Requires >= Python 3.7")
|
_bootstrap_logger.warn(
|
||||||
|
"Unable to enforce required submenu: Requires >= Python 3.7"
|
||||||
|
)
|
||||||
del func_args["required"]
|
del func_args["required"]
|
||||||
# END fix for Python<3.7
|
# END fix for Python<3.7
|
||||||
|
|
||||||
@ -100,13 +104,17 @@ class CommandTree:
|
|||||||
submenu.submenu_path = ""
|
submenu.submenu_path = ""
|
||||||
submenu.var_name = param_name
|
submenu.var_name = param_name
|
||||||
|
|
||||||
_bootstrap_logger.info("Initialized root-level submenu: Parameter = '%s'", param_name)
|
_bootstrap_logger.info(
|
||||||
|
"Initialized root-level submenu: Parameter = '%s'", param_name
|
||||||
|
)
|
||||||
self.entries[param_name] = submenu
|
self.entries[param_name] = submenu
|
||||||
self.submenu_param = param_name
|
self.submenu_param = param_name
|
||||||
|
|
||||||
return submenu
|
return submenu
|
||||||
|
|
||||||
def register_command(self, func, cmd_name=None, func_signature=None, docstring=None):
|
def register_command(
|
||||||
|
self, func, cmd_name=None, func_signature=None, docstring=None
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
When no submenu functionality is desired, this links a single
|
When no submenu functionality is desired, this links a single
|
||||||
command into underlying argparse options.
|
command into underlying argparse options.
|
||||||
@ -154,7 +162,9 @@ class CommandTree:
|
|||||||
helptext = "default provided"
|
helptext = "default provided"
|
||||||
else:
|
else:
|
||||||
helptext = "default = '{}'".format(param.default)
|
helptext = "default = '{}'".format(param.default)
|
||||||
self.root_parser.add_argument(key, help=helptext, nargs="?", default=param.default)
|
self.root_parser.add_argument(
|
||||||
|
key, help=helptext, nargs="?", default=param.default
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
helptext = "required"
|
helptext = "required"
|
||||||
self.root_parser.add_argument(key, help=helptext)
|
self.root_parser.add_argument(key, help=helptext)
|
||||||
@ -230,16 +240,22 @@ class CommandTree:
|
|||||||
# the CommandTree with no SubMenu (submenu will be disabled
|
# the CommandTree with no SubMenu (submenu will be disabled
|
||||||
# in this case):
|
# in this case):
|
||||||
if self._cmd_tree_is_single_command:
|
if self._cmd_tree_is_single_command:
|
||||||
assert self._cmd_tree_is_single_command is True, "corrupt data structure in CommandMenu"
|
assert (
|
||||||
|
self._cmd_tree_is_single_command is True
|
||||||
|
), "corrupt data structure in CommandMenu"
|
||||||
assert self._entries is None, "corrupt data structure in CommandMenu"
|
assert self._entries is None, "corrupt data structure in CommandMenu"
|
||||||
assert isinstance(self._single_command, CommandEntry), "corrupt data structure in CommandMenu"
|
assert isinstance(
|
||||||
|
self._single_command, CommandEntry
|
||||||
|
), "corrupt data structure in CommandMenu"
|
||||||
return self._single_command
|
return self._single_command
|
||||||
|
|
||||||
# There is at least one submenu we need to go down:
|
# There is at least one submenu we need to go down:
|
||||||
else:
|
else:
|
||||||
|
|
||||||
assert self._single_command is None, "corrupt data structure in CommandMenu"
|
assert self._single_command is None, "corrupt data structure in CommandMenu"
|
||||||
assert self._cmd_tree_is_single_command == False, "corrupt data structure in CommandMenu"
|
assert (
|
||||||
|
self._cmd_tree_is_single_command == False
|
||||||
|
), "corrupt data structure in CommandMenu"
|
||||||
|
|
||||||
# Key or variable name used by argparse to store the submenu options
|
# Key or variable name used by argparse to store the submenu options
|
||||||
argparse_param = self.submenu_param # e.g.: submenu_root
|
argparse_param = self.submenu_param # e.g.: submenu_root
|
||||||
@ -251,10 +267,14 @@ class CommandTree:
|
|||||||
input("<broken>")
|
input("<broken>")
|
||||||
|
|
||||||
val = args.get(argparse_param)
|
val = args.get(argparse_param)
|
||||||
_bootstrap_logger.debug("cli - argparse command is '{}' = {}".format(argparse_param, val))
|
_bootstrap_logger.debug(
|
||||||
|
"cli - argparse command is '{}' = {}".format(argparse_param, val)
|
||||||
|
)
|
||||||
|
|
||||||
lookup = submenu.entries.get(val)
|
lookup = submenu.entries.get(val)
|
||||||
_bootstrap_logger.debug("cli - lookup, entries[{}] = {}".format(val, lookup))
|
_bootstrap_logger.debug(
|
||||||
|
"cli - lookup, entries[{}] = {}".format(val, lookup)
|
||||||
|
)
|
||||||
|
|
||||||
# pop value
|
# pop value
|
||||||
del args[argparse_param]
|
del args[argparse_param]
|
||||||
@ -297,7 +317,9 @@ class SubMenu:
|
|||||||
|
|
||||||
self.entries = {}
|
self.entries = {}
|
||||||
|
|
||||||
def register_command(self, func, cmd_name=None, func_signature=None, docstring=None):
|
def register_command(
|
||||||
|
self, func, cmd_name=None, func_signature=None, docstring=None
|
||||||
|
):
|
||||||
"""
|
"""
|
||||||
Registers a command as an entry in this submenu. Provided function is
|
Registers a command as an entry in this submenu. Provided function is
|
||||||
converted into argparse arguments and made available to the user.
|
converted into argparse arguments and made available to the user.
|
||||||
@ -371,7 +393,9 @@ class SubMenu:
|
|||||||
helptext = "default provided"
|
helptext = "default provided"
|
||||||
else:
|
else:
|
||||||
helptext = "default = '{}'".format(param.default)
|
helptext = "default = '{}'".format(param.default)
|
||||||
child_node.add_argument(key, help=helptext, nargs="?", default=param.default)
|
child_node.add_argument(
|
||||||
|
key, help=helptext, nargs="?", default=param.default
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
helptext = "required"
|
helptext = "required"
|
||||||
child_node.add_argument(key, help=helptext)
|
child_node.add_argument(key, help=helptext)
|
||||||
@ -422,7 +446,9 @@ class SubMenu:
|
|||||||
func_args = {"dest": var_name, "metavar": var_name, "required": is_required}
|
func_args = {"dest": var_name, "metavar": var_name, "required": is_required}
|
||||||
if sys.version_info.major == 3 and sys.version_info.minor < 7:
|
if sys.version_info.major == 3 and sys.version_info.minor < 7:
|
||||||
if is_required:
|
if is_required:
|
||||||
_bootstrap_logger.warn("Unable to enforce required submenu: Requires >= Python 3.7")
|
_bootstrap_logger.warn(
|
||||||
|
"Unable to enforce required submenu: Requires >= Python 3.7"
|
||||||
|
)
|
||||||
del func_args["required"]
|
del func_args["required"]
|
||||||
# END fix for Python<3.7
|
# END fix for Python<3.7
|
||||||
|
|
||||||
|
@ -16,7 +16,13 @@ DEFAULT_LOG_SETTINGS = {
|
|||||||
"format": "%(white)s%(name)7s%(reset)s|%(log_color)s%(message)s",
|
"format": "%(white)s%(name)7s%(reset)s|%(log_color)s%(message)s",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"handlers": {"stderr": {"class": "logging.StreamHandler", "level": "debug", "formatter": "colored"}},
|
"handlers": {
|
||||||
|
"stderr": {
|
||||||
|
"class": "logging.StreamHandler",
|
||||||
|
"level": "debug",
|
||||||
|
"formatter": "colored",
|
||||||
|
}
|
||||||
|
},
|
||||||
"loggers": {
|
"loggers": {
|
||||||
"root": {
|
"root": {
|
||||||
"handlers": [
|
"handlers": [
|
||||||
@ -65,7 +71,9 @@ class LoggingLayer:
|
|||||||
noise for typical operation.
|
noise for typical operation.
|
||||||
"""
|
"""
|
||||||
if config_dict is None:
|
if config_dict is None:
|
||||||
_bootstrap_logger.debug("log - No application logging configuration provided. Using default")
|
_bootstrap_logger.debug(
|
||||||
|
"log - No application logging configuration provided. Using default"
|
||||||
|
)
|
||||||
config_dict = DEFAULT_LOG_SETTINGS
|
config_dict = DEFAULT_LOG_SETTINGS
|
||||||
|
|
||||||
self.transform_config(config_dict)
|
self.transform_config(config_dict)
|
||||||
@ -108,19 +116,26 @@ class LoggingLayer:
|
|||||||
config_dict["loggers"][""] = config_dict["loggers"]["root"]
|
config_dict["loggers"][""] = config_dict["loggers"]["root"]
|
||||||
del config_dict["loggers"]["root"]
|
del config_dict["loggers"]["root"]
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
_bootstrap_logger.warn("was not able to find and patch root logger configuration from arguments")
|
_bootstrap_logger.warn(
|
||||||
|
"was not able to find and patch root logger configuration from arguments"
|
||||||
|
)
|
||||||
|
|
||||||
# Evaluate the full filepath of the file handler
|
# Evaluate the full filepath of the file handler
|
||||||
if "file" not in config_dict["handlers"]:
|
if "file" not in config_dict["handlers"]:
|
||||||
return
|
return
|
||||||
|
|
||||||
if os.path.abspath(config_dict["handlers"]["file"]["filename"]) == config_dict["handlers"]["file"]["filename"]:
|
if (
|
||||||
|
os.path.abspath(config_dict["handlers"]["file"]["filename"])
|
||||||
|
== config_dict["handlers"]["file"]["filename"]
|
||||||
|
):
|
||||||
# Path is already absolute
|
# Path is already absolute
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
dirname = appdirs.user_log_dir(self.appname, self.appauthor)
|
dirname = appdirs.user_log_dir(self.appname, self.appauthor)
|
||||||
_util.ensure_dir_exists(dirname)
|
_util.ensure_dir_exists(dirname)
|
||||||
log_filepath = os.path.join(dirname, config_dict["handlers"]["file"]["filename"])
|
log_filepath = os.path.join(
|
||||||
|
dirname, config_dict["handlers"]["file"]["filename"]
|
||||||
|
)
|
||||||
config_dict["handlers"]["file"]["filename"] = log_filepath
|
config_dict["handlers"]["file"]["filename"] = log_filepath
|
||||||
|
|
||||||
def _add_own_logconfig(self, config_dict):
|
def _add_own_logconfig(self, config_dict):
|
||||||
@ -133,7 +148,10 @@ class LoggingLayer:
|
|||||||
# See _bootstrap.py
|
# See _bootstrap.py
|
||||||
if os.environ.get("APPSKELLINGTON_DEBUG", None):
|
if os.environ.get("APPSKELLINGTON_DEBUG", None):
|
||||||
if _logger_name not in config_dict["loggers"]:
|
if _logger_name not in config_dict["loggers"]:
|
||||||
config_dict["loggers"][_logger_name] = {"level": "debug", "propagate": "false"}
|
config_dict["loggers"][_logger_name] = {
|
||||||
|
"level": "debug",
|
||||||
|
"propagate": "false",
|
||||||
|
}
|
||||||
else:
|
else:
|
||||||
config_dict["loggers"][_logger_name]["level"] = "debug"
|
config_dict["loggers"][_logger_name]["level"] = "debug"
|
||||||
|
|
||||||
|
@ -32,12 +32,18 @@ def sample_invalid_configspec_filepath():
|
|||||||
class TestConfig_e2e:
|
class TestConfig_e2e:
|
||||||
def test_allows_reading_ini_and_no_spec(self, sample_configini_filepath):
|
def test_allows_reading_ini_and_no_spec(self, sample_configini_filepath):
|
||||||
cfg = Config(configini_filepath=sample_configini_filepath)
|
cfg = Config(configini_filepath=sample_configini_filepath)
|
||||||
assert cfg["root_option"] == "root_option_val", "expecting default from config.spec (didnt get)"
|
assert (
|
||||||
assert cfg["app"]["sub_option"] == "sub_option_val", "expecting default for sub option"
|
cfg["root_option"] == "root_option_val"
|
||||||
|
), "expecting default from config.spec (didnt get)"
|
||||||
|
assert (
|
||||||
|
cfg["app"]["sub_option"] == "sub_option_val"
|
||||||
|
), "expecting default for sub option"
|
||||||
|
|
||||||
def test_allows_reading_spec_and_no_ini(self, sample_configspec_filepath):
|
def test_allows_reading_spec_and_no_ini(self, sample_configspec_filepath):
|
||||||
cfg = Config(configspec_filepath=sample_configspec_filepath)
|
cfg = Config(configspec_filepath=sample_configspec_filepath)
|
||||||
assert cfg["root_option"] == "def_string", "expecting default from config.spec (didnt get)"
|
assert (
|
||||||
|
cfg["root_option"] == "def_string"
|
||||||
|
), "expecting default from config.spec (didnt get)"
|
||||||
|
|
||||||
# NOTE(MG) Changed the functionality to not do it this way.
|
# NOTE(MG) Changed the functionality to not do it this way.
|
||||||
# def test_constructor_fails_with_invalid_spec(
|
# def test_constructor_fails_with_invalid_spec(
|
||||||
@ -65,7 +71,9 @@ class TestConfig_e2e:
|
|||||||
assert cfg["root_option"] == "newval"
|
assert cfg["root_option"] == "newval"
|
||||||
|
|
||||||
cfg["app"]["sub_option"] = "another_new_val"
|
cfg["app"]["sub_option"] = "another_new_val"
|
||||||
assert cfg["app"]["sub_option"] == "another_new_val", "expecting default for sub option"
|
assert (
|
||||||
|
cfg["app"]["sub_option"] == "another_new_val"
|
||||||
|
), "expecting default for sub option"
|
||||||
|
|
||||||
def test_can_set_option_without_config(self):
|
def test_can_set_option_without_config(self):
|
||||||
cfg = Config()
|
cfg = Config()
|
||||||
@ -78,5 +86,7 @@ class TestConfig_e2e:
|
|||||||
|
|
||||||
def test_uses_spec_as_defaults(self, sample_configspec_filepath):
|
def test_uses_spec_as_defaults(self, sample_configspec_filepath):
|
||||||
cfg = Config(configspec_filepath=sample_configspec_filepath)
|
cfg = Config(configspec_filepath=sample_configspec_filepath)
|
||||||
assert cfg["root_option"] == "def_string", "expecting default from config.spec (didnt get)"
|
assert (
|
||||||
|
cfg["root_option"] == "def_string"
|
||||||
|
), "expecting default from config.spec (didnt get)"
|
||||||
assert cfg["app"]["sub_option"] == "def_sub", "expecting default for sub option"
|
assert cfg["app"]["sub_option"] == "def_sub", "expecting default for sub option"
|
||||||
|
Loading…
Reference in New Issue
Block a user