diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..6993c35 --- /dev/null +++ b/config.toml @@ -0,0 +1 @@ +[general_config] diff --git a/pyproject.toml b/pyproject.toml index 9129c3f..92506dc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ dependencies = [ [project.scripts] hello = "hello_world:main" +taco = "trygo_py_cliclient.cli:main" [build-system] requires = ["hatchling"] diff --git a/src/trygo_py_cliclient/cli/__init__.py b/src/trygo_py_cliclient/cli/__init__.py new file mode 100644 index 0000000..796f4c3 --- /dev/null +++ b/src/trygo_py_cliclient/cli/__init__.py @@ -0,0 +1,30 @@ +import argparse +import pathlib +import logging +import trygo_py_cliclient.config +import trygo_py_cliclient.cli.common + +_logger = logging.getLogger(__name__) + + +def parse_args(): + parser = argparse.ArgumentParser( + "trygo-client", formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + + parser.add_argument( + "--config-file", type=str, help="config file location", default="config.toml" + ) + args = parser.parse_args() + return args + + +def main(): + args = parse_args() + + config = trygo_py_cliclient.config.read_config(pathlib.Path(args.config_file)) + + trygo_py_cliclient.cli.common.set_up_logging( + config, + ) + _logger.info(f"Loaded config {config=}") diff --git a/src/trygo_py_cliclient/cli/common/__init__.py b/src/trygo_py_cliclient/cli/common/__init__.py new file mode 100644 index 0000000..b7de9e9 --- /dev/null +++ b/src/trygo_py_cliclient/cli/common/__init__.py @@ -0,0 +1,29 @@ +import trygo_py_cliclient.config +import typing +import logging +import pathlib + + +def set_up_logging( + config: trygo_py_cliclient.config.Config, + create_logfile_parents: bool = True, +): + # for convenience + conf = config.general_config + handlers: typing.List[logging.Handler] = [] + + if conf.log_stream: + handlers.append(logging.StreamHandler()) + + if conf.log_file is not None: + if create_logfile_parents: + # create any parent directories for the log file if needed. + pathlib.Path(conf.log_file).parent.mkdir(parents=True, exist_ok=True) + handlers.append(logging.FileHandler(conf.log_file)) + + logging.basicConfig( + level=logging.DEBUG, + format=conf.log_pattern, + handlers=handlers, + ) + logging.captureWarnings(True) diff --git a/src/trygo_py_cliclient/cli/main.py b/src/trygo_py_cliclient/cli/main.py new file mode 100644 index 0000000..e69de29 diff --git a/src/trygo_py_cliclient/config/__init__.py b/src/trygo_py_cliclient/config/__init__.py index aea2873..38be7d3 100644 --- a/src/trygo_py_cliclient/config/__init__.py +++ b/src/trygo_py_cliclient/config/__init__.py @@ -1,5 +1,10 @@ from trygo_py_cliclient.config.config import ( GeneralConfig, + Config, ) -__all__ = ["GeneralConfig"] +from trygo_py_cliclient.config.config_reader import ( + read_config, +) + +__all__ = ["GeneralConfig", "Config", "read_config"] diff --git a/src/trygo_py_cliclient/config/config.py b/src/trygo_py_cliclient/config/config.py index 5d592fb..da7deda 100644 --- a/src/trygo_py_cliclient/config/config.py +++ b/src/trygo_py_cliclient/config/config.py @@ -1,6 +1,14 @@ from dataclasses import dataclass +from typing import Optional @dataclass(frozen=True) class GeneralConfig: log_pattern: str = "%(asctime)s | %(process)d | %(levelname)-7s | %(name)s:%(lineno)d | %(message)s" + log_file: Optional[str] = None + log_stream: bool = True + + +@dataclass(frozen=True) +class Config: + general_config: GeneralConfig = GeneralConfig() diff --git a/src/trygo_py_cliclient/config/config_reader.py b/src/trygo_py_cliclient/config/config_reader.py index 2d4a655..ee2d853 100644 --- a/src/trygo_py_cliclient/config/config_reader.py +++ b/src/trygo_py_cliclient/config/config_reader.py @@ -1,7 +1,9 @@ import logging import dacite +import pathlib +import tomli -from trygo_py_cliclient.config import GeneralConfig +from trygo_py_cliclient.config import GeneralConfig, Config _logger = logging.getLogger(__name__) @@ -10,7 +12,7 @@ _common_dacite_config = dacite.Config( ) -def read_general_config_dict(general_config_dict: dict) -> GeneralConfig: +def read_general_config_from_dict(general_config_dict: dict) -> GeneralConfig: """ Converts a dictionary to a GeneralConfig object @@ -23,3 +25,58 @@ def read_general_config_dict(general_config_dict: dict) -> GeneralConfig: config=_common_dacite_config, ) return general_config + + +def read_config_dict(file_path: pathlib.Path) -> dict: + """ + Read a dict from file + """ + _logger.debug(f"Reading config from {file_path=}") + with open(file_path, "rb") as toml_file: + config_dict = tomli.load(toml_file) + return config_dict + + +def serialize_config(config_dict: dict) -> Config: + """ + Converts a dictionary to a Config object + + Makes assumptions about structure of the config_dict, so validation should happen here too if needed. + + :param config_dict: dictionary containing config values + :return: Config object + """ + # generation_config = GenerationConfig(**config_dict["generation_config"]) + + # general_config_dict = config_dict["general_config"] + # general_config = GeneralConfig( + # root_directory=general_config_dict["root_directory"], + # out_dir_name=general_config_dict["out_dir_name"], + # dots_json_name=general_config_dict["dots_json_name"], + # mega_merged_name=general_config_dict["mega_merged_name"], + # mega_merged_inferenced_name=general_config_dict["mega_merged_inferenced_name"], + # skip_to_stage=general_config_dict["skip_to_stage"], + # measurement_type=MeasurementTypeEnum(general_config_dict["measurement_type"]), + # indexes_json_name=general_config_dict["indexes_json_name"], + # log_pattern=general_config_dict["log_pattern"], + # ) + + # deepdog_config = DeepdogConfig(**config_dict["deepdog_config"]) + # config = Config( + # generation_config=generation_config, + # general_config=general_config, + # deepdog_config=deepdog_config, + # ) + config = dacite.from_dict( + data_class=Config, + data=config_dict, + config=_common_dacite_config, + ) + _logger.warning(config) + + return config + + +def read_config(file_path: pathlib.Path) -> Config: + config_dict = read_config_dict(file_path) + return serialize_config(config_dict)