apprc 0.1.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.
- apprc-0.1.0/LICENSE +21 -0
- apprc-0.1.0/PKG-INFO +498 -0
- apprc-0.1.0/README.pypi.md +468 -0
- apprc-0.1.0/pyproject.toml +190 -0
- apprc-0.1.0/src/apprc/__init__.py +19 -0
- apprc-0.1.0/src/apprc/_dotenv_guard.py +29 -0
- apprc-0.1.0/src/apprc/_lazy.py +62 -0
- apprc-0.1.0/src/apprc/cli/__init__.py +31 -0
- apprc-0.1.0/src/apprc/cli/bootstrap.py +66 -0
- apprc-0.1.0/src/apprc/cli/config_app.py +555 -0
- apprc-0.1.0/src/apprc/cli/doctor.py +182 -0
- apprc-0.1.0/src/apprc/cli/options.py +17 -0
- apprc-0.1.0/src/apprc/cli/typer_utils.py +153 -0
- apprc-0.1.0/src/apprc/config/__init__.py +49 -0
- apprc-0.1.0/src/apprc/config/app_spec.py +69 -0
- apprc-0.1.0/src/apprc/config/base_config.py +429 -0
- apprc-0.1.0/src/apprc/config/environment.py +329 -0
- apprc-0.1.0/src/apprc/config/kit.py +299 -0
- apprc-0.1.0/src/apprc/config/local_env.py +171 -0
- apprc-0.1.0/src/apprc/config/schema.py +396 -0
- apprc-0.1.0/src/apprc/config/storage_registry.py +268 -0
- apprc-0.1.0/src/apprc/config/tui.py +452 -0
- apprc-0.1.0/src/apprc/config/tui_rendering.py +225 -0
- apprc-0.1.0/src/apprc/logging/__init__.py +5 -0
- apprc-0.1.0/src/apprc/logging/__init__.pyi +27 -0
- apprc-0.1.0/src/apprc/logging/_facade.py +44 -0
- apprc-0.1.0/src/apprc/logging/config.py +239 -0
- apprc-0.1.0/src/apprc/logging/context.py +168 -0
- apprc-0.1.0/src/apprc/logging/core.py +633 -0
- apprc-0.1.0/src/apprc/logging/exceptions.py +383 -0
- apprc-0.1.0/src/apprc/logging/formats.py +426 -0
- apprc-0.1.0/src/apprc/logging/functions/__init__.py +19 -0
- apprc-0.1.0/src/apprc/logging/functions/lifecycle.py +59 -0
- apprc-0.1.0/src/apprc/logging/functions/telemetry.py +326 -0
- apprc-0.1.0/src/apprc/logging/levels.py +192 -0
- apprc-0.1.0/src/apprc/logging/subprocess.py +64 -0
- apprc-0.1.0/src/apprc/main.py +28 -0
- apprc-0.1.0/src/apprc/paths.py +29 -0
- apprc-0.1.0/src/apprc/py.typed +1 -0
- apprc-0.1.0/src/apprc/utils/__init__.py +18 -0
- apprc-0.1.0/src/apprc/utils/path_resolver.py +206 -0
- apprc-0.1.0/src/apprc/utils/stdlib.py +91 -0
- apprc-0.1.0/src/apprc_dev/build/pypi_readme.py +102 -0
- apprc-0.1.0/tests/__init__.py +1 -0
- apprc-0.1.0/tests/support_config.py +137 -0
- apprc-0.1.0/tests/test_base_config.py +58 -0
- apprc-0.1.0/tests/test_config_kit.py +445 -0
- apprc-0.1.0/tests/test_environment_bootstrap.py +137 -0
- apprc-0.1.0/tests/test_local_env.py +97 -0
- apprc-0.1.0/tests/test_pypi_readme.py +43 -0
- apprc-0.1.0/tests/test_storage_registry.py +90 -0
- apprc-0.1.0/tests/test_tui_rendering.py +54 -0
- apprc-0.1.0/tests/test_typer_utils.py +54 -0
- apprc-0.1.0/tests/test_utils.py +21 -0
apprc-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 markur4
|
|
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.
|
apprc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,498 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: apprc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Reusable runtime configuration, config CLI, and logging helpers for Python applications.
|
|
5
|
+
Keywords: configuration,dotenv,logging,runtime-config,typer
|
|
6
|
+
Author: markur4
|
|
7
|
+
Author-email: markur4 <noreply@hisqu.de>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Dist: python-dotenv
|
|
20
|
+
Requires-Dist: typed-settings[dotenv]
|
|
21
|
+
Requires-Dist: structlog
|
|
22
|
+
Requires-Dist: rich
|
|
23
|
+
Requires-Dist: textual
|
|
24
|
+
Requires-Dist: typer
|
|
25
|
+
Requires-Python: >=3.12
|
|
26
|
+
Project-URL: Homepage, https://hisqu.de
|
|
27
|
+
Project-URL: Repository, https://github.com/HisQu/apprc
|
|
28
|
+
Project-URL: Issues, https://github.com/HisQu/apprc/issues
|
|
29
|
+
Description-Content-Type: text/markdown
|
|
30
|
+
|
|
31
|
+
<!-- ============================================================== -->
|
|
32
|
+
<!-- == Header ==================================================== -->
|
|
33
|
+
<div align="center">
|
|
34
|
+
|
|
35
|
+
# `apprc`: Application Runtime Config
|
|
36
|
+
|
|
37
|
+
*Part of:*
|
|
38
|
+
|
|
39
|
+
<a href="https://hisqu.de" target="_blank">
|
|
40
|
+
<img
|
|
41
|
+
src="https://avatars.githubusercontent.com/u/196629600?s=200&v=4"
|
|
42
|
+
width="100px" alt="logo"
|
|
43
|
+
style="margin-top: -10px;">
|
|
44
|
+
</a>
|
|
45
|
+
|
|
46
|
+
<br>
|
|
47
|
+
|
|
48
|
+
[](https://github.com/astral-sh/uv)
|
|
49
|
+
[](https://www.python.org/downloads/)
|
|
50
|
+
|
|
51
|
+
[](https://github.com/astral-sh/ruff)
|
|
52
|
+
[](https://microsoft.github.io/pyright/)
|
|
53
|
+
[](https://docs.pytest.org/)
|
|
54
|
+
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
[`direnv`]: https://direnv.net/
|
|
58
|
+
[`just`]: https://github.com/casey/just?tab=readme-ov-file#packages
|
|
59
|
+
[`uv`]: https://github.com/astral-sh/uv?tab=readme-ov-file#uv
|
|
60
|
+
[PEP 621]: https://peps.python.org/pep-0621/#packaging-type-information
|
|
61
|
+
[`typed-settings`]: https://typed-settings.readthedocs.io/
|
|
62
|
+
[`typer`]: https://typer.tiangolo.com/
|
|
63
|
+
[`python-dotenv`]: https://github.com/theskumar/python-dotenv
|
|
64
|
+
[`textual`]: https://github.com/Textualize/textual
|
|
65
|
+
[`structlog`]: https://github.com/hynek/structlog
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
`apprc` is a small Python library for application runtime configuration and
|
|
69
|
+
logging. It is useful when a project needs typed env-backed config, packaged
|
|
70
|
+
defaults, per-user storage registries, local override files, a reusable
|
|
71
|
+
`config` CLI, a terminal config editor, and structured logs without rebuilding
|
|
72
|
+
that plumbing in every application.
|
|
73
|
+
|
|
74
|
+
The key idea: the application declares its config contract once, and `apprc`
|
|
75
|
+
derives the boring workflows from that contract.
|
|
76
|
+
|
|
77
|
+
### Tech Stack:
|
|
78
|
+
- [`typed-settings`] for typed config fields and runtime dataclasses.
|
|
79
|
+
- [`typer`] for CLI commands.
|
|
80
|
+
- [`python-dotenv`] for `.env` file parsing and writing.
|
|
81
|
+
- [`textual`] for the terminal config editor.
|
|
82
|
+
- [`structlog`] for structured logging.
|
|
83
|
+
|
|
84
|
+
<br>
|
|
85
|
+
|
|
86
|
+
# Installation
|
|
87
|
+
|
|
88
|
+
**Important**
|
|
89
|
+
|
|
90
|
+
### Prerequisites
|
|
91
|
+
- Python >=3.12
|
|
92
|
+
- `git`
|
|
93
|
+
- Optional: [`uv`], [`just`], [`direnv`]
|
|
94
|
+
|
|
95
|
+
<br>
|
|
96
|
+
|
|
97
|
+
### Install From PyPI
|
|
98
|
+
|
|
99
|
+
```shell
|
|
100
|
+
python -m pip install apprc
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
<br>
|
|
104
|
+
|
|
105
|
+
### Use `apprc` As Project Dependency
|
|
106
|
+
|
|
107
|
+
Any Python build system supporting `pyproject.toml` ([PEP 621]) works.
|
|
108
|
+
|
|
109
|
+
For published releases, depend on the PyPI package:
|
|
110
|
+
|
|
111
|
+
```toml
|
|
112
|
+
[project]
|
|
113
|
+
dependencies = [
|
|
114
|
+
"apprc",
|
|
115
|
+
]
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
For the current repository revision, depend on the Git URL:
|
|
119
|
+
|
|
120
|
+
```toml
|
|
121
|
+
[project]
|
|
122
|
+
dependencies = [
|
|
123
|
+
"apprc @ git+https://github.com/HisQu/apprc.git",
|
|
124
|
+
]
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
<br>
|
|
128
|
+
|
|
129
|
+
### Editable Install With `pip`
|
|
130
|
+
|
|
131
|
+
```shell
|
|
132
|
+
git clone https://github.com/HisQu/apprc.git
|
|
133
|
+
cd apprc
|
|
134
|
+
|
|
135
|
+
python -m venv .venv
|
|
136
|
+
source .venv/bin/activate
|
|
137
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
138
|
+
.venv/bin/python -m pip install -e "." --group dev
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
<br>
|
|
142
|
+
|
|
143
|
+
### Editable Install With `uv`
|
|
144
|
+
|
|
145
|
+
```shell
|
|
146
|
+
git clone https://github.com/HisQu/apprc.git
|
|
147
|
+
cd apprc
|
|
148
|
+
|
|
149
|
+
uv sync --frozen --all-groups
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
<br>
|
|
153
|
+
|
|
154
|
+
### Verify
|
|
155
|
+
|
|
156
|
+
```shell
|
|
157
|
+
python -c "import apprc; print(apprc.AppConfigKit)"
|
|
158
|
+
pytest
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
<br>
|
|
162
|
+
|
|
163
|
+
# Example
|
|
164
|
+
|
|
165
|
+
An application usually wires AppRC in three steps: declare fields, create the
|
|
166
|
+
kit, and mount the generated `config` CLI.
|
|
167
|
+
|
|
168
|
+
```python
|
|
169
|
+
from dataclasses import dataclass
|
|
170
|
+
|
|
171
|
+
import typer
|
|
172
|
+
|
|
173
|
+
from apprc import AppConfigKit
|
|
174
|
+
from apprc.config import ConfigOwner, config_field
|
|
175
|
+
|
|
176
|
+
# 1) Declare the config fields your app owns.
|
|
177
|
+
CLIENT_OWNER = ConfigOwner(
|
|
178
|
+
key="client",
|
|
179
|
+
title="Client",
|
|
180
|
+
env_prefix="MYAPP_",
|
|
181
|
+
rc_path=("client",),
|
|
182
|
+
runtime_cls=None,
|
|
183
|
+
fields=(
|
|
184
|
+
config_field(
|
|
185
|
+
"model",
|
|
186
|
+
"MODEL",
|
|
187
|
+
str,
|
|
188
|
+
default="demo-model",
|
|
189
|
+
title="Model",
|
|
190
|
+
explanation="Model used by client calls.",
|
|
191
|
+
),
|
|
192
|
+
),
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
# 2) Create the reusable AppRC facade for your application.
|
|
196
|
+
MYAPP_CONFIG = AppConfigKit(
|
|
197
|
+
app_name="myapp",
|
|
198
|
+
display_name="MyApp",
|
|
199
|
+
config_package="myapp.config",
|
|
200
|
+
owners=(CLIENT_OWNER,),
|
|
201
|
+
storage_root_env_key="MYAPP_D_STORAGE",
|
|
202
|
+
registry_filename="myapp.toml",
|
|
203
|
+
shared_env_filename=".env.shared",
|
|
204
|
+
local_env_filename=".env.local",
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# 3) Mount the generated `myapp config ...` command group.
|
|
208
|
+
@dataclass(slots=True)
|
|
209
|
+
class CliState:
|
|
210
|
+
env_bootstrap: object | None = None
|
|
211
|
+
storage: str | None = None
|
|
212
|
+
|
|
213
|
+
|
|
214
|
+
app = typer.Typer()
|
|
215
|
+
app.add_typer(
|
|
216
|
+
MYAPP_CONFIG.typer_app(state_type=CliState),
|
|
217
|
+
name="config",
|
|
218
|
+
)
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
Runtime dataclasses can inherit `BaseEnv` when you want typed objects populated
|
|
222
|
+
from the bootstrapped environment. The important first step is the owner
|
|
223
|
+
inventory: AppRC reuses it for loading, validation, docs, CLI commands, and the
|
|
224
|
+
terminal editor.
|
|
225
|
+
|
|
226
|
+
AppRC does not install its own `apprc` command. The config CLI is meant to be
|
|
227
|
+
mounted as a subcommand of the application that depends on AppRC.
|
|
228
|
+
|
|
229
|
+
Users then get:
|
|
230
|
+
|
|
231
|
+
```shell
|
|
232
|
+
myapp config init /absolute/path/to/storage --name default --default
|
|
233
|
+
myapp config doctor
|
|
234
|
+
myapp config show --json
|
|
235
|
+
myapp config set client.model other-model
|
|
236
|
+
myapp config edit
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
<br>
|
|
240
|
+
|
|
241
|
+
# Explanations
|
|
242
|
+
|
|
243
|
+
### Config Model
|
|
244
|
+
|
|
245
|
+
`apprc` separates config into clear layers:
|
|
246
|
+
|
|
247
|
+
| Layer | Owner | Purpose |
|
|
248
|
+
|---|---|---|
|
|
249
|
+
| `ConfigField` | application | One typed env-backed setting. |
|
|
250
|
+
| `ConfigOwner` | application | A named section of related fields. |
|
|
251
|
+
| `.env.shared` | application package | Packaged defaults shipped with code. |
|
|
252
|
+
| `<storage>/.env.local` | user/project | Per-storage local overrides. |
|
|
253
|
+
| shell environment | user/process | Highest-priority process values by default. |
|
|
254
|
+
| `~/.config/<app>/<app>.toml` | AppRC registry | Named storage roots and default storage. |
|
|
255
|
+
|
|
256
|
+
Runtime dataclasses inherit `BaseEnv`. The dataclass owns Python attributes;
|
|
257
|
+
`ConfigOwner` owns env names, docs labels, editor labels, choices, and
|
|
258
|
+
redaction metadata.
|
|
259
|
+
|
|
260
|
+
### Bootstrap Precedence
|
|
261
|
+
|
|
262
|
+
Applications call `AppConfigKit.bootstrap(...)` once at CLI startup. It merges:
|
|
263
|
+
|
|
264
|
+
1. packaged `.env.shared`
|
|
265
|
+
2. selected storage-local `.env.local`
|
|
266
|
+
3. explicit `--env-file`
|
|
267
|
+
4. current shell environment
|
|
268
|
+
|
|
269
|
+
By default, the shell wins over `--env-file`. Set
|
|
270
|
+
`env_file_overrides_shell=True` when an explicit file should win inside the
|
|
271
|
+
current process.
|
|
272
|
+
|
|
273
|
+
### Storage Registries
|
|
274
|
+
|
|
275
|
+
Globally installed commands need to find user data without hardcoding one path.
|
|
276
|
+
`apprc` stores named roots in `~/.config/<app>/<registry_filename>`, for
|
|
277
|
+
example:
|
|
278
|
+
|
|
279
|
+
```toml
|
|
280
|
+
default_storage = "default"
|
|
281
|
+
|
|
282
|
+
[storages.default]
|
|
283
|
+
root = "/absolute/path/to/storage"
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
Each storage root owns its own local override file, such as `.env.local`.
|
|
287
|
+
|
|
288
|
+
### Logging
|
|
289
|
+
|
|
290
|
+
`apprc.logging` wraps stdlib logging and structlog. `setup_logging()` installs
|
|
291
|
+
formatters and dependency logger levels. `get_logger()` returns an `AppLogger`
|
|
292
|
+
with semantic helper methods such as `action_begin`, `success`, `retry`,
|
|
293
|
+
`fallback`, `telemetry`, and `traceback`.
|
|
294
|
+
|
|
295
|
+
Use AppRC logging when application logs should stay structured and readable in
|
|
296
|
+
CLI output, notebooks, and tests.
|
|
297
|
+
|
|
298
|
+
<br>
|
|
299
|
+
|
|
300
|
+
# Guides
|
|
301
|
+
|
|
302
|
+
### Define Config Fields
|
|
303
|
+
|
|
304
|
+
Put config declarations in your application package, usually
|
|
305
|
+
`myapp/config/owners.py`.
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
from pathlib import Path
|
|
309
|
+
|
|
310
|
+
from apprc.config import CONFIG_MISSING, ConfigOwner, config_field
|
|
311
|
+
|
|
312
|
+
STORAGE_OWNER = ConfigOwner(
|
|
313
|
+
key="storage",
|
|
314
|
+
title="Storage",
|
|
315
|
+
env_prefix="MYAPP_",
|
|
316
|
+
rc_path=("storage",),
|
|
317
|
+
runtime_cls=None,
|
|
318
|
+
fields=(
|
|
319
|
+
config_field(
|
|
320
|
+
"root",
|
|
321
|
+
"D_STORAGE",
|
|
322
|
+
Path,
|
|
323
|
+
default=CONFIG_MISSING,
|
|
324
|
+
editable=False,
|
|
325
|
+
required=True,
|
|
326
|
+
explanation_short="Active storage root.",
|
|
327
|
+
explanation_long="Selected through the AppRC storage registry.",
|
|
328
|
+
),
|
|
329
|
+
),
|
|
330
|
+
)
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
Use `editable=False` for values owned by the registry instead of `.env.local`.
|
|
334
|
+
|
|
335
|
+
### Bootstrap a CLI
|
|
336
|
+
|
|
337
|
+
Call bootstrap before creating runtime config objects.
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
from apprc.cli import bootstrap_cli_env
|
|
341
|
+
from apprc.logging import setup_logging
|
|
342
|
+
|
|
343
|
+
state.env_bootstrap = bootstrap_cli_env(
|
|
344
|
+
MYAPP_CONFIG,
|
|
345
|
+
env_file=env_file,
|
|
346
|
+
env_file_overrides_shell=env_file_overrides_shell,
|
|
347
|
+
no_dotenv=no_dotenv,
|
|
348
|
+
storage_name=storage,
|
|
349
|
+
log_level=log_level,
|
|
350
|
+
setup_logging=setup_logging,
|
|
351
|
+
)
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
### Add the Generated Config CLI
|
|
355
|
+
|
|
356
|
+
```python
|
|
357
|
+
config_app = MYAPP_CONFIG.typer_app(
|
|
358
|
+
state_type=CliState,
|
|
359
|
+
runtime_payload=lambda state: {
|
|
360
|
+
"storage": str(state.env_bootstrap.storage_root)
|
|
361
|
+
if state.env_bootstrap
|
|
362
|
+
else None,
|
|
363
|
+
},
|
|
364
|
+
)
|
|
365
|
+
app.add_typer(config_app, name="config")
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### Edit Local Values in the Terminal
|
|
369
|
+
|
|
370
|
+
`config edit` opens a Textual editor. The editor shows:
|
|
371
|
+
|
|
372
|
+
- key number
|
|
373
|
+
- section
|
|
374
|
+
- env key
|
|
375
|
+
- shell status
|
|
376
|
+
- local value
|
|
377
|
+
- default value
|
|
378
|
+
- short explanation
|
|
379
|
+
|
|
380
|
+
Selecting a row opens a modal with type information, possible values, and the
|
|
381
|
+
long explanation. Secret values are redacted. Required missing values show
|
|
382
|
+
`<required>`.
|
|
383
|
+
|
|
384
|
+
### Use Logging
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
from apprc.logging import get_logger, setup_logging
|
|
388
|
+
|
|
389
|
+
setup_logging(level="INFO", renderer="cli")
|
|
390
|
+
log = get_logger(__name__)
|
|
391
|
+
|
|
392
|
+
log.action_begin("Loading workspace")
|
|
393
|
+
log.success("Workspace ready", storage="default")
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
<br>
|
|
397
|
+
|
|
398
|
+
# References
|
|
399
|
+
|
|
400
|
+
### Important Modules
|
|
401
|
+
|
|
402
|
+
| Module | Look Here For |
|
|
403
|
+
|---|---|
|
|
404
|
+
| `apprc.config.schema` | `ConfigField`, `ConfigOwner`, field lookup, typed loading. |
|
|
405
|
+
| `apprc.config.kit` | `AppConfigKit`, the high-level app integration facade. |
|
|
406
|
+
| `apprc.config.environment` | CLI startup dotenv/bootstrap precedence. |
|
|
407
|
+
| `apprc.config.storage_registry` | `~/.config/<app>/*.toml` storage names. |
|
|
408
|
+
| `apprc.config.local_env` | `<storage>/.env.local` reads, writes, validation. |
|
|
409
|
+
| `apprc.config.tui` | Textual app and modal interactions. |
|
|
410
|
+
| `apprc.config.tui_rendering` | Pure table cell rendering and styles. |
|
|
411
|
+
| `apprc.cli.config_app` | Generated `config` Typer commands. |
|
|
412
|
+
| `apprc.cli.bootstrap` | Common root CLI bootstrap options. |
|
|
413
|
+
| `apprc.logging` | Logging facade: `setup_logging`, `get_logger`, `AppLogger`. |
|
|
414
|
+
|
|
415
|
+
### Important Config Types
|
|
416
|
+
|
|
417
|
+
| Type | Meaning |
|
|
418
|
+
|---|---|
|
|
419
|
+
| `AppConfigKit` | Convenient object applications keep around. |
|
|
420
|
+
| `AppConfigSpec` | Frozen declaration behind the kit. |
|
|
421
|
+
| `ConfigOwner` | One config section, env prefix, runtime path, and fields. |
|
|
422
|
+
| `ConfigField` | One editable or read-only env-backed setting. |
|
|
423
|
+
| `BaseEnv` | Runtime dataclass base that binds values from env. |
|
|
424
|
+
| `EnvBootstrapResult` | Files and storage selected during CLI startup. |
|
|
425
|
+
| `StorageRegistry` | Parsed TOML registry. |
|
|
426
|
+
| `LocalEnvUpdate` | Result of writing one local dotenv override. |
|
|
427
|
+
|
|
428
|
+
### Config CLI Commands
|
|
429
|
+
|
|
430
|
+
| Command | Purpose |
|
|
431
|
+
|---|---|
|
|
432
|
+
| `config init STORAGE_ROOT --name NAME --default` | Register a storage root. |
|
|
433
|
+
| `config doctor` | Diagnose registry and selected storage state. |
|
|
434
|
+
| `config show --json` | Print resolved runtime config payload. |
|
|
435
|
+
| `config set-default NAME` | Change default storage. |
|
|
436
|
+
| `config set KEY VALUE` | Write one local override. |
|
|
437
|
+
| `config edit` | Open the Textual editor. |
|
|
438
|
+
|
|
439
|
+
### Logging Functions
|
|
440
|
+
|
|
441
|
+
| Function | Purpose |
|
|
442
|
+
|---|---|
|
|
443
|
+
| `setup_logging(...)` | Configure stdlib/structlog output. |
|
|
444
|
+
| `get_logger(__name__)` | Return an `AppLogger`. |
|
|
445
|
+
| `log.action_begin(...)` | Start a visible operation. |
|
|
446
|
+
| `log.success(...)` | Mark a completed operation. |
|
|
447
|
+
| `log.retry(...)` | Record retry attempts. |
|
|
448
|
+
| `log.fallback(...)` | Record fallback behavior. |
|
|
449
|
+
| `log.traceback(...)` | Emit exception information with redaction support. |
|
|
450
|
+
| `async_telemetry(...)` | Emit periodic async progress logs. |
|
|
451
|
+
|
|
452
|
+
<br>
|
|
453
|
+
|
|
454
|
+
# Development
|
|
455
|
+
|
|
456
|
+
### Local Setup
|
|
457
|
+
|
|
458
|
+
```shell
|
|
459
|
+
git clone https://github.com/HisQu/apprc.git
|
|
460
|
+
cd apprc
|
|
461
|
+
|
|
462
|
+
python -m venv .venv
|
|
463
|
+
source .venv/bin/activate
|
|
464
|
+
.venv/bin/python -m pip install --upgrade pip
|
|
465
|
+
.venv/bin/python -m pip install -e "." --group dev
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
or:
|
|
469
|
+
|
|
470
|
+
```shell
|
|
471
|
+
uv sync --frozen --all-groups
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
### Quality Gates
|
|
475
|
+
|
|
476
|
+
Run these before sending changes:
|
|
477
|
+
|
|
478
|
+
```shell
|
|
479
|
+
ruff format .
|
|
480
|
+
ruff check .
|
|
481
|
+
pyright
|
|
482
|
+
pytest
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
### Test Against Haiu
|
|
486
|
+
|
|
487
|
+
Haiu is the main downstream integration test for AppRC. From the Haiu repo:
|
|
488
|
+
|
|
489
|
+
```shell
|
|
490
|
+
cd ../haiu
|
|
491
|
+
.venv/bin/python -m pip install --no-deps --no-build-isolation -e ../apprc
|
|
492
|
+
.venv/bin/pytest tests/haiu/core/test_config_tui.py -q
|
|
493
|
+
.venv/bin/pytest
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
Keep refactors behavior-preserving. If a cleanup would remove a public module,
|
|
497
|
+
change import-time side effects, or alter CLI output, treat that as a feature
|
|
498
|
+
change and ask first.
|