config-cli-gui 0.3.3__tar.gz → 0.3.5__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.3.3 → config_cli_gui-0.3.5}/.github/workflows/main.yml +1 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/HISTORY.md +27 -0
- {config_cli_gui-0.3.3/src/config_cli_gui.egg-info → config_cli_gui-0.3.5}/PKG-INFO +2 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/config.yaml +18 -24
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/usage/config.md +20 -23
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/pyproject.toml +1 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/_version.py +3 -3
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/config.py +120 -10
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/docs.py +8 -4
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/gui.py +155 -72
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/logging.py +80 -6
- config_cli_gui-0.3.5/src/config_cli_gui/persistence.py +75 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5/src/config_cli_gui.egg-info}/PKG-INFO +2 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui.egg-info/SOURCES.txt +1 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui.egg-info/requires.txt +1 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/cli/cli_example.py +6 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/config/config_example.py +3 -64
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/gui/gui_example.py +52 -6
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/test_config_manager.py +1 -1
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/uv.lock +14 -0
- config_cli_gui-0.3.3/tests/example_project/gui/config.yaml +0 -48
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/FUNDING.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/actions/setup-environment/action.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/dependabot.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/init.sh +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/release_message.sh +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/update_funding.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/workflows/release.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.github/workflows/update_readme.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.gitignore +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.idea/runConfigurations/config_generate.xml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.idea/runConfigurations/example_project_cli.xml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.idea/runConfigurations/example_project_gui.xml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.pre-commit-config.yaml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/.readthedocs.yaml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/LICENSE +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/Makefile +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/README.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/.nav.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/_static/img/favicon.png +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/_static/img/logo.png +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/_static/img/settings_dlg.png +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/_static/img/settings_doc.png +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/css/custom.css +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/develop/contributing.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/develop/make_windows.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/develop/naming_convention.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/funding/funding.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/getting-started/install.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/getting-started/virtual-environment.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/index.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/docs/usage/cli.md +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/mkdocs.yml +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/scripts/show_filelist.ps1 +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/scripts/show_tree.ps1 +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/scripts/show_tree.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/scripts/update_readme.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/setup.cfg +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/cli.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/configtypes/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/configtypes/color.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/configtypes/font.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui/configtypes/vector.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui.egg-info/dependency_links.txt +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui.egg-info/entry_points.txt +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/src/config_cli_gui.egg-info/top_level.txt +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/template.yml.url +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/__main__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/cli/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/cli/__main__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/config/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/core/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/core/base.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/example.gpx +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/gui/__init__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/example_project/gui/__main__.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/test_cli.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/test_docs.py +0 -0
- {config_cli_gui-0.3.3 → config_cli_gui-0.3.5}/tests/test_generic_cli.py +0 -0
|
@@ -4,6 +4,33 @@ Changelog
|
|
|
4
4
|
|
|
5
5
|
(unreleased)
|
|
6
6
|
------------
|
|
7
|
+
- Improve gui. [Paul Magister]
|
|
8
|
+
- Fix gui log issue: even better fix. [Paul Magister]
|
|
9
|
+
- Fix gui log issue: [Paul Magister]
|
|
10
|
+
|
|
11
|
+
Previously the logger handler attempted to call the passed object like a function; GuiLogWriter provides write(), not a call. Because emit() swallowed exceptions, you saw nothing in the GUI log.
|
|
12
|
+
Now connect_gui_logging detects objects with .write() and registers the writer.write callable with the UI handler. GuiLogHandler.emit calls that callable, which writes to the text widget and the text appears.
|
|
13
|
+
- Improve config consistency: correctly consider logging parameters.
|
|
14
|
+
[Paul Magister]
|
|
15
|
+
- Improve config usage consistency: allways load last config. Move
|
|
16
|
+
AppConfig into config.py since it is used in the core lib component.
|
|
17
|
+
[Paul Magister]
|
|
18
|
+
- Save last opened config to start there on the next session, move theme
|
|
19
|
+
to app category. [Paul Magister]
|
|
20
|
+
- Do not run tests on macos. [Paul Magister]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
0.3.4 (2026-06-18)
|
|
24
|
+
------------------
|
|
25
|
+
- Docs: Update HISTORY.md for release 0.3.4. [Paul Magister]
|
|
26
|
+
- Bugfix: init color display properly. [Paul Magister]
|
|
27
|
+
- Use ttkbootstrap gui styles. [Paul Magister]
|
|
28
|
+
- Improve GUI scaling and font sizes. [Paul Magister]
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
0.3.3 (2026-06-13)
|
|
32
|
+
------------------
|
|
33
|
+
- Docs: Update HISTORY.md for release 0.3.3. [Paul Magister]
|
|
7
34
|
- Update to minimum python 3.11. [Paul Magister]
|
|
8
35
|
|
|
9
36
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: config-cli-gui
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.5
|
|
4
4
|
Summary: Feature-rich Python project template for config-cli-gui.
|
|
5
5
|
Author: pamagister
|
|
6
6
|
Requires-Python: <3.12,>=3.11
|
|
@@ -9,6 +9,7 @@ License-File: LICENSE
|
|
|
9
9
|
Requires-Dist: pydantic>=2.11.7
|
|
10
10
|
Requires-Dist: pyyaml>=6.0.2
|
|
11
11
|
Requires-Dist: pillow>=12.0.0
|
|
12
|
+
Requires-Dist: ttkbootstrap>=1.20.3
|
|
12
13
|
Provides-Extra: dev
|
|
13
14
|
Requires-Dist: pytest>=8.4.0; extra == "dev"
|
|
14
15
|
Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
|
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
app:
|
|
2
|
+
# Date format to use | type=str
|
|
3
|
+
date_format: '%Y-%m-%d'
|
|
4
|
+
# Logging level for the application | type=str | choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
|
5
|
+
log_level: INFO
|
|
6
|
+
# Maximum log file size in MB before rotation | type=int
|
|
7
|
+
log_file_max_size: 2
|
|
8
|
+
# Enable logging to file | type=bool | choices=[True, False]
|
|
9
|
+
enable_file_logging: true
|
|
10
|
+
# Enable logging to console | type=bool | choices=[True, False]
|
|
11
|
+
enable_console_logging: true
|
|
12
|
+
# GUI theme setting supported by ttkbootstrap | type=str | choices=['cosmo', 'flatly', 'litera', 'minty', 'lumen', 'sandstone', 'yeti', 'pulse', 'united', 'darkly', 'superhero', 'solar', 'cyborg', 'vapor', 'simplex']
|
|
13
|
+
theme: superhero
|
|
1
14
|
cli:
|
|
2
15
|
# Path to input (file or folder) | type=str | [CLI]
|
|
3
16
|
input: ''
|
|
@@ -9,26 +22,7 @@ cli:
|
|
|
9
22
|
extract_waypoints: true
|
|
10
23
|
# Include elevation data in waypoints | type=bool | [CLI] | choices=[True, False]
|
|
11
24
|
elevation: false
|
|
12
|
-
app:
|
|
13
|
-
# Date format to use | type=str
|
|
14
|
-
date_format: '%Y-%m-%d'
|
|
15
|
-
# Logging level for the application | type=str | choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
|
|
16
|
-
log_level: INFO
|
|
17
|
-
# Maximum log file size in MB before rotation | type=int
|
|
18
|
-
log_file_max_size: 10
|
|
19
|
-
# Number of backup log files to keep | type=int
|
|
20
|
-
log_backup_count: 5
|
|
21
|
-
# Log message format style | type=str | choices=['simple', 'detailed', 'json']
|
|
22
|
-
log_format: detailed
|
|
23
|
-
# Maximum number of worker threads | type=int
|
|
24
|
-
max_workers: 4
|
|
25
|
-
# Enable logging to file | type=bool | choices=[True, False]
|
|
26
|
-
enable_file_logging: true
|
|
27
|
-
# Enable logging to console | type=bool | choices=[True, False]
|
|
28
|
-
enable_console_logging: true
|
|
29
25
|
gui:
|
|
30
|
-
# GUI theme setting | type=str | choices=['light', 'dark', 'auto']
|
|
31
|
-
theme: light
|
|
32
26
|
# Default window width | type=int
|
|
33
27
|
window_width: 800
|
|
34
28
|
# Default window height | type=int
|
|
@@ -40,21 +34,21 @@ gui:
|
|
|
40
34
|
# Maximum number of log lines to keep in GUI | type=int
|
|
41
35
|
max_log_lines: 1000
|
|
42
36
|
# Point in 2D space | type=Vector
|
|
43
|
-
point2D: (7, 11)
|
|
37
|
+
point2D: (7.0, 11.0)
|
|
44
38
|
# Point in 3D space | type=Vector
|
|
45
39
|
point3D: (1.2, 3.4, 5.6)
|
|
46
40
|
misc:
|
|
47
41
|
# Example integer | type=int
|
|
48
42
|
some_numeric: 42
|
|
49
43
|
# Example vector 2D | type=Vector
|
|
50
|
-
some_vector2d: (1, 2)
|
|
44
|
+
some_vector2d: (1.0, 2.0)
|
|
51
45
|
# Example vector 3D | type=Vector
|
|
52
46
|
some_vector3d: (1.1, 2.2, 3.3)
|
|
53
|
-
# Path to the file to use | type=
|
|
47
|
+
# Path to the file to use | type=str
|
|
54
48
|
some_file: some_file.txt
|
|
55
49
|
# Color setting for the application | type=Color
|
|
56
50
|
some_color: '#ff0000'
|
|
57
51
|
# Date setting for the application | type=datetime
|
|
58
|
-
some_date: '2025-12-31T10:30:
|
|
52
|
+
some_date: '2025-12-31T10:30:00'
|
|
59
53
|
# Font setting for the application | type=Font
|
|
60
|
-
some_font: 'DejaVuSans.ttf, 12, #0000ff'
|
|
54
|
+
some_font: 'DejaVuSans.ttf, 12.0, #0000ff'
|
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
These parameters are available to configure the behavior of your application.
|
|
4
4
|
The parameters in the cli category can be accessed via the command line interface.
|
|
5
5
|
|
|
6
|
+
## Category "app"
|
|
7
|
+
|
|
8
|
+
| Name | Type | Description | Default | Choices |
|
|
9
|
+
|------------------------|------|---------------------------------------------|------------|-------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
10
|
+
| date_format | str | Date format to use | '%Y-%m-%d' | - |
|
|
11
|
+
| log_level | str | Logging level for the application | 'INFO' | ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] |
|
|
12
|
+
| log_file_max_size | int | Maximum log file size in MB before rotation | 2 | - |
|
|
13
|
+
| enable_file_logging | bool | Enable logging to file | True | [True, False] |
|
|
14
|
+
| enable_console_logging | bool | Enable logging to console | True | [True, False] |
|
|
15
|
+
| theme | str | GUI theme setting supported by ttkbootstrap | 'darkly' | ['cosmo', 'flatly', 'litera', 'minty', 'lumen', 'sandstone', 'yeti', 'pulse', 'united', 'darkly', 'superhero', 'solar', 'cyborg', 'vapor', 'simplex'] |
|
|
16
|
+
|
|
6
17
|
## Category "cli"
|
|
7
18
|
|
|
8
19
|
| Name | Type | Description | Default | Choices |
|
|
@@ -13,31 +24,17 @@ The parameters in the cli category can be accessed via the command line interfac
|
|
|
13
24
|
| extract_waypoints | bool | Extract starting points of each track as waypoint | True | [True, False] |
|
|
14
25
|
| elevation | bool | Include elevation data in waypoints | False | [True, False] |
|
|
15
26
|
|
|
16
|
-
## Category "app"
|
|
17
|
-
|
|
18
|
-
| Name | Type | Description | Default | Choices |
|
|
19
|
-
|------------------------|------|---------------------------------------------|------------|---------------------------------------------------|
|
|
20
|
-
| date_format | str | Date format to use | '%Y-%m-%d' | - |
|
|
21
|
-
| log_level | str | Logging level for the application | 'INFO' | ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] |
|
|
22
|
-
| log_file_max_size | int | Maximum log file size in MB before rotation | 10 | - |
|
|
23
|
-
| log_backup_count | int | Number of backup log files to keep | 5 | - |
|
|
24
|
-
| log_format | str | Log message format style | 'detailed' | ['simple', 'detailed', 'json'] |
|
|
25
|
-
| max_workers | int | Maximum number of worker threads | 4 | - |
|
|
26
|
-
| enable_file_logging | bool | Enable logging to file | True | [True, False] |
|
|
27
|
-
| enable_console_logging | bool | Enable logging to console | True | [True, False] |
|
|
28
|
-
|
|
29
27
|
## Category "gui"
|
|
30
28
|
|
|
31
|
-
| Name | Type | Description | Default | Choices
|
|
32
|
-
|
|
33
|
-
|
|
|
34
|
-
|
|
|
35
|
-
|
|
|
36
|
-
|
|
|
37
|
-
|
|
|
38
|
-
|
|
|
39
|
-
|
|
|
40
|
-
| point3D | Vector | Point in 3D space | Vector(1.2, 3.4, 5.6) | - |
|
|
29
|
+
| Name | Type | Description | Default | Choices |
|
|
30
|
+
|-------------------|--------|------------------------------------------------|-----------------------|---------------|
|
|
31
|
+
| window_width | int | Default window width | 800 | - |
|
|
32
|
+
| window_height | int | Default window height | 600 | - |
|
|
33
|
+
| log_window_height | int | Height of the log window in pixels | 200 | - |
|
|
34
|
+
| auto_scroll_log | bool | Automatically scroll to the newest log entries | True | [True, False] |
|
|
35
|
+
| max_log_lines | int | Maximum number of log lines to keep in GUI | 1000 | - |
|
|
36
|
+
| point2D | Vector | Point in 2D space | Vector(7, 11) | - |
|
|
37
|
+
| point3D | Vector | Point in 3D space | Vector(1.2, 3.4, 5.6) | - |
|
|
41
38
|
|
|
42
39
|
## Category "misc"
|
|
43
40
|
|
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '0.3.
|
|
22
|
-
__version_tuple__ = version_tuple = (0, 3,
|
|
21
|
+
__version__ = version = '0.3.5'
|
|
22
|
+
__version_tuple__ = version_tuple = (0, 3, 5)
|
|
23
23
|
|
|
24
|
-
__commit_id__ = commit_id = '
|
|
24
|
+
__commit_id__ = commit_id = 'g089c3018c'
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
|
+
import logging
|
|
2
3
|
from abc import ABC, abstractmethod
|
|
3
4
|
from collections.abc import Iterable
|
|
4
5
|
from dataclasses import dataclass
|
|
@@ -9,6 +10,7 @@ from typing import Any
|
|
|
9
10
|
import yaml
|
|
10
11
|
from pydantic import BaseModel
|
|
11
12
|
|
|
13
|
+
from config_cli_gui import persistence
|
|
12
14
|
from config_cli_gui.configtypes.color import Color
|
|
13
15
|
from config_cli_gui.configtypes.font import Font
|
|
14
16
|
from config_cli_gui.configtypes.vector import Vector
|
|
@@ -63,21 +65,25 @@ class ConfigSerializer:
|
|
|
63
65
|
TYPE_MAPPING = {
|
|
64
66
|
Font: {
|
|
65
67
|
"to_serializable": lambda v: v.to_str(),
|
|
66
|
-
"from_serializable": lambda v:
|
|
67
|
-
|
|
68
|
-
|
|
68
|
+
"from_serializable": lambda v: (
|
|
69
|
+
Font.from_list(v) if isinstance(v, list) else Font.from_str(v)
|
|
70
|
+
),
|
|
69
71
|
},
|
|
70
72
|
Color: {
|
|
71
73
|
"to_serializable": lambda v: v.to_hex(),
|
|
72
|
-
"from_serializable": lambda v:
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
"from_serializable": lambda v: (
|
|
75
|
+
Color.from_list(v)
|
|
76
|
+
if isinstance(v, list)
|
|
77
|
+
else (Color.from_hex(v) if isinstance(v, str) else v)
|
|
78
|
+
),
|
|
75
79
|
},
|
|
76
80
|
Vector: {
|
|
77
81
|
"to_serializable": lambda v: v.to_str(),
|
|
78
|
-
"from_serializable": lambda v:
|
|
79
|
-
|
|
80
|
-
|
|
82
|
+
"from_serializable": lambda v: (
|
|
83
|
+
Vector.from_list(v)
|
|
84
|
+
if isinstance(v, list)
|
|
85
|
+
else (Vector.from_str(v) if isinstance(v, str) else v)
|
|
86
|
+
),
|
|
81
87
|
},
|
|
82
88
|
Path: {
|
|
83
89
|
"to_serializable": lambda v: str(v.as_posix()),
|
|
@@ -85,7 +91,7 @@ class ConfigSerializer:
|
|
|
85
91
|
},
|
|
86
92
|
datetime: {
|
|
87
93
|
"to_serializable": lambda v: v.isoformat(),
|
|
88
|
-
"from_serializable": lambda v: datetime.fromisoformat(v) if isinstance(v, str) else v,
|
|
94
|
+
"from_serializable": lambda v: (datetime.fromisoformat(v) if isinstance(v, str) else v),
|
|
89
95
|
},
|
|
90
96
|
}
|
|
91
97
|
|
|
@@ -104,6 +110,74 @@ class ConfigSerializer:
|
|
|
104
110
|
return value
|
|
105
111
|
|
|
106
112
|
|
|
113
|
+
class AppConfig(ConfigCategory):
|
|
114
|
+
"""Application-specific configuration parameters (centralized).
|
|
115
|
+
|
|
116
|
+
This category was moved from example project to the core library so that
|
|
117
|
+
every project uses a consistent, non-editable application configuration
|
|
118
|
+
section. It contains general application settings such as logging and
|
|
119
|
+
theme preferences.
|
|
120
|
+
"""
|
|
121
|
+
|
|
122
|
+
def get_category_name(self) -> str:
|
|
123
|
+
return "app"
|
|
124
|
+
|
|
125
|
+
date_format: ConfigParameter = ConfigParameter(
|
|
126
|
+
name="date_format",
|
|
127
|
+
value="%Y-%m-%d",
|
|
128
|
+
help="Date format to use",
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
log_level: ConfigParameter = ConfigParameter(
|
|
132
|
+
name="log_level",
|
|
133
|
+
value="INFO",
|
|
134
|
+
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
135
|
+
help="Logging level for the application",
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
log_file_max_size: ConfigParameter = ConfigParameter(
|
|
139
|
+
name="log_file_max_size",
|
|
140
|
+
value=2,
|
|
141
|
+
help="Maximum log file size in MB before rotation",
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
enable_file_logging: ConfigParameter = ConfigParameter(
|
|
145
|
+
name="enable_file_logging",
|
|
146
|
+
value=True,
|
|
147
|
+
help="Enable logging to file",
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
enable_console_logging: ConfigParameter = ConfigParameter(
|
|
151
|
+
name="enable_console_logging",
|
|
152
|
+
value=True,
|
|
153
|
+
help="Enable logging to console",
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# ttkbootstrap.Style().theme_names()
|
|
157
|
+
theme: ConfigParameter = ConfigParameter(
|
|
158
|
+
name="theme",
|
|
159
|
+
value="darkly",
|
|
160
|
+
choices=[
|
|
161
|
+
"cosmo",
|
|
162
|
+
"flatly",
|
|
163
|
+
"litera",
|
|
164
|
+
"minty",
|
|
165
|
+
"lumen",
|
|
166
|
+
"sandstone",
|
|
167
|
+
"yeti",
|
|
168
|
+
"pulse",
|
|
169
|
+
"united",
|
|
170
|
+
"darkly",
|
|
171
|
+
"superhero",
|
|
172
|
+
"solar",
|
|
173
|
+
"cyborg",
|
|
174
|
+
"vapor",
|
|
175
|
+
"simplex",
|
|
176
|
+
],
|
|
177
|
+
help="GUI theme setting supported by ttkbootstrap",
|
|
178
|
+
)
|
|
179
|
+
|
|
180
|
+
|
|
107
181
|
class ConfigManager:
|
|
108
182
|
"""Manages loading, saving, and accessing configuration categories."""
|
|
109
183
|
|
|
@@ -115,7 +189,9 @@ class ConfigManager:
|
|
|
115
189
|
):
|
|
116
190
|
self._categories: dict[str, ConfigCategory] = {}
|
|
117
191
|
self._serializer = ConfigSerializer()
|
|
192
|
+
self.app: AppConfig = AppConfig()
|
|
118
193
|
|
|
194
|
+
categories = (self.app, *categories)
|
|
119
195
|
for category in categories:
|
|
120
196
|
if not isinstance(category, ConfigCategory):
|
|
121
197
|
raise TypeError(f"Expected ConfigCategory instance, got {type(category)}")
|
|
@@ -163,6 +239,18 @@ class ConfigManager:
|
|
|
163
239
|
data = yaml.safe_load(f) if path.suffix.lower() in [".yml", ".yaml"] else json.load(f)
|
|
164
240
|
|
|
165
241
|
self._apply_config_data(data)
|
|
242
|
+
# Persist the information about the last used configuration file so the
|
|
243
|
+
# application can restore the same config on next start.
|
|
244
|
+
try:
|
|
245
|
+
persistence.write_last_used_config("config-cli-gui", str(path))
|
|
246
|
+
except Exception:
|
|
247
|
+
# Persistence should not break normal config loading.
|
|
248
|
+
pass
|
|
249
|
+
try:
|
|
250
|
+
logging.getLogger("config_cli_gui").info(f"Loaded configuration from: {path}")
|
|
251
|
+
except Exception:
|
|
252
|
+
# Non-fatal: logging may not be configured yet.
|
|
253
|
+
pass
|
|
166
254
|
|
|
167
255
|
def _apply_config_data(self, data: dict[str, Any]) -> None:
|
|
168
256
|
"""Apply loaded data to the configuration parameters."""
|
|
@@ -201,6 +289,28 @@ class ConfigManager:
|
|
|
201
289
|
if file_format == "yaml":
|
|
202
290
|
self._append_comments_to_yaml(path)
|
|
203
291
|
|
|
292
|
+
# Record the saved config as the last-used config as well.
|
|
293
|
+
try:
|
|
294
|
+
persistence.write_last_used_config("config-cli-gui", str(path))
|
|
295
|
+
except Exception:
|
|
296
|
+
# Ignore persistence failures when saving
|
|
297
|
+
pass
|
|
298
|
+
try:
|
|
299
|
+
logging.getLogger("config_cli_gui").info(f"Saved configuration to: {path}")
|
|
300
|
+
except Exception:
|
|
301
|
+
# Non-fatal: logging may not be configured yet.
|
|
302
|
+
pass
|
|
303
|
+
|
|
304
|
+
def get_last_used_config(self) -> str | None:
|
|
305
|
+
"""Return the last used config file path recorded by the persistence layer.
|
|
306
|
+
|
|
307
|
+
This is a convenience wrapper around persistence.read_last_used_config.
|
|
308
|
+
"""
|
|
309
|
+
try:
|
|
310
|
+
return persistence.read_last_used_config("config-cli-gui")
|
|
311
|
+
except Exception:
|
|
312
|
+
return None
|
|
313
|
+
|
|
204
314
|
def to_dict(self) -> dict[str, Any]:
|
|
205
315
|
"""Convert all configuration categories to a dictionary."""
|
|
206
316
|
result: dict[str, dict[str, Any]] = {}
|
|
@@ -16,13 +16,15 @@ class DocumentationGenerator:
|
|
|
16
16
|
def pad(s, width):
|
|
17
17
|
return s + " " * (width - len(s))
|
|
18
18
|
|
|
19
|
-
markdown_content = dedent(
|
|
19
|
+
markdown_content = dedent(
|
|
20
|
+
"""
|
|
20
21
|
# Configuration Parameters
|
|
21
22
|
|
|
22
23
|
These parameters are available to configure the behavior of your application.
|
|
23
24
|
The parameters in the cli category can be accessed via the command line interface.
|
|
24
25
|
|
|
25
|
-
"""
|
|
26
|
+
"""
|
|
27
|
+
).lstrip()
|
|
26
28
|
|
|
27
29
|
for category_name, category in self.config_manager._categories.items():
|
|
28
30
|
markdown_content += f'## Category "{category_name}"\n\n'
|
|
@@ -165,13 +167,15 @@ class DocumentationGenerator:
|
|
|
165
167
|
continue
|
|
166
168
|
example_value = param.choices[0] if param.choices else param.value
|
|
167
169
|
examples.append(
|
|
168
|
-
dedent(
|
|
170
|
+
dedent(
|
|
171
|
+
f"""
|
|
169
172
|
### {i}. With {param.name} parameter
|
|
170
173
|
|
|
171
174
|
```bash
|
|
172
175
|
python -m {app_name} --{param.name} {example_value} {required_arg}
|
|
173
176
|
```
|
|
174
|
-
"""
|
|
177
|
+
"""
|
|
178
|
+
)
|
|
175
179
|
)
|
|
176
180
|
|
|
177
181
|
markdown = dedent(
|