configui 1.0.0__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.
- configui-1.0.0/.github/CODEOWNERS +1 -0
- configui-1.0.0/.github/workflows/release.yml +32 -0
- configui-1.0.0/.github/workflows/tests.yml +44 -0
- configui-1.0.0/.gitignore +225 -0
- configui-1.0.0/AGENTS.md +253 -0
- configui-1.0.0/LICENSE +21 -0
- configui-1.0.0/PKG-INFO +82 -0
- configui-1.0.0/PM/design_doc.md +83 -0
- configui-1.0.0/PM/tasks/CUI-101.md +12 -0
- configui-1.0.0/PM/tasks/CUI-201.md +57 -0
- configui-1.0.0/PM/tasks/CUI-202.md +49 -0
- configui-1.0.0/PM/tasks/CUI-301.md +123 -0
- configui-1.0.0/PM/tasks/CUI-302.md +83 -0
- configui-1.0.0/PM/tasks/CUI-303.md +27 -0
- configui-1.0.0/PM/tasks/CUI-304.md +169 -0
- configui-1.0.0/PM/tasks/CUI-401.md +92 -0
- configui-1.0.0/PM/tasks/CUI-402.md +142 -0
- configui-1.0.0/PM/tasks/CUI-501.md +64 -0
- configui-1.0.0/PM/tasks/CUI-502.md +60 -0
- configui-1.0.0/README.md +67 -0
- configui-1.0.0/_assets/ConfigUI_screenshot.svg +184 -0
- configui-1.0.0/pyproject.toml +40 -0
- configui-1.0.0/requirements.txt +66 -0
- configui-1.0.0/samples/training_config.json +48 -0
- configui-1.0.0/samples/training_config.toml +38 -0
- configui-1.0.0/samples/training_config.yaml +41 -0
- configui-1.0.0/src/configui/__about__.py +1 -0
- configui-1.0.0/src/configui/__init__.py +3 -0
- configui-1.0.0/src/configui/__main__.py +4 -0
- configui-1.0.0/src/configui/config/__init__.py +7 -0
- configui-1.0.0/src/configui/config/_atomic.py +49 -0
- configui-1.0.0/src/configui/config/_protocol.py +18 -0
- configui-1.0.0/src/configui/config/formats.py +37 -0
- configui-1.0.0/src/configui/config/json_config.py +37 -0
- configui-1.0.0/src/configui/config/toml_config.py +39 -0
- configui-1.0.0/src/configui/config/yaml_config.py +47 -0
- configui-1.0.0/src/configui/tui/__init__.py +0 -0
- configui-1.0.0/src/configui/tui/app.py +347 -0
- configui-1.0.0/src/configui/tui/cli.py +14 -0
- configui-1.0.0/src/configui/tui/collector.py +70 -0
- configui-1.0.0/src/configui/tui/screens.py +178 -0
- configui-1.0.0/src/configui/tui/widgets.py +108 -0
- configui-1.0.0/tests/__init__.py +0 -0
- configui-1.0.0/tests/test_config/__init__.py +0 -0
- configui-1.0.0/tests/test_config/test_atomic.py +132 -0
- configui-1.0.0/tests/test_config/test_formats.py +58 -0
- configui-1.0.0/tests/test_config/test_json_config.py +125 -0
- configui-1.0.0/tests/test_config/test_protocol.py +28 -0
- configui-1.0.0/tests/test_config/test_toml_config.py +120 -0
- configui-1.0.0/tests/test_config/test_yaml_config.py +132 -0
- configui-1.0.0/tests/test_import.py +8 -0
- configui-1.0.0/tests/test_tui/__init__.py +0 -0
- configui-1.0.0/tests/test_tui/test_app.py +393 -0
- configui-1.0.0/tests/test_tui/test_collector.py +186 -0
- configui-1.0.0/tests/test_tui/test_widgets.py +240 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
* @ChenchaoZhao
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: release
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- v*
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
publish:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
permissions:
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v4
|
|
15
|
+
|
|
16
|
+
- uses: actions/setup-python@v5
|
|
17
|
+
with:
|
|
18
|
+
python-version: "3.12"
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
run: pip install uv
|
|
22
|
+
|
|
23
|
+
- name: Install hatch
|
|
24
|
+
run: pip install hatch
|
|
25
|
+
|
|
26
|
+
- name: Build
|
|
27
|
+
run: hatch build
|
|
28
|
+
|
|
29
|
+
- name: Publish to PyPI
|
|
30
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
31
|
+
with:
|
|
32
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
name: unit tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- main
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
strategy:
|
|
15
|
+
matrix:
|
|
16
|
+
python-version: ["3.12", "3.13"]
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout code
|
|
19
|
+
uses: actions/checkout@v4
|
|
20
|
+
|
|
21
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
22
|
+
uses: actions/setup-python@v4
|
|
23
|
+
with:
|
|
24
|
+
python-version: ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install uv
|
|
27
|
+
run: pip install uv
|
|
28
|
+
|
|
29
|
+
- name: Install hatch
|
|
30
|
+
run: pip install hatch
|
|
31
|
+
|
|
32
|
+
- name: Install pip compile
|
|
33
|
+
run: pip install hatch-pip-compile
|
|
34
|
+
|
|
35
|
+
- name: Run tests with coverage
|
|
36
|
+
run: hatch run release
|
|
37
|
+
|
|
38
|
+
- name: Upload coverage data
|
|
39
|
+
uses: actions/upload-artifact@v4
|
|
40
|
+
with:
|
|
41
|
+
name: coverage-${{ matrix.python-version }}
|
|
42
|
+
path: .coverage*
|
|
43
|
+
include-hidden-files: true
|
|
44
|
+
if-no-files-found: warn
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
.hypothesis/
|
|
51
|
+
.pytest_cache/
|
|
52
|
+
cover/
|
|
53
|
+
|
|
54
|
+
# Translations
|
|
55
|
+
*.mo
|
|
56
|
+
*.pot
|
|
57
|
+
|
|
58
|
+
# Django stuff:
|
|
59
|
+
*.log
|
|
60
|
+
local_settings.py
|
|
61
|
+
db.sqlite3
|
|
62
|
+
db.sqlite3-journal
|
|
63
|
+
|
|
64
|
+
# Flask stuff:
|
|
65
|
+
instance/
|
|
66
|
+
.webassets-cache
|
|
67
|
+
|
|
68
|
+
# Scrapy stuff:
|
|
69
|
+
.scrapy
|
|
70
|
+
|
|
71
|
+
# Sphinx documentation
|
|
72
|
+
docs/_build/
|
|
73
|
+
|
|
74
|
+
# PyBuilder
|
|
75
|
+
.pybuilder/
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
87
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
88
|
+
# .python-version
|
|
89
|
+
|
|
90
|
+
# pipenv
|
|
91
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
92
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
93
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
94
|
+
# install all needed dependencies.
|
|
95
|
+
# Pipfile.lock
|
|
96
|
+
|
|
97
|
+
# UV
|
|
98
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
99
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
100
|
+
# commonly ignored for libraries.
|
|
101
|
+
# uv.lock
|
|
102
|
+
|
|
103
|
+
# poetry
|
|
104
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
105
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
106
|
+
# commonly ignored for libraries.
|
|
107
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
108
|
+
# poetry.lock
|
|
109
|
+
# poetry.toml
|
|
110
|
+
|
|
111
|
+
# pdm
|
|
112
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
113
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
114
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
115
|
+
# pdm.lock
|
|
116
|
+
# pdm.toml
|
|
117
|
+
.pdm-python
|
|
118
|
+
.pdm-build/
|
|
119
|
+
|
|
120
|
+
# pixi
|
|
121
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
122
|
+
# pixi.lock
|
|
123
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
124
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
125
|
+
.pixi
|
|
126
|
+
|
|
127
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
128
|
+
__pypackages__/
|
|
129
|
+
|
|
130
|
+
# Celery stuff
|
|
131
|
+
celerybeat-schedule
|
|
132
|
+
celerybeat.pid
|
|
133
|
+
|
|
134
|
+
# Redis
|
|
135
|
+
*.rdb
|
|
136
|
+
*.aof
|
|
137
|
+
*.pid
|
|
138
|
+
|
|
139
|
+
# RabbitMQ
|
|
140
|
+
mnesia/
|
|
141
|
+
rabbitmq/
|
|
142
|
+
rabbitmq-data/
|
|
143
|
+
|
|
144
|
+
# ActiveMQ
|
|
145
|
+
activemq-data/
|
|
146
|
+
|
|
147
|
+
# SageMath parsed files
|
|
148
|
+
*.sage.py
|
|
149
|
+
|
|
150
|
+
# Environments
|
|
151
|
+
.env
|
|
152
|
+
.envrc
|
|
153
|
+
.venv
|
|
154
|
+
env/
|
|
155
|
+
venv/
|
|
156
|
+
ENV/
|
|
157
|
+
env.bak/
|
|
158
|
+
venv.bak/
|
|
159
|
+
|
|
160
|
+
# Spyder project settings
|
|
161
|
+
.spyderproject
|
|
162
|
+
.spyproject
|
|
163
|
+
|
|
164
|
+
# Rope project settings
|
|
165
|
+
.ropeproject
|
|
166
|
+
|
|
167
|
+
# mkdocs documentation
|
|
168
|
+
/site
|
|
169
|
+
|
|
170
|
+
# mypy
|
|
171
|
+
.mypy_cache/
|
|
172
|
+
.dmypy.json
|
|
173
|
+
dmypy.json
|
|
174
|
+
|
|
175
|
+
# Pyre type checker
|
|
176
|
+
.pyre/
|
|
177
|
+
|
|
178
|
+
# pytype static type analyzer
|
|
179
|
+
.pytype/
|
|
180
|
+
|
|
181
|
+
# Cython debug symbols
|
|
182
|
+
cython_debug/
|
|
183
|
+
|
|
184
|
+
# PyCharm
|
|
185
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
186
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
187
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
188
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
189
|
+
# .idea/
|
|
190
|
+
|
|
191
|
+
# Abstra
|
|
192
|
+
# Abstra is an AI-powered process automation framework.
|
|
193
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
194
|
+
# Learn more at https://abstra.io/docs
|
|
195
|
+
.abstra/
|
|
196
|
+
|
|
197
|
+
# Visual Studio Code
|
|
198
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore
|
|
199
|
+
# that can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
200
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer,
|
|
201
|
+
# you could uncomment the following to ignore the entire vscode folder
|
|
202
|
+
# .vscode/
|
|
203
|
+
# Temporary file for partial code execution
|
|
204
|
+
tempCodeRunnerFile.py
|
|
205
|
+
|
|
206
|
+
# Ruff stuff:
|
|
207
|
+
.ruff_cache/
|
|
208
|
+
|
|
209
|
+
# macOS
|
|
210
|
+
.DS_Store
|
|
211
|
+
|
|
212
|
+
# Hatch
|
|
213
|
+
.lock
|
|
214
|
+
hatch.lock
|
|
215
|
+
|
|
216
|
+
# PyPI configuration file
|
|
217
|
+
.pypirc
|
|
218
|
+
|
|
219
|
+
# Marimo
|
|
220
|
+
marimo/_static/
|
|
221
|
+
marimo/_lsp/
|
|
222
|
+
__marimo__/
|
|
223
|
+
|
|
224
|
+
# Streamlit
|
|
225
|
+
.streamlit/secrets.toml
|
configui-1.0.0/AGENTS.md
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Initial Exploration
|
|
4
|
+
|
|
5
|
+
Before writing any code, explore the project structure and understand the conventions:
|
|
6
|
+
|
|
7
|
+
### Read First (Priority Order)
|
|
8
|
+
|
|
9
|
+
1. **`pyproject.toml`** — Single source of truth for all configuration
|
|
10
|
+
2. **`README.md`** — Project overview and setup instructions
|
|
11
|
+
3. **`AGENTS.md`** — Agent-specific instructions if it exists
|
|
12
|
+
|
|
13
|
+
### Extract Key Configuration
|
|
14
|
+
|
|
15
|
+
From `pyproject.toml`, identify:
|
|
16
|
+
|
|
17
|
+
| Setting | Location |
|
|
18
|
+
| ---------------- | ------------------------------------- |
|
|
19
|
+
| Package name | `[project].name` |
|
|
20
|
+
| Python version | `[project].requires-python` |
|
|
21
|
+
| Source directory | `[tool.hatch.build.targets.wheel]` |
|
|
22
|
+
| Test directory | `[tool.pytest.ini_options].testpaths` |
|
|
23
|
+
| Max line length | `[tool.ruff].line-length` |
|
|
24
|
+
| Mypy config | `[tool.mypy]` |
|
|
25
|
+
|
|
26
|
+
### Common Patterns to Match
|
|
27
|
+
|
|
28
|
+
- Import style and organization
|
|
29
|
+
- Type annotation conventions
|
|
30
|
+
- Naming conventions (modules, classes, functions)
|
|
31
|
+
- Error handling patterns
|
|
32
|
+
- Documentation approach
|
|
33
|
+
|
|
34
|
+
## Toolchain Standard
|
|
35
|
+
|
|
36
|
+
Standard development commands (verify in `pyproject.toml`):
|
|
37
|
+
|
|
38
|
+
- `hatch fmt` — Format + lint (ruff)
|
|
39
|
+
- `hatch test` — Run tests (pytest)
|
|
40
|
+
- `hatch run typing` — Type check (mypy)
|
|
41
|
+
- `hatch run release` — fmt + typing + test
|
|
42
|
+
|
|
43
|
+
### Tool Purposes
|
|
44
|
+
|
|
45
|
+
Ask human to install those tools if they are not installed yet.
|
|
46
|
+
|
|
47
|
+
| Tool | Purpose |
|
|
48
|
+
|------|---------|
|
|
49
|
+
| **hatch** | Project and environment management |
|
|
50
|
+
| **uv** | Fast dependency resolution |
|
|
51
|
+
| **ruff** | Linting and formatting |
|
|
52
|
+
| **mypy** | Static type checking |
|
|
53
|
+
| **pytest** | Test execution |
|
|
54
|
+
|
|
55
|
+
## Behavioral Guidelines
|
|
56
|
+
|
|
57
|
+
### Think Before Coding
|
|
58
|
+
|
|
59
|
+
- State assumptions explicitly. If uncertain, ask.
|
|
60
|
+
- If multiple interpretations exist, present them — don't pick silently.
|
|
61
|
+
- If a simpler approach exists, say so.
|
|
62
|
+
- If something is unclear, stop and ask.
|
|
63
|
+
|
|
64
|
+
### Simplicity First
|
|
65
|
+
|
|
66
|
+
- No features beyond what was asked.
|
|
67
|
+
- No abstractions for single-use code.
|
|
68
|
+
- No "flexibility" that wasn't requested.
|
|
69
|
+
- If you write 200 lines and it could be 50, rewrite it.
|
|
70
|
+
|
|
71
|
+
### Surgical Changes
|
|
72
|
+
|
|
73
|
+
- Touch only what you must.
|
|
74
|
+
- Don't "improve" adjacent code.
|
|
75
|
+
- Match existing style, even if you'd do it differently.
|
|
76
|
+
- Clean up only YOUR changes' orphans.
|
|
77
|
+
|
|
78
|
+
### Goal-Driven Execution
|
|
79
|
+
|
|
80
|
+
- Define verifiable success criteria:
|
|
81
|
+
- "Add validation" → "Write tests for invalid inputs, then make them pass"
|
|
82
|
+
- "Fix the bug" → "Write a test that reproduces it, then make it pass"
|
|
83
|
+
- "Refactor X" → "Ensure tests pass before and after"
|
|
84
|
+
|
|
85
|
+
### Additional Pythonic Behaviors
|
|
86
|
+
|
|
87
|
+
- Follow the **Zen of Python** (`import this`):
|
|
88
|
+
- Explicit is better than implicit.
|
|
89
|
+
- Simple is better than complex.
|
|
90
|
+
- Readability counts.
|
|
91
|
+
- If the implementation is hard to explain, it's a bad idea.
|
|
92
|
+
- **Flat over nested.** Prefer early returns and guard clauses over deeply indented logic.
|
|
93
|
+
- **One thing per function.** A function should do exactly what its name says.
|
|
94
|
+
- **Name things well.** A good name is worth more than a comment.
|
|
95
|
+
|
|
96
|
+
## Code Conventions
|
|
97
|
+
|
|
98
|
+
### No Magic Numbers
|
|
99
|
+
|
|
100
|
+
Define default constants at module top in `UPPER_SNAKE_CASE` with explicit types. Use these constants in function signatures, `dataclass` defaults or doc strings instead of hard-coding values.
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
DEFAULT_INIT_TIMEOUT_SECONDS: int = 300
|
|
104
|
+
|
|
105
|
+
def init(timeout: int = DEFAULT_INIT_TIMEOUT_SECONDS) -> None: ...
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
In tests, import constants to assert default values:
|
|
109
|
+
|
|
110
|
+
```python
|
|
111
|
+
from mypackage.some_module import DEFAULT_BATCH_SIZE
|
|
112
|
+
|
|
113
|
+
def test_default_batch_size():
|
|
114
|
+
assert config.batch_size == DEFAULT_BATCH_SIZE
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Docstring Defaults
|
|
118
|
+
|
|
119
|
+
Use string templating to keep docstrings in sync with defaults:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
DEFAULT_LR: float = 8e-4
|
|
123
|
+
|
|
124
|
+
_OPTIMIZER_CONFIG_DOC = f"Learning rate (Defaults to {DEFAULT_LR})"
|
|
125
|
+
|
|
126
|
+
@dataclass
|
|
127
|
+
class OptimizerConfig:
|
|
128
|
+
__doc__ = _OPTIMIZER_CONFIG_DOC
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### Magic and One-Liners
|
|
132
|
+
|
|
133
|
+
Occasional clever code is acceptable when it meaningfully improves performance or reduces boilerplate — but it **must** have a docstring or inline comment explaining what it does and why.
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
# Good — magic with explanation
|
|
137
|
+
class Registry:
|
|
138
|
+
"""
|
|
139
|
+
Uses __init_subclass__ to auto-register subclasses by name.
|
|
140
|
+
This avoids manual registration boilerplate in every subclass.
|
|
141
|
+
"""
|
|
142
|
+
_registry: dict[str, type] = {}
|
|
143
|
+
|
|
144
|
+
def __init_subclass__(cls, **kwargs: object) -> None:
|
|
145
|
+
super().__init_subclass__(**kwargs)
|
|
146
|
+
Registry._registry[cls.__name__] = cls
|
|
147
|
+
|
|
148
|
+
# Bad — clever with no explanation
|
|
149
|
+
return {k: v for d in maps for k, v in d.items() if v is not None}
|
|
150
|
+
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Enum is Preferred
|
|
154
|
+
|
|
155
|
+
Enums are better than arbitrary string inputs
|
|
156
|
+
|
|
157
|
+
```python
|
|
158
|
+
class SchedulerNameEnum(StrEnum):
|
|
159
|
+
LINEAR = auto()
|
|
160
|
+
COSINE = auto()
|
|
161
|
+
CONSTANT = auto()
|
|
162
|
+
|
|
163
|
+
# automatic validation
|
|
164
|
+
string_input = "linear"
|
|
165
|
+
scheduler_name = SchedulerNameEnum(string_input)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Type Annotations
|
|
169
|
+
|
|
170
|
+
- Annotate ALL function signatures (parameters and return types)
|
|
171
|
+
- Use `TypeAlias` and `NewType` over bare primitives when semantic meaning matters
|
|
172
|
+
- Fix `mypy` errors; do not silence with `# type: ignore` without explanation
|
|
173
|
+
- Prefer `TypeAlias` and `NewType` over bare primitives when the semantic meaning matters.
|
|
174
|
+
|
|
175
|
+
## Testing Rules
|
|
176
|
+
|
|
177
|
+
### Structure: Arrange / Act / Assert
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
def test_invoice_total_includes_tax() -> None:
|
|
181
|
+
# Arrange
|
|
182
|
+
invoice = Invoice(subtotal=100.0, tax_rate=0.1)
|
|
183
|
+
|
|
184
|
+
# Act
|
|
185
|
+
total = invoice.total()
|
|
186
|
+
|
|
187
|
+
# Assert
|
|
188
|
+
assert total == 110.0
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Naming Conventions
|
|
192
|
+
|
|
193
|
+
- Test file: `test_<module>.py`
|
|
194
|
+
- Test function: `test_<what>_<condition>_<expected_outcome>`
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
def test_parse_date_with_invalid_string_raises_value_error() -> None: ...
|
|
198
|
+
def test_user_is_active_after_email_verification() -> None: ...
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### Rules
|
|
202
|
+
|
|
203
|
+
- **One assertion concept per test**
|
|
204
|
+
- **No logic in tests** — No loops, no conditionals. Use `@pytest.mark.parametrize`
|
|
205
|
+
- **Fixtures over setUp** — Use pytest fixtures for shared setup
|
|
206
|
+
- **Test behavior, not implementation** — Tests must survive refactoring
|
|
207
|
+
|
|
208
|
+
### Parametrize for Variations
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
@pytest.mark.parametrize(("raw", "expected"), [
|
|
212
|
+
("2024-01-01", date(2024, 1, 1)),
|
|
213
|
+
("2024-12-31", date(2024, 12, 31)),
|
|
214
|
+
])
|
|
215
|
+
def test_parse_date_returns_correct_date(raw: str, expected: date) -> None:
|
|
216
|
+
assert parse_date(raw) == expected
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
## CI Pipeline Setup
|
|
220
|
+
|
|
221
|
+
Typical CI pipeline stages:
|
|
222
|
+
|
|
223
|
+
1. **Typing** — `hatch run typing` (mypy)
|
|
224
|
+
2. **Test** — `hatch test` (pytest)
|
|
225
|
+
|
|
226
|
+
Note: Lint is typically NOT run in CI (ran locally).
|
|
227
|
+
|
|
228
|
+
## Pre-Commit Checklist
|
|
229
|
+
|
|
230
|
+
Before submitting changes:
|
|
231
|
+
|
|
232
|
+
- [ ] `hatch fmt` passes with no changes
|
|
233
|
+
- [ ] `hatch test` passes
|
|
234
|
+
- [ ] `hatch run typing` passes
|
|
235
|
+
- [ ] All functions have type annotations
|
|
236
|
+
- [ ] No silenced errors without explanation
|
|
237
|
+
- [ ] No unexplained magic or one-liners
|
|
238
|
+
|
|
239
|
+
## Common Gotchas
|
|
240
|
+
|
|
241
|
+
- Do NOT install pytest directly; use `hatch test`
|
|
242
|
+
- `requirements.txt` is auto-generated — do not edit manually
|
|
243
|
+
- Dependencies go in `pyproject.toml`, not in `requirements.txt`
|
|
244
|
+
- Never leave project in state where `hatch fmt` or `hatch test` fails
|
|
245
|
+
|
|
246
|
+
## For This Project
|
|
247
|
+
|
|
248
|
+
- Read project management files in `PM/`
|
|
249
|
+
- The project design doc is `PM/design_doc.md`
|
|
250
|
+
- The task tickets are `PM/tasks/CUI-*.md`
|
|
251
|
+
- When a subtask is finished, remember to check the box
|
|
252
|
+
- You MUST draft your plan first and update the ticket before doing anything
|
|
253
|
+
- You MUST NOT write code before formulating the plan
|
configui-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Chenchao Zhao
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
configui-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: configui
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Dynamic: License
|
|
5
|
+
Dynamic: License-Expression
|
|
6
|
+
Summary: A tool that turns any yaml or json configs into tui
|
|
7
|
+
Author-email: Chenchao Zhao <chenchao.zhao.dev+github@gmail.com>
|
|
8
|
+
License-File: LICENSE
|
|
9
|
+
Requires-Python: <3.14,>=3.12
|
|
10
|
+
Requires-Dist: click>=8.1.0
|
|
11
|
+
Requires-Dist: ruamel-yaml>=0.18.0
|
|
12
|
+
Requires-Dist: textual>=1.0.0
|
|
13
|
+
Requires-Dist: tomlkit>=0.13.0
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
|
|
16
|
+
# ConfigUI
|
|
17
|
+
|
|
18
|
+
[](https://github.com/chenchaozhao/configui/actions/workflows/tests.yml)
|
|
19
|
+
[](https://pypi.org/project/configui/)
|
|
20
|
+
[](https://www.python.org/)
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
|
|
23
|
+
Turn YAML, JSON, and TOML configuration files into a terminal user interface (TUI) — no IDE required.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Install from PyPI
|
|
31
|
+
uv tool install configui
|
|
32
|
+
|
|
33
|
+
# Or with pip
|
|
34
|
+
pip install configui
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quickstart
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
configui path/to/config.yaml
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Open a configuration file in the interactive TUI editor. Edit values, toggle booleans, navigate nested structures — everything stays type-aware. Try it with the sample configs in `samples/`:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
configui samples/training_config.yaml
|
|
47
|
+
configui samples/training_config.json
|
|
48
|
+
configui samples/training_config.toml
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
configui path/to/config.yaml -r # Read-only mode
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
## Features
|
|
58
|
+
|
|
59
|
+
- **Type-aware editing** — booleans become checkboxes, numbers get numeric inputs, nested objects become collapsible sections.
|
|
60
|
+
- **Multi-format** — YAML (with comment preservation via `ruamel.yaml`), JSON, and TOML (with `tomlkit`).
|
|
61
|
+
- **Read-only mode** — inspect configs without accidental edits (`-r` flag).
|
|
62
|
+
- **Save or Save As** — overwrite the original or write to a new path.
|
|
63
|
+
- **Comment preservation** — your YAML and TOML comments stay intact.
|
|
64
|
+
|
|
65
|
+
## Supported Formats
|
|
66
|
+
|
|
67
|
+
| Format | Library | Comments preserved |
|
|
68
|
+
|--------|---------|-------------------|
|
|
69
|
+
| YAML | ruamel.yaml | ✅ |
|
|
70
|
+
| JSON | stdlib json | ❌ (not supported by format) |
|
|
71
|
+
| TOML | tomlkit | ✅ |
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
uv tool install hatch
|
|
77
|
+
hatch run release # fmt → typing → test with coverage
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
MIT
|