config-cli-gui 0.1.10__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.idea/runConfigurations/config_generate.xml +3 -3
- config_cli_gui-0.2.1/.idea/runConfigurations/example_project_cli.xml +24 -0
- config_cli_gui-0.2.1/.idea/runConfigurations/example_project_gui.xml +24 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/HISTORY.md +7 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/PKG-INFO +1 -1
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/config.yaml +2 -2
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/usage/config.md +5 -5
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui/_version.py +3 -3
- config_cli_gui-0.2.1/src/config_cli_gui/cli.py +147 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui/config.py +2 -2
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/PKG-INFO +1 -1
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/SOURCES.txt +3 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/cli/cli_example.py +11 -10
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/config/config_example.py +5 -5
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/core/base.py +7 -1
- config_cli_gui-0.2.1/tests/example_project/example.gpx +6042 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/test_config_manager.py +2 -2
- config_cli_gui-0.1.10/src/config_cli_gui/cli.py +0 -179
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/FUNDING.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/actions/setup-environment/action.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/dependabot.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/init.sh +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/release_message.sh +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/update_funding.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/workflows/main.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/workflows/release.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.github/workflows/update_readme.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.gitignore +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.pre-commit-config.yaml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/.readthedocs.yaml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/LICENSE +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/Makefile +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/README.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/.nav.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/_static/img/favicon.png +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/_static/img/logo.png +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/css/custom.css +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/develop/contributing.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/develop/make_windows.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/develop/naming_convention.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/funding/funding.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/getting-started/install.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/getting-started/virtual-environment.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/index.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/docs/usage/cli.md +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/mkdocs.yml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/pyproject.toml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/scripts/show_filelist.ps1 +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/scripts/show_tree.ps1 +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/scripts/show_tree.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/scripts/update_readme.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/setup.cfg +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui/docs.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui/gui.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/dependency_links.txt +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/entry_points.txt +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/requires.txt +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/src/config_cli_gui.egg-info/top_level.txt +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/template.yml.url +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/__main__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/cli/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/cli/__main__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/config/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/core/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/core/logging.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/gui/__init__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/gui/__main__.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/gui/config.yaml +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/gui/gui_example.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/test_docs.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/test_generic_cli.py +0 -0
- {config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/uv.lock +0 -0
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
9
|
</envs>
|
|
10
10
|
<option name="SDK_HOME" value="" />
|
|
11
|
-
<option name="WORKING_DIRECTORY" value="$
|
|
11
|
+
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
|
|
12
12
|
<option name="IS_MODULE_SDK" value="true" />
|
|
13
13
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
14
14
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
15
15
|
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
|
|
16
|
-
<option name="SCRIPT_NAME" value="
|
|
16
|
+
<option name="SCRIPT_NAME" value="example_project.config.config_example" />
|
|
17
17
|
<option name="PARAMETERS" value="" />
|
|
18
18
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
19
19
|
<option name="EMULATE_TERMINAL" value="false" />
|
|
20
|
-
<option name="MODULE_MODE" value="
|
|
20
|
+
<option name="MODULE_MODE" value="true" />
|
|
21
21
|
<option name="REDIRECT_INPUT" value="false" />
|
|
22
22
|
<option name="INPUT_FILE" value="" />
|
|
23
23
|
<method v="2" />
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="example_project.cli" type="PythonConfigurationType" factoryName="Python">
|
|
3
|
+
<module name="config-cli-gui" />
|
|
4
|
+
<option name="ENV_FILES" value="" />
|
|
5
|
+
<option name="INTERPRETER_OPTIONS" value="" />
|
|
6
|
+
<option name="PARENT_ENVS" value="true" />
|
|
7
|
+
<envs>
|
|
8
|
+
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
|
+
</envs>
|
|
10
|
+
<option name="SDK_HOME" value="" />
|
|
11
|
+
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
|
|
12
|
+
<option name="IS_MODULE_SDK" value="true" />
|
|
13
|
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
14
|
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
15
|
+
<option name="SCRIPT_NAME" value="example_project.cli" />
|
|
16
|
+
<option name="PARAMETERS" value="--elevation --min_dist 77 --output outputfile.gpx tests/example_project/example.gpx" />
|
|
17
|
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
18
|
+
<option name="EMULATE_TERMINAL" value="false" />
|
|
19
|
+
<option name="MODULE_MODE" value="true" />
|
|
20
|
+
<option name="REDIRECT_INPUT" value="false" />
|
|
21
|
+
<option name="INPUT_FILE" value="" />
|
|
22
|
+
<method v="2" />
|
|
23
|
+
</configuration>
|
|
24
|
+
</component>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<component name="ProjectRunConfigurationManager">
|
|
2
|
+
<configuration default="false" name="example_project.gui" type="PythonConfigurationType" factoryName="Python" nameIsGenerated="true">
|
|
3
|
+
<module name="config-cli-gui" />
|
|
4
|
+
<option name="ENV_FILES" value="" />
|
|
5
|
+
<option name="INTERPRETER_OPTIONS" value="" />
|
|
6
|
+
<option name="PARENT_ENVS" value="true" />
|
|
7
|
+
<envs>
|
|
8
|
+
<env name="PYTHONUNBUFFERED" value="1" />
|
|
9
|
+
</envs>
|
|
10
|
+
<option name="SDK_HOME" value="" />
|
|
11
|
+
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$" />
|
|
12
|
+
<option name="IS_MODULE_SDK" value="true" />
|
|
13
|
+
<option name="ADD_CONTENT_ROOTS" value="true" />
|
|
14
|
+
<option name="ADD_SOURCE_ROOTS" value="true" />
|
|
15
|
+
<option name="SCRIPT_NAME" value="example_project.gui" />
|
|
16
|
+
<option name="PARAMETERS" value="" />
|
|
17
|
+
<option name="SHOW_COMMAND_LINE" value="false" />
|
|
18
|
+
<option name="EMULATE_TERMINAL" value="false" />
|
|
19
|
+
<option name="MODULE_MODE" value="true" />
|
|
20
|
+
<option name="REDIRECT_INPUT" value="false" />
|
|
21
|
+
<option name="INPUT_FILE" value="" />
|
|
22
|
+
<method v="2" />
|
|
23
|
+
</configuration>
|
|
24
|
+
</component>
|
|
@@ -4,6 +4,13 @@ Changelog
|
|
|
4
4
|
|
|
5
5
|
(unreleased)
|
|
6
6
|
------------
|
|
7
|
+
- #9 fix posix path issue. [Paul Magister]
|
|
8
|
+
- #9 fix posix path issue. [Paul Magister]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
0.1.10 (2025-11-13)
|
|
12
|
+
-------------------
|
|
13
|
+
- Docs: Update HISTORY.md for release 0.1.10. [Paul Magister]
|
|
7
14
|
- #9 unittests docs.py. [Paul Magister]
|
|
8
15
|
- #9 unittests config.py. [Paul Magister]
|
|
9
16
|
- #9 roll back to .value usage to be type save: documentation. [Paul
|
|
@@ -42,7 +42,7 @@ gui:
|
|
|
42
42
|
misc:
|
|
43
43
|
# Color setting for the application | type=Color, default=#ff0000
|
|
44
44
|
some_color: '#ff0000'
|
|
45
|
-
# Date setting for the application | type=datetime, default=2025-
|
|
46
|
-
some_date: '2025-
|
|
45
|
+
# Date setting for the application | type=datetime, default=2025-12-31 10:30:45
|
|
46
|
+
some_date: '2025-12-31T10:30:45'
|
|
47
47
|
# Path to the file to use | type=PosixPath, default=some_file.txt
|
|
48
48
|
some_file: some_file.txt
|
|
@@ -39,9 +39,9 @@ The parameters in the cli category can be accessed via the command line interfac
|
|
|
39
39
|
|
|
40
40
|
## Category "misc"
|
|
41
41
|
|
|
42
|
-
| Name | Type | Description | Default
|
|
43
|
-
|
|
44
|
-
| some_file | PosixPath | Path to the file to use | PosixPath('some_file.txt')
|
|
45
|
-
| some_color | Color | Color setting for the application | Color(255, 0, 0)
|
|
46
|
-
| some_date | datetime | Date setting for the application | datetime.datetime(2025,
|
|
42
|
+
| Name | Type | Description | Default | Choices |
|
|
43
|
+
|------------|-----------|-----------------------------------|---------------------------------------------|---------|
|
|
44
|
+
| some_file | PosixPath | Path to the file to use | PosixPath('some_file.txt') | - |
|
|
45
|
+
| some_color | Color | Color setting for the application | Color(255, 0, 0) | - |
|
|
46
|
+
| some_date | datetime | Date setting for the application | datetime.datetime(2025, 12, 31, 10, 30, 45) | - |
|
|
47
47
|
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.1
|
|
32
|
-
__version_tuple__ = version_tuple = (0,
|
|
31
|
+
__version__ = version = '0.2.1'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 1)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'ge612edfc1'
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
# config_cli_gui/cli_example.py
|
|
2
|
+
"""Generic CLI generator for configuration framework."""
|
|
3
|
+
|
|
4
|
+
import argparse
|
|
5
|
+
import traceback
|
|
6
|
+
from collections.abc import Callable
|
|
7
|
+
from typing import Any
|
|
8
|
+
|
|
9
|
+
from config_cli_gui.config import ConfigManager
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def str2bool(v: str):
|
|
13
|
+
if isinstance(v, bool):
|
|
14
|
+
return v
|
|
15
|
+
if v.lower() in ("yes", "true", "t", "1"):
|
|
16
|
+
return True
|
|
17
|
+
if v.lower() in ("no", "false", "f", "0"):
|
|
18
|
+
return False
|
|
19
|
+
raise argparse.ArgumentTypeError("Boolean value expected.")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ToggleOrBool(argparse.Action):
|
|
23
|
+
def __call__(self, parser, namespace, values, option_string=None):
|
|
24
|
+
if values is None:
|
|
25
|
+
# toggle mode
|
|
26
|
+
current = getattr(namespace, self.dest, None)
|
|
27
|
+
default = self.default
|
|
28
|
+
setattr(namespace, self.dest, not default if current is None else not current)
|
|
29
|
+
else:
|
|
30
|
+
# explicit boolean mode
|
|
31
|
+
setattr(namespace, self.dest, str2bool(values))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class CliGenerator:
|
|
35
|
+
"""Generates a CLI automatically from a ConfigManager."""
|
|
36
|
+
|
|
37
|
+
def __init__(self, config_manager: ConfigManager, app_name: str = "app"):
|
|
38
|
+
self.config_manager = config_manager
|
|
39
|
+
self.app_name = app_name
|
|
40
|
+
|
|
41
|
+
# ----------------------------------------------------------------------
|
|
42
|
+
# Argument parser builder
|
|
43
|
+
# ----------------------------------------------------------------------
|
|
44
|
+
def create_argument_parser(self, description: str = None) -> argparse.ArgumentParser:
|
|
45
|
+
if description is None:
|
|
46
|
+
description = f"Command line interface for {self.app_name}"
|
|
47
|
+
|
|
48
|
+
parser = argparse.ArgumentParser(description=description)
|
|
49
|
+
|
|
50
|
+
# Config file argument
|
|
51
|
+
parser.add_argument("--config", help="Path to configuration file")
|
|
52
|
+
|
|
53
|
+
# verbosity
|
|
54
|
+
parser.add_argument("-v", "--verbose", action="store_true", help="Verbose logging")
|
|
55
|
+
parser.add_argument("-q", "--quiet", action="store_true", help="Quiet mode")
|
|
56
|
+
|
|
57
|
+
# CLI parameters
|
|
58
|
+
for p in self.config_manager.get_cli_parameters():
|
|
59
|
+
if p.required: # POSITONAL ARGUMENT
|
|
60
|
+
parser.add_argument(p.name, help=p.help)
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
# OPTIONAL FLAG
|
|
64
|
+
kwargs = {
|
|
65
|
+
"help": f"{p.help} (default: {p.value})",
|
|
66
|
+
"default": argparse.SUPPRESS,
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
# Handle different parameter types
|
|
70
|
+
if isinstance(p.value, bool):
|
|
71
|
+
kwargs["nargs"] = "?" # allow optional argument
|
|
72
|
+
kwargs["default"] = p.value # default remains as defined
|
|
73
|
+
kwargs["const"] = None # triggers toggle mode
|
|
74
|
+
kwargs["action"] = ToggleOrBool
|
|
75
|
+
else:
|
|
76
|
+
kwargs["type"] = type(p.value)
|
|
77
|
+
if p.choices:
|
|
78
|
+
kwargs["choices"] = p.choices
|
|
79
|
+
|
|
80
|
+
parser.add_argument(p.cli_arg, **kwargs)
|
|
81
|
+
|
|
82
|
+
return parser
|
|
83
|
+
|
|
84
|
+
# ----------------------------------------------------------------------
|
|
85
|
+
# convert args → config overrides
|
|
86
|
+
# ----------------------------------------------------------------------
|
|
87
|
+
def create_config_overrides(self, args: argparse.Namespace) -> dict[str, Any]:
|
|
88
|
+
overrides = {}
|
|
89
|
+
|
|
90
|
+
for p in self.config_manager.get_cli_parameters():
|
|
91
|
+
if hasattr(args, p.name):
|
|
92
|
+
overrides[f"{p.category}__{p.name}"] = getattr(args, p.name)
|
|
93
|
+
|
|
94
|
+
if getattr(args, "verbose", False):
|
|
95
|
+
overrides["app__log_level"] = "DEBUG"
|
|
96
|
+
elif getattr(args, "quiet", False):
|
|
97
|
+
overrides["app__log_level"] = "WARNING"
|
|
98
|
+
|
|
99
|
+
return overrides
|
|
100
|
+
|
|
101
|
+
# ----------------------------------------------------------------------
|
|
102
|
+
# Main CLI runner
|
|
103
|
+
# ----------------------------------------------------------------------
|
|
104
|
+
def run_cli(
|
|
105
|
+
self,
|
|
106
|
+
main_function: Callable[[ConfigManager], int],
|
|
107
|
+
description: str = None,
|
|
108
|
+
validator: Callable[[ConfigManager], bool] = None,
|
|
109
|
+
) -> int:
|
|
110
|
+
parser = self.create_argument_parser(description)
|
|
111
|
+
args = parser.parse_args()
|
|
112
|
+
|
|
113
|
+
# Load config_file only ONCE
|
|
114
|
+
config = ConfigManager(
|
|
115
|
+
categories=tuple(self.config_manager._categories.values()),
|
|
116
|
+
config_file=getattr(args, "config", None),
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
# Apply CLI overrides
|
|
120
|
+
overrides = self.create_config_overrides(args)
|
|
121
|
+
config.apply_overrides(overrides)
|
|
122
|
+
|
|
123
|
+
# Try to get logger if logging is configured
|
|
124
|
+
try:
|
|
125
|
+
from .logging import get_logger
|
|
126
|
+
|
|
127
|
+
logger = get_logger(f"{self.app_name}.cli")
|
|
128
|
+
logger.info(f"Starting {self.app_name} CLI")
|
|
129
|
+
logger.debug(f"Command line arguments: {vars(args)}")
|
|
130
|
+
except ImportError:
|
|
131
|
+
pass
|
|
132
|
+
|
|
133
|
+
# Optional validation
|
|
134
|
+
if validator and not validator(config):
|
|
135
|
+
print("Configuration validation failed.")
|
|
136
|
+
return 1
|
|
137
|
+
|
|
138
|
+
# Execute main
|
|
139
|
+
try:
|
|
140
|
+
return main_function(config)
|
|
141
|
+
except KeyboardInterrupt:
|
|
142
|
+
print("Interrupted.")
|
|
143
|
+
return 130
|
|
144
|
+
except Exception as e:
|
|
145
|
+
print(f"Unexpected error: {e}")
|
|
146
|
+
traceback.print_exc()
|
|
147
|
+
return 1
|
|
@@ -96,7 +96,7 @@ class ConfigManager:
|
|
|
96
96
|
|
|
97
97
|
def __init__(
|
|
98
98
|
self,
|
|
99
|
-
categories: tuple[ConfigCategory, ...],
|
|
99
|
+
categories: tuple[ConfigCategory, ...] = None,
|
|
100
100
|
config_file: str | None = None,
|
|
101
101
|
**overrides: Any,
|
|
102
102
|
):
|
|
@@ -196,7 +196,7 @@ class ConfigManager:
|
|
|
196
196
|
if isinstance(val, Color):
|
|
197
197
|
val = val.to_hex()
|
|
198
198
|
elif isinstance(val, Path):
|
|
199
|
-
val = str(val)
|
|
199
|
+
val = str(val.as_posix())
|
|
200
200
|
elif isinstance(val, datetime):
|
|
201
201
|
val = val.isoformat()
|
|
202
202
|
result[category_name][param.name] = val
|
|
@@ -23,6 +23,8 @@ uv.lock
|
|
|
23
23
|
.github/workflows/release.yml
|
|
24
24
|
.github/workflows/update_readme.yml
|
|
25
25
|
.idea/runConfigurations/config_generate.xml
|
|
26
|
+
.idea/runConfigurations/example_project_cli.xml
|
|
27
|
+
.idea/runConfigurations/example_project_gui.xml
|
|
26
28
|
docs/.nav.yml
|
|
27
29
|
docs/index.md
|
|
28
30
|
docs/_static/img/favicon.png
|
|
@@ -59,6 +61,7 @@ tests/test_docs.py
|
|
|
59
61
|
tests/test_generic_cli.py
|
|
60
62
|
tests/example_project/__init__.py
|
|
61
63
|
tests/example_project/__main__.py
|
|
64
|
+
tests/example_project/example.gpx
|
|
62
65
|
tests/example_project/cli/__init__.py
|
|
63
66
|
tests/example_project/cli/__main__.py
|
|
64
67
|
tests/example_project/cli/cli_example.py
|
|
@@ -4,13 +4,12 @@ This file uses the CliGenerator from the generic config framework.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
from config_cli_gui.cli import CliGenerator
|
|
7
|
-
from config_cli_gui.config import ConfigManager
|
|
8
7
|
from tests.example_project.config.config_example import ProjectConfigManager
|
|
9
8
|
from tests.example_project.core.base import BaseGPXProcessor
|
|
10
9
|
from tests.example_project.core.logging import initialize_logging
|
|
11
10
|
|
|
12
11
|
|
|
13
|
-
def run_main_processing(_config:
|
|
12
|
+
def run_main_processing(_config: ProjectConfigManager) -> int:
|
|
14
13
|
"""Main processing function that gets called by the CLI generator.
|
|
15
14
|
|
|
16
15
|
Args:
|
|
@@ -32,11 +31,12 @@ def run_main_processing(_config: ConfigManager) -> int:
|
|
|
32
31
|
|
|
33
32
|
# Create and run BaseGPXProcessor
|
|
34
33
|
processor = BaseGPXProcessor(
|
|
35
|
-
_config.
|
|
36
|
-
_config.
|
|
37
|
-
_config.
|
|
38
|
-
_config.
|
|
39
|
-
_config.
|
|
34
|
+
_config.cli.input.value,
|
|
35
|
+
_config.cli.output.value,
|
|
36
|
+
_config.cli.min_dist.value,
|
|
37
|
+
_config.app.date_format.value,
|
|
38
|
+
_config.cli.elevation.value,
|
|
39
|
+
_config.cli.extract_waypoints.value,
|
|
40
40
|
logger=logger,
|
|
41
41
|
)
|
|
42
42
|
|
|
@@ -58,10 +58,11 @@ def main():
|
|
|
58
58
|
# Create the base configuration manager
|
|
59
59
|
config_manager = ProjectConfigManager()
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
|
|
61
|
+
cli_generator = CliGenerator(
|
|
62
|
+
config_manager=config_manager,
|
|
63
|
+
app_name="config_cli_gui",
|
|
64
|
+
)
|
|
63
65
|
|
|
64
|
-
# Run the CLI with our main processing function
|
|
65
66
|
return cli_generator.run_cli(
|
|
66
67
|
main_function=run_main_processing,
|
|
67
68
|
description="Example CLI for config-cli-gui using the generic config framework.",
|
{config_cli_gui-0.1.10 → config_cli_gui-0.2.1}/tests/example_project/config/config_example.py
RENAMED
|
@@ -56,7 +56,7 @@ class CliConfig(ConfigCategory):
|
|
|
56
56
|
|
|
57
57
|
elevation: ConfigParameter = ConfigParameter(
|
|
58
58
|
name="elevation",
|
|
59
|
-
value=
|
|
59
|
+
value=False,
|
|
60
60
|
help="Include elevation data in waypoints",
|
|
61
61
|
is_cli=True,
|
|
62
62
|
)
|
|
@@ -181,7 +181,7 @@ class MiscConfig(ConfigCategory):
|
|
|
181
181
|
|
|
182
182
|
some_date: ConfigParameter = ConfigParameter(
|
|
183
183
|
name="some_date",
|
|
184
|
-
value=datetime.
|
|
184
|
+
value=datetime.fromisoformat("2025-12-31 10:30:45"),
|
|
185
185
|
help="Date setting for the application",
|
|
186
186
|
)
|
|
187
187
|
|
|
@@ -202,9 +202,9 @@ class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
|
|
|
202
202
|
|
|
203
203
|
def main():
|
|
204
204
|
"""Main function to generate config file and documentation."""
|
|
205
|
-
default_config: str = "
|
|
206
|
-
default_cli_doc: str = "
|
|
207
|
-
default_config_doc: str = "
|
|
205
|
+
default_config: str = "config.yaml"
|
|
206
|
+
default_cli_doc: str = "docs/usage/cli.md"
|
|
207
|
+
default_config_doc: str = "docs/usage/config.md"
|
|
208
208
|
_config = ProjectConfigManager()
|
|
209
209
|
doc_gen = DocumentationGenerator(_config)
|
|
210
210
|
doc_gen.generate_default_config_file(output_file=default_config)
|
|
@@ -11,6 +11,7 @@ class BaseGPXProcessor:
|
|
|
11
11
|
min_dist=10,
|
|
12
12
|
date_format="%Y-%m-%d",
|
|
13
13
|
elevation=True,
|
|
14
|
+
extract_waypoints=True,
|
|
14
15
|
logger=None,
|
|
15
16
|
):
|
|
16
17
|
# ensure that input is converted into a list[Path]
|
|
@@ -29,7 +30,12 @@ class BaseGPXProcessor:
|
|
|
29
30
|
self.include_elevation = elevation
|
|
30
31
|
self.logger = logger
|
|
31
32
|
|
|
32
|
-
self.logger.info(
|
|
33
|
+
self.logger.info("example module successfully initialized with:")
|
|
34
|
+
self.logger.info(f"output: {output}")
|
|
35
|
+
self.logger.info(f"min_dist: {min_dist}")
|
|
36
|
+
self.logger.info(f"date_format: {date_format}")
|
|
37
|
+
self.logger.info(f"elevation: {elevation}")
|
|
38
|
+
self.logger.info(f"extract_waypoints: {extract_waypoints}")
|
|
33
39
|
|
|
34
40
|
def compress_files(self) -> list[str]:
|
|
35
41
|
"""Shrink the size of all given gpx/kml files in se
|