config-cli-gui 0.2.7__tar.gz → 0.2.9__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.2.7 → config_cli_gui-0.2.9}/HISTORY.md +16 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/PKG-INFO +48 -27
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/README.md +1 -1
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/config.yaml +12 -1
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/index.md +46 -26
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/usage/config.md +9 -5
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/pyproject.toml +1 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/_version.py +3 -3
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/config.py +8 -78
- config_cli_gui-0.2.9/src/config_cli_gui/configtypes/color.py +43 -0
- config_cli_gui-0.2.9/src/config_cli_gui/configtypes/font.py +80 -0
- config_cli_gui-0.2.9/src/config_cli_gui/configtypes/vector.py +31 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/gui.py +130 -12
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/PKG-INFO +48 -27
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/SOURCES.txt +4 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/requires.txt +1 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/config/config_example.py +27 -2
- config_cli_gui-0.2.9/tests/example_project/gui/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/test_config_manager.py +9 -2
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/test_docs.py +1 -1
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/uv.lock +40 -1
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/FUNDING.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/actions/setup-environment/action.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/dependabot.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/init.sh +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/release_message.sh +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/update_funding.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/workflows/main.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/workflows/release.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.github/workflows/update_readme.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.gitignore +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.idea/runConfigurations/config_generate.xml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.idea/runConfigurations/example_project_cli.xml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.idea/runConfigurations/example_project_gui.xml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.pre-commit-config.yaml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/.readthedocs.yaml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/LICENSE +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/Makefile +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/.nav.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/_static/img/favicon.png +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/_static/img/logo.png +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/css/custom.css +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/develop/contributing.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/develop/make_windows.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/develop/naming_convention.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/funding/funding.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/getting-started/install.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/getting-started/virtual-environment.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/docs/usage/cli.md +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/mkdocs.yml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/scripts/show_filelist.ps1 +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/scripts/show_tree.ps1 +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/scripts/show_tree.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/scripts/update_readme.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/setup.cfg +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/cli.py +0 -0
- {config_cli_gui-0.2.7/tests → config_cli_gui-0.2.9/src/config_cli_gui/configtypes}/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui/docs.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/dependency_links.txt +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/entry_points.txt +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/src/config_cli_gui.egg-info/top_level.txt +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/template.yml.url +0 -0
- {config_cli_gui-0.2.7/tests/example_project → config_cli_gui-0.2.9/tests}/__init__.py +0 -0
- {config_cli_gui-0.2.7/tests/example_project/cli → config_cli_gui-0.2.9/tests/example_project}/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/__main__.py +0 -0
- {config_cli_gui-0.2.7/tests/example_project/config → config_cli_gui-0.2.9/tests/example_project/cli}/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/cli/__main__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/cli/cli_example.py +0 -0
- {config_cli_gui-0.2.7/tests/example_project/core → config_cli_gui-0.2.9/tests/example_project/config}/__init__.py +0 -0
- {config_cli_gui-0.2.7/tests/example_project/gui → config_cli_gui-0.2.9/tests/example_project/core}/__init__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/core/base.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/core/logging.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/example.gpx +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/gui/__main__.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/gui/config.yaml +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/example_project/gui/gui_example.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/test_cli.py +0 -0
- {config_cli_gui-0.2.7 → config_cli_gui-0.2.9}/tests/test_generic_cli.py +0 -0
|
@@ -4,6 +4,22 @@ Changelog
|
|
|
4
4
|
|
|
5
5
|
(unreleased)
|
|
6
6
|
------------
|
|
7
|
+
- Spinbox for vector. [Paul Magister]
|
|
8
|
+
- Better example, make get_image_font sensitive to dpi, [Paul Magister]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
0.2.8 (2025-12-02)
|
|
12
|
+
------------------
|
|
13
|
+
- Docs: Update HISTORY.md for release 0.2.8. [Paul Magister]
|
|
14
|
+
- Refactoring: get_image_font will look for the actual font path in the
|
|
15
|
+
system. [Paul Magister]
|
|
16
|
+
- Font preview. [Paul Magister]
|
|
17
|
+
- Add font category in config.py. [Paul Magister]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
0.2.7 (2025-11-29)
|
|
21
|
+
------------------
|
|
22
|
+
- Docs: Update HISTORY.md for release 0.2.7. [Paul Magister]
|
|
7
23
|
- Also show required params in gui. [Paul Magister]
|
|
8
24
|
|
|
9
25
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: config-cli-gui
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.9
|
|
4
4
|
Summary: Feature-rich Python project template for config-cli-gui.
|
|
5
5
|
Author: pamagister
|
|
6
6
|
Requires-Python: <3.12,>=3.10
|
|
@@ -8,6 +8,7 @@ Description-Content-Type: text/markdown
|
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
Requires-Dist: pydantic>=2.11.7
|
|
10
10
|
Requires-Dist: pyyaml>=6.0.2
|
|
11
|
+
Requires-Dist: pillow>=12.0.0
|
|
11
12
|
Provides-Extra: dev
|
|
12
13
|
Requires-Dist: pytest>=8.4.0; extra == "dev"
|
|
13
14
|
Requires-Dist: pytest-mock>=3.14.1; extra == "dev"
|
|
@@ -80,40 +81,58 @@ Start by defining your application's configuration parameters in a central `conf
|
|
|
80
81
|
```python
|
|
81
82
|
# my_project/config_example.py
|
|
82
83
|
|
|
84
|
+
from datetime import datetime
|
|
85
|
+
from pathlib import Path
|
|
86
|
+
|
|
83
87
|
from config_cli_gui.config import (
|
|
84
88
|
ConfigCategory,
|
|
85
89
|
ConfigManager,
|
|
86
90
|
ConfigParameter,
|
|
87
91
|
)
|
|
92
|
+
from config_cli_gui.configtypes.color import Color
|
|
93
|
+
from config_cli_gui.configtypes.font import Font
|
|
94
|
+
from config_cli_gui.configtypes.vector import Vector
|
|
88
95
|
|
|
89
96
|
|
|
90
|
-
class
|
|
91
|
-
"""CLI-specific configuration parameters."""
|
|
92
|
-
|
|
97
|
+
class MiscConfig(ConfigCategory):
|
|
93
98
|
def get_category_name(self) -> str:
|
|
94
|
-
return "
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
help="Path to input (file or folder)",
|
|
101
|
-
required=True,
|
|
99
|
+
return "misc"
|
|
100
|
+
|
|
101
|
+
some_numeric: ConfigParameter = ConfigParameter(
|
|
102
|
+
name="some_numeric",
|
|
103
|
+
value=int(42),
|
|
104
|
+
help="Example integer",
|
|
102
105
|
is_cli=True,
|
|
103
106
|
)
|
|
104
107
|
|
|
105
|
-
|
|
106
|
-
name="
|
|
107
|
-
|
|
108
|
-
help="
|
|
109
|
-
is_cli=True,
|
|
108
|
+
some_vector: ConfigParameter = ConfigParameter(
|
|
109
|
+
name="some_vector",
|
|
110
|
+
value=Vector(1, 2, 3),
|
|
111
|
+
help="Example vector",
|
|
110
112
|
)
|
|
111
113
|
|
|
112
|
-
|
|
113
|
-
name="
|
|
114
|
-
|
|
115
|
-
help="
|
|
116
|
-
|
|
114
|
+
some_file: ConfigParameter = ConfigParameter(
|
|
115
|
+
name="some_file",
|
|
116
|
+
value=Path("some_file.txt"),
|
|
117
|
+
help="Path to the file to use",
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
some_color: ConfigParameter = ConfigParameter(
|
|
121
|
+
name="some_color",
|
|
122
|
+
value=Color(255, 0, 0),
|
|
123
|
+
help="Color setting for the application",
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
some_date: ConfigParameter = ConfigParameter(
|
|
127
|
+
name="some_date",
|
|
128
|
+
value=datetime.fromisoformat("2025-12-31 10:30:45"),
|
|
129
|
+
help="Date setting for the application",
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
some_font: ConfigParameter = ConfigParameter(
|
|
133
|
+
name="some_font",
|
|
134
|
+
value=Font("DejaVuSans.ttf", size=12, color=Color(0, 0, 255)),
|
|
135
|
+
help="Font setting for the application",
|
|
117
136
|
)
|
|
118
137
|
|
|
119
138
|
|
|
@@ -125,14 +144,14 @@ class AppConfig(ConfigCategory):
|
|
|
125
144
|
|
|
126
145
|
log_level: ConfigParameter = ConfigParameter(
|
|
127
146
|
name="log_level",
|
|
128
|
-
|
|
147
|
+
value="INFO",
|
|
129
148
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
130
149
|
help="Logging level for the application",
|
|
131
150
|
)
|
|
132
151
|
|
|
133
152
|
log_file_max_size: ConfigParameter = ConfigParameter(
|
|
134
153
|
name="log_file_max_size",
|
|
135
|
-
|
|
154
|
+
value=10,
|
|
136
155
|
help="Maximum log file size in MB before rotation",
|
|
137
156
|
)
|
|
138
157
|
|
|
@@ -140,11 +159,13 @@ class AppConfig(ConfigCategory):
|
|
|
140
159
|
class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
|
|
141
160
|
"""Main configuration manager that handles all parameter categories."""
|
|
142
161
|
|
|
143
|
-
|
|
144
|
-
|
|
162
|
+
app: AppConfig
|
|
163
|
+
misc: MiscConfig
|
|
164
|
+
|
|
145
165
|
def __init__(self, config_file: str | None = None, **kwargs):
|
|
146
166
|
"""Initialize the configuration manager with all parameter categories."""
|
|
147
|
-
|
|
167
|
+
categories = (MiscConfig(), AppConfig())
|
|
168
|
+
super().__init__(categories, config_file, **kwargs)
|
|
148
169
|
|
|
149
170
|
|
|
150
171
|
```
|
|
@@ -62,11 +62,11 @@ from datetime import datetime
|
|
|
62
62
|
from pathlib import Path
|
|
63
63
|
|
|
64
64
|
from config_cli_gui.config import (
|
|
65
|
-
Color,
|
|
66
65
|
ConfigCategory,
|
|
67
66
|
ConfigManager,
|
|
68
67
|
ConfigParameter,
|
|
69
68
|
)
|
|
69
|
+
from config_cli_gui.configtypes.color import Color
|
|
70
70
|
from config_cli_gui.docs import DocumentationGenerator
|
|
71
71
|
|
|
72
72
|
|
|
@@ -49,4 +49,15 @@ misc:
|
|
|
49
49
|
# Date setting for the application | type=datetime
|
|
50
50
|
some_date: '2025-12-31T10:30:45'
|
|
51
51
|
# Path to the file to use | type=PosixPath
|
|
52
|
-
some_file: some_file.txt
|
|
52
|
+
some_file: some_file.txt
|
|
53
|
+
# Font setting for the application | type=Font
|
|
54
|
+
some_font:
|
|
55
|
+
- DejaVuSans.ttf
|
|
56
|
+
- 12
|
|
57
|
+
- '#0000ff'
|
|
58
|
+
# Example integer | type=int
|
|
59
|
+
some_numeric: 42
|
|
60
|
+
# Example vector 2D | type=Vector
|
|
61
|
+
some_vector2d: (1, 2)
|
|
62
|
+
# Example vector 3D | type=Vector
|
|
63
|
+
some_vector3d: (1.1, 2.2, 3.3)
|
|
@@ -51,40 +51,58 @@ Start by defining your application's configuration parameters in a central `conf
|
|
|
51
51
|
```python
|
|
52
52
|
# my_project/config_example.py
|
|
53
53
|
|
|
54
|
+
from datetime import datetime
|
|
55
|
+
from pathlib import Path
|
|
56
|
+
|
|
54
57
|
from config_cli_gui.config import (
|
|
55
58
|
ConfigCategory,
|
|
56
59
|
ConfigManager,
|
|
57
60
|
ConfigParameter,
|
|
58
61
|
)
|
|
62
|
+
from config_cli_gui.configtypes.color import Color
|
|
63
|
+
from config_cli_gui.configtypes.font import Font
|
|
64
|
+
from config_cli_gui.configtypes.vector import Vector
|
|
59
65
|
|
|
60
66
|
|
|
61
|
-
class
|
|
62
|
-
"""CLI-specific configuration parameters."""
|
|
63
|
-
|
|
67
|
+
class MiscConfig(ConfigCategory):
|
|
64
68
|
def get_category_name(self) -> str:
|
|
65
|
-
return "
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
help="Path to input (file or folder)",
|
|
72
|
-
required=True,
|
|
69
|
+
return "misc"
|
|
70
|
+
|
|
71
|
+
some_numeric: ConfigParameter = ConfigParameter(
|
|
72
|
+
name="some_numeric",
|
|
73
|
+
value=int(42),
|
|
74
|
+
help="Example integer",
|
|
73
75
|
is_cli=True,
|
|
74
76
|
)
|
|
75
77
|
|
|
76
|
-
|
|
77
|
-
name="
|
|
78
|
-
|
|
79
|
-
help="
|
|
80
|
-
is_cli=True,
|
|
78
|
+
some_vector: ConfigParameter = ConfigParameter(
|
|
79
|
+
name="some_vector",
|
|
80
|
+
value=Vector(1, 2, 3),
|
|
81
|
+
help="Example vector",
|
|
81
82
|
)
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
name="
|
|
85
|
-
|
|
86
|
-
help="
|
|
87
|
-
|
|
84
|
+
some_file: ConfigParameter = ConfigParameter(
|
|
85
|
+
name="some_file",
|
|
86
|
+
value=Path("some_file.txt"),
|
|
87
|
+
help="Path to the file to use",
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
some_color: ConfigParameter = ConfigParameter(
|
|
91
|
+
name="some_color",
|
|
92
|
+
value=Color(255, 0, 0),
|
|
93
|
+
help="Color setting for the application",
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
some_date: ConfigParameter = ConfigParameter(
|
|
97
|
+
name="some_date",
|
|
98
|
+
value=datetime.fromisoformat("2025-12-31 10:30:45"),
|
|
99
|
+
help="Date setting for the application",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
some_font: ConfigParameter = ConfigParameter(
|
|
103
|
+
name="some_font",
|
|
104
|
+
value=Font("DejaVuSans.ttf", size=12, color=Color(0, 0, 255)),
|
|
105
|
+
help="Font setting for the application",
|
|
88
106
|
)
|
|
89
107
|
|
|
90
108
|
|
|
@@ -96,14 +114,14 @@ class AppConfig(ConfigCategory):
|
|
|
96
114
|
|
|
97
115
|
log_level: ConfigParameter = ConfigParameter(
|
|
98
116
|
name="log_level",
|
|
99
|
-
|
|
117
|
+
value="INFO",
|
|
100
118
|
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
|
|
101
119
|
help="Logging level for the application",
|
|
102
120
|
)
|
|
103
121
|
|
|
104
122
|
log_file_max_size: ConfigParameter = ConfigParameter(
|
|
105
123
|
name="log_file_max_size",
|
|
106
|
-
|
|
124
|
+
value=10,
|
|
107
125
|
help="Maximum log file size in MB before rotation",
|
|
108
126
|
)
|
|
109
127
|
|
|
@@ -111,11 +129,13 @@ class AppConfig(ConfigCategory):
|
|
|
111
129
|
class ProjectConfigManager(ConfigManager): # Inherit from ConfigManager
|
|
112
130
|
"""Main configuration manager that handles all parameter categories."""
|
|
113
131
|
|
|
114
|
-
|
|
115
|
-
|
|
132
|
+
app: AppConfig
|
|
133
|
+
misc: MiscConfig
|
|
134
|
+
|
|
116
135
|
def __init__(self, config_file: str | None = None, **kwargs):
|
|
117
136
|
"""Initialize the configuration manager with all parameter categories."""
|
|
118
|
-
|
|
137
|
+
categories = (MiscConfig(), AppConfig())
|
|
138
|
+
super().__init__(categories, config_file, **kwargs)
|
|
119
139
|
|
|
120
140
|
|
|
121
141
|
```
|
|
@@ -41,9 +41,13 @@ The parameters in the cli category can be accessed via the command line interfac
|
|
|
41
41
|
|
|
42
42
|
## Category "misc"
|
|
43
43
|
|
|
44
|
-
| Name
|
|
45
|
-
|
|
46
|
-
|
|
|
47
|
-
|
|
|
48
|
-
|
|
|
44
|
+
| Name | Type | Description | Default | Choices |
|
|
45
|
+
|---------------|-----------|-----------------------------------|--------------------------------------------------------------|---------|
|
|
46
|
+
| some_numeric | int | Example integer | 42 | - |
|
|
47
|
+
| some_vector2d | Vector | Example vector 2D | Vector(1, 2) | - |
|
|
48
|
+
| some_vector3d | Vector | Example vector 3D | Vector(1.1, 2.2, 3.3) | - |
|
|
49
|
+
| some_file | PosixPath | Path to the file to use | PosixPath('some_file.txt') | - |
|
|
50
|
+
| some_color | Color | Color setting for the application | Color(255, 0, 0) | - |
|
|
51
|
+
| some_date | datetime | Date setting for the application | datetime.datetime(2025, 12, 31, 10, 30, 45) | - |
|
|
52
|
+
| some_font | Font | Font setting for the application | Font(type='DejaVuSans.ttf', size=12, color=Color(0, 0, 255)) | - |
|
|
49
53
|
|
|
@@ -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.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.9'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 9)
|
|
33
33
|
|
|
34
|
-
__commit_id__ = commit_id = '
|
|
34
|
+
__commit_id__ = commit_id = 'gc34b684af'
|
|
@@ -8,83 +8,9 @@ from typing import Any
|
|
|
8
8
|
import yaml
|
|
9
9
|
from pydantic import BaseModel
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def __init__(self, x: int | float, y: int | float, z: int | float | None = None):
|
|
16
|
-
self.x = x
|
|
17
|
-
self.y = y
|
|
18
|
-
self.z = z
|
|
19
|
-
|
|
20
|
-
def to_list(self) -> list[int]:
|
|
21
|
-
return [self.x, self.y, self.z] if self.z is not None else [self.x, self.y]
|
|
22
|
-
|
|
23
|
-
@classmethod
|
|
24
|
-
def from_list(cls, coordinate: list[int | str | float]) -> "Vector":
|
|
25
|
-
if len(coordinate) == 2:
|
|
26
|
-
return cls(float(coordinate[0]), float(coordinate[1]))
|
|
27
|
-
if len(coordinate) >= 3:
|
|
28
|
-
return cls(float(coordinate[0]), float(coordinate[1]), float(coordinate[2]))
|
|
29
|
-
return cls()
|
|
30
|
-
|
|
31
|
-
@classmethod
|
|
32
|
-
def from_str(cls, coordinate: str) -> "Vector":
|
|
33
|
-
return cls.from_list(coordinate.strip("()[]").split(","))
|
|
34
|
-
|
|
35
|
-
def to_str(self) -> str:
|
|
36
|
-
return f"({self.x}, {self.y}, {self.z})" if self.z is not None else f"({self.x}, {self.y})" # type: ignore
|
|
37
|
-
|
|
38
|
-
def __str__(self):
|
|
39
|
-
return self.to_str()
|
|
40
|
-
|
|
41
|
-
def __repr__(self):
|
|
42
|
-
return f"Vector{str(self)}"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
class Color:
|
|
46
|
-
"""Simple color class for RGB values."""
|
|
47
|
-
|
|
48
|
-
def __init__(self, r: int = 0, g: int = 0, b: int = 0):
|
|
49
|
-
self.r = max(0, min(255, r))
|
|
50
|
-
self.g = max(0, min(255, g))
|
|
51
|
-
self.b = max(0, min(255, b))
|
|
52
|
-
|
|
53
|
-
def to_list(self) -> list[int]:
|
|
54
|
-
return [self.r, self.g, self.b]
|
|
55
|
-
|
|
56
|
-
def to_rgb(self) -> tuple[float]:
|
|
57
|
-
return (self.r / 255, self.g / 255, self.b / 255)
|
|
58
|
-
|
|
59
|
-
def to_pil(self) -> tuple[int, ...]:
|
|
60
|
-
"""Convert Color object to Pillow-compatible RGB tuple."""
|
|
61
|
-
return tuple(int(c) for c in self.to_list())
|
|
62
|
-
|
|
63
|
-
def to_hex(self) -> str:
|
|
64
|
-
return f"#{self.r:02x}{self.g:02x}{self.b:02x}"
|
|
65
|
-
|
|
66
|
-
@classmethod
|
|
67
|
-
def from_list(cls, rgb_list: list[int | str]) -> "Color":
|
|
68
|
-
if len(rgb_list) >= 3:
|
|
69
|
-
return cls(int(rgb_list[0]), int(rgb_list[1]), int(rgb_list[2]))
|
|
70
|
-
return cls()
|
|
71
|
-
|
|
72
|
-
@classmethod
|
|
73
|
-
def from_hex(cls, hex_color: str) -> "Color":
|
|
74
|
-
hex_color = hex_color.lstrip("#")
|
|
75
|
-
if len(hex_color) == 6:
|
|
76
|
-
return cls(
|
|
77
|
-
int(hex_color[0:2], 16),
|
|
78
|
-
int(hex_color[2:4], 16),
|
|
79
|
-
int(hex_color[4:6], 16),
|
|
80
|
-
)
|
|
81
|
-
return cls()
|
|
82
|
-
|
|
83
|
-
def __str__(self):
|
|
84
|
-
return self.to_hex()
|
|
85
|
-
|
|
86
|
-
def __repr__(self):
|
|
87
|
-
return f"Color({self.r}, {self.g}, {self.b})"
|
|
11
|
+
from config_cli_gui.configtypes.color import Color
|
|
12
|
+
from config_cli_gui.configtypes.font import Font
|
|
13
|
+
from config_cli_gui.configtypes.vector import Vector
|
|
88
14
|
|
|
89
15
|
|
|
90
16
|
@dataclass
|
|
@@ -197,6 +123,8 @@ class ConfigManager:
|
|
|
197
123
|
continue
|
|
198
124
|
|
|
199
125
|
# Type conversions
|
|
126
|
+
if isinstance(param.value, Font) and isinstance(param_value, list):
|
|
127
|
+
param_value = Font.from_list(param_value)
|
|
200
128
|
if isinstance(param.value, Color) and isinstance(param_value, list):
|
|
201
129
|
param_value = Color.from_list(param_value)
|
|
202
130
|
if isinstance(param.value, Color) and isinstance(param_value, str):
|
|
@@ -237,7 +165,9 @@ class ConfigManager:
|
|
|
237
165
|
result[category_name] = {}
|
|
238
166
|
for param in category.get_parameters():
|
|
239
167
|
val = getattr(category, param.name).value
|
|
240
|
-
if isinstance(val,
|
|
168
|
+
if isinstance(val, Font):
|
|
169
|
+
val = val.to_list()
|
|
170
|
+
elif isinstance(val, Color):
|
|
241
171
|
val = val.to_hex()
|
|
242
172
|
elif isinstance(val, Vector):
|
|
243
173
|
val = str(val.to_str())
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class Color:
|
|
2
|
+
"""Simple color class for RGB values."""
|
|
3
|
+
|
|
4
|
+
def __init__(self, r: int = 0, g: int = 0, b: int = 0):
|
|
5
|
+
self.r = max(0, min(255, r))
|
|
6
|
+
self.g = max(0, min(255, g))
|
|
7
|
+
self.b = max(0, min(255, b))
|
|
8
|
+
|
|
9
|
+
def to_list(self) -> list[int]:
|
|
10
|
+
return [self.r, self.g, self.b]
|
|
11
|
+
|
|
12
|
+
def to_rgb(self) -> tuple[float, float, float]:
|
|
13
|
+
return self.r / 255, self.g / 255, self.b / 255
|
|
14
|
+
|
|
15
|
+
def to_pil(self) -> tuple[int, ...]:
|
|
16
|
+
"""Convert Color object to Pillow-compatible RGB tuple."""
|
|
17
|
+
return tuple(int(c) for c in self.to_list())
|
|
18
|
+
|
|
19
|
+
def to_hex(self) -> str:
|
|
20
|
+
return f"#{self.r:02x}{self.g:02x}{self.b:02x}"
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_list(cls, rgb_list: list[int | str]) -> "Color":
|
|
24
|
+
if len(rgb_list) >= 3:
|
|
25
|
+
return cls(int(rgb_list[0]), int(rgb_list[1]), int(rgb_list[2]))
|
|
26
|
+
return cls()
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def from_hex(cls, hex_color: str) -> "Color":
|
|
30
|
+
hex_color = hex_color.lstrip("#")
|
|
31
|
+
if len(hex_color) == 6:
|
|
32
|
+
return cls(
|
|
33
|
+
int(hex_color[0:2], 16),
|
|
34
|
+
int(hex_color[2:4], 16),
|
|
35
|
+
int(hex_color[4:6], 16),
|
|
36
|
+
)
|
|
37
|
+
return cls()
|
|
38
|
+
|
|
39
|
+
def __str__(self):
|
|
40
|
+
return self.to_hex()
|
|
41
|
+
|
|
42
|
+
def __repr__(self):
|
|
43
|
+
return f"Color({self.r}, {self.g}, {self.b})"
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from PIL import ImageFont
|
|
6
|
+
|
|
7
|
+
from config_cli_gui.configtypes.color import Color
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def list_system_fonts() -> list[str]:
|
|
11
|
+
font_dirs = [
|
|
12
|
+
"/usr/share/fonts",
|
|
13
|
+
"/usr/local/share/fonts",
|
|
14
|
+
str(Path.home() / ".fonts"),
|
|
15
|
+
"/Library/Fonts",
|
|
16
|
+
"/System/Library/Fonts",
|
|
17
|
+
"C:/Windows/Fonts",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
fonts: list[str] = []
|
|
21
|
+
for d in font_dirs:
|
|
22
|
+
if os.path.isdir(d):
|
|
23
|
+
for root, _, files in os.walk(d):
|
|
24
|
+
for f in files:
|
|
25
|
+
if f.lower().endswith((".ttf", ".otf")):
|
|
26
|
+
fonts.append(os.path.join(root, f))
|
|
27
|
+
return fonts
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class Font:
|
|
31
|
+
"""Represents a font with type, size and color."""
|
|
32
|
+
|
|
33
|
+
# Klassenattribute nach Klassendefinition setzen
|
|
34
|
+
font_files = list_system_fonts()
|
|
35
|
+
font_names = sorted([os.path.basename(f) for f in font_files])
|
|
36
|
+
font_files_sorted = sorted(font_files, key=os.path.basename)
|
|
37
|
+
|
|
38
|
+
def __init__(self, font_type: str, size: float, color: "Color"):
|
|
39
|
+
self.name = font_type
|
|
40
|
+
self.size = size
|
|
41
|
+
self.color = color
|
|
42
|
+
|
|
43
|
+
def to_list(self) -> list[Any]:
|
|
44
|
+
return [self.name, self.size, self.color.to_hex()]
|
|
45
|
+
|
|
46
|
+
@classmethod
|
|
47
|
+
def from_list(cls, font_data: list[Any]) -> "Font":
|
|
48
|
+
if len(font_data) < 3:
|
|
49
|
+
return cls("Arial", 12, Color(0, 0, 0))
|
|
50
|
+
|
|
51
|
+
font_type, size, color_val = font_data
|
|
52
|
+
color = (
|
|
53
|
+
Color.from_hex(color_val) if isinstance(color_val, str) else Color.from_list(color_val)
|
|
54
|
+
)
|
|
55
|
+
return cls(str(font_type), float(size), color)
|
|
56
|
+
|
|
57
|
+
def get_image_font(self, dpi=25.4) -> ImageFont.FreeTypeFont:
|
|
58
|
+
"""
|
|
59
|
+
Return a PIL FreeTypeFont, with fallback to default.
|
|
60
|
+
|
|
61
|
+
:param dpi: if dpi is provided, the font size is re-calculated on base of the dpi
|
|
62
|
+
:return:
|
|
63
|
+
"""
|
|
64
|
+
try:
|
|
65
|
+
if self.name in self.font_names:
|
|
66
|
+
idx = self.font_names.index(self.name)
|
|
67
|
+
path = self.font_files_sorted[idx]
|
|
68
|
+
size = self.size * dpi / 25.4
|
|
69
|
+
return ImageFont.truetype(path, size)
|
|
70
|
+
except Exception as e:
|
|
71
|
+
print(f"Fehler beim Laden der Schrift '{self.name}': {e}")
|
|
72
|
+
|
|
73
|
+
print("Fallback: Nutze Default-Font.")
|
|
74
|
+
return ImageFont.load_default()
|
|
75
|
+
|
|
76
|
+
def __repr__(self) -> str:
|
|
77
|
+
return f"Font(type='{self.name}', size={self.size}, color={self.color!r})"
|
|
78
|
+
|
|
79
|
+
def __str__(self) -> str:
|
|
80
|
+
return f"{self.name}, {self.size}pt, {self.color}"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
class Vector:
|
|
2
|
+
"""Class that represents a vector or point in 2D or 3D"""
|
|
3
|
+
|
|
4
|
+
def __init__(self, x: int | float, y: int | float, z: int | float | None = None):
|
|
5
|
+
self.x = x
|
|
6
|
+
self.y = y
|
|
7
|
+
self.z = z
|
|
8
|
+
|
|
9
|
+
def to_list(self) -> list[int]:
|
|
10
|
+
return [self.x, self.y, self.z] if self.z is not None else [self.x, self.y]
|
|
11
|
+
|
|
12
|
+
@classmethod
|
|
13
|
+
def from_list(cls, coordinate: list[int | str | float]) -> "Vector":
|
|
14
|
+
if len(coordinate) == 2:
|
|
15
|
+
return cls(float(coordinate[0]), float(coordinate[1]))
|
|
16
|
+
if len(coordinate) >= 3:
|
|
17
|
+
return cls(float(coordinate[0]), float(coordinate[1]), float(coordinate[2]))
|
|
18
|
+
return cls()
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def from_str(cls, coordinate: str) -> "Vector":
|
|
22
|
+
return cls.from_list(coordinate.strip("()[]").split(","))
|
|
23
|
+
|
|
24
|
+
def to_str(self) -> str:
|
|
25
|
+
return f"({self.x}, {self.y}, {self.z})" if self.z is not None else f"({self.x}, {self.y})" # type: ignore
|
|
26
|
+
|
|
27
|
+
def __str__(self):
|
|
28
|
+
return self.to_str()
|
|
29
|
+
|
|
30
|
+
def __repr__(self):
|
|
31
|
+
return f"Vector{str(self)}"
|