audex 1.0.7a3__py3-none-any.whl
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.
- audex/__init__.py +9 -0
- audex/__main__.py +7 -0
- audex/cli/__init__.py +189 -0
- audex/cli/apis/__init__.py +12 -0
- audex/cli/apis/init/__init__.py +34 -0
- audex/cli/apis/init/gencfg.py +130 -0
- audex/cli/apis/init/setup.py +330 -0
- audex/cli/apis/init/vprgroup.py +125 -0
- audex/cli/apis/serve.py +141 -0
- audex/cli/args.py +356 -0
- audex/cli/exceptions.py +44 -0
- audex/cli/helper/__init__.py +0 -0
- audex/cli/helper/ansi.py +193 -0
- audex/cli/helper/display.py +288 -0
- audex/config/__init__.py +64 -0
- audex/config/core/__init__.py +30 -0
- audex/config/core/app.py +29 -0
- audex/config/core/audio.py +45 -0
- audex/config/core/logging.py +163 -0
- audex/config/core/session.py +11 -0
- audex/config/helper/__init__.py +1 -0
- audex/config/helper/client/__init__.py +1 -0
- audex/config/helper/client/http.py +28 -0
- audex/config/helper/client/websocket.py +21 -0
- audex/config/helper/provider/__init__.py +1 -0
- audex/config/helper/provider/dashscope.py +13 -0
- audex/config/helper/provider/unisound.py +18 -0
- audex/config/helper/provider/xfyun.py +23 -0
- audex/config/infrastructure/__init__.py +31 -0
- audex/config/infrastructure/cache.py +51 -0
- audex/config/infrastructure/database.py +48 -0
- audex/config/infrastructure/recorder.py +32 -0
- audex/config/infrastructure/store.py +19 -0
- audex/config/provider/__init__.py +18 -0
- audex/config/provider/transcription.py +109 -0
- audex/config/provider/vpr.py +99 -0
- audex/container.py +40 -0
- audex/entity/__init__.py +468 -0
- audex/entity/doctor.py +109 -0
- audex/entity/doctor.pyi +51 -0
- audex/entity/fields.py +401 -0
- audex/entity/segment.py +115 -0
- audex/entity/segment.pyi +38 -0
- audex/entity/session.py +133 -0
- audex/entity/session.pyi +47 -0
- audex/entity/utterance.py +142 -0
- audex/entity/utterance.pyi +48 -0
- audex/entity/vp.py +68 -0
- audex/entity/vp.pyi +35 -0
- audex/exceptions.py +157 -0
- audex/filters/__init__.py +692 -0
- audex/filters/generated/__init__.py +21 -0
- audex/filters/generated/doctor.py +987 -0
- audex/filters/generated/segment.py +723 -0
- audex/filters/generated/session.py +978 -0
- audex/filters/generated/utterance.py +939 -0
- audex/filters/generated/vp.py +815 -0
- audex/helper/__init__.py +1 -0
- audex/helper/hash.py +33 -0
- audex/helper/mixin.py +65 -0
- audex/helper/net.py +19 -0
- audex/helper/settings/__init__.py +830 -0
- audex/helper/settings/fields.py +317 -0
- audex/helper/stream.py +153 -0
- audex/injectors/__init__.py +1 -0
- audex/injectors/config.py +12 -0
- audex/injectors/lifespan.py +7 -0
- audex/lib/__init__.py +1 -0
- audex/lib/cache/__init__.py +383 -0
- audex/lib/cache/inmemory.py +513 -0
- audex/lib/database/__init__.py +83 -0
- audex/lib/database/sqlite.py +406 -0
- audex/lib/exporter.py +189 -0
- audex/lib/injectors/__init__.py +1 -0
- audex/lib/injectors/cache.py +25 -0
- audex/lib/injectors/container.py +47 -0
- audex/lib/injectors/exporter.py +26 -0
- audex/lib/injectors/recorder.py +33 -0
- audex/lib/injectors/server.py +17 -0
- audex/lib/injectors/session.py +18 -0
- audex/lib/injectors/sqlite.py +24 -0
- audex/lib/injectors/store.py +13 -0
- audex/lib/injectors/transcription.py +42 -0
- audex/lib/injectors/usb.py +12 -0
- audex/lib/injectors/vpr.py +65 -0
- audex/lib/injectors/wifi.py +7 -0
- audex/lib/recorder.py +844 -0
- audex/lib/repos/__init__.py +149 -0
- audex/lib/repos/container.py +23 -0
- audex/lib/repos/database/__init__.py +1 -0
- audex/lib/repos/database/sqlite.py +672 -0
- audex/lib/repos/decorators.py +74 -0
- audex/lib/repos/doctor.py +286 -0
- audex/lib/repos/segment.py +302 -0
- audex/lib/repos/session.py +285 -0
- audex/lib/repos/tables/__init__.py +70 -0
- audex/lib/repos/tables/doctor.py +137 -0
- audex/lib/repos/tables/segment.py +113 -0
- audex/lib/repos/tables/session.py +140 -0
- audex/lib/repos/tables/utterance.py +131 -0
- audex/lib/repos/tables/vp.py +102 -0
- audex/lib/repos/utterance.py +288 -0
- audex/lib/repos/vp.py +286 -0
- audex/lib/restful.py +251 -0
- audex/lib/server/__init__.py +97 -0
- audex/lib/server/auth.py +98 -0
- audex/lib/server/handlers.py +248 -0
- audex/lib/server/templates/index.html.j2 +226 -0
- audex/lib/server/templates/login.html.j2 +111 -0
- audex/lib/server/templates/static/script.js +68 -0
- audex/lib/server/templates/static/style.css +579 -0
- audex/lib/server/types.py +123 -0
- audex/lib/session.py +503 -0
- audex/lib/store/__init__.py +238 -0
- audex/lib/store/localfile.py +411 -0
- audex/lib/transcription/__init__.py +33 -0
- audex/lib/transcription/dashscope.py +525 -0
- audex/lib/transcription/events.py +62 -0
- audex/lib/usb.py +554 -0
- audex/lib/vpr/__init__.py +38 -0
- audex/lib/vpr/unisound/__init__.py +185 -0
- audex/lib/vpr/unisound/types.py +469 -0
- audex/lib/vpr/xfyun/__init__.py +483 -0
- audex/lib/vpr/xfyun/types.py +679 -0
- audex/lib/websocket/__init__.py +8 -0
- audex/lib/websocket/connection.py +485 -0
- audex/lib/websocket/pool.py +991 -0
- audex/lib/wifi.py +1146 -0
- audex/lifespan.py +75 -0
- audex/service/__init__.py +27 -0
- audex/service/decorators.py +73 -0
- audex/service/doctor/__init__.py +652 -0
- audex/service/doctor/const.py +36 -0
- audex/service/doctor/exceptions.py +96 -0
- audex/service/doctor/types.py +54 -0
- audex/service/export/__init__.py +236 -0
- audex/service/export/const.py +17 -0
- audex/service/export/exceptions.py +34 -0
- audex/service/export/types.py +21 -0
- audex/service/injectors/__init__.py +1 -0
- audex/service/injectors/container.py +53 -0
- audex/service/injectors/doctor.py +34 -0
- audex/service/injectors/export.py +27 -0
- audex/service/injectors/session.py +49 -0
- audex/service/session/__init__.py +754 -0
- audex/service/session/const.py +34 -0
- audex/service/session/exceptions.py +67 -0
- audex/service/session/types.py +91 -0
- audex/types.py +39 -0
- audex/utils.py +287 -0
- audex/valueobj/__init__.py +81 -0
- audex/valueobj/common/__init__.py +1 -0
- audex/valueobj/common/auth.py +84 -0
- audex/valueobj/common/email.py +16 -0
- audex/valueobj/common/ops.py +22 -0
- audex/valueobj/common/phone.py +84 -0
- audex/valueobj/common/version.py +72 -0
- audex/valueobj/session.py +19 -0
- audex/valueobj/utterance.py +15 -0
- audex/view/__init__.py +51 -0
- audex/view/container.py +17 -0
- audex/view/decorators.py +303 -0
- audex/view/pages/__init__.py +1 -0
- audex/view/pages/dashboard/__init__.py +286 -0
- audex/view/pages/dashboard/wifi.py +407 -0
- audex/view/pages/login.py +110 -0
- audex/view/pages/recording.py +348 -0
- audex/view/pages/register.py +202 -0
- audex/view/pages/sessions/__init__.py +196 -0
- audex/view/pages/sessions/details.py +224 -0
- audex/view/pages/sessions/export.py +443 -0
- audex/view/pages/settings.py +374 -0
- audex/view/pages/voiceprint/__init__.py +1 -0
- audex/view/pages/voiceprint/enroll.py +195 -0
- audex/view/pages/voiceprint/update.py +195 -0
- audex/view/static/css/dashboard.css +452 -0
- audex/view/static/css/glass.css +22 -0
- audex/view/static/css/global.css +541 -0
- audex/view/static/css/login.css +386 -0
- audex/view/static/css/recording.css +439 -0
- audex/view/static/css/register.css +293 -0
- audex/view/static/css/sessions/styles.css +501 -0
- audex/view/static/css/settings.css +186 -0
- audex/view/static/css/voiceprint/enroll.css +43 -0
- audex/view/static/css/voiceprint/styles.css +209 -0
- audex/view/static/css/voiceprint/update.css +44 -0
- audex/view/static/images/logo.svg +95 -0
- audex/view/static/js/recording.js +42 -0
- audex-1.0.7a3.dist-info/METADATA +361 -0
- audex-1.0.7a3.dist-info/RECORD +192 -0
- audex-1.0.7a3.dist-info/WHEEL +4 -0
- audex-1.0.7a3.dist-info/entry_points.txt +3 -0
audex/__init__.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
__title__ = "Audex"
|
|
4
|
+
__prog__ = "audex"
|
|
5
|
+
__version__ = "1.0.7-a3"
|
|
6
|
+
__description__ = """
|
|
7
|
+
Audex is an intelligent medical transcription system designed specifically for clinical scenarios.
|
|
8
|
+
It uses Voice Print Recognition (VPR) and real-time speech-to-text technology to automatically distinguish between the doctor and the patient, producing structured medical documentation from their conversations.
|
|
9
|
+
"""
|
audex/__main__.py
ADDED
audex/cli/__init__.py
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import pathlib
|
|
5
|
+
import sys
|
|
6
|
+
|
|
7
|
+
import dotenv
|
|
8
|
+
|
|
9
|
+
from audex.cli.apis import register_apis
|
|
10
|
+
from audex.cli.args import parser_with_version
|
|
11
|
+
from audex.cli.exceptions import CLIError
|
|
12
|
+
from audex.cli.helper import display
|
|
13
|
+
from audex.config import Config
|
|
14
|
+
from audex.config import build_config
|
|
15
|
+
from audex.config import setconfig
|
|
16
|
+
from audex.exceptions import AudexError
|
|
17
|
+
from audex.utils import flatten_dict
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def main() -> int:
|
|
21
|
+
"""Main entry point for the Audex CLI.
|
|
22
|
+
|
|
23
|
+
This function parses command-line arguments, executes the appropriate
|
|
24
|
+
command, and handles errors gracefully.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Exit code indicating success or type of failure.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# Load environment variables from .env file if it exists
|
|
31
|
+
if dotenv.find_dotenv():
|
|
32
|
+
dotenv.load_dotenv()
|
|
33
|
+
|
|
34
|
+
try:
|
|
35
|
+
args = parse_args()
|
|
36
|
+
args.func(args)
|
|
37
|
+
return 0
|
|
38
|
+
except KeyboardInterrupt:
|
|
39
|
+
# Handle Ctrl+C gracefully
|
|
40
|
+
print()
|
|
41
|
+
display.warning("Cancelled by user")
|
|
42
|
+
return 130
|
|
43
|
+
except CLIError as e:
|
|
44
|
+
# Handle known CLI errors
|
|
45
|
+
verbose = "--verbose" in sys.argv or "-v" in sys.argv
|
|
46
|
+
display.show_error(e, verbose=verbose)
|
|
47
|
+
return e.exit_code
|
|
48
|
+
except AudexError as e:
|
|
49
|
+
# Handle known Audex errors
|
|
50
|
+
verbose = "--verbose" in sys.argv or "-v" in sys.argv
|
|
51
|
+
display.show_error(e, verbose=verbose)
|
|
52
|
+
return e.code
|
|
53
|
+
except Exception as e:
|
|
54
|
+
# Handle unexpected errors
|
|
55
|
+
verbose = "--verbose" in sys.argv or "-v" in sys.argv
|
|
56
|
+
display.show_error(e, verbose=verbose)
|
|
57
|
+
return 1
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def parse_args() -> argparse.Namespace:
|
|
61
|
+
parser = parser_with_version()
|
|
62
|
+
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--verbose",
|
|
65
|
+
"-v",
|
|
66
|
+
action="store_true",
|
|
67
|
+
help="Enable verbose output for debugging",
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
# Add config argument at top level
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--config",
|
|
73
|
+
"-c",
|
|
74
|
+
type=pathlib.Path,
|
|
75
|
+
default=None,
|
|
76
|
+
help="Path to the configuration file",
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Create subparsers for other commands (serve, init, etc.)
|
|
80
|
+
subparsers = parser.add_subparsers(
|
|
81
|
+
title="Available Commands",
|
|
82
|
+
dest="command",
|
|
83
|
+
help="Command to execute (optional, default is to run the application)",
|
|
84
|
+
metavar="<command>",
|
|
85
|
+
required=False,
|
|
86
|
+
)
|
|
87
|
+
|
|
88
|
+
# Register other commands (not run, since it's default)
|
|
89
|
+
register_apis(subparsers)
|
|
90
|
+
|
|
91
|
+
# Set default function to run the application
|
|
92
|
+
parser.set_defaults(func=run_application)
|
|
93
|
+
|
|
94
|
+
return parser.parse_args()
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def run_application(args: argparse.Namespace) -> None:
|
|
98
|
+
"""Run the main Audex application (default behavior)."""
|
|
99
|
+
from nicegui import core
|
|
100
|
+
|
|
101
|
+
core.app.native.start_args.update({"gui": "qt"})
|
|
102
|
+
|
|
103
|
+
display.banner("Audex", subtitle="Smart Medical Recording & Transcription System")
|
|
104
|
+
|
|
105
|
+
# Bootstrap
|
|
106
|
+
display.step("Bootstrapping application", step=0)
|
|
107
|
+
print()
|
|
108
|
+
|
|
109
|
+
# Load configuration
|
|
110
|
+
with display.section("Loading Configuration"):
|
|
111
|
+
if args.config:
|
|
112
|
+
display.info(f"Loading config from: {args.config}")
|
|
113
|
+
display.path(args.config, exists=args.config.exists())
|
|
114
|
+
|
|
115
|
+
if args.config.suffix in {".yaml", ".yml"}:
|
|
116
|
+
setconfig(Config.from_yaml(args.config))
|
|
117
|
+
display.success("YAML configuration loaded")
|
|
118
|
+
else:
|
|
119
|
+
from audex.cli.exceptions import InvalidArgumentError
|
|
120
|
+
|
|
121
|
+
raise InvalidArgumentError(
|
|
122
|
+
arg="config",
|
|
123
|
+
value=args.config,
|
|
124
|
+
reason=f"Unsupported config file format: {args.config.suffix}."
|
|
125
|
+
"Supported formats are .yaml, .yml, .json, .jsonc, .json5",
|
|
126
|
+
)
|
|
127
|
+
else:
|
|
128
|
+
display.info("Using default configuration")
|
|
129
|
+
|
|
130
|
+
# Show configuration summary
|
|
131
|
+
cfg = build_config()
|
|
132
|
+
with display.section("Application Configuration"):
|
|
133
|
+
display.table_dict(flatten_dict(cfg.model_dump()))
|
|
134
|
+
|
|
135
|
+
# Initialize container
|
|
136
|
+
display.step("Initializing application", step=1)
|
|
137
|
+
with display.loading("Wiring dependencies..."):
|
|
138
|
+
from audex.container import Container
|
|
139
|
+
import audex.view.pages
|
|
140
|
+
|
|
141
|
+
container = Container()
|
|
142
|
+
container.wire(packages=[audex.view.pages])
|
|
143
|
+
|
|
144
|
+
display.success("Application initialized")
|
|
145
|
+
|
|
146
|
+
# Launch info
|
|
147
|
+
display.step("Launching application", step=2)
|
|
148
|
+
print()
|
|
149
|
+
|
|
150
|
+
import platform
|
|
151
|
+
|
|
152
|
+
if cfg.core.app.native:
|
|
153
|
+
display.info("Launching in native window mode")
|
|
154
|
+
display.info(f"GUI Backend: PyQt6 ({platform.system()})")
|
|
155
|
+
else:
|
|
156
|
+
display.info("Application will open in your default browser")
|
|
157
|
+
|
|
158
|
+
display.info("Press Ctrl+C to stop")
|
|
159
|
+
|
|
160
|
+
# Separator before app logs
|
|
161
|
+
print()
|
|
162
|
+
display.separator()
|
|
163
|
+
print()
|
|
164
|
+
|
|
165
|
+
# Start application
|
|
166
|
+
view = container.views().view()
|
|
167
|
+
view.run()
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def cli() -> None:
|
|
171
|
+
"""Entry point for installed command-line script.
|
|
172
|
+
|
|
173
|
+
This function is called when running `audex` as an installed command.
|
|
174
|
+
It's registered in pyproject.toml as a console script entry point.
|
|
175
|
+
|
|
176
|
+
Example:
|
|
177
|
+
After installing with pip:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
audex --help
|
|
181
|
+
audex -c .config.yml
|
|
182
|
+
audex serve --port 8080
|
|
183
|
+
```
|
|
184
|
+
"""
|
|
185
|
+
sys.exit(main())
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
if __name__ == "__main__":
|
|
189
|
+
sys.exit(main())
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def register_apis(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
7
|
+
from audex.cli.apis import init
|
|
8
|
+
from audex.cli.apis import serve
|
|
9
|
+
|
|
10
|
+
# Only register serve and init, not run
|
|
11
|
+
serve.Args.register_subparser(subparsers, name="serve", help_text="Serve Audex export service")
|
|
12
|
+
init.register(subparsers)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def register(subparsers: argparse._SubParsersAction[argparse.ArgumentParser]) -> None:
|
|
7
|
+
from audex.cli.apis.init import gencfg
|
|
8
|
+
from audex.cli.apis.init import setup
|
|
9
|
+
from audex.cli.apis.init import vprgroup
|
|
10
|
+
|
|
11
|
+
parser = subparsers.add_parser(
|
|
12
|
+
"init",
|
|
13
|
+
help="Initialize various Audex components.",
|
|
14
|
+
)
|
|
15
|
+
init_subparsers = parser.add_subparsers(
|
|
16
|
+
title="init commands",
|
|
17
|
+
dest="init_command",
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
gencfg.Args.register_subparser(
|
|
21
|
+
init_subparsers,
|
|
22
|
+
name="gencfg",
|
|
23
|
+
help_text="Generate a default configuration file for Audex.",
|
|
24
|
+
)
|
|
25
|
+
setup.Args.register_subparser(
|
|
26
|
+
init_subparsers,
|
|
27
|
+
name="setup",
|
|
28
|
+
help_text="Run the initial setup wizard for Audex.",
|
|
29
|
+
)
|
|
30
|
+
vprgroup.Args.register_subparser(
|
|
31
|
+
init_subparsers,
|
|
32
|
+
name="vprgroup",
|
|
33
|
+
help_text="Initialize a VPR service group.",
|
|
34
|
+
)
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
import pathlib
|
|
5
|
+
import typing as t
|
|
6
|
+
|
|
7
|
+
from pydantic import Field
|
|
8
|
+
|
|
9
|
+
from audex.cli.args import BaseArgs
|
|
10
|
+
from audex.cli.helper import display
|
|
11
|
+
from audex.utils import flatten_dict
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class Args(BaseArgs):
|
|
15
|
+
format: t.Literal["dotenv", "yaml", "json", "system"] = Field(
|
|
16
|
+
default="dotenv",
|
|
17
|
+
alias="f",
|
|
18
|
+
description="The format of the generated configuration file.",
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
output: pathlib.Path | None = Field(
|
|
22
|
+
default=None,
|
|
23
|
+
alias="o",
|
|
24
|
+
description="The output file path.If not provided, the configuration will be printed to stdout.",
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
platform: t.Literal["linux", "windows"] | None = Field(
|
|
28
|
+
default=None,
|
|
29
|
+
alias="p",
|
|
30
|
+
description="Target platform for system configuration (only used with --format=system).",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def run(self) -> None:
|
|
34
|
+
from audex.config import Config
|
|
35
|
+
|
|
36
|
+
display.banner("Configuration Generator", subtitle="Generate Configuration File")
|
|
37
|
+
|
|
38
|
+
# Show format selection
|
|
39
|
+
with display.section("Generation Options"):
|
|
40
|
+
options_info = {
|
|
41
|
+
"Format": self.format.upper(),
|
|
42
|
+
"Output": str(self.output) if self.output else "(auto-generated filename)",
|
|
43
|
+
}
|
|
44
|
+
if self.format == "system":
|
|
45
|
+
options_info["Platform"] = self.platform or "(current platform)" # type: ignore
|
|
46
|
+
display.key_value(options_info)
|
|
47
|
+
|
|
48
|
+
# Load default configuration
|
|
49
|
+
display.step("Loading default configuration", step=1)
|
|
50
|
+
cfg = Config()
|
|
51
|
+
|
|
52
|
+
# For system format, show platform-specific preview
|
|
53
|
+
platform = self.platform or ("linux" if os.name == "posix" else "windows") # type: ignore
|
|
54
|
+
if self.format == "system":
|
|
55
|
+
with display.section(f"System Configuration Preview ({platform})"):
|
|
56
|
+
display.info(f"Generating system configuration for {platform.upper()}")
|
|
57
|
+
display.warning("Only fields with platform-specific defaults will be included")
|
|
58
|
+
display.info("Unset fields will be omitted from the output")
|
|
59
|
+
else:
|
|
60
|
+
# Preview configuration
|
|
61
|
+
with display.section("Default Configuration Preview"):
|
|
62
|
+
cfg_dict = flatten_dict(cfg.model_dump())
|
|
63
|
+
display.info(f"Total {len(cfg_dict)} configuration keys")
|
|
64
|
+
display.table_dict(cfg_dict)
|
|
65
|
+
|
|
66
|
+
# Confirm generation
|
|
67
|
+
if not display.confirm("Generate configuration file?", default=True):
|
|
68
|
+
display.warning("Operation cancelled by user")
|
|
69
|
+
return
|
|
70
|
+
|
|
71
|
+
# Generate configuration file
|
|
72
|
+
display.step("Generating configuration file", step=2)
|
|
73
|
+
|
|
74
|
+
out = self.output
|
|
75
|
+
|
|
76
|
+
with display.loading(f"Writing {self.format.upper()} configuration..."):
|
|
77
|
+
if self.format == "dotenv":
|
|
78
|
+
cfg.to_dotenv(out or (out := pathlib.Path(".env.gen")))
|
|
79
|
+
elif self.format == "yaml":
|
|
80
|
+
cfg.to_yaml(out or (out := pathlib.Path(".config.gen.yml")))
|
|
81
|
+
elif self.format == "json":
|
|
82
|
+
cfg.to_json(out or (out := pathlib.Path(".config.gen.jsonc")))
|
|
83
|
+
elif self.format == "system":
|
|
84
|
+
platform = self.platform or ("linux" if os.name == "posix" else "windows")
|
|
85
|
+
default_filename = f"config.system.{platform}.yml"
|
|
86
|
+
cfg.to_system_yaml(
|
|
87
|
+
out or (out := pathlib.Path(default_filename)),
|
|
88
|
+
platform=platform, # type: ignore
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# Show result
|
|
92
|
+
print()
|
|
93
|
+
display.success("Configuration file generated successfully!")
|
|
94
|
+
|
|
95
|
+
# Summary
|
|
96
|
+
display.header("Generation Summary")
|
|
97
|
+
summary_data: dict[str, t.Any] = {
|
|
98
|
+
"Format": self.format.upper(),
|
|
99
|
+
"Output File": str(out),
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
if self.format == "system":
|
|
103
|
+
summary_data["Platform"] = platform.upper()
|
|
104
|
+
summary_data["Note"] = "Only non-Unset fields included"
|
|
105
|
+
else:
|
|
106
|
+
summary_data["Total Keys"] = len(cfg_dict)
|
|
107
|
+
|
|
108
|
+
display.key_value(summary_data)
|
|
109
|
+
|
|
110
|
+
# Show file path with existence check
|
|
111
|
+
display.path(out, label="Saved to", exists=out.exists())
|
|
112
|
+
|
|
113
|
+
# Show usage hints
|
|
114
|
+
if self.format == "system":
|
|
115
|
+
print()
|
|
116
|
+
display.header("Usage Instructions")
|
|
117
|
+
display.info("This system configuration file is intended for:")
|
|
118
|
+
print(" • Deployment to /etc/audex/config.system.yml on Linux")
|
|
119
|
+
print(" • Use as read-only system-wide defaults")
|
|
120
|
+
print(" • User configurations should override this at ~/.config/audex/config.yml")
|
|
121
|
+
|
|
122
|
+
if platform == "linux":
|
|
123
|
+
print()
|
|
124
|
+
display.info("To deploy on Linux:")
|
|
125
|
+
print(f" sudo cp {out} /etc/audex/config.system.yml")
|
|
126
|
+
print(" sudo chown root:root /etc/audex/config.system.yml")
|
|
127
|
+
print(" sudo chmod 644 /etc/audex/config.system.yml")
|
|
128
|
+
|
|
129
|
+
print()
|
|
130
|
+
display.success("Done! 🎉")
|