config-cli-gui 0.1.2__tar.gz → 0.1.4__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.
Files changed (81) hide show
  1. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.idea/runConfigurations/config_generate.xml +1 -1
  2. config_cli_gui-0.1.4/HISTORY.md +50 -0
  3. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/PKG-INFO +145 -134
  4. config_cli_gui-0.1.4/README.md +264 -0
  5. config_cli_gui-0.1.4/config.yaml +51 -0
  6. config_cli_gui-0.1.4/docs/index.md +262 -0
  7. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/usage/config.md +13 -13
  8. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui/_version.py +2 -2
  9. config_cli_gui-0.1.2/src/config_cli_gui/cli_generator.py → config_cli_gui-0.1.4/src/config_cli_gui/cli.py +2 -2
  10. config_cli_gui-0.1.2/src/config_cli_gui/config_framework.py → config_cli_gui-0.1.4/src/config_cli_gui/config.py +8 -9
  11. config_cli_gui-0.1.2/src/config_cli_gui/docs_generator.py → config_cli_gui-0.1.4/src/config_cli_gui/docs.py +1 -1
  12. config_cli_gui-0.1.2/src/config_cli_gui/gui_generator.py → config_cli_gui-0.1.4/src/config_cli_gui/gui.py +2 -2
  13. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/PKG-INFO +145 -134
  14. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/SOURCES.txt +7 -11
  15. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/top_level.txt +0 -1
  16. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/__main__.py +1 -1
  17. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/cli/__main__.py +1 -1
  18. config_cli_gui-0.1.4/tests/example_project/cli/cli_example.py +74 -0
  19. config_cli_gui-0.1.2/tests/example_project/config/config.py → config_cli_gui-0.1.4/tests/example_project/config/config_example.py +14 -14
  20. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/core/base.py +6 -10
  21. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/core/logging.py +4 -4
  22. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/gui/__main__.py +1 -1
  23. config_cli_gui-0.1.2/tests/example_project/gui/gui.py → config_cli_gui-0.1.4/tests/example_project/gui/gui_example.py +11 -13
  24. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/test_generic_cli.py +7 -7
  25. config_cli_gui-0.1.2/HISTORY.md +0 -25
  26. config_cli_gui-0.1.2/README.md +0 -253
  27. config_cli_gui-0.1.2/config.yaml +0 -51
  28. config_cli_gui-0.1.2/docs/index.md +0 -251
  29. config_cli_gui-0.1.2/examples/kuhkopfsteig.gpx +0 -8189
  30. config_cli_gui-0.1.2/examples/rother_lilienstein.gpx +0 -571
  31. config_cli_gui-0.1.2/examples/teneriffa.gpx +0 -6042
  32. config_cli_gui-0.1.2/src/main.py +0 -153
  33. config_cli_gui-0.1.2/tests/example_project/cli/cli.py +0 -132
  34. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/FUNDING.yml +0 -0
  35. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  36. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  37. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  38. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/actions/setup-environment/action.yml +0 -0
  39. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/dependabot.yml +0 -0
  40. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/init.sh +0 -0
  41. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/release_message.sh +0 -0
  42. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/update_funding.py +0 -0
  43. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/workflows/main.yml +0 -0
  44. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/workflows/release.yml +0 -0
  45. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.github/workflows/update_readme.yml +0 -0
  46. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.gitignore +0 -0
  47. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.pre-commit-config.yaml +0 -0
  48. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/.readthedocs.yaml +0 -0
  49. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/LICENSE +0 -0
  50. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/Makefile +0 -0
  51. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/.nav.yml +0 -0
  52. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/_static/img/favicon.png +0 -0
  53. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/_static/img/logo.png +0 -0
  54. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/css/custom.css +0 -0
  55. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/develop/contributing.md +0 -0
  56. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/develop/make_windows.md +0 -0
  57. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/develop/naming_convention.md +0 -0
  58. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/funding/funding.md +0 -0
  59. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/getting-started/install.md +0 -0
  60. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/getting-started/virtual-environment.md +0 -0
  61. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/docs/usage/cli.md +0 -0
  62. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/mkdocs.yml +0 -0
  63. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/pyproject.toml +0 -0
  64. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/scripts/show_filelist.ps1 +0 -0
  65. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/scripts/show_tree.ps1 +0 -0
  66. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/scripts/show_tree.py +0 -0
  67. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/scripts/update_readme.py +0 -0
  68. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/setup.cfg +0 -0
  69. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/__init__.py +0 -0
  70. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui/__init__.py +0 -0
  71. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/dependency_links.txt +0 -0
  72. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/entry_points.txt +0 -0
  73. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/src/config_cli_gui.egg-info/requires.txt +0 -0
  74. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/template.yml.url +0 -0
  75. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/__init__.py +0 -0
  76. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/__init__.py +0 -0
  77. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/cli/__init__.py +0 -0
  78. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/config/__init__.py +0 -0
  79. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/core/__init__.py +0 -0
  80. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/tests/example_project/gui/__init__.py +0 -0
  81. {config_cli_gui-0.1.2 → config_cli_gui-0.1.4}/uv.lock +0 -0
@@ -13,7 +13,7 @@
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="$PROJECT_DIR$/tests/example_project/config/config.py" />
16
+ <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tests/example_project/config/config_example.py" />
17
17
  <option name="PARAMETERS" value="" />
18
18
  <option name="SHOW_COMMAND_LINE" value="false" />
19
19
  <option name="EMULATE_TERMINAL" value="false" />
@@ -0,0 +1,50 @@
1
+ Changelog
2
+ =========
3
+
4
+
5
+ (unreleased)
6
+ ------------
7
+ - Update README.md from docs/index.md. [github-actions]
8
+ - Feat #5: extensive renaming and adjustments. [Paul Magister]
9
+ - Feat #5: extensive renaming. [Paul Magister]
10
+ - Feat #5: extensive renaming. [Paul Magister]
11
+
12
+
13
+ 0.1.2 (2025-06-23)
14
+ ------------------
15
+ - Feat #5: improve dialog. [Paul Magister]
16
+ - Feat #5: Bugfig: use specific dialog for path parameters. [Paul
17
+ Magister]
18
+ - Fix #4: fix test. [Paul Magister]
19
+ - Fix #4: write yaml file with nicely with comments. [Paul Magister]
20
+ - Fix #4: add comments to the yaml. [Paul Magister]
21
+ - Fix #4: make new special datatypes work (Color, Path): correct
22
+ load/save lifecycle. [Paul Magister]
23
+ - Feat #3: some advanced parameter types as example. [Paul Magister]
24
+ - Feat #3: delete build workflow since it is not necessary for the lib.
25
+ [Paul Magister]
26
+ - Feat #3: add verbose and quiet doc to auto generated config. [Paul
27
+ Magister]
28
+
29
+
30
+ 0.1.1 (2025-06-22)
31
+ ------------------
32
+ - Feat #3: avoid type_ [Paul Magister]
33
+ - Feat #3: Improved paramter types: [Paul Magister]
34
+ - Feat #3: Improved paramter types: * move example project to tests *
35
+ remove type_ * add improved widgets to gui_generator.py * separate
36
+ module for docs_generator.py. [Paul Magister]
37
+
38
+
39
+ 0.1.0 (2025-06-22)
40
+ ------------------
41
+ - Remove unnecessary example files and deps. [Paul Magister]
42
+ - Update README.md from docs/index.md. [github-actions]
43
+ - Fix doc: formatting. [Paul Magister]
44
+
45
+
46
+ 0.0.2 (2025-06-22)
47
+ ------------------
48
+ - Remove _version.py. [Paul Magister]
49
+
50
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: config-cli-gui
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Feature-rich Python project template for config-cli-gui.
5
5
  Author: pamagister
6
6
  Requires-Python: <3.12,>=3.10
@@ -78,79 +78,74 @@ pip install config-cli-gui
78
78
  Start by defining your application's configuration parameters in a central `config.py` file within your project. You will inherit from `config-cli-gui`'s `GenericConfigManager` and `BaseConfigCategory`.
79
79
 
80
80
  ```python
81
- # my_project/config.py
82
- from config_cli_gui.config import ConfigParameter, GenericConfigManager, BaseConfigCategory
83
- from pydantic import Field # Make sure pydantic is installed
84
-
85
- class MyCliConfig(BaseConfigCategory):
86
- """CLI-specific parameters for MyProject."""
87
- input_path: ConfigParameter = ConfigParameter(
88
- name="input_path",
81
+ # my_project/config_example.py
82
+
83
+ from config_cli_gui.config import (
84
+ ConfigCategory,
85
+ ConfigManager,
86
+ ConfigParameter,
87
+ )
88
+
89
+
90
+ class CliConfig(ConfigCategory):
91
+ """CLI-specific configuration parameters."""
92
+
93
+ def get_category_name(self) -> str:
94
+ return "cli"
95
+
96
+ # Positional argument
97
+ input: ConfigParameter = ConfigParameter(
98
+ name="input",
89
99
  default="",
90
- type_=str,
91
- help="Path to the input file or directory",
100
+ help="Path to input (file or folder)",
92
101
  required=True,
93
- cli_arg=None # Positional argument
102
+ is_cli=True,
94
103
  )
95
- output_dir: ConfigParameter = ConfigParameter(
96
- name="output_dir",
97
- default="./output",
98
- type_=str,
99
- help="Directory for output files",
100
- cli_arg="--output"
104
+
105
+ min_dist: ConfigParameter = ConfigParameter(
106
+ name="min_dist",
107
+ default=20,
108
+ help="Maximum distance between two waypoints",
109
+ is_cli=True,
101
110
  )
102
- dry_run: ConfigParameter = ConfigParameter(
103
- name="dry_run",
104
- default=False,
105
- type_=bool,
106
- help="Perform a dry run without making actual changes",
107
- cli_arg="--dry-run"
111
+
112
+ extract_waypoints: ConfigParameter = ConfigParameter(
113
+ name="extract_waypoints",
114
+ default=True,
115
+ help="Extract starting points of each track as waypoint",
116
+ is_cli=True,
108
117
  )
109
118
 
110
- class MyAppConfig(BaseConfigCategory):
111
- """Application-wide settings."""
119
+
120
+ class AppConfig(ConfigCategory):
121
+ """Application-specific configuration parameters."""
122
+
123
+ def get_category_name(self) -> str:
124
+ return "app"
125
+
112
126
  log_level: ConfigParameter = ConfigParameter(
113
127
  name="log_level",
114
128
  default="INFO",
115
- type_=str,
116
- choices=["DEBUG", "INFO", "WARNING", "ERROR"],
117
- help="Logging verbosity level"
118
- )
119
- max_threads: ConfigParameter = ConfigParameter(
120
- name="max_threads",
121
- default=4,
122
- type_=int,
123
- help="Maximum number of processing threads"
129
+ choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
130
+ help="Logging level for the application",
124
131
  )
125
132
 
126
- class MyGuiConfig(BaseConfigCategory):
127
- """GUI-specific settings."""
128
- theme: ConfigParameter = ConfigParameter(
129
- name="theme",
130
- default="dark",
131
- type_=str,
132
- choices=["light", "dark", "system"],
133
- help="GUI theme"
134
- )
135
- window_size: ConfigParameter = ConfigParameter(
136
- name="window_size",
137
- default="800x600",
138
- type_=str,
139
- help="Initial GUI window size"
133
+ log_file_max_size: ConfigParameter = ConfigParameter(
134
+ name="log_file_max_size",
135
+ default=10,
136
+ help="Maximum log file size in MB before rotation",
140
137
  )
141
138
 
142
- class ProjectConfigManager(GenericConfigManager):
143
- """Main configuration manager for MyProject."""
144
- cli: MyCliConfig = Field(default_factory=MyCliConfig)
145
- app: MyAppConfig = Field(default_factory=MyAppConfig)
146
- gui: MyGuiConfig = Field(default_factory=MyGuiConfig)
139
+
140
+ class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
141
+ """Main configuration manager that handles all parameter categories."""
142
+
143
+ categories = (CliConfig(), AppConfig())
147
144
 
148
145
  def __init__(self, config_file: str | None = None, **kwargs):
149
- # Dynamically register categories for the generic manager
150
- self.__class__.add_config_category("cli", MyCliConfig)
151
- self.__class__.add_config_category("app", MyAppConfig)
152
- self.__class__.add_config_category("gui", MyGuiConfig)
153
- super().__init__(config_file, **kwargs)
146
+ """Initialize the configuration manager with all parameter categories."""
147
+ super().__init__(self.categories, config_file, **kwargs)
148
+
154
149
 
155
150
  ```
156
151
 
@@ -159,60 +154,76 @@ class ProjectConfigManager(GenericConfigManager):
159
154
  Use the generic CLI functions to parse command-line arguments based on your defined `CliConfig`.
160
155
 
161
156
  ```python
162
- # my_project/cli.py
163
- import argparse
164
- from my_project.config import ProjectConfigManager
165
- from config_cli_gui.cli import create_argument_parser, create_config_overrides_from_args
166
-
167
- def parse_my_args():
168
- # Define any project-specific hardcoded CLI args (e.g., --version)
169
- extra_cli_args = {
170
- "--version": {"action": "version", "version": "MyProject 1.0.0", "help": "Show program's version number and exit."}
171
- }
172
-
173
- parser = create_argument_parser(
174
- config_manager_class=ProjectConfigManager,
175
- description="MyProject CLI application",
176
- epilog="""
177
- Examples:
178
- python -m my_project.cli my_input.txt --output ./results
179
- python -m my_project.cli --config custom.yaml another_input.csv
180
- """,
181
- cli_category_name="cli", # The name of your CLI config category
182
- extra_arguments=extra_cli_args
183
- )
184
- return parser.parse_args()
185
-
186
- def main_cli():
187
- args = parse_my_args()
188
-
189
- # Map generic flags like verbose/quiet to specific log levels if desired
190
- log_level_map = {
191
- "verbose": "DEBUG", # Assuming you added a --verbose flag in extra_cli_args
192
- "quiet": "WARNING" # Assuming you added a --quiet flag
193
- }
194
-
195
- cli_overrides = create_config_overrides_from_args(
196
- args,
197
- config_manager_class=ProjectConfigManager,
198
- cli_category_name="cli",
199
- log_level_map=log_level_map
157
+ # my_project/cli_example.py
158
+ from config_cli_gui.cli import CliGenerator
159
+ from config_cli_gui.config import ConfigManager
160
+ from tests.example_project.config.config_example import ProjectConfigManager
161
+ from tests.example_project.core.base import BaseGPXProcessor
162
+ from tests.example_project.core.logging import initialize_logging
163
+
164
+
165
+ def run_main_processing(_config: ConfigManager) -> int:
166
+ """Main processing function that gets called by the CLI generator.
167
+
168
+ Args:
169
+ _config: Configuration manager with all settings
170
+
171
+ Returns:
172
+ Exit code (0 for success, non-zero for error)
173
+ """
174
+ # Initialize logging system
175
+ logger_manager = initialize_logging(_config)
176
+ logger = logger_manager.get_logger("config_cli_gui.cli")
177
+
178
+ try:
179
+ # Log startup information
180
+ logger.info("Starting config_cli_gui CLI")
181
+ logger_manager.log_config_summary()
182
+
183
+ logger.info(f"Processing input")
184
+
185
+ # Create and run BaseGPXProcessor
186
+ processor = BaseGPXProcessor(
187
+ _config.get_category("cli").input.default,
188
+ _config.get_category("cli").output.default,
189
+ _config.get_category("cli").min_dist.default,
190
+ _config.get_category("app").date_format.default,
191
+ _config.get_category("cli").elevation.default,
192
+ logger=logger,
193
+ )
194
+
195
+ logger.info("Starting conversion process")
196
+
197
+ # Run the processing (adjust method name based on your actual implementation)
198
+ result_files = processor.compress_files()
199
+ logger.info(f"Successfully processed {result_files}")
200
+ return 0
201
+
202
+ except Exception as e:
203
+ logger.error(f"Processing failed: {e}")
204
+ logger.debug("Full traceback:", exc_info=True)
205
+ return 1
206
+
207
+
208
+ def main():
209
+ """Main entry point for the CLI application."""
210
+ # Create the base configuration manager
211
+ config_manager = ProjectConfigManager()
212
+
213
+ # Create CLI generator
214
+ cli_generator = CliGenerator(config_manager=config_manager, app_name="config_cli_gui")
215
+
216
+ # Run the CLI with our main processing function
217
+ return cli_generator.run_cli(
218
+ main_function=run_main_processing,
219
+ description="Example CLI for config-cli-gui using the generic config framework.",
200
220
  )
201
221
 
202
- # Initialize your project's configuration
203
- config = ProjectConfigManager(
204
- config_file=args.config if hasattr(args, "config") and args.config else None,
205
- **cli_overrides
206
- )
207
-
208
- print(f"Input Path: {config.cli.input_path.default}")
209
- print(f"Output Directory: {config.cli.output_dir.default}")
210
- print(f"Dry Run: {config.cli.dry_run.default}")
211
- print(f"Log Level: {config.app.log_level.default}")
212
- # ... your application logic using 'config'
213
222
 
214
223
  if __name__ == "__main__":
215
- main_cli()
224
+ import sys
225
+
226
+ sys.exit(main())
216
227
  ```
217
228
 
218
229
  ### 3\. Integrate GUI Settings Dialog
@@ -220,27 +231,29 @@ if __name__ == "__main__":
220
231
  The `SettingsDialog` from `config-cli-gui` (or your project's adapted version) can be used to easily create a settings window.
221
232
 
222
233
  ```python
223
- # my_project/gui.py (Simplified example)
234
+ # my_project/gui_example.py (Simplified example)
224
235
  import tkinter as tk
225
- from my_project.config import ProjectConfigManager
226
- from config_cli_gui.gui_settings import SettingsDialog # Assuming gui_settings is part of the generic lib or adapted
236
+ from tests.example_project.config.config_example import ProjectConfigManager
237
+ from config_cli_gui.gui import GenericSettingsDialog # Assuming gui_settings is part of the generic lib or adapted
238
+
227
239
 
228
240
  def open_settings_window(parent_root, config_manager: ProjectConfigManager):
229
- dialog = SettingsDialog(parent_root, config_manager)
241
+ dialog = GenericSettingsDialog(parent_root, config_manager)
230
242
  parent_root.wait_window(dialog.dialog)
231
243
  # After dialog closes, config_manager will have updated values if 'OK' was clicked
232
244
  print("Settings updated or cancelled.")
233
- print(f"New GUI Theme: {config_manager.gui.theme.default}")
245
+ print(f"New GUI Theme: {config_manager.get_category('gui').theme.default}")
246
+
234
247
 
235
248
  if __name__ == "__main__":
236
249
  root = tk.Tk()
237
- root.withdraw() # Hide main window for this example
238
-
250
+ root.withdraw() # Hide main window for this example
251
+
239
252
  # Initialize your project's config manager
240
- project_config = ProjectConfigManager()
241
-
253
+ project_config = ProjectConfigManager()
254
+
242
255
  open_settings_window(root, project_config)
243
-
256
+
244
257
  root.destroy()
245
258
  ```
246
259
 
@@ -250,29 +263,27 @@ Use the static methods on your `ProjectConfigManager` to generate `config.yaml`,
250
263
 
251
264
  ```python
252
265
  # scripts/generate_docs.py (or similar script in your project)
253
- from my_project.config import ProjectConfigManager
266
+ from tests.example_project.config.config_example import ProjectConfigManager
267
+ from config_cli_gui.docs import DocumentationGenerator
254
268
  import os
255
269
 
256
270
  # Define output paths
257
271
  output_dir = "docs/generated"
258
272
  os.makedirs(output_dir, exist_ok=True)
259
273
 
260
- config_file_path = "config.yaml" # At the project root or similar
261
- cli_doc_path = os.path.join(output_dir, "cli.md")
262
- config_doc_path = os.path.join(output_dir, "config.md")
263
-
264
- print(f"Generating default config to: {config_file_path}")
265
- ProjectConfigManager.generate_default_config_file(config_file_path)
274
+ default_config = "config.yaml" # At the project root or similar
275
+ default_cli_doc = os.path.join(output_dir, "cli.md")
276
+ default_config_doc = os.path.join(output_dir, "config.md")
277
+ _config = ProjectConfigManager()
278
+ doc_gen = DocumentationGenerator(_config)
279
+ doc_gen.generate_default_config_file(output_file=default_config)
280
+ print(f"Generated: {default_config}")
266
281
 
267
- print(f"Generating general config documentation to: {config_doc_path}")
268
- ProjectConfigManager.generate_config_markdown_doc(config_doc_path)
282
+ doc_gen.generate_config_markdown_doc(output_file=default_config_doc)
283
+ print(f"Generated: {default_config_doc}")
269
284
 
270
- print(f"Generating CLI documentation to: {cli_doc_path}")
271
- ProjectConfigManager.generate_cli_markdown_doc(
272
- output_file=cli_doc_path,
273
- cli_category_name="cli", # Ensure this matches your CLI config category
274
- cli_entry_point="python -m my_project.cli" # Your project's actual CLI entry point
275
- )
285
+ doc_gen.generate_cli_markdown_doc(output_file=default_cli_doc)
286
+ print(f"Generated: {default_cli_doc}")
276
287
 
277
288
  print("Documentation and default config generation complete.")
278
289
  ```
@@ -0,0 +1,264 @@
1
+ <!-- This README.md is auto-generated from docs/index.md -->
2
+
3
+ # Welcome to config-cli-gui
4
+
5
+ **Unified Configuration and Interface Management**
6
+
7
+ Provides a generic configuration framework that automatically generates both command-line interfaces and GUI settings dialogs from configuration parameters.
8
+
9
+ [![Github CI Status](https://github.com/pamagister/config-cli-gui/actions/workflows/main.yml/badge.svg)](https://github.com/pamagister/config-cli-gui/actions)
10
+ [![GitHub release](https://img.shields.io/github/v/release/pamagister/config-cli-gui)](https://github.com/pamagister/config-cli-gui/releases)
11
+ [![Read the Docs](https://readthedocs.org/projects/config-cli-gui/badge/?version=stable)](https://config-cli-gui.readthedocs.io/en/stable/)
12
+ [![License](https://img.shields.io/github/license/pamagister/config-cli-gui)](https://github.com/pamagister/config-cli-gui/blob/main/LICENSE)
13
+ [![GitHub issues](https://img.shields.io/github/issues/pamagister/config-cli-gui)](https://github.com/pamagister/config-cli-gui/issues)
14
+ [![PyPI](https://img.shields.io/pypi/v/config-cli-gui)](https://pypi.org/project/config-cli-gui/)
15
+ [![Downloads](https://pepy.tech/badge/config-cli-gui)](https://pepy.tech/project/config-cli-gui/)
16
+
17
+
18
+ `config-cli-gui` is a Python library designed to streamline the management of application configurations,
19
+ generating command-line interfaces (CLIs), and dynamically creating graphical user interface (GUI) settings dialogs
20
+ from a single source of truth. It leverages Pydantic for robust parameter definition and offers
21
+ powerful features for consistent configuration across different application entry points.
22
+
23
+ ---
24
+
25
+ ## 🚀 Installation
26
+
27
+ You can install `config-cli-gui` using pip:
28
+
29
+ ```bash
30
+ pip install config-cli-gui
31
+ ```
32
+
33
+ ---
34
+
35
+ ## ✨ Features
36
+
37
+ * **Single Source of Truth**: Define all your application parameters in one place using simple, dataclass-like structures based on Pydantic's `BaseModel`. This ensures consistency and reduces errors across your application.
38
+ * **Categorized Configuration**: Organize your parameters into logical categories (e.g., `cli`, `app`, `gui`) for better structure and maintainability.
39
+ * **Dynamic CLI Generation**: Automatically generate `argparse`-compatible command-line arguments directly from your defined configuration parameters, including help texts, types, and choices.
40
+ * **Config File Management**: Easily load and save configurations from/to YAML or JSON files, allowing users to customize default settings.
41
+ * **GUI Settings Dialogs**: Dynamically create Tkinter-based settings dialogs for your application, allowing users to intuitively modify configuration parameters via a graphical interface.
42
+ * **Documentation Generation**: Generate detailed Markdown documentation for both your CLI options and all configuration parameters, keeping your user guides always up-to-date with your codebase.
43
+ * **Override System**: Supports robust overriding of configuration values via configuration files and command-line arguments, with clear precedence.
44
+
45
+ ---
46
+
47
+ ## 📚 Usage
48
+
49
+ ### 1\. Define Your Configuration
50
+
51
+ Start by defining your application's configuration parameters in a central `config.py` file within your project. You will inherit from `config-cli-gui`'s `GenericConfigManager` and `BaseConfigCategory`.
52
+
53
+ ```python
54
+ # my_project/config_example.py
55
+
56
+ from config_cli_gui.config import (
57
+ ConfigCategory,
58
+ ConfigManager,
59
+ ConfigParameter,
60
+ )
61
+
62
+
63
+ class CliConfig(ConfigCategory):
64
+ """CLI-specific configuration parameters."""
65
+
66
+ def get_category_name(self) -> str:
67
+ return "cli"
68
+
69
+ # Positional argument
70
+ input: ConfigParameter = ConfigParameter(
71
+ name="input",
72
+ default="",
73
+ help="Path to input (file or folder)",
74
+ required=True,
75
+ is_cli=True,
76
+ )
77
+
78
+ min_dist: ConfigParameter = ConfigParameter(
79
+ name="min_dist",
80
+ default=20,
81
+ help="Maximum distance between two waypoints",
82
+ is_cli=True,
83
+ )
84
+
85
+ extract_waypoints: ConfigParameter = ConfigParameter(
86
+ name="extract_waypoints",
87
+ default=True,
88
+ help="Extract starting points of each track as waypoint",
89
+ is_cli=True,
90
+ )
91
+
92
+
93
+ class AppConfig(ConfigCategory):
94
+ """Application-specific configuration parameters."""
95
+
96
+ def get_category_name(self) -> str:
97
+ return "app"
98
+
99
+ log_level: ConfigParameter = ConfigParameter(
100
+ name="log_level",
101
+ default="INFO",
102
+ choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
103
+ help="Logging level for the application",
104
+ )
105
+
106
+ log_file_max_size: ConfigParameter = ConfigParameter(
107
+ name="log_file_max_size",
108
+ default=10,
109
+ help="Maximum log file size in MB before rotation",
110
+ )
111
+
112
+
113
+ class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
114
+ """Main configuration manager that handles all parameter categories."""
115
+
116
+ categories = (CliConfig(), AppConfig())
117
+
118
+ def __init__(self, config_file: str | None = None, **kwargs):
119
+ """Initialize the configuration manager with all parameter categories."""
120
+ super().__init__(self.categories, config_file, **kwargs)
121
+
122
+
123
+ ```
124
+
125
+ ### 2\. Generate CLI
126
+
127
+ Use the generic CLI functions to parse command-line arguments based on your defined `CliConfig`.
128
+
129
+ ```python
130
+ # my_project/cli_example.py
131
+ from config_cli_gui.cli import CliGenerator
132
+ from config_cli_gui.config import ConfigManager
133
+ from tests.example_project.config.config_example import ProjectConfigManager
134
+ from tests.example_project.core.base import BaseGPXProcessor
135
+ from tests.example_project.core.logging import initialize_logging
136
+
137
+
138
+ def run_main_processing(_config: ConfigManager) -> int:
139
+ """Main processing function that gets called by the CLI generator.
140
+
141
+ Args:
142
+ _config: Configuration manager with all settings
143
+
144
+ Returns:
145
+ Exit code (0 for success, non-zero for error)
146
+ """
147
+ # Initialize logging system
148
+ logger_manager = initialize_logging(_config)
149
+ logger = logger_manager.get_logger("config_cli_gui.cli")
150
+
151
+ try:
152
+ # Log startup information
153
+ logger.info("Starting config_cli_gui CLI")
154
+ logger_manager.log_config_summary()
155
+
156
+ logger.info(f"Processing input")
157
+
158
+ # Create and run BaseGPXProcessor
159
+ processor = BaseGPXProcessor(
160
+ _config.get_category("cli").input.default,
161
+ _config.get_category("cli").output.default,
162
+ _config.get_category("cli").min_dist.default,
163
+ _config.get_category("app").date_format.default,
164
+ _config.get_category("cli").elevation.default,
165
+ logger=logger,
166
+ )
167
+
168
+ logger.info("Starting conversion process")
169
+
170
+ # Run the processing (adjust method name based on your actual implementation)
171
+ result_files = processor.compress_files()
172
+ logger.info(f"Successfully processed {result_files}")
173
+ return 0
174
+
175
+ except Exception as e:
176
+ logger.error(f"Processing failed: {e}")
177
+ logger.debug("Full traceback:", exc_info=True)
178
+ return 1
179
+
180
+
181
+ def main():
182
+ """Main entry point for the CLI application."""
183
+ # Create the base configuration manager
184
+ config_manager = ProjectConfigManager()
185
+
186
+ # Create CLI generator
187
+ cli_generator = CliGenerator(config_manager=config_manager, app_name="config_cli_gui")
188
+
189
+ # Run the CLI with our main processing function
190
+ return cli_generator.run_cli(
191
+ main_function=run_main_processing,
192
+ description="Example CLI for config-cli-gui using the generic config framework.",
193
+ )
194
+
195
+
196
+ if __name__ == "__main__":
197
+ import sys
198
+
199
+ sys.exit(main())
200
+ ```
201
+
202
+ ### 3\. Integrate GUI Settings Dialog
203
+
204
+ The `SettingsDialog` from `config-cli-gui` (or your project's adapted version) can be used to easily create a settings window.
205
+
206
+ ```python
207
+ # my_project/gui_example.py (Simplified example)
208
+ import tkinter as tk
209
+ from tests.example_project.config.config_example import ProjectConfigManager
210
+ from config_cli_gui.gui import GenericSettingsDialog # Assuming gui_settings is part of the generic lib or adapted
211
+
212
+
213
+ def open_settings_window(parent_root, config_manager: ProjectConfigManager):
214
+ dialog = GenericSettingsDialog(parent_root, config_manager)
215
+ parent_root.wait_window(dialog.dialog)
216
+ # After dialog closes, config_manager will have updated values if 'OK' was clicked
217
+ print("Settings updated or cancelled.")
218
+ print(f"New GUI Theme: {config_manager.get_category('gui').theme.default}")
219
+
220
+
221
+ if __name__ == "__main__":
222
+ root = tk.Tk()
223
+ root.withdraw() # Hide main window for this example
224
+
225
+ # Initialize your project's config manager
226
+ project_config = ProjectConfigManager()
227
+
228
+ open_settings_window(root, project_config)
229
+
230
+ root.destroy()
231
+ ```
232
+
233
+ ### 4\. Generate Documentation and Default Config
234
+
235
+ Use the static methods on your `ProjectConfigManager` to generate `config.yaml`, `cli.md`, and `config.md` files.
236
+
237
+ ```python
238
+ # scripts/generate_docs.py (or similar script in your project)
239
+ from tests.example_project.config.config_example import ProjectConfigManager
240
+ from config_cli_gui.docs import DocumentationGenerator
241
+ import os
242
+
243
+ # Define output paths
244
+ output_dir = "docs/generated"
245
+ os.makedirs(output_dir, exist_ok=True)
246
+
247
+ default_config = "config.yaml" # At the project root or similar
248
+ default_cli_doc = os.path.join(output_dir, "cli.md")
249
+ default_config_doc = os.path.join(output_dir, "config.md")
250
+ _config = ProjectConfigManager()
251
+ doc_gen = DocumentationGenerator(_config)
252
+ doc_gen.generate_default_config_file(output_file=default_config)
253
+ print(f"Generated: {default_config}")
254
+
255
+ doc_gen.generate_config_markdown_doc(output_file=default_config_doc)
256
+ print(f"Generated: {default_config_doc}")
257
+
258
+ doc_gen.generate_cli_markdown_doc(output_file=default_cli_doc)
259
+ print(f"Generated: {default_cli_doc}")
260
+
261
+ print("Documentation and default config generation complete.")
262
+ ```
263
+
264
+ By following this structure, `config-cli-gui` provides a robust and maintainable foundation for your application's configuration needs.